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

* 'cpus4096-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (31 commits)
  NR_CPUS: Replace NR_CPUS in speedstep-centrino.c
  cpumask: Provide a generic set of CPUMASK_ALLOC macros, FIXUP
  NR_CPUS: Replace NR_CPUS in cpufreq userspace routines
  NR_CPUS: Replace per_cpu(..., smp_processor_id()) with __get_cpu_var
  NR_CPUS: Replace NR_CPUS in arch/x86/kernel/genapic_flat_64.c
  NR_CPUS: Replace NR_CPUS in arch/x86/kernel/genx2apic_uv_x.c
  NR_CPUS: Replace NR_CPUS in arch/x86/kernel/cpu/proc.c
  NR_CPUS: Replace NR_CPUS in arch/x86/kernel/cpu/mcheck/mce_64.c
  cpumask: Optimize cpumask_of_cpu in lib/smp_processor_id.c, fix
  cpumask: Use optimized CPUMASK_ALLOC macros in the centrino_target
  cpumask: Provide a generic set of CPUMASK_ALLOC macros
  cpumask: Optimize cpumask_of_cpu in lib/smp_processor_id.c
  cpumask: Optimize cpumask_of_cpu in kernel/time/tick-common.c
  cpumask: Optimize cpumask_of_cpu in drivers/misc/sgi-xp/xpc_main.c
  cpumask: Optimize cpumask_of_cpu in arch/x86/kernel/ldt.c
  cpumask: Optimize cpumask_of_cpu in arch/x86/kernel/io_apic_64.c
  cpumask: Replace cpumask_of_cpu with cpumask_of_cpu_ptr
  Revert "cpumask: introduce new APIs"
  cpumask: make for_each_cpu_mask a bit smaller
  net: Pass reference to cpumask variable in net/sunrpc/svc.c
  ...

Fix up trivial conflicts in drivers/cpufreq/cpufreq.c manually
diff --git a/CREDITS b/CREDITS
index e97bea0..077b1473 100644
--- a/CREDITS
+++ b/CREDITS
@@ -3344,8 +3344,7 @@
 N: Linus Torvalds
 E: torvalds@linux-foundation.org
 D: Original kernel hacker
-S: 12725 SW Millikan Way, Suite 400
-S: Beaverton, Oregon 97005
+S: Portland, Oregon 97005
 S: USA
 
 N: Marcelo Tosatti
diff --git a/Documentation/ABI/testing/sysfs-dev b/Documentation/ABI/testing/sysfs-dev
new file mode 100644
index 0000000..a9f2b8b
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-dev
@@ -0,0 +1,20 @@
+What:		/sys/dev
+Date:		April 2008
+KernelVersion:	2.6.26
+Contact:	Dan Williams <dan.j.williams@intel.com>
+Description:	The /sys/dev tree provides a method to look up the sysfs
+		path for a device using the information returned from
+		stat(2).  There are two directories, 'block' and 'char',
+		beneath /sys/dev containing symbolic links with names of
+		the form "<major>:<minor>".  These links point to the
+		corresponding sysfs path for the given device.
+
+		Example:
+		$ readlink /sys/dev/block/8:32
+		../../block/sdc
+
+		Entries in /sys/dev/char and /sys/dev/block will be
+		dynamically created and destroyed as devices enter and
+		leave the system.
+
+Users:		mdadm <linux-raid@vger.kernel.org>
diff --git a/Documentation/DMA-attributes.txt b/Documentation/DMA-attributes.txt
index 6d772f8..b768cc0 100644
--- a/Documentation/DMA-attributes.txt
+++ b/Documentation/DMA-attributes.txt
@@ -22,3 +22,12 @@
 could race with data DMA.  Mapping the memory used for completion
 indications with DMA_ATTR_WRITE_BARRIER would prevent the race.
 
+DMA_ATTR_WEAK_ORDERING
+----------------------
+
+DMA_ATTR_WEAK_ORDERING specifies that reads and writes to the mapping
+may be weakly ordered, that is that reads and writes may pass each other.
+
+Since it is optional for platforms to implement DMA_ATTR_WEAK_ORDERING,
+those that do not will simply ignore the attribute and exhibit default
+behavior.
diff --git a/Documentation/DocBook/gadget.tmpl b/Documentation/DocBook/gadget.tmpl
index 5a8ffa7..ea3bc95 100644
--- a/Documentation/DocBook/gadget.tmpl
+++ b/Documentation/DocBook/gadget.tmpl
@@ -524,6 +524,44 @@
 <!-- !Edrivers/usb/gadget/epautoconf.c -->
 </sect1>
 
+<sect1 id="composite"><title>Composite Device Framework</title>
+
+<para>The core API is sufficient for writing drivers for composite
+USB devices (with more than one function in a given configuration),
+and also multi-configuration devices (also more than one function,
+but not necessarily sharing a given configuration).
+There is however an optional framework which makes it easier to
+reuse and combine functions.
+</para>
+
+<para>Devices using this framework provide a <emphasis>struct
+usb_composite_driver</emphasis>, which in turn provides one or
+more <emphasis>struct usb_configuration</emphasis> instances.
+Each such configuration includes at least one
+<emphasis>struct usb_function</emphasis>, which packages a user
+visible role such as "network link" or "mass storage device".
+Management functions may also exist, such as "Device Firmware
+Upgrade".
+</para>
+
+!Iinclude/linux/usb/composite.h
+!Edrivers/usb/gadget/composite.c
+
+</sect1>
+
+<sect1 id="functions"><title>Composite Device Functions</title>
+
+<para>At this writing, a few of the current gadget drivers have
+been converted to this framework.
+Near-term plans include converting all of them, except for "gadgetfs".
+</para>
+
+!Edrivers/usb/gadget/f_acm.c
+!Edrivers/usb/gadget/f_serial.c
+
+</sect1>
+
+
 </chapter>
 
 <chapter id="controllers"><title>Peripheral Controller Drivers</title>
diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl
index fdd7f4f..df87d1b 100644
--- a/Documentation/DocBook/uio-howto.tmpl
+++ b/Documentation/DocBook/uio-howto.tmpl
@@ -21,6 +21,18 @@
     </affiliation>
 </author>
 
+<copyright>
+	<year>2006-2008</year>
+	<holder>Hans-Jürgen Koch.</holder>
+</copyright>
+
+<legalnotice>
+<para>
+This documentation is Free Software licensed under the terms of the
+GPL version 2.
+</para>
+</legalnotice>
+
 <pubdate>2006-12-11</pubdate>
 
 <abstract>
@@ -30,6 +42,12 @@
 
 <revhistory>
 	<revision>
+	<revnumber>0.5</revnumber>
+	<date>2008-05-22</date>
+	<authorinitials>hjk</authorinitials>
+	<revremark>Added description of write() function.</revremark>
+	</revision>
+	<revision>
 	<revnumber>0.4</revnumber>
 	<date>2007-11-26</date>
 	<authorinitials>hjk</authorinitials>
@@ -57,20 +75,9 @@
 </bookinfo>
 
 <chapter id="aboutthisdoc">
-<?dbhtml filename="about.html"?>
+<?dbhtml filename="aboutthis.html"?>
 <title>About this document</title>
 
-<sect1 id="copyright">
-<?dbhtml filename="copyright.html"?>
-<title>Copyright and License</title>
-<para>
-      Copyright (c) 2006 by Hans-Jürgen Koch.</para>
-<para>
-This documentation is Free Software licensed under the terms of the
-GPL version 2.
-</para>
-</sect1>
-
 <sect1 id="translations">
 <?dbhtml filename="translations.html"?>
 <title>Translations</title>
@@ -189,6 +196,30 @@
 	represents the total interrupt count. You can use this number
 	to figure out if you missed some interrupts.
 	</para>
+	<para>
+	For some hardware that has more than one interrupt source internally,
+	but not separate IRQ mask and status registers, there might be
+	situations where userspace cannot determine what the interrupt source
+	was if the kernel handler disables them by writing to the chip's IRQ
+	register. In such a case, the kernel has to disable the IRQ completely
+	to leave the chip's register untouched. Now the userspace part can
+	determine the cause of the interrupt, but it cannot re-enable
+	interrupts. Another cornercase is chips where re-enabling interrupts
+	is a read-modify-write operation to a combined IRQ status/acknowledge
+	register. This would be racy if a new interrupt occurred
+	simultaneously.
+	</para>
+	<para>
+	To address these problems, UIO also implements a write() function. It
+	is normally not used and can be ignored for hardware that has only a
+	single interrupt source or has separate IRQ mask and status registers.
+	If you need it, however, a write to <filename>/dev/uioX</filename>
+	will call the <function>irqcontrol()</function> function implemented
+	by the driver. You have to write a 32-bit value that is usually either
+	0 or 1 to disable or enable interrupts. If a driver does not implement
+	<function>irqcontrol()</function>, <function>write()</function> will
+	return with <varname>-ENOSYS</varname>.
+	</para>
 
 	<para>
 	To handle interrupts properly, your custom kernel module can
@@ -362,6 +393,14 @@
 <function>open()</function>, you will probably also want a custom
 <function>release()</function> function.
 </para></listitem>
+
+<listitem><para>
+<varname>int (*irqcontrol)(struct uio_info *info, s32 irq_on)
+</varname>: Optional. If you need to be able to enable or disable
+interrupts from userspace by writing to <filename>/dev/uioX</filename>,
+you can implement this function. The parameter <varname>irq_on</varname>
+will be 0 to disable interrupts and 1 to enable them.
+</para></listitem>
 </itemizedlist>
 
 <para>
diff --git a/Documentation/HOWTO b/Documentation/HOWTO
index 619e8ca..c2371c5 100644
--- a/Documentation/HOWTO
+++ b/Documentation/HOWTO
@@ -358,7 +358,7 @@
     - pcmcia, Dominik Brodowski <linux@dominikbrodowski.net>
 	git.kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git
 
-    - SCSI, James Bottomley <James.Bottomley@SteelEye.com>
+    - SCSI, James Bottomley <James.Bottomley@hansenpartnership.com>
 	git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
 
     - x86, Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 86334b6..9f73587 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -336,3 +336,13 @@
 Why:	Over 1K .text/.data size reduction, data is available in other
 	ways (ioctls)
 Who:	Johannes Berg <johannes@sipsolutions.net>
+
+---------------------------
+
+What: CONFIG_NF_CT_ACCT
+When: 2.6.29
+Why:  Accounting can now be enabled/disabled without kernel recompilation.
+      Currently used only to set a default value for a feature that is also
+      controlled by a kernel/module/sysfs/sysctl parameter.
+Who:  Krzysztof Piotr Oledzki <ole@ans.pl>
+
diff --git a/Documentation/filesystems/bfs.txt b/Documentation/filesystems/bfs.txt
index ea825e1..78043d5 100644
--- a/Documentation/filesystems/bfs.txt
+++ b/Documentation/filesystems/bfs.txt
@@ -26,11 +26,11 @@
 
 this will allocate the first available loopback device (and load loop.o 
 kernel module if necessary) automatically. If the loopback driver is not
-loaded automatically, make sure that your kernel is compiled with kmod 
-support (CONFIG_KMOD) enabled. Beware that umount will not
-deallocate /dev/loopN device if /etc/mtab file on your system is a
-symbolic link to /proc/mounts. You will need to do it manually using
-"-d" switch of losetup(8). Read losetup(8) manpage for more info.
+loaded automatically, make sure that you have compiled the module and
+that modprobe is functioning. Beware that umount will not deallocate
+/dev/loopN device if /etc/mtab file on your system is a symbolic link to
+/proc/mounts. You will need to do it manually using "-d" switch of
+losetup(8). Read losetup(8) manpage for more info.
 
 To create the BFS image under UnixWare you need to find out first which
 slice contains it. The command prtvtoc(1M) is your friend:
diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt
index 7f27b8f..9e9c348 100644
--- a/Documentation/filesystems/sysfs.txt
+++ b/Documentation/filesystems/sysfs.txt
@@ -248,6 +248,7 @@
 block/
 bus/
 class/
+dev/
 devices/
 firmware/
 net/
@@ -274,6 +275,11 @@
 filesystem wanting to export attributes must create its own hierarchy
 below fs/ (see ./fuse.txt for an example).
 
+dev/ contains two directories char/ and block/. Inside these two
+directories there are symlinks named <major>:<minor>.  These symlinks
+point to the sysfs directory for the given device.  /sys/dev provides a
+quick way to lookup the sysfs interface for a device from the result of
+a stat(2) operation.
 
 More information can driver-model specific features can be found in
 Documentation/driver-model/. 
diff --git a/Documentation/ia64/paravirt_ops.txt b/Documentation/ia64/paravirt_ops.txt
new file mode 100644
index 0000000..39ded02
--- /dev/null
+++ b/Documentation/ia64/paravirt_ops.txt
@@ -0,0 +1,137 @@
+Paravirt_ops on IA64
+====================
+                          21 May 2008, Isaku Yamahata <yamahata@valinux.co.jp>
+
+
+Introduction
+------------
+The aim of this documentation is to help with maintainability and/or to
+encourage people to use paravirt_ops/IA64.
+
+paravirt_ops (pv_ops in short) is a way for virtualization support of
+Linux kernel on x86. Several ways for virtualization support were
+proposed, paravirt_ops is the winner.
+On the other hand, now there are also several IA64 virtualization
+technologies like kvm/IA64, xen/IA64 and many other academic IA64
+hypervisors so that it is good to add generic virtualization
+infrastructure on Linux/IA64.
+
+
+What is paravirt_ops?
+---------------------
+It has been developed on x86 as virtualization support via API, not ABI.
+It allows each hypervisor to override operations which are important for
+hypervisors at API level. And it allows a single kernel binary to run on
+all supported execution environments including native machine.
+Essentially paravirt_ops is a set of function pointers which represent
+operations corresponding to low level sensitive instructions and high
+level functionalities in various area. But one significant difference
+from usual function pointer table is that it allows optimization with
+binary patch. It is because some of these operations are very
+performance sensitive and indirect call overhead is not negligible.
+With binary patch, indirect C function call can be transformed into
+direct C function call or in-place execution to eliminate the overhead.
+
+Thus, operations of paravirt_ops are classified into three categories.
+- simple indirect call
+  These operations correspond to high level functionality so that the
+  overhead of indirect call isn't very important.
+
+- indirect call which allows optimization with binary patch
+  Usually these operations correspond to low level instructions. They
+  are called frequently and performance critical. So the overhead is
+  very important.
+
+- a set of macros for hand written assembly code
+  Hand written assembly codes (.S files) also need paravirtualization
+  because they include sensitive instructions or some of code paths in
+  them are very performance critical.
+
+
+The relation to the IA64 machine vector
+---------------------------------------
+Linux/IA64 has the IA64 machine vector functionality which allows the
+kernel to switch implementations (e.g. initialization, ipi, dma api...)
+depending on executing platform.
+We can replace some implementations very easily defining a new machine
+vector. Thus another approach for virtualization support would be
+enhancing the machine vector functionality.
+But paravirt_ops approach was taken because
+- virtualization support needs wider support than machine vector does.
+  e.g. low level instruction paravirtualization. It must be
+       initialized very early before platform detection.
+
+- virtualization support needs more functionality like binary patch.
+  Probably the calling overhead might not be very large compared to the
+  emulation overhead of virtualization. However in the native case, the
+  overhead should be eliminated completely.
+  A single kernel binary should run on each environment including native,
+  and the overhead of paravirt_ops on native environment should be as
+  small as possible.
+
+- for full virtualization technology, e.g. KVM/IA64 or
+  Xen/IA64 HVM domain, the result would be
+  (the emulated platform machine vector. probably dig) + (pv_ops).
+  This means that the virtualization support layer should be under
+  the machine vector layer.
+
+Possibly it might be better to move some function pointers from
+paravirt_ops to machine vector. In fact, Xen domU case utilizes both
+pv_ops and machine vector.
+
+
+IA64 paravirt_ops
+-----------------
+In this section, the concrete paravirt_ops will be discussed.
+Because of the architecture difference between ia64 and x86, the
+resulting set of functions is very different from x86 pv_ops.
+
+- C function pointer tables
+They are not very performance critical so that simple C indirect
+function call is acceptable. The following structures are defined at
+this moment. For details see linux/include/asm-ia64/paravirt.h
+  - struct pv_info
+    This structure describes the execution environment.
+  - struct pv_init_ops
+    This structure describes the various initialization hooks.
+  - struct pv_iosapic_ops
+    This structure describes hooks to iosapic operations.
+  - struct pv_irq_ops
+    This structure describes hooks to irq related operations
+  - struct pv_time_op
+    This structure describes hooks to steal time accounting.
+
+- a set of indirect calls which need optimization
+Currently this class of functions correspond to a subset of IA64
+intrinsics. At this moment the optimization with binary patch isn't
+implemented yet.
+struct pv_cpu_op is defined. For details see
+linux/include/asm-ia64/paravirt_privop.h
+Mostly they correspond to ia64 intrinsics 1-to-1.
+Caveat: Now they are defined as C indirect function pointers, but in
+order to support binary patch optimization, they will be changed
+using GCC extended inline assembly code.
+
+- a set of macros for hand written assembly code (.S files)
+For maintenance purpose, the taken approach for .S files is single
+source code and compile multiple times with different macros definitions.
+Each pv_ops instance must define those macros to compile.
+The important thing here is that sensitive, but non-privileged
+instructions must be paravirtualized and that some privileged
+instructions also need paravirtualization for reasonable performance.
+Developers who modify .S files must be aware of that. At this moment
+an easy checker is implemented to detect paravirtualization breakage.
+But it doesn't cover all the cases.
+
+Sometimes this set of macros is called pv_cpu_asm_op. But there is no
+corresponding structure in the source code.
+Those macros mostly 1:1 correspond to a subset of privileged
+instructions. See linux/include/asm-ia64/native/inst.h.
+And some functions written in assembly also need to be overrided so
+that each pv_ops instance have to define some macros. Again see
+linux/include/asm-ia64/native/inst.h.
+
+
+Those structures must be initialized very early before start_kernel.
+Probably initialized in head.S using multi entry point or some other trick.
+For native case implementation see linux/arch/ia64/kernel/paravirt.c.
diff --git a/Documentation/input/gameport-programming.txt b/Documentation/input/gameport-programming.txt
index 14e0a8b..03a74fc 100644
--- a/Documentation/input/gameport-programming.txt
+++ b/Documentation/input/gameport-programming.txt
@@ -1,5 +1,3 @@
-$Id: gameport-programming.txt,v 1.3 2001/04/24 13:51:37 vojtech Exp $
-
 Programming gameport drivers
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/Documentation/input/input.txt b/Documentation/input/input.txt
index ff8cea0..686ee99 100644
--- a/Documentation/input/input.txt
+++ b/Documentation/input/input.txt
@@ -1,7 +1,6 @@
 			  Linux Input drivers v1.0
 	       (c) 1999-2001 Vojtech Pavlik <vojtech@ucw.cz>
 			     Sponsored by SuSE
-	    $Id: input.txt,v 1.8 2002/05/29 03:15:01 bradleym Exp $
 ----------------------------------------------------------------------------
 
 0. Disclaimer
diff --git a/Documentation/input/joystick-api.txt b/Documentation/input/joystick-api.txt
index acbd32b..c507330 100644
--- a/Documentation/input/joystick-api.txt
+++ b/Documentation/input/joystick-api.txt
@@ -5,8 +5,6 @@
 
 			      7 Aug 1998
 
-	$Id: joystick-api.txt,v 1.2 2001/05/08 21:21:23 vojtech Exp $
-
 1. Initialization
 ~~~~~~~~~~~~~~~~~
 
diff --git a/Documentation/input/joystick-parport.txt b/Documentation/input/joystick-parport.txt
index ede5f33..1c856f3 100644
--- a/Documentation/input/joystick-parport.txt
+++ b/Documentation/input/joystick-parport.txt
@@ -2,7 +2,6 @@
 	       (c) 1998-2000 Vojtech Pavlik <vojtech@ucw.cz>
 	       (c) 1998 Andree Borrmann <a.borrmann@tu-bs.de>
 			     Sponsored by SuSE
-	$Id: joystick-parport.txt,v 1.6 2001/09/25 09:31:32 vojtech Exp $
 ----------------------------------------------------------------------------
 
 0. Disclaimer
diff --git a/Documentation/input/joystick.txt b/Documentation/input/joystick.txt
index 389de9b..154d767 100644
--- a/Documentation/input/joystick.txt
+++ b/Documentation/input/joystick.txt
@@ -1,7 +1,6 @@
 		       Linux Joystick driver v2.0.0
 	       (c) 1996-2000 Vojtech Pavlik <vojtech@ucw.cz>
 			     Sponsored by SuSE
-	   $Id: joystick.txt,v 1.12 2002/03/03 12:13:07 jdeneux Exp $
 ----------------------------------------------------------------------------
 
 0. Disclaimer
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 09ad745..47e7d87 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1206,7 +1206,7 @@
 			         or
 			         memmap=0x10000$0x18690000
 
-	memtest=	[KNL,X86_64] Enable memtest
+	memtest=	[KNL,X86] Enable memtest
 			Format: <integer>
 			range: 0,4 : pattern number
 			default : 0 <disable>
@@ -1279,6 +1279,13 @@
 			This usage is only documented in each driver source
 			file if at all.
 
+	nf_conntrack.acct=
+			[NETFILTER] Enable connection tracking flow accounting
+			0 to disable accounting
+			1 to enable accounting
+			Default value depends on CONFIG_NF_CT_ACCT that is
+			going to be removed in 2.6.29.
+
 	nfsaddrs=	[NFS]
 			See Documentation/filesystems/nfsroot.txt.
 
@@ -2027,6 +2034,9 @@
 
 	snd-ymfpci=	[HW,ALSA]
 
+	softlockup_panic=
+			[KNL] Should the soft-lockup detector generate panics.
+
 	sonypi.*=	[HW] Sony Programmable I/O Control Device driver
 			See Documentation/sonypi.txt
 
@@ -2158,6 +2168,10 @@
 			Note that genuine overcurrent events won't be
 			reported either.
 
+	unknown_nmi_panic
+			[X86-32,X86-64]
+			Set unknown_nmi_panic=1 early on boot.
+
 	usbcore.autosuspend=
 			[USB] The autosuspend time delay (in seconds) used
 			for newly-detected USB devices (default 2).  This
diff --git a/Documentation/md.txt b/Documentation/md.txt
index a8b4306..1da9d1b 100644
--- a/Documentation/md.txt
+++ b/Documentation/md.txt
@@ -236,6 +236,11 @@
      writing the word for the desired state, however some states
      cannot be explicitly set, and some transitions are not allowed.
 
+     Select/poll works on this file.  All changes except between
+     	active_idle and active (which can be frequent and are not
+	very interesting) are notified.  active->active_idle is
+	reported if the metadata is externally managed.
+
      clear
          No devices, no size, no level
          Writing is equivalent to STOP_ARRAY ioctl
@@ -292,6 +297,10 @@
 	      writemostly - device will only be subject to read
 		         requests if there are no other options.
 			 This applies only to raid1 arrays.
+	      blocked  - device has failed, metadata is "external",
+	                 and the failure hasn't been acknowledged yet.
+			 Writes that would write to this device if
+			 it were not faulty are blocked.
 	      spare    - device is working, but not a full member.
 			 This includes spares that are in the process
 			 of being recovered to
@@ -301,6 +310,12 @@
 	Writing "remove" removes the device from the array.
 	Writing "writemostly" sets the writemostly flag.
 	Writing "-writemostly" clears the writemostly flag.
+	Writing "blocked" sets the "blocked" flag.
+	Writing "-blocked" clear the "blocked" flag and allows writes
+		to complete.
+
+	This file responds to select/poll. Any change to 'faulty'
+	or 'blocked' causes an event.
 
       errors
 	An approximate count of read errors that have been detected on
@@ -332,7 +347,7 @@
         for storage of data.  This will normally be the same as the
 	component_size.  This can be written while assembling an
         array.  If a value less than the current component_size is
-        written, component_size will be reduced to this value.
+        written, it will be rejected.
 
 
 An active md device will also contain and entry for each active device
@@ -381,6 +396,19 @@
 	'check' and 'repair' will start the appropriate process
            providing the current state is 'idle'.
 
+      This file responds to select/poll.  Any important change in the value
+      triggers a poll event.  Sometimes the value will briefly be
+      "recover" if a recovery seems to be needed, but cannot be
+      achieved. In that case, the transition to "recover" isn't
+      notified, but the transition away is.
+
+   degraded
+      This contains a count of the number of devices by which the
+      arrays is degraded.  So an optimal array with show '0'.  A
+      single failed/missing drive will show '1', etc.
+      This file responds to select/poll, any increase or decrease
+      in the count of missing devices will trigger an event.
+
    mismatch_count
       When performing 'check' and 'repair', and possibly when
       performing 'resync', md will count the number of errors that are
diff --git a/Documentation/networking/e1000.txt b/Documentation/networking/e1000.txt
index 61b171c..2df7186 100644
--- a/Documentation/networking/e1000.txt
+++ b/Documentation/networking/e1000.txt
@@ -513,21 +513,11 @@
   Intel(R) PRO/1000 PT Dual Port Server Connection
   Intel(R) PRO/1000 PT Dual Port Server Adapter
   Intel(R) PRO/1000 PF Dual Port Server Adapter
-  Intel(R) PRO/1000 PT Quad Port Server Adapter 
+  Intel(R) PRO/1000 PT Quad Port Server Adapter
 
   NAPI
   ----
-  NAPI (Rx polling mode) is supported in the e1000 driver.  NAPI is enabled
-  or disabled based on the configuration of the kernel.  To override
-  the default, use the following compile-time flags.
-
-  To enable NAPI, compile the driver module, passing in a configuration option:
-
-       make CFLAGS_EXTRA=-DE1000_NAPI install
-
-  To disable NAPI, compile the driver module, passing in a configuration option:
-
-       make CFLAGS_EXTRA=-DE1000_NO_NAPI install
+  NAPI (Rx polling mode) is enabled in the e1000 driver.
 
   See www.cyberus.ca/~hadi/usenix-paper.tgz for more information on NAPI.
 
diff --git a/Documentation/networking/udplite.txt b/Documentation/networking/udplite.txt
index 3870f28..855d8da 100644
--- a/Documentation/networking/udplite.txt
+++ b/Documentation/networking/udplite.txt
@@ -148,7 +148,7 @@
         getsockopt(sockfd, SOL_SOCKET, SO_NO_CHECK, &value, ...);
 
   is meaningless (as in TCP). Packets with a zero checksum field are
-  illegal (cf. RFC 3828, sec. 3.1) will be silently discarded.
+  illegal (cf. RFC 3828, sec. 3.1) and will be silently discarded.
 
   4) Fragmentation
 
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index aee243a..ea1b70b 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -89,10 +89,12 @@
     3) OpenPIC Interrupt Controllers
     4) ISA Interrupt Controllers
 
-  VIII - Specifying GPIO information for devices
+  IX - Specifying GPIO information for devices
     1) gpios property
     2) gpio-controller nodes
 
+  X - Specifying device power management information (sleep property)
+
   Appendix A - Sample SOC node for MPC8540
 
 
@@ -2488,8 +2490,8 @@
 	2 =  high to low edge sensitive type enabled
 	3 =  low to high edge sensitive type enabled
 
-VIII - Specifying GPIO information for devices
-==============================================
+IX - Specifying GPIO information for devices
+============================================
 
 1) gpios property
 -----------------
@@ -2537,116 +2539,151 @@
 		gpio-controller;
 	};
 
+X - Specifying Device Power Management Information (sleep property)
+===================================================================
+
+Devices on SOCs often have mechanisms for placing devices into low-power
+states that are decoupled from the devices' own register blocks.  Sometimes,
+this information is more complicated than a cell-index property can
+reasonably describe.  Thus, each device controlled in such a manner
+may contain a "sleep" property which describes these connections.
+
+The sleep property consists of one or more sleep resources, each of
+which consists of a phandle to a sleep controller, followed by a
+controller-specific sleep specifier of zero or more cells.
+
+The semantics of what type of low power modes are possible are defined
+by the sleep controller.  Some examples of the types of low power modes
+that may be supported are:
+
+ - Dynamic: The device may be disabled or enabled at any time.
+ - System Suspend: The device may request to be disabled or remain
+   awake during system suspend, but will not be disabled until then.
+ - Permanent: The device is disabled permanently (until the next hard
+   reset).
+
+Some devices may share a clock domain with each other, such that they should
+only be suspended when none of the devices are in use.  Where reasonable,
+such nodes should be placed on a virtual bus, where the bus has the sleep
+property.  If the clock domain is shared among devices that cannot be
+reasonably grouped in this manner, then create a virtual sleep controller
+(similar to an interrupt nexus, except that defining a standardized
+sleep-map should wait until its necessity is demonstrated).
+
 Appendix A - Sample SOC node for MPC8540
 ========================================
 
-Note that the #address-cells and #size-cells for the SoC node
-in this example have been explicitly listed; these are likely
-not necessary as they are usually the same as the root node.
-
-	soc8540@e0000000 {
+	soc@e0000000 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		#interrupt-cells = <2>;
+		compatible = "fsl,mpc8540-ccsr", "simple-bus";
 		device_type = "soc";
-		ranges = <00000000 e0000000 00100000>
-		reg = <e0000000 00003000>;
+		ranges = <0x00000000 0xe0000000 0x00100000>
 		bus-frequency = <0>;
-
-		mdio@24520 {
-			reg = <24520 20>;
-			device_type = "mdio";
-			compatible = "gianfar";
-
-			ethernet-phy@0 {
-				linux,phandle = <2452000>
-				interrupt-parent = <40000>;
-				interrupts = <35 1>;
-				reg = <0>;
-				device_type = "ethernet-phy";
-			};
-
-			ethernet-phy@1 {
-				linux,phandle = <2452001>
-				interrupt-parent = <40000>;
-				interrupts = <35 1>;
-				reg = <1>;
-				device_type = "ethernet-phy";
-			};
-
-			ethernet-phy@3 {
-				linux,phandle = <2452002>
-				interrupt-parent = <40000>;
-				interrupts = <35 1>;
-				reg = <3>;
-				device_type = "ethernet-phy";
-			};
-
-		};
+		interrupt-parent = <&pic>;
 
 		ethernet@24000 {
-			#size-cells = <0>;
+			#address-cells = <1>;
+			#size-cells = <1>;
 			device_type = "network";
 			model = "TSEC";
-			compatible = "gianfar";
-			reg = <24000 1000>;
-			mac-address = [ 00 E0 0C 00 73 00 ];
-			interrupts = <d 3 e 3 12 3>;
-			interrupt-parent = <40000>;
-			phy-handle = <2452000>;
+			compatible = "gianfar", "simple-bus";
+			reg = <0x24000 0x1000>;
+			local-mac-address = [ 00 E0 0C 00 73 00 ];
+			interrupts = <29 2 30 2 34 2>;
+			phy-handle = <&phy0>;
+			sleep = <&pmc 00000080>;
+			ranges;
+
+			mdio@24520 {
+				reg = <0x24520 0x20>;
+				compatible = "fsl,gianfar-mdio";
+
+				phy0: ethernet-phy@0 {
+					interrupts = <5 1>;
+					reg = <0>;
+					device_type = "ethernet-phy";
+				};
+
+				phy1: ethernet-phy@1 {
+					interrupts = <5 1>;
+					reg = <1>;
+					device_type = "ethernet-phy";
+				};
+
+				phy3: ethernet-phy@3 {
+					interrupts = <7 1>;
+					reg = <3>;
+					device_type = "ethernet-phy";
+				};
+			};
 		};
 
 		ethernet@25000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
 			device_type = "network";
 			model = "TSEC";
 			compatible = "gianfar";
-			reg = <25000 1000>;
-			mac-address = [ 00 E0 0C 00 73 01 ];
-			interrupts = <13 3 14 3 18 3>;
-			interrupt-parent = <40000>;
-			phy-handle = <2452001>;
+			reg = <0x25000 0x1000>;
+			local-mac-address = [ 00 E0 0C 00 73 01 ];
+			interrupts = <13 2 14 2 18 2>;
+			phy-handle = <&phy1>;
+			sleep = <&pmc 00000040>;
 		};
 
 		ethernet@26000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
 			device_type = "network";
 			model = "FEC";
 			compatible = "gianfar";
-			reg = <26000 1000>;
-			mac-address = [ 00 E0 0C 00 73 02 ];
-			interrupts = <19 3>;
-			interrupt-parent = <40000>;
-			phy-handle = <2452002>;
+			reg = <0x26000 0x1000>;
+			local-mac-address = [ 00 E0 0C 00 73 02 ];
+			interrupts = <41 2>;
+			phy-handle = <&phy3>;
+			sleep = <&pmc 00000020>;
 		};
 
 		serial@4500 {
-			device_type = "serial";
-			compatible = "ns16550";
-			reg = <4500 100>;
-			clock-frequency = <0>;
-			interrupts = <1a 3>;
-			interrupt-parent = <40000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8540-duart", "simple-bus";
+			sleep = <&pmc 00000002>;
+			ranges;
+
+			serial@4500 {
+				device_type = "serial";
+				compatible = "ns16550";
+				reg = <0x4500 0x100>;
+				clock-frequency = <0>;
+				interrupts = <42 2>;
+			};
+
+			serial@4600 {
+				device_type = "serial";
+				compatible = "ns16550";
+				reg = <0x4600 0x100>;
+				clock-frequency = <0>;
+				interrupts = <42 2>;
+			};
 		};
 
-		pic@40000 {
-			linux,phandle = <40000>;
+		pic: pic@40000 {
 			interrupt-controller;
 			#address-cells = <0>;
-			reg = <40000 40000>;
+			#interrupt-cells = <2>;
+			reg = <0x40000 0x40000>;
 			compatible = "chrp,open-pic";
 			device_type = "open-pic";
 		};
 
 		i2c@3000 {
-			interrupt-parent = <40000>;
-			interrupts = <1b 3>;
-			reg = <3000 18>;
-			device_type = "i2c";
+			interrupts = <43 2>;
+			reg = <0x3000 0x100>;
 			compatible  = "fsl-i2c";
 			dfsrr;
+			sleep = <&pmc 00000004>;
 		};
 
+		pmc: power@e0070 {
+			compatible = "fsl,mpc8540-pmc", "fsl,mpc8548-pmc";
+			reg = <0xe0070 0x20>;
+		};
 	};
diff --git a/Documentation/powerpc/dts-bindings/fsl/cpm_qe/gpio.txt b/Documentation/powerpc/dts-bindings/fsl/cpm_qe/gpio.txt
new file mode 100644
index 0000000..1815dfe
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/fsl/cpm_qe/gpio.txt
@@ -0,0 +1,38 @@
+Every GPIO controller node must have #gpio-cells property defined,
+this information will be used to translate gpio-specifiers.
+
+On CPM1 devices, all ports are using slightly different register layouts.
+Ports A, C and D are 16bit ports and Ports B and E are 32bit ports.
+
+On CPM2 devices, all ports are 32bit ports and use a common register layout.
+
+Required properties:
+- compatible : "fsl,cpm1-pario-bank-a", "fsl,cpm1-pario-bank-b",
+  "fsl,cpm1-pario-bank-c", "fsl,cpm1-pario-bank-d",
+  "fsl,cpm1-pario-bank-e", "fsl,cpm2-pario-bank"
+- #gpio-cells : Should be two. The first cell is the pin number and the
+  second cell is used to specify optional paramters (currently unused).
+- gpio-controller : Marks the port as GPIO controller.
+
+Example of three SOC GPIO banks defined as gpio-controller nodes:
+
+	CPM1_PIO_A: gpio-controller@950 {
+		#gpio-cells = <2>;
+		compatible = "fsl,cpm1-pario-bank-a";
+		reg = <0x950 0x10>;
+		gpio-controller;
+	};
+
+	CPM1_PIO_B: gpio-controller@ab8 {
+		#gpio-cells = <2>;
+		compatible = "fsl,cpm1-pario-bank-b";
+		reg = <0xab8 0x10>;
+		gpio-controller;
+	};
+
+	CPM1_PIO_E: gpio-controller@ac8 {
+		#gpio-cells = <2>;
+		compatible = "fsl,cpm1-pario-bank-e";
+		reg = <0xac8 0x18>;
+		gpio-controller;
+	};
diff --git a/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/usb.txt b/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/usb.txt
index c8f44d6..9ccd5f3 100644
--- a/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/usb.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/cpm_qe/qe/usb.txt
@@ -1,22 +1,37 @@
-* USB (Universal Serial Bus Controller)
+Freescale QUICC Engine USB Controller
 
 Required properties:
-- compatible : could be "qe_udc" or "fhci-hcd".
-- mode : the could be "host" or "slave".
-- reg : Offset and length of the register set for the device
-- interrupts : <a b> where a is the interrupt number and b is a
-  field that represents an encoding of the sense and level
-  information for the interrupt.  This should be encoded based on
-  the information in section 2) depending on the type of interrupt
-  controller you have.
-- interrupt-parent : the phandle for the interrupt controller that
-  services interrupts for this device.
+- compatible : should be "fsl,<chip>-qe-usb", "fsl,mpc8323-qe-usb".
+- reg : the first two cells should contain usb registers location and
+  length, the next two two cells should contain PRAM location and
+  length.
+- interrupts : should contain USB interrupt.
+- interrupt-parent : interrupt source phandle.
+- fsl,fullspeed-clock : specifies the full speed USB clock source:
+  "none": clock source is disabled
+  "brg1" through "brg16": clock source is BRG1-BRG16, respectively
+  "clk1" through "clk24": clock source is CLK1-CLK24, respectively
+- fsl,lowspeed-clock : specifies the low speed USB clock source:
+  "none": clock source is disabled
+  "brg1" through "brg16": clock source is BRG1-BRG16, respectively
+  "clk1" through "clk24": clock source is CLK1-CLK24, respectively
+- hub-power-budget : USB power budget for the root hub, in mA.
+- gpios : should specify GPIOs in this order: USBOE, USBTP, USBTN, USBRP,
+  USBRN, SPEED (optional), and POWER (optional).
 
-Example(slave):
-	usb@6c0 {
-		compatible = "qe_udc";
-		reg = <6c0 40>;
-		interrupts = <8b 0>;
-		interrupt-parent = <700>;
-		mode = "slave";
-	};
+Example:
+
+usb@6c0 {
+	compatible = "fsl,mpc8360-qe-usb", "fsl,mpc8323-qe-usb";
+	reg = <0x6c0 0x40 0x8b00 0x100>;
+	interrupts = <11>;
+	interrupt-parent = <&qeic>;
+	fsl,fullspeed-clock = "clk21";
+	gpios = <&qe_pio_b  2 0 /* USBOE */
+		 &qe_pio_b  3 0 /* USBTP */
+		 &qe_pio_b  8 0 /* USBTN */
+		 &qe_pio_b  9 0 /* USBRP */
+		 &qe_pio_b 11 0 /* USBRN */
+		 &qe_pio_e 20 0 /* SPEED */
+		 &qe_pio_e 21 0 /* POWER */>;
+};
diff --git a/Documentation/powerpc/dts-bindings/fsl/mcu-mpc8349emitx.txt b/Documentation/powerpc/dts-bindings/fsl/mcu-mpc8349emitx.txt
new file mode 100644
index 0000000..0f76633
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/fsl/mcu-mpc8349emitx.txt
@@ -0,0 +1,17 @@
+Freescale MPC8349E-mITX-compatible Power Management Micro Controller Unit (MCU)
+
+Required properties:
+- compatible : "fsl,<mcu-chip>-<board>", "fsl,mcu-mpc8349emitx".
+- reg : should specify I2C address (0x0a).
+- #gpio-cells : should be 2.
+- gpio-controller : should be present.
+
+Example:
+
+mcu@0a {
+	#gpio-cells = <2>;
+	compatible = "fsl,mc9s08qg8-mpc8349emitx",
+		     "fsl,mcu-mpc8349emitx";
+	reg = <0x0a>;
+	gpio-controller;
+};
diff --git a/Documentation/powerpc/dts-bindings/fsl/pmc.txt b/Documentation/powerpc/dts-bindings/fsl/pmc.txt
new file mode 100644
index 0000000..02f6f43
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/fsl/pmc.txt
@@ -0,0 +1,63 @@
+* Power Management Controller
+
+Properties:
+- compatible: "fsl,<chip>-pmc".
+
+  "fsl,mpc8349-pmc" should be listed for any chip whose PMC is
+  compatible.  "fsl,mpc8313-pmc" should also be listed for any chip
+  whose PMC is compatible, and implies deep-sleep capability.
+
+  "fsl,mpc8548-pmc" should be listed for any chip whose PMC is
+  compatible.  "fsl,mpc8536-pmc" should also be listed for any chip
+  whose PMC is compatible, and implies deep-sleep capability.
+
+  "fsl,mpc8641d-pmc" should be listed for any chip whose PMC is
+  compatible; all statements below that apply to "fsl,mpc8548-pmc" also
+  apply to "fsl,mpc8641d-pmc".
+
+  Compatibility does not include bit assigments in SCCR/PMCDR/DEVDISR; these
+  bit assigments are indicated via the sleep specifier in each device's
+  sleep property.
+
+- reg: For devices compatible with "fsl,mpc8349-pmc", the first resource
+  is the PMC block, and the second resource is the Clock Configuration
+  block.
+
+  For devices compatible with "fsl,mpc8548-pmc", the first resource
+  is a 32-byte block beginning with DEVDISR.
+
+- interrupts: For "fsl,mpc8349-pmc"-compatible devices, the first
+  resource is the PMC block interrupt.
+
+- fsl,mpc8313-wakeup-timer: For "fsl,mpc8313-pmc"-compatible devices,
+  this is a phandle to an "fsl,gtm" node on which timer 4 can be used as
+  a wakeup source from deep sleep.
+
+Sleep specifiers:
+
+  fsl,mpc8349-pmc: Sleep specifiers consist of one cell.  For each bit
+  that is set in the cell, the corresponding bit in SCCR will be saved
+  and cleared on suspend, and restored on resume.  This sleep controller
+  supports disabling and resuming devices at any time.
+
+  fsl,mpc8536-pmc: Sleep specifiers consist of three cells, the third of
+  which will be ORed into PMCDR upon suspend, and cleared from PMCDR
+  upon resume.  The first two cells are as described for fsl,mpc8578-pmc.
+  This sleep controller only supports disabling devices during system
+  sleep, or permanently.
+
+  fsl,mpc8548-pmc: Sleep specifiers consist of one or two cells, the
+  first of which will be ORed into DEVDISR (and the second into
+  DEVDISR2, if present -- this cell should be zero or absent if the
+  hardware does not have DEVDISR2) upon a request for permanent device
+  disabling.  This sleep controller does not support configuring devices
+  to disable during system sleep (unless supported by another compatible
+  match), or dynamically.
+
+Example:
+
+	power@b00 {
+		compatible = "fsl,mpc8313-pmc", "fsl,mpc8349-pmc";
+		reg = <0xb00 0x100 0xa00 0x100>;
+		interrupts = <80 8>;
+	};
diff --git a/Documentation/powerpc/dts-bindings/fsl/tsec.txt b/Documentation/powerpc/dts-bindings/fsl/tsec.txt
index 583ef6b..cf55fa4 100644
--- a/Documentation/powerpc/dts-bindings/fsl/tsec.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/tsec.txt
@@ -24,46 +24,39 @@
 
 * Gianfar-compatible ethernet nodes
 
-Required properties:
+Properties:
 
   - device_type : Should be "network"
   - model : Model of the device.  Can be "TSEC", "eTSEC", or "FEC"
   - compatible : Should be "gianfar"
   - reg : Offset and length of the register set for the device
-  - mac-address : List of bytes representing the ethernet address of
+  - local-mac-address : List of bytes representing the ethernet address of
     this controller
-  - interrupts : <a b> where a is the interrupt number and b is a
-    field that represents an encoding of the sense and level
-    information for the interrupt.  This should be encoded based on
-    the information in section 2) depending on the type of interrupt
-    controller you have.
-  - interrupt-parent : the phandle for the interrupt controller that
-    services interrupts for this device.
+  - interrupts : For FEC devices, the first interrupt is the device's
+    interrupt.  For TSEC and eTSEC devices, the first interrupt is
+    transmit, the second is receive, and the third is error.
   - phy-handle : The phandle for the PHY connected to this ethernet
     controller.
   - fixed-link : <a b c d e> where a is emulated phy id - choose any,
     but unique to the all specified fixed-links, b is duplex - 0 half,
     1 full, c is link speed - d#10/d#100/d#1000, d is pause - 0 no
     pause, 1 pause, e is asym_pause - 0 no asym_pause, 1 asym_pause.
-
-Recommended properties:
-
   - phy-connection-type : a string naming the controller/PHY interface type,
     i.e., "mii" (default), "rmii", "gmii", "rgmii", "rgmii-id", "sgmii",
     "tbi", or "rtbi".  This property is only really needed if the connection
     is of type "rgmii-id", as all other connection types are detected by
     hardware.
-
+  - fsl,magic-packet : If present, indicates that the hardware supports
+    waking up via magic packet.
 
 Example:
 	ethernet@24000 {
-		#size-cells = <0>;
 		device_type = "network";
 		model = "TSEC";
 		compatible = "gianfar";
-		reg = <24000 1000>;
-		mac-address = [ 00 E0 0C 00 73 00 ];
-		interrupts = <d 3 e 3 12 3>;
-		interrupt-parent = <40000>;
-		phy-handle = <2452000>
+		reg = <0x24000 0x1000>;
+		local-mac-address = [ 00 E0 0C 00 73 00 ];
+		interrupts = <29 2 30 2 34 2>;
+		interrupt-parent = <&mpic>;
+		phy-handle = <&phy0>
 	};
diff --git a/Documentation/powerpc/dts-bindings/fsl/upm-nand.txt b/Documentation/powerpc/dts-bindings/fsl/upm-nand.txt
new file mode 100644
index 0000000..84a04d5
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/fsl/upm-nand.txt
@@ -0,0 +1,28 @@
+Freescale Localbus UPM programmed to work with NAND flash
+
+Required properties:
+- compatible : "fsl,upm-nand".
+- reg : should specify localbus chip select and size used for the chip.
+- fsl,upm-addr-offset : UPM pattern offset for the address latch.
+- fsl,upm-cmd-offset : UPM pattern offset for the command latch.
+- gpios : may specify optional GPIO connected to the Ready-Not-Busy pin.
+
+Example:
+
+upm@1,0 {
+	compatible = "fsl,upm-nand";
+	reg = <1 0 1>;
+	fsl,upm-addr-offset = <16>;
+	fsl,upm-cmd-offset = <8>;
+	gpios = <&qe_pio_e 18 0>;
+
+	flash {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "...";
+
+		partition@0 {
+			...
+		};
+	};
+};
diff --git a/Documentation/powerpc/dts-bindings/gpio/led.txt b/Documentation/powerpc/dts-bindings/gpio/led.txt
new file mode 100644
index 0000000..ff51f4c0
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/gpio/led.txt
@@ -0,0 +1,15 @@
+LED connected to GPIO
+
+Required properties:
+- compatible : should be "gpio-led".
+- label : (optional) the label for this LED. If omitted, the label is
+  taken from the node name (excluding the unit address).
+- gpios : should specify LED GPIO.
+
+Example:
+
+led@0 {
+	compatible = "gpio-led";
+	label = "hdd";
+	gpios = <&mcu_pio 0 1>;
+};
diff --git a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl b/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
index c4d2e35..9d644f7 100644
--- a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
+++ b/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
@@ -42,7 +42,7 @@
      <sect1><title>Device Components</title>
 !Esound/core/device.c
      </sect1>
-     <sect1><title>KMOD and Device File Entries</title>
+     <sect1><title>Module requests and Device File Entries</title>
 !Esound/core/sound.c
      </sect1>
      <sect1><title>Memory Management Helpers</title>
diff --git a/Documentation/specialix.txt b/Documentation/specialix.txt
index 4a4b428..6eb6f3a 100644
--- a/Documentation/specialix.txt
+++ b/Documentation/specialix.txt
@@ -270,8 +270,8 @@
 Hardware handshaking issues.
 ============================
 
-The driver can be compiled in two different ways. The default
-("Specialix DTR/RTS pin is RTS" is off) the pin behaves as DTR when
+The driver can be told to operate in two different ways. The default
+behaviour is specialix.sx_rtscts = 0 where the pin behaves as DTR when
 hardware handshaking is off. It behaves as the RTS hardware
 handshaking signal when hardware handshaking is selected.
 
@@ -280,7 +280,7 @@
 software handshaking. So switching on the fly is not really an
 option.
 
-I actually prefer to use the "Specialix DTR/RTS pin is RTS" option.
+I actually prefer to use the "specialix.sx_rtscts=1" option.
 This makes the DTR/RTS pin always an RTS pin, and ioctls to
 change DTR are always ignored. I have a cable that is configured
 for this. 
@@ -379,7 +379,5 @@
             You have to WRITE to the address register to even 
             read-probe a CD186x register. Disable autodetection?
          -- Specialix: any suggestions?
-       - Arbitrary baud rates are not implemented yet. 
-            If you need this, bug me about it. 
 
 
diff --git a/Documentation/sysfs-rules.txt b/Documentation/sysfs-rules.txt
index 80ef562..6049a2a 100644
--- a/Documentation/sysfs-rules.txt
+++ b/Documentation/sysfs-rules.txt
@@ -3,9 +3,8 @@
 The kernel-exported sysfs exports internal kernel implementation details
 and depends on internal kernel structures and layout. It is agreed upon
 by the kernel developers that the Linux kernel does not provide a stable
-internal API. As sysfs is a direct export of kernel internal
-structures, the sysfs interface cannot provide a stable interface either;
-it may always change along with internal kernel changes.
+internal API. Therefore, there are aspects of the sysfs interface that
+may not be stable across kernel releases.
 
 To minimize the risk of breaking users of sysfs, which are in most cases
 low-level userspace applications, with a new kernel release, the users
diff --git a/Documentation/telephony/ixj.txt b/Documentation/telephony/ixj.txt
index 621024f..44d12400 100644
--- a/Documentation/telephony/ixj.txt
+++ b/Documentation/telephony/ixj.txt
@@ -305,21 +305,14 @@
 
 which will result in the needed drivers getting loaded automatically.
 
-   g.  if you are planning on using kerneld to automatically load the 
-module for you, then you need to edit /etc/conf.modules and add the 
+   g.  if you are planning on having the kernel automatically request
+the module for you, then you need to edit /etc/conf.modules and add the
 following lines:
 
 	options ixj dspio=0x340 xio=0x330 ixjdebug=0
 
 If you do this, then when you execute an application that uses the
-module kerneld will load the module for you.  Note that to do this,
-you need to have your kernel set to support kerneld.  You can check
-for this by looking at /usr/src/linux/.config and you should see this:
-
-	# Loadable module support
-	#
-	<snip>
-	CONFIG_KMOD=y
+module the kernel will request that it is loaded.
 
   h.  if you want non-root users to be able to read and write to the 
 ixj devices (this is a good idea!) you should do the following:
diff --git a/Documentation/usb/gadget_serial.txt b/Documentation/usb/gadget_serial.txt
index 815f5c2..9b22bd1 100644
--- a/Documentation/usb/gadget_serial.txt
+++ b/Documentation/usb/gadget_serial.txt
@@ -1,6 +1,7 @@
 
                  Linux Gadget Serial Driver v2.0
                            11/20/2004
+                  (updated 8-May-2008 for v2.3)
 
 
 License and Disclaimer
@@ -31,7 +32,7 @@
 -------------
 Versions of the gadget serial driver are available for the
 2.4 Linux kernels, but this document assumes you are using
-version 2.0 or later of the gadget serial driver in a 2.6
+version 2.3 or later of the gadget serial driver in a 2.6
 Linux kernel.
 
 This document assumes that you are familiar with Linux and
@@ -40,6 +41,12 @@
 USB and serial devices.  It also assumes you configure the Linux
 gadget and usb drivers as modules.
 
+With version 2.3 of the driver, major and minor device nodes are
+no longer statically defined.  Your Linux based system should mount
+sysfs in /sys, and use "mdev" (in Busybox) or "udev" to make the
+/dev nodes matching the sysfs /sys/class/tty files.
+
+
 
 Overview
 --------
@@ -104,15 +111,8 @@
 configuring the kernel.  Then rebuild and install the kernel or
 modules.
 
-The gadget serial driver uses major number 127, for now.  So you
-will need to create a device node for it, like this:
-
-  mknod /dev/ttygserial c 127 0
-
-You only need to do this once.
-
 Then you must load the gadget serial driver.  To load it as an
-ACM device, do this:
+ACM device (recommended for interoperability), do this:
 
   modprobe g_serial use_acm=1
 
@@ -125,6 +125,23 @@
 side Linux system.  You can add this to the start up scripts, if
 desired.
 
+Your system should use mdev (from busybox) or udev to make the
+device nodes.  After this gadget driver has been set up you should
+then see a /dev/ttyGS0 node:
+
+  # ls -l /dev/ttyGS0 | cat
+  crw-rw----    1 root     root     253,   0 May  8 14:10 /dev/ttyGS0
+  #
+
+Note that the major number (253, above) is system-specific.  If
+you need to create /dev nodes by hand, the right numbers to use
+will be in the /sys/class/tty/ttyGS0/dev file.
+
+When you link this gadget driver early, perhaps even statically,
+you may want to set up an /etc/inittab entry to run "getty" on it.
+The /dev/ttyGS0 line should work like most any other serial port.
+
+
 If gadget serial is loaded as an ACM device you will want to use
 either the Windows or Linux ACM driver on the host side.  If gadget
 serial is loaded as a bulk in/out device, you will want to use the
diff --git a/Documentation/usb/persist.txt b/Documentation/usb/persist.txt
index d56cb1a..074b159 100644
--- a/Documentation/usb/persist.txt
+++ b/Documentation/usb/persist.txt
@@ -81,8 +81,11 @@
 same descriptors as before, including the Vendor and Product IDs, then
 the kernel continues to use the same device structure.  In effect, the
 kernel treats the device as though it had merely been reset instead of
-unplugged.  The same thing happens if the host controller is in the
-expected state but a USB device was unplugged and then replugged.
+unplugged.
+
+The same thing happens if the host controller is in the expected state
+but a USB device was unplugged and then replugged, or if a USB device
+fails to carry out a normal resume.
 
 If no device is now attached to the port, or if the descriptors are
 different from what the kernel remembers, then the treatment is what
diff --git a/Documentation/usb/uhci.txt b/Documentation/usb/uhci.txt
deleted file mode 100644
index 2f25952..0000000
--- a/Documentation/usb/uhci.txt
+++ /dev/null
@@ -1,165 +0,0 @@
-Specification and Internals for the New UHCI Driver (Whitepaper...)
-
-	brought to you by
-
-	Georg Acher, acher@in.tum.de (executive slave) (base guitar)
-	Deti Fliegl, deti@fliegl.de (executive slave) (lead voice)
-	Thomas Sailer, sailer@ife.ee.ethz.ch (chief consultant) (cheer leader)
- 
-	$Id: README.uhci,v 1.1 1999/12/14 14:03:02 fliegl Exp $
-
-This document and the new uhci sources can be found on
-		http://hotswap.in.tum.de/usb
-
-1. General issues
-
-1.1 Why a new UHCI driver, we already have one?!?
-
-Correct, but its internal structure got more and more mixed up by the (still
-ongoing) efforts to get isochronous transfers (ISO) to work.
-Since there is an increasing need for reliable ISO-transfers (especially 
-for USB-audio needed by TS and for a DAB-USB-Receiver build by GA and DF), 
-this state was a bit unsatisfying in our opinion, so we've decided (based
-on knowledge and experiences with the old UHCI driver) to start 
-from scratch with a new approach, much simpler but at the same time more 
-powerful.
-It is inspired by the way Win98/Win2000 handles USB requests via URBs,
-but it's definitely 100% free of MS-code and doesn't crash while 
-unplugging an used ISO-device like Win98 ;-)
-Some code for HW setup and root hub management was taken from the 
-original UHCI driver, but heavily modified to fit into the new code.
-The invention of the basic concept, and major coding were completed in two 
-days (and nights) on the 16th and 17th of October 1999, now known as the
-great USB-October-Revolution started by GA, DF, and TS ;-)
-
-Since the concept is in no way UHCI dependent, we hope that it will also be 
-transferred to the OHCI-driver, so both drivers share a common API.
-
-1.2. Advantages and disadvantages
-
-+ All USB transfer types work now!
-+ Asynchronous operation
-+ Simple, but powerful interface (only two calls for start and cancel)
-+ Easy migration to the new API, simplified by a compatibility API
-+ Simple usage of ISO transfers
-+ Automatic linking of requests
-+ ISO transfers allow variable length for each frame and striping
-+ No CPU dependent and non-portable atomic memory access, no asm()-inlines
-+ Tested on x86 and Alpha
-
-- Rewriting for ISO transfers needed
-
-1.3. Is there some compatibility to the old API?
-
-Yes, but only for control, bulk and interrupt transfers. We've implemented 
-some wrapper calls for these transfer types. The usbcore works fine with 
-these wrappers. For ISO there's no compatibility, because the old ISO-API 
-and its semantics were unnecessary complicated in our opinion.
-
-1.4. What's really working?
-
-As said above, CTRL and BULK already work fine even with the wrappers,
-so legacy code wouldn't notice the change.
-Regarding to Thomas, ISO transfers now run stable with USB audio.
-INT transfers (e.g. mouse driver) work fine, too.
-
-1.5. Are there any bugs?
-
-No ;-)
-Hm...
-Well, of course this implementation needs extensive testing on all available
-hardware, but we believe that any fixes shouldn't harm the overall concept.
-
-1.6. What should be done next?
-
-A large part of the request handling seems to be identical for UHCI and 
-OHCI, so it would be a good idea to extract the common parts and have only 
-the HW specific stuff in uhci.c. Furthermore, all other USB device drivers
-should need URBification, if they use isochronous or interrupt transfers.
-One thing missing in the current implementation (and the old UHCI driver) 
-is fair queueing for BULK transfers. Since this would need (in principle) 
-the alteration of already constructed TD chains (to switch from depth to 
-breadth execution), another way has to be found. Maybe some simple 
-heuristics work with the same effect.
-
----------------------------------------------------------------------------
-
-2. Internal structure and mechanisms
-
-To get quickly familiar with the internal structures, here's a short
-description how the new UHCI driver works. However, the ultimate source of
-truth is only uhci.c!
-
-2.1. Descriptor structure (QHs and TDs)
-
-During initialization, the following skeleton is allocated in init_skel:
-
-	 framespecific           |           common chain     
-
-framelist[]
-[  0 ]-----> TD --> TD -------\
-[  1 ]-----> TD --> TD --------> TD ----> QH -------> QH -------> QH ---> NULL
-  ...        TD --> TD -------/
-[1023]-----> TD --> TD ------/
-	     
-	     ^^     ^^           ^^       ^^          ^^          ^^
-   1024 TDs for   7 TDs for    1 TD for   Start of    Start of    End Chain
-	    ISO  INT (2-128ms) 1ms-INT    CTRL Chain  BULK Chain
-
-For each CTRL or BULK transfer a new QH is allocated and the containing data
-transfers are appended as (vertical) TDs. After building the whole QH with its
-dangling TDs, the QH is inserted before the BULK Chain QH (for CTRL) or
-before the End Chain QH (for BULK). Since only the QH->next pointers are
-affected, no atomic memory operation is required. The three QHs in the
-common chain are never equipped with TDs!
-
-For ISO or INT, the TD for each frame is simply inserted into the appropriate
-ISO/INT-TD-chain for the desired frame. The 7 skeleton INT-TDs are scattered
-among the 1024 frames similar to the old UHCI driver.
-
-For CTRL/BULK/ISO, the last TD in the transfer has the IOC-bit set. For INT,
-every TD (there is only one...) has the IOC-bit set.
-
-Besides the data for the UHCI controller (2 or 4 32bit words), the descriptors
-are double-linked through the .vertical and .horizontal elements in the 
-SW data of the descriptor (using the double-linked list structures and 
-operations), but SW-linking occurs only in closed domains, i.e. for each of
-the 1024 ISO-chains and the 8 INT-chains there is a closed cycle. This 
-simplifies all insertions and unlinking operations and avoids costly 
-bus_to_virt()-calls.
-
-2.2. URB structure and linking to QH/TDs
-
-During assembly of the QH and TDs of the requested action, these descriptors
-are stored in urb->urb_list, so the allocated QH/TD descriptors are bound to
-this URB.
-If the assembly was successful and the descriptors were added to the HW chain,
-the corresponding URB is inserted into a global URB list for this controller.
-This list stores all pending URBs.
-
-2.3. Interrupt processing
-
-Since UHCI provides no means to directly detect completed transactions, the
-following is done in each UHCI interrupt (uhci_interrupt()):
-
-For each URB in the pending queue (process_urb()), the ACTIVE-flag of the 
-associated TDs are processed (depending on the transfer type 
-process_{transfer|interrupt|iso}()). If the TDs are not active anymore, 
-they indicate the completion of the transaction and the status is calculated. 
-Inactive QH/TDs are removed from the HW chain (since the host controller
-already removed the TDs from the QH, no atomic access is needed) and 
-eventually the URB is marked as completed (OK or errors) and removed from the 
-pending queue. Then the next linked URB is submitted. After (or immediately 
-before) that, the completion handler is called.
-
-2.4. Unlinking URBs
-
-First, all QH/TDs stored in the URB are unlinked from the HW chain. 
-To ensure that the host controller really left a vertical TD chain, we 
-wait for one frame. After that, the TDs are physically destroyed.
-
-2.5. URB linking and the consequences
-
-Since URBs can be linked and the corresponding submit_urb is called in
-the UHCI-interrupt, all work associated with URB/QH/TD assembly has to be
-interrupt save. This forces kmalloc to use GFP_ATOMIC in the interrupt.
diff --git a/Documentation/video4linux/w9968cf.txt b/Documentation/video4linux/w9968cf.txt
index e0bba83..05138e8 100644
--- a/Documentation/video4linux/w9968cf.txt
+++ b/Documentation/video4linux/w9968cf.txt
@@ -193,9 +193,6 @@
 		 loads that module automatically. This action is performed as
 		 once soon as the 'w9968cf' module is loaded into memory.
 Default:         1
-Note:            The kernel must be compiled with the CONFIG_KMOD option
-		 enabled for the 'ovcamchip' module to be loaded and for
-		 this parameter to be present.
 -------------------------------------------------------------------------------
 Name:           simcams
 Type:           int
diff --git a/MAINTAINERS b/MAINTAINERS
index ec0c9c9..5d8971c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -441,10 +441,7 @@
 S:	Maintained
 
 ARM PRIMECELL MMCI PL180/1 DRIVER
-P:	Russell King
-M:	rmk@arm.linux.org.uk
-L:	linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
-S:	Maintained
+S:	Orphan
 
 ARM/ADI ROADRUNNER MACHINE SUPPORT
 P:	Lennert Buytenhek
@@ -483,11 +480,28 @@
 L:	linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:	Maintained
 
+ARM/COMPULAB CM-X270/EM-X270 MACHINE SUPPORT
+P:	Mike Rapoport
+M:	mike@compulab.co.il
+L:	linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+S:	Maintained
+
 ARM/CORGI MACHINE SUPPORT
 P:	Richard Purdie
 M:	rpurdie@rpsys.net
 S:	Maintained
 
+ARM/EZX SMARTPHONES (A780, A910, A1200, E680, ROKR E2 and ROKR E6)
+P:	Daniel Ribeiro
+M:	drwyrm@gmail.com
+P:	Stefan Schmidt
+M:	stefan@openezx.org
+P:	Harald Welte
+M:	laforge@openezx.org
+L:	openezx-devel@lists.openezx.org (subscribers-only)
+W:	http://www.openezx.org/
+S:	Maintained
+
 ARM/GLOMATION GESBC9312SX MACHINE SUPPORT
 P:	Lennert Buytenhek
 M:	kernel@wantstofly.org
@@ -575,10 +589,18 @@
 S:	Maintained
 
 ARM/TOSA MACHINE SUPPORT
+P:	Dmitry Baryshkov
+M:	dbaryshkov@gmail.com
 P:	Dirk Opfer
 M:	dirk@opfer-online.de
 S:	Maintained
 
+ARM/PALMTX SUPPORT
+P:	Marek Vasut
+M:	marek.vasut@gmail.com
+W:	http://hackndev.com
+S:	Maintained
+
 ARM/PLEB SUPPORT
 P:	Peter Chubb
 M:	pleb@gelato.unsw.edu.au
@@ -1988,6 +2010,12 @@
 W:	http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
 S:	Maintained
 
+HTCPEN TOUCHSCREEN DRIVER
+P:	Pau Oliva Fora
+M:	pof@eslack.org
+L:	linux-input@vger.kernel.org
+S:	Maintained
+
 HUGETLB FILESYSTEM
 P:	William Irwin
 M:	wli@holomorphy.com
@@ -3527,7 +3555,7 @@
 
 S390 NETWORK DRIVERS
 P:	Ursula Braun
-M:	ubraun@linux.vnet.ibm.com
+M:	ursula.braun@de.ibm.com
 P:	Frank Blaschka
 M:	blaschka@linux.vnet.ibm.com
 M:	linux390@de.ibm.com
@@ -3547,7 +3575,7 @@
 
 S390 IUCV NETWORK LAYER
 P:	Ursula Braun
-M:	ubraun@linux.vnet.ibm.com
+M:	ursula.braun@de.ibm.com
 M:	linux390@de.ibm.com
 L:	linux-s390@vger.kernel.org
 W:	http://www.ibm.com/developerworks/linux/linux390/
@@ -4041,9 +4069,10 @@
 S:	Maintained
 
 TPM DEVICE DRIVER
-P:     Debora Velarde
-P:     Rajiv Andrade
-M:	tpmdd-devel@lists.sourceforge.net
+P:	Debora Velarde
+M:	debora@linux.vnet.ibm.com
+P:	Rajiv Andrade
+M:	srajiv@linux.vnet.ibm.com
 W:	http://tpmdd.sourceforge.net
 P:	Marcel Selhorst
 M:	tpm@selhorst.net
diff --git a/Makefile b/Makefile
index 6192922..4bcd1cf 100644
--- a/Makefile
+++ b/Makefile
@@ -1148,7 +1148,8 @@
 	@find . $(RCS_FIND_IGNORE) \
 		\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
 		-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
-		-o -name '*.symtypes' -o -name 'modules.order' \) \
+		-o -name '*.symtypes' -o -name 'modules.order' \
+		-o -name 'Module.markers' \) \
 		-type f -print | xargs rm -f
 
 # mrproper - Delete all generated files, including .config
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index c7ad324..d048f68 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -12,6 +12,7 @@
 	select RTC_LIB
 	select SYS_SUPPORTS_APM_EMULATION
 	select HAVE_OPROFILE
+	select HAVE_ARCH_KGDB
 	select HAVE_KPROBES if (!XIP_KERNEL)
 	select HAVE_KRETPROBES if (HAVE_KPROBES)
 	select HAVE_FTRACE if (!XIP_KERNEL)
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 2744673..dd29473 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -554,9 +554,8 @@
 
 	device_info = kmalloc(sizeof(struct dmabounce_device_info), GFP_ATOMIC);
 	if (!device_info) {
-		printk(KERN_ERR
-			"Could not allocated dmabounce_device_info for %s",
-			dev->bus_id);
+		dev_err(dev,
+			"Could not allocated dmabounce_device_info\n");
 		return -ENOMEM;
 	}
 
@@ -594,8 +593,7 @@
 
 	dev->archdata.dmabounce = device_info;
 
-	printk(KERN_INFO "dmabounce: registered device %s on %s bus\n",
-		dev->bus_id, dev->bus->name);
+	dev_info(dev, "dmabounce: registered device\n");
 
 	return 0;
 
@@ -614,16 +612,15 @@
 	dev->archdata.dmabounce = NULL;
 
 	if (!device_info) {
-		printk(KERN_WARNING
-			"%s: Never registered with dmabounce but attempting" \
-			"to unregister!\n", dev->bus_id);
+		dev_warn(dev,
+			 "Never registered with dmabounce but attempting"
+			 "to unregister!\n");
 		return;
 	}
 
 	if (!list_empty(&device_info->safe_buffers)) {
-		printk(KERN_ERR
-			"%s: Removing from dmabounce with pending buffers!\n",
-			dev->bus_id);
+		dev_err(dev,
+			"Removing from dmabounce with pending buffers!\n");
 		BUG();
 	}
 
@@ -639,8 +636,7 @@
 
 	kfree(device_info);
 
-	printk(KERN_INFO "dmabounce: device %s on %s bus unregistered\n",
-		dev->bus_id, dev->bus->name);
+	dev_info(dev, "dmabounce: device unregistered\n");
 }
 
 
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index d973c98..c3c3a33 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -543,7 +543,6 @@
 		goto out;
 	}
 
-	strncpy(dev->dev.bus_id, info->name, sizeof(dev->dev.bus_id));
 	/*
 	 * If the parent device has a DMA mask associated with it,
 	 * propagate it down to the children.
@@ -553,6 +552,7 @@
 		dev->dev.dma_mask = &dev->dma_mask;
 	}
 
+	dev_set_name(&dev->dev, "%s", info->name);
 	dev->devid	 = info->devid;
 	dev->dev.parent  = lchip->dev;
 	dev->dev.bus     = &locomo_bus_type;
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index eb06d0b..0a8e1ff 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -550,9 +550,7 @@
 		goto out;
 	}
 
-	snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id),
-		 "%4.4lx", info->offset);
-
+	dev_set_name(&dev->dev, "%4.4lx", info->offset);
 	dev->devid	 = info->devid;
 	dev->dev.parent  = sachip->dev;
 	dev->dev.bus     = &sa1111_bus_type;
@@ -560,7 +558,7 @@
 	dev->dev.coherent_dma_mask = sachip->dev->coherent_dma_mask;
 	dev->res.start   = sachip->phys + info->offset;
 	dev->res.end     = dev->res.start + 511;
-	dev->res.name    = dev->dev.bus_id;
+	dev->res.name    = dev_name(&dev->dev);
 	dev->res.flags   = IORESOURCE_MEM;
 	dev->mapbase     = sachip->base + info->offset;
 	dev->skpcr_mask  = info->skpcr_mask;
@@ -570,6 +568,7 @@
 	if (ret) {
 		printk("SA1111: failed to allocate resource for %s\n",
 			dev->res.name);
+		dev_set_name(&dev->dev, NULL);
 		kfree(dev);
 		goto out;
 	}
@@ -593,7 +592,8 @@
 		if (dev->dma_mask != 0xffffffffUL) {
 			ret = dmabounce_register_dev(&dev->dev, 1024, 4096);
 			if (ret) {
-				printk("SA1111: Failed to register %s with dmabounce", dev->dev.bus_id);
+				dev_err(&dev->dev, "SA1111: Failed to register"
+					" with dmabounce\n");
 				device_unregister(&dev->dev);
 			}
 		}
@@ -627,7 +627,7 @@
 	if (!sachip)
 		return -ENOMEM;
 
-	sachip->clk = clk_get(me, "GPIO27_CLK");
+	sachip->clk = clk_get(me, "SA1111_CLK");
 	if (!sachip->clk) {
 		ret = PTR_ERR(sachip->clk);
 		goto err_free;
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
index bc299b0..ae39553 100644
--- a/arch/arm/common/scoop.c
+++ b/arch/arm/common/scoop.c
@@ -247,7 +247,7 @@
 	devptr->gpio.base = -1;
 
 	if (inf->gpio_base != 0) {
-		devptr->gpio.label = pdev->dev.bus_id;
+		devptr->gpio.label = dev_name(&pdev->dev);
 		devptr->gpio.base = inf->gpio_base;
 		devptr->gpio.ngpio = 12; /* PA11 = 0, PA12 = 1, etc. up to PA22 = 11 */
 		devptr->gpio.set = scoop_gpio_set;
diff --git a/arch/arm/configs/ezx_defconfig b/arch/arm/configs/ezx_defconfig
new file mode 100644
index 0000000..2a84d55
--- /dev/null
+++ b/arch/arm/configs/ezx_defconfig
@@ -0,0 +1,1614 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.26-rc3
+# Mon Jul  7 17:52:21 2008
+#
+CONFIG_ARM=y
+CONFIG_HAVE_PWM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
+CONFIG_ZONE_DMA=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION="-ezxdev"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_CLASSIC_RCU=y
+
+#
+# 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_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+CONFIG_ARCH_PXA=y
+# 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_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_MSM7X00A is not set
+
+#
+# Intel PXA2xx/PXA3xx Implementations
+#
+# CONFIG_ARCH_GUMSTIX is not set
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_MACH_LOGICPD_PXA270 is not set
+# CONFIG_MACH_MAINSTONE is not set
+# CONFIG_ARCH_PXA_IDP is not set
+# CONFIG_PXA_SHARPSL is not set
+# CONFIG_ARCH_PXA_ESERIES is not set
+# CONFIG_MACH_TRIZEPS4 is not set
+# CONFIG_MACH_EM_X270 is not set
+# CONFIG_MACH_COLIBRI is not set
+# CONFIG_MACH_ZYLONITE is not set
+# CONFIG_MACH_LITTLETON is not set
+# CONFIG_MACH_ARMCORE is not set
+# CONFIG_MACH_MAGICIAN is not set
+# CONFIG_MACH_PCM027 is not set
+CONFIG_PXA_EZX=y
+CONFIG_MACH_EZX_A780=y
+CONFIG_MACH_EZX_E680=y
+CONFIG_MACH_EZX_A1200=y
+CONFIG_MACH_EZX_A910=y
+CONFIG_MACH_EZX_E6=y
+CONFIG_MACH_EZX_E2=y
+CONFIG_PXA27x=y
+CONFIG_PXA_SSP=y
+CONFIG_PXA_PWM=y
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_PABRT_NOIFAR=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_OUTER_CACHE is not set
+CONFIG_IWMMXT=y
+CONFIG_XSCALE_PMU=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# 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_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=tty1 root=/dev/mmcblk0p2 rootfstype=ext2 rootdelay=1 ip=192.168.0.202:192.168.0.200:192.168.0.200:255.255.255.0 debug"
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ 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=m
+CONFIG_BINFMT_MISC=m
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_APM_EMULATION=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+# CONFIG_NF_CT_PROTO_DCCP is not set
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# Bridge: Netfilter Configuration
+#
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=m
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_SCH_FIFO=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=y
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+# CONFIG_BT_HCIUSB is not set
+# CONFIG_BT_HCIBTUSB is not set
+# CONFIG_BT_HCIBTSDIO is not set
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+# CONFIG_BT_HCIUART_BCSP is not set
+# CONFIG_BT_HCIUART_LL is not set
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+
+#
+# Wireless
+#
+CONFIG_CFG80211=m
+CONFIG_NL80211=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_MAC80211=m
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_NONE is not set
+
+#
+# Selecting 'y' for an algorithm will
+#
+
+#
+# build the algorithm into mac80211.
+#
+CONFIG_MAC80211_RC_DEFAULT="pid"
+CONFIG_MAC80211_RC_PID=y
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT is not set
+# CONFIG_MAC80211_DEBUG is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=m
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+# CONFIG_MTD_BLKDEVS is not set
+# CONFIG_MTD_BLOCK is not set
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=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=y
+# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
+# 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 is not set
+# 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
+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=y
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x0
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PXA2XX is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_SHARP_SL is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_NET_ETHERNET is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+# CONFIG_INPUT_APMPOWER is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_KEYBOARD_PXA27x=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_UCB1400 is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+CONFIG_TOUCHSCREEN_PCAP=y
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+CONFIG_INPUT_UINPUT=y
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=8
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_PXA=y
+# CONFIG_I2C_PXA_SLAVE is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+CONFIG_SPI_PXA2XX=m
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_HAVE_GPIO_LIB=y
+
+#
+# GPIO Support
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TC6393XB is not set
+CONFIG_EZX_PCAP=y
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+# CONFIG_DVB_CORE is not set
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_V4L_USB_DRIVERS is not set
+# CONFIG_SOC_CAMERA is not set
+# CONFIG_VIDEO_PXA27x is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_SI470X is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_SMARTPANEL is not set
+CONFIG_FB_PXA_PARAMETERS=y
+# CONFIG_FB_MBX is not set
+# CONFIG_FB_AM200EPD is not set
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_CORGI is not set
+CONFIG_BACKLIGHT_PWM=y
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+CONFIG_FONT_MINI_4x6=y
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+# CONFIG_LOGO is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+# CONFIG_SND_PXA2XX_AC97 is not set
+
+#
+# SPI devices
+#
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+
+#
+# System on Chip audio support
+#
+CONFIG_SND_SOC=y
+CONFIG_SND_PXA2XX_SOC=y
+
+#
+# ALSA SoC audio for Freescale SOCs
+#
+
+#
+# SoC Audio for the Texas Instruments OMAP
+#
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW 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_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_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_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MON is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_M66592 is not set
+CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=y
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+# CONFIG_USB_ZERO is not set
+CONFIG_USB_ETH=y
+# CONFIG_USB_ETH_RNDIS is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=y
+
+#
+# MMC/SD Host Controller Drivers
+#
+CONFIG_MMC_PXA=y
+# CONFIG_MMC_SPI is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_GPIO is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_SA1100=m
+# CONFIG_UIO 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=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=m
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_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_JFFS2_FS is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+# CONFIG_NFS_V4 is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+# CONFIG_NFSD_V4 is not set
+# CONFIG_ROOT_NFS is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+# CONFIG_CIFS_STATS2 is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_SAMPLES is not set
+# CONFIG_DEBUG_USER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+# CONFIG_CRYPTO_CAMELLIA is not set
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+# CONFIG_CRYPTO_SALSA20 is not set
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_GENERIC_FIND_NEXT_BIT is not set
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index eb9092c..1d296fc 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -28,6 +28,7 @@
 obj-$(CONFIG_ATAGS_PROC)	+= atags.o
 obj-$(CONFIG_OABI_COMPAT)	+= sys_oabi-compat.o
 obj-$(CONFIG_ARM_THUMBEE)	+= thumbee.o
+obj-$(CONFIG_KGDB)		+= kgdb.o
 
 obj-$(CONFIG_CRUNCH)		+= crunch.o crunch-bits.o
 AFLAGS_crunch-bits.o		:= -Wa,-mcpu=ep9312
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index 8bfd299..f5cfdab 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -783,7 +783,7 @@
 
 #define ec_set_resource(ec,nr,st,sz)				\
 	do {							\
-		(ec)->resource[nr].name = ec->dev.bus_id;	\
+		(ec)->resource[nr].name = dev_name(&ec->dev);	\
 		(ec)->resource[nr].start = st;			\
 		(ec)->resource[nr].end = (st) + (sz) - 1;	\
 		(ec)->resource[nr].flags = IORESOURCE_MEM;	\
@@ -853,8 +853,7 @@
 	for (i = 0; i < ECARD_NUM_RESOURCES; i++) {
 		if (ec->resource[i].flags &&
 		    request_resource(&iomem_resource, &ec->resource[i])) {
-			printk(KERN_ERR "%s: resource(s) not available\n",
-				ec->dev.bus_id);
+			dev_err(&ec->dev, "resource(s) not available\n");
 			ec->resource[i].end -= ec->resource[i].start;
 			ec->resource[i].start = 0;
 			ec->resource[i].flags = 0;
diff --git a/arch/arm/kernel/kgdb.c b/arch/arm/kernel/kgdb.c
new file mode 100644
index 0000000..aaffaec
--- /dev/null
+++ b/arch/arm/kernel/kgdb.c
@@ -0,0 +1,201 @@
+/*
+ * arch/arm/kernel/kgdb.c
+ *
+ * ARM KGDB support
+ *
+ * Copyright (c) 2002-2004 MontaVista Software, Inc
+ * Copyright (c) 2008 Wind River Systems, Inc.
+ *
+ * Authors:  George Davis <davis_g@mvista.com>
+ *           Deepak Saxena <dsaxena@plexity.net>
+ */
+#include <linux/kgdb.h>
+#include <asm/traps.h>
+
+/* Make a local copy of the registers passed into the handler (bletch) */
+void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs)
+{
+	int regno;
+
+	/* Initialize all to zero. */
+	for (regno = 0; regno < GDB_MAX_REGS; regno++)
+		gdb_regs[regno] = 0;
+
+	gdb_regs[_R0]		= kernel_regs->ARM_r0;
+	gdb_regs[_R1]		= kernel_regs->ARM_r1;
+	gdb_regs[_R2]		= kernel_regs->ARM_r2;
+	gdb_regs[_R3]		= kernel_regs->ARM_r3;
+	gdb_regs[_R4]		= kernel_regs->ARM_r4;
+	gdb_regs[_R5]		= kernel_regs->ARM_r5;
+	gdb_regs[_R6]		= kernel_regs->ARM_r6;
+	gdb_regs[_R7]		= kernel_regs->ARM_r7;
+	gdb_regs[_R8]		= kernel_regs->ARM_r8;
+	gdb_regs[_R9]		= kernel_regs->ARM_r9;
+	gdb_regs[_R10]		= kernel_regs->ARM_r10;
+	gdb_regs[_FP]		= kernel_regs->ARM_fp;
+	gdb_regs[_IP]		= kernel_regs->ARM_ip;
+	gdb_regs[_SPT]		= kernel_regs->ARM_sp;
+	gdb_regs[_LR]		= kernel_regs->ARM_lr;
+	gdb_regs[_PC]		= kernel_regs->ARM_pc;
+	gdb_regs[_CPSR]		= kernel_regs->ARM_cpsr;
+}
+
+/* Copy local gdb registers back to kgdb regs, for later copy to kernel */
+void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs)
+{
+	kernel_regs->ARM_r0	= gdb_regs[_R0];
+	kernel_regs->ARM_r1	= gdb_regs[_R1];
+	kernel_regs->ARM_r2	= gdb_regs[_R2];
+	kernel_regs->ARM_r3	= gdb_regs[_R3];
+	kernel_regs->ARM_r4	= gdb_regs[_R4];
+	kernel_regs->ARM_r5	= gdb_regs[_R5];
+	kernel_regs->ARM_r6	= gdb_regs[_R6];
+	kernel_regs->ARM_r7	= gdb_regs[_R7];
+	kernel_regs->ARM_r8	= gdb_regs[_R8];
+	kernel_regs->ARM_r9	= gdb_regs[_R9];
+	kernel_regs->ARM_r10	= gdb_regs[_R10];
+	kernel_regs->ARM_fp	= gdb_regs[_FP];
+	kernel_regs->ARM_ip	= gdb_regs[_IP];
+	kernel_regs->ARM_sp	= gdb_regs[_SPT];
+	kernel_regs->ARM_lr	= gdb_regs[_LR];
+	kernel_regs->ARM_pc	= gdb_regs[_PC];
+	kernel_regs->ARM_cpsr	= gdb_regs[_CPSR];
+}
+
+void
+sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task)
+{
+	struct pt_regs *thread_regs;
+	int regno;
+
+	/* Just making sure... */
+	if (task == NULL)
+		return;
+
+	/* Initialize to zero */
+	for (regno = 0; regno < GDB_MAX_REGS; regno++)
+		gdb_regs[regno] = 0;
+
+	/* Otherwise, we have only some registers from switch_to() */
+	thread_regs		= task_pt_regs(task);
+	gdb_regs[_R0]		= thread_regs->ARM_r0;
+	gdb_regs[_R1]		= thread_regs->ARM_r1;
+	gdb_regs[_R2]		= thread_regs->ARM_r2;
+	gdb_regs[_R3]		= thread_regs->ARM_r3;
+	gdb_regs[_R4]		= thread_regs->ARM_r4;
+	gdb_regs[_R5]		= thread_regs->ARM_r5;
+	gdb_regs[_R6]		= thread_regs->ARM_r6;
+	gdb_regs[_R7]		= thread_regs->ARM_r7;
+	gdb_regs[_R8]		= thread_regs->ARM_r8;
+	gdb_regs[_R9]		= thread_regs->ARM_r9;
+	gdb_regs[_R10]		= thread_regs->ARM_r10;
+	gdb_regs[_FP]		= thread_regs->ARM_fp;
+	gdb_regs[_IP]		= thread_regs->ARM_ip;
+	gdb_regs[_SPT]		= thread_regs->ARM_sp;
+	gdb_regs[_LR]		= thread_regs->ARM_lr;
+	gdb_regs[_PC]		= thread_regs->ARM_pc;
+	gdb_regs[_CPSR]		= thread_regs->ARM_cpsr;
+}
+
+static int compiled_break;
+
+int kgdb_arch_handle_exception(int exception_vector, int signo,
+			       int err_code, char *remcom_in_buffer,
+			       char *remcom_out_buffer,
+			       struct pt_regs *linux_regs)
+{
+	unsigned long addr;
+	char *ptr;
+
+	switch (remcom_in_buffer[0]) {
+	case 'D':
+	case 'k':
+	case 'c':
+		kgdb_contthread = NULL;
+
+		/*
+		 * Try to read optional parameter, pc unchanged if no parm.
+		 * If this was a compiled breakpoint, we need to move
+		 * to the next instruction or we will just breakpoint
+		 * over and over again.
+		 */
+		ptr = &remcom_in_buffer[1];
+		if (kgdb_hex2long(&ptr, &addr))
+			linux_regs->ARM_pc = addr;
+		else if (compiled_break == 1)
+			linux_regs->ARM_pc += 4;
+
+		compiled_break = 0;
+
+		return 0;
+	}
+
+	return -1;
+}
+
+static int kgdb_brk_fn(struct pt_regs *regs, unsigned int instr)
+{
+	kgdb_handle_exception(1, SIGTRAP, 0, regs);
+
+	return 0;
+}
+
+static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int instr)
+{
+	compiled_break = 1;
+	kgdb_handle_exception(1, SIGTRAP, 0, regs);
+
+	return 0;
+}
+
+static struct undef_hook kgdb_brkpt_hook = {
+	.instr_mask		= 0xffffffff,
+	.instr_val		= KGDB_BREAKINST,
+	.fn			= kgdb_brk_fn
+};
+
+static struct undef_hook kgdb_compiled_brkpt_hook = {
+	.instr_mask		= 0xffffffff,
+	.instr_val		= KGDB_COMPILED_BREAK,
+	.fn			= kgdb_compiled_brk_fn
+};
+
+/**
+ *	kgdb_arch_init - Perform any architecture specific initalization.
+ *
+ *	This function will handle the initalization of any architecture
+ *	specific callbacks.
+ */
+int kgdb_arch_init(void)
+{
+	register_undef_hook(&kgdb_brkpt_hook);
+	register_undef_hook(&kgdb_compiled_brkpt_hook);
+
+	return 0;
+}
+
+/**
+ *	kgdb_arch_exit - Perform any architecture specific uninitalization.
+ *
+ *	This function will handle the uninitalization of any architecture
+ *	specific callbacks, for dynamic registration and unregistration.
+ */
+void kgdb_arch_exit(void)
+{
+	unregister_undef_hook(&kgdb_brkpt_hook);
+	unregister_undef_hook(&kgdb_compiled_brkpt_hook);
+}
+
+/*
+ * Register our undef instruction hooks with ARM undef core.
+ * We regsiter a hook specifically looking for the KGB break inst
+ * and we handle the normal undef case within the do_undefinstr
+ * handler.
+ */
+struct kgdb_arch arch_kgdb_ops = {
+#ifndef __ARMEB__
+	.gdb_bpt_instr		= {0xfe, 0xde, 0xff, 0xe7}
+#else /* ! __ARMEB__ */
+	.gdb_bpt_instr		= {0xe7, 0xff, 0xde, 0xfe}
+#endif
+};
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index b7b0720..38f0e79 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -36,6 +36,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
+#include <asm/traps.h>
 
 #include "compat.h"
 #include "atags.h"
@@ -853,6 +854,7 @@
 	conswitchp = &dummy_con;
 #endif
 #endif
+	early_trap_init();
 }
 
 
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index cc5145b..368d171 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -130,7 +130,9 @@
 	{ "red",   led_red_on,   led_red_off   },
 };
 
-static ssize_t leds_store(struct sys_device *dev, const char *buf, size_t size)
+static ssize_t leds_store(struct sys_device *dev,
+			struct sysdev_attribute *attr,
+			const char *buf, size_t size)
 {
 	int ret = -EINVAL, len = strcspn(buf, " ");
 
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 5595fdd..7277aef 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -708,6 +708,11 @@
 
 void __init trap_init(void)
 {
+	return;
+}
+
+void __init early_trap_init(void)
+{
 	unsigned long vectors = CONFIG_VECTORS_BASE;
 	extern char __stubs_start[], __stubs_end[];
 	extern char __vectors_start[], __vectors_end[];
diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c
index 62e653a..5a1588c 100644
--- a/arch/arm/mach-integrator/impd1.c
+++ b/arch/arm/mach-integrator/impd1.c
@@ -393,9 +393,7 @@
 		if (!d)
 			continue;
 
-		snprintf(d->dev.bus_id, sizeof(d->dev.bus_id),
-			 "lm%x:%5.5lx", dev->id, idev->offset >> 12);
-
+		dev_set_name(&d->dev, "lm%x:%5.5lx", dev->id, idev->offset >> 12);
 		d->dev.parent	= &dev->dev;
 		d->res.start	= dev->resource.start + idev->offset;
 		d->res.end	= d->res.start + SZ_4K - 1;
@@ -407,8 +405,7 @@
 
 		ret = amba_device_register(d, &dev->resource);
 		if (ret) {
-			printk("unable to register device %s: %d\n",
-				d->dev.bus_id, ret);
+			dev_err(&d->dev, "unable to register device: %d\n");
 			kfree(d);
 		}
 	}
diff --git a/arch/arm/mach-integrator/lm.c b/arch/arm/mach-integrator/lm.c
index 622cdc4..f939c50 100644
--- a/arch/arm/mach-integrator/lm.c
+++ b/arch/arm/mach-integrator/lm.c
@@ -81,8 +81,10 @@
 	dev->dev.release = lm_device_release;
 	dev->dev.bus = &lm_bustype;
 
-	snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id), "lm%d", dev->id);
-	dev->resource.name = dev->dev.bus_id;
+	ret = dev_set_name(&dev->dev, "lm%d", dev->id);
+	if (ret)
+		return ret;
+	dev->resource.name = dev_name(&dev->dev);
 
 	ret = request_resource(&iomem_resource, &dev->resource);
 	if (ret == 0) {
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 914bb33..e8ee7ec 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -16,18 +16,24 @@
 config CPU_PXA320
 	bool "PXA320 (codename Monahans-P)"
 
+config CPU_PXA930
+	bool "PXA930 (codename Tavor-P)"
+
 endmenu
 
 endif
 
-menu "Select target boards"
-
 config ARCH_GUMSTIX
 	bool "Gumstix XScale boards"
 	help
 	  Say Y here if you intend to run this kernel on a
 	  Gumstix Full Function Minature Computer.
 
+config MACH_GUMSTIX_F
+	bool "Basix, Connex, ws-200ax, ws-400ax systems"
+	depends on ARCH_GUMSTIX
+	select PXA25x
+
 config ARCH_LUBBOCK
 	bool "Intel DBPXA250 Development Platform"
 	select PXA25x
@@ -58,146 +64,6 @@
 	  SL-C3000 (Spitz), SL-C3100 (Borzoi) or SL-C6000x (Tosa)
 	  handheld computer.
 
-config ARCH_PXA_ESERIES
-	bool "PXA based Toshiba e-series PDAs"
-	select PXA25x
-
-config MACH_E330
-	bool "Toshiba e330"
-	default y
-	depends on ARCH_PXA_ESERIES
-	help
-	  Say Y here if you intend to run this kernel on a Toshiba
-	  e330 family PDA.
-
-config MACH_E740
-	bool "Toshiba e740"
-	default y
-	depends on ARCH_PXA_ESERIES
-	help
-	  Say Y here if you intend to run this kernel on a Toshiba
-	  e740 family PDA.
-
-config MACH_E750
-	bool "Toshiba e750"
-	default y
-	depends on ARCH_PXA_ESERIES
-	help
-	  Say Y here if you intend to run this kernel on a Toshiba
-	  e750 family PDA.
-
-config MACH_E400
-	bool "Toshiba e400"
-	default y
-	depends on ARCH_PXA_ESERIES
-	help
-	  Say Y here if you intend to run this kernel on a Toshiba
-	  e400 family PDA.
-
-config MACH_E800
-	bool "Toshiba e800"
-	default y
-	depends on ARCH_PXA_ESERIES
-	help
-	  Say Y here if you intend to run this kernel on a Toshiba
-	  e800 family PDA.
-
-config MACH_TRIZEPS4
-	bool "Keith und Koep Trizeps4 DIMM-Module"
-	select PXA27x
-
-config MACH_EM_X270
-	bool "CompuLab EM-x270 platform"
-	select PXA27x
-
-config MACH_COLIBRI
-	bool "Toradex Colibri PX27x"
-	select PXA27x
-
-config MACH_ZYLONITE
-	bool "PXA3xx Development Platform"
-	select PXA3xx
-	select HAVE_PWM
-
-config MACH_LITTLETON
-	bool "PXA3xx Form Factor Platform (aka Littleton)"
-	select PXA3xx
-	select PXA_SSP
-
-config MACH_ARMCORE
-	bool "CompuLab CM-X270 modules"
-	select PXA27x
-	select IWMMXT
-
-config MACH_MAGICIAN
-	bool "Enable HTC Magician Support"
-	depends on ARCH_PXA
-	select PXA27x
-	select IWMMXT
-
-config MACH_PCM027
-	bool "Phytec phyCORE-PXA270 CPU module (PCM-027)"
-	select PXA27x
-	select IWMMXT
-
-endmenu
-
-choice
-	prompt "Used baseboard"
-	depends on MACH_PCM027
-
-config MACH_PCM990_BASEBOARD
-	bool "PHYTEC PCM-990 development board"
-	select HAVE_PWM
-
-endchoice
-
-choice
-	prompt "display on pcm990"
-	depends on MACH_PCM990_BASEBOARD
-
-config PCM990_DISPLAY_SHARP
-	bool "sharp lq084v1dg21 stn display"
-
-config PCM990_DISPLAY_NEC
-	bool "nec nl6448bc20_18d tft display"
-
-config PCM990_DISPLAY_NONE
-	bool "no display"
-
-endchoice
-
-if ARCH_GUMSTIX
-
-choice
-	prompt "Select target Gumstix board"
-
-config MACH_GUMSTIX_F
-	bool "Basix, Connex, ws-200ax, ws-400ax systems"
-	select PXA25x
-
-endchoice
-
-endif
-
-
-if MACH_TRIZEPS4
-
-choice
-	prompt "Select base board for Trizeps 4 module"
-
-config MACH_TRIZEPS4_CONXS
-	bool "ConXS Eval Board"
-
-config MACH_TRIZEPS4_ANY
-	bool "another Board"
-
-endchoice
-
-endif
-
-endmenu
-
 config MACH_POODLE
 	bool "Enable Sharp SL-5600 (Poodle) Support"
 	depends on PXA_SHARPSL
@@ -249,6 +115,186 @@
 	depends on PXA_SHARPSL
 	select PXA25x
 
+config ARCH_PXA_ESERIES
+	bool "PXA based Toshiba e-series PDAs"
+	select PXA25x
+
+config MACH_E330
+	bool "Toshiba e330"
+	default y
+	depends on ARCH_PXA_ESERIES
+	help
+	  Say Y here if you intend to run this kernel on a Toshiba
+	  e330 family PDA.
+
+config MACH_E350
+	bool "Toshiba e350"
+	default y
+	depends on ARCH_PXA_ESERIES
+	help
+	  Say Y here if you intend to run this kernel on a Toshiba
+	  e350 family PDA.
+
+config MACH_E740
+	bool "Toshiba e740"
+	default y
+	depends on ARCH_PXA_ESERIES
+	select FB_W100
+	help
+	  Say Y here if you intend to run this kernel on a Toshiba
+	  e740 family PDA.
+
+config MACH_E750
+	bool "Toshiba e750"
+	default y
+	depends on ARCH_PXA_ESERIES
+	select FB_W100
+	help
+	  Say Y here if you intend to run this kernel on a Toshiba
+	  e750 family PDA.
+
+config MACH_E400
+	bool "Toshiba e400"
+	default y
+	depends on ARCH_PXA_ESERIES
+	help
+	  Say Y here if you intend to run this kernel on a Toshiba
+	  e400 family PDA.
+
+config MACH_E800
+	bool "Toshiba e800"
+	default y
+	depends on ARCH_PXA_ESERIES
+	select FB_W100
+	help
+	  Say Y here if you intend to run this kernel on a Toshiba
+	  e800 family PDA.
+
+config MACH_TRIZEPS4
+	bool "Keith und Koep Trizeps4 DIMM-Module"
+	select PXA27x
+
+config MACH_TRIZEPS4_CONXS
+	bool "ConXS Eval Board"
+	depends on MACH_TRIZEPS4
+
+config MACH_EM_X270
+	bool "CompuLab EM-x270 platform"
+	select PXA27x
+
+config MACH_COLIBRI
+	bool "Toradex Colibri PX27x"
+	select PXA27x
+
+config MACH_ZYLONITE
+	bool "PXA3xx Development Platform (aka Zylonite)"
+	select PXA3xx
+	select HAVE_PWM
+
+config MACH_LITTLETON
+	bool "PXA3xx Form Factor Platform (aka Littleton)"
+	select PXA3xx
+	select PXA_SSP
+
+config MACH_TAVOREVB
+	bool "PXA930 Evaluation Board (aka TavorEVB)"
+	select PXA3xx
+	select PXA930
+
+config MACH_SAAR
+	bool "PXA930 Handheld Platform (aka SAAR)"
+	select PXA3xx
+	select PXA930
+
+config MACH_ARMCORE
+	bool "CompuLab CM-X270 modules"
+	select PXA27x
+	select IWMMXT
+
+config MACH_MAGICIAN
+	bool "Enable HTC Magician Support"
+	select PXA27x
+	select IWMMXT
+
+config MACH_PCM027
+	bool "Phytec phyCORE-PXA270 CPU module (PCM-027)"
+	select PXA27x
+	select IWMMXT
+	select PXA_SSP
+
+config ARCH_PXA_PALM
+	bool "PXA based Palm PDAs"
+	select HAVE_PWM
+
+config MACH_PALMTX
+	bool "Palm T|X"
+	default y
+	depends on ARCH_PXA_PALM
+	select PXA27x
+	select IWMMXT
+	help
+	  Say Y here if you intend to run this kernel on a Palm T|X
+	  handheld computer.
+
+config MACH_PCM990_BASEBOARD
+	bool "PHYTEC PCM-990 development board"
+	select HAVE_PWM
+	depends on MACH_PCM027
+
+choice
+	prompt "display on pcm990"
+	depends on MACH_PCM990_BASEBOARD
+
+config PCM990_DISPLAY_SHARP
+	bool "sharp lq084v1dg21 stn display"
+
+config PCM990_DISPLAY_NEC
+	bool "nec nl6448bc20_18d tft display"
+
+config PCM990_DISPLAY_NONE
+	bool "no display"
+
+endchoice
+
+
+config PXA_EZX
+	bool "Motorola EZX Platform"
+	select PXA27x
+	select IWMMXT
+	select HAVE_PWM
+
+config MACH_EZX_A780
+	bool "Motorola EZX A780"
+	default y
+	depends on PXA_EZX
+
+config MACH_EZX_E680
+	bool "Motorola EZX E680"
+	default y
+	depends on PXA_EZX
+
+config MACH_EZX_A1200
+	bool "Motorola EZX A1200"
+	default y
+	depends on PXA_EZX
+
+config MACH_EZX_A910
+	bool "Motorola EZX A910"
+	default y
+	depends on PXA_EZX
+
+config MACH_EZX_E6
+	bool "Motorola EZX E6"
+	default y
+	depends on PXA_EZX
+
+config MACH_EZX_E2
+	bool "Motorola EZX E2"
+	default y
+	depends on PXA_EZX
+
+endmenu
+
 config PXA25x
 	bool
 	help
@@ -288,4 +334,13 @@
 	default BACKLIGHT_PWM
 	help
 	  Enable support for PXA2xx/PXA3xx PWM controllers
+
+config TOSA_BT
+	tristate "Control the state of built-in bluetooth chip on Sharp SL-6000"
+	depends on MACH_TOSA
+	select RFKILL
+	help
+	  This is a simple driver that is able to control
+	  the state of built in bluetooth chip on tosa.
+
 endif
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index c4dfbe8..99ecbe7 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -4,7 +4,7 @@
 
 # Common support (must be linked before board specific support)
 obj-y				+= clock.o devices.o generic.o irq.o dma.o \
-				   time.o gpio.o
+				   time.o gpio.o reset.o
 obj-$(CONFIG_PM)		+= pm.o sleep.o standby.o
 obj-$(CONFIG_CPU_FREQ)		+= cpu-pxa.o
 
@@ -18,6 +18,7 @@
 obj-$(CONFIG_PXA3xx)		+= mfp-pxa3xx.o pxa3xx.o smemc.o
 obj-$(CONFIG_CPU_PXA300)	+= pxa300.o
 obj-$(CONFIG_CPU_PXA320)	+= pxa320.o
+obj-$(CONFIG_CPU_PXA930)	+= pxa930.o
 
 # Specific board support
 obj-$(CONFIG_ARCH_GUMSTIX)	+= gumstix.o
@@ -36,7 +37,12 @@
 obj-$(CONFIG_MACH_TOSA)		+= tosa.o
 obj-$(CONFIG_MACH_EM_X270)	+= em-x270.o
 obj-$(CONFIG_MACH_MAGICIAN)	+= magician.o
-obj-$(CONFIG_ARCH_PXA_ESERIES)	+= eseries.o
+obj-$(CONFIG_ARCH_PXA_ESERIES)	+= eseries.o eseries_udc.o
+obj-$(CONFIG_MACH_E740)		+= e740_lcd.o
+obj-$(CONFIG_MACH_E750)		+= e750_lcd.o
+obj-$(CONFIG_MACH_E400)		+= e400_lcd.o
+obj-$(CONFIG_MACH_E800)		+= e800_lcd.o
+obj-$(CONFIG_MACH_PALMTX)	+= palmtx.o
 
 ifeq ($(CONFIG_MACH_ZYLONITE),y)
   obj-y				+= zylonite.o
@@ -44,8 +50,11 @@
   obj-$(CONFIG_CPU_PXA320)	+= zylonite_pxa320.o
 endif
 obj-$(CONFIG_MACH_LITTLETON)	+= littleton.o
+obj-$(CONFIG_MACH_TAVOREVB)	+= tavorevb.o
+obj-$(CONFIG_MACH_SAAR)		+= saar.o
 
 obj-$(CONFIG_MACH_ARMCORE)      += cm-x270.o
+obj-$(CONFIG_PXA_EZX)           += ezx.o
 
 # Support for blinky lights
 led-y := leds.o
@@ -59,3 +68,5 @@
 ifeq ($(CONFIG_PCI),y)
 obj-$(CONFIG_MACH_ARMCORE) += cm-x270-pci.o
 endif
+
+obj-$(CONFIG_TOSA_BT)		+= tosa-bt.o
diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c
index b4d0495..630063f 100644
--- a/arch/arm/mach-pxa/clock.c
+++ b/arch/arm/mach-pxa/clock.c
@@ -101,21 +101,6 @@
 EXPORT_SYMBOL(clk_get_rate);
 
 
-static void clk_gpio27_enable(struct clk *clk)
-{
-	pxa_gpio_mode(GPIO11_3_6MHz_MD);
-}
-
-static void clk_gpio27_disable(struct clk *clk)
-{
-}
-
-static const struct clkops clk_gpio27_ops = {
-	.enable		= clk_gpio27_enable,
-	.disable	= clk_gpio27_disable,
-};
-
-
 void clk_cken_enable(struct clk *clk)
 {
 	CKEN |= 1 << clk->cken;
@@ -131,14 +116,6 @@
 	.disable	= clk_cken_disable,
 };
 
-static struct clk common_clks[] = {
-	{
-		.name		= "GPIO27_CLK",
-		.ops		= &clk_gpio27_ops,
-		.rate		= 3686400,
-	},
-};
-
 void clks_register(struct clk *clks, size_t num)
 {
 	int i;
@@ -148,10 +125,3 @@
 		list_add(&clks[i].node, &clocks);
 	mutex_unlock(&clocks_mutex);
 }
-
-static int __init clk_init(void)
-{
-	clks_register(common_clks, ARRAY_SIZE(common_clks));
-	return 0;
-}
-arch_initcall(clk_init);
diff --git a/arch/arm/mach-pxa/clock.h b/arch/arm/mach-pxa/clock.h
index 83cbfab..1ec8f91 100644
--- a/arch/arm/mach-pxa/clock.h
+++ b/arch/arm/mach-pxa/clock.h
@@ -47,9 +47,42 @@
 		.other	= _other,			\
 	}
 
+#define INIT_CLK(_name, _ops, _rate, _delay, _dev)      \
+	{                                               \
+		.name   = _name,                        \
+		.dev    = _dev,                         \
+		.ops    = _ops,                         \
+		.rate   = _rate,                        \
+		.delay	= _delay,			\
+	}
+
 extern const struct clkops clk_cken_ops;
 
 void clk_cken_enable(struct clk *clk);
 void clk_cken_disable(struct clk *clk);
 
+#ifdef CONFIG_PXA3xx
+#define PXA3xx_CKEN(_name, _cken, _rate, _delay, _dev)	\
+	{						\
+		.name	= _name,			\
+		.dev	= _dev,				\
+		.ops	= &clk_pxa3xx_cken_ops,		\
+		.rate	= _rate,			\
+		.cken	= CKEN_##_cken,			\
+		.delay	= _delay,			\
+	}
+
+#define PXA3xx_CK(_name, _cken, _ops, _dev)		\
+	{						\
+		.name	= _name,			\
+		.dev	= _dev,				\
+		.ops	= _ops,				\
+		.cken	= CKEN_##_cken,			\
+	}
+
+extern const struct clkops clk_pxa3xx_cken_ops;
+extern void clk_pxa3xx_cken_enable(struct clk *);
+extern void clk_pxa3xx_cken_disable(struct clk *);
+#endif
+
 void clks_register(struct clk *clks, size_t num);
diff --git a/arch/arm/mach-pxa/cm-x270-pci.c b/arch/arm/mach-pxa/cm-x270-pci.c
index 319c9ff..bcf0cde 100644
--- a/arch/arm/mach-pxa/cm-x270-pci.c
+++ b/arch/arm/mach-pxa/cm-x270-pci.c
@@ -5,7 +5,7 @@
  *
  * Bits taken from various places.
  *
- * Copyright (C) 2007 Compulab, Ltd.
+ * Copyright (C) 2007, 2008 Compulab, Ltd.
  * Mike Rapoport <mike@compulab.co.il>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -19,16 +19,16 @@
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/irq.h>
+#include <linux/gpio.h>
 
 #include <asm/mach/pci.h>
-#include <asm/arch/cm-x270.h>
 #include <asm/arch/pxa-regs.h>
-#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/mach-types.h>
 
 #include <asm/hardware/it8152.h>
 
-unsigned long it8152_base_address = CMX270_IT8152_VIRT;
+unsigned long it8152_base_address;
+static int cmx270_it8152_irq_gpio;
 
 /*
  * Only first 64MB of memory can be accessed via PCI.
@@ -42,7 +42,7 @@
 	unsigned int sz = SZ_64M >> PAGE_SHIFT;
 
 	if (machine_is_armcore()) {
-		pr_info("Adjusting zones for CM-x270\n");
+		pr_info("Adjusting zones for CM-X270\n");
 
 		/*
 		 * Only adjust if > 64M on current system
@@ -60,19 +60,20 @@
 static void cmx270_it8152_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
 	/* clear our parent irq */
-	GEDR(GPIO_IT8152_IRQ) = GPIO_bit(GPIO_IT8152_IRQ);
+	GEDR(cmx270_it8152_irq_gpio) = GPIO_bit(cmx270_it8152_irq_gpio);
 
 	it8152_irq_demux(irq, desc);
 }
 
-void __cmx270_pci_init_irq(void)
+void __cmx270_pci_init_irq(int irq_gpio)
 {
 	it8152_init_irq();
-	pxa_gpio_mode(IRQ_TO_GPIO(GPIO_IT8152_IRQ));
-	set_irq_type(IRQ_GPIO(GPIO_IT8152_IRQ), IRQT_RISING);
 
-	set_irq_chained_handler(IRQ_GPIO(GPIO_IT8152_IRQ),
-				cmx270_it8152_irq_demux);
+	cmx270_it8152_irq_gpio = irq_gpio;
+
+	set_irq_type(gpio_to_irq(irq_gpio), IRQT_RISING);
+
+	set_irq_chained_handler(gpio_to_irq(irq_gpio), cmx270_it8152_irq_demux);
 }
 
 #ifdef CONFIG_PM
@@ -115,8 +116,8 @@
 
 	/*
 	  Here comes the ugly part. The routing is baseboard specific,
-	  but defining a platform for each possible base of CM-x270 is
-	  unrealistic. Here we keep mapping for ATXBase and SB-x270.
+	  but defining a platform for each possible base of CM-X270 is
+	  unrealistic. Here we keep mapping for ATXBase and SB-X270.
 	*/
 	/* ATXBASE PCI slot */
 	if (slot == 7)
diff --git a/arch/arm/mach-pxa/cm-x270-pci.h b/arch/arm/mach-pxa/cm-x270-pci.h
index ffe37b6..48f532f 100644
--- a/arch/arm/mach-pxa/cm-x270-pci.h
+++ b/arch/arm/mach-pxa/cm-x270-pci.h
@@ -1,13 +1,13 @@
-extern void __cmx270_pci_init_irq(void);
+extern void __cmx270_pci_init_irq(int irq_gpio);
 extern void __cmx270_pci_suspend(void);
 extern void __cmx270_pci_resume(void);
 
 #ifdef CONFIG_PCI
-#define cmx270_pci_init_irq __cmx270_pci_init_irq
-#define cmx270_pci_suspend __cmx270_pci_suspend
-#define cmx270_pci_resume __cmx270_pci_resume
+#define cmx270_pci_init_irq(x) __cmx270_pci_init_irq(x)
+#define cmx270_pci_suspend(x) __cmx270_pci_suspend(x)
+#define cmx270_pci_resume(x) __cmx270_pci_resume(x)
 #else
-#define cmx270_pci_init_irq() do {} while (0)
-#define cmx270_pci_suspend() do {} while (0)
-#define cmx270_pci_resume() do {} while (0)
+#define cmx270_pci_init_irq(x) do {} while (0)
+#define cmx270_pci_suspend(x) do {} while (0)
+#define cmx270_pci_resume(x) do {} while (0)
 #endif
diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c
index 01b9964..402e807 100644
--- a/arch/arm/mach-pxa/cm-x270.c
+++ b/arch/arm/mach-pxa/cm-x270.c
@@ -1,7 +1,7 @@
 /*
  * linux/arch/arm/mach-pxa/cm-x270.c
  *
- * Copyright (C) 2007 CompuLab, Ltd.
+ * Copyright (C) 2007, 2008 CompuLab, Ltd.
  * Mike Rapoport <mike@compulab.co.il>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -9,44 +9,156 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/types.h>
-#include <linux/pm.h>
-#include <linux/fb.h>
 #include <linux/platform_device.h>
-#include <linux/irq.h>
 #include <linux/sysdev.h>
-#include <linux/io.h>
-#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
 
 #include <linux/dm9000.h>
 #include <linux/rtc-v3020.h>
-#include <linux/serial_8250.h>
-
 #include <video/mbxfb.h>
+#include <linux/leds.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
 
-#include <asm/arch/pxa-regs.h>
 #include <asm/arch/pxa2xx-regs.h>
-#include <asm/arch/pxa2xx-gpio.h>
+#include <asm/arch/mfp-pxa27x.h>
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/audio.h>
 #include <asm/arch/pxafb.h>
 #include <asm/arch/ohci.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/bitfield.h>
-#include <asm/arch/cm-x270.h>
 
 #include <asm/hardware/it8152.h>
 
 #include "generic.h"
 #include "cm-x270-pci.h"
 
+/* virtual addresses for statically mapped regions */
+#define CMX270_VIRT_BASE	(0xe8000000)
+#define CMX270_IT8152_VIRT	(CMX270_VIRT_BASE)
+
 #define RTC_PHYS_BASE		(PXA_CS1_PHYS + (5 << 22))
 #define DM9000_PHYS_BASE	(PXA_CS1_PHYS + (6 << 22))
 
-static struct resource cmx270_dm9k_resource[] = {
+/* GPIO IRQ usage */
+#define GPIO10_ETHIRQ		(10)
+#define GPIO22_IT8152_IRQ	(22)
+#define GPIO83_MMC_IRQ		(83)
+#define GPIO95_GFXIRQ		(95)
+
+#define CMX270_ETHIRQ		IRQ_GPIO(GPIO10_ETHIRQ)
+#define CMX270_IT8152_IRQ	IRQ_GPIO(GPIO22_IT8152_IRQ)
+#define CMX270_MMC_IRQ		IRQ_GPIO(GPIO83_MMC_IRQ)
+#define CMX270_GFXIRQ		IRQ_GPIO(GPIO95_GFXIRQ)
+
+/* MMC power enable */
+#define GPIO105_MMC_POWER	(105)
+
+static unsigned long cmx270_pin_config[] = {
+	/* AC'97 */
+	GPIO28_AC97_BITCLK,
+	GPIO29_AC97_SDATA_IN_0,
+	GPIO30_AC97_SDATA_OUT,
+	GPIO31_AC97_SYNC,
+	GPIO98_AC97_SYSCLK,
+	GPIO113_AC97_nRESET,
+
+	/* BTUART */
+	GPIO42_BTUART_RXD,
+	GPIO43_BTUART_TXD,
+	GPIO44_BTUART_CTS,
+	GPIO45_BTUART_RTS,
+
+	/* STUART */
+	GPIO46_STUART_RXD,
+	GPIO47_STUART_TXD,
+
+	/* MCI controller */
+	GPIO32_MMC_CLK,
+	GPIO112_MMC_CMD,
+	GPIO92_MMC_DAT_0,
+	GPIO109_MMC_DAT_1,
+	GPIO110_MMC_DAT_2,
+	GPIO111_MMC_DAT_3,
+
+	/* LCD */
+	GPIO58_LCD_LDD_0,
+	GPIO59_LCD_LDD_1,
+	GPIO60_LCD_LDD_2,
+	GPIO61_LCD_LDD_3,
+	GPIO62_LCD_LDD_4,
+	GPIO63_LCD_LDD_5,
+	GPIO64_LCD_LDD_6,
+	GPIO65_LCD_LDD_7,
+	GPIO66_LCD_LDD_8,
+	GPIO67_LCD_LDD_9,
+	GPIO68_LCD_LDD_10,
+	GPIO69_LCD_LDD_11,
+	GPIO70_LCD_LDD_12,
+	GPIO71_LCD_LDD_13,
+	GPIO72_LCD_LDD_14,
+	GPIO73_LCD_LDD_15,
+	GPIO74_LCD_FCLK,
+	GPIO75_LCD_LCLK,
+	GPIO76_LCD_PCLK,
+	GPIO77_LCD_BIAS,
+
+	/* I2C */
+	GPIO117_I2C_SCL,
+	GPIO118_I2C_SDA,
+
+	/* SSP1 */
+	GPIO23_SSP1_SCLK,
+	GPIO24_SSP1_SFRM,
+	GPIO25_SSP1_TXD,
+	GPIO26_SSP1_RXD,
+
+	/* SSP2 */
+	GPIO19_SSP2_SCLK,
+	GPIO14_SSP2_SFRM,
+	GPIO87_SSP2_TXD,
+	GPIO88_SSP2_RXD,
+
+	/* PC Card */
+	GPIO48_nPOE,
+	GPIO49_nPWE,
+	GPIO50_nPIOR,
+	GPIO51_nPIOW,
+	GPIO85_nPCE_1,
+	GPIO54_nPCE_2,
+	GPIO55_nPREG,
+	GPIO56_nPWAIT,
+	GPIO57_nIOIS16,
+
+	/* SDRAM and local bus */
+	GPIO15_nCS_1,
+	GPIO78_nCS_2,
+	GPIO79_nCS_3,
+	GPIO80_nCS_4,
+	GPIO33_nCS_5,
+	GPIO49_nPWE,
+	GPIO18_RDY,
+
+	/* GPIO */
+	GPIO0_GPIO	| WAKEUP_ON_EDGE_BOTH,
+	GPIO105_GPIO	| MFP_LPM_DRIVE_HIGH,	/* MMC/SD power */
+	GPIO53_GPIO,				/* PC card reset */
+
+	/* NAND controls */
+	GPIO11_GPIO	| MFP_LPM_DRIVE_HIGH,	/* NAND CE# */
+	GPIO89_GPIO,				/* NAND Ready/Busy */
+
+	/* interrupts */
+	GPIO10_GPIO,	/* DM9000 interrupt */
+	GPIO83_GPIO,	/* MMC card detect */
+};
+
+#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
+static struct resource cmx270_dm9000_resource[] = {
 	[0] = {
 		.start = DM9000_PHYS_BASE,
 		.end   = DM9000_PHYS_BASE + 4,
@@ -64,31 +176,45 @@
 	}
 };
 
-/* for the moment we limit ourselves to 32bit IO until some
- * better IO routines can be written and tested
- */
-static struct dm9000_plat_data cmx270_dm9k_platdata = {
+static struct dm9000_plat_data cmx270_dm9000_platdata = {
 	.flags		= DM9000_PLATF_32BITONLY,
 };
 
-/* Ethernet device */
-static struct platform_device cmx270_device_dm9k = {
+static struct platform_device cmx270_dm9000_device = {
 	.name		= "dm9000",
 	.id		= 0,
-	.num_resources	= ARRAY_SIZE(cmx270_dm9k_resource),
-	.resource	= cmx270_dm9k_resource,
+	.num_resources	= ARRAY_SIZE(cmx270_dm9000_resource),
+	.resource	= cmx270_dm9000_resource,
 	.dev		= {
-		.platform_data = &cmx270_dm9k_platdata,
+		.platform_data = &cmx270_dm9000_platdata,
 	}
 };
 
-/* touchscreen controller */
+static void __init cmx270_init_dm9000(void)
+{
+	platform_device_register(&cmx270_dm9000_device);
+}
+#else
+static inline void cmx270_init_dm9000(void) {}
+#endif
+
+/* UCB1400 touchscreen controller */
+#if defined(CONFIG_TOUCHSCREEN_UCB1400) || defined(CONFIG_TOUCHSCREEN_UCB1400_MODULE)
 static struct platform_device cmx270_ts_device = {
 	.name		= "ucb1400_ts",
 	.id		= -1,
 };
 
-/* RTC */
+static void __init cmx270_init_touchscreen(void)
+{
+	platform_device_register(&cmx270_ts_device);
+}
+#else
+static inline void cmx270_init_touchscreen(void) {}
+#endif
+
+/* V3020 RTC */
+#if defined(CONFIG_RTC_DRV_V3020) || defined(CONFIG_RTC_DRV_V3020_MODULE)
 static struct resource cmx270_v3020_resource[] = {
 	[0] = {
 		.start = RTC_PHYS_BASE,
@@ -111,28 +237,67 @@
 	}
 };
 
-/*
- * CM-X270 LEDs
- */
-static struct platform_device cmx270_led_device = {
-	.name		= "cm-x270-led",
-	.id		= -1,
+static void __init cmx270_init_rtc(void)
+{
+	platform_device_register(&cmx270_rtc_device);
+}
+#else
+static inline void cmx270_init_rtc(void) {}
+#endif
+
+/* CM-X270 LEDs */
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+static struct gpio_led cmx270_leds[] = {
+	[0] = {
+		.name = "cm-x270:red",
+		.default_trigger = "nand-disk",
+		.gpio = 93,
+		.active_low = 1,
+	},
+	[1] = {
+		.name = "cm-x270:green",
+		.default_trigger = "heartbeat",
+		.gpio = 94,
+		.active_low = 1,
+	},
 };
 
+static struct gpio_led_platform_data cmx270_gpio_led_pdata = {
+	.num_leds = ARRAY_SIZE(cmx270_leds),
+	.leds = cmx270_leds,
+};
+
+static struct platform_device cmx270_led_device = {
+	.name		= "leds-gpio",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &cmx270_gpio_led_pdata,
+	},
+};
+
+static void __init cmx270_init_leds(void)
+{
+	platform_device_register(&cmx270_led_device);
+}
+#else
+static inline void cmx270_init_leds(void) {}
+#endif
+
 /* 2700G graphics */
+#if defined(CONFIG_FB_MBX) || defined(CONFIG_FB_MBX_MODULE)
 static u64 fb_dma_mask = ~(u64)0;
 
 static struct resource cmx270_2700G_resource[] = {
 	/* frame buffer memory including ODFB and External SDRAM */
 	[0] = {
-		.start = MARATHON_PHYS,
-		.end   = MARATHON_PHYS + 0x02000000,
+		.start = PXA_CS2_PHYS,
+		.end   = PXA_CS2_PHYS + 0x01ffffff,
 		.flags = IORESOURCE_MEM,
 	},
 	/* Marathon registers */
 	[1] = {
-		.start = MARATHON_PHYS + 0x03fe0000,
-		.end   = MARATHON_PHYS + 0x03ffffff,
+		.start = PXA_CS2_PHYS + 0x03fe0000,
+		.end   = PXA_CS2_PHYS + 0x03ffffff,
 		.flags = IORESOURCE_MEM,
 	},
 };
@@ -200,43 +365,15 @@
 	.id		= -1,
 };
 
-static u64 ata_dma_mask = ~(u64)0;
+static void __init cmx270_init_2700G(void)
+{
+	platform_device_register(&cmx270_2700G);
+}
+#else
+static inline void cmx270_init_2700G(void) {}
+#endif
 
-static struct platform_device cmx270_ata = {
-	.name = "pata_cm_x270",
-	.id = -1,
-	.dev		= {
-		.dma_mask	= &ata_dma_mask,
-		.coherent_dma_mask = 0xffffffff,
-	},
-};
-
-/* platform devices */
-static struct platform_device *platform_devices[] __initdata = {
-	&cmx270_device_dm9k,
-	&cmx270_rtc_device,
-	&cmx270_2700G,
-	&cmx270_led_device,
-	&cmx270_ts_device,
-	&cmx270_ata,
-};
-
-/* Map PCI companion and IDE/General Purpose CS statically */
-static struct map_desc cmx270_io_desc[] __initdata = {
-	[0] = { /* IDE/general purpose space */
-		.virtual	= CMX270_IDE104_VIRT,
-		.pfn		= __phys_to_pfn(CMX270_IDE104_PHYS),
-		.length		= SZ_64M - SZ_8M,
-		.type		= MT_DEVICE
-	},
-	[1] = { /* PCI bridge */
-		.virtual	= CMX270_IT8152_VIRT,
-		.pfn		= __phys_to_pfn(CMX270_IT8152_PHYS),
-		.length		= SZ_64M,
-		.type		= MT_DEVICE
-	},
-};
-
+#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
 /*
   Display definitions
   keep these for backwards compatibility, although symbolic names (as
@@ -446,7 +583,16 @@
 */
 __setup("monitor=", cmx270_set_display);
 
+static void __init cmx270_init_display(void)
+{
+	set_pxa_fb_info(cmx270_display);
+}
+#else
+static inline void cmx270_init_display(void) {}
+#endif
+
 /* PXA27x OHCI controller setup */
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
 static int cmx270_ohci_init(struct device *dev)
 {
 	/* Set the Power Control Polarity Low */
@@ -461,35 +607,37 @@
 	.init		= cmx270_ohci_init,
 };
 
+static void __init cmx270_init_ohci(void)
+{
+	pxa_set_ohci_info(&cmx270_ohci_platform_data);
+}
+#else
+static inline void cmx270_init_ohci(void) {}
+#endif
 
+#if defined(CONFIG_MMC) || defined(CONFIG_MMC_MODULE)
 static int cmx270_mci_init(struct device *dev,
 			   irq_handler_t cmx270_detect_int,
 			   void *data)
 {
 	int err;
 
-	/*
-	 * setup GPIO for PXA27x MMC controller
-	 */
-	pxa_gpio_mode(GPIO32_MMCCLK_MD);
-	pxa_gpio_mode(GPIO112_MMCCMD_MD);
-	pxa_gpio_mode(GPIO92_MMCDAT0_MD);
-	pxa_gpio_mode(GPIO109_MMCDAT1_MD);
-	pxa_gpio_mode(GPIO110_MMCDAT2_MD);
-	pxa_gpio_mode(GPIO111_MMCDAT3_MD);
+	err = gpio_request(GPIO105_MMC_POWER, "MMC/SD power");
+	if (err) {
+		dev_warn(dev, "power gpio unavailable\n");
+		return err;
+	}
 
-	/* SB-X270 uses GPIO105 as SD power enable */
-	pxa_gpio_mode(105 | GPIO_OUT);
-
-	/* card detect IRQ on GPIO 83 */
-	pxa_gpio_mode(IRQ_TO_GPIO(CMX270_MMC_IRQ));
+	gpio_direction_output(GPIO105_MMC_POWER, 0);
 
 	err = request_irq(CMX270_MMC_IRQ, cmx270_detect_int,
 			  IRQF_DISABLED | IRQF_TRIGGER_FALLING,
 			  "MMC card detect", data);
-	if (err)
-		printk(KERN_ERR "cmx270_mci_init: MMC/SD: can't"
-		       " request MMC card detect IRQ\n");
+	if (err) {
+		gpio_free(GPIO105_MMC_POWER);
+		dev_err(dev, "cmx270_mci_init: MMC/SD: can't"
+			" request MMC card detect IRQ\n");
+	}
 
 	return err;
 }
@@ -499,17 +647,18 @@
 	struct pxamci_platform_data *p_d = dev->platform_data;
 
 	if ((1 << vdd) & p_d->ocr_mask) {
-		printk(KERN_DEBUG "%s: on\n", __func__);
-		GPCR(105) = GPIO_bit(105);
+		dev_dbg(dev, "power on\n");
+		gpio_set_value(GPIO105_MMC_POWER, 0);
 	} else {
-		GPSR(105) = GPIO_bit(105);
-		printk(KERN_DEBUG "%s: off\n", __func__);
+		gpio_set_value(GPIO105_MMC_POWER, 1);
+		dev_dbg(dev, "power off\n");
 	}
 }
 
 static void cmx270_mci_exit(struct device *dev, void *data)
 {
 	free_irq(CMX270_MMC_IRQ, data);
+	gpio_free(GPIO105_MMC_POWER);
 }
 
 static struct pxamci_platform_data cmx270_mci_platform_data = {
@@ -519,6 +668,14 @@
 	.exit		= cmx270_mci_exit,
 };
 
+static void __init cmx270_init_mmc(void)
+{
+	pxa_set_mci_info(&cmx270_mci_platform_data);
+}
+#else
+static inline void cmx270_init_mmc(void) {}
+#endif
+
 #ifdef CONFIG_PM
 static unsigned long sleep_save_msc[10];
 
@@ -580,53 +737,63 @@
 static int __init cmx270_pm_init(void) { return 0; }
 #endif
 
+#if defined(CONFIG_SND_PXA2XX_AC97) || defined(CONFIG_SND_PXA2XX_AC97_MODULE)
+static void __init cmx270_init_ac97(void)
+{
+	pxa_set_ac97_info(NULL);
+}
+#else
+static inline void cmx270_init_ac97(void) {}
+#endif
+
 static void __init cmx270_init(void)
 {
 	cmx270_pm_init();
 
-	set_pxa_fb_info(cmx270_display);
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(cmx270_pin_config));
 
-	/* register CM-X270 platform devices */
-	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
-	pxa_set_ac97_info(NULL);
-
-	/* set MCI and OHCI platform parameters */
-	pxa_set_mci_info(&cmx270_mci_platform_data);
-	pxa_set_ohci_info(&cmx270_ohci_platform_data);
-
-	/* This enables the STUART */
-	pxa_gpio_mode(GPIO46_STRXD_MD);
-	pxa_gpio_mode(GPIO47_STTXD_MD);
-
-	/* This enables the BTUART  */
-	pxa_gpio_mode(GPIO42_BTRXD_MD);
-	pxa_gpio_mode(GPIO43_BTTXD_MD);
-	pxa_gpio_mode(GPIO44_BTCTS_MD);
-	pxa_gpio_mode(GPIO45_BTRTS_MD);
+	cmx270_init_dm9000();
+	cmx270_init_rtc();
+	cmx270_init_display();
+	cmx270_init_mmc();
+	cmx270_init_ohci();
+	cmx270_init_ac97();
+	cmx270_init_touchscreen();
+	cmx270_init_leds();
+	cmx270_init_2700G();
 }
 
 static void __init cmx270_init_irq(void)
 {
 	pxa27x_init_irq();
 
-
-	cmx270_pci_init_irq();
-
-	/* Setup interrupt for dm9000 */
-	pxa_gpio_mode(IRQ_TO_GPIO(CMX270_ETHIRQ));
-	set_irq_type(CMX270_ETHIRQ, IRQT_RISING);
-
-	/* Setup interrupt for 2700G */
-	pxa_gpio_mode(IRQ_TO_GPIO(CMX270_GFXIRQ));
-	set_irq_type(CMX270_GFXIRQ, IRQT_FALLING);
+	cmx270_pci_init_irq(GPIO22_IT8152_IRQ);
 }
 
+#ifdef CONFIG_PCI
+/* Map PCI companion statically */
+static struct map_desc cmx270_io_desc[] __initdata = {
+	[0] = { /* PCI bridge */
+		.virtual	= CMX270_IT8152_VIRT,
+		.pfn		= __phys_to_pfn(PXA_CS4_PHYS),
+		.length		= SZ_64M,
+		.type		= MT_DEVICE
+	},
+};
+
 static void __init cmx270_map_io(void)
 {
 	pxa_map_io();
 	iotable_init(cmx270_io_desc, ARRAY_SIZE(cmx270_io_desc));
-}
 
+	it8152_base_address = CMX270_IT8152_VIRT;
+}
+#else
+static void __init cmx270_map_io(void)
+{
+	pxa_map_io();
+}
+#endif
 
 MACHINE_START(ARMCORE, "Compulab CM-x270")
 	.boot_params	= 0xa0000100,
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index b37671b..e58504e 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -465,6 +465,7 @@
 		GPSR(CORGI_GPIO_IR_ON) = GPIO_bit(CORGI_GPIO_IR_ON);
 	else
 		GPCR(CORGI_GPIO_IR_ON) = GPIO_bit(CORGI_GPIO_IR_ON);
+	pxa2xx_transceiver_mode(dev, mode);
 }
 
 static struct pxaficp_platform_data corgi_ficp_platform_data = {
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index a6f2390..84489dc 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -13,8 +13,10 @@
 #include <asm/arch/mfp-pxa27x.h>
 #include <asm/arch/ohci.h>
 #include <asm/arch/pxa27x_keypad.h>
+#include <asm/arch/pxa2xx_spi.h>
 #include <asm/arch/camera.h>
 #include <asm/arch/audio.h>
+#include <asm/arch/pxa3xx_nand.h>
 
 #include "devices.h"
 #include "generic.h"
@@ -830,4 +832,63 @@
 	pxa_register_device(&pxa3xx_device_mci3, info);
 }
 
+static struct resource pxa3xx_resources_nand[] = {
+	[0] = {
+		.start	= 0x43100000,
+		.end	= 0x43100053,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_NAND,
+		.end	= IRQ_NAND,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		/* DRCMR for Data DMA */
+		.start	= 97,
+		.end	= 97,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		/* DRCMR for Command DMA */
+		.start	= 99,
+		.end	= 99,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+static u64 pxa3xx_nand_dma_mask = DMA_BIT_MASK(32);
+
+struct platform_device pxa3xx_device_nand = {
+	.name		= "pxa3xx-nand",
+	.id		= -1,
+	.dev		= {
+		.dma_mask = &pxa3xx_nand_dma_mask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+	.num_resources	= ARRAY_SIZE(pxa3xx_resources_nand),
+	.resource	= pxa3xx_resources_nand,
+};
+
+void __init pxa3xx_set_nand_info(struct pxa3xx_nand_platform_data *info)
+{
+	pxa_register_device(&pxa3xx_device_nand, info);
+}
 #endif /* CONFIG_PXA3xx */
+
+/* pxa2xx-spi platform-device ID equals respective SSP platform-device ID + 1.
+ * See comment in arch/arm/mach-pxa/ssp.c::ssp_probe() */
+void __init pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_master *info)
+{
+	struct platform_device *pd;
+
+	pd = platform_device_alloc("pxa2xx-spi", id);
+	if (pd == NULL) {
+		printk(KERN_ERR "pxa2xx-spi: failed to allocate device id %d\n",
+		       id);
+		return;
+	}
+
+	pd->dev.platform_data = info;
+	platform_device_add(pd);
+}
diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h
index b852eb1..887c738 100644
--- a/arch/arm/mach-pxa/devices.h
+++ b/arch/arm/mach-pxa/devices.h
@@ -31,4 +31,6 @@
 extern struct platform_device pxa27x_device_pwm0;
 extern struct platform_device pxa27x_device_pwm1;
 
+extern struct platform_device pxa3xx_device_nand;
+
 void __init pxa_register_device(struct platform_device *dev, void *data);
diff --git a/arch/arm/mach-pxa/e400_lcd.c b/arch/arm/mach-pxa/e400_lcd.c
new file mode 100644
index 0000000..16c0236
--- /dev/null
+++ b/arch/arm/mach-pxa/e400_lcd.c
@@ -0,0 +1,56 @@
+/*
+ * e400_lcd.c
+ *
+ * (c) 2005 Ian Molton <spyro@f2s.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/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <asm/mach-types.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxafb.h>
+
+static struct pxafb_mode_info e400_pxafb_mode_info = {
+	.pixclock       = 140703,
+	.xres           = 240,
+	.yres           = 320,
+	.bpp            = 16,
+	.hsync_len      = 4,
+	.left_margin    = 28,
+	.right_margin   = 8,
+	.vsync_len      = 3,
+	.upper_margin   = 5,
+	.lower_margin   = 6,
+	.sync           = 0,
+};
+
+static struct pxafb_mach_info e400_pxafb_mach_info = {
+	.modes          = &e400_pxafb_mode_info,
+	.num_modes      = 1,
+	.lccr0          = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+	.lccr3          = 0,
+	.pxafb_backlight_power  = NULL,
+};
+
+static int __init e400_lcd_init(void)
+{
+	if (!machine_is_e400())
+		return -ENODEV;
+
+	set_pxa_fb_info(&e400_pxafb_mach_info);
+	return 0;
+}
+
+module_init(e400_lcd_init);
+
+MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
+MODULE_DESCRIPTION("e400 lcd driver");
+MODULE_LICENSE("GPLv2");
+
diff --git a/arch/arm/mach-pxa/e740_lcd.c b/arch/arm/mach-pxa/e740_lcd.c
new file mode 100644
index 0000000..26bd599
--- /dev/null
+++ b/arch/arm/mach-pxa/e740_lcd.c
@@ -0,0 +1,123 @@
+/* e740_lcd.c
+ *
+ * This file contains the definitions for the LCD timings and functions
+ * to control the LCD power / frontlighting via the w100fb driver.
+ *
+ * (c) 2005 Ian Molton <spyro@f2s.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/module.h>
+#include <linux/device.h>
+#include <linux/fb.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+
+#include <video/w100fb.h>
+
+/*
+**potential** shutdown routine - to be investigated
+devmem2 0x0c010528 w 0xff3fff00
+devmem2 0x0c010190 w 0x7FFF8000
+devmem2 0x0c0101b0 w 0x00FF0000
+devmem2 0x0c01008c w 0x00000000
+devmem2 0x0c010080 w 0x000000bf
+devmem2 0x0c010098 w 0x00000015
+devmem2 0x0c010088 w 0x4b000204
+devmem2 0x0c010098 w 0x0000001d
+*/
+
+static struct w100_gen_regs e740_lcd_regs = {
+	.lcd_format =            0x00008023,
+	.lcdd_cntl1 =            0x0f000000,
+	.lcdd_cntl2 =            0x0003ffff,
+	.genlcd_cntl1 =          0x00ffff03,
+	.genlcd_cntl2 =          0x003c0f03,
+	.genlcd_cntl3 =          0x000143aa,
+};
+
+static struct w100_mode e740_lcd_mode = {
+	.xres            = 240,
+	.yres            = 320,
+	.left_margin     = 20,
+	.right_margin    = 28,
+	.upper_margin    = 9,
+	.lower_margin    = 8,
+	.crtc_ss         = 0x80140013,
+	.crtc_ls         = 0x81150110,
+	.crtc_gs         = 0x80050005,
+	.crtc_vpos_gs    = 0x000a0009,
+	.crtc_rev        = 0x0040010a,
+	.crtc_dclk       = 0xa906000a,
+	.crtc_gclk       = 0x80050108,
+	.crtc_goe        = 0x80050108,
+	.pll_freq        = 57,
+	.pixclk_divider         = 4,
+	.pixclk_divider_rotated = 4,
+	.pixclk_src     = CLK_SRC_XTAL,
+	.sysclk_divider  = 1,
+	.sysclk_src     = CLK_SRC_PLL,
+	.crtc_ps1_active =       0x41060010,
+};
+
+
+static struct w100_gpio_regs e740_w100_gpio_info = {
+	.init_data1 = 0x21002103,
+	.gpio_dir1  = 0xffffdeff,
+	.gpio_oe1   = 0x03c00643,
+	.init_data2 = 0x003f003f,
+	.gpio_dir2  = 0xffffffff,
+	.gpio_oe2   = 0x000000ff,
+};
+
+static struct w100fb_mach_info e740_fb_info = {
+	.modelist   = &e740_lcd_mode,
+	.num_modes  = 1,
+	.regs       = &e740_lcd_regs,
+	.gpio       = &e740_w100_gpio_info,
+	.xtal_freq = 14318000,
+	.xtal_dbl   = 1,
+};
+
+static struct resource e740_fb_resources[] = {
+	[0] = {
+		.start          = 0x0c000000,
+		.end            = 0x0cffffff,
+		.flags          = IORESOURCE_MEM,
+	},
+};
+
+/* ----------------------- device declarations -------------------------- */
+
+
+static struct platform_device e740_fb_device = {
+	.name           = "w100fb",
+	.id             = -1,
+	.dev            = {
+		.platform_data  = &e740_fb_info,
+	},
+	.num_resources  = ARRAY_SIZE(e740_fb_resources),
+	.resource       = e740_fb_resources,
+};
+
+static int e740_lcd_init(void)
+{
+	int ret;
+
+	if (!machine_is_e740())
+		return -ENODEV;
+
+	return platform_device_register(&e740_fb_device);
+}
+
+module_init(e740_lcd_init);
+
+MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
+MODULE_DESCRIPTION("e740 lcd driver");
+MODULE_LICENSE("GPLv2");
diff --git a/arch/arm/mach-pxa/e750_lcd.c b/arch/arm/mach-pxa/e750_lcd.c
new file mode 100644
index 0000000..75edc3b
--- /dev/null
+++ b/arch/arm/mach-pxa/e750_lcd.c
@@ -0,0 +1,109 @@
+/* e750_lcd.c
+ *
+ * This file contains the definitions for the LCD timings and functions
+ * to control the LCD power / frontlighting via the w100fb driver.
+ *
+ * (c) 2005 Ian Molton <spyro@f2s.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/module.h>
+#include <linux/device.h>
+#include <linux/fb.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+
+#include <video/w100fb.h>
+
+static struct w100_gen_regs e750_lcd_regs = {
+	.lcd_format =            0x00008003,
+	.lcdd_cntl1 =            0x00000000,
+	.lcdd_cntl2 =            0x0003ffff,
+	.genlcd_cntl1 =          0x00fff003,
+	.genlcd_cntl2 =          0x003c0f03,
+	.genlcd_cntl3 =          0x000143aa,
+};
+
+static struct w100_mode e750_lcd_mode = {
+	.xres            = 240,
+	.yres            = 320,
+	.left_margin     = 21,
+	.right_margin    = 22,
+	.upper_margin    = 5,
+	.lower_margin    = 4,
+	.crtc_ss         = 0x80150014,
+	.crtc_ls         = 0x8014000d,
+	.crtc_gs         = 0xc1000005,
+	.crtc_vpos_gs    = 0x00020147,
+	.crtc_rev        = 0x0040010a,
+	.crtc_dclk       = 0xa1700030,
+	.crtc_gclk       = 0x80cc0015,
+	.crtc_goe        = 0x80cc0015,
+	.crtc_ps1_active = 0x61060017,
+	.pll_freq        = 57,
+	.pixclk_divider         = 4,
+	.pixclk_divider_rotated = 4,
+	.pixclk_src     = CLK_SRC_XTAL,
+	.sysclk_divider  = 1,
+	.sysclk_src     = CLK_SRC_PLL,
+};
+
+
+static struct w100_gpio_regs e750_w100_gpio_info = {
+	.init_data1 = 0x01192f1b,
+	.gpio_dir1  = 0xd5ffdeff,
+	.gpio_oe1   = 0x000020bf,
+	.init_data2 = 0x010f010f,
+	.gpio_dir2  = 0xffffffff,
+	.gpio_oe2   = 0x000001cf,
+};
+
+static struct w100fb_mach_info e750_fb_info = {
+	.modelist   = &e750_lcd_mode,
+	.num_modes  = 1,
+	.regs       = &e750_lcd_regs,
+	.gpio       = &e750_w100_gpio_info,
+	.xtal_freq  = 14318000,
+	.xtal_dbl   = 1,
+};
+
+static struct resource e750_fb_resources[] = {
+	[0] = {
+		.start          = 0x0c000000,
+		.end            = 0x0cffffff,
+		.flags          = IORESOURCE_MEM,
+	},
+};
+
+/* ----------------------- device declarations -------------------------- */
+
+
+static struct platform_device e750_fb_device = {
+	.name           = "w100fb",
+	.id             = -1,
+	.dev            = {
+		.platform_data  = &e750_fb_info,
+	},
+	.num_resources  = ARRAY_SIZE(e750_fb_resources),
+	.resource       = e750_fb_resources,
+};
+
+static int e750_lcd_init(void)
+{
+	if (!machine_is_e750())
+		return -ENODEV;
+
+	return platform_device_register(&e750_fb_device);
+}
+
+module_init(e750_lcd_init);
+
+MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
+MODULE_DESCRIPTION("e750 lcd driver");
+MODULE_LICENSE("GPLv2");
diff --git a/arch/arm/mach-pxa/e800_lcd.c b/arch/arm/mach-pxa/e800_lcd.c
new file mode 100644
index 0000000..e6aeab0e
--- /dev/null
+++ b/arch/arm/mach-pxa/e800_lcd.c
@@ -0,0 +1,159 @@
+/* e800_lcd.c
+ *
+ * This file contains the definitions for the LCD timings and functions
+ * to control the LCD power / frontlighting via the w100fb driver.
+ *
+ * (c) 2005 Ian Molton <spyro@f2s.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/module.h>
+#include <linux/device.h>
+#include <linux/fb.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+
+#include <video/w100fb.h>
+
+static struct w100_gen_regs e800_lcd_regs = {
+	.lcd_format =            0x00008003,
+	.lcdd_cntl1 =            0x02a00000,
+	.lcdd_cntl2 =            0x0003ffff,
+	.genlcd_cntl1 =          0x000ff2a3,
+	.genlcd_cntl2 =          0x000002a3,
+	.genlcd_cntl3 =          0x000102aa,
+};
+
+static struct w100_mode e800_lcd_mode[2] = {
+	[0] = {
+		.xres            = 480,
+		.yres            = 640,
+		.left_margin     = 52,
+		.right_margin    = 148,
+		.upper_margin    = 2,
+		.lower_margin    = 6,
+		.crtc_ss         = 0x80350034,
+		.crtc_ls         = 0x802b0026,
+		.crtc_gs         = 0x80160016,
+		.crtc_vpos_gs    = 0x00020003,
+		.crtc_rev        = 0x0040001d,
+		.crtc_dclk       = 0xe0000000,
+		.crtc_gclk       = 0x82a50049,
+		.crtc_goe        = 0x80ee001c,
+		.crtc_ps1_active = 0x00000000,
+		.pll_freq        = 128,
+		.pixclk_divider         = 4,
+		.pixclk_divider_rotated = 6,
+		.pixclk_src     = CLK_SRC_PLL,
+		.sysclk_divider  = 0,
+		.sysclk_src     = CLK_SRC_PLL,
+	},
+	[1] = {
+		.xres            = 240,
+		.yres            = 320,
+		.left_margin     = 15,
+		.right_margin    = 88,
+		.upper_margin    = 0,
+		.lower_margin    = 7,
+		.crtc_ss         = 0xd010000f,
+		.crtc_ls         = 0x80070003,
+		.crtc_gs         = 0x80000000,
+		.crtc_vpos_gs    = 0x01460147,
+		.crtc_rev        = 0x00400003,
+		.crtc_dclk       = 0xa1700030,
+		.crtc_gclk       = 0x814b0008,
+		.crtc_goe        = 0x80cc0015,
+		.crtc_ps1_active = 0x00000000,
+		.pll_freq        = 100,
+		.pixclk_divider         = 6, /* Wince uses 14 which gives a 7MHz pclk. */
+		.pixclk_divider_rotated = 6, /* we want a 14MHz one (much nicer to look at) */
+		.pixclk_src     = CLK_SRC_PLL,
+		.sysclk_divider  = 0,
+		.sysclk_src     = CLK_SRC_PLL,
+	}
+};
+
+
+static struct w100_gpio_regs e800_w100_gpio_info = {
+	.init_data1 = 0xc13fc019,
+	.gpio_dir1  = 0x3e40df7f,
+	.gpio_oe1   = 0x003c3000,
+	.init_data2 = 0x00000000,
+	.gpio_dir2  = 0x00000000,
+	.gpio_oe2   = 0x00000000,
+};
+
+static struct w100_mem_info e800_w100_mem_info = {
+	.ext_cntl        = 0x09640011,
+	.sdram_mode_reg  = 0x00600021,
+	.ext_timing_cntl = 0x10001545,
+	.io_cntl         = 0x7ddd7333,
+	.size            = 0x1fffff,
+};
+
+static void e800_tg_change(struct w100fb_par *par)
+{
+	unsigned long tmp;
+
+	tmp = w100fb_gpio_read(W100_GPIO_PORT_A);
+	if (par->mode->xres == 480)
+		tmp |= 0x100;
+	else
+		tmp &= ~0x100;
+	w100fb_gpio_write(W100_GPIO_PORT_A, tmp);
+}
+
+static struct w100_tg_info e800_tg_info = {
+	.change = e800_tg_change,
+};
+
+static struct w100fb_mach_info e800_fb_info = {
+	.modelist   = e800_lcd_mode,
+	.num_modes  = 2,
+	.regs       = &e800_lcd_regs,
+	.gpio       = &e800_w100_gpio_info,
+	.mem        = &e800_w100_mem_info,
+	.tg         = &e800_tg_info,
+	.xtal_freq  = 16000000,
+};
+
+static struct resource e800_fb_resources[] = {
+	[0] = {
+		.start          = 0x0c000000,
+		.end            = 0x0cffffff,
+		.flags          = IORESOURCE_MEM,
+	},
+};
+
+/* ----------------------- device declarations -------------------------- */
+
+
+static struct platform_device e800_fb_device = {
+	.name           = "w100fb",
+	.id             = -1,
+	.dev            = {
+		.platform_data  = &e800_fb_info,
+	},
+	.num_resources  = ARRAY_SIZE(e800_fb_resources),
+	.resource       = e800_fb_resources,
+};
+
+static int e800_lcd_init(void)
+{
+	if (!machine_is_e800())
+		return -ENODEV;
+
+	return platform_device_register(&e800_fb_device);
+}
+
+module_init(e800_lcd_init);
+
+MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
+MODULE_DESCRIPTION("e800 lcd driver");
+MODULE_LICENSE("GPLv2");
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index 1bf6807..e5cc6ca 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -1,7 +1,7 @@
 /*
- * Support for CompuLab EM-x270 platform
+ * Support for CompuLab EM-X270 platform
  *
- * Copyright (C) 2007 CompuLab, Ltd.
+ * Copyright (C) 2007, 2008 CompuLab, Ltd.
  * Author: Mike Rapoport <mike@compulab.co.il>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -14,31 +14,159 @@
 
 #include <linux/dm9000.h>
 #include <linux/rtc-v3020.h>
-
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+#include <linux/gpio.h>
 
 #include <asm/mach-types.h>
-
 #include <asm/mach/arch.h>
 
+#include <asm/arch/mfp-pxa27x.h>
 #include <asm/arch/pxa-regs.h>
-#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/arch/pxa27x-udc.h>
 #include <asm/arch/audio.h>
 #include <asm/arch/pxafb.h>
 #include <asm/arch/ohci.h>
 #include <asm/arch/mmc.h>
-#include <asm/arch/bitfield.h>
+#include <asm/arch/pxa27x_keypad.h>
 
 #include "generic.h"
 
 /* GPIO IRQ usage */
-#define EM_X270_MMC_PD		(105)
-#define EM_X270_ETHIRQ		IRQ_GPIO(41)
-#define EM_X270_MMC_IRQ		IRQ_GPIO(13)
+#define GPIO41_ETHIRQ		(41)
+#define GPIO13_MMC_CD		(13)
+#define EM_X270_ETHIRQ		IRQ_GPIO(GPIO41_ETHIRQ)
+#define EM_X270_MMC_CD		IRQ_GPIO(GPIO13_MMC_CD)
 
-static struct resource em_x270_dm9k_resource[] = {
+/* NAND control GPIOs */
+#define GPIO11_NAND_CS	(11)
+#define GPIO56_NAND_RB	(56)
+
+static unsigned long em_x270_pin_config[] = {
+	/* AC'97 */
+	GPIO28_AC97_BITCLK,
+	GPIO29_AC97_SDATA_IN_0,
+	GPIO30_AC97_SDATA_OUT,
+	GPIO31_AC97_SYNC,
+	GPIO98_AC97_SYSCLK,
+	GPIO113_AC97_nRESET,
+
+	/* BTUART */
+	GPIO42_BTUART_RXD,
+	GPIO43_BTUART_TXD,
+	GPIO44_BTUART_CTS,
+	GPIO45_BTUART_RTS,
+
+	/* STUART */
+	GPIO46_STUART_RXD,
+	GPIO47_STUART_TXD,
+
+	/* MCI controller */
+	GPIO32_MMC_CLK,
+	GPIO112_MMC_CMD,
+	GPIO92_MMC_DAT_0,
+	GPIO109_MMC_DAT_1,
+	GPIO110_MMC_DAT_2,
+	GPIO111_MMC_DAT_3,
+
+	/* LCD */
+	GPIO58_LCD_LDD_0,
+	GPIO59_LCD_LDD_1,
+	GPIO60_LCD_LDD_2,
+	GPIO61_LCD_LDD_3,
+	GPIO62_LCD_LDD_4,
+	GPIO63_LCD_LDD_5,
+	GPIO64_LCD_LDD_6,
+	GPIO65_LCD_LDD_7,
+	GPIO66_LCD_LDD_8,
+	GPIO67_LCD_LDD_9,
+	GPIO68_LCD_LDD_10,
+	GPIO69_LCD_LDD_11,
+	GPIO70_LCD_LDD_12,
+	GPIO71_LCD_LDD_13,
+	GPIO72_LCD_LDD_14,
+	GPIO73_LCD_LDD_15,
+	GPIO74_LCD_FCLK,
+	GPIO75_LCD_LCLK,
+	GPIO76_LCD_PCLK,
+	GPIO77_LCD_BIAS,
+
+	/* QCI */
+	GPIO84_CIF_FV,
+	GPIO25_CIF_LV,
+	GPIO53_CIF_MCLK,
+	GPIO54_CIF_PCLK,
+	GPIO81_CIF_DD_0,
+	GPIO55_CIF_DD_1,
+	GPIO51_CIF_DD_2,
+	GPIO50_CIF_DD_3,
+	GPIO52_CIF_DD_4,
+	GPIO48_CIF_DD_5,
+	GPIO17_CIF_DD_6,
+	GPIO12_CIF_DD_7,
+
+	/* I2C */
+	GPIO117_I2C_SCL,
+	GPIO118_I2C_SDA,
+
+	/* Keypad */
+	GPIO100_KP_MKIN_0	| WAKEUP_ON_LEVEL_HIGH,
+	GPIO101_KP_MKIN_1	| WAKEUP_ON_LEVEL_HIGH,
+	GPIO102_KP_MKIN_2	| WAKEUP_ON_LEVEL_HIGH,
+	GPIO34_KP_MKIN_3	| WAKEUP_ON_LEVEL_HIGH,
+	GPIO39_KP_MKIN_4	| WAKEUP_ON_LEVEL_HIGH,
+	GPIO99_KP_MKIN_5	| WAKEUP_ON_LEVEL_HIGH,
+	GPIO91_KP_MKIN_6	| WAKEUP_ON_LEVEL_HIGH,
+	GPIO36_KP_MKIN_7	| WAKEUP_ON_LEVEL_HIGH,
+	GPIO103_KP_MKOUT_0,
+	GPIO104_KP_MKOUT_1,
+	GPIO105_KP_MKOUT_2,
+	GPIO106_KP_MKOUT_3,
+	GPIO107_KP_MKOUT_4,
+	GPIO108_KP_MKOUT_5,
+	GPIO96_KP_MKOUT_6,
+	GPIO22_KP_MKOUT_7,
+
+	/* SSP1 */
+	GPIO26_SSP1_RXD,
+	GPIO23_SSP1_SCLK,
+	GPIO24_SSP1_SFRM,
+	GPIO57_SSP1_TXD,
+
+	/* SSP2 */
+	GPIO19_SSP2_SCLK,
+	GPIO14_SSP2_SFRM,
+	GPIO89_SSP2_TXD,
+	GPIO88_SSP2_RXD,
+
+	/* SDRAM and local bus */
+	GPIO15_nCS_1,
+	GPIO78_nCS_2,
+	GPIO79_nCS_3,
+	GPIO80_nCS_4,
+	GPIO49_nPWE,
+	GPIO18_RDY,
+
+	/* GPIO */
+	GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH,
+
+	/* power controls */
+	GPIO20_GPIO	| MFP_LPM_DRIVE_LOW,	/* GPRS_PWEN */
+	GPIO115_GPIO	| MFP_LPM_DRIVE_LOW,	/* WLAN_PWEN */
+
+	/* NAND controls */
+	GPIO11_GPIO	| MFP_LPM_DRIVE_HIGH,	/* NAND CE# */
+	GPIO56_GPIO,				/* NAND Ready/Busy */
+
+	/* interrupts */
+	GPIO13_GPIO,	/* MMC card detect */
+	GPIO41_GPIO,	/* DM9000 interrupt */
+};
+
+#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
+static struct resource em_x270_dm9000_resource[] = {
 	[0] = {
 		.start = PXA_CS2_PHYS,
 		.end   = PXA_CS2_PHYS + 3,
@@ -56,32 +184,30 @@
 	}
 };
 
-/* for the moment we limit ourselves to 32bit IO until some
- * better IO routines can be written and tested
- */
-static struct dm9000_plat_data em_x270_dm9k_platdata = {
+static struct dm9000_plat_data em_x270_dm9000_platdata = {
 	.flags		= DM9000_PLATF_32BITONLY,
 };
 
-/* Ethernet device */
-static struct platform_device em_x270_dm9k = {
+static struct platform_device em_x270_dm9000 = {
 	.name		= "dm9000",
 	.id		= 0,
-	.num_resources	= ARRAY_SIZE(em_x270_dm9k_resource),
-	.resource	= em_x270_dm9k_resource,
+	.num_resources	= ARRAY_SIZE(em_x270_dm9000_resource),
+	.resource	= em_x270_dm9000_resource,
 	.dev		= {
-		.platform_data = &em_x270_dm9k_platdata,
+		.platform_data = &em_x270_dm9000_platdata,
 	}
 };
 
-/* WM9712 touchscreen controller. Hopefully the driver will make it to
- * the mainstream sometime */
-static struct platform_device em_x270_ts = {
-	.name		= "wm97xx-ts",
-	.id		= -1,
-};
+static void __init em_x270_init_dm9000(void)
+{
+	platform_device_register(&em_x270_dm9000);
+}
+#else
+static inline void em_x270_init_dm9000(void) {}
+#endif
 
-/* RTC */
+/* V3020 RTC */
+#if defined(CONFIG_RTC_DRV_V3020) || defined(CONFIG_RTC_DRV_V3020_MODULE)
 static struct resource em_x270_v3020_resource[] = {
 	[0] = {
 		.start = PXA_CS4_PHYS,
@@ -104,20 +230,26 @@
 	}
 };
 
-/* NAND flash */
-#define GPIO_NAND_CS	(11)
-#define GPIO_NAND_RB	(56)
+static void __init em_x270_init_rtc(void)
+{
+	platform_device_register(&em_x270_rtc);
+}
+#else
+static inline void em_x270_init_rtc(void) {}
+#endif
 
+/* NAND flash */
+#if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
 static inline void nand_cs_on(void)
 {
-	GPCR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS);
+	gpio_set_value(GPIO11_NAND_CS, 0);
 }
 
 static void nand_cs_off(void)
 {
 	dsb();
 
-	GPSR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS);
+	gpio_set_value(GPIO11_NAND_CS, 1);
 }
 
 /* hardware specific access to control-lines */
@@ -157,7 +289,7 @@
 {
 	dsb();
 
-	return GPLR(GPIO_NAND_RB) & GPIO_bit(GPIO_NAND_RB);
+	return gpio_get_value(GPIO56_NAND_RB);
 }
 
 static struct mtd_partition em_x270_partition_info[] = {
@@ -210,16 +342,35 @@
 	}
 };
 
-/* platform devices */
-static struct platform_device *platform_devices[] __initdata = {
-	&em_x270_dm9k,
-	&em_x270_ts,
-	&em_x270_rtc,
-	&em_x270_nand,
-};
+static void __init em_x270_init_nand(void)
+{
+	int err;
 
+	err = gpio_request(GPIO11_NAND_CS, "NAND CS");
+	if (err) {
+		pr_warning("EM-X270: failed to request NAND CS gpio\n");
+		return;
+	}
+
+	gpio_direction_output(GPIO11_NAND_CS, 1);
+
+	err = gpio_request(GPIO56_NAND_RB, "NAND R/B");
+	if (err) {
+		pr_warning("EM-X270: failed to request NAND R/B gpio\n");
+		gpio_free(GPIO11_NAND_CS);
+		return;
+	}
+
+	gpio_direction_input(GPIO56_NAND_RB);
+
+	platform_device_register(&em_x270_nand);
+}
+#else
+static inline void em_x270_init_nand(void) {}
+#endif
 
 /* PXA27x OHCI controller setup */
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
 static int em_x270_ohci_init(struct device *dev)
 {
 	/* Set the Power Control Polarity Low */
@@ -237,27 +388,23 @@
 	.init		= em_x270_ohci_init,
 };
 
+static void __init em_x270_init_ohci(void)
+{
+	pxa_set_ohci_info(&em_x270_ohci_platform_data);
+}
+#else
+static inline void em_x270_init_ohci(void) {}
+#endif
 
+/* MCI controller setup */
+#if defined(CONFIG_MMC) || defined(CONFIG_MMC_MODULE)
 static int em_x270_mci_init(struct device *dev,
 			    irq_handler_t em_x270_detect_int,
 			    void *data)
 {
-	int err;
-
-	/* setup GPIO for PXA27x MMC controller */
-	pxa_gpio_mode(GPIO32_MMCCLK_MD);
-	pxa_gpio_mode(GPIO112_MMCCMD_MD);
-	pxa_gpio_mode(GPIO92_MMCDAT0_MD);
-	pxa_gpio_mode(GPIO109_MMCDAT1_MD);
-	pxa_gpio_mode(GPIO110_MMCDAT2_MD);
-	pxa_gpio_mode(GPIO111_MMCDAT3_MD);
-
-	/* EM-X270 uses GPIO13 as SD power enable */
-	pxa_gpio_mode(EM_X270_MMC_PD | GPIO_OUT);
-
-	err = request_irq(EM_X270_MMC_IRQ, em_x270_detect_int,
-			  IRQF_DISABLED | IRQF_TRIGGER_FALLING,
-			  "MMC card detect", data);
+	int err = request_irq(EM_X270_MMC_CD, em_x270_detect_int,
+			      IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+			      "MMC card detect", data);
 	if (err) {
 		printk(KERN_ERR "%s: can't request MMC card detect IRQ: %d\n",
 		       __func__, err);
@@ -279,7 +426,8 @@
 
 static void em_x270_mci_exit(struct device *dev, void *data)
 {
-	free_irq(EM_X270_MMC_IRQ, data);
+	int irq = gpio_to_irq(GPIO13_MMC_CD);
+	free_irq(irq, data);
 }
 
 static struct pxamci_platform_data em_x270_mci_platform_data = {
@@ -289,7 +437,16 @@
 	.exit		= em_x270_mci_exit,
 };
 
+static void __init em_x270_init_mmc(void)
+{
+	pxa_set_mci_info(&em_x270_mci_platform_data);
+}
+#else
+static inline void em_x270_init_mmc(void) {}
+#endif
+
 /* LCD 480x640 */
+#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
 static struct pxafb_mode_info em_x270_lcd_mode = {
 	.pixclock	= 50000,
 	.bpp		= 16,
@@ -307,40 +464,96 @@
 static struct pxafb_mach_info em_x270_lcd = {
 	.modes		= &em_x270_lcd_mode,
 	.num_modes	= 1,
-	.cmap_inverse	= 0,
-	.cmap_static	= 0,
-	.lccr0		= LCCR0_PAS,
-	.lccr3		= LCCR3_PixClkDiv(0x01) | LCCR3_Acb(0xff),
+	.lcd_conn	= LCD_COLOR_TFT_16BPP,
 };
+static void __init em_x270_init_lcd(void)
+{
+	set_pxa_fb_info(&em_x270_lcd);
+}
+#else
+static inline void em_x270_init_lcd(void) {}
+#endif
+
+#if defined(CONFIG_SND_PXA2XX_AC97) || defined(CONFIG_SND_PXA2XX_AC97_MODULE)
+static void __init em_x270_init_ac97(void)
+{
+	pxa_set_ac97_info(NULL);
+}
+#else
+static inline void em_x270_init_ac97(void) {}
+#endif
+
+#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE)
+static unsigned int em_x270_matrix_keys[] = {
+	KEY(0, 0, KEY_A), KEY(1, 0, KEY_UP), KEY(2, 1, KEY_B),
+	KEY(0, 2, KEY_LEFT), KEY(1, 1, KEY_ENTER), KEY(2, 0, KEY_RIGHT),
+	KEY(0, 1, KEY_C), KEY(1, 2, KEY_DOWN), KEY(2, 2, KEY_D),
+};
+
+struct pxa27x_keypad_platform_data em_x270_keypad_info = {
+	/* code map for the matrix keys */
+	.matrix_key_rows	= 3,
+	.matrix_key_cols	= 3,
+	.matrix_key_map		= em_x270_matrix_keys,
+	.matrix_key_map_size	= ARRAY_SIZE(em_x270_matrix_keys),
+};
+
+static void __init em_x270_init_keypad(void)
+{
+	pxa_set_keypad_info(&em_x270_keypad_info);
+}
+#else
+static inline void em_x270_init_keypad(void) {}
+#endif
+
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+static struct gpio_keys_button gpio_keys_button[] = {
+	[0] = {
+		.desc	= "sleep/wakeup",
+		.code	= KEY_SUSPEND,
+		.type	= EV_PWR,
+		.gpio	= 1,
+		.wakeup	= 1,
+	},
+};
+
+static struct gpio_keys_platform_data em_x270_gpio_keys_data = {
+	.buttons	= gpio_keys_button,
+	.nbuttons	= 1,
+};
+
+static struct platform_device em_x270_gpio_keys = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &em_x270_gpio_keys_data,
+	},
+};
+
+static void __init em_x270_init_gpio_keys(void)
+{
+	platform_device_register(&em_x270_gpio_keys);
+}
+#else
+static inline void em_x270_init_gpio_keys(void) {}
+#endif
 
 static void __init em_x270_init(void)
 {
-	/* setup LCD */
-	set_pxa_fb_info(&em_x270_lcd);
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(em_x270_pin_config));
 
-	/* register EM-X270 platform devices */
-	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
-	pxa_set_ac97_info(NULL);
-
-	/* set MCI and OHCI platform parameters */
-	pxa_set_mci_info(&em_x270_mci_platform_data);
-	pxa_set_ohci_info(&em_x270_ohci_platform_data);
-
-	/* setup STUART GPIOs */
-	pxa_gpio_mode(GPIO46_STRXD_MD);
-	pxa_gpio_mode(GPIO47_STTXD_MD);
-
-	/* setup BTUART GPIOs */
-	pxa_gpio_mode(GPIO42_BTRXD_MD);
-	pxa_gpio_mode(GPIO43_BTTXD_MD);
-	pxa_gpio_mode(GPIO44_BTCTS_MD);
-	pxa_gpio_mode(GPIO45_BTRTS_MD);
-
-	/* Setup interrupt for dm9000 */
-	set_irq_type(EM_X270_ETHIRQ, IRQT_RISING);
+	em_x270_init_dm9000();
+	em_x270_init_rtc();
+	em_x270_init_nand();
+	em_x270_init_lcd();
+	em_x270_init_mmc();
+	em_x270_init_ohci();
+	em_x270_init_keypad();
+	em_x270_init_gpio_keys();
+	em_x270_init_ac97();
 }
 
-MACHINE_START(EM_X270, "Compulab EM-x270")
+MACHINE_START(EM_X270, "Compulab EM-X270")
 	.boot_params	= 0xa0000100,
 	.phys_io	= 0x40000000,
 	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
diff --git a/arch/arm/mach-pxa/eseries.c b/arch/arm/mach-pxa/eseries.c
index ee0ae93..c29b7b2 100644
--- a/arch/arm/mach-pxa/eseries.c
+++ b/arch/arm/mach-pxa/eseries.c
@@ -17,7 +17,7 @@
 #include <asm/arch/hardware.h>
 #include <asm/mach-types.h>
 
-#include <generic.h>
+#include "generic.h"
 
 /* Only e800 has 128MB RAM */
 static void __init eseries_fixup(struct machine_desc *desc,
@@ -47,6 +47,19 @@
 MACHINE_END
 #endif
 
+#ifdef CONFIG_MACH_E350
+MACHINE_START(E350, "Toshiba e350")
+	/* Maintainer: Ian Molton (spyro@f2s.com) */
+	.phys_io        = 0x40000000,
+	.io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.boot_params    = 0xa0000100,
+	.map_io         = pxa_map_io,
+	.init_irq       = pxa25x_init_irq,
+	.fixup          = eseries_fixup,
+	.timer = &pxa_timer,
+MACHINE_END
+#endif
+
 #ifdef CONFIG_MACH_E740
 MACHINE_START(E740, "Toshiba e740")
         /* Maintainer: Ian Molton (spyro@f2s.com) */
diff --git a/arch/arm/mach-pxa/eseries_udc.c b/arch/arm/mach-pxa/eseries_udc.c
new file mode 100644
index 0000000..362847a
--- /dev/null
+++ b/arch/arm/mach-pxa/eseries_udc.c
@@ -0,0 +1,57 @@
+/*
+ * UDC functions for the Toshiba e-series PDAs
+ *
+ * Copyright (c) Ian Molton 2003
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/arch/udc.h>
+#include <asm/arch/eseries-gpio.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+#include <asm/domain.h>
+
+/* local PXA generic code */
+#include "generic.h"
+
+static struct pxa2xx_udc_mach_info e7xx_udc_mach_info = {
+	.gpio_vbus   = GPIO_E7XX_USB_DISC,
+	.gpio_pullup = GPIO_E7XX_USB_PULLUP,
+	.gpio_pullup_inverted = 1
+};
+
+static struct pxa2xx_udc_mach_info e800_udc_mach_info = {
+	.gpio_vbus   = GPIO_E800_USB_DISC,
+	.gpio_pullup = GPIO_E800_USB_PULLUP,
+	.gpio_pullup_inverted = 1
+};
+
+static int __init eseries_udc_init(void)
+{
+	if (machine_is_e330() || machine_is_e350() ||
+	    machine_is_e740() || machine_is_e750() ||
+	    machine_is_e400())
+		pxa_set_udc_info(&e7xx_udc_mach_info);
+	else if (machine_is_e800())
+		pxa_set_udc_info(&e800_udc_mach_info);
+
+	return 0;
+}
+
+module_init(eseries_udc_init);
+
+MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
+MODULE_DESCRIPTION("eseries UDC support");
+MODULE_LICENSE("GPLv2");
diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c
new file mode 100644
index 0000000..0143eed
--- /dev/null
+++ b/arch/arm/mach-pxa/ezx.c
@@ -0,0 +1,220 @@
+/*
+ *  ezx.c - Common code for the EZX platform.
+ *
+ *  Copyright (C) 2005-2006 Harald Welte <laforge@openezx.org>,
+ *		  2007-2008 Daniel Ribeiro <drwyrm@gmail.com>,
+ *		  2007-2008 Stefan Schmidt <stefan@datenfreihafen.org>
+ *
+ *  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/platform_device.h>
+#include <linux/delay.h>
+#include <linux/pwm_backlight.h>
+
+#include <asm/setup.h>
+#include <asm/arch/pxafb.h>
+#include <asm/arch/ohci.h>
+#include <asm/arch/i2c.h>
+
+#include <asm/arch/mfp-pxa27x.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-regs.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include "devices.h"
+#include "generic.h"
+
+static struct platform_pwm_backlight_data ezx_backlight_data = {
+	.pwm_id		= 0,
+	.max_brightness	= 1023,
+	.dft_brightness	= 1023,
+	.pwm_period_ns	= 78770,
+};
+
+static struct platform_device ezx_backlight_device = {
+	.name		= "pwm-backlight",
+	.dev		= {
+		.parent	= &pxa27x_device_pwm0.dev,
+		.platform_data = &ezx_backlight_data,
+	},
+};
+
+static struct pxafb_mode_info mode_ezx_old = {
+	.pixclock		= 150000,
+	.xres			= 240,
+	.yres			= 320,
+	.bpp			= 16,
+	.hsync_len		= 10,
+	.left_margin		= 20,
+	.right_margin		= 10,
+	.vsync_len		= 2,
+	.upper_margin		= 3,
+	.lower_margin		= 2,
+	.sync			= 0,
+};
+
+static struct pxafb_mach_info ezx_fb_info_1 = {
+	.modes		= &mode_ezx_old,
+	.num_modes	= 1,
+	.lcd_conn	= LCD_COLOR_TFT_16BPP,
+};
+
+static struct pxafb_mode_info mode_72r89803y01 = {
+	.pixclock		= 192308,
+	.xres			= 240,
+	.yres			= 320,
+	.bpp			= 32,
+	.depth			= 18,
+	.hsync_len		= 10,
+	.left_margin		= 20,
+	.right_margin		= 10,
+	.vsync_len		= 2,
+	.upper_margin		= 3,
+	.lower_margin		= 2,
+	.sync			= 0,
+};
+
+static struct pxafb_mach_info ezx_fb_info_2 = {
+	.modes		= &mode_72r89803y01,
+	.num_modes	= 1,
+	.lcd_conn	= LCD_COLOR_TFT_18BPP,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&ezx_backlight_device,
+};
+
+static unsigned long ezx_pin_config[] __initdata = {
+	/* PWM backlight */
+	GPIO16_PWM0_OUT,
+
+	/* BTUART */
+	GPIO42_BTUART_RXD,
+	GPIO43_BTUART_TXD,
+	GPIO44_BTUART_CTS,
+	GPIO45_BTUART_RTS,
+
+	/* STUART */
+	GPIO46_STUART_RXD,
+	GPIO47_STUART_TXD,
+
+	/* For A780 support (connected with Neptune GSM chip) */
+	GPIO30_USB_P3_2,	/* ICL_TXENB */
+	GPIO31_USB_P3_6,	/* ICL_VPOUT */
+	GPIO90_USB_P3_5,	/* ICL_VPIN */
+	GPIO91_USB_P3_1,	/* ICL_XRXD */
+	GPIO56_USB_P3_4,	/* ICL_VMOUT */
+	GPIO113_USB_P3_3,	/* /ICL_VMIN */
+};
+
+static void __init ezx_init(void)
+{
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config));
+	pxa_set_i2c_info(NULL);
+	if (machine_is_ezx_a780() || machine_is_ezx_e680())
+		set_pxa_fb_info(&ezx_fb_info_1);
+	else
+		set_pxa_fb_info(&ezx_fb_info_2);
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+static void __init ezx_fixup(struct machine_desc *desc, struct tag *tags,
+		char **cmdline, struct meminfo *mi)
+{
+	/* We have two ram chips. First one with 32MB at 0xA0000000 and a second
+	 * 16MB one at 0xAC000000
+	 */
+	mi->nr_banks = 2;
+	mi->bank[0].start = 0xa0000000;
+	mi->bank[0].node = 0;
+	mi->bank[0].size = (32*1024*1024);
+	mi->bank[1].start = 0xac000000;
+	mi->bank[1].node = 1;
+	mi->bank[1].size = (16*1024*1024);
+}
+
+#ifdef CONFIG_MACH_EZX_A780
+MACHINE_START(EZX_A780, "Motorola EZX A780")
+	.phys_io        = 0x40000000,
+	.io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.fixup			= ezx_fixup,
+	.boot_params    = 0xa0000100,
+	.map_io         = pxa_map_io,
+	.init_irq       = pxa27x_init_irq,
+	.timer          = &pxa_timer,
+	.init_machine   = &ezx_init,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EZX_E680
+MACHINE_START(EZX_E680, "Motorola EZX E680")
+	.phys_io        = 0x40000000,
+	.io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.fixup			= ezx_fixup,
+	.boot_params    = 0xa0000100,
+	.map_io         = pxa_map_io,
+	.init_irq       = pxa27x_init_irq,
+	.timer          = &pxa_timer,
+	.init_machine   = &ezx_init,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EZX_A1200
+MACHINE_START(EZX_A1200, "Motorola EZX A1200")
+	.phys_io        = 0x40000000,
+	.io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.fixup			= ezx_fixup,
+	.boot_params    = 0xa0000100,
+	.map_io         = pxa_map_io,
+	.init_irq       = pxa27x_init_irq,
+	.timer          = &pxa_timer,
+	.init_machine   = &ezx_init,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EZX_A910
+MACHINE_START(EZX_A910, "Motorola EZX A910")
+	.phys_io        = 0x40000000,
+	.io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.fixup			= ezx_fixup,
+	.boot_params    = 0xa0000100,
+	.map_io         = pxa_map_io,
+	.init_irq       = pxa27x_init_irq,
+	.timer          = &pxa_timer,
+	.init_machine   = &ezx_init,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EZX_E6
+MACHINE_START(EZX_E6, "Motorola EZX E6")
+	.phys_io        = 0x40000000,
+	.io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.fixup			= ezx_fixup,
+	.boot_params    = 0xa0000100,
+	.map_io         = pxa_map_io,
+	.init_irq       = pxa27x_init_irq,
+	.timer          = &pxa_timer,
+	.init_machine   = &ezx_init,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_EZX_E2
+MACHINE_START(EZX_E2, "Motorola EZX E2")
+	.phys_io        = 0x40000000,
+	.io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.fixup			= ezx_fixup,
+	.boot_params    = 0xa0000100,
+	.map_io         = pxa_map_io,
+	.init_irq       = pxa27x_init_irq,
+	.timer          = &pxa_timer,
+	.init_machine   = &ezx_init,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
index 5306544..dd759d0 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -20,6 +20,7 @@
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/smc91x.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
@@ -38,6 +39,7 @@
 #include <asm/arch/pxafb.h>
 #include <asm/arch/ssp.h>
 #include <asm/arch/pxa27x_keypad.h>
+#include <asm/arch/pxa3xx_nand.h>
 #include <asm/arch/littleton.h>
 
 #include "generic.h"
@@ -101,18 +103,26 @@
 	[1] = {
 		.start	= IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO90)),
 		.end	= IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO90)),
-		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_FALLING,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
 	}
 };
 
+static struct smc91x_platdata littleton_smc91x_info = {
+	.flags	= SMC91X_USE_8BIT | SMC91X_USE_16BIT |
+		  SMC91X_NOWAIT | SMC91X_USE_DMA,
+};
+
 static struct platform_device smc91x_device = {
 	.name		= "smc91x",
 	.id		= 0,
 	.num_resources	= ARRAY_SIZE(smc91x_resources),
 	.resource	= smc91x_resources,
+	.dev		= {
+		.platform_data = &littleton_smc91x_info,
+	},
 };
 
-#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULES)
+#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
 /* use bit 30, 31 as the indicator of command parameter number */
 #define CMD0(x)		((0x00000000) | ((x) << 9))
 #define CMD1(x, x1)	((0x40000000) | ((x) << 9) | 0x100 | (x1))
@@ -311,9 +321,9 @@
 }
 #else
 static inline void littleton_init_lcd(void) {};
-#endif /* CONFIG_FB_PXA || CONFIG_FB_PXA_MODULES */
+#endif /* CONFIG_FB_PXA || CONFIG_FB_PXA_MODULE */
 
-#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULES)
+#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE)
 static unsigned int littleton_matrix_key_map[] = {
 	/* KEY(row, col, key_code) */
 	KEY(1, 3, KEY_0), KEY(0, 0, KEY_1), KEY(1, 0, KEY_2), KEY(2, 0, KEY_3),
@@ -361,6 +371,57 @@
 static inline void littleton_init_keypad(void) {}
 #endif
 
+#if defined(CONFIG_MTD_NAND_PXA3xx) || defined(CONFIG_MTD_NAND_PXA3xx_MODULE)
+static struct mtd_partition littleton_nand_partitions[] = {
+	[0] = {
+		.name        = "Bootloader",
+		.offset      = 0,
+		.size        = 0x060000,
+		.mask_flags  = MTD_WRITEABLE, /* force read-only */
+	},
+	[1] = {
+		.name        = "Kernel",
+		.offset      = 0x060000,
+		.size        = 0x200000,
+		.mask_flags  = MTD_WRITEABLE, /* force read-only */
+	},
+	[2] = {
+		.name        = "Filesystem",
+		.offset      = 0x0260000,
+		.size        = 0x3000000,     /* 48M - rootfs */
+	},
+	[3] = {
+		.name        = "MassStorage",
+		.offset      = 0x3260000,
+		.size        = 0x3d40000,
+	},
+	[4] = {
+		.name        = "BBT",
+		.offset      = 0x6FA0000,
+		.size        = 0x80000,
+		.mask_flags  = MTD_WRITEABLE,  /* force read-only */
+	},
+	/* NOTE: we reserve some blocks at the end of the NAND flash for
+	 * bad block management, and the max number of relocation blocks
+	 * differs on different platforms. Please take care with it when
+	 * defining the partition table.
+	 */
+};
+
+static struct pxa3xx_nand_platform_data littleton_nand_info = {
+	.enable_arbiter	= 1,
+	.parts		= littleton_nand_partitions,
+	.nr_parts	= ARRAY_SIZE(littleton_nand_partitions),
+};
+
+static void __init littleton_init_nand(void)
+{
+	pxa3xx_set_nand_info(&littleton_nand_info);
+}
+#else
+static inline void littleton_init_nand(void) {}
+#endif /* CONFIG_MTD_NAND_PXA3xx || CONFIG_MTD_NAND_PXA3xx_MODULE */
+
 static void __init littleton_init(void)
 {
 	/* initialize MFP configurations */
@@ -374,6 +435,7 @@
 
 	littleton_init_lcd();
 	littleton_init_keypad();
+	littleton_init_nand();
 }
 
 MACHINE_START(LITTLETON, "Marvell Form Factor Development Platform (aka Littleton)")
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index a3fae41..ac26423 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -21,6 +21,7 @@
 #include <linux/interrupt.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
+#include <linux/smc91x.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
@@ -226,14 +227,6 @@
 	.num_chipselect	= 0,
 };
 
-static struct platform_device pxa_ssp = {
-	.name		= "pxa2xx-spi",
-	.id		= 1,
-	.dev = {
-		.platform_data	= &pxa_ssp_master_info,
-	},
-};
-
 static int lubbock_ads7846_pendown_state(void)
 {
 	/* TS_BUSY is bit 8 in LUB_MISC_RD, but pendown is irq-only */
@@ -292,11 +285,18 @@
 	},
 };
 
+static struct smc91x_platdata lubbock_smc91x_info = {
+	.flags	= SMC91X_USE_16BIT | SMC91X_NOWAIT | SMC91X_IO_SHIFT_2,
+};
+
 static struct platform_device smc91x_device = {
 	.name		= "smc91x",
 	.id		= -1,
 	.num_resources	= ARRAY_SIZE(smc91x_resources),
 	.resource	= smc91x_resources,
+	.dev		= {
+		.platform_data = &lubbock_smc91x_info,
+	},
 };
 
 static struct resource flash_resources[] = {
@@ -367,7 +367,6 @@
 	&smc91x_device,
 	&lubbock_flash_device[0],
 	&lubbock_flash_device[1],
-	&pxa_ssp,
 };
 
 static struct pxafb_mode_info sharp_lm8v31_mode = {
@@ -471,6 +470,7 @@
 	} else if (mode & IR_FIRMODE) {
 		LUB_MISC_WR |= 1 << 4;
 	}
+	pxa2xx_transceiver_mode(dev, mode);
 	local_irq_restore(flags);
 }
 
@@ -501,6 +501,7 @@
 	lubbock_flash_data[flashboot].name = "boot-rom";
 	(void) platform_add_devices(devices, ARRAY_SIZE(devices));
 
+	pxa2xx_set_spi_info(1, &pxa_ssp_master_info);
 	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
 }
 
diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
index 01b2fa7..c9d274f 100644
--- a/arch/arm/mach-pxa/magician.c
+++ b/arch/arm/mach-pxa/magician.c
@@ -17,17 +17,15 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
+#include <linux/gpio.h>
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
 #include <linux/mfd/htc-egpio.h>
 #include <linux/mfd/htc-pasic3.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
 #include <linux/mtd/physmap.h>
 #include <linux/pda_power.h>
 #include <linux/pwm_backlight.h>
 
-#include <asm/gpio.h>
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -44,7 +42,7 @@
 #include "devices.h"
 #include "generic.h"
 
-static unsigned long magician_pin_config[] = {
+static unsigned long magician_pin_config[] __initdata = {
 
 	/* SDRAM and Static Memory I/O Signals */
 	GPIO20_nSDCS_2,
@@ -134,6 +132,7 @@
 static void magician_irda_transceiver_mode(struct device *dev, int mode)
 {
 	gpio_set_value(GPIO83_MAGICIAN_nIR_EN, mode & IR_OFF);
+	pxa2xx_transceiver_mode(dev, mode);
 }
 
 static struct pxaficp_platform_data magician_ficp_info = {
@@ -399,6 +398,7 @@
 
 static struct platform_device backlight = {
 	.name = "pwm-backlight",
+	.id   = -1,
 	.dev  = {
 		.parent        = &pxa27x_device_pwm0.dev,
 		.platform_data = &backlight_data,
@@ -511,6 +511,37 @@
  * External power
  */
 
+static int power_supply_init(struct device *dev)
+{
+	int ret;
+
+	ret = gpio_request(EGPIO_MAGICIAN_CABLE_STATE_AC, "CABLE_STATE_AC");
+	if (ret)
+		goto err_cs_ac;
+	ret = gpio_request(EGPIO_MAGICIAN_CABLE_STATE_USB, "CABLE_STATE_USB");
+	if (ret)
+		goto err_cs_usb;
+	ret = gpio_request(EGPIO_MAGICIAN_CHARGE_EN, "CHARGE_EN");
+	if (ret)
+		goto err_chg_en;
+	ret = gpio_request(GPIO30_MAGICIAN_nCHARGE_EN, "nCHARGE_EN");
+	if (!ret)
+		ret = gpio_direction_output(GPIO30_MAGICIAN_nCHARGE_EN, 0);
+	if (ret)
+		goto err_nchg_en;
+
+	return 0;
+
+err_nchg_en:
+	gpio_free(EGPIO_MAGICIAN_CHARGE_EN);
+err_chg_en:
+	gpio_free(EGPIO_MAGICIAN_CABLE_STATE_USB);
+err_cs_usb:
+	gpio_free(EGPIO_MAGICIAN_CABLE_STATE_AC);
+err_cs_ac:
+	return ret;
+}
+
 static int magician_is_ac_online(void)
 {
 	return gpio_get_value(EGPIO_MAGICIAN_CABLE_STATE_AC);
@@ -527,14 +558,24 @@
 	gpio_set_value(EGPIO_MAGICIAN_CHARGE_EN, flags);
 }
 
+static void power_supply_exit(struct device *dev)
+{
+	gpio_free(GPIO30_MAGICIAN_nCHARGE_EN);
+	gpio_free(EGPIO_MAGICIAN_CHARGE_EN);
+	gpio_free(EGPIO_MAGICIAN_CABLE_STATE_USB);
+	gpio_free(EGPIO_MAGICIAN_CABLE_STATE_AC);
+}
+
 static char *magician_supplicants[] = {
 	"ds2760-battery.0", "backup-battery"
 };
 
 static struct pda_power_pdata power_supply_info = {
+	.init            = power_supply_init,
 	.is_ac_online    = magician_is_ac_online,
 	.is_usb_online   = magician_is_usb_online,
 	.set_charge      = magician_set_charge,
+	.exit            = power_supply_exit,
 	.supplied_to     = magician_supplicants,
 	.num_supplicants = ARRAY_SIZE(magician_supplicants),
 };
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index f2e9e7c..851ec2d 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -26,6 +26,7 @@
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
 #include <linux/pwm_backlight.h>
+#include <linux/smc91x.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
@@ -110,9 +111,9 @@
 	GPIO45_AC97_SYSCLK,
 
 	/* Keypad */
-	GPIO93_KP_DKIN_0	| WAKEUP_ON_LEVEL_HIGH,
-	GPIO94_KP_DKIN_1	| WAKEUP_ON_LEVEL_HIGH,
-	GPIO95_KP_DKIN_2	| WAKEUP_ON_LEVEL_HIGH,
+	GPIO93_KP_DKIN_0,
+	GPIO94_KP_DKIN_1,
+	GPIO95_KP_DKIN_2,
 	GPIO100_KP_MKIN_0	| WAKEUP_ON_LEVEL_HIGH,
 	GPIO101_KP_MKIN_1	| WAKEUP_ON_LEVEL_HIGH,
 	GPIO102_KP_MKIN_2	| WAKEUP_ON_LEVEL_HIGH,
@@ -240,11 +241,19 @@
 	}
 };
 
+static struct smc91x_platdata mainstone_smc91x_info = {
+	.flags	= SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT |
+		  SMC91X_NOWAIT | SMC91X_USE_DMA,
+};
+
 static struct platform_device smc91x_device = {
 	.name		= "smc91x",
 	.id		= 0,
 	.num_resources	= ARRAY_SIZE(smc91x_resources),
 	.resource	= smc91x_resources,
+	.dev		= {
+		.platform_data = &mainstone_smc91x_info,
+	},
 };
 
 static int mst_audio_startup(struct snd_pcm_substream *substream, void *priv)
@@ -455,6 +464,7 @@
 	} else if (mode & IR_FIRMODE) {
 		MST_MSCWR1 |= MST_MSCWR1_IRDA_FIR;
 	}
+	pxa2xx_transceiver_mode(dev, mode);
 	if (mode & IR_OFF) {
 		MST_MSCWR1 = (MST_MSCWR1 & ~MST_MSCWR1_IRDA_MASK) | MST_MSCWR1_IRDA_OFF;
 	} else {
@@ -513,7 +523,7 @@
 	.init		= mainstone_ohci_init,
 };
 
-#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULES)
+#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE)
 static unsigned int mainstone_matrix_keys[] = {
 	KEY(0, 0, KEY_A), KEY(1, 0, KEY_B), KEY(2, 0, KEY_C),
 	KEY(3, 0, KEY_D), KEY(4, 0, KEY_E), KEY(5, 0, KEY_F),
diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c
index d1cdb4e..fd4545e 100644
--- a/arch/arm/mach-pxa/mfp-pxa2xx.c
+++ b/arch/arm/mach-pxa/mfp-pxa2xx.c
@@ -39,6 +39,28 @@
 
 static struct gpio_desc gpio_desc[MFP_PIN_GPIO127 + 1];
 
+static int __mfp_config_lpm(unsigned gpio, unsigned long lpm)
+{
+	unsigned mask = GPIO_bit(gpio);
+
+	/* low power state */
+	switch (lpm) {
+	case MFP_LPM_DRIVE_HIGH:
+		PGSR(gpio) |= mask;
+		break;
+	case MFP_LPM_DRIVE_LOW:
+		PGSR(gpio) &= ~mask;
+		break;
+	case MFP_LPM_INPUT:
+		break;
+	default:
+		pr_warning("%s: invalid low power state for GPIO%d\n",
+				__func__, gpio);
+		return -EINVAL;
+	}
+	return 0;
+}
+
 static int __mfp_config_gpio(unsigned gpio, unsigned long c)
 {
 	unsigned long gafr, mask = GPIO_bit(gpio);
@@ -57,21 +79,8 @@
 	else
 		GPDR(gpio) &= ~mask;
 
-	/* low power state */
-	switch (c & MFP_LPM_STATE_MASK) {
-	case MFP_LPM_DRIVE_HIGH:
-		PGSR(gpio) |= mask;
-		break;
-	case MFP_LPM_DRIVE_LOW:
-		PGSR(gpio) &= ~mask;
-		break;
-	case MFP_LPM_INPUT:
-		break;
-	default:
-		pr_warning("%s: invalid low power state for GPIO%d\n",
-				__func__, gpio);
+	if (__mfp_config_lpm(gpio, c & MFP_LPM_STATE_MASK))
 		return -EINVAL;
-	}
 
 	/* give early warning if MFP_LPM_CAN_WAKEUP is set on the
 	 * configurations of those pins not able to wakeup
@@ -91,6 +100,18 @@
 	return 0;
 }
 
+static inline int __mfp_validate(int mfp)
+{
+	int gpio = mfp_to_gpio(mfp);
+
+	if ((mfp > MFP_PIN_GPIO127) || !gpio_desc[gpio].valid) {
+		pr_warning("%s: GPIO%d is invalid pin\n", __func__, gpio);
+		return -1;
+	}
+
+	return gpio;
+}
+
 void pxa2xx_mfp_config(unsigned long *mfp_cfgs, int num)
 {
 	unsigned long flags;
@@ -99,13 +120,9 @@
 
 	for (i = 0, c = mfp_cfgs; i < num; i++, c++) {
 
-		gpio = mfp_to_gpio(MFP_PIN(*c));
-
-		if (!gpio_desc[gpio].valid) {
-			pr_warning("%s: GPIO%d is invalid pin\n",
-				__func__, gpio);
+		gpio = __mfp_validate(MFP_PIN(*c));
+		if (gpio < 0)
 			continue;
-		}
 
 		local_irq_save(flags);
 
@@ -116,6 +133,20 @@
 	}
 }
 
+void pxa2xx_mfp_set_lpm(int mfp, unsigned long lpm)
+{
+	unsigned long flags;
+	int gpio;
+
+	gpio = __mfp_validate(mfp);
+	if (gpio < 0)
+		return;
+
+	local_irq_save(flags);
+	__mfp_config_lpm(gpio, lpm);
+	local_irq_restore(flags);
+}
+
 int gpio_set_wake(unsigned int gpio, unsigned int on)
 {
 	struct gpio_desc *d;
diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c
new file mode 100644
index 0000000..408657a
--- /dev/null
+++ b/arch/arm/mach-pxa/palmtx.c
@@ -0,0 +1,416 @@
+/*
+ * Hardware definitions for PalmTX
+ *
+ * Author:     Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on work of:
+ *		Alex Osborne <ato@meshy.org>
+ *		Cristiano P. <cristianop@users.sourceforge.net>
+ *		Jan Herman <2hp@seznam.cz>
+ *		Michal Hrusecky
+ *
+ * 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.
+ *
+ * (find more info at www.hackndev.com)
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/pda_power.h>
+#include <linux/pwm_backlight.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/audio.h>
+#include <asm/arch/palmtx.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/pxafb.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/mfp-pxa27x.h>
+#include <asm/arch/irda.h>
+#include <asm/arch/pxa27x_keypad.h>
+#include <asm/arch/udc.h>
+
+#include "generic.h"
+#include "devices.h"
+
+/******************************************************************************
+ * Pin configuration
+ ******************************************************************************/
+static unsigned long palmtx_pin_config[] __initdata = {
+	/* MMC */
+	GPIO32_MMC_CLK,
+	GPIO92_MMC_DAT_0,
+	GPIO109_MMC_DAT_1,
+	GPIO110_MMC_DAT_2,
+	GPIO111_MMC_DAT_3,
+	GPIO112_MMC_CMD,
+
+	/* AC97 */
+	GPIO28_AC97_BITCLK,
+	GPIO29_AC97_SDATA_IN_0,
+	GPIO30_AC97_SDATA_OUT,
+	GPIO31_AC97_SYNC,
+
+	/* IrDA */
+	GPIO46_FICP_RXD,
+	GPIO47_FICP_TXD,
+
+	/* PWM */
+	GPIO16_PWM0_OUT,
+
+	/* USB */
+	GPIO13_GPIO,
+
+	/* PCMCIA */
+	GPIO48_nPOE,
+	GPIO49_nPWE,
+	GPIO50_nPIOR,
+	GPIO51_nPIOW,
+	GPIO85_nPCE_1,
+	GPIO54_nPCE_2,
+	GPIO79_PSKTSEL,
+	GPIO55_nPREG,
+	GPIO56_nPWAIT,
+	GPIO57_nIOIS16,
+};
+
+/******************************************************************************
+ * SD/MMC card controller
+ ******************************************************************************/
+static int palmtx_mci_init(struct device *dev, irq_handler_t palmtx_detect_int,
+				void *data)
+{
+	int err = 0;
+
+	/* Setup an interrupt for detecting card insert/remove events */
+	err = request_irq(IRQ_GPIO_PALMTX_SD_DETECT_N, palmtx_detect_int,
+			IRQF_DISABLED | IRQF_SAMPLE_RANDOM |
+			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+			"SD/MMC card detect", data);
+	if (err) {
+		printk(KERN_ERR "%s: cannot request SD/MMC card detect IRQ\n",
+				__func__);
+		return err;
+	}
+
+	err = gpio_request(GPIO_NR_PALMTX_SD_POWER, "SD_POWER");
+	if (err)
+		goto pwr_err;
+
+	err = gpio_request(GPIO_NR_PALMTX_SD_READONLY, "SD_READONLY");
+	if (err)
+		goto ro_err;
+
+	printk(KERN_DEBUG "%s: irq registered\n", __func__);
+
+	return 0;
+
+ro_err:
+	gpio_free(GPIO_NR_PALMTX_SD_POWER);
+pwr_err:
+	free_irq(IRQ_GPIO_PALMTX_SD_DETECT_N, data);
+	return err;
+}
+
+static void palmtx_mci_exit(struct device *dev, void *data)
+{
+	gpio_free(GPIO_NR_PALMTX_SD_READONLY);
+	gpio_free(GPIO_NR_PALMTX_SD_POWER);
+	free_irq(IRQ_GPIO_PALMTX_SD_DETECT_N, data);
+}
+
+static void palmtx_mci_power(struct device *dev, unsigned int vdd)
+{
+	struct pxamci_platform_data *p_d = dev->platform_data;
+	gpio_set_value(GPIO_NR_PALMTX_SD_POWER, p_d->ocr_mask & (1 << vdd));
+}
+
+static int palmtx_mci_get_ro(struct device *dev)
+{
+	return gpio_get_value(GPIO_NR_PALMTX_SD_READONLY);
+}
+
+static struct pxamci_platform_data palmtx_mci_platform_data = {
+	.ocr_mask	= MMC_VDD_32_33 | MMC_VDD_33_34,
+	.setpower	= palmtx_mci_power,
+	.get_ro		= palmtx_mci_get_ro,
+	.init 		= palmtx_mci_init,
+	.exit		= palmtx_mci_exit,
+};
+
+/******************************************************************************
+ * GPIO keyboard
+ ******************************************************************************/
+static unsigned int palmtx_matrix_keys[] = {
+	KEY(0, 0, KEY_POWER),
+	KEY(0, 1, KEY_F1),
+	KEY(0, 2, KEY_ENTER),
+
+	KEY(1, 0, KEY_F2),
+	KEY(1, 1, KEY_F3),
+	KEY(1, 2, KEY_F4),
+
+	KEY(2, 0, KEY_UP),
+	KEY(2, 2, KEY_DOWN),
+
+	KEY(3, 0, KEY_RIGHT),
+	KEY(3, 2, KEY_LEFT),
+
+};
+
+static struct pxa27x_keypad_platform_data palmtx_keypad_platform_data = {
+	.matrix_key_rows	= 4,
+	.matrix_key_cols	= 3,
+	.matrix_key_map		= palmtx_matrix_keys,
+	.matrix_key_map_size	= ARRAY_SIZE(palmtx_matrix_keys),
+
+	.debounce_interval	= 30,
+};
+
+/******************************************************************************
+ * GPIO keys
+ ******************************************************************************/
+static struct gpio_keys_button palmtx_pxa_buttons[] = {
+	{KEY_F8, GPIO_NR_PALMTX_HOTSYNC_BUTTON_N, 1, "HotSync Button" },
+};
+
+static struct gpio_keys_platform_data palmtx_pxa_keys_data = {
+	.buttons	= palmtx_pxa_buttons,
+	.nbuttons	= ARRAY_SIZE(palmtx_pxa_buttons),
+};
+
+static struct platform_device palmtx_pxa_keys = {
+	.name	= "gpio-keys",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &palmtx_pxa_keys_data,
+	},
+};
+
+/******************************************************************************
+ * Backlight
+ ******************************************************************************/
+static int palmtx_backlight_init(struct device *dev)
+{
+	int ret;
+
+	ret = gpio_request(GPIO_NR_PALMTX_BL_POWER, "BL POWER");
+	if (ret)
+		goto err;
+	ret = gpio_request(GPIO_NR_PALMTX_LCD_POWER, "LCD POWER");
+	if (ret)
+		goto err2;
+
+	return 0;
+err2:
+	gpio_free(GPIO_NR_PALMTX_BL_POWER);
+err:
+	return ret;
+}
+
+static int palmtx_backlight_notify(int brightness)
+{
+	gpio_set_value(GPIO_NR_PALMTX_BL_POWER, brightness);
+	gpio_set_value(GPIO_NR_PALMTX_LCD_POWER, brightness);
+	return brightness;
+}
+
+static void palmtx_backlight_exit(struct device *dev)
+{
+	gpio_free(GPIO_NR_PALMTX_BL_POWER);
+	gpio_free(GPIO_NR_PALMTX_LCD_POWER);
+}
+
+static struct platform_pwm_backlight_data palmtx_backlight_data = {
+	.pwm_id		= 0,
+	.max_brightness	= PALMTX_MAX_INTENSITY,
+	.dft_brightness	= PALMTX_MAX_INTENSITY,
+	.pwm_period_ns	= PALMTX_PERIOD_NS,
+	.init		= palmtx_backlight_init,
+	.notify		= palmtx_backlight_notify,
+	.exit		= palmtx_backlight_exit,
+};
+
+static struct platform_device palmtx_backlight = {
+	.name	= "pwm-backlight",
+	.dev	= {
+		.parent		= &pxa27x_device_pwm0.dev,
+		.platform_data	= &palmtx_backlight_data,
+	},
+};
+
+/******************************************************************************
+ * IrDA
+ ******************************************************************************/
+static void palmtx_irda_transceiver_mode(struct device *dev, int mode)
+{
+	gpio_set_value(GPIO_NR_PALMTX_IR_DISABLE, mode & IR_OFF);
+	pxa2xx_transceiver_mode(dev, mode);
+}
+
+static struct pxaficp_platform_data palmtx_ficp_platform_data = {
+	.transceiver_cap	= IR_SIRMODE | IR_FIRMODE | IR_OFF,
+	.transceiver_mode	= palmtx_irda_transceiver_mode,
+};
+
+/******************************************************************************
+ * UDC
+ ******************************************************************************/
+static void palmtx_udc_command(int cmd)
+{
+	gpio_set_value(GPIO_NR_PALMTX_USB_POWER, !cmd);
+	udelay(50);
+	gpio_set_value(GPIO_NR_PALMTX_USB_PULLUP, !cmd);
+}
+
+static struct pxa2xx_udc_mach_info palmtx_udc_info __initdata = {
+	.gpio_vbus		= GPIO_NR_PALMTX_USB_DETECT_N,
+	.gpio_vbus_inverted	= 1,
+	.udc_command		= palmtx_udc_command,
+};
+
+/******************************************************************************
+ * Power supply
+ ******************************************************************************/
+static int power_supply_init(struct device *dev)
+{
+	int ret;
+
+	ret = gpio_request(GPIO_NR_PALMTX_POWER_DETECT, "CABLE_STATE_AC");
+	if (ret)
+		goto err_cs_ac;
+
+	ret = gpio_request(GPIO_NR_PALMTX_USB_DETECT_N, "CABLE_STATE_USB");
+	if (ret)
+		goto err_cs_usb;
+
+	return 0;
+
+err_cs_usb:
+	gpio_free(GPIO_NR_PALMTX_POWER_DETECT);
+err_cs_ac:
+	return ret;
+}
+
+static int palmtx_is_ac_online(void)
+{
+	return gpio_get_value(GPIO_NR_PALMTX_POWER_DETECT);
+}
+
+static int palmtx_is_usb_online(void)
+{
+	return !gpio_get_value(GPIO_NR_PALMTX_USB_DETECT_N);
+}
+
+static void power_supply_exit(struct device *dev)
+{
+	gpio_free(GPIO_NR_PALMTX_USB_DETECT_N);
+	gpio_free(GPIO_NR_PALMTX_POWER_DETECT);
+}
+
+static char *palmtx_supplicants[] = {
+	"main-battery",
+};
+
+static struct pda_power_pdata power_supply_info = {
+	.init            = power_supply_init,
+	.is_ac_online    = palmtx_is_ac_online,
+	.is_usb_online   = palmtx_is_usb_online,
+	.exit            = power_supply_exit,
+	.supplied_to     = palmtx_supplicants,
+	.num_supplicants = ARRAY_SIZE(palmtx_supplicants),
+};
+
+static struct platform_device power_supply = {
+	.name = "pda-power",
+	.id   = -1,
+	.dev  = {
+		.platform_data = &power_supply_info,
+	},
+};
+
+/******************************************************************************
+ * Framebuffer
+ ******************************************************************************/
+static struct pxafb_mode_info palmtx_lcd_modes[] = {
+{
+	.pixclock	= 57692,
+	.xres		= 320,
+	.yres		= 480,
+	.bpp		= 16,
+
+	.left_margin	= 32,
+	.right_margin	= 1,
+	.upper_margin	= 7,
+	.lower_margin	= 1,
+
+	.hsync_len	= 4,
+	.vsync_len	= 1,
+},
+};
+
+static struct pxafb_mach_info palmtx_lcd_screen = {
+	.modes		= palmtx_lcd_modes,
+	.num_modes	= ARRAY_SIZE(palmtx_lcd_modes),
+	.lcd_conn	= LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
+};
+
+/******************************************************************************
+ * Machine init
+ ******************************************************************************/
+static struct platform_device *devices[] __initdata = {
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+	&palmtx_pxa_keys,
+#endif
+	&palmtx_backlight,
+	&power_supply,
+};
+
+static struct map_desc palmtx_io_desc[] __initdata = {
+{
+	.virtual	= PALMTX_PCMCIA_VIRT,
+	.pfn		= __phys_to_pfn(PALMTX_PCMCIA_PHYS),
+	.length		= PALMTX_PCMCIA_SIZE,
+	.type		= MT_DEVICE
+},
+};
+
+static void __init palmtx_map_io(void)
+{
+	pxa_map_io();
+	iotable_init(palmtx_io_desc, ARRAY_SIZE(palmtx_io_desc));
+}
+
+static void __init palmtx_init(void)
+{
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(palmtx_pin_config));
+
+	set_pxa_fb_info(&palmtx_lcd_screen);
+	pxa_set_mci_info(&palmtx_mci_platform_data);
+	pxa_set_udc_info(&palmtx_udc_info);
+	pxa_set_ac97_info(NULL);
+	pxa_set_ficp_info(&palmtx_ficp_platform_data);
+	pxa_set_keypad_info(&palmtx_keypad_platform_data);
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+MACHINE_START(PALMTX, "Palm T|X")
+	.phys_io	= PALMTX_PHYS_IO_START,
+	.io_pg_offst	= io_p2v(0x40000000),
+	.boot_params	= 0xa0000100,
+	.map_io		= palmtx_map_io,
+	.init_irq	= pxa27x_init_irq,
+	.timer		= &pxa_timer,
+	.init_machine	= palmtx_init
+MACHINE_END
diff --git a/arch/arm/mach-pxa/pcm027.c b/arch/arm/mach-pxa/pcm027.c
index 3b945eb..377f3be8 100644
--- a/arch/arm/mach-pxa/pcm027.c
+++ b/arch/arm/mach-pxa/pcm027.c
@@ -24,7 +24,9 @@
 #include <linux/platform_device.h>
 #include <linux/mtd/physmap.h>
 #include <linux/spi/spi.h>
+#include <linux/spi/max7301.h>
 #include <linux/leds.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/arch/hardware.h>
@@ -108,6 +110,32 @@
 	.resource	= smc91x_resources,
 };
 
+/*
+ * SPI host and devices
+ */
+static struct pxa2xx_spi_master pxa_ssp_master_info = {
+	.num_chipselect	= 1,
+};
+
+static struct max7301_platform_data max7301_info = {
+	.base = -1,
+};
+
+/* bus_num must match id in pxa2xx_set_spi_info() call */
+static struct spi_board_info spi_board_info[] __initdata = {
+	{
+		.modalias	= "max7301",
+		.platform_data	= &max7301_info,
+		.max_speed_hz	= 13000000,
+		.bus_num	= 1,
+		.chip_select	= 0,
+		.mode		= SPI_MODE_0,
+	},
+};
+
+/*
+ * NOR flash
+ */
 static struct physmap_flash_data pcm027_flash_data = {
 	.width  = 4,
 };
@@ -190,6 +218,9 @@
 #ifdef CONFIG_MACH_PCM990_BASEBOARD
 	pcm990_baseboard_init();
 #endif
+
+	pxa2xx_set_spi_info(1, &pxa_ssp_master_info);
+	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
 }
 
 static void __init pcm027_map_io(void)
diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
index 5d87c7c..30023b0 100644
--- a/arch/arm/mach-pxa/pcm990-baseboard.c
+++ b/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -33,14 +33,30 @@
 #include <asm/arch/camera.h>
 #include <asm/mach/map.h>
 #include <asm/arch/pxa-regs.h>
-#include <asm/arch/pxa2xx-gpio.h>
 #include <asm/arch/audio.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/ohci.h>
 #include <asm/arch/pcm990_baseboard.h>
 #include <asm/arch/pxafb.h>
+#include <asm/arch/mfp-pxa27x.h>
 
 #include "devices.h"
+#include "generic.h"
+
+static unsigned long pcm990_pin_config[] __initdata = {
+	/* MMC */
+	GPIO32_MMC_CLK,
+	GPIO112_MMC_CMD,
+	GPIO92_MMC_DAT_0,
+	GPIO109_MMC_DAT_1,
+	GPIO110_MMC_DAT_2,
+	GPIO111_MMC_DAT_3,
+	/* USB */
+	GPIO88_USBH1_PWR,
+	GPIO89_USBH1_PEN,
+	/* PWM0 */
+	GPIO16_PWM0_OUT,
+};
 
 /*
  * pcm990_lcd_power - control power supply to the LCD
@@ -277,16 +293,6 @@
 {
 	int err;
 
-	/*
-	 * enable GPIO for PXA27x MMC controller
-	 */
-	pxa_gpio_mode(GPIO32_MMCCLK_MD);
-	pxa_gpio_mode(GPIO112_MMCCMD_MD);
-	pxa_gpio_mode(GPIO92_MMCDAT0_MD);
-	pxa_gpio_mode(GPIO109_MMCDAT1_MD);
-	pxa_gpio_mode(GPIO110_MMCDAT2_MD);
-	pxa_gpio_mode(GPIO111_MMCDAT3_MD);
-
 	err = request_irq(PCM027_MMCDET_IRQ, mci_detect_int, IRQF_DISABLED,
 			     "MMC card detect", data);
 	if (err)
@@ -333,8 +339,6 @@
  */
 static int pcm990_ohci_init(struct device *dev)
 {
-	pxa_gpio_mode(PCM990_USB_OVERCURRENT);
-	pxa_gpio_mode(PCM990_USB_PWR_EN);
 	/*
 	 * disable USB port 2 and 3
 	 * power sense is active low
@@ -361,23 +365,27 @@
  * PXA27x Camera specific stuff
  */
 #if defined(CONFIG_VIDEO_PXA27x) || defined(CONFIG_VIDEO_PXA27x_MODULE)
+static unsigned long pcm990_camera_pin_config[] = {
+	/* CIF */
+	GPIO98_CIF_DD_0,
+	GPIO105_CIF_DD_1,
+	GPIO104_CIF_DD_2,
+	GPIO103_CIF_DD_3,
+	GPIO95_CIF_DD_4,
+	GPIO94_CIF_DD_5,
+	GPIO93_CIF_DD_6,
+	GPIO108_CIF_DD_7,
+	GPIO107_CIF_DD_8,
+	GPIO106_CIF_DD_9,
+	GPIO42_CIF_MCLK,
+	GPIO45_CIF_PCLK,
+	GPIO43_CIF_FV,
+	GPIO44_CIF_LV,
+};
+
 static int pcm990_pxacamera_init(struct device *dev)
 {
-	pxa_gpio_mode(GPIO98_CIF_DD_0_MD);
-	pxa_gpio_mode(GPIO105_CIF_DD_1_MD);
-	pxa_gpio_mode(GPIO104_CIF_DD_2_MD);
-	pxa_gpio_mode(GPIO103_CIF_DD_3_MD);
-	pxa_gpio_mode(GPIO95_CIF_DD_4_MD);
-	pxa_gpio_mode(GPIO94_CIF_DD_5_MD);
-	pxa_gpio_mode(GPIO93_CIF_DD_6_MD);
-	pxa_gpio_mode(GPIO108_CIF_DD_7_MD);
-	pxa_gpio_mode(GPIO107_CIF_DD_8_MD);
-	pxa_gpio_mode(GPIO106_CIF_DD_9_MD);
-	pxa_gpio_mode(GPIO42_CIF_MCLK_MD);
-	pxa_gpio_mode(GPIO45_CIF_PCLK_MD);
-	pxa_gpio_mode(GPIO43_CIF_FV_MD);
-	pxa_gpio_mode(GPIO44_CIF_LV_MD);
-
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(pcm990_camera_pin_config));
 	return 0;
 }
 
@@ -449,8 +457,10 @@
  */
 void __init pcm990_baseboard_init(void)
 {
+	pxa2xx_mfp_config(ARRAY_AND_SIZE(pcm990_pin_config));
+
 	/* register CPLD access */
-	iotable_init(pcm990_io_desc, ARRAY_SIZE(pcm990_io_desc));
+	iotable_init(ARRAY_AND_SIZE(pcm990_io_desc));
 
 	/* register CPLD's IRQ controller */
 	pcm990_init_irq();
@@ -458,7 +468,6 @@
 #ifndef CONFIG_PCM990_DISPLAY_NONE
 	set_pxa_fb_info(&pcm990_fbinfo);
 #endif
-	pxa_gpio_mode(GPIO16_PWM0_MD);
 	platform_device_register(&pcm990_backlight_device);
 
 	/* MMC */
@@ -473,9 +482,8 @@
 #if defined(CONFIG_VIDEO_PXA27x) || defined(CONFIG_VIDEO_PXA27x_MODULE)
 	pxa_set_camera_info(&pcm990_pxacamera_platform_data);
 
-	i2c_register_board_info(0, pcm990_i2c_devices,
-		ARRAY_SIZE(pcm990_i2c_devices));
+	i2c_register_board_info(0, ARRAY_AND_SIZE(pcm990_i2c_devices));
 #endif
 
-	printk(KERN_INFO"PCM-990 Evaluation baseboard initialized\n");
+	printk(KERN_INFO "PCM-990 Evaluation baseboard initialized\n");
 }
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index f81c10c..39612cf 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -267,6 +267,7 @@
 	} else {
 		GPCR(POODLE_GPIO_IR_ON) = GPIO_bit(POODLE_GPIO_IR_ON);
 	}
+	pxa2xx_transceiver_mode(dev, mode);
 }
 
 static struct pxaficp_platform_data poodle_ficp_platform_data = {
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index 4cd50e3..c5b845b 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -109,6 +109,52 @@
 	.getrate	= clk_pxa25x_lcd_getrate,
 };
 
+static unsigned long gpio12_config_32k[] = {
+	GPIO12_32KHz,
+};
+
+static unsigned long gpio12_config_gpio[] = {
+	GPIO12_GPIO,
+};
+
+static void clk_gpio12_enable(struct clk *clk)
+{
+	pxa2xx_mfp_config(gpio12_config_32k, 1);
+}
+
+static void clk_gpio12_disable(struct clk *clk)
+{
+	pxa2xx_mfp_config(gpio12_config_gpio, 1);
+}
+
+static const struct clkops clk_pxa25x_gpio12_ops = {
+	.enable         = clk_gpio12_enable,
+	.disable        = clk_gpio12_disable,
+};
+
+static unsigned long gpio11_config_3m6[] = {
+	GPIO11_3_6MHz,
+};
+
+static unsigned long gpio11_config_gpio[] = {
+	GPIO11_GPIO,
+};
+
+static void clk_gpio11_enable(struct clk *clk)
+{
+	pxa2xx_mfp_config(gpio11_config_3m6, 1);
+}
+
+static void clk_gpio11_disable(struct clk *clk)
+{
+	pxa2xx_mfp_config(gpio11_config_gpio, 1);
+}
+
+static const struct clkops clk_pxa25x_gpio11_ops = {
+	.enable         = clk_gpio11_enable,
+	.disable        = clk_gpio11_disable,
+};
+
 /*
  * 3.6864MHz -> OST, GPIO, SSP, PWM, PLLs (95.842MHz, 147.456MHz)
  * 95.842MHz -> MMC 19.169MHz, I2C 31.949MHz, FICP 47.923MHz, USB 47.923MHz
@@ -128,6 +174,8 @@
 	INIT_CKEN("UARTCLK", BTUART, 14745600, 1, &pxa_device_btuart.dev),
 	INIT_CKEN("UARTCLK", STUART, 14745600, 1, NULL),
 	INIT_CKEN("UDCCLK", USB, 47923000, 5, &pxa25x_device_udc.dev),
+	INIT_CLK("GPIO11_CLK", &clk_pxa25x_gpio11_ops, 3686400, 0, NULL),
+	INIT_CLK("GPIO12_CLK", &clk_pxa25x_gpio12_ops, 32768, 0, NULL),
 	INIT_CKEN("MMCCLK", MMC, 19169000, 0, &pxa_device_mci.dev),
 	INIT_CKEN("I2CCLK", I2C, 31949000, 0, &pxa_device_i2c.dev),
 
@@ -145,7 +193,10 @@
 	INIT_CKEN("FICPCLK", FICP, 47923000, 0, NULL),
 };
 
-static struct clk gpio7_clk = INIT_CKOTHER("GPIO7_CK", &pxa25x_clks[4], NULL);
+static struct clk pxa2xx_clk_aliases[] = {
+	INIT_CKOTHER("GPIO7_CLK", &pxa25x_clks[4], NULL),
+	INIT_CKOTHER("SA1111_CLK", &pxa25x_clks[5], NULL),
+};
 
 #ifdef CONFIG_PM
 
@@ -293,7 +344,7 @@
 	int i, ret = 0;
 
 	/* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
-	if (cpu_is_pxa25x())
+	if (cpu_is_pxa255())
 		clks_register(&pxa25x_hwuart_clk, 1);
 
 	if (cpu_is_pxa21x() || cpu_is_pxa25x()) {
@@ -317,10 +368,10 @@
 	}
 
 	/* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
-	if (cpu_is_pxa25x())
+	if (cpu_is_pxa255())
 		ret = platform_device_register(&pxa_device_hwuart);
 
-	clks_register(&gpio7_clk, 1);
+	clks_register(pxa2xx_clk_aliases, ARRAY_SIZE(pxa2xx_clk_aliases));
 
 	return ret;
 }
diff --git a/arch/arm/mach-pxa/pxa300.c b/arch/arm/mach-pxa/pxa300.c
index 0a0d387..da92e97 100644
--- a/arch/arm/mach-pxa/pxa300.c
+++ b/arch/arm/mach-pxa/pxa300.c
@@ -15,10 +15,16 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/platform_device.h>
 
 #include <asm/hardware.h>
+#include <asm/arch/pxa3xx-regs.h>
 #include <asm/arch/mfp-pxa300.h>
 
+#include "generic.h"
+#include "devices.h"
+#include "clock.h"
+
 static struct pxa3xx_mfp_addr_map pxa300_mfp_addr_map[] __initdata = {
 
 	MFP_ADDR_X(GPIO0,   GPIO2,   0x00b4),
@@ -79,15 +85,26 @@
 	MFP_ADDR_END,
 };
 
+static struct clk common_clks[] = {
+	PXA3xx_CKEN("NANDCLK", NAND, 156000000, 0, &pxa3xx_device_nand.dev),
+};
+
+static struct clk pxa310_clks[] = {
+	PXA3xx_CKEN("MMCCLK", MMC3, 19500000, 0, &pxa3xx_device_mci3.dev),
+};
+
 static int __init pxa300_init(void)
 {
 	if (cpu_is_pxa300() || cpu_is_pxa310()) {
 		pxa3xx_init_mfp();
 		pxa3xx_mfp_init_addr(pxa300_mfp_addr_map);
+		clks_register(ARRAY_AND_SIZE(common_clks));
 	}
 
-	if (cpu_is_pxa310())
+	if (cpu_is_pxa310()) {
 		pxa3xx_mfp_init_addr(pxa310_mfp_addr_map);
+		clks_register(ARRAY_AND_SIZE(pxa310_clks));
+	}
 
 	return 0;
 }
diff --git a/arch/arm/mach-pxa/pxa320.c b/arch/arm/mach-pxa/pxa320.c
index 74128eb..c557c23 100644
--- a/arch/arm/mach-pxa/pxa320.c
+++ b/arch/arm/mach-pxa/pxa320.c
@@ -15,11 +15,17 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/platform_device.h>
 
 #include <asm/hardware.h>
 #include <asm/arch/mfp.h>
+#include <asm/arch/pxa3xx-regs.h>
 #include <asm/arch/mfp-pxa320.h>
 
+#include "generic.h"
+#include "devices.h"
+#include "clock.h"
+
 static struct pxa3xx_mfp_addr_map pxa320_mfp_addr_map[] __initdata = {
 
 	MFP_ADDR_X(GPIO0,  GPIO4,   0x0124),
@@ -74,16 +80,17 @@
 	MFP_ADDR_END,
 };
 
-static void __init pxa320_init_mfp(void)
-{
-	pxa3xx_init_mfp();
-	pxa3xx_mfp_init_addr(pxa320_mfp_addr_map);
-}
+static struct clk pxa320_clks[] = {
+	PXA3xx_CKEN("NANDCLK", NAND, 104000000, 0, &pxa3xx_device_nand.dev),
+};
 
 static int __init pxa320_init(void)
 {
-	if (cpu_is_pxa320())
-		pxa320_init_mfp();
+	if (cpu_is_pxa320()) {
+		pxa3xx_init_mfp();
+		pxa3xx_mfp_init_addr(pxa320_mfp_addr_map);
+		clks_register(ARRAY_AND_SIZE(pxa320_clks));
+	}
 
 	return 0;
 }
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 15685d2..f491025 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -144,7 +144,7 @@
 	return hsio_clk;
 }
 
-static void clk_pxa3xx_cken_enable(struct clk *clk)
+void clk_pxa3xx_cken_enable(struct clk *clk)
 {
 	unsigned long mask = 1ul << (clk->cken & 0x1f);
 
@@ -154,7 +154,7 @@
 		CKENB |= mask;
 }
 
-static void clk_pxa3xx_cken_disable(struct clk *clk)
+void clk_pxa3xx_cken_disable(struct clk *clk)
 {
 	unsigned long mask = 1ul << (clk->cken & 0x1f);
 
@@ -164,7 +164,7 @@
 		CKENB &= ~mask;
 }
 
-static const struct clkops clk_pxa3xx_cken_ops = {
+const struct clkops clk_pxa3xx_cken_ops = {
 	.enable		= clk_pxa3xx_cken_enable,
 	.disable	= clk_pxa3xx_cken_disable,
 };
@@ -196,24 +196,6 @@
 	.disable	= clk_pout_disable,
 };
 
-#define PXA3xx_CKEN(_name, _cken, _rate, _delay, _dev)	\
-	{						\
-		.name	= _name,			\
-		.dev	= _dev,				\
-		.ops	= &clk_pxa3xx_cken_ops,		\
-		.rate	= _rate,			\
-		.cken	= CKEN_##_cken,			\
-		.delay	= _delay,			\
-	}
-
-#define PXA3xx_CK(_name, _cken, _ops, _dev)		\
-	{						\
-		.name	= _name,			\
-		.dev	= _dev,				\
-		.ops	= _ops,				\
-		.cken	= CKEN_##_cken,			\
-	}
-
 static struct clk pxa3xx_clks[] = {
 	{
 		.name           = "CLK_POUT",
@@ -244,7 +226,6 @@
 
 	PXA3xx_CKEN("MMCCLK", MMC1, 19500000, 0, &pxa_device_mci.dev),
 	PXA3xx_CKEN("MMCCLK", MMC2, 19500000, 0, &pxa3xx_device_mci2.dev),
-	PXA3xx_CKEN("MMCCLK", MMC3, 19500000, 0, &pxa3xx_device_mci3.dev),
 };
 
 #ifdef CONFIG_PM
diff --git a/arch/arm/mach-pxa/pxa930.c b/arch/arm/mach-pxa/pxa930.c
new file mode 100644
index 0000000..9503897
--- /dev/null
+++ b/arch/arm/mach-pxa/pxa930.c
@@ -0,0 +1,190 @@
+/*
+ * linux/arch/arm/mach-pxa/pxa930.c
+ *
+ * Code specific to PXA930
+ *
+ * Copyright (C) 2007-2008 Marvell Internation Ltd.
+ *
+ * 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/platform_device.h>
+#include <linux/irq.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/mfp-pxa930.h>
+
+static struct pxa3xx_mfp_addr_map pxa930_mfp_addr_map[] __initdata = {
+
+	MFP_ADDR(GPIO0, 0x02e0),
+	MFP_ADDR(GPIO1, 0x02dc),
+	MFP_ADDR(GPIO2, 0x02e8),
+	MFP_ADDR(GPIO3, 0x02d8),
+	MFP_ADDR(GPIO4, 0x02e4),
+	MFP_ADDR(GPIO5, 0x02ec),
+	MFP_ADDR(GPIO6, 0x02f8),
+	MFP_ADDR(GPIO7, 0x02fc),
+	MFP_ADDR(GPIO8, 0x0300),
+	MFP_ADDR(GPIO9, 0x02d4),
+	MFP_ADDR(GPIO10, 0x02f4),
+	MFP_ADDR(GPIO11, 0x02f0),
+	MFP_ADDR(GPIO12, 0x0304),
+	MFP_ADDR(GPIO13, 0x0310),
+	MFP_ADDR(GPIO14, 0x0308),
+	MFP_ADDR(GPIO15, 0x030c),
+	MFP_ADDR(GPIO16, 0x04e8),
+	MFP_ADDR(GPIO17, 0x04f4),
+	MFP_ADDR(GPIO18, 0x04f8),
+	MFP_ADDR(GPIO19, 0x04fc),
+	MFP_ADDR(GPIO20, 0x0518),
+	MFP_ADDR(GPIO21, 0x051c),
+	MFP_ADDR(GPIO22, 0x04ec),
+	MFP_ADDR(GPIO23, 0x0500),
+	MFP_ADDR(GPIO24, 0x04f0),
+	MFP_ADDR(GPIO25, 0x0504),
+	MFP_ADDR(GPIO26, 0x0510),
+	MFP_ADDR(GPIO27, 0x0514),
+	MFP_ADDR(GPIO28, 0x0520),
+	MFP_ADDR(GPIO29, 0x0600),
+	MFP_ADDR(GPIO30, 0x0618),
+	MFP_ADDR(GPIO31, 0x0610),
+	MFP_ADDR(GPIO32, 0x060c),
+	MFP_ADDR(GPIO33, 0x061c),
+	MFP_ADDR(GPIO34, 0x0620),
+	MFP_ADDR(GPIO35, 0x0628),
+	MFP_ADDR(GPIO36, 0x062c),
+	MFP_ADDR(GPIO37, 0x0630),
+	MFP_ADDR(GPIO38, 0x0634),
+	MFP_ADDR(GPIO39, 0x0638),
+	MFP_ADDR(GPIO40, 0x063c),
+	MFP_ADDR(GPIO41, 0x0614),
+	MFP_ADDR(GPIO42, 0x0624),
+	MFP_ADDR(GPIO43, 0x0608),
+	MFP_ADDR(GPIO44, 0x0604),
+	MFP_ADDR(GPIO45, 0x050c),
+	MFP_ADDR(GPIO46, 0x0508),
+	MFP_ADDR(GPIO47, 0x02bc),
+	MFP_ADDR(GPIO48, 0x02b4),
+	MFP_ADDR(GPIO49, 0x02b8),
+	MFP_ADDR(GPIO50, 0x02c8),
+	MFP_ADDR(GPIO51, 0x02c0),
+	MFP_ADDR(GPIO52, 0x02c4),
+	MFP_ADDR(GPIO53, 0x02d0),
+	MFP_ADDR(GPIO54, 0x02cc),
+	MFP_ADDR(GPIO55, 0x029c),
+	MFP_ADDR(GPIO56, 0x02a0),
+	MFP_ADDR(GPIO57, 0x0294),
+	MFP_ADDR(GPIO58, 0x0298),
+	MFP_ADDR(GPIO59, 0x02a4),
+	MFP_ADDR(GPIO60, 0x02a8),
+	MFP_ADDR(GPIO61, 0x02b0),
+	MFP_ADDR(GPIO62, 0x02ac),
+	MFP_ADDR(GPIO63, 0x0640),
+	MFP_ADDR(GPIO64, 0x065c),
+	MFP_ADDR(GPIO65, 0x0648),
+	MFP_ADDR(GPIO66, 0x0644),
+	MFP_ADDR(GPIO67, 0x0674),
+	MFP_ADDR(GPIO68, 0x0658),
+	MFP_ADDR(GPIO69, 0x0654),
+	MFP_ADDR(GPIO70, 0x0660),
+	MFP_ADDR(GPIO71, 0x0668),
+	MFP_ADDR(GPIO72, 0x0664),
+	MFP_ADDR(GPIO73, 0x0650),
+	MFP_ADDR(GPIO74, 0x066c),
+	MFP_ADDR(GPIO75, 0x064c),
+	MFP_ADDR(GPIO76, 0x0670),
+	MFP_ADDR(GPIO77, 0x0678),
+	MFP_ADDR(GPIO78, 0x067c),
+	MFP_ADDR(GPIO79, 0x0694),
+	MFP_ADDR(GPIO80, 0x069c),
+	MFP_ADDR(GPIO81, 0x06a0),
+	MFP_ADDR(GPIO82, 0x06a4),
+	MFP_ADDR(GPIO83, 0x0698),
+	MFP_ADDR(GPIO84, 0x06bc),
+	MFP_ADDR(GPIO85, 0x06b4),
+	MFP_ADDR(GPIO86, 0x06b0),
+	MFP_ADDR(GPIO87, 0x06c0),
+	MFP_ADDR(GPIO88, 0x06c4),
+	MFP_ADDR(GPIO89, 0x06ac),
+	MFP_ADDR(GPIO90, 0x0680),
+	MFP_ADDR(GPIO91, 0x0684),
+	MFP_ADDR(GPIO92, 0x0688),
+	MFP_ADDR(GPIO93, 0x0690),
+	MFP_ADDR(GPIO94, 0x068c),
+	MFP_ADDR(GPIO95, 0x06a8),
+	MFP_ADDR(GPIO96, 0x06b8),
+	MFP_ADDR(GPIO97, 0x0410),
+	MFP_ADDR(GPIO98, 0x0418),
+	MFP_ADDR(GPIO99, 0x041c),
+	MFP_ADDR(GPIO100, 0x0414),
+	MFP_ADDR(GPIO101, 0x0408),
+	MFP_ADDR(GPIO102, 0x0324),
+	MFP_ADDR(GPIO103, 0x040c),
+	MFP_ADDR(GPIO104, 0x0400),
+	MFP_ADDR(GPIO105, 0x0328),
+	MFP_ADDR(GPIO106, 0x0404),
+
+	MFP_ADDR(nXCVREN, 0x0204),
+	MFP_ADDR(DF_CLE_nOE, 0x020c),
+	MFP_ADDR(DF_nADV1_ALE, 0x0218),
+	MFP_ADDR(DF_SCLK_E, 0x0214),
+	MFP_ADDR(DF_SCLK_S, 0x0210),
+	MFP_ADDR(nBE0, 0x021c),
+	MFP_ADDR(nBE1, 0x0220),
+	MFP_ADDR(DF_nADV2_ALE, 0x0224),
+	MFP_ADDR(DF_INT_RnB, 0x0228),
+	MFP_ADDR(DF_nCS0, 0x022c),
+	MFP_ADDR(DF_nCS1, 0x0230),
+	MFP_ADDR(nLUA, 0x0254),
+	MFP_ADDR(nLLA, 0x0258),
+	MFP_ADDR(DF_nWE, 0x0234),
+	MFP_ADDR(DF_nRE_nOE, 0x0238),
+	MFP_ADDR(DF_ADDR0, 0x024c),
+	MFP_ADDR(DF_ADDR1, 0x0250),
+	MFP_ADDR(DF_ADDR2, 0x025c),
+	MFP_ADDR(DF_ADDR3, 0x0260),
+	MFP_ADDR(DF_IO0, 0x023c),
+	MFP_ADDR(DF_IO1, 0x0240),
+	MFP_ADDR(DF_IO2, 0x0244),
+	MFP_ADDR(DF_IO3, 0x0248),
+	MFP_ADDR(DF_IO4, 0x0264),
+	MFP_ADDR(DF_IO5, 0x0268),
+	MFP_ADDR(DF_IO6, 0x026c),
+	MFP_ADDR(DF_IO7, 0x0270),
+	MFP_ADDR(DF_IO8, 0x0274),
+	MFP_ADDR(DF_IO9, 0x0278),
+	MFP_ADDR(DF_IO10, 0x027c),
+	MFP_ADDR(DF_IO11, 0x0280),
+	MFP_ADDR(DF_IO12, 0x0284),
+	MFP_ADDR(DF_IO13, 0x0288),
+	MFP_ADDR(DF_IO14, 0x028c),
+	MFP_ADDR(DF_IO15, 0x0290),
+
+	MFP_ADDR(GSIM_UIO, 0x0314),
+	MFP_ADDR(GSIM_UCLK, 0x0318),
+	MFP_ADDR(GSIM_UDET, 0x031c),
+	MFP_ADDR(GSIM_nURST, 0x0320),
+
+	MFP_ADDR(PMIC_INT, 0x06c8),
+
+	MFP_ADDR(RDY, 0x0200),
+
+	MFP_ADDR_END,
+};
+
+static int __init pxa930_init(void)
+{
+	if (cpu_is_pxa930()) {
+		pxa3xx_init_mfp();
+		pxa3xx_mfp_init_addr(pxa930_mfp_addr_map);
+	}
+
+	return 0;
+}
+
+core_initcall(pxa930_init);
diff --git a/arch/arm/mach-pxa/reset.c b/arch/arm/mach-pxa/reset.c
new file mode 100644
index 0000000..9d39dea
--- /dev/null
+++ b/arch/arm/mach-pxa/reset.c
@@ -0,0 +1,96 @@
+/*
+ * 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/module.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <asm/io.h>
+#include <asm/proc-fns.h>
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pxa2xx-regs.h>
+
+static void do_hw_reset(void);
+
+static int reset_gpio = -1;
+
+int init_gpio_reset(int gpio)
+{
+	int rc;
+
+	rc = gpio_request(gpio, "reset generator");
+	if (rc) {
+		printk(KERN_ERR "Can't request reset_gpio\n");
+		goto out;
+	}
+
+	rc = gpio_direction_input(gpio);
+	if (rc) {
+		printk(KERN_ERR "Can't configure reset_gpio for input\n");
+		gpio_free(gpio);
+		goto out;
+	}
+
+out:
+	if (!rc)
+		reset_gpio = gpio;
+
+	return rc;
+}
+
+/*
+ * Trigger GPIO reset.
+ * This covers various types of logic connecting gpio pin
+ * to RESET pins (nRESET or GPIO_RESET):
+ */
+static void do_gpio_reset(void)
+{
+	BUG_ON(reset_gpio == -1);
+
+	/* drive it low */
+	gpio_direction_output(reset_gpio, 0);
+	mdelay(2);
+	/* rising edge or drive high */
+	gpio_set_value(reset_gpio, 1);
+	mdelay(2);
+	/* falling edge */
+	gpio_set_value(reset_gpio, 0);
+
+	/* give it some time */
+	mdelay(10);
+
+	WARN_ON(1);
+	/* fallback */
+	do_hw_reset();
+}
+
+static void do_hw_reset(void)
+{
+	/* Initialize the watchdog and let it fire */
+	OWER = OWER_WME;
+	OSSR = OSSR_M3;
+	OSMR3 = OSCR + 368640;	/* ... in 100 ms */
+}
+
+void arch_reset(char mode)
+{
+	if (cpu_is_pxa2xx())
+		RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
+
+	switch (mode) {
+	case 's':
+		/* Jump into ROM at address 0 */
+		cpu_reset(0);
+		break;
+	case 'h':
+		do_hw_reset();
+		break;
+	case 'g':
+		do_gpio_reset();
+		break;
+	}
+}
+
diff --git a/arch/arm/mach-pxa/saar.c b/arch/arm/mach-pxa/saar.c
new file mode 100644
index 0000000..d02bc6f
--- /dev/null
+++ b/arch/arm/mach-pxa/saar.c
@@ -0,0 +1,84 @@
+/*
+ *  linux/arch/arm/mach-pxa/saar.c
+ *
+ *  Support for the Marvell PXA930 Handheld Platform (aka SAAR)
+ *
+ *  Copyright (C) 2007-2008 Marvell International Ltd.
+ *
+ *  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
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/smc91x.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/hardware.h>
+#include <asm/arch/pxa3xx-regs.h>
+#include <asm/arch/mfp-pxa930.h>
+
+#include "devices.h"
+#include "generic.h"
+
+/* SAAR MFP configurations */
+static mfp_cfg_t saar_mfp_cfg[] __initdata = {
+	/* Ethernet */
+	DF_nCS1_nCS3,
+	GPIO97_GPIO,
+};
+
+#define SAAR_ETH_PHYS	(0x14000000)
+
+static struct resource smc91x_resources[] = {
+	[0] = {
+		.start	= (SAAR_ETH_PHYS + 0x300),
+		.end	= (SAAR_ETH_PHYS + 0xfffff),
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO97)),
+		.end	= gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO97)),
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+	}
+};
+
+static struct smc91x_platdata saar_smc91x_info = {
+	.flags	= SMC91X_USE_16BIT | SMC91X_NOWAIT | SMC91X_USE_DMA,
+};
+
+static struct platform_device smc91x_device = {
+	.name		= "smc91x",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(smc91x_resources),
+	.resource	= smc91x_resources,
+	.dev		= {
+		.platform_data = &saar_smc91x_info,
+	},
+};
+
+static void __init saar_init(void)
+{
+	/* initialize MFP configurations */
+	pxa3xx_mfp_config(ARRAY_AND_SIZE(saar_mfp_cfg));
+
+	platform_device_register(&smc91x_device);
+}
+
+MACHINE_START(SAAR, "PXA930 Handheld Platform (aka SAAR)")
+	/* Maintainer: Eric Miao <eric.miao@marvell.com> */
+	.phys_io        = 0x40000000,
+	.boot_params    = 0xa0000100,
+	.io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.map_io         = pxa_map_io,
+	.init_irq       = pxa3xx_init_irq,
+	.timer          = &pxa_timer,
+	.init_machine   = saar_init,
+MACHINE_END
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index e7d0fcd..762249c 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -38,6 +38,7 @@
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/pxa2xx-regs.h>
 #include <asm/arch/pxa2xx-gpio.h>
+#include <asm/arch/pxa27x-udc.h>
 #include <asm/arch/irda.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/ohci.h>
@@ -450,6 +451,7 @@
 		set_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_IR_ON);
 	else
 		reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_IR_ON);
+	pxa2xx_transceiver_mode(dev, mode);
 }
 
 #ifdef CONFIG_MACH_AKITA
@@ -459,6 +461,7 @@
 		akita_set_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_IR_ON);
 	else
 		akita_reset_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_IR_ON);
+	pxa2xx_transceiver_mode(dev, mode);
 }
 #endif
 
@@ -529,11 +532,7 @@
 
 static void spitz_poweroff(void)
 {
-	pxa_gpio_mode(SPITZ_GPIO_ON_RESET | GPIO_OUT);
-	GPSR(SPITZ_GPIO_ON_RESET) = GPIO_bit(SPITZ_GPIO_ON_RESET);
-
-	mdelay(1000);
-	arm_machine_restart('h');
+	arm_machine_restart('g');
 }
 
 static void spitz_restart(char mode)
@@ -547,6 +546,7 @@
 
 static void __init common_init(void)
 {
+	init_gpio_reset(SPITZ_GPIO_ON_RESET);
 	pm_power_off = spitz_poweroff;
 	arm_pm_restart = spitz_restart;
 
diff --git a/arch/arm/mach-pxa/ssp.c b/arch/arm/mach-pxa/ssp.c
index 0bb3198..89f3868 100644
--- a/arch/arm/mach-pxa/ssp.c
+++ b/arch/arm/mach-pxa/ssp.c
@@ -14,13 +14,6 @@
  *  IO-based SSP applications and allows easy port setup for DMA access.
  *
  *  Author: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
- *
- *  Revision history:
- *   22nd Aug 2003 Initial version.
- *   20th Dec 2004 Added ssp_config for changing port config without
- *                 closing the port.
- *    4th Aug 2005 Added option to disable irq handler registration and
- *                 cleaned up irq and clock detection.
  */
 
 #include <linux/module.h>
@@ -285,7 +278,7 @@
 			goto out_region;
 		dev->irq = ssp->irq;
 	} else
-		dev->irq = 0;
+		dev->irq = NO_IRQ;
 
 	/* turn on SSP port clock */
 	clk_enable(ssp->clk);
@@ -306,7 +299,8 @@
 	struct ssp_device *ssp = dev->ssp;
 
 	ssp_disable(dev);
-	free_irq(dev->irq, dev);
+	if (dev->irq != NO_IRQ)
+		free_irq(dev->irq, dev);
 	clk_disable(ssp->clk);
 	ssp_free(ssp);
 }
@@ -360,6 +354,7 @@
 		dev_err(&pdev->dev, "failed to allocate memory");
 		return -ENOMEM;
 	}
+	ssp->pdev = pdev;
 
 	ssp->clk = clk_get(&pdev->dev, "SSPCLK");
 	if (IS_ERR(ssp->clk)) {
diff --git a/arch/arm/mach-pxa/tavorevb.c b/arch/arm/mach-pxa/tavorevb.c
new file mode 100644
index 0000000..ac28350
--- /dev/null
+++ b/arch/arm/mach-pxa/tavorevb.c
@@ -0,0 +1,84 @@
+/*
+ *  linux/arch/arm/mach-pxa/tavorevb.c
+ *
+ *  Support for the Marvell PXA930 Evaluation Board
+ *
+ *  Copyright (C) 2007-2008 Marvell International Ltd.
+ *
+ *  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
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/smc91x.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/hardware.h>
+#include <asm/arch/pxa3xx-regs.h>
+#include <asm/arch/mfp-pxa930.h>
+
+#include "devices.h"
+#include "generic.h"
+
+/* Tavor EVB MFP configurations */
+static mfp_cfg_t tavorevb_mfp_cfg[] __initdata = {
+	/* Ethernet */
+	DF_nCS1_nCS3,
+	GPIO47_GPIO,
+};
+
+#define TAVOREVB_ETH_PHYS	(0x14000000)
+
+static struct resource smc91x_resources[] = {
+	[0] = {
+		.start	= (TAVOREVB_ETH_PHYS + 0x300),
+		.end	= (TAVOREVB_ETH_PHYS + 0xfffff),
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO47)),
+		.end	= gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO47)),
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+	}
+};
+
+static struct smc91x_platdata tavorevb_smc91x_info = {
+	.flags	= SMC91X_USE_16BIT | SMC91X_NOWAIT | SMC91X_USE_DMA,
+};
+
+static struct platform_device smc91x_device = {
+	.name		= "smc91x",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(smc91x_resources),
+	.resource	= smc91x_resources,
+	.dev		= {
+		.platform_data = &tavorevb_smc91x_info,
+	},
+};
+
+static void __init tavorevb_init(void)
+{
+	/* initialize MFP configurations */
+	pxa3xx_mfp_config(ARRAY_AND_SIZE(tavorevb_mfp_cfg));
+
+	platform_device_register(&smc91x_device);
+}
+
+MACHINE_START(TAVOREVB, "PXA930 Evaluation Board (aka TavorEVB)")
+	/* Maintainer: Eric Miao <eric.miao@marvell.com> */
+	.phys_io        = 0x40000000,
+	.boot_params    = 0xa0000100,
+	.io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
+	.map_io         = pxa_map_io,
+	.init_irq       = pxa3xx_init_irq,
+	.timer          = &pxa_timer,
+	.init_machine   = tavorevb_init,
+MACHINE_END
diff --git a/arch/arm/mach-pxa/tosa-bt.c b/arch/arm/mach-pxa/tosa-bt.c
new file mode 100644
index 0000000..7d85054
--- /dev/null
+++ b/arch/arm/mach-pxa/tosa-bt.c
@@ -0,0 +1,150 @@
+/*
+ * Bluetooth built-in chip control
+ *
+ * Copyright (c) 2008 Dmitry Baryshkov
+ *
+ * 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/module.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/rfkill.h>
+
+#include <asm/arch/tosa_bt.h>
+
+static void tosa_bt_on(struct tosa_bt_data *data)
+{
+	gpio_set_value(data->gpio_reset, 0);
+	gpio_set_value(data->gpio_pwr, 1);
+	gpio_set_value(data->gpio_reset, 1);
+	mdelay(20);
+	gpio_set_value(data->gpio_reset, 0);
+}
+
+static void tosa_bt_off(struct tosa_bt_data *data)
+{
+	gpio_set_value(data->gpio_reset, 1);
+	mdelay(10);
+	gpio_set_value(data->gpio_pwr, 0);
+	gpio_set_value(data->gpio_reset, 0);
+}
+
+static int tosa_bt_toggle_radio(void *data, enum rfkill_state state)
+{
+	pr_info("BT_RADIO going: %s\n",
+			state == RFKILL_STATE_ON ? "on" : "off");
+
+	if (state == RFKILL_STATE_ON) {
+		pr_info("TOSA_BT: going ON\n");
+		tosa_bt_on(data);
+	} else {
+		pr_info("TOSA_BT: going OFF\n");
+		tosa_bt_off(data);
+	}
+	return 0;
+}
+
+static int tosa_bt_probe(struct platform_device *dev)
+{
+	int rc;
+	struct rfkill *rfk;
+
+	struct tosa_bt_data *data = dev->dev.platform_data;
+
+	rc = gpio_request(data->gpio_reset, "Bluetooth reset");
+	if (rc)
+		goto err_reset;
+	rc = gpio_direction_output(data->gpio_reset, 0);
+	if (rc)
+		goto err_reset_dir;
+	rc = gpio_request(data->gpio_pwr, "Bluetooth power");
+	if (rc)
+		goto err_pwr;
+	rc = gpio_direction_output(data->gpio_pwr, 0);
+	if (rc)
+		goto err_pwr_dir;
+
+	rfk = rfkill_allocate(&dev->dev, RFKILL_TYPE_BLUETOOTH);
+	if (!rfk) {
+		rc = -ENOMEM;
+		goto err_rfk_alloc;
+	}
+
+	rfk->name = "tosa-bt";
+	rfk->toggle_radio = tosa_bt_toggle_radio;
+	rfk->data = data;
+#ifdef CONFIG_RFKILL_LEDS
+	rfk->led_trigger.name = "tosa-bt";
+#endif
+
+	rc = rfkill_register(rfk);
+	if (rc)
+		goto err_rfkill;
+
+	platform_set_drvdata(dev, rfk);
+
+	return 0;
+
+err_rfkill:
+	if (rfk)
+		rfkill_free(rfk);
+	rfk = NULL;
+err_rfk_alloc:
+	tosa_bt_off(data);
+err_pwr_dir:
+	gpio_free(data->gpio_pwr);
+err_pwr:
+err_reset_dir:
+	gpio_free(data->gpio_reset);
+err_reset:
+	return rc;
+}
+
+static int __devexit tosa_bt_remove(struct platform_device *dev)
+{
+	struct tosa_bt_data *data = dev->dev.platform_data;
+	struct rfkill *rfk = platform_get_drvdata(dev);
+
+	platform_set_drvdata(dev, NULL);
+
+	if (rfk)
+		rfkill_unregister(rfk);
+	rfk = NULL;
+
+	tosa_bt_off(data);
+
+	gpio_free(data->gpio_pwr);
+	gpio_free(data->gpio_reset);
+
+	return 0;
+}
+
+static struct platform_driver tosa_bt_driver = {
+	.probe = tosa_bt_probe,
+	.remove = __devexit_p(tosa_bt_remove),
+
+	.driver = {
+		.name = "tosa-bt",
+		.owner = THIS_MODULE,
+	},
+};
+
+
+static int __init tosa_bt_init(void)
+{
+	return platform_driver_register(&tosa_bt_driver);
+}
+
+static void __exit tosa_bt_exit(void)
+{
+	platform_driver_unregister(&tosa_bt_driver);
+}
+
+module_init(tosa_bt_init);
+module_exit(tosa_bt_exit);
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index ab4a9f5..fea17ce 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -18,30 +18,31 @@
 #include <linux/major.h>
 #include <linux/fs.h>
 #include <linux/interrupt.h>
-#include <linux/mmc/host.h>
-#include <linux/pm.h>
 #include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/mmc/host.h>
+#include <linux/mfd/tc6393xb.h>
+#include <linux/mfd/tmio.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/pm.h>
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
 #include <linux/gpio.h>
+#include <linux/pda_power.h>
+#include <linux/rfkill.h>
 
 #include <asm/setup.h>
-#include <asm/memory.h>
 #include <asm/mach-types.h>
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/arch/pxa-regs.h>
 #include <asm/arch/pxa2xx-regs.h>
 #include <asm/arch/mfp-pxa25x.h>
 #include <asm/arch/irda.h>
 #include <asm/arch/i2c.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/udc.h>
+#include <asm/arch/tosa_bt.h>
 
 #include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
 #include <asm/arch/tosa.h>
 
 #include <asm/hardware/scoop.h>
@@ -86,7 +87,7 @@
 	GPIO6_MMC_CLK,
 	GPIO8_MMC_CS0,
 	GPIO9_GPIO, /* Detect */
-	// GPIO10 nSD_INT
+	GPIO10_GPIO, /* nSD_INT */
 
 	/* CF */
 	GPIO13_GPIO, /* CD_IRQ */
@@ -124,34 +125,34 @@
 	GPIO44_BTUART_CTS,
 	GPIO45_BTUART_RTS,
 
-	/* IrDA */
-	GPIO46_STUART_RXD,
-	GPIO47_STUART_TXD,
-
 	/* Keybd */
-	GPIO58_GPIO,
-	GPIO59_GPIO,
-	GPIO60_GPIO,
-	GPIO61_GPIO,
-	GPIO62_GPIO,
-	GPIO63_GPIO,
-	GPIO64_GPIO,
-	GPIO65_GPIO,
-	GPIO66_GPIO,
-	GPIO67_GPIO,
-	GPIO68_GPIO,
-	GPIO69_GPIO,
-	GPIO70_GPIO,
-	GPIO71_GPIO,
-	GPIO72_GPIO,
-	GPIO73_GPIO,
-	GPIO74_GPIO,
-	GPIO75_GPIO,
+	GPIO58_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO59_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO60_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO61_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO62_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO63_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO64_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO65_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO66_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO67_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO68_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO69_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO70_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO71_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO72_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO73_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO74_GPIO | MFP_LPM_DRIVE_LOW,
+	GPIO75_GPIO | MFP_LPM_DRIVE_LOW,
 
 	/* SPI */
 	GPIO81_SSP2_CLK_OUT,
 	GPIO82_SSP2_FRM_OUT,
 	GPIO83_SSP2_TXD,
+
+	/* IrDA is managed in other way */
+	GPIO46_GPIO,
+	GPIO47_GPIO,
 };
 
 /*
@@ -249,6 +250,15 @@
 
 	tosa_mci_platform_data.detect_delay = msecs_to_jiffies(250);
 
+	err = gpio_request(TOSA_GPIO_nSD_DETECT, "MMC/SD card detect");
+	if (err) {
+		printk(KERN_ERR "tosa_mci_init: can't request nSD_DETECT gpio\n");
+		goto err_gpio_detect;
+	}
+	err = gpio_direction_input(TOSA_GPIO_nSD_DETECT);
+	if (err)
+		goto err_gpio_detect_dir;
+
 	err = request_irq(TOSA_IRQ_GPIO_nSD_DETECT, tosa_detect_int,
 			  IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 				"MMC/SD card detect", data);
@@ -257,7 +267,7 @@
 		goto err_irq;
 	}
 
-	err = gpio_request(TOSA_GPIO_SD_WP, "sd_wp");
+	err = gpio_request(TOSA_GPIO_SD_WP, "SD Write Protect");
 	if (err) {
 		printk(KERN_ERR "tosa_mci_init: can't request SD_WP gpio\n");
 		goto err_gpio_wp;
@@ -266,7 +276,7 @@
 	if (err)
 		goto err_gpio_wp_dir;
 
-	err = gpio_request(TOSA_GPIO_PWR_ON, "sd_pwr");
+	err = gpio_request(TOSA_GPIO_PWR_ON, "SD Power");
 	if (err) {
 		printk(KERN_ERR "tosa_mci_init: can't request SD_PWR gpio\n");
 		goto err_gpio_pwr;
@@ -275,8 +285,20 @@
 	if (err)
 		goto err_gpio_pwr_dir;
 
+	err = gpio_request(TOSA_GPIO_nSD_INT, "SD Int");
+	if (err) {
+		printk(KERN_ERR "tosa_mci_init: can't request SD_PWR gpio\n");
+		goto err_gpio_int;
+	}
+	err = gpio_direction_input(TOSA_GPIO_nSD_INT);
+	if (err)
+		goto err_gpio_int_dir;
+
 	return 0;
 
+err_gpio_int_dir:
+	gpio_free(TOSA_GPIO_nSD_INT);
+err_gpio_int:
 err_gpio_pwr_dir:
 	gpio_free(TOSA_GPIO_PWR_ON);
 err_gpio_pwr:
@@ -285,6 +307,9 @@
 err_gpio_wp:
 	free_irq(TOSA_IRQ_GPIO_nSD_DETECT, data);
 err_irq:
+err_gpio_detect_dir:
+	gpio_free(TOSA_GPIO_nSD_DETECT);
+err_gpio_detect:
 	return err;
 }
 
@@ -306,9 +331,11 @@
 
 static void tosa_mci_exit(struct device *dev, void *data)
 {
+	gpio_free(TOSA_GPIO_nSD_INT);
 	gpio_free(TOSA_GPIO_PWR_ON);
 	gpio_free(TOSA_GPIO_SD_WP);
 	free_irq(TOSA_IRQ_GPIO_nSD_DETECT, data);
+	gpio_free(TOSA_GPIO_nSD_DETECT);
 }
 
 static struct pxamci_platform_data tosa_mci_platform_data = {
@@ -322,29 +349,55 @@
 /*
  * Irda
  */
+static void tosa_irda_transceiver_mode(struct device *dev, int mode)
+{
+	if (mode & IR_OFF) {
+		gpio_set_value(TOSA_GPIO_IR_POWERDWN, 0);
+		pxa2xx_transceiver_mode(dev, mode);
+		gpio_direction_output(TOSA_GPIO_IRDA_TX, 0);
+	} else {
+		pxa2xx_transceiver_mode(dev, mode);
+		gpio_set_value(TOSA_GPIO_IR_POWERDWN, 1);
+	}
+}
+
 static int tosa_irda_startup(struct device *dev)
 {
 	int ret;
 
+	ret = gpio_request(TOSA_GPIO_IRDA_TX, "IrDA TX");
+	if (ret)
+		goto err_tx;
+	ret = gpio_direction_output(TOSA_GPIO_IRDA_TX, 0);
+	if (ret)
+		goto err_tx_dir;
+
 	ret = gpio_request(TOSA_GPIO_IR_POWERDWN, "IrDA powerdown");
 	if (ret)
-		return ret;
+		goto err_pwr;
 
 	ret = gpio_direction_output(TOSA_GPIO_IR_POWERDWN, 0);
 	if (ret)
-		gpio_free(TOSA_GPIO_IR_POWERDWN);
+		goto err_pwr_dir;
 
+	tosa_irda_transceiver_mode(dev, IR_SIRMODE | IR_OFF);
+
+	return 0;
+
+err_pwr_dir:
+	gpio_free(TOSA_GPIO_IR_POWERDWN);
+err_pwr:
+err_tx_dir:
+	gpio_free(TOSA_GPIO_IRDA_TX);
+err_tx:
 	return ret;
-	}
+}
 
 static void tosa_irda_shutdown(struct device *dev)
 {
+	tosa_irda_transceiver_mode(dev, IR_SIRMODE | IR_OFF);
 	gpio_free(TOSA_GPIO_IR_POWERDWN);
-}
-
-static void tosa_irda_transceiver_mode(struct device *dev, int mode)
-{
-	gpio_set_value(TOSA_GPIO_IR_POWERDWN, !(mode & IR_OFF));
+	gpio_free(TOSA_GPIO_IRDA_TX);
 }
 
 static struct pxaficp_platform_data tosa_ficp_platform_data = {
@@ -355,6 +408,70 @@
 };
 
 /*
+ * Tosa AC IN
+ */
+static int tosa_power_init(struct device *dev)
+{
+	int ret = gpio_request(TOSA_GPIO_AC_IN, "ac in");
+	if (ret)
+		goto err_gpio_req;
+
+	ret = gpio_direction_input(TOSA_GPIO_AC_IN);
+	if (ret)
+		goto err_gpio_in;
+
+	return 0;
+
+err_gpio_in:
+	gpio_free(TOSA_GPIO_AC_IN);
+err_gpio_req:
+	return ret;
+}
+
+static void tosa_power_exit(struct device *dev)
+{
+	gpio_free(TOSA_GPIO_AC_IN);
+}
+
+static int tosa_power_ac_online(void)
+{
+	return gpio_get_value(TOSA_GPIO_AC_IN) == 0;
+}
+
+static char *tosa_ac_supplied_to[] = {
+	"main-battery",
+	"backup-battery",
+	"jacket-battery",
+};
+
+static struct pda_power_pdata tosa_power_data = {
+	.init			= tosa_power_init,
+	.is_ac_online		= tosa_power_ac_online,
+	.exit			= tosa_power_exit,
+	.supplied_to		= tosa_ac_supplied_to,
+	.num_supplicants	= ARRAY_SIZE(tosa_ac_supplied_to),
+};
+
+static struct resource tosa_power_resource[] = {
+	{
+		.name		= "ac",
+		.start		= gpio_to_irq(TOSA_GPIO_AC_IN),
+		.end		= gpio_to_irq(TOSA_GPIO_AC_IN),
+		.flags		= IORESOURCE_IRQ |
+				  IORESOURCE_IRQ_HIGHEDGE |
+				  IORESOURCE_IRQ_LOWEDGE,
+	},
+};
+
+static struct platform_device tosa_power_device = {
+	.name			= "pda-power",
+	.id			= -1,
+	.dev.platform_data	= &tosa_power_data,
+	.resource		= tosa_power_resource,
+	.num_resources		= ARRAY_SIZE(tosa_power_resource),
+};
+
+/*
  * Tosa Keyboard
  */
 static struct platform_device tosakbd_device = {
@@ -439,7 +556,7 @@
 	},
 	{
 		.name			= "tosa:blue:bluetooth",
-		.default_trigger	= "none",
+		.default_trigger	= "tosa-bt",
 		.gpio			= TOSA_GPIO_BT_LED,
 	},
 };
@@ -457,21 +574,184 @@
 	},
 };
 
+/*
+ * Toshiba Mobile IO Controller
+ */
+static struct resource tc6393xb_resources[] = {
+	[0] = {
+		.start	= TOSA_LCDC_PHYS,
+		.end	= TOSA_LCDC_PHYS + 0x3ffffff,
+		.flags	= IORESOURCE_MEM,
+	},
+
+	[1] = {
+		.start	= TOSA_IRQ_GPIO_TC6393XB_INT,
+		.end	= TOSA_IRQ_GPIO_TC6393XB_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+
+static int tosa_tc6393xb_enable(struct platform_device *dev)
+{
+	int rc;
+
+	rc = gpio_request(TOSA_GPIO_TC6393XB_REST_IN, "tc6393xb #pclr");
+	if (rc)
+		goto err_req_pclr;
+	rc = gpio_request(TOSA_GPIO_TC6393XB_SUSPEND, "tc6393xb #suspend");
+	if (rc)
+		goto err_req_suspend;
+	rc = gpio_request(TOSA_GPIO_TC6393XB_L3V_ON, "l3v");
+	if (rc)
+		goto err_req_l3v;
+	rc = gpio_direction_output(TOSA_GPIO_TC6393XB_L3V_ON, 0);
+	if (rc)
+		goto err_dir_l3v;
+	rc = gpio_direction_output(TOSA_GPIO_TC6393XB_SUSPEND, 0);
+	if (rc)
+		goto err_dir_suspend;
+	rc = gpio_direction_output(TOSA_GPIO_TC6393XB_REST_IN, 0);
+	if (rc)
+		goto err_dir_pclr;
+
+	mdelay(1);
+
+	gpio_set_value(TOSA_GPIO_TC6393XB_SUSPEND, 1);
+
+	mdelay(10);
+
+	gpio_set_value(TOSA_GPIO_TC6393XB_REST_IN, 1);
+	gpio_set_value(TOSA_GPIO_TC6393XB_L3V_ON, 1);
+
+	return 0;
+err_dir_pclr:
+err_dir_suspend:
+err_dir_l3v:
+	gpio_free(TOSA_GPIO_TC6393XB_L3V_ON);
+err_req_l3v:
+	gpio_free(TOSA_GPIO_TC6393XB_SUSPEND);
+err_req_suspend:
+	gpio_free(TOSA_GPIO_TC6393XB_REST_IN);
+err_req_pclr:
+	return rc;
+}
+
+static int tosa_tc6393xb_disable(struct platform_device *dev)
+{
+	gpio_free(TOSA_GPIO_TC6393XB_L3V_ON);
+	gpio_free(TOSA_GPIO_TC6393XB_SUSPEND);
+	gpio_free(TOSA_GPIO_TC6393XB_REST_IN);
+
+	return 0;
+}
+
+static int tosa_tc6393xb_resume(struct platform_device *dev)
+{
+	gpio_set_value(TOSA_GPIO_TC6393XB_SUSPEND, 1);
+	mdelay(10);
+	gpio_set_value(TOSA_GPIO_TC6393XB_L3V_ON, 1);
+	mdelay(10);
+
+	return 0;
+}
+
+static int tosa_tc6393xb_suspend(struct platform_device *dev)
+{
+	gpio_set_value(TOSA_GPIO_TC6393XB_L3V_ON, 0);
+	gpio_set_value(TOSA_GPIO_TC6393XB_SUSPEND, 0);
+	return 0;
+}
+
+static struct mtd_partition tosa_nand_partition[] = {
+	{
+		.name	= "smf",
+		.offset	= 0,
+		.size	= 7 * 1024 * 1024,
+	},
+	{
+		.name	= "root",
+		.offset	= MTDPART_OFS_APPEND,
+		.size	= 28 * 1024 * 1024,
+	},
+	{
+		.name	= "home",
+		.offset	= MTDPART_OFS_APPEND,
+		.size	= MTDPART_SIZ_FULL,
+	},
+};
+
+static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
+
+static struct nand_bbt_descr tosa_tc6393xb_nand_bbt = {
+	.options	= 0,
+	.offs		= 4,
+	.len		= 2,
+	.pattern	= scan_ff_pattern
+};
+
+static struct tmio_nand_data tosa_tc6393xb_nand_config = {
+	.num_partitions	= ARRAY_SIZE(tosa_nand_partition),
+	.partition	= tosa_nand_partition,
+	.badblock_pattern = &tosa_tc6393xb_nand_bbt,
+};
+
+static struct tc6393xb_platform_data tosa_tc6393xb_setup = {
+	.scr_pll2cr	= 0x0cc1,
+	.scr_gper	= 0x3300,
+	.scr_gpo_dsr	=
+		TOSA_TC6393XB_GPIO_BIT(TOSA_GPIO_CARD_VCC_ON),
+	.scr_gpo_doecr	=
+		TOSA_TC6393XB_GPIO_BIT(TOSA_GPIO_CARD_VCC_ON),
+
+	.irq_base	= IRQ_BOARD_START,
+	.gpio_base	= TOSA_TC6393XB_GPIO_BASE,
+
+	.enable		= tosa_tc6393xb_enable,
+	.disable	= tosa_tc6393xb_disable,
+	.suspend	= tosa_tc6393xb_suspend,
+	.resume		= tosa_tc6393xb_resume,
+
+	.nand_data	= &tosa_tc6393xb_nand_config,
+};
+
+
+static struct platform_device tc6393xb_device = {
+	.name	= "tc6393xb",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &tosa_tc6393xb_setup,
+	},
+	.num_resources	= ARRAY_SIZE(tc6393xb_resources),
+	.resource	= tc6393xb_resources,
+};
+
+static struct tosa_bt_data tosa_bt_data = {
+	.gpio_pwr	= TOSA_GPIO_BT_PWR_EN,
+	.gpio_reset	= TOSA_GPIO_BT_RESET,
+};
+
+static struct platform_device tosa_bt_device = {
+	.name	= "tosa-bt",
+	.id	= -1,
+	.dev.platform_data = &tosa_bt_data,
+};
+
+
 static struct platform_device *devices[] __initdata = {
 	&tosascoop_device,
 	&tosascoop_jc_device,
+	&tc6393xb_device,
+	&tosa_power_device,
 	&tosakbd_device,
 	&tosa_gpio_keys_device,
 	&tosaled_device,
+	&tosa_bt_device,
 };
 
 static void tosa_poweroff(void)
 {
-	gpio_direction_output(TOSA_GPIO_ON_RESET, 0);
-	gpio_set_value(TOSA_GPIO_ON_RESET, 1);
-
-	mdelay(1000);
-	arm_machine_restart('h');
+	arm_machine_restart('g');
 }
 
 static void tosa_restart(char mode)
@@ -485,10 +765,14 @@
 
 static void __init tosa_init(void)
 {
+	int dummy;
+
 	pxa2xx_mfp_config(ARRAY_AND_SIZE(tosa_pin_config));
 	gpio_set_wake(MFP_PIN_GPIO1, 1);
 	/* We can't pass to gpio-keys since it will drop the Reset altfunc */
 
+	init_gpio_reset(TOSA_GPIO_ON_RESET);
+
 	pm_power_off = tosa_poweroff;
 	arm_pm_restart = tosa_restart;
 
@@ -497,6 +781,10 @@
 	/* enable batt_fault */
 	PMCR = 0x01;
 
+	dummy = gpiochip_reserve(TOSA_SCOOP_GPIO_BASE, 12);
+	dummy = gpiochip_reserve(TOSA_SCOOP_JC_GPIO_BASE, 12);
+	dummy = gpiochip_reserve(TOSA_TC6393XB_GPIO_BASE, 16);
+
 	pxa_set_mci_info(&tosa_mci_platform_data);
 	pxa_set_udc_info(&udc_info);
 	pxa_set_ficp_info(&tosa_ficp_platform_data);
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index 61e2440..dee7bf3 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -254,6 +254,7 @@
 		/* Fast mode */
 		trizeps_conxs_ircr |= ConXS_IRCR_MODE;
 	}
+	pxa2xx_transceiver_mode(dev, mode);
 	if (mode & IR_OFF) {
 		trizeps_conxs_ircr |= ConXS_IRCR_SD;
 	} else {
diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
index 66b446c..8fca6d8 100644
--- a/arch/arm/mach-pxa/zylonite.c
+++ b/arch/arm/mach-pxa/zylonite.c
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/pwm_backlight.h>
+#include <linux/smc91x.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -29,6 +30,7 @@
 #include <asm/arch/zylonite.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/pxa27x_keypad.h>
+#include <asm/arch/pxa3xx_nand.h>
 
 #include "devices.h"
 #include "generic.h"
@@ -37,6 +39,8 @@
 struct platform_mmc_slot zylonite_mmc_slot[MAX_SLOTS];
 
 int gpio_eth_irq;
+int gpio_debug_led1;
+int gpio_debug_led2;
 
 int wm9713_irq;
 
@@ -56,13 +60,57 @@
 	}
 };
 
+static struct smc91x_platdata zylonite_smc91x_info = {
+	.flags	= SMC91X_USE_8BIT | SMC91X_USE_16BIT |
+		  SMC91X_NOWAIT | SMC91X_USE_DMA,
+};
+
 static struct platform_device smc91x_device = {
 	.name		= "smc91x",
 	.id		= 0,
 	.num_resources	= ARRAY_SIZE(smc91x_resources),
 	.resource	= smc91x_resources,
+	.dev		= {
+		.platform_data = &zylonite_smc91x_info,
+	},
 };
 
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+static struct gpio_led zylonite_debug_leds[] = {
+	[0] = {
+		.name			= "zylonite:yellow:1",
+		.default_trigger	= "heartbeat",
+	},
+	[1] = {
+		.name			= "zylonite:yellow:2",
+		.default_trigger	= "default-on",
+	},
+};
+
+static struct gpio_led_platform_data zylonite_debug_leds_info = {
+	.leds		= zylonite_debug_leds,
+	.num_leds	= ARRAY_SIZE(zylonite_debug_leds),
+};
+
+static struct platform_device zylonite_device_leds = {
+	.name		= "leds-gpio",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &zylonite_debug_leds_info,
+	}
+};
+
+static void __init zylonite_init_leds(void)
+{
+	zylonite_debug_leds[0].gpio = gpio_debug_led1;
+	zylonite_debug_leds[1].gpio = gpio_debug_led2;
+
+	platform_device_register(&zylonite_device_leds);
+}
+#else
+static inline void zylonite_init_leds(void) {}
+#endif
+
 #if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
 static struct platform_pwm_backlight_data zylonite_backlight_data = {
 	.pwm_id		= 3,
@@ -259,7 +307,7 @@
 static inline void zylonite_init_mmc(void) {}
 #endif
 
-#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULES)
+#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE)
 static unsigned int zylonite_matrix_key_map[] = {
 	/* KEY(row, col, key_code) */
 	KEY(0, 0, KEY_A), KEY(0, 1, KEY_B), KEY(0, 2, KEY_C), KEY(0, 5, KEY_D),
@@ -324,6 +372,57 @@
 static inline void zylonite_init_keypad(void) {}
 #endif
 
+#if defined(CONFIG_MTD_NAND_PXA3xx) || defined(CONFIG_MTD_NAND_PXA3xx_MODULE)
+static struct mtd_partition zylonite_nand_partitions[] = {
+	[0] = {
+		.name        = "Bootloader",
+		.offset      = 0,
+		.size        = 0x060000,
+		.mask_flags  = MTD_WRITEABLE, /* force read-only */
+	},
+	[1] = {
+		.name        = "Kernel",
+		.offset      = 0x060000,
+		.size        = 0x200000,
+		.mask_flags  = MTD_WRITEABLE, /* force read-only */
+	},
+	[2] = {
+		.name        = "Filesystem",
+		.offset      = 0x0260000,
+		.size        = 0x3000000,     /* 48M - rootfs */
+	},
+	[3] = {
+		.name        = "MassStorage",
+		.offset      = 0x3260000,
+		.size        = 0x3d40000,
+	},
+	[4] = {
+		.name        = "BBT",
+		.offset      = 0x6FA0000,
+		.size        = 0x80000,
+		.mask_flags  = MTD_WRITEABLE,  /* force read-only */
+	},
+	/* NOTE: we reserve some blocks at the end of the NAND flash for
+	 * bad block management, and the max number of relocation blocks
+	 * differs on different platforms. Please take care with it when
+	 * defining the partition table.
+	 */
+};
+
+static struct pxa3xx_nand_platform_data zylonite_nand_info = {
+	.enable_arbiter	= 1,
+	.parts		= zylonite_nand_partitions,
+	.nr_parts	= ARRAY_SIZE(zylonite_nand_partitions),
+};
+
+static void __init zylonite_init_nand(void)
+{
+	pxa3xx_set_nand_info(&zylonite_nand_info);
+}
+#else
+static inline void zylonite_init_nand(void) {}
+#endif /* CONFIG_MTD_NAND_PXA3xx || CONFIG_MTD_NAND_PXA3xx_MODULE */
+
 static void __init zylonite_init(void)
 {
 	/* board-processor specific initialization */
@@ -342,6 +441,8 @@
 	zylonite_init_lcd();
 	zylonite_init_mmc();
 	zylonite_init_keypad();
+	zylonite_init_nand();
+	zylonite_init_leds();
 }
 
 MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
diff --git a/arch/arm/mach-pxa/zylonite_pxa300.c b/arch/arm/mach-pxa/zylonite_pxa300.c
index 6f7ae97..b28d46e 100644
--- a/arch/arm/mach-pxa/zylonite_pxa300.c
+++ b/arch/arm/mach-pxa/zylonite_pxa300.c
@@ -16,9 +16,12 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pca953x.h>
 
 #include <asm/gpio.h>
 #include <asm/arch/mfp-pxa300.h>
+#include <asm/arch/i2c.h>
 #include <asm/arch/zylonite.h>
 
 #include "generic.h"
@@ -109,6 +112,10 @@
 	GPIO12_MMC2_DAT3,
 	GPIO13_MMC2_CLK,
 	GPIO14_MMC2_CMD,
+
+	/* Standard I2C */
+	GPIO21_I2C_SCL,
+	GPIO22_I2C_SDA,
 };
 
 static mfp_cfg_t pxa300_mfp_cfg[] __initdata = {
@@ -192,6 +199,39 @@
 		pxa3xx_mfp_write(lcd_detect_pins[i], mfpr_save[i]);
 }
 
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static struct pca953x_platform_data gpio_exp[] = {
+	[0] = {
+		.gpio_base	= 128,
+	},
+	[1] = {
+		.gpio_base	= 144,
+	},
+};
+
+struct i2c_board_info zylonite_i2c_board_info[] = {
+	{
+		.type		= "pca9539",
+		.addr		= 0x74,
+		.platform_data	= &gpio_exp[0],
+		.irq		= IRQ_GPIO(18),
+	}, {
+		.type		= "pca9539",
+		.addr		= 0x75,
+		.platform_data	= &gpio_exp[1],
+		.irq		= IRQ_GPIO(19),
+	},
+};
+
+static void __init zylonite_init_i2c(void)
+{
+	pxa_set_i2c_info(NULL);
+	i2c_register_board_info(0, ARRAY_AND_SIZE(zylonite_i2c_board_info));
+}
+#else
+static inline void zylonite_init_i2c(void) {}
+#endif
+
 void __init zylonite_pxa300_init(void)
 {
 	if (cpu_is_pxa300() || cpu_is_pxa310()) {
@@ -207,6 +247,8 @@
 
 		/* WM9713 IRQ */
 		wm9713_irq = mfp_to_gpio(MFP_PIN_GPIO26);
+
+		zylonite_init_i2c();
 	}
 
 	if (cpu_is_pxa300()) {
@@ -222,4 +264,8 @@
 		zylonite_mmc_slot[2].gpio_cd = EXT_GPIO(30);
 		zylonite_mmc_slot[2].gpio_wp = EXT_GPIO(31);
 	}
+
+	/* GPIOs for Debug LEDs */
+	gpio_debug_led1 = EXT_GPIO(25);
+	gpio_debug_led2 = EXT_GPIO(26);
 }
diff --git a/arch/arm/mach-pxa/zylonite_pxa320.c b/arch/arm/mach-pxa/zylonite_pxa320.c
index 2b4fc34..2b7fba7 100644
--- a/arch/arm/mach-pxa/zylonite_pxa320.c
+++ b/arch/arm/mach-pxa/zylonite_pxa320.c
@@ -116,6 +116,10 @@
 	GPIO27_MMC2_DAT3,
 	GPIO28_MMC2_CLK,
 	GPIO29_MMC2_CMD,
+
+	/* Debug LEDs */
+	GPIO1_2_GPIO | MFP_LPM_DRIVE_HIGH,
+	GPIO4_2_GPIO | MFP_LPM_DRIVE_HIGH,
 };
 
 #define NUM_LCD_DETECT_PINS	7
@@ -189,6 +193,8 @@
 
 		/* GPIO pin assignment */
 		gpio_eth_irq	= mfp_to_gpio(MFP_PIN_GPIO9);
+		gpio_debug_led1	= mfp_to_gpio(MFP_PIN_GPIO1_2);
+		gpio_debug_led2	= mfp_to_gpio(MFP_PIN_GPIO4_2);
 
 		/* MMC card detect & write protect for controller 0 */
 		zylonite_mmc_slot[0].gpio_cd  = mfp_to_gpio(MFP_PIN_GPIO1);
diff --git a/arch/arm/mach-sa1100/clock.c b/arch/arm/mach-sa1100/clock.c
index fc97fe5..b5809c5 100644
--- a/arch/arm/mach-sa1100/clock.c
+++ b/arch/arm/mach-sa1100/clock.c
@@ -103,7 +103,7 @@
 }
 
 static struct clk clk_gpio27 = {
-	.name		= "GPIO27_CLK",
+	.name		= "SA1111_CLK",
 	.rate		= 3686400,
 	.enable		= clk_gpio27_enable,
 	.disable	= clk_gpio27_disable,
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index f64b925..2e27a8c 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -76,3 +76,5 @@
 
 obj-$(CONFIG_CACHE_FEROCEON_L2)	+= cache-feroceon-l2.o
 obj-$(CONFIG_CACHE_L2X0)	+= cache-l2x0.o
+obj-$(CONFIG_CACHE_XSC3L2)	+= cache-xsc3l2.o
+
diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c
index 6f33f58..ff1413e 100644
--- a/arch/arm/plat-omap/mailbox.c
+++ b/arch/arm/plat-omap/mailbox.c
@@ -334,7 +334,7 @@
 	}
 
 	mbox->dev.class = &omap_mbox_class;
-	strlcpy(mbox->dev.bus_id, mbox->name, KOBJ_NAME_LEN);
+	dev_set_name(&mbox->dev, "%s", mbox->name);
 	dev_set_drvdata(&mbox->dev, mbox);
 
 	ret = device_register(&mbox->dev);
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 0be5630..8b8f564 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 Jul 7 16:25:39 2008
+# Last update: Sun Jul 13 12:04:05 2008
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -1812,3 +1812,11 @@
 ks8695_softplc		MACH_KS8695_SOFTPLC	KS8695_SOFTPLC		1822
 gprisc4			MACH_GPRISC4		GPRISC4			1823
 stamp9260		MACH_STAMP9260		STAMP9260		1824
+smdk6430		MACH_SMDK6430		SMDK6430		1825
+smdkc100		MACH_SMDKC100		SMDKC100		1826
+tavorevb		MACH_TAVOREVB		TAVOREVB		1827
+saar			MACH_SAAR		SAAR			1828
+deister_eyecam		MACH_DEISTER_EYECAM	DEISTER_EYECAM		1829
+at91sam9m10ek		MACH_AT91SAM9M10EK	AT91SAM9M10EK		1830
+linkstation_produo	MACH_LINKSTATION_PRODUO	LINKSTATION_PRODUO	1831
+hit_b0			MACH_HIT_B0		HIT_B0			1832
diff --git a/arch/avr32/kernel/cpu.c b/arch/avr32/kernel/cpu.c
index b8409ca..e84faff 100644
--- a/arch/avr32/kernel/cpu.c
+++ b/arch/avr32/kernel/cpu.c
@@ -26,14 +26,16 @@
  * XXX: If/when a SMP-capable implementation of AVR32 will ever be
  * made, we must make sure that the code executes on the correct CPU.
  */
-static ssize_t show_pc0event(struct sys_device *dev, char *buf)
+static ssize_t show_pc0event(struct sys_device *dev,
+			struct sysdev_attribute *attr, char *buf)
 {
 	unsigned long pccr;
 
 	pccr = sysreg_read(PCCR);
 	return sprintf(buf, "0x%lx\n", (pccr >> 12) & 0x3f);
 }
-static ssize_t store_pc0event(struct sys_device *dev, const char *buf,
+static ssize_t store_pc0event(struct sys_device *dev,
+			struct sysdev_attribute *attr, const char *buf,
 			      size_t count)
 {
 	unsigned long val;
@@ -46,15 +48,17 @@
 	sysreg_write(PCCR, val);
 	return count;
 }
-static ssize_t show_pc0count(struct sys_device *dev, char *buf)
+static ssize_t show_pc0count(struct sys_device *dev,
+			struct sysdev_attribute *attr, char *buf)
 {
 	unsigned long pcnt0;
 
 	pcnt0 = sysreg_read(PCNT0);
 	return sprintf(buf, "%lu\n", pcnt0);
 }
-static ssize_t store_pc0count(struct sys_device *dev, const char *buf,
-			      size_t count)
+static ssize_t store_pc0count(struct sys_device *dev,
+				struct sysdev_attribute *attr,
+				const char *buf, size_t count)
 {
 	unsigned long val;
 	char *endp;
@@ -67,14 +71,16 @@
 	return count;
 }
 
-static ssize_t show_pc1event(struct sys_device *dev, char *buf)
+static ssize_t show_pc1event(struct sys_device *dev,
+				struct sysdev_attribute *attr, char *buf)
 {
 	unsigned long pccr;
 
 	pccr = sysreg_read(PCCR);
 	return sprintf(buf, "0x%lx\n", (pccr >> 18) & 0x3f);
 }
-static ssize_t store_pc1event(struct sys_device *dev, const char *buf,
+static ssize_t store_pc1event(struct sys_device *dev,
+			      struct sysdev_attribute *attr, const char *buf,
 			      size_t count)
 {
 	unsigned long val;
@@ -87,14 +93,16 @@
 	sysreg_write(PCCR, val);
 	return count;
 }
-static ssize_t show_pc1count(struct sys_device *dev, char *buf)
+static ssize_t show_pc1count(struct sys_device *dev,
+				struct sysdev_attribute *attr, char *buf)
 {
 	unsigned long pcnt1;
 
 	pcnt1 = sysreg_read(PCNT1);
 	return sprintf(buf, "%lu\n", pcnt1);
 }
-static ssize_t store_pc1count(struct sys_device *dev, const char *buf,
+static ssize_t store_pc1count(struct sys_device *dev,
+				struct sysdev_attribute *attr, const char *buf,
 			      size_t count)
 {
 	unsigned long val;
@@ -108,14 +116,16 @@
 	return count;
 }
 
-static ssize_t show_pccycles(struct sys_device *dev, char *buf)
+static ssize_t show_pccycles(struct sys_device *dev,
+				struct sysdev_attribute *attr, char *buf)
 {
 	unsigned long pccnt;
 
 	pccnt = sysreg_read(PCCNT);
 	return sprintf(buf, "%lu\n", pccnt);
 }
-static ssize_t store_pccycles(struct sys_device *dev, const char *buf,
+static ssize_t store_pccycles(struct sys_device *dev,
+				struct sysdev_attribute *attr, const char *buf,
 			      size_t count)
 {
 	unsigned long val;
@@ -129,14 +139,16 @@
 	return count;
 }
 
-static ssize_t show_pcenable(struct sys_device *dev, char *buf)
+static ssize_t show_pcenable(struct sys_device *dev,
+			struct sysdev_attribute *attr, char *buf)
 {
 	unsigned long pccr;
 
 	pccr = sysreg_read(PCCR);
 	return sprintf(buf, "%c\n", (pccr & 1)?'1':'0');
 }
-static ssize_t store_pcenable(struct sys_device *dev, const char *buf,
+static ssize_t store_pcenable(struct sys_device *dev,
+			      struct sysdev_attribute *attr, const char *buf,
 			      size_t count)
 {
 	unsigned long pccr, val;
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c
index 021d512..604f44f 100644
--- a/arch/avr32/mach-at32ap/at32ap700x.c
+++ b/arch/avr32/mach-at32ap/at32ap700x.c
@@ -7,6 +7,7 @@
  */
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/dw_dmac.h>
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -594,6 +595,17 @@
 	clk->parent = parent;
 }
 
+static struct dw_dma_platform_data dw_dmac0_data = {
+	.nr_channels	= 3,
+};
+
+static struct resource dw_dmac0_resource[] = {
+	PBMEM(0xff200000),
+	IRQ(2),
+};
+DEFINE_DEV_DATA(dw_dmac, 0);
+DEV_CLK(hclk, dw_dmac0, hsb, 10);
+
 /* --------------------------------------------------------------------
  *  System peripherals
  * -------------------------------------------------------------------- */
@@ -708,17 +720,6 @@
 	.users		= 1,
 };
 
-static struct resource dmaca0_resource[] = {
-	{
-		.start	= 0xff200000,
-		.end	= 0xff20ffff,
-		.flags	= IORESOURCE_MEM,
-	},
-	IRQ(2),
-};
-DEFINE_DEV(dmaca, 0);
-DEV_CLK(hclk, dmaca0, hsb, 10);
-
 /* --------------------------------------------------------------------
  * HMATRIX
  * -------------------------------------------------------------------- */
@@ -831,7 +832,7 @@
 	platform_device_register(&at32_eic0_device);
 	platform_device_register(&smc0_device);
 	platform_device_register(&pdc_device);
-	platform_device_register(&dmaca0_device);
+	platform_device_register(&dw_dmac0_device);
 
 	platform_device_register(&at32_tcb0_device);
 	platform_device_register(&at32_tcb1_device);
@@ -2032,7 +2033,7 @@
 	&smc0_mck,
 	&pdc_hclk,
 	&pdc_pclk,
-	&dmaca0_hclk,
+	&dw_dmac0_hclk,
 	&pico_clk,
 	&pio0_mck,
 	&pio1_mck,
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index b87634e..b83b8ef 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -873,8 +873,8 @@
 	  plugged into slots found on all modern laptop computers.  Another
 	  example, used on modern desktops as well as laptops, is USB.
 
-	  Enable HOTPLUG and KMOD, and build a modular kernel.  Get agent
-	  software (at <http://linux-hotplug.sourceforge.net/>) and install it.
+	  Enable HOTPLUG and build a modular kernel.  Get agent software
+	  (from <http://linux-hotplug.sourceforge.net/>) and install it.
 	  Then your kernel will automatically call out to a user mode "policy
 	  agent" (/sbin/hotplug) to load modules and set up software needed
 	  to use devices as you hotplug them.
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 18bcc10..451f2ff 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -540,8 +540,8 @@
 	  strongly in flux, so no good recommendation can be made.
 
 config CRASH_DUMP
-	  bool "kernel crash dumps (EXPERIMENTAL)"
-	  depends on EXPERIMENTAL && IA64_MCA_RECOVERY && !IA64_HP_SIM && (!SMP || HOTPLUG_CPU)
+	  bool "kernel crash dumps"
+	  depends on IA64_MCA_RECOVERY && !IA64_HP_SIM && (!SMP || HOTPLUG_CPU)
 	  help
 	    Generate crash dump after being started by kexec.
 
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile
index e67ee3f..905d25b 100644
--- a/arch/ia64/Makefile
+++ b/arch/ia64/Makefile
@@ -100,3 +100,9 @@
   echo '  boot		- Build vmlinux and bootloader for Ski simulator'
   echo '* unwcheck	- Check vmlinux for invalid unwind info'
 endef
+
+archprepare: make_nr_irqs_h FORCE
+PHONY += make_nr_irqs_h FORCE
+
+make_nr_irqs_h: FORCE
+	$(Q)$(MAKE) $(build)=arch/ia64/kernel include/asm-ia64/nr-irqs.h
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index 13fd10e..87fea11 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -36,6 +36,8 @@
 mca_recovery-y			+= mca_drv.o mca_drv_asm.o
 obj-$(CONFIG_IA64_MC_ERR_INJECT)+= err_inject.o
 
+obj-$(CONFIG_PARAVIRT)		+= paravirt.o paravirtentry.o
+
 obj-$(CONFIG_IA64_ESI)		+= esi.o
 ifneq ($(CONFIG_IA64_ESI),)
 obj-y				+= esi_stub.o	# must be in kernel proper
@@ -70,3 +72,45 @@
 # We must build gate.so before we can assemble it.
 # Note: kbuild does not track this dependency due to usage of .incbin
 $(obj)/gate-data.o: $(obj)/gate.so
+
+# Calculate NR_IRQ = max(IA64_NATIVE_NR_IRQS, XEN_NR_IRQS, ...) based on config
+define sed-y
+	"/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}"
+endef
+quiet_cmd_nr_irqs = GEN     $@
+define cmd_nr_irqs
+	(set -e; \
+	 echo "#ifndef __ASM_NR_IRQS_H__"; \
+	 echo "#define __ASM_NR_IRQS_H__"; \
+	 echo "/*"; \
+	 echo " * DO NOT MODIFY."; \
+	 echo " *"; \
+	 echo " * This file was generated by Kbuild"; \
+	 echo " *"; \
+	 echo " */"; \
+	 echo ""; \
+	 sed -ne $(sed-y) $<; \
+	 echo ""; \
+	 echo "#endif" ) > $@
+endef
+
+# We use internal kbuild rules to avoid the "is up to date" message from make
+arch/$(SRCARCH)/kernel/nr-irqs.s: $(srctree)/arch/$(SRCARCH)/kernel/nr-irqs.c \
+				$(wildcard $(srctree)/include/asm-ia64/*/irq.h)
+	$(Q)mkdir -p $(dir $@)
+	$(call if_changed_dep,cc_s_c)
+
+include/asm-ia64/nr-irqs.h: arch/$(SRCARCH)/kernel/nr-irqs.s
+	$(Q)mkdir -p $(dir $@)
+	$(call cmd,nr_irqs)
+
+clean-files += $(objtree)/include/asm-ia64/nr-irqs.h
+
+#
+# native ivt.S and entry.S
+#
+ASM_PARAVIRT_OBJS = ivt.o entry.o
+define paravirtualized_native
+AFLAGS_$(1) += -D__IA64_ASM_PARAVIRTUALIZED_NATIVE
+endef
+$(foreach obj,$(ASM_PARAVIRT_OBJS),$(eval $(call paravirtualized_native,$(obj))))
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 43687cc..5d1eb7e 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -774,7 +774,7 @@
  */
 #ifdef CONFIG_ACPI_HOTPLUG_CPU
 static
-int acpi_map_cpu2node(acpi_handle handle, int cpu, long physid)
+int acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
 {
 #ifdef CONFIG_ACPI_NUMA
 	int pxm_id;
@@ -854,8 +854,7 @@
 	union acpi_object *obj;
 	struct acpi_madt_local_sapic *lsapic;
 	cpumask_t tmp_map;
-	long physid;
-	int cpu;
+	int cpu, physid;
 
 	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
 		return -EINVAL;
diff --git a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
index b8498ea..7b43545 100644
--- a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
+++ b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
@@ -51,7 +51,7 @@
 	retval = ia64_pal_set_pstate((u64)value);
 
 	if (retval) {
-		dprintk("Failed to set freq to 0x%x, with error 0x%x\n",
+		dprintk("Failed to set freq to 0x%x, with error 0x%lx\n",
 		        value, retval);
 		return -ENODEV;
 	}
@@ -74,7 +74,7 @@
 
 	if (retval)
 		dprintk("Failed to get current freq with "
-		        "error 0x%x, idx 0x%x\n", retval, *value);
+			"error 0x%lx, idx 0x%x\n", retval, *value);
 
 	return (int)retval;
 }
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index ca2bb95..56ab156 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -23,6 +23,11 @@
  * 11/07/2000
  */
 /*
+ * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *                    pv_ops.
+ */
+/*
  * Global (preserved) predicate usage on syscall entry/exit path:
  *
  *	pKStk:		See entry.h.
@@ -45,6 +50,7 @@
 
 #include "minstate.h"
 
+#ifdef __IA64_ASM_PARAVIRTUALIZED_NATIVE
 	/*
 	 * execve() is special because in case of success, we need to
 	 * setup a null register window frame.
@@ -173,6 +179,7 @@
 	mov rp=loc0
 	br.ret.sptk.many rp
 END(sys_clone)
+#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
 
 /*
  * prev_task <- ia64_switch_to(struct task_struct *next)
@@ -180,7 +187,7 @@
  *	called.  The code starting at .map relies on this.  The rest of the code
  *	doesn't care about the interrupt masking status.
  */
-GLOBAL_ENTRY(ia64_switch_to)
+GLOBAL_ENTRY(__paravirt_switch_to)
 	.prologue
 	alloc r16=ar.pfs,1,0,0,0
 	DO_SAVE_SWITCH_STACK
@@ -204,7 +211,7 @@
 	;;
 .done:
 	ld8 sp=[r21]			// load kernel stack pointer of new task
-	mov IA64_KR(CURRENT)=in0	// update "current" application register
+	MOV_TO_KR(CURRENT, in0, r8, r9)		// update "current" application register
 	mov r8=r13			// return pointer to previously running task
 	mov r13=in0			// set "current" pointer
 	;;
@@ -216,26 +223,25 @@
 	br.ret.sptk.many rp		// boogie on out in new context
 
 .map:
-	rsm psr.ic			// interrupts (psr.i) are already disabled here
+	RSM_PSR_IC(r25)			// interrupts (psr.i) are already disabled here
 	movl r25=PAGE_KERNEL
 	;;
 	srlz.d
 	or r23=r25,r20			// construct PA | page properties
 	mov r25=IA64_GRANULE_SHIFT<<2
 	;;
-	mov cr.itir=r25
-	mov cr.ifa=in0			// VA of next task...
+	MOV_TO_ITIR(p0, r25, r8)
+	MOV_TO_IFA(in0, r8)		// VA of next task...
 	;;
 	mov r25=IA64_TR_CURRENT_STACK
-	mov IA64_KR(CURRENT_STACK)=r26	// remember last page we mapped...
+	MOV_TO_KR(CURRENT_STACK, r26, r8, r9)	// remember last page we mapped...
 	;;
 	itr.d dtr[r25]=r23		// wire in new mapping...
-	ssm psr.ic			// reenable the psr.ic bit
-	;;
-	srlz.d
+	SSM_PSR_IC_AND_SRLZ_D(r8, r9)	// reenable the psr.ic bit
 	br.cond.sptk .done
-END(ia64_switch_to)
+END(__paravirt_switch_to)
 
+#ifdef __IA64_ASM_PARAVIRTUALIZED_NATIVE
 /*
  * Note that interrupts are enabled during save_switch_stack and load_switch_stack.  This
  * means that we may get an interrupt with "sp" pointing to the new kernel stack while
@@ -375,7 +381,7 @@
  *	- b7 holds address to return to
  *	- must not touch r8-r11
  */
-ENTRY(load_switch_stack)
+GLOBAL_ENTRY(load_switch_stack)
 	.prologue
 	.altrp b7
 
@@ -571,7 +577,7 @@
 .ret3:
 (pUStk)	cmp.eq.unc p6,p0=r0,r0			// p6 <- pUStk
 (pUStk)	rsm psr.i				// disable interrupts
-	br.cond.sptk .work_pending_syscall_end
+	br.cond.sptk ia64_work_pending_syscall_end
 
 strace_error:
 	ld8 r3=[r2]				// load pt_regs.r8
@@ -636,8 +642,17 @@
 	adds r2=PT(R8)+16,sp			// r2 = &pt_regs.r8
 	mov r10=r0				// clear error indication in r10
 (p7)	br.cond.spnt handle_syscall_error	// handle potential syscall failure
+#ifdef CONFIG_PARAVIRT
+	;;
+	br.cond.sptk.few ia64_leave_syscall
+	;;
+#endif /* CONFIG_PARAVIRT */
 END(ia64_ret_from_syscall)
+#ifndef CONFIG_PARAVIRT
 	// fall through
+#endif
+#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
+
 /*
  * ia64_leave_syscall(): Same as ia64_leave_kernel, except that it doesn't
  *	need to switch to bank 0 and doesn't restore the scratch registers.
@@ -682,7 +697,7 @@
  *	      ar.csd: cleared
  *	      ar.ssd: cleared
  */
-ENTRY(ia64_leave_syscall)
+GLOBAL_ENTRY(__paravirt_leave_syscall)
 	PT_REGS_UNWIND_INFO(0)
 	/*
 	 * work.need_resched etc. mustn't get changed by this CPU before it returns to
@@ -692,11 +707,11 @@
 	 * extra work.  We always check for extra work when returning to user-level.
 	 * With CONFIG_PREEMPT, we also check for extra work when the preempt_count
 	 * is 0.  After extra work processing has been completed, execution
-	 * resumes at .work_processed_syscall with p6 set to 1 if the extra-work-check
+	 * resumes at ia64_work_processed_syscall with p6 set to 1 if the extra-work-check
 	 * needs to be redone.
 	 */
 #ifdef CONFIG_PREEMPT
-	rsm psr.i				// disable interrupts
+	RSM_PSR_I(p0, r2, r18)			// disable interrupts
 	cmp.eq pLvSys,p0=r0,r0			// pLvSys=1: leave from syscall
 (pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
 	;;
@@ -706,11 +721,12 @@
 	;;
 	cmp.eq p6,p0=r21,r0		// p6 <- pUStk || (preempt_count == 0)
 #else /* !CONFIG_PREEMPT */
-(pUStk)	rsm psr.i
+	RSM_PSR_I(pUStk, r2, r18)
 	cmp.eq pLvSys,p0=r0,r0		// pLvSys=1: leave from syscall
 (pUStk)	cmp.eq.unc p6,p0=r0,r0		// p6 <- pUStk
 #endif
-.work_processed_syscall:
+.global __paravirt_work_processed_syscall;
+__paravirt_work_processed_syscall:
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	adds r2=PT(LOADRS)+16,r12
 (pUStk)	mov.m r22=ar.itc			// fetch time at leave
@@ -744,7 +760,7 @@
 (pNonSys) break 0		//      bug check: we shouldn't be here if pNonSys is TRUE!
 	;;
 	invala			// M0|1 invalidate ALAT
-	rsm psr.i | psr.ic	// M2   turn off interrupts and interruption collection
+	RSM_PSR_I_IC(r28, r29, r30)	// M2   turn off interrupts and interruption collection
 	cmp.eq p9,p0=r0,r0	// A    set p9 to indicate that we should restore cr.ifs
 
 	ld8 r29=[r2],16		// M0|1 load cr.ipsr
@@ -765,7 +781,7 @@
 	;;
 #endif
 	ld8 r26=[r2],PT(B0)-PT(AR_PFS)	// M0|1 load ar.pfs
-(pKStk)	mov r22=psr			// M2   read PSR now that interrupts are disabled
+	MOV_FROM_PSR(pKStk, r22, r21)	// M2   read PSR now that interrupts are disabled
 	nop 0
 	;;
 	ld8 r21=[r2],PT(AR_RNAT)-PT(B0) // M0|1 load b0
@@ -798,7 +814,7 @@
 
 	srlz.d				// M0   ensure interruption collection is off (for cover)
 	shr.u r18=r19,16		// I0|1 get byte size of existing "dirty" partition
-	cover				// B    add current frame into dirty partition & set cr.ifs
+	COVER				// B    add current frame into dirty partition & set cr.ifs
 	;;
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	mov r19=ar.bsp			// M2   get new backing store pointer
@@ -823,8 +839,9 @@
 	mov.m ar.ssd=r0			// M2   clear ar.ssd
 	mov f11=f0			// F    clear f11
 	br.cond.sptk.many rbs_switch	// B
-END(ia64_leave_syscall)
+END(__paravirt_leave_syscall)
 
+#ifdef __IA64_ASM_PARAVIRTUALIZED_NATIVE
 #ifdef CONFIG_IA32_SUPPORT
 GLOBAL_ENTRY(ia64_ret_from_ia32_execve)
 	PT_REGS_UNWIND_INFO(0)
@@ -835,10 +852,20 @@
 	st8.spill [r2]=r8	// store return value in slot for r8 and set unat bit
 	.mem.offset 8,0
 	st8.spill [r3]=r0	// clear error indication in slot for r10 and set unat bit
+#ifdef CONFIG_PARAVIRT
+	;;
+	// don't fall through, ia64_leave_kernel may be #define'd
+	br.cond.sptk.few ia64_leave_kernel
+	;;
+#endif /* CONFIG_PARAVIRT */
 END(ia64_ret_from_ia32_execve)
+#ifndef CONFIG_PARAVIRT
 	// fall through
+#endif
 #endif /* CONFIG_IA32_SUPPORT */
-GLOBAL_ENTRY(ia64_leave_kernel)
+#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
+
+GLOBAL_ENTRY(__paravirt_leave_kernel)
 	PT_REGS_UNWIND_INFO(0)
 	/*
 	 * work.need_resched etc. mustn't get changed by this CPU before it returns to
@@ -852,7 +879,7 @@
 	 * needs to be redone.
 	 */
 #ifdef CONFIG_PREEMPT
-	rsm psr.i				// disable interrupts
+	RSM_PSR_I(p0, r17, r31)			// disable interrupts
 	cmp.eq p0,pLvSys=r0,r0			// pLvSys=0: leave from kernel
 (pKStk)	adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
 	;;
@@ -862,7 +889,7 @@
 	;;
 	cmp.eq p6,p0=r21,r0		// p6 <- pUStk || (preempt_count == 0)
 #else
-(pUStk)	rsm psr.i
+	RSM_PSR_I(pUStk, r17, r31)
 	cmp.eq p0,pLvSys=r0,r0		// pLvSys=0: leave from kernel
 (pUStk)	cmp.eq.unc p6,p0=r0,r0		// p6 <- pUStk
 #endif
@@ -910,7 +937,7 @@
 	mov ar.csd=r30
 	mov ar.ssd=r31
 	;;
-	rsm psr.i | psr.ic	// initiate turning off of interrupt and interruption collection
+	RSM_PSR_I_IC(r23, r22, r25)	// initiate turning off of interrupt and interruption collection
 	invala			// invalidate ALAT
 	;;
 	ld8.fill r22=[r2],24
@@ -942,7 +969,7 @@
 	mov ar.ccv=r15
 	;;
 	ldf.fill f11=[r2]
-	bsw.0			// switch back to bank 0 (no stop bit required beforehand...)
+	BSW_0(r2, r3, r15)	// switch back to bank 0 (no stop bit required beforehand...)
 	;;
 (pUStk)	mov r18=IA64_KR(CURRENT)// M2 (12 cycle read latency)
 	adds r16=PT(CR_IPSR)+16,r12
@@ -950,12 +977,12 @@
 
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	.pred.rel.mutex pUStk,pKStk
-(pKStk)	mov r22=psr		// M2 read PSR now that interrupts are disabled
+	MOV_FROM_PSR(pKStk, r22, r29)	// M2 read PSR now that interrupts are disabled
 (pUStk)	mov.m r22=ar.itc	// M  fetch time at leave
 	nop.i 0
 	;;
 #else
-(pKStk)	mov r22=psr		// M2 read PSR now that interrupts are disabled
+	MOV_FROM_PSR(pKStk, r22, r29)	// M2 read PSR now that interrupts are disabled
 	nop.i 0
 	nop.i 0
 	;;
@@ -1027,7 +1054,7 @@
 	 * NOTE: alloc, loadrs, and cover can't be predicated.
 	 */
 (pNonSys) br.cond.dpnt dont_preserve_current_frame
-	cover				// add current frame into dirty partition and set cr.ifs
+	COVER				// add current frame into dirty partition and set cr.ifs
 	;;
 	mov r19=ar.bsp			// get new backing store pointer
 rbs_switch:
@@ -1130,16 +1157,16 @@
 (pKStk)	dep r29=r22,r29,21,1	// I0 update ipsr.pp with psr.pp
 (pLvSys)mov r16=r0		// A  clear r16 for leave_syscall, no-op otherwise
 	;;
-	mov cr.ipsr=r29		// M2
+	MOV_TO_IPSR(p0, r29, r25)	// M2
 	mov ar.pfs=r26		// I0
 (pLvSys)mov r17=r0		// A  clear r17 for leave_syscall, no-op otherwise
 
-(p9)	mov cr.ifs=r30		// M2
+	MOV_TO_IFS(p9, r30, r25)// M2
 	mov b0=r21		// I0
 (pLvSys)mov r18=r0		// A  clear r18 for leave_syscall, no-op otherwise
 
 	mov ar.fpsr=r20		// M2
-	mov cr.iip=r28		// M2
+	MOV_TO_IIP(r28, r25)	// M2
 	nop 0
 	;;
 (pUStk)	mov ar.rnat=r24		// M2 must happen with RSE in lazy mode
@@ -1148,7 +1175,7 @@
 
 	mov ar.rsc=r27		// M2
 	mov pr=r31,-1		// I0
-	rfi			// B
+	RFI			// B
 
 	/*
 	 * On entry:
@@ -1174,35 +1201,36 @@
 	;;
 (pKStk) st4 [r20]=r21
 #endif
-	ssm psr.i		// enable interrupts
+	SSM_PSR_I(p0, p6, r2)	// enable interrupts
 	br.call.spnt.many rp=schedule
 .ret9:	cmp.eq p6,p0=r0,r0	// p6 <- 1 (re-check)
-	rsm psr.i		// disable interrupts
+	RSM_PSR_I(p0, r2, r20)	// disable interrupts
 	;;
 #ifdef CONFIG_PREEMPT
 (pKStk)	adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
 	;;
 (pKStk)	st4 [r20]=r0		// preempt_count() <- 0
 #endif
-(pLvSys)br.cond.sptk.few  .work_pending_syscall_end
+(pLvSys)br.cond.sptk.few  __paravirt_pending_syscall_end
 	br.cond.sptk.many .work_processed_kernel
 
 .notify:
 (pUStk)	br.call.spnt.many rp=notify_resume_user
 .ret10:	cmp.ne p6,p0=r0,r0	// p6 <- 0 (don't re-check)
-(pLvSys)br.cond.sptk.few  .work_pending_syscall_end
+(pLvSys)br.cond.sptk.few  __paravirt_pending_syscall_end
 	br.cond.sptk.many .work_processed_kernel
 
-.work_pending_syscall_end:
+.global __paravirt_pending_syscall_end;
+__paravirt_pending_syscall_end:
 	adds r2=PT(R8)+16,r12
 	adds r3=PT(R10)+16,r12
 	;;
 	ld8 r8=[r2]
 	ld8 r10=[r3]
-	br.cond.sptk.many .work_processed_syscall
+	br.cond.sptk.many __paravirt_work_processed_syscall_target
+END(__paravirt_leave_kernel)
 
-END(ia64_leave_kernel)
-
+#ifdef __IA64_ASM_PARAVIRTUALIZED_NATIVE
 ENTRY(handle_syscall_error)
 	/*
 	 * Some system calls (e.g., ptrace, mmap) can return arbitrary values which could
@@ -1244,7 +1272,7 @@
 	 * We declare 8 input registers so the system call args get preserved,
 	 * in case we need to restart a system call.
 	 */
-ENTRY(notify_resume_user)
+GLOBAL_ENTRY(notify_resume_user)
 	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
 	alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs in case of syscall restart!
 	mov r9=ar.unat
@@ -1306,7 +1334,7 @@
 	adds sp=16,sp
 	;;
 	ld8 r9=[sp]				// load new ar.unat
-	mov.sptk b7=r8,ia64_leave_kernel
+	mov.sptk b7=r8,ia64_native_leave_kernel
 	;;
 	mov ar.unat=r9
 	br.many b7
@@ -1665,3 +1693,4 @@
 	data8 sys_timerfd_gettime
 
 	.org sys_call_table + 8*NR_syscalls	// guard against failures to increase NR_syscalls
+#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
diff --git a/arch/ia64/kernel/err_inject.c b/arch/ia64/kernel/err_inject.c
index b642648..c539c68 100644
--- a/arch/ia64/kernel/err_inject.c
+++ b/arch/ia64/kernel/err_inject.c
@@ -55,7 +55,8 @@
 
 #define show(name) 							\
 static ssize_t 								\
-show_##name(struct sys_device *dev, char *buf)				\
+show_##name(struct sys_device *dev, struct sysdev_attribute *attr,	\
+		char *buf)						\
 {									\
 	u32 cpu=dev->id;						\
 	return sprintf(buf, "%lx\n", name[cpu]);			\
@@ -63,7 +64,8 @@
 
 #define store(name)							\
 static ssize_t 								\
-store_##name(struct sys_device *dev, const char *buf, size_t size)	\
+store_##name(struct sys_device *dev, struct sysdev_attribute *attr,	\
+					const char *buf, size_t size)	\
 {									\
 	unsigned int cpu=dev->id;					\
 	name[cpu] = simple_strtoull(buf, NULL, 16);			\
@@ -76,7 +78,8 @@
  * processor. The cpu number in driver is only used for storing data.
  */
 static ssize_t
-store_call_start(struct sys_device *dev, const char *buf, size_t size)
+store_call_start(struct sys_device *dev, struct sysdev_attribute *attr,
+		const char *buf, size_t size)
 {
 	unsigned int cpu=dev->id;
 	unsigned long call_start = simple_strtoull(buf, NULL, 16);
@@ -124,14 +127,16 @@
 store(err_type_info)
 
 static ssize_t
-show_virtual_to_phys(struct sys_device *dev, char *buf)
+show_virtual_to_phys(struct sys_device *dev, struct sysdev_attribute *attr,
+			char *buf)
 {
 	unsigned int cpu=dev->id;
 	return sprintf(buf, "%lx\n", phys_addr[cpu]);
 }
 
 static ssize_t
-store_virtual_to_phys(struct sys_device *dev, const char *buf, size_t size)
+store_virtual_to_phys(struct sys_device *dev, struct sysdev_attribute *attr,
+			const char *buf, size_t size)
 {
 	unsigned int cpu=dev->id;
 	u64 virt_addr=simple_strtoull(buf, NULL, 16);
@@ -154,7 +159,8 @@
 store(err_struct_info)
 
 static ssize_t
-show_err_data_buffer(struct sys_device *dev, char *buf)
+show_err_data_buffer(struct sys_device *dev,
+			struct sysdev_attribute *attr, char *buf)
 {
 	unsigned int cpu=dev->id;
 
@@ -165,7 +171,9 @@
 }
 
 static ssize_t
-store_err_data_buffer(struct sys_device *dev, const char *buf, size_t size)
+store_err_data_buffer(struct sys_device *dev,
+			struct sysdev_attribute *attr,
+			const char *buf, size_t size)
 {
 	unsigned int cpu=dev->id;
 	int ret;
diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
index ddeab4e..db540e5 100644
--- a/arch/ia64/kernel/head.S
+++ b/arch/ia64/kernel/head.S
@@ -26,11 +26,14 @@
 #include <asm/mmu_context.h>
 #include <asm/asm-offsets.h>
 #include <asm/pal.h>
+#include <asm/paravirt.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 #include <asm/system.h>
 #include <asm/mca_asm.h>
+#include <linux/init.h>
+#include <linux/linkage.h>
 
 #ifdef CONFIG_HOTPLUG_CPU
 #define SAL_PSR_BITS_TO_SET				\
@@ -367,6 +370,44 @@
 	;;
 (isBP)	st8 [r2]=r28		// save the address of the boot param area passed by the bootloader
 
+#ifdef CONFIG_PARAVIRT
+
+	movl r14=hypervisor_setup_hooks
+	movl r15=hypervisor_type
+	mov r16=num_hypervisor_hooks
+	;;
+	ld8 r2=[r15]
+	;;
+	cmp.ltu p7,p0=r2,r16	// array size check
+	shladd r8=r2,3,r14
+	;;
+(p7)	ld8 r9=[r8]
+	;;
+(p7)	mov b1=r9
+(p7)	cmp.ne.unc p7,p0=r9,r0	// no actual branch to NULL
+	;;
+(p7)	br.call.sptk.many rp=b1
+
+	__INITDATA
+
+default_setup_hook = 0		// Currently nothing needs to be done.
+
+	.weak xen_setup_hook
+
+	.global hypervisor_type
+hypervisor_type:
+	data8		PARAVIRT_HYPERVISOR_TYPE_DEFAULT
+
+	// must have the same order with PARAVIRT_HYPERVISOR_TYPE_xxx
+
+hypervisor_setup_hooks:
+	data8		default_setup_hook
+	data8		xen_setup_hook
+num_hypervisor_hooks = (. - hypervisor_setup_hooks) / 8
+	.previous
+
+#endif
+
 #ifdef CONFIG_SMP
 (isAP)	br.call.sptk.many rp=start_secondary
 .ret0:
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index 39752cd..3bc2fa6 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -585,6 +585,15 @@
 	return (iosapic_intr_info[irq].count > 1);
 }
 
+struct irq_chip*
+ia64_native_iosapic_get_irq_chip(unsigned long trigger)
+{
+	if (trigger == IOSAPIC_EDGE)
+		return &irq_type_iosapic_edge;
+	else
+		return &irq_type_iosapic_level;
+}
+
 static int
 register_intr (unsigned int gsi, int irq, unsigned char delivery,
 	       unsigned long polarity, unsigned long trigger)
@@ -635,13 +644,10 @@
 	iosapic_intr_info[irq].dmode    = delivery;
 	iosapic_intr_info[irq].trigger  = trigger;
 
-	if (trigger == IOSAPIC_EDGE)
-		irq_type = &irq_type_iosapic_edge;
-	else
-		irq_type = &irq_type_iosapic_level;
+	irq_type = iosapic_get_irq_chip(trigger);
 
 	idesc = irq_desc + irq;
-	if (idesc->chip != irq_type) {
+	if (irq_type != NULL && idesc->chip != irq_type) {
 		if (idesc->chip != &no_irq_type)
 			printk(KERN_WARNING
 			       "%s: changing vector %d from %s to %s\n",
@@ -974,6 +980,22 @@
 }
 
 void __init
+ia64_native_iosapic_pcat_compat_init(void)
+{
+	if (pcat_compat) {
+		/*
+		 * Disable the compatibility mode interrupts (8259 style),
+		 * needs IN/OUT support enabled.
+		 */
+		printk(KERN_INFO
+		       "%s: Disabling PC-AT compatible 8259 interrupts\n",
+		       __func__);
+		outb(0xff, 0xA1);
+		outb(0xff, 0x21);
+	}
+}
+
+void __init
 iosapic_system_init (int system_pcat_compat)
 {
 	int irq;
@@ -987,17 +1009,8 @@
 	}
 
 	pcat_compat = system_pcat_compat;
-	if (pcat_compat) {
-		/*
-		 * Disable the compatibility mode interrupts (8259 style),
-		 * needs IN/OUT support enabled.
-		 */
-		printk(KERN_INFO
-		       "%s: Disabling PC-AT compatible 8259 interrupts\n",
-		       __func__);
-		outb(0xff, 0xA1);
-		outb(0xff, 0x21);
-	}
+	if (pcat_compat)
+		iosapic_pcat_compat_init();
 }
 
 static inline int
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index 5538471..28d3d48 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -196,7 +196,7 @@
 }
 
 int
-assign_irq_vector (int irq)
+ia64_native_assign_irq_vector (int irq)
 {
 	unsigned long flags;
 	int vector, cpu;
@@ -222,7 +222,7 @@
 }
 
 void
-free_irq_vector (int vector)
+ia64_native_free_irq_vector (int vector)
 {
 	if (vector < IA64_FIRST_DEVICE_VECTOR ||
 	    vector > IA64_LAST_DEVICE_VECTOR)
@@ -600,7 +600,6 @@
 {
 	BUG();
 }
-extern irqreturn_t handle_IPI (int irq, void *dev_id);
 
 static struct irqaction ipi_irqaction = {
 	.handler =	handle_IPI,
@@ -623,7 +622,7 @@
 #endif
 
 void
-register_percpu_irq (ia64_vector vec, struct irqaction *action)
+ia64_native_register_percpu_irq (ia64_vector vec, struct irqaction *action)
 {
 	irq_desc_t *desc;
 	unsigned int irq;
@@ -638,13 +637,21 @@
 }
 
 void __init
-init_IRQ (void)
+ia64_native_register_ipi(void)
 {
-	register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL);
 #ifdef CONFIG_SMP
 	register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction);
 	register_percpu_irq(IA64_IPI_RESCHEDULE, &resched_irqaction);
 	register_percpu_irq(IA64_IPI_LOCAL_TLB_FLUSH, &tlb_irqaction);
+#endif
+}
+
+void __init
+init_IRQ (void)
+{
+	ia64_register_ipi();
+	register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL);
+#ifdef CONFIG_SMP
 #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_DIG)
 	if (vector_domain_type != VECTOR_DOMAIN_NONE) {
 		BUG_ON(IA64_FIRST_DEVICE_VECTOR != IA64_IRQ_MOVE_VECTOR);
diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S
index 80b44ea..c39627d 100644
--- a/arch/ia64/kernel/ivt.S
+++ b/arch/ia64/kernel/ivt.S
@@ -12,6 +12,14 @@
  *
  * 00/08/23 Asit Mallick <asit.k.mallick@intel.com> TLB handling for SMP
  * 00/12/20 David Mosberger-Tang <davidm@hpl.hp.com> DTLB/ITLB handler now uses virtual PT.
+ *
+ * Copyright (C) 2005 Hewlett-Packard Co
+ *	Dan Magenheimer <dan.magenheimer@hp.com>
+ *      Xen paravirtualization
+ * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *                    pv_ops.
+ *      Yaozu (Eddie) Dong <eddie.dong@intel.com>
  */
 /*
  * This file defines the interruption vector table used by the CPU.
@@ -102,13 +110,13 @@
 	 *	- the faulting virtual address uses unimplemented address bits
 	 *	- the faulting virtual address has no valid page table mapping
 	 */
-	mov r16=cr.ifa				// get address that caused the TLB miss
+	MOV_FROM_IFA(r16)			// get address that caused the TLB miss
 #ifdef CONFIG_HUGETLB_PAGE
 	movl r18=PAGE_SHIFT
-	mov r25=cr.itir
+	MOV_FROM_ITIR(r25)
 #endif
 	;;
-	rsm psr.dt				// use physical addressing for data
+	RSM_PSR_DT				// use physical addressing for data
 	mov r31=pr				// save the predicate registers
 	mov r19=IA64_KR(PT_BASE)		// get page table base address
 	shl r21=r16,3				// shift bit 60 into sign bit
@@ -168,21 +176,21 @@
 	dep r21=r19,r20,3,(PAGE_SHIFT-3)	// r21=pte_offset(pmd,addr)
 	;;
 (p7)	ld8 r18=[r21]				// read *pte
-	mov r19=cr.isr				// cr.isr bit 32 tells us if this is an insn miss
+	MOV_FROM_ISR(r19)			// cr.isr bit 32 tells us if this is an insn miss
 	;;
 (p7)	tbit.z p6,p7=r18,_PAGE_P_BIT		// page present bit cleared?
-	mov r22=cr.iha				// get the VHPT address that caused the TLB miss
+	MOV_FROM_IHA(r22)			// get the VHPT address that caused the TLB miss
 	;;					// avoid RAW on p7
 (p7)	tbit.nz.unc p10,p11=r19,32		// is it an instruction TLB miss?
 	dep r23=0,r20,0,PAGE_SHIFT		// clear low bits to get page address
 	;;
-(p10)	itc.i r18				// insert the instruction TLB entry
-(p11)	itc.d r18				// insert the data TLB entry
+	ITC_I_AND_D(p10, p11, r18, r24)		// insert the instruction TLB entry and
+						// insert the data TLB entry
 (p6)	br.cond.spnt.many page_fault		// handle bad address/page not present (page fault)
-	mov cr.ifa=r22
+	MOV_TO_IFA(r22, r24)
 
 #ifdef CONFIG_HUGETLB_PAGE
-(p8)	mov cr.itir=r25				// change to default page-size for VHPT
+	MOV_TO_ITIR(p8, r25, r24)		// change to default page-size for VHPT
 #endif
 
 	/*
@@ -192,7 +200,7 @@
 	 */
 	adds r24=__DIRTY_BITS_NO_ED|_PAGE_PL_0|_PAGE_AR_RW,r23
 	;;
-(p7)	itc.d r24
+	ITC_D(p7, r24, r25)
 	;;
 #ifdef CONFIG_SMP
 	/*
@@ -234,7 +242,7 @@
 #endif
 
 	mov pr=r31,-1				// restore predicate registers
-	rfi
+	RFI
 END(vhpt_miss)
 
 	.org ia64_ivt+0x400
@@ -248,11 +256,11 @@
 	 * mode, walk the page table, and then re-execute the PTE read and
 	 * go on normally after that.
 	 */
-	mov r16=cr.ifa				// get virtual address
+	MOV_FROM_IFA(r16)			// get virtual address
 	mov r29=b0				// save b0
 	mov r31=pr				// save predicates
 .itlb_fault:
-	mov r17=cr.iha				// get virtual address of PTE
+	MOV_FROM_IHA(r17)			// get virtual address of PTE
 	movl r30=1f				// load nested fault continuation point
 	;;
 1:	ld8 r18=[r17]				// read *pte
@@ -261,7 +269,7 @@
 	tbit.z p6,p0=r18,_PAGE_P_BIT		// page present bit cleared?
 (p6)	br.cond.spnt page_fault
 	;;
-	itc.i r18
+	ITC_I(p0, r18, r19)
 	;;
 #ifdef CONFIG_SMP
 	/*
@@ -278,7 +286,7 @@
 (p7)	ptc.l r16,r20
 #endif
 	mov pr=r31,-1
-	rfi
+	RFI
 END(itlb_miss)
 
 	.org ia64_ivt+0x0800
@@ -292,11 +300,11 @@
 	 * mode, walk the page table, and then re-execute the PTE read and
 	 * go on normally after that.
 	 */
-	mov r16=cr.ifa				// get virtual address
+	MOV_FROM_IFA(r16)			// get virtual address
 	mov r29=b0				// save b0
 	mov r31=pr				// save predicates
 dtlb_fault:
-	mov r17=cr.iha				// get virtual address of PTE
+	MOV_FROM_IHA(r17)			// get virtual address of PTE
 	movl r30=1f				// load nested fault continuation point
 	;;
 1:	ld8 r18=[r17]				// read *pte
@@ -305,7 +313,7 @@
 	tbit.z p6,p0=r18,_PAGE_P_BIT		// page present bit cleared?
 (p6)	br.cond.spnt page_fault
 	;;
-	itc.d r18
+	ITC_D(p0, r18, r19)
 	;;
 #ifdef CONFIG_SMP
 	/*
@@ -322,7 +330,7 @@
 (p7)	ptc.l r16,r20
 #endif
 	mov pr=r31,-1
-	rfi
+	RFI
 END(dtlb_miss)
 
 	.org ia64_ivt+0x0c00
@@ -330,9 +338,9 @@
 // 0x0c00 Entry 3 (size 64 bundles) Alt ITLB (19)
 ENTRY(alt_itlb_miss)
 	DBG_FAULT(3)
-	mov r16=cr.ifa		// get address that caused the TLB miss
+	MOV_FROM_IFA(r16)	// get address that caused the TLB miss
 	movl r17=PAGE_KERNEL
-	mov r21=cr.ipsr
+	MOV_FROM_IPSR(p0, r21)
 	movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
 	mov r31=pr
 	;;
@@ -341,9 +349,9 @@
 	;;
 	cmp.gt p8,p0=6,r22			// user mode
 	;;
-(p8)	thash r17=r16
+	THASH(p8, r17, r16, r23)
 	;;
-(p8)	mov cr.iha=r17
+	MOV_TO_IHA(p8, r17, r23)
 (p8)	mov r29=b0				// save b0
 (p8)	br.cond.dptk .itlb_fault
 #endif
@@ -358,9 +366,9 @@
 	or r19=r19,r18		// set bit 4 (uncached) if the access was to region 6
 (p8)	br.cond.spnt page_fault
 	;;
-	itc.i r19		// insert the TLB entry
+	ITC_I(p0, r19, r18)	// insert the TLB entry
 	mov pr=r31,-1
-	rfi
+	RFI
 END(alt_itlb_miss)
 
 	.org ia64_ivt+0x1000
@@ -368,11 +376,11 @@
 // 0x1000 Entry 4 (size 64 bundles) Alt DTLB (7,46)
 ENTRY(alt_dtlb_miss)
 	DBG_FAULT(4)
-	mov r16=cr.ifa		// get address that caused the TLB miss
+	MOV_FROM_IFA(r16)	// get address that caused the TLB miss
 	movl r17=PAGE_KERNEL
-	mov r20=cr.isr
+	MOV_FROM_ISR(r20)
 	movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
-	mov r21=cr.ipsr
+	MOV_FROM_IPSR(p0, r21)
 	mov r31=pr
 	mov r24=PERCPU_ADDR
 	;;
@@ -381,9 +389,9 @@
 	;;
 	cmp.gt p8,p0=6,r22			// access to region 0-5
 	;;
-(p8)	thash r17=r16
+	THASH(p8, r17, r16, r25)
 	;;
-(p8)	mov cr.iha=r17
+	MOV_TO_IHA(p8, r17, r25)
 (p8)	mov r29=b0				// save b0
 (p8)	br.cond.dptk dtlb_fault
 #endif
@@ -402,7 +410,7 @@
 	tbit.nz p9,p0=r20,IA64_ISR_NA_BIT	// is non-access bit on?
 	;;
 (p10)	sub r19=r19,r26
-(p10)	mov cr.itir=r25
+	MOV_TO_ITIR(p10, r25, r24)
 	cmp.ne p8,p0=r0,r23
 (p9)	cmp.eq.or.andcm p6,p7=IA64_ISR_CODE_LFETCH,r22	// check isr.code field
 (p12)	dep r17=-1,r17,4,1			// set ma=UC for region 6 addr
@@ -411,11 +419,11 @@
 	dep r21=-1,r21,IA64_PSR_ED_BIT,1
 	;;
 	or r19=r19,r17		// insert PTE control bits into r19
-(p6)	mov cr.ipsr=r21
+	MOV_TO_IPSR(p6, r21, r24)
 	;;
-(p7)	itc.d r19		// insert the TLB entry
+	ITC_D(p7, r19, r18)	// insert the TLB entry
 	mov pr=r31,-1
-	rfi
+	RFI
 END(alt_dtlb_miss)
 
 	.org ia64_ivt+0x1400
@@ -444,10 +452,10 @@
 	 *
 	 * Clobbered:	b0, r18, r19, r21, r22, psr.dt (cleared)
 	 */
-	rsm psr.dt				// switch to using physical data addressing
+	RSM_PSR_DT				// switch to using physical data addressing
 	mov r19=IA64_KR(PT_BASE)		// get the page table base address
 	shl r21=r16,3				// shift bit 60 into sign bit
-	mov r18=cr.itir
+	MOV_FROM_ITIR(r18)
 	;;
 	shr.u r17=r16,61			// get the region number into r17
 	extr.u r18=r18,2,6			// get the faulting page size
@@ -507,33 +515,6 @@
 	FAULT(6)
 END(ikey_miss)
 
-	//-----------------------------------------------------------------------------------
-	// call do_page_fault (predicates are in r31, psr.dt may be off, r16 is faulting address)
-ENTRY(page_fault)
-	ssm psr.dt
-	;;
-	srlz.i
-	;;
-	SAVE_MIN_WITH_COVER
-	alloc r15=ar.pfs,0,0,3,0
-	mov out0=cr.ifa
-	mov out1=cr.isr
-	adds r3=8,r2				// set up second base pointer
-	;;
-	ssm psr.ic | PSR_DEFAULT_BITS
-	;;
-	srlz.i					// guarantee that interruption collectin is on
-	;;
-(p15)	ssm psr.i				// restore psr.i
-	movl r14=ia64_leave_kernel
-	;;
-	SAVE_REST
-	mov rp=r14
-	;;
-	adds out2=16,r12			// out2 = pointer to pt_regs
-	br.call.sptk.many b6=ia64_do_page_fault	// ignore return address
-END(page_fault)
-
 	.org ia64_ivt+0x1c00
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
@@ -556,10 +537,10 @@
 	 * page table TLB entry isn't present, we take a nested TLB miss hit where we look
 	 * up the physical address of the L3 PTE and then continue at label 1 below.
 	 */
-	mov r16=cr.ifa				// get the address that caused the fault
+	MOV_FROM_IFA(r16)			// get the address that caused the fault
 	movl r30=1f				// load continuation point in case of nested fault
 	;;
-	thash r17=r16				// compute virtual address of L3 PTE
+	THASH(p0, r17, r16, r18)		// compute virtual address of L3 PTE
 	mov r29=b0				// save b0 in case of nested fault
 	mov r31=pr				// save pr
 #ifdef CONFIG_SMP
@@ -576,7 +557,7 @@
 	;;
 (p6)	cmp.eq p6,p7=r26,r18			// Only compare if page is present
 	;;
-(p6)	itc.d r25				// install updated PTE
+	ITC_D(p6, r25, r18)			// install updated PTE
 	;;
 	/*
 	 * Tell the assemblers dependency-violation checker that the above "itc" instructions
@@ -602,7 +583,7 @@
 	itc.d r18				// install updated PTE
 #endif
 	mov pr=r31,-1				// restore pr
-	rfi
+	RFI
 END(dirty_bit)
 
 	.org ia64_ivt+0x2400
@@ -611,22 +592,22 @@
 ENTRY(iaccess_bit)
 	DBG_FAULT(9)
 	// Like Entry 8, except for instruction access
-	mov r16=cr.ifa				// get the address that caused the fault
+	MOV_FROM_IFA(r16)			// get the address that caused the fault
 	movl r30=1f				// load continuation point in case of nested fault
 	mov r31=pr				// save predicates
 #ifdef CONFIG_ITANIUM
 	/*
 	 * Erratum 10 (IFA may contain incorrect address) has "NoFix" status.
 	 */
-	mov r17=cr.ipsr
+	MOV_FROM_IPSR(p0, r17)
 	;;
-	mov r18=cr.iip
+	MOV_FROM_IIP(r18)
 	tbit.z p6,p0=r17,IA64_PSR_IS_BIT	// IA64 instruction set?
 	;;
 (p6)	mov r16=r18				// if so, use cr.iip instead of cr.ifa
 #endif /* CONFIG_ITANIUM */
 	;;
-	thash r17=r16				// compute virtual address of L3 PTE
+	THASH(p0, r17, r16, r18)		// compute virtual address of L3 PTE
 	mov r29=b0				// save b0 in case of nested fault)
 #ifdef CONFIG_SMP
 	mov r28=ar.ccv				// save ar.ccv
@@ -642,7 +623,7 @@
 	;;
 (p6)	cmp.eq p6,p7=r26,r18			// Only if page present
 	;;
-(p6)	itc.i r25				// install updated PTE
+	ITC_I(p6, r25, r26)			// install updated PTE
 	;;
 	/*
 	 * Tell the assemblers dependency-violation checker that the above "itc" instructions
@@ -668,7 +649,7 @@
 	itc.i r18				// install updated PTE
 #endif /* !CONFIG_SMP */
 	mov pr=r31,-1
-	rfi
+	RFI
 END(iaccess_bit)
 
 	.org ia64_ivt+0x2800
@@ -677,10 +658,10 @@
 ENTRY(daccess_bit)
 	DBG_FAULT(10)
 	// Like Entry 8, except for data access
-	mov r16=cr.ifa				// get the address that caused the fault
+	MOV_FROM_IFA(r16)			// get the address that caused the fault
 	movl r30=1f				// load continuation point in case of nested fault
 	;;
-	thash r17=r16				// compute virtual address of L3 PTE
+	THASH(p0, r17, r16, r18)		// compute virtual address of L3 PTE
 	mov r31=pr
 	mov r29=b0				// save b0 in case of nested fault)
 #ifdef CONFIG_SMP
@@ -697,7 +678,7 @@
 	;;
 (p6)	cmp.eq p6,p7=r26,r18			// Only if page is present
 	;;
-(p6)	itc.d r25				// install updated PTE
+	ITC_D(p6, r25, r26)			// install updated PTE
 	/*
 	 * Tell the assemblers dependency-violation checker that the above "itc" instructions
 	 * cannot possibly affect the following loads:
@@ -721,7 +702,7 @@
 #endif
 	mov b0=r29				// restore b0
 	mov pr=r31,-1
-	rfi
+	RFI
 END(daccess_bit)
 
 	.org ia64_ivt+0x2c00
@@ -745,10 +726,10 @@
 	 */
 	DBG_FAULT(11)
 	mov.m r16=IA64_KR(CURRENT)		// M2 r16 <- current task (12 cyc)
-	mov r29=cr.ipsr				// M2 (12 cyc)
+	MOV_FROM_IPSR(p0, r29)			// M2 (12 cyc)
 	mov r31=pr				// I0 (2 cyc)
 
-	mov r17=cr.iim				// M2 (2 cyc)
+	MOV_FROM_IIM(r17)			// M2 (2 cyc)
 	mov.m r27=ar.rsc			// M2 (12 cyc)
 	mov r18=__IA64_BREAK_SYSCALL		// A
 
@@ -767,7 +748,7 @@
 	nop.m 0
 	movl r30=sys_call_table			// X
 
-	mov r28=cr.iip				// M2 (2 cyc)
+	MOV_FROM_IIP(r28)			// M2 (2 cyc)
 	cmp.eq p0,p7=r18,r17			// I0 is this a system call?
 (p7)	br.cond.spnt non_syscall		// B  no ->
 	//
@@ -864,18 +845,17 @@
 #endif
 	mov ar.rsc=0x3				// M2   set eager mode, pl 0, LE, loadrs=0
 	nop 0
-	bsw.1					// B (6 cyc) regs are saved, switch to bank 1
+	BSW_1(r2, r14)				// B (6 cyc) regs are saved, switch to bank 1
 	;;
 
-	ssm psr.ic | PSR_DEFAULT_BITS		// M2	now it's safe to re-enable intr.-collection
+	SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r16)	// M2	now it's safe to re-enable intr.-collection
+						// M0   ensure interruption collection is on
 	movl r3=ia64_ret_from_syscall		// X
 	;;
-
-	srlz.i					// M0   ensure interruption collection is on
 	mov rp=r3				// I0   set the real return addr
 (p10)	br.cond.spnt.many ia64_ret_from_syscall	// B    return if bad call-frame or r15 is a NaT
 
-(p15)	ssm psr.i				// M2   restore psr.i
+	SSM_PSR_I(p15, p15, r16)		// M2   restore psr.i
 (p14)	br.call.sptk.many b6=b6			// B    invoke syscall-handker (ignore return addr)
 	br.cond.spnt.many ia64_trace_syscall	// B	do syscall-tracing thingamagic
 	// NOT REACHED
@@ -895,27 +875,8 @@
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x3000 Entry 12 (size 64 bundles) External Interrupt (4)
 ENTRY(interrupt)
-	DBG_FAULT(12)
-	mov r31=pr		// prepare to save predicates
-	;;
-	SAVE_MIN_WITH_COVER	// uses r31; defines r2 and r3
-	ssm psr.ic | PSR_DEFAULT_BITS
-	;;
-	adds r3=8,r2		// set up second base pointer for SAVE_REST
-	srlz.i			// ensure everybody knows psr.ic is back on
-	;;
-	SAVE_REST
-	;;
-	MCA_RECOVER_RANGE(interrupt)
-	alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group
-	mov out0=cr.ivr		// pass cr.ivr as first arg
-	add out1=16,sp		// pass pointer to pt_regs as second arg
-	;;
-	srlz.d			// make sure we see the effect of cr.ivr
-	movl r14=ia64_leave_kernel
-	;;
-	mov rp=r14
-	br.call.sptk.many b6=ia64_handle_irq
+	/* interrupt handler has become too big to fit this area. */
+	br.sptk.many __interrupt
 END(interrupt)
 
 	.org ia64_ivt+0x3400
@@ -978,6 +939,7 @@
 	 *	- ar.fpsr: set to kernel settings
 	 *	-  b6: preserved (same as on entry)
 	 */
+#ifdef __IA64_ASM_PARAVIRTUALIZED_NATIVE
 GLOBAL_ENTRY(ia64_syscall_setup)
 #if PT(B6) != 0
 # error This code assumes that b6 is the first field in pt_regs.
@@ -1069,6 +1031,7 @@
 (p10)	mov r8=-EINVAL
 	br.ret.sptk.many b7
 END(ia64_syscall_setup)
+#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
 
 	.org ia64_ivt+0x3c00
 /////////////////////////////////////////////////////////////////////////////////////////
@@ -1082,7 +1045,7 @@
 	DBG_FAULT(16)
 	FAULT(16)
 
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+#if defined(CONFIG_VIRT_CPU_ACCOUNTING) && defined(__IA64_ASM_PARAVIRTUALIZED_NATIVE)
 	/*
 	 * There is no particular reason for this code to be here, other than
 	 * that there happens to be space here that would go unused otherwise.
@@ -1092,7 +1055,7 @@
 	 * account_sys_enter is called from SAVE_MIN* macros if accounting is
 	 * enabled and if the macro is entered from user mode.
 	 */
-ENTRY(account_sys_enter)
+GLOBAL_ENTRY(account_sys_enter)
 	// mov.m r20=ar.itc is called in advance, and r13 is current
 	add r16=TI_AC_STAMP+IA64_TASK_SIZE,r13
 	add r17=TI_AC_LEAVE+IA64_TASK_SIZE,r13
@@ -1123,110 +1086,18 @@
 	DBG_FAULT(17)
 	FAULT(17)
 
-ENTRY(non_syscall)
-	mov ar.rsc=r27			// restore ar.rsc before SAVE_MIN_WITH_COVER
-	;;
-	SAVE_MIN_WITH_COVER
-
-	// There is no particular reason for this code to be here, other than that
-	// there happens to be space here that would go unused otherwise.  If this
-	// fault ever gets "unreserved", simply moved the following code to a more
-	// suitable spot...
-
-	alloc r14=ar.pfs,0,0,2,0
-	mov out0=cr.iim
-	add out1=16,sp
-	adds r3=8,r2			// set up second base pointer for SAVE_REST
-
-	ssm psr.ic | PSR_DEFAULT_BITS
-	;;
-	srlz.i				// guarantee that interruption collection is on
-	;;
-(p15)	ssm psr.i			// restore psr.i
-	movl r15=ia64_leave_kernel
-	;;
-	SAVE_REST
-	mov rp=r15
-	;;
-	br.call.sptk.many b6=ia64_bad_break	// avoid WAW on CFM and ignore return addr
-END(non_syscall)
-
 	.org ia64_ivt+0x4800
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x4800 Entry 18 (size 64 bundles) Reserved
 	DBG_FAULT(18)
 	FAULT(18)
 
-	/*
-	 * There is no particular reason for this code to be here, other than that
-	 * there happens to be space here that would go unused otherwise.  If this
-	 * fault ever gets "unreserved", simply moved the following code to a more
-	 * suitable spot...
-	 */
-
-ENTRY(dispatch_unaligned_handler)
-	SAVE_MIN_WITH_COVER
-	;;
-	alloc r14=ar.pfs,0,0,2,0		// now it's safe (must be first in insn group!)
-	mov out0=cr.ifa
-	adds out1=16,sp
-
-	ssm psr.ic | PSR_DEFAULT_BITS
-	;;
-	srlz.i					// guarantee that interruption collection is on
-	;;
-(p15)	ssm psr.i				// restore psr.i
-	adds r3=8,r2				// set up second base pointer
-	;;
-	SAVE_REST
-	movl r14=ia64_leave_kernel
-	;;
-	mov rp=r14
-	br.sptk.many ia64_prepare_handle_unaligned
-END(dispatch_unaligned_handler)
-
 	.org ia64_ivt+0x4c00
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x4c00 Entry 19 (size 64 bundles) Reserved
 	DBG_FAULT(19)
 	FAULT(19)
 
-	/*
-	 * There is no particular reason for this code to be here, other than that
-	 * there happens to be space here that would go unused otherwise.  If this
-	 * fault ever gets "unreserved", simply moved the following code to a more
-	 * suitable spot...
-	 */
-
-ENTRY(dispatch_to_fault_handler)
-	/*
-	 * Input:
-	 *	psr.ic:	off
-	 *	r19:	fault vector number (e.g., 24 for General Exception)
-	 *	r31:	contains saved predicates (pr)
-	 */
-	SAVE_MIN_WITH_COVER_R19
-	alloc r14=ar.pfs,0,0,5,0
-	mov out0=r15
-	mov out1=cr.isr
-	mov out2=cr.ifa
-	mov out3=cr.iim
-	mov out4=cr.itir
-	;;
-	ssm psr.ic | PSR_DEFAULT_BITS
-	;;
-	srlz.i					// guarantee that interruption collection is on
-	;;
-(p15)	ssm psr.i				// restore psr.i
-	adds r3=8,r2				// set up second base pointer for SAVE_REST
-	;;
-	SAVE_REST
-	movl r14=ia64_leave_kernel
-	;;
-	mov rp=r14
-	br.call.sptk.many b6=ia64_fault
-END(dispatch_to_fault_handler)
-
 //
 // --- End of long entries, Beginning of short entries
 //
@@ -1236,8 +1107,8 @@
 // 0x5000 Entry 20 (size 16 bundles) Page Not Present (10,22,49)
 ENTRY(page_not_present)
 	DBG_FAULT(20)
-	mov r16=cr.ifa
-	rsm psr.dt
+	MOV_FROM_IFA(r16)
+	RSM_PSR_DT
 	/*
 	 * The Linux page fault handler doesn't expect non-present pages to be in
 	 * the TLB.  Flush the existing entry now, so we meet that expectation.
@@ -1256,8 +1127,8 @@
 // 0x5100 Entry 21 (size 16 bundles) Key Permission (13,25,52)
 ENTRY(key_permission)
 	DBG_FAULT(21)
-	mov r16=cr.ifa
-	rsm psr.dt
+	MOV_FROM_IFA(r16)
+	RSM_PSR_DT
 	mov r31=pr
 	;;
 	srlz.d
@@ -1269,8 +1140,8 @@
 // 0x5200 Entry 22 (size 16 bundles) Instruction Access Rights (26)
 ENTRY(iaccess_rights)
 	DBG_FAULT(22)
-	mov r16=cr.ifa
-	rsm psr.dt
+	MOV_FROM_IFA(r16)
+	RSM_PSR_DT
 	mov r31=pr
 	;;
 	srlz.d
@@ -1282,8 +1153,8 @@
 // 0x5300 Entry 23 (size 16 bundles) Data Access Rights (14,53)
 ENTRY(daccess_rights)
 	DBG_FAULT(23)
-	mov r16=cr.ifa
-	rsm psr.dt
+	MOV_FROM_IFA(r16)
+	RSM_PSR_DT
 	mov r31=pr
 	;;
 	srlz.d
@@ -1295,7 +1166,7 @@
 // 0x5400 Entry 24 (size 16 bundles) General Exception (5,32,34,36,38,39)
 ENTRY(general_exception)
 	DBG_FAULT(24)
-	mov r16=cr.isr
+	MOV_FROM_ISR(r16)
 	mov r31=pr
 	;;
 	cmp4.eq p6,p0=0,r16
@@ -1324,8 +1195,8 @@
 ENTRY(nat_consumption)
 	DBG_FAULT(26)
 
-	mov r16=cr.ipsr
-	mov r17=cr.isr
+	MOV_FROM_IPSR(p0, r16)
+	MOV_FROM_ISR(r17)
 	mov r31=pr				// save PR
 	;;
 	and r18=0xf,r17				// r18 = cr.ipsr.code{3:0}
@@ -1335,10 +1206,10 @@
 	dep r16=-1,r16,IA64_PSR_ED_BIT,1
 (p6)	br.cond.spnt 1f		// branch if (cr.ispr.na == 0 || cr.ipsr.code{3:0} != LFETCH)
 	;;
-	mov cr.ipsr=r16		// set cr.ipsr.na
+	MOV_TO_IPSR(p0, r16, r18)
 	mov pr=r31,-1
 	;;
-	rfi
+	RFI
 
 1:	mov pr=r31,-1
 	;;
@@ -1360,26 +1231,26 @@
 	 *
 	 * cr.imm contains zero_ext(imm21)
 	 */
-	mov r18=cr.iim
+	MOV_FROM_IIM(r18)
 	;;
-	mov r17=cr.iip
+	MOV_FROM_IIP(r17)
 	shl r18=r18,43			// put sign bit in position (43=64-21)
 	;;
 
-	mov r16=cr.ipsr
+	MOV_FROM_IPSR(p0, r16)
 	shr r18=r18,39			// sign extend (39=43-4)
 	;;
 
 	add r17=r17,r18			// now add the offset
 	;;
-	mov cr.iip=r17
+	MOV_FROM_IIP(r17)
 	dep r16=0,r16,41,2		// clear EI
 	;;
 
-	mov cr.ipsr=r16
+	MOV_FROM_IPSR(p0, r16)
 	;;
 
-	rfi				// and go back
+	RFI
 END(speculation_vector)
 
 	.org ia64_ivt+0x5800
@@ -1517,11 +1388,11 @@
 	DBG_FAULT(46)
 #ifdef	CONFIG_IA32_SUPPORT
 	mov r31=pr
-	mov r16=cr.isr
+	MOV_FROM_ISR(r16)
 	;;
 	extr.u r17=r16,16,8	// get ISR.code
 	mov r18=ar.eflag
-	mov r19=cr.iim		// old eflag value
+	MOV_FROM_IIM(r19)	// old eflag value
 	;;
 	cmp.ne p6,p0=2,r17
 (p6)	br.cond.spnt 1f		// not a system flag fault
@@ -1533,7 +1404,7 @@
 (p6)	br.cond.spnt 1f		// eflags.ac bit didn't change
 	;;
 	mov pr=r31,-1		// restore predicate registers
-	rfi
+	RFI
 
 1:
 #endif	// CONFIG_IA32_SUPPORT
@@ -1673,6 +1544,137 @@
 	DBG_FAULT(67)
 	FAULT(67)
 
+	//-----------------------------------------------------------------------------------
+	// call do_page_fault (predicates are in r31, psr.dt may be off, r16 is faulting address)
+ENTRY(page_fault)
+	SSM_PSR_DT_AND_SRLZ_I
+	;;
+	SAVE_MIN_WITH_COVER
+	alloc r15=ar.pfs,0,0,3,0
+	MOV_FROM_IFA(out0)
+	MOV_FROM_ISR(out1)
+	SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r14, r3)
+	adds r3=8,r2				// set up second base pointer
+	SSM_PSR_I(p15, p15, r14)		// restore psr.i
+	movl r14=ia64_leave_kernel
+	;;
+	SAVE_REST
+	mov rp=r14
+	;;
+	adds out2=16,r12			// out2 = pointer to pt_regs
+	br.call.sptk.many b6=ia64_do_page_fault	// ignore return address
+END(page_fault)
+
+ENTRY(non_syscall)
+	mov ar.rsc=r27			// restore ar.rsc before SAVE_MIN_WITH_COVER
+	;;
+	SAVE_MIN_WITH_COVER
+
+	// There is no particular reason for this code to be here, other than that
+	// there happens to be space here that would go unused otherwise.  If this
+	// fault ever gets "unreserved", simply moved the following code to a more
+	// suitable spot...
+
+	alloc r14=ar.pfs,0,0,2,0
+	MOV_FROM_IIM(out0)
+	add out1=16,sp
+	adds r3=8,r2			// set up second base pointer for SAVE_REST
+
+	SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r15, r24)
+					// guarantee that interruption collection is on
+	SSM_PSR_I(p15, p15, r15)	// restore psr.i
+	movl r15=ia64_leave_kernel
+	;;
+	SAVE_REST
+	mov rp=r15
+	;;
+	br.call.sptk.many b6=ia64_bad_break	// avoid WAW on CFM and ignore return addr
+END(non_syscall)
+
+ENTRY(__interrupt)
+	DBG_FAULT(12)
+	mov r31=pr		// prepare to save predicates
+	;;
+	SAVE_MIN_WITH_COVER	// uses r31; defines r2 and r3
+	SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r14)
+				// ensure everybody knows psr.ic is back on
+	adds r3=8,r2		// set up second base pointer for SAVE_REST
+	;;
+	SAVE_REST
+	;;
+	MCA_RECOVER_RANGE(interrupt)
+	alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group
+	MOV_FROM_IVR(out0, r8)	// pass cr.ivr as first arg
+	add out1=16,sp		// pass pointer to pt_regs as second arg
+	;;
+	srlz.d			// make sure we see the effect of cr.ivr
+	movl r14=ia64_leave_kernel
+	;;
+	mov rp=r14
+	br.call.sptk.many b6=ia64_handle_irq
+END(__interrupt)
+
+	/*
+	 * There is no particular reason for this code to be here, other than that
+	 * there happens to be space here that would go unused otherwise.  If this
+	 * fault ever gets "unreserved", simply moved the following code to a more
+	 * suitable spot...
+	 */
+
+ENTRY(dispatch_unaligned_handler)
+	SAVE_MIN_WITH_COVER
+	;;
+	alloc r14=ar.pfs,0,0,2,0		// now it's safe (must be first in insn group!)
+	MOV_FROM_IFA(out0)
+	adds out1=16,sp
+
+	SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r24)
+						// guarantee that interruption collection is on
+	SSM_PSR_I(p15, p15, r3)			// restore psr.i
+	adds r3=8,r2				// set up second base pointer
+	;;
+	SAVE_REST
+	movl r14=ia64_leave_kernel
+	;;
+	mov rp=r14
+	br.sptk.many ia64_prepare_handle_unaligned
+END(dispatch_unaligned_handler)
+
+	/*
+	 * There is no particular reason for this code to be here, other than that
+	 * there happens to be space here that would go unused otherwise.  If this
+	 * fault ever gets "unreserved", simply moved the following code to a more
+	 * suitable spot...
+	 */
+
+ENTRY(dispatch_to_fault_handler)
+	/*
+	 * Input:
+	 *	psr.ic:	off
+	 *	r19:	fault vector number (e.g., 24 for General Exception)
+	 *	r31:	contains saved predicates (pr)
+	 */
+	SAVE_MIN_WITH_COVER_R19
+	alloc r14=ar.pfs,0,0,5,0
+	MOV_FROM_ISR(out1)
+	MOV_FROM_IFA(out2)
+	MOV_FROM_IIM(out3)
+	MOV_FROM_ITIR(out4)
+	;;
+	SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, out0)
+						// guarantee that interruption collection is on
+	mov out0=r15
+	;;
+	SSM_PSR_I(p15, p15, r3)			// restore psr.i
+	adds r3=8,r2				// set up second base pointer for SAVE_REST
+	;;
+	SAVE_REST
+	movl r14=ia64_leave_kernel
+	;;
+	mov rp=r14
+	br.call.sptk.many b6=ia64_fault
+END(dispatch_to_fault_handler)
+
 	/*
 	 * Squatting in this space ...
 	 *
@@ -1686,11 +1688,10 @@
 	.prologue
 	.body
 	SAVE_MIN_WITH_COVER
-	ssm psr.ic | PSR_DEFAULT_BITS
+	SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r24)
+				// guarantee that interruption collection is on
 	;;
-	srlz.i		// guarantee that interruption collection is on
-	;;
-(p15)	ssm psr.i	// restore psr.i
+	SSM_PSR_I(p15, p15, r3)	// restore psr.i
 	adds r3=8,r2	// set up second base pointer for SAVE_REST
 	;;
 	alloc r14=ar.pfs,0,0,1,0	// must be first in insn group
@@ -1729,12 +1730,11 @@
 ENTRY(dispatch_to_ia32_handler)
 	SAVE_MIN
 	;;
-	mov r14=cr.isr
-	ssm psr.ic | PSR_DEFAULT_BITS
+	MOV_FROM_ISR(r14)
+	SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r24)
+				// guarantee that interruption collection is on
 	;;
-	srlz.i					// guarantee that interruption collection is on
-	;;
-(p15)	ssm psr.i
+	SSM_PSR_I(p15, p15, r3)
 	adds r3=8,r2		// Base pointer for SAVE_REST
 	;;
 	SAVE_REST
diff --git a/arch/ia64/kernel/minstate.h b/arch/ia64/kernel/minstate.h
index 74b6d67..292e214 100644
--- a/arch/ia64/kernel/minstate.h
+++ b/arch/ia64/kernel/minstate.h
@@ -2,6 +2,7 @@
 #include <asm/cache.h>
 
 #include "entry.h"
+#include "paravirt_inst.h"
 
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 /* read ar.itc in advance, and use it before leaving bank 0 */
@@ -43,16 +44,16 @@
  * Note that psr.ic is NOT turned on by this macro.  This is so that
  * we can pass interruption state as arguments to a handler.
  */
-#define DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA,WORKAROUND)						\
+#define IA64_NATIVE_DO_SAVE_MIN(__COVER,SAVE_IFS,EXTRA,WORKAROUND)				\
 	mov r16=IA64_KR(CURRENT);	/* M */							\
 	mov r27=ar.rsc;			/* M */							\
 	mov r20=r1;			/* A */							\
 	mov r25=ar.unat;		/* M */							\
-	mov r29=cr.ipsr;		/* M */							\
+	MOV_FROM_IPSR(p0,r29);		/* M */							\
 	mov r26=ar.pfs;			/* I */							\
-	mov r28=cr.iip;			/* M */							\
+	MOV_FROM_IIP(r28);			/* M */						\
 	mov r21=ar.fpsr;		/* M */							\
-	COVER;				/* B;; (or nothing) */					\
+	__COVER;				/* B;; (or nothing) */				\
 	;;											\
 	adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16;						\
 	;;											\
@@ -244,6 +245,6 @@
 1:						\
 	.pred.rel "mutex", pKStk, pUStk
 
-#define SAVE_MIN_WITH_COVER	DO_SAVE_MIN(cover, mov r30=cr.ifs, , RSE_WORKAROUND)
-#define SAVE_MIN_WITH_COVER_R19	DO_SAVE_MIN(cover, mov r30=cr.ifs, mov r15=r19, RSE_WORKAROUND)
+#define SAVE_MIN_WITH_COVER	DO_SAVE_MIN(COVER, mov r30=cr.ifs, , RSE_WORKAROUND)
+#define SAVE_MIN_WITH_COVER_R19	DO_SAVE_MIN(COVER, mov r30=cr.ifs, mov r15=r19, RSE_WORKAROUND)
 #define SAVE_MIN			DO_SAVE_MIN(     , mov r30=r0, , )
diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c
index e83e2ea..29aad34 100644
--- a/arch/ia64/kernel/module.c
+++ b/arch/ia64/kernel/module.c
@@ -321,7 +321,8 @@
 void
 module_free (struct module *mod, void *module_region)
 {
-	if (mod->arch.init_unw_table && module_region == mod->module_init) {
+	if (mod && mod->arch.init_unw_table &&
+	    module_region == mod->module_init) {
 		unw_remove_unwind_table(mod->arch.init_unw_table);
 		mod->arch.init_unw_table = NULL;
 	}
diff --git a/arch/ia64/kernel/nr-irqs.c b/arch/ia64/kernel/nr-irqs.c
new file mode 100644
index 0000000..1ae0491
--- /dev/null
+++ b/arch/ia64/kernel/nr-irqs.c
@@ -0,0 +1,24 @@
+/*
+ * calculate
+ * NR_IRQS = max(IA64_NATIVE_NR_IRQS, XEN_NR_IRQS, FOO_NR_IRQS...)
+ * depending on config.
+ * This must be calculated before processing asm-offset.c.
+ */
+
+#define ASM_OFFSETS_C 1
+
+#include <linux/kbuild.h>
+#include <linux/threads.h>
+#include <asm-ia64/native/irq.h>
+
+void foo(void)
+{
+	union paravirt_nr_irqs_max {
+		char ia64_native_nr_irqs[IA64_NATIVE_NR_IRQS];
+#ifdef CONFIG_XEN
+		char xen_nr_irqs[XEN_NR_IRQS];
+#endif
+	};
+
+	DEFINE(NR_IRQS, sizeof (union paravirt_nr_irqs_max));
+}
diff --git a/arch/ia64/kernel/paravirt.c b/arch/ia64/kernel/paravirt.c
new file mode 100644
index 0000000..afaf5b9
--- /dev/null
+++ b/arch/ia64/kernel/paravirt.c
@@ -0,0 +1,369 @@
+/******************************************************************************
+ * arch/ia64/kernel/paravirt.c
+ *
+ * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *     Yaozu (Eddie) Dong <eddie.dong@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/init.h>
+
+#include <linux/compiler.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/types.h>
+
+#include <asm/iosapic.h>
+#include <asm/paravirt.h>
+
+/***************************************************************************
+ * general info
+ */
+struct pv_info pv_info = {
+	.kernel_rpl = 0,
+	.paravirt_enabled = 0,
+	.name = "bare hardware"
+};
+
+/***************************************************************************
+ * pv_init_ops
+ * initialization hooks.
+ */
+
+struct pv_init_ops pv_init_ops;
+
+/***************************************************************************
+ * pv_cpu_ops
+ * intrinsics hooks.
+ */
+
+/* ia64_native_xxx are macros so that we have to make them real functions */
+
+#define DEFINE_VOID_FUNC1(name)					\
+	static void						\
+	ia64_native_ ## name ## _func(unsigned long arg)	\
+	{							\
+		ia64_native_ ## name(arg);			\
+	}							\
+
+#define DEFINE_VOID_FUNC2(name)					\
+	static void						\
+	ia64_native_ ## name ## _func(unsigned long arg0,	\
+				      unsigned long arg1)	\
+	{							\
+		ia64_native_ ## name(arg0, arg1);		\
+	}							\
+
+#define DEFINE_FUNC0(name)			\
+	static unsigned long			\
+	ia64_native_ ## name ## _func(void)	\
+	{					\
+		return ia64_native_ ## name();	\
+	}
+
+#define DEFINE_FUNC1(name, type)			\
+	static unsigned long				\
+	ia64_native_ ## name ## _func(type arg)		\
+	{						\
+		return ia64_native_ ## name(arg);	\
+	}						\
+
+DEFINE_VOID_FUNC1(fc);
+DEFINE_VOID_FUNC1(intrin_local_irq_restore);
+
+DEFINE_VOID_FUNC2(ptcga);
+DEFINE_VOID_FUNC2(set_rr);
+
+DEFINE_FUNC0(get_psr_i);
+
+DEFINE_FUNC1(thash, unsigned long);
+DEFINE_FUNC1(get_cpuid, int);
+DEFINE_FUNC1(get_pmd, int);
+DEFINE_FUNC1(get_rr, unsigned long);
+
+static void
+ia64_native_ssm_i_func(void)
+{
+	ia64_native_ssm(IA64_PSR_I);
+}
+
+static void
+ia64_native_rsm_i_func(void)
+{
+	ia64_native_rsm(IA64_PSR_I);
+}
+
+static void
+ia64_native_set_rr0_to_rr4_func(unsigned long val0, unsigned long val1,
+				unsigned long val2, unsigned long val3,
+				unsigned long val4)
+{
+	ia64_native_set_rr0_to_rr4(val0, val1, val2, val3, val4);
+}
+
+#define CASE_GET_REG(id)				\
+	case _IA64_REG_ ## id:				\
+	res = ia64_native_getreg(_IA64_REG_ ## id);	\
+	break;
+#define CASE_GET_AR(id) CASE_GET_REG(AR_ ## id)
+#define CASE_GET_CR(id) CASE_GET_REG(CR_ ## id)
+
+unsigned long
+ia64_native_getreg_func(int regnum)
+{
+	unsigned long res = -1;
+	switch (regnum) {
+	CASE_GET_REG(GP);
+	CASE_GET_REG(IP);
+	CASE_GET_REG(PSR);
+	CASE_GET_REG(TP);
+	CASE_GET_REG(SP);
+
+	CASE_GET_AR(KR0);
+	CASE_GET_AR(KR1);
+	CASE_GET_AR(KR2);
+	CASE_GET_AR(KR3);
+	CASE_GET_AR(KR4);
+	CASE_GET_AR(KR5);
+	CASE_GET_AR(KR6);
+	CASE_GET_AR(KR7);
+	CASE_GET_AR(RSC);
+	CASE_GET_AR(BSP);
+	CASE_GET_AR(BSPSTORE);
+	CASE_GET_AR(RNAT);
+	CASE_GET_AR(FCR);
+	CASE_GET_AR(EFLAG);
+	CASE_GET_AR(CSD);
+	CASE_GET_AR(SSD);
+	CASE_GET_AR(CFLAG);
+	CASE_GET_AR(FSR);
+	CASE_GET_AR(FIR);
+	CASE_GET_AR(FDR);
+	CASE_GET_AR(CCV);
+	CASE_GET_AR(UNAT);
+	CASE_GET_AR(FPSR);
+	CASE_GET_AR(ITC);
+	CASE_GET_AR(PFS);
+	CASE_GET_AR(LC);
+	CASE_GET_AR(EC);
+
+	CASE_GET_CR(DCR);
+	CASE_GET_CR(ITM);
+	CASE_GET_CR(IVA);
+	CASE_GET_CR(PTA);
+	CASE_GET_CR(IPSR);
+	CASE_GET_CR(ISR);
+	CASE_GET_CR(IIP);
+	CASE_GET_CR(IFA);
+	CASE_GET_CR(ITIR);
+	CASE_GET_CR(IIPA);
+	CASE_GET_CR(IFS);
+	CASE_GET_CR(IIM);
+	CASE_GET_CR(IHA);
+	CASE_GET_CR(LID);
+	CASE_GET_CR(IVR);
+	CASE_GET_CR(TPR);
+	CASE_GET_CR(EOI);
+	CASE_GET_CR(IRR0);
+	CASE_GET_CR(IRR1);
+	CASE_GET_CR(IRR2);
+	CASE_GET_CR(IRR3);
+	CASE_GET_CR(ITV);
+	CASE_GET_CR(PMV);
+	CASE_GET_CR(CMCV);
+	CASE_GET_CR(LRR0);
+	CASE_GET_CR(LRR1);
+
+	default:
+		printk(KERN_CRIT "wrong_getreg %d\n", regnum);
+		break;
+	}
+	return res;
+}
+
+#define CASE_SET_REG(id)				\
+	case _IA64_REG_ ## id:				\
+	ia64_native_setreg(_IA64_REG_ ## id, val);	\
+	break;
+#define CASE_SET_AR(id) CASE_SET_REG(AR_ ## id)
+#define CASE_SET_CR(id) CASE_SET_REG(CR_ ## id)
+
+void
+ia64_native_setreg_func(int regnum, unsigned long val)
+{
+	switch (regnum) {
+	case _IA64_REG_PSR_L:
+		ia64_native_setreg(_IA64_REG_PSR_L, val);
+		ia64_dv_serialize_data();
+		break;
+	CASE_SET_REG(SP);
+	CASE_SET_REG(GP);
+
+	CASE_SET_AR(KR0);
+	CASE_SET_AR(KR1);
+	CASE_SET_AR(KR2);
+	CASE_SET_AR(KR3);
+	CASE_SET_AR(KR4);
+	CASE_SET_AR(KR5);
+	CASE_SET_AR(KR6);
+	CASE_SET_AR(KR7);
+	CASE_SET_AR(RSC);
+	CASE_SET_AR(BSP);
+	CASE_SET_AR(BSPSTORE);
+	CASE_SET_AR(RNAT);
+	CASE_SET_AR(FCR);
+	CASE_SET_AR(EFLAG);
+	CASE_SET_AR(CSD);
+	CASE_SET_AR(SSD);
+	CASE_SET_AR(CFLAG);
+	CASE_SET_AR(FSR);
+	CASE_SET_AR(FIR);
+	CASE_SET_AR(FDR);
+	CASE_SET_AR(CCV);
+	CASE_SET_AR(UNAT);
+	CASE_SET_AR(FPSR);
+	CASE_SET_AR(ITC);
+	CASE_SET_AR(PFS);
+	CASE_SET_AR(LC);
+	CASE_SET_AR(EC);
+
+	CASE_SET_CR(DCR);
+	CASE_SET_CR(ITM);
+	CASE_SET_CR(IVA);
+	CASE_SET_CR(PTA);
+	CASE_SET_CR(IPSR);
+	CASE_SET_CR(ISR);
+	CASE_SET_CR(IIP);
+	CASE_SET_CR(IFA);
+	CASE_SET_CR(ITIR);
+	CASE_SET_CR(IIPA);
+	CASE_SET_CR(IFS);
+	CASE_SET_CR(IIM);
+	CASE_SET_CR(IHA);
+	CASE_SET_CR(LID);
+	CASE_SET_CR(IVR);
+	CASE_SET_CR(TPR);
+	CASE_SET_CR(EOI);
+	CASE_SET_CR(IRR0);
+	CASE_SET_CR(IRR1);
+	CASE_SET_CR(IRR2);
+	CASE_SET_CR(IRR3);
+	CASE_SET_CR(ITV);
+	CASE_SET_CR(PMV);
+	CASE_SET_CR(CMCV);
+	CASE_SET_CR(LRR0);
+	CASE_SET_CR(LRR1);
+	default:
+		printk(KERN_CRIT "wrong setreg %d\n", regnum);
+		break;
+	}
+}
+
+struct pv_cpu_ops pv_cpu_ops = {
+	.fc		= ia64_native_fc_func,
+	.thash		= ia64_native_thash_func,
+	.get_cpuid	= ia64_native_get_cpuid_func,
+	.get_pmd	= ia64_native_get_pmd_func,
+	.ptcga		= ia64_native_ptcga_func,
+	.get_rr		= ia64_native_get_rr_func,
+	.set_rr		= ia64_native_set_rr_func,
+	.set_rr0_to_rr4	= ia64_native_set_rr0_to_rr4_func,
+	.ssm_i		= ia64_native_ssm_i_func,
+	.getreg		= ia64_native_getreg_func,
+	.setreg		= ia64_native_setreg_func,
+	.rsm_i		= ia64_native_rsm_i_func,
+	.get_psr_i	= ia64_native_get_psr_i_func,
+	.intrin_local_irq_restore
+			= ia64_native_intrin_local_irq_restore_func,
+};
+EXPORT_SYMBOL(pv_cpu_ops);
+
+/******************************************************************************
+ * replacement of hand written assembly codes.
+ */
+
+void
+paravirt_cpu_asm_init(const struct pv_cpu_asm_switch *cpu_asm_switch)
+{
+	extern unsigned long paravirt_switch_to_targ;
+	extern unsigned long paravirt_leave_syscall_targ;
+	extern unsigned long paravirt_work_processed_syscall_targ;
+	extern unsigned long paravirt_leave_kernel_targ;
+
+	paravirt_switch_to_targ = cpu_asm_switch->switch_to;
+	paravirt_leave_syscall_targ = cpu_asm_switch->leave_syscall;
+	paravirt_work_processed_syscall_targ =
+		cpu_asm_switch->work_processed_syscall;
+	paravirt_leave_kernel_targ = cpu_asm_switch->leave_kernel;
+}
+
+/***************************************************************************
+ * pv_iosapic_ops
+ * iosapic read/write hooks.
+ */
+
+static unsigned int
+ia64_native_iosapic_read(char __iomem *iosapic, unsigned int reg)
+{
+	return __ia64_native_iosapic_read(iosapic, reg);
+}
+
+static void
+ia64_native_iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val)
+{
+	__ia64_native_iosapic_write(iosapic, reg, val);
+}
+
+struct pv_iosapic_ops pv_iosapic_ops = {
+	.pcat_compat_init = ia64_native_iosapic_pcat_compat_init,
+	.get_irq_chip = ia64_native_iosapic_get_irq_chip,
+
+	.__read = ia64_native_iosapic_read,
+	.__write = ia64_native_iosapic_write,
+};
+
+/***************************************************************************
+ * pv_irq_ops
+ * irq operations
+ */
+
+struct pv_irq_ops pv_irq_ops = {
+	.register_ipi = ia64_native_register_ipi,
+
+	.assign_irq_vector = ia64_native_assign_irq_vector,
+	.free_irq_vector = ia64_native_free_irq_vector,
+	.register_percpu_irq = ia64_native_register_percpu_irq,
+
+	.resend_irq = ia64_native_resend_irq,
+};
+
+/***************************************************************************
+ * pv_time_ops
+ * time operations
+ */
+
+static int
+ia64_native_do_steal_accounting(unsigned long *new_itm)
+{
+	return 0;
+}
+
+struct pv_time_ops pv_time_ops = {
+	.do_steal_accounting = ia64_native_do_steal_accounting,
+};
diff --git a/arch/ia64/kernel/paravirt_inst.h b/arch/ia64/kernel/paravirt_inst.h
new file mode 100644
index 0000000..5cad6fb
--- /dev/null
+++ b/arch/ia64/kernel/paravirt_inst.h
@@ -0,0 +1,29 @@
+/******************************************************************************
+ * linux/arch/ia64/xen/paravirt_inst.h
+ *
+ * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * 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
+ *
+ */
+
+#ifdef __IA64_ASM_PARAVIRTUALIZED_XEN
+#include <asm/xen/inst.h>
+#include <asm/xen/minstate.h>
+#else
+#include <asm/native/inst.h>
+#endif
+
diff --git a/arch/ia64/kernel/paravirtentry.S b/arch/ia64/kernel/paravirtentry.S
new file mode 100644
index 0000000..2f42fcb
--- /dev/null
+++ b/arch/ia64/kernel/paravirtentry.S
@@ -0,0 +1,60 @@
+/******************************************************************************
+ * linux/arch/ia64/xen/paravirtentry.S
+ *
+ * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * 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 <asm/asmmacro.h>
+#include <asm/asm-offsets.h>
+#include "entry.h"
+
+#define DATA8(sym, init_value)			\
+	.pushsection .data.read_mostly ;	\
+	.align 8 ;				\
+	.global sym ;				\
+	sym: ;					\
+	data8 init_value ;			\
+	.popsection
+
+#define BRANCH(targ, reg, breg)		\
+	movl reg=targ ;			\
+	;;				\
+	ld8 reg=[reg] ;			\
+	;;				\
+	mov breg=reg ;			\
+	br.cond.sptk.many breg
+
+#define BRANCH_PROC(sym, reg, breg)				\
+	DATA8(paravirt_ ## sym ## _targ, ia64_native_ ## sym) ; \
+	GLOBAL_ENTRY(paravirt_ ## sym) ;			\
+		BRANCH(paravirt_ ## sym ## _targ, reg, breg) ;	\
+	END(paravirt_ ## sym)
+
+#define BRANCH_PROC_UNWINFO(sym, reg, breg)			\
+	DATA8(paravirt_ ## sym ## _targ, ia64_native_ ## sym) ; \
+	GLOBAL_ENTRY(paravirt_ ## sym) ;			\
+		PT_REGS_UNWIND_INFO(0) ;			\
+		BRANCH(paravirt_ ## sym ## _targ, reg, breg) ;	\
+	END(paravirt_ ## sym)
+
+
+BRANCH_PROC(switch_to, r22, b7)
+BRANCH_PROC_UNWINFO(leave_syscall, r22, b7)
+BRANCH_PROC(work_processed_syscall, r2, b7)
+BRANCH_PROC_UNWINFO(leave_kernel, r22, b7)
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 632cda8..e5c2de9 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -51,6 +51,7 @@
 #include <asm/mca.h>
 #include <asm/meminit.h>
 #include <asm/page.h>
+#include <asm/paravirt.h>
 #include <asm/patch.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
@@ -341,6 +342,8 @@
 	rsvd_region[n].end   = (unsigned long) ia64_imva(_end);
 	n++;
 
+	n += paravirt_reserve_memory(&rsvd_region[n]);
+
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (ia64_boot_param->initrd_start) {
 		rsvd_region[n].start = (unsigned long)__va(ia64_boot_param->initrd_start);
@@ -519,6 +522,8 @@
 {
 	unw_init();
 
+	paravirt_arch_setup_early();
+
 	ia64_patch_vtop((u64) __start___vtop_patchlist, (u64) __end___vtop_patchlist);
 
 	*cmdline_p = __va(ia64_boot_param->command_line);
@@ -583,6 +588,9 @@
 	acpi_boot_init();
 #endif
 
+	paravirt_banner();
+	paravirt_arch_setup_console(cmdline_p);
+
 #ifdef CONFIG_VT
 	if (!conswitchp) {
 # if defined(CONFIG_DUMMY_CONSOLE)
@@ -602,6 +610,8 @@
 #endif
 
 	/* enable IA-64 Machine Check Abort Handling unless disabled */
+	if (paravirt_arch_setup_nomca())
+		nomca = 1;
 	if (!nomca)
 		ia64_mca_init();
 
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 9d1d429..03f1a99 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -50,6 +50,7 @@
 #include <asm/machvec.h>
 #include <asm/mca.h>
 #include <asm/page.h>
+#include <asm/paravirt.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
@@ -642,6 +643,7 @@
 	cpu_set(smp_processor_id(), cpu_online_map);
 	cpu_set(smp_processor_id(), cpu_callin_map);
 	per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
+	paravirt_post_smp_prepare_boot_cpu();
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index aad1b7b..65c10a4 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -24,6 +24,7 @@
 #include <asm/machvec.h>
 #include <asm/delay.h>
 #include <asm/hw_irq.h>
+#include <asm/paravirt.h>
 #include <asm/ptrace.h>
 #include <asm/sal.h>
 #include <asm/sections.h>
@@ -48,6 +49,15 @@
 
 #endif
 
+#ifdef CONFIG_PARAVIRT
+static void
+paravirt_clocksource_resume(void)
+{
+	if (pv_time_ops.clocksource_resume)
+		pv_time_ops.clocksource_resume();
+}
+#endif
+
 static struct clocksource clocksource_itc = {
 	.name           = "itc",
 	.rating         = 350,
@@ -56,6 +66,9 @@
 	.mult           = 0, /*to be calculated*/
 	.shift          = 16,
 	.flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+#ifdef CONFIG_PARAVIRT
+	.resume		= paravirt_clocksource_resume,
+#endif
 };
 static struct clocksource *itc_clocksource;
 
@@ -157,6 +170,9 @@
 
 	profile_tick(CPU_PROFILING);
 
+	if (paravirt_do_steal_accounting(&new_itm))
+		goto skip_process_time_accounting;
+
 	while (1) {
 		update_process_times(user_mode(get_irq_regs()));
 
@@ -186,6 +202,8 @@
 		local_irq_disable();
 	}
 
+skip_process_time_accounting:
+
 	do {
 		/*
 		 * If we're too close to the next clock tick for
@@ -335,6 +353,11 @@
 		 */
 		clocksource_itc.rating = 50;
 
+	paravirt_init_missing_ticks_accounting(smp_processor_id());
+
+	/* avoid softlock up message when cpu is unplug and plugged again. */
+	touch_softlockup_watchdog();
+
 	/* Setup the CPU local timer tick */
 	ia64_cpu_local_tick();
 
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index 5929ab1..5a77206 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -4,7 +4,6 @@
 #include <asm/system.h>
 #include <asm/pgtable.h>
 
-#define LOAD_OFFSET	(KERNEL_START - KERNEL_TR_PAGE_SIZE)
 #include <asm-generic/vmlinux.lds.h>
 
 #define IVT_TEXT							\
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index b556419..dfd868b 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -522,8 +522,8 @@
 		atomic_set(&channel_wqs[i].in_open, 0);
 		mutex_init(&channel_wqs[i].mutex);
 
-		dev = device_create(mt_class, NULL, MKDEV(major, i),
-		                    "%s%d", module_name, i);
+		dev = device_create_drvdata(mt_class, NULL, MKDEV(major, i),
+					    NULL, "%s%d", module_name, i);
 		if (IS_ERR(dev)) {
 			err = PTR_ERR(dev);
 			goto out_chrdev;
diff --git a/arch/mips/sibyte/common/sb_tbprof.c b/arch/mips/sibyte/common/sb_tbprof.c
index 28b012a..66e3e3f 100644
--- a/arch/mips/sibyte/common/sb_tbprof.c
+++ b/arch/mips/sibyte/common/sb_tbprof.c
@@ -576,7 +576,8 @@
 
 	tb_class = tbc;
 
-	dev = device_create(tbc, NULL, MKDEV(SBPROF_TB_MAJOR, 0), "tb");
+	dev = device_create_drvdata(tbc, NULL, MKDEV(SBPROF_TB_MAJOR, 0),
+				    NULL, "tb");
 	if (IS_ERR(dev)) {
 		err = PTR_ERR(dev);
 		goto out_class;
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index de88972..737ebf9 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -112,6 +112,7 @@
 	select HAVE_FTRACE
 	select HAVE_IDE
 	select HAVE_KPROBES
+	select HAVE_ARCH_KGDB
 	select HAVE_KRETPROBES
 	select HAVE_LMB
 	select HAVE_DMA_ATTRS if PPC64
@@ -199,7 +200,7 @@
 
 config ARCH_SUSPEND_POSSIBLE
 	def_bool y
-	depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200
+	depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx
 
 config PPC_DCR_NATIVE
 	bool
@@ -568,11 +569,15 @@
 config MCA
 	bool
 
+# Platforms that what PCI turned unconditionally just do select PCI
+# in their config node.  Platforms that want to choose at config
+# time should select PPC_PCI_CHOICE
+config PPC_PCI_CHOICE
+	bool
+
 config PCI
-	bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \
-		|| PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \
-		|| PPC_PS3 || 44x
-	default y if !40x && !CPM2 && !8xx && !PPC_MPC512x && !PPC_83xx \
+	bool "PCI support" if PPC_PCI_CHOICE
+	default y if !40x && !CPM2 && !8xx && !PPC_83xx \
 		&& !PPC_85xx && !PPC_86xx
 	default PCI_PERMEDIA if !4xx && !CPM2 && !8xx
 	default PCI_QSPAN if !4xx && !CPM2 && 8xx
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 2840ab6..8c8aadb 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -41,22 +41,6 @@
 	  This option will add a small amount of overhead to all hypervisor
 	  calls.
 
-config DEBUGGER
-	bool "Enable debugger hooks"
-	depends on DEBUG_KERNEL
-	help
-	  Include in-kernel hooks for kernel debuggers. Unless you are
-	  intending to debug the kernel, say N here.
-
-config KGDB
-	bool "Include kgdb kernel debugger"
-	depends on DEBUGGER && (BROKEN || PPC_GEN550 || 4xx)
-	select DEBUG_INFO
-	help
-	  Include in-kernel hooks for kgdb, the Linux kernel source level
-	  debugger.  See <http://kgdb.sourceforge.net/> for more information.
-	  Unless you are intending to debug the kernel, say N here.
-
 config CODE_PATCHING_SELFTEST
 	bool "Run self-tests of the code-patching code."
 	depends on DEBUG_KERNEL
@@ -67,36 +51,9 @@
 	depends on DEBUG_KERNEL
 	default n
 
-choice
-	prompt "Serial Port"
-	depends on KGDB
-	default KGDB_TTYS1
-
-config KGDB_TTYS0
-	bool "ttyS0"
-
-config KGDB_TTYS1
-	bool "ttyS1"
-
-config KGDB_TTYS2
-	bool "ttyS2"
-
-config KGDB_TTYS3
-	bool "ttyS3"
-
-endchoice
-
-config KGDB_CONSOLE
-	bool "Enable serial console thru kgdb port"
-	depends on KGDB && 8xx || CPM2
-	help
-	  If you enable this, all serial console messages will be sent
-	  over the gdb stub.
-	  If unsure, say N.
-
 config XMON
 	bool "Include xmon kernel debugger"
-	depends on DEBUGGER
+	depends on DEBUG_KERNEL
 	help
 	  Include in-kernel hooks for the xmon kernel monitor/debugger.
 	  Unless you are intending to debug the kernel, say N here.
@@ -126,6 +83,11 @@
 	  to say Y here, unless you're building for a memory-constrained
 	  system.
 
+config DEBUGGER
+	bool
+	depends on KGDB || XMON
+	default y
+
 config IRQSTACKS
 	bool "Use separate kernel stacks when processing interrupts"
 	help
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 19f83c8..14174aa 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -163,12 +163,12 @@
       cmd_flex = $(FLEX) -o$@ $<; cp $@ $@_shipped
 
 $(obj)/dtc-src/dtc-parser.tab.c: $(src)/dtc-src/dtc-parser.y FORCE
-     $(call if_changed,bison)
+	$(call if_changed,bison)
 
 $(obj)/dtc-src/dtc-parser.tab.h: $(obj)/dtc-src/dtc-parser.tab.c
 
 $(obj)/dtc-src/dtc-lexer.lex.c: $(src)/dtc-src/dtc-lexer.l FORCE
-     $(call if_changed,flex)
+	$(call if_changed,flex)
 endif
 
 #############
diff --git a/arch/powerpc/boot/dts/mpc7448hpc2.dts b/arch/powerpc/boot/dts/mpc7448hpc2.dts
index 705c23c..2544f3e 100644
--- a/arch/powerpc/boot/dts/mpc7448hpc2.dts
+++ b/arch/powerpc/boot/dts/mpc7448hpc2.dts
@@ -18,6 +18,16 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+
+		serial0 = &serial0;
+		serial1 = &serial1;
+
+		pci0 = &pci0;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells =<0>;
@@ -78,7 +88,7 @@
 
 		};
 
-		ethernet@6200 {
+		enet0: ethernet@6200 {
 			linux,network-index = <0>;
 			#size-cells = <0>;
 			device_type = "network";
@@ -91,7 +101,7 @@
 			phy-handle = <&phy8>;
 		};
 
-		ethernet@6600 {
+		enet1: ethernet@6600 {
 			linux,network-index = <1>;
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -105,7 +115,7 @@
 			phy-handle = <&phy9>;
 		};
 
-		serial@7808 {
+		serial0: serial@7808 {
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <0x7808 0x200>;
@@ -114,7 +124,7 @@
 			interrupt-parent = <&mpic>;
 		};
 
-		serial@7c08 {
+		serial1: serial@7c08 {
 			device_type = "serial";
 			compatible = "ns16550";
 			reg = <0x7c08 0x200>;
@@ -131,7 +141,7 @@
 			compatible = "chrp,open-pic";
 			device_type = "open-pic";
 		};
-		pci@1000 {
+		pci0: pci@1000 {
 			compatible = "tsi108-pci";
 			device_type = "pci";
 			#interrupt-cells = <1>;
@@ -184,8 +194,4 @@
 			};
 		};
 	};
-	chosen {
-		linux,stdout-path = "/tsi108@c0000000/serial@7808";
-	};
-
 };
diff --git a/arch/powerpc/boot/dts/mpc8313erdb.dts b/arch/powerpc/boot/dts/mpc8313erdb.dts
index 3664fb5..2a94ae0 100644
--- a/arch/powerpc/boot/dts/mpc8313erdb.dts
+++ b/arch/powerpc/boot/dts/mpc8313erdb.dts
@@ -109,18 +109,38 @@
 			reg = <0x200 0x100>;
 		};
 
-		i2c@3000 {
+		sleep-nexus {
 			#address-cells = <1>;
-			#size-cells = <0>;
-			cell-index = <0>;
-			compatible = "fsl-i2c";
-			reg = <0x3000 0x100>;
-			interrupts = <14 0x8>;
-			interrupt-parent = <&ipic>;
-			dfsrr;
-			rtc@68 {
-				compatible = "dallas,ds1339";
-				reg = <0x68>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			sleep = <&pmc 0x03000000>;
+			ranges;
+
+			i2c@3000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				cell-index = <0>;
+				compatible = "fsl-i2c";
+				reg = <0x3000 0x100>;
+				interrupts = <14 0x8>;
+				interrupt-parent = <&ipic>;
+				dfsrr;
+				rtc@68 {
+					compatible = "dallas,ds1339";
+					reg = <0x68>;
+				};
+			};
+
+			crypto@30000 {
+				compatible = "fsl,sec2.2", "fsl,sec2.1",
+				             "fsl,sec2.0";
+				reg = <0x30000 0x10000>;
+				interrupts = <11 0x8>;
+				interrupt-parent = <&ipic>;
+				fsl,num-channels = <1>;
+				fsl,channel-fifo-len = <24>;
+				fsl,exec-units-mask = <0x4c>;
+				fsl,descriptor-types-mask = <0x0122003f>;
 			};
 		};
 
@@ -188,37 +208,44 @@
 			interrupt-parent = <&ipic>;
 			interrupts = <38 0x8>;
 			phy_type = "utmi_wide";
-		};
-
-		mdio@24520 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "fsl,gianfar-mdio";
-			reg = <0x24520 0x20>;
-			phy1: ethernet-phy@1 {
-				interrupt-parent = <&ipic>;
-				interrupts = <19 0x8>;
-				reg = <0x1>;
-				device_type = "ethernet-phy";
-			};
-			phy4: ethernet-phy@4 {
-				interrupt-parent = <&ipic>;
-				interrupts = <20 0x8>;
-				reg = <0x4>;
-				device_type = "ethernet-phy";
-			};
+			sleep = <&pmc 0x00300000>;
 		};
 
 		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			sleep = <&pmc 0x20000000>;
+			ranges;
+
 			cell-index = <0>;
 			device_type = "network";
 			model = "eTSEC";
-			compatible = "gianfar";
+			compatible = "gianfar", "simple-bus";
 			reg = <0x24000 0x1000>;
 			local-mac-address = [ 00 00 00 00 00 00 ];
 			interrupts = <37 0x8 36 0x8 35 0x8>;
 			interrupt-parent = <&ipic>;
 			phy-handle = < &phy1 >;
+			fsl,magic-packet;
+
+			mdio@24520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x24520 0x20>;
+				phy1: ethernet-phy@1 {
+					interrupt-parent = <&ipic>;
+					interrupts = <19 0x8>;
+					reg = <0x1>;
+					device_type = "ethernet-phy";
+				};
+				phy4: ethernet-phy@4 {
+					interrupt-parent = <&ipic>;
+					interrupts = <20 0x8>;
+					reg = <0x4>;
+					device_type = "ethernet-phy";
+				};
+			};
 		};
 
 		enet1: ethernet@25000 {
@@ -231,6 +258,8 @@
 			interrupts = <34 0x8 33 0x8 32 0x8>;
 			interrupt-parent = <&ipic>;
 			phy-handle = < &phy4 >;
+			sleep = <&pmc 0x10000000>;
+			fsl,magic-packet;
 		};
 
 		serial0: serial@4500 {
@@ -253,17 +282,6 @@
 			interrupt-parent = <&ipic>;
 		};
 
-		crypto@30000 {
-			compatible = "fsl,sec2.2", "fsl,sec2.1", "fsl,sec2.0";
-			reg = <0x30000 0x10000>;
-			interrupts = <11 0x8>;
-			interrupt-parent = <&ipic>;
-			fsl,num-channels = <1>;
-			fsl,channel-fifo-len = <24>;
-			fsl,exec-units-mask = <0x4c>;
-			fsl,descriptor-types-mask = <0x0122003f>;
-		};
-
 		/* IPIC
 		 * interrupts cell = <intr #, sense>
 		 * sense values match linux IORESOURCE_IRQ_* defines:
@@ -277,36 +295,119 @@
 			reg = <0x700 0x100>;
 			device_type = "ipic";
 		};
+
+		pmc: power@b00 {
+			compatible = "fsl,mpc8313-pmc", "fsl,mpc8349-pmc";
+			reg = <0xb00 0x100 0xa00 0x100>;
+			interrupts = <80 8>;
+			interrupt-parent = <&ipic>;
+			fsl,mpc8313-wakeup-timer = <&gtm1>;
+
+			/* Remove this (or change to "okay") if you have
+			 * a REVA3 or later board, if you apply one of the
+			 * workarounds listed in section 8.5 of the board
+			 * manual, or if you are adapting this device tree
+			 * to a different board.
+			 */
+			status = "fail";
+		};
+
+		gtm1: timer@500 {
+			compatible = "fsl,mpc8313-gtm", "fsl,gtm";
+			reg = <0x500 0x100>;
+			interrupts = <90 8 78 8 84 8 72 8>;
+			interrupt-parent = <&ipic>;
+		};
+
+		timer@600 {
+			compatible = "fsl,mpc8313-gtm", "fsl,gtm";
+			reg = <0x600 0x100>;
+			interrupts = <91 8 79 8 85 8 73 8>;
+			interrupt-parent = <&ipic>;
+		};
 	};
 
-	pci0: pci@e0008500 {
-		cell-index = <1>;
-		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
-		interrupt-map = <
+	sleep-nexus {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		sleep = <&pmc 0x00010000>;
+		ranges;
 
-				/* IDSEL 0x0E -mini PCI */
-				 0x7000 0x0 0x0 0x1 &ipic 18 0x8
-				 0x7000 0x0 0x0 0x2 &ipic 18 0x8
-				 0x7000 0x0 0x0 0x3 &ipic 18 0x8
-				 0x7000 0x0 0x0 0x4 &ipic 18 0x8
+		pci0: pci@e0008500 {
+			cell-index = <1>;
+			interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+			interrupt-map = <
+					/* IDSEL 0x0E -mini PCI */
+					 0x7000 0x0 0x0 0x1 &ipic 18 0x8
+					 0x7000 0x0 0x0 0x2 &ipic 18 0x8
+					 0x7000 0x0 0x0 0x3 &ipic 18 0x8
+					 0x7000 0x0 0x0 0x4 &ipic 18 0x8
 
-				/* IDSEL 0x0F - PCI slot */
-				 0x7800 0x0 0x0 0x1 &ipic 17 0x8
-				 0x7800 0x0 0x0 0x2 &ipic 18 0x8
-				 0x7800 0x0 0x0 0x3 &ipic 17 0x8
-				 0x7800 0x0 0x0 0x4 &ipic 18 0x8>;
-		interrupt-parent = <&ipic>;
-		interrupts = <66 0x8>;
-		bus-range = <0x0 0x0>;
-		ranges = <0x02000000 0x0 0x90000000 0x90000000 0x0 0x10000000
-			  0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000
-			  0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
-		clock-frequency = <66666666>;
-		#interrupt-cells = <1>;
-		#size-cells = <2>;
-		#address-cells = <3>;
-		reg = <0xe0008500 0x100>;
-		compatible = "fsl,mpc8349-pci";
-		device_type = "pci";
+					/* IDSEL 0x0F - PCI slot */
+					 0x7800 0x0 0x0 0x1 &ipic 17 0x8
+					 0x7800 0x0 0x0 0x2 &ipic 18 0x8
+					 0x7800 0x0 0x0 0x3 &ipic 17 0x8
+					 0x7800 0x0 0x0 0x4 &ipic 18 0x8>;
+			interrupt-parent = <&ipic>;
+			interrupts = <66 0x8>;
+			bus-range = <0x0 0x0>;
+			ranges = <0x02000000 0x0 0x90000000 0x90000000 0x0 0x10000000
+				  0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000
+				  0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
+			clock-frequency = <66666666>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <0xe0008500 0x100>;
+			compatible = "fsl,mpc8349-pci";
+			device_type = "pci";
+		};
+
+		dma@82a8 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8313-dma", "fsl,elo-dma";
+			reg = <0xe00082a8 4>;
+			ranges = <0 0xe0008100 0x1a8>;
+			interrupt-parent = <&ipic>;
+			interrupts = <71 8>;
+
+			dma-channel@0 {
+				compatible = "fsl,mpc8313-dma-channel",
+				             "fsl,elo-dma-channel";
+				reg = <0 0x28>;
+				interrupt-parent = <&ipic>;
+				interrupts = <71 8>;
+				cell-index = <0>;
+			};
+
+			dma-channel@80 {
+				compatible = "fsl,mpc8313-dma-channel",
+				             "fsl,elo-dma-channel";
+				reg = <0x80 0x28>;
+				interrupt-parent = <&ipic>;
+				interrupts = <71 8>;
+				cell-index = <1>;
+			};
+
+			dma-channel@100 {
+				compatible = "fsl,mpc8313-dma-channel",
+				             "fsl,elo-dma-channel";
+				reg = <0x100 0x28>;
+				interrupt-parent = <&ipic>;
+				interrupts = <71 8>;
+				cell-index = <2>;
+			};
+
+			dma-channel@180 {
+				compatible = "fsl,mpc8313-dma-channel",
+				             "fsl,elo-dma-channel";
+				reg = <0x180 0x28>;
+				interrupt-parent = <&ipic>;
+				interrupts = <71 8>;
+				cell-index = <3>;
+			};
+		};
 	};
 };
diff --git a/arch/powerpc/boot/dts/mpc8610_hpcd.dts b/arch/powerpc/boot/dts/mpc8610_hpcd.dts
index 981941e..666185f 100644
--- a/arch/powerpc/boot/dts/mpc8610_hpcd.dts
+++ b/arch/powerpc/boot/dts/mpc8610_hpcd.dts
@@ -388,6 +388,20 @@
 					  0x01000000 0x0 0x00000000
 					  0x01000000 0x0 0x00000000
 					  0x0 0x00100000>;
+
+				isa@1e {
+					device_type = "isa";
+					#size-cells = <1>;
+					#address-cells = <2>;
+					reg = <0xf000 0 0 0 0>;
+					ranges = <1 0 0x01000000 0 0
+						  0x00001000>;
+
+					rtc@70 {
+						compatible = "pnpPNP,b00";
+						reg = <1 0x70 2>;
+					};
+				};
 			};
 		};
 	};
diff --git a/arch/powerpc/configs/85xx/mpc8544_ds_defconfig b/arch/powerpc/configs/85xx/mpc8544_ds_defconfig
index 042a85e..a0583e5 100644
--- a/arch/powerpc/configs/85xx/mpc8544_ds_defconfig
+++ b/arch/powerpc/configs/85xx/mpc8544_ds_defconfig
@@ -997,10 +997,12 @@
 CONFIG_SND_TIMER=y
 CONFIG_SND_PCM=y
 # CONFIG_SND_SEQUENCER is not set
-# CONFIG_SND_MIXER_OSS is not set
-# CONFIG_SND_PCM_OSS is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
 # CONFIG_SND_DYNAMIC_MINORS is not set
-CONFIG_SND_SUPPORT_OLD_API=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
 CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
diff --git a/arch/powerpc/configs/85xx/mpc8572_ds_defconfig b/arch/powerpc/configs/85xx/mpc8572_ds_defconfig
index 03627cfe..164fd96 100644
--- a/arch/powerpc/configs/85xx/mpc8572_ds_defconfig
+++ b/arch/powerpc/configs/85xx/mpc8572_ds_defconfig
@@ -997,10 +997,12 @@
 CONFIG_SND_TIMER=y
 CONFIG_SND_PCM=y
 # CONFIG_SND_SEQUENCER is not set
-# CONFIG_SND_MIXER_OSS is not set
-# CONFIG_SND_PCM_OSS is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
 # CONFIG_SND_DYNAMIC_MINORS is not set
-CONFIG_SND_SUPPORT_OLD_API=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
 CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig
index 3efab71..fa01705 100644
--- a/arch/powerpc/configs/mpc85xx_defconfig
+++ b/arch/powerpc/configs/mpc85xx_defconfig
@@ -1005,10 +1005,12 @@
 CONFIG_SND_TIMER=y
 CONFIG_SND_PCM=y
 # CONFIG_SND_SEQUENCER is not set
-# CONFIG_SND_MIXER_OSS is not set
-# CONFIG_SND_PCM_OSS is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
 # CONFIG_SND_DYNAMIC_MINORS is not set
-CONFIG_SND_SUPPORT_OLD_API=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
 CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
diff --git a/arch/powerpc/configs/mpc8610_hpcd_defconfig b/arch/powerpc/configs/mpc8610_hpcd_defconfig
index 5612d40..cdf98ae 100644
--- a/arch/powerpc/configs/mpc8610_hpcd_defconfig
+++ b/arch/powerpc/configs/mpc8610_hpcd_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.26-rc5
-# Mon Jun  9 08:50:24 2008
+# Linux kernel version: 2.6.26
+# Tue Jul 15 08:31:01 2008
 #
 # CONFIG_PPC64 is not set
 
@@ -51,6 +51,8 @@
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
 CONFIG_DEFAULT_UIMAGE=y
+CONFIG_HIBERNATE_32=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -97,6 +99,7 @@
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
+CONFIG_PCSPKR_PLATFORM=y
 CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
@@ -117,7 +120,7 @@
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
-# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_HAVE_DMA_ATTRS=y
 CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -153,31 +156,43 @@
 #
 # Platform support
 #
-# CONFIG_PPC_MULTIPLATFORM is not set
-# CONFIG_PPC_82xx is not set
-# CONFIG_PPC_83xx is not set
-CONFIG_PPC_86xx=y
+CONFIG_PPC_MULTIPLATFORM=y
+CONFIG_CLASSIC32=y
+CONFIG_PPC_CHRP=y
 # CONFIG_PPC_MPC512x is not set
 # CONFIG_PPC_MPC5121 is not set
+# CONFIG_MPC5121_ADS is not set
+# CONFIG_PPC_MPC52xx is not set
+CONFIG_PPC_PMAC=y
 # CONFIG_PPC_CELL is not set
 # CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
 # CONFIG_PQ2ADS is not set
+# CONFIG_PPC_83xx is not set
+CONFIG_PPC_86xx=y
 # CONFIG_MPC8641_HPCN is not set
 # CONFIG_SBC8641D is not set
 CONFIG_MPC8610_HPCD=y
 CONFIG_MPC8610=y
+# CONFIG_EMBEDDED6xx is not set
+CONFIG_PPC_NATIVE=y
+# CONFIG_UDBG_RTAS_CONSOLE is not set
 # CONFIG_IPIC is not set
 CONFIG_MPIC=y
 # CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
-# CONFIG_PPC_RTAS is not set
+CONFIG_PPC_I8259=y
+CONFIG_PPC_RTAS=y
+# CONFIG_RTAS_ERROR_LOGGING is not set
+CONFIG_RTAS_PROC=y
 # CONFIG_MMIO_NVRAM is not set
-# CONFIG_PPC_MPC106 is not set
+CONFIG_PPC_MPC106=y
 # CONFIG_PPC_970_NAP is not set
 # CONFIG_PPC_INDIRECT_IO is not set
 # CONFIG_GENERIC_IOMAP is not set
 # CONFIG_CPU_FREQ is not set
-# CONFIG_FSL_ULI1575 is not set
+# CONFIG_PPC601_SYNC_FIX is not set
+# CONFIG_TAU is not set
+CONFIG_FSL_ULI1575=y
 
 #
 # Kernel options
@@ -202,6 +217,7 @@
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+# CONFIG_KEXEC is not set
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
@@ -228,11 +244,13 @@
 #
 # Bus options
 #
+# CONFIG_ISA is not set
 CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_PPC_INDIRECT_PCI=y
 CONFIG_FSL_SOC=y
 CONFIG_FSL_PCI=y
+CONFIG_PPC_PCI_CHOICE=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 CONFIG_PCI_SYSCALL=y
@@ -469,6 +487,7 @@
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
+# CONFIG_MAC_FLOPPY 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
@@ -571,6 +590,8 @@
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_MESH is not set
+# CONFIG_SCSI_MAC53C94 is not set
 # CONFIG_SCSI_SRP is not set
 CONFIG_ATA=y
 # CONFIG_ATA_NONSTANDARD is not set
@@ -639,6 +660,10 @@
 #
 # IEEE 1394 (FireWire) support
 #
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
@@ -655,6 +680,8 @@
 # CONFIG_PHYLIB is not set
 CONFIG_NET_ETHERNET=y
 # CONFIG_MII is not set
+# CONFIG_MACE is not set
+# CONFIG_BMAC is not set
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 # CONFIG_CASSINI is not set
@@ -762,14 +789,16 @@
 # CONFIG_SERIAL_UARTLITE is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_PMACZILOG is not set
 # CONFIG_SERIAL_JSM is not set
 # CONFIG_SERIAL_OF_PLATFORM is not set
 CONFIG_UNIX98_PTYS=y
 # CONFIG_LEGACY_PTYS is not set
+# CONFIG_BRIQ_PANEL is not set
+# CONFIG_HVC_RTAS is not set
 # CONFIG_IPMI_HANDLER is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_NVRAM is not set
-# CONFIG_GEN_RTC is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_RAW_DRIVER is not set
@@ -787,9 +816,11 @@
 # CONFIG_I2C_ALI15X3 is not set
 # CONFIG_I2C_AMD756 is not set
 # CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_HYDRA is not set
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_POWERMAC=y
 CONFIG_I2C_MPC=y
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_OCORES is not set
@@ -826,6 +857,7 @@
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
 # CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
 
 #
@@ -888,6 +920,9 @@
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
 # CONFIG_FB_OF is not set
+# CONFIG_FB_CONTROL is not set
+# CONFIG_FB_PLATINUM is not set
+# CONFIG_FB_VALKYRIE is not set
 # CONFIG_FB_CT65550 is not set
 # CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
@@ -1027,12 +1062,19 @@
 #
 # ALSA PowerMac devices
 #
+# CONFIG_SND_POWERMAC is not set
 
 #
 # ALSA PowerPC devices
 #
 
 #
+# Apple Onboard Audio driver
+#
+# CONFIG_SND_AOA is not set
+# CONFIG_SND_AOA_SOUNDBUS is not set
+
+#
 # System on Chip audio support
 #
 CONFIG_SND_SOC=y
@@ -1075,7 +1117,57 @@
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_INFINIBAND is not set
 # CONFIG_EDAC is not set
-# CONFIG_RTC_CLASS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=y
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_PPC is not set
 # CONFIG_DMADEVICES is not set
 # CONFIG_UIO is not set
 
@@ -1295,8 +1387,11 @@
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_DEBUG_PAGEALLOC is not set
 # CONFIG_DEBUGGER is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BDI_SWITCH is not set
+# CONFIG_BOOTX_TEXT is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
 
 #
diff --git a/arch/powerpc/configs/mpc8641_hpcn_defconfig b/arch/powerpc/configs/mpc8641_hpcn_defconfig
index 4a81715..867b8c02 100644
--- a/arch/powerpc/configs/mpc8641_hpcn_defconfig
+++ b/arch/powerpc/configs/mpc8641_hpcn_defconfig
@@ -991,10 +991,12 @@
 CONFIG_SND_TIMER=y
 CONFIG_SND_PCM=y
 # CONFIG_SND_SEQUENCER is not set
-# CONFIG_SND_MIXER_OSS is not set
-# CONFIG_SND_PCM_OSS is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
 # CONFIG_SND_DYNAMIC_MINORS is not set
-CONFIG_SND_SUPPORT_OLD_API=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
 CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig
new file mode 100644
index 0000000..e6e91c8
--- /dev/null
+++ b/arch/powerpc/configs/ppc6xx_defconfig
@@ -0,0 +1,3304 @@
+# powerpc
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.26-git2
+# Tue Jul 15 23:54:18 2008
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+CONFIG_6xx=y
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_PPC_FPU=y
+CONFIG_FSL_EMB_PERFMON=y
+CONFIG_ALTIVEC=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_GPIO=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_DEFAULT_UIMAGE=y
+CONFIG_REDBOOT=y
+CONFIG_HIBERNATE_32=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+CONFIG_AUDIT_TREE=y
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+CONFIG_CGROUP_NS=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+# CONFIG_USER_SCHED is not set
+CONFIG_CGROUP_SCHED=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+# CONFIG_CGROUP_MEM_RES_CTLR is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+CONFIG_RELAY=y
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+CONFIG_USER_NS=y
+CONFIG_PID_NS=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_MARKERS=y
+CONFIG_OPROFILE=m
+CONFIG_HAVE_OPROFILE=y
+CONFIG_KPROBES=y
+CONFIG_KRETPROBES=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+# CONFIG_HAVE_DMA_ATTRS is not set
+# CONFIG_USE_GENERIC_SMP_HELPERS is not set
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_LSF=y
+CONFIG_BLK_DEV_BSG=y
+CONFIG_BLK_DEV_INTEGRITY=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_CLASSIC_RCU=y
+
+#
+# Platform support
+#
+CONFIG_PPC_MULTIPLATFORM=y
+CONFIG_CLASSIC32=y
+CONFIG_PPC_CHRP=y
+# CONFIG_MPC5121_ADS is not set
+# CONFIG_MPC5121_GENERIC is not set
+CONFIG_PPC_MPC52xx=y
+# CONFIG_PPC_MPC5200_SIMPLE is not set
+CONFIG_PPC_EFIKA=y
+# CONFIG_PPC_LITE5200 is not set
+CONFIG_PPC_MPC5200_BUGFIX=y
+CONFIG_PPC_MPC5200_GPIO=y
+CONFIG_PPC_PMAC=y
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+CONFIG_PPC_82xx=y
+CONFIG_MPC8272_ADS=y
+CONFIG_PQ2FADS=y
+CONFIG_EP8248E=y
+CONFIG_PQ2ADS=y
+CONFIG_8260=y
+CONFIG_8272=y
+CONFIG_PQ2_ADS_PCI_PIC=y
+CONFIG_PPC_83xx=y
+CONFIG_MPC831x_RDB=y
+CONFIG_MPC832x_MDS=y
+CONFIG_MPC832x_RDB=y
+CONFIG_MPC834x_MDS=y
+CONFIG_MPC834x_ITX=y
+CONFIG_MPC836x_MDS=y
+CONFIG_MPC836x_RDK=y
+CONFIG_MPC837x_MDS=y
+CONFIG_MPC837x_RDB=y
+CONFIG_SBC834x=y
+CONFIG_ASP834x=y
+CONFIG_PPC_MPC831x=y
+CONFIG_PPC_MPC832x=y
+CONFIG_PPC_MPC834x=y
+CONFIG_PPC_MPC837x=y
+CONFIG_PPC_86xx=y
+CONFIG_MPC8641_HPCN=y
+CONFIG_SBC8641D=y
+CONFIG_MPC8610_HPCD=y
+CONFIG_MPC8641=y
+CONFIG_MPC8610=y
+# CONFIG_EMBEDDED6xx is not set
+CONFIG_PPC_NATIVE=y
+# CONFIG_UDBG_RTAS_CONSOLE is not set
+CONFIG_IPIC=y
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+CONFIG_PPC_I8259=y
+CONFIG_PPC_RTAS=y
+# CONFIG_RTAS_ERROR_LOGGING is not set
+CONFIG_RTAS_PROC=y
+# CONFIG_MMIO_NVRAM is not set
+CONFIG_PPC_MPC106=y
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+
+#
+# CPU Frequency drivers
+#
+CONFIG_CPU_FREQ_PMAC=y
+# CONFIG_PPC601_SYNC_FIX is not set
+CONFIG_TAU=y
+# CONFIG_TAU_INT is not set
+CONFIG_TAU_AVERAGE=y
+CONFIG_QUICC_ENGINE=y
+CONFIG_CPM2=y
+CONFIG_PPC_CPM_NEW_BINDING=y
+CONFIG_FSL_ULI1575=y
+CONFIG_CPM=y
+CONFIG_PPC_BESTCOMM=y
+CONFIG_PPC_BESTCOMM_ATA=m
+CONFIG_PPC_BESTCOMM_FEC=m
+CONFIG_PPC_BESTCOMM_GEN_BD=m
+
+#
+# Kernel options
+#
+CONFIG_HIGHMEM=y
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
+# CONFIG_SCHED_HRTICK is not set
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_IOMMU_HELPER is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+# CONFIG_KEXEC is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
+CONFIG_ARCH_WANTS_FREEZER_CONTROL=y
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_VERBOSE is not set
+CONFIG_CAN_PM_TRACE=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_HIBERNATION=y
+CONFIG_PM_STD_PARTITION=""
+CONFIG_APM_EMULATION=y
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ISA=y
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_FSL_PCI=y
+CONFIG_FSL_LBC=y
+CONFIG_FSL_GTM=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
+CONFIG_PCI_8260=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIEAER=y
+CONFIG_PCIEASPM=y
+# CONFIG_PCIEASPM_DEBUG is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_DEBUG is not set
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+CONFIG_I82365=m
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_PROBE=y
+CONFIG_PCCARD_NONSTATIC=y
+# CONFIG_HOTPLUG_PCI is not set
+CONFIG_HAS_RAPIDIO=y
+# CONFIG_RAPIDIO is not set
+
+#
+# Advanced setup
+#
+CONFIG_ADVANCED_OPTIONS=y
+# CONFIG_LOWMEM_SIZE_BOOL is not set
+CONFIG_LOWMEM_SIZE=0x30000000
+# CONFIG_PAGE_OFFSET_BOOL is not set
+CONFIG_PAGE_OFFSET=0xc0000000
+# CONFIG_KERNEL_START_BOOL is not set
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_PHYSICAL_START=0x00000000
+# CONFIG_TASK_SIZE_BOOL is not set
+CONFIG_TASK_SIZE=0xc0000000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_XFRM_MIGRATE=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_NET_KEY=m
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_LRO=y
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+# CONFIG_DEFAULT_BIC is not set
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_PIMSM_V2=y
+CONFIG_NETLABEL=y
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_CONNTRACK_IPV4=m
+# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_DCCP=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# DECnet: Netfilter Configuration
+#
+# CONFIG_DECNET_NF_GRABULATOR is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+CONFIG_BRIDGE_EBT_NFLOG=m
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID2=m
+# CONFIG_IP_DCCP_CCID2_DEBUG is not set
+CONFIG_IP_DCCP_CCID3=m
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_CCID3_RTO=100
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+CONFIG_NET_DCCPPROBE=m
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+CONFIG_TIPC=m
+# CONFIG_TIPC_ADVANCED is not set
+# CONFIG_TIPC_DEBUG is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+# CONFIG_ATM_MPOA is not set
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+# CONFIG_LTPC is not set
+# CONFIG_COPS is not set
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+CONFIG_WAN_ROUTER=m
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_NAT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_SCH_FIFO=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+CONFIG_KINGSUN_DONGLE=m
+CONFIG_KSDAZZLE_DONGLE=m
+CONFIG_KS959_DONGLE=m
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_TOSHIBA_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+
+#
+# Wireless
+#
+CONFIG_CFG80211=m
+CONFIG_NL80211=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_MAC80211=m
+CONFIG_MAC80211_QOS=y
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+CONFIG_MAC80211_RC_DEFAULT="pid"
+CONFIG_MAC80211_MESH=y
+CONFIG_MAC80211_LEDS=y
+CONFIG_MAC80211_DEBUGFS=y
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_IEEE80211=m
+CONFIG_IEEE80211_DEBUG=y
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_RFKILL is not set
+CONFIG_NET_9P=m
+CONFIG_NET_9P_VIRTIO=m
+# CONFIG_NET_9P_DEBUG is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+CONFIG_DEBUG_DEVRES=y
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+# CONFIG_MTD is not set
+CONFIG_OF_DEVICE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_I2C=y
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+# CONFIG_PARPORT_PC_PCMCIA is not set
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+CONFIG_PARPORT_1284=y
+CONFIG_PARPORT_NOT_PC=y
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_ISAPNP=y
+# CONFIG_PNPACPI is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_MAC_FLOPPY=m
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_VIRTIO_BLK=m
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+CONFIG_EEPROM_93CX6=m
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+CONFIG_ENCLOSURE_SERVICES=m
+CONFIG_HAVE_IDE=y
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
+#
+CONFIG_IDE_ATAPI=y
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+# CONFIG_BLK_DEV_IDECS is not set
+# CONFIG_BLK_DEV_DELKIN is not set
+CONFIG_BLK_DEV_IDECD=m
+CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=m
+# CONFIG_BLK_DEV_IDESCSI is not set
+CONFIG_IDE_TASK_IOCTL=y
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_BLK_DEV_PLATFORM is not set
+# CONFIG_BLK_DEV_IDEPNP is not set
+CONFIG_BLK_DEV_IDEDMA_SFF=y
+
+#
+# PCI IDE chipsets support
+#
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_PCIBUS_ORDER is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
+CONFIG_BLK_DEV_IDE_PMAC=y
+CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
+CONFIG_BLK_DEV_IDEDMA_PMAC=y
+CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_BLK_DEV_HD_ONLY=y
+CONFIG_BLK_DEV_HD=y
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_TGT=m
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=m
+CONFIG_SCSI_ENCLOSURE=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=m
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+CONFIG_SCSI_SRP_ATTRS=m
+CONFIG_SCSI_SRP_TGT_ATTRS=y
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
+# CONFIG_SCSI_MVSAS is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+CONFIG_SCSI_MESH=m
+CONFIG_SCSI_MESH_SYNC_RATE=5
+CONFIG_SCSI_MESH_RESET_DELAY_MS=4000
+CONFIG_SCSI_MAC53C94=m
+CONFIG_SCSI_SRP=m
+CONFIG_SCSI_LOWLEVEL_PCMCIA=y
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+CONFIG_SCSI_DH=y
+CONFIG_SCSI_DH_RDAC=m
+CONFIG_SCSI_DH_HP_SW=m
+CONFIG_SCSI_DH_EMC=m
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+# CONFIG_SATA_PMP is not set
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SIL24 is not set
+CONFIG_SATA_FSL=m
+CONFIG_ATA_SFF=y
+# CONFIG_SATA_SVW is not set
+CONFIG_ATA_PIIX=m
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+CONFIG_PDC_ADMA=m
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+CONFIG_ATA_GENERIC=m
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_ISAPNP is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_LEGACY is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+CONFIG_PATA_MPC52xx=m
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NINJA32 is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
+# CONFIG_PATA_OPTI is not set
+CONFIG_PATA_OPTIDMA=m
+# CONFIG_PATA_PCMCIA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_QDI is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+CONFIG_PATA_VIA=m
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_WINBOND_VLB is not set
+CONFIG_PATA_PLATFORM=m
+CONFIG_PATA_OF_PLATFORM=m
+CONFIG_PATA_SCH=m
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_DEBUG=y
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+# CONFIG_DM_DELAY is not set
+CONFIG_DM_UEVENT=y
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
+CONFIG_FIREWIRE=m
+CONFIG_FIREWIRE_OHCI=m
+CONFIG_FIREWIRE_OHCI_DEBUG=y
+CONFIG_FIREWIRE_SBP2=m
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+CONFIG_MACINTOSH_DRIVERS=y
+CONFIG_ADB=y
+CONFIG_ADB_CUDA=y
+CONFIG_ADB_PMU=y
+CONFIG_ADB_PMU_LED=y
+CONFIG_ADB_PMU_LED_IDE=y
+CONFIG_PMAC_APM_EMU=y
+CONFIG_PMAC_MEDIABAY=y
+CONFIG_PMAC_BACKLIGHT=y
+# CONFIG_PMAC_BACKLIGHT_LEGACY is not set
+CONFIG_ADB_MACIO=y
+CONFIG_INPUT_ADBHID=y
+CONFIG_MAC_EMUMOUSEBTN=y
+CONFIG_THERM_WINDTUNNEL=m
+CONFIG_THERM_ADT746X=m
+CONFIG_WINDFARM=y
+# CONFIG_ANSLCD is not set
+CONFIG_PMAC_RACKMETER=m
+CONFIG_NETDEVICES=y
+CONFIG_NETDEVICES_MULTIQUEUE=y
+CONFIG_IFB=m
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_VETH=m
+CONFIG_NET_SB1000=m
+# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_BROADCOM_PHY=m
+CONFIG_ICPLUS_PHY=m
+CONFIG_REALTEK_PHY=m
+CONFIG_MDIO_BITBANG=y
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_MACE=m
+# CONFIG_MACE_AAUI_PORT is not set
+CONFIG_BMAC=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_EL1 is not set
+# CONFIG_EL2 is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_EL16 is not set
+CONFIG_EL3=m
+# CONFIG_3C515 is not set
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+# CONFIG_LANCE is not set
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_WD80x3 is not set
+CONFIG_ULTRA=m
+# CONFIG_SMC9194 is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_ISA=y
+# CONFIG_E2100 is not set
+CONFIG_EWRK3=m
+# CONFIG_EEXPRESS is not set
+# CONFIG_EEXPRESS_PRO is not set
+# CONFIG_HPLAN_PLUS is not set
+# CONFIG_HPLAN is not set
+# CONFIG_LP486E is not set
+# CONFIG_ETH16I is not set
+CONFIG_NE2000=m
+# CONFIG_ZNET is not set
+# CONFIG_SEEQ8005 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_AMD8111E_NAPI=y
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_ADAPTEC_STARFIRE_NAPI=y
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+CONFIG_B44=m
+CONFIG_B44_PCI_AUTOSELECT=y
+CONFIG_B44_PCICORE_AUTOSELECT=y
+CONFIG_B44_PCI=y
+CONFIG_FORCEDETH=m
+CONFIG_FORCEDETH_NAPI=y
+# CONFIG_CS89x0 is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_R6040=m
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_TLAN=m
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+CONFIG_VIA_RHINE_NAPI=y
+CONFIG_SC92031=m
+CONFIG_NET_POCKET=y
+CONFIG_DE600=m
+CONFIG_DE620=m
+CONFIG_FEC_MPC52xx=m
+CONFIG_FEC_MPC52xx_MDIO=y
+# CONFIG_FS_ENET is not set
+CONFIG_NETDEV_1000=y
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+CONFIG_E1000E=m
+CONFIG_E1000E_ENABLED=y
+CONFIG_IP1000=m
+CONFIG_IGB=m
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+# CONFIG_SKGE_DEBUG is not set
+CONFIG_SKY2=m
+# CONFIG_SKY2_DEBUG is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+CONFIG_GIANFAR=m
+CONFIG_GFAR_NAPI=y
+# CONFIG_UCC_GETH is not set
+CONFIG_MV643XX_ETH=m
+CONFIG_QLA3XXX=m
+CONFIG_ATL1=m
+CONFIG_NETDEV_10000=y
+CONFIG_CHELSIO_T1=m
+CONFIG_CHELSIO_T1_1G=y
+CONFIG_CHELSIO_T1_NAPI=y
+CONFIG_CHELSIO_T3=m
+CONFIG_IXGBE=m
+CONFIG_IXGB=m
+CONFIG_IXGB_NAPI=y
+CONFIG_S2IO=m
+CONFIG_S2IO_NAPI=y
+CONFIG_MYRI10GE=m
+CONFIG_NETXEN_NIC=m
+CONFIG_NIU=m
+# CONFIG_MLX4_CORE is not set
+CONFIG_TEHUTI=m
+CONFIG_BNX2X=m
+CONFIG_SFC=m
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=m
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+# CONFIG_WAN is not set
+CONFIG_ATM_DRIVERS=y
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+# CONFIG_ATM_FIRESTREAM is not set
+# CONFIG_ATM_ZATM is not set
+CONFIG_ATM_NICSTAR=m
+# CONFIG_ATM_NICSTAR_USE_SUNI is not set
+# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+# CONFIG_ATM_IDT77252_RCV_ALL is not set
+CONFIG_ATM_IDT77252_USE_SUNI=y
+# CONFIG_ATM_AMBASSADOR is not set
+# CONFIG_ATM_HORIZON is not set
+# CONFIG_ATM_IA is not set
+CONFIG_ATM_FORE200E_MAYBE=m
+# CONFIG_ATM_FORE200E_PCA is not set
+CONFIG_ATM_HE=m
+# CONFIG_ATM_HE_USE_SUNI is not set
+CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
+CONFIG_SKFP=m
+# CONFIG_HIPPI is not set
+CONFIG_PLIP=m
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_PPPOL2TP=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=m
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+CONFIG_NET_FC=y
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+CONFIG_VIRTIO_NET=m
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=y
+CONFIG_INPUT_POLLDEV=m
+
+#
+# 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=m
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_GPIO is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_APPLETOUCH=m
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+CONFIG_MOUSE_VSXXXAA=m
+# CONFIG_MOUSE_GPIO is not set
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_ZHENHUA=m
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_JOYSTICK_XPAD=m
+CONFIG_JOYSTICK_XPAD_FF=y
+CONFIG_JOYSTICK_XPAD_LEDS=y
+CONFIG_INPUT_TABLET=y
+CONFIG_TABLET_USB_ACECAD=m
+CONFIG_TABLET_USB_AIPTEK=m
+CONFIG_TABLET_USB_GTCO=m
+CONFIG_TABLET_USB_KBTAB=m
+CONFIG_TABLET_USB_WACOM=m
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=m
+CONFIG_INPUT_ATI_REMOTE=m
+CONFIG_INPUT_ATI_REMOTE2=m
+CONFIG_INPUT_KEYSPAN_REMOTE=m
+CONFIG_INPUT_POWERMATE=m
+CONFIG_INPUT_YEALINK=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_FM801=m
+CONFIG_INPUT_LIRC=y
+CONFIG_LIRC_DEV=m
+CONFIG_LIRC_ATIUSB=m
+CONFIG_LIRC_BT829=m
+CONFIG_LIRC_CMDIR=m
+CONFIG_LIRC_I2C=m
+CONFIG_LIRC_IGORPLUGUSB=m
+CONFIG_LIRC_IMON=m
+CONFIG_LIRC_IT87=m
+CONFIG_LIRC_MCEUSB=m
+CONFIG_LIRC_MCEUSB2=m
+CONFIG_LIRC_PVR150=m
+CONFIG_LIRC_PARALLEL=m
+CONFIG_LIRC_SERIAL=m
+CONFIG_LIRC_SIR=m
+CONFIG_LIRC_STREAMZAP=m
+CONFIG_LIRC_TTUSBIR=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+CONFIG_ROCKETPORT=m
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_ESPSERIAL is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+CONFIG_NOZOMI=m
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+# CONFIG_SERIAL_8250_FOURPORT is not set
+# CONFIG_SERIAL_8250_ACCENT is not set
+# CONFIG_SERIAL_8250_BOCA is not set
+# CONFIG_SERIAL_8250_EXAR_ST16C554 is not set
+# CONFIG_SERIAL_8250_HUB6 is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_UARTLITE=m
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_PMACZILOG=m
+# CONFIG_SERIAL_PMACZILOG_TTYS is not set
+# CONFIG_SERIAL_CPM is not set
+CONFIG_SERIAL_MPC52xx=y
+CONFIG_SERIAL_MPC52xx_CONSOLE=y
+CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200
+CONFIG_SERIAL_JSM=m
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_QE is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_CRASH is not set
+CONFIG_BRIQ_PANEL=m
+CONFIG_PRINTER=m
+CONFIG_LP_CONSOLE=y
+CONFIG_PPDEV=m
+# CONFIG_HVC_RTAS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_VIRTIO=m
+CONFIG_NVRAM=y
+CONFIG_DTLK=m
+CONFIG_R3964=m
+# CONFIG_APPLICOM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+CONFIG_IPWIRELESS=m
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_ALGOBIT=y
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# 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_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# Mac SMBus host controller drivers
+#
+CONFIG_I2C_HYDRA=m
+CONFIG_I2C_POWERMAC=y
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_CPM is not set
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_MPC=m
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_SIMTEC=m
+
+#
+# External I2C/SMBus adapter drivers
+#
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+# CONFIG_I2C_TAOS_EVM is not set
+CONFIG_I2C_TINY_USB=m
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
+CONFIG_I2C_VOODOO3=m
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_ELEKTOR is not set
+CONFIG_I2C_PCA_ISA=m
+CONFIG_I2C_PCA_PLATFORM=m
+CONFIG_I2C_STUB=m
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+CONFIG_AT24=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_PCF8575=m
+CONFIG_SENSORS_PCA9539=m
+CONFIG_SENSORS_PCF8591=m
+# CONFIG_TPS65010 is not set
+CONFIG_SENSORS_MAX6875=m
+CONFIG_SENSORS_TSL2550=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+CONFIG_HAVE_GPIO_LIB=y
+
+#
+# GPIO Support
+#
+# CONFIG_DEBUG_GPIO is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# SPI GPIO expanders:
+#
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_MATROX is not set
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+# CONFIG_W1_MASTER_GPIO is not set
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2433=m
+CONFIG_W1_SLAVE_DS2433_CRC=y
+CONFIG_W1_SLAVE_DS2760=m
+CONFIG_POWER_SUPPLY=m
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+CONFIG_APM_POWER=m
+# CONFIG_BATTERY_DS2760 is not set
+CONFIG_BATTERY_PMU=m
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_AD7418=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1029=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ADT7470=m
+CONFIG_SENSORS_ADT7473=m
+CONFIG_SENSORS_AMS=m
+CONFIG_SENSORS_AMS_PMU=y
+CONFIG_SENSORS_AMS_I2C=y
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS1621=m
+# CONFIG_SENSORS_I5K_AMB is not set
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_F71882FG=m
+CONFIG_SENSORS_F75375S=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_LM93=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_MAX6650=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_PC87427=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_DME1737=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_ADS7828=m
+CONFIG_SENSORS_THMC50=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT1211=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83793=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83L786NG=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_THERMAL=y
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+# CONFIG_MPC5200_WDT is not set
+CONFIG_83xx_WDT=m
+CONFIG_WATCHDOG_RTAS=m
+
+#
+# ISA-based Watchdog Cards
+#
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_WDT is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+CONFIG_SSB=m
+CONFIG_SSB_SPROM=y
+CONFIG_SSB_PCIHOST_POSSIBLE=y
+CONFIG_SSB_PCIHOST=y
+# CONFIG_SSB_B43_PCI_BRIDGE is not set
+CONFIG_SSB_PCMCIAHOST_POSSIBLE=y
+CONFIG_SSB_PCMCIAHOST=y
+# CONFIG_SSB_DEBUG is not set
+CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
+CONFIG_SSB_DRIVER_PCICORE=y
+
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_SM501=m
+# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_MT2131=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_DMA_SG=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_IR_I2C=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+
+#
+# Encoders/decoders and other helper chips
+#
+
+#
+# Audio decoders
+#
+CONFIG_VIDEO_TVAUDIO=m
+CONFIG_VIDEO_TDA7432=m
+CONFIG_VIDEO_TDA9840=m
+CONFIG_VIDEO_TDA9875=m
+CONFIG_VIDEO_TEA6415C=m
+CONFIG_VIDEO_TEA6420=m
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS5345=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_M52790=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_VP27SMPX=m
+
+#
+# Video decoders
+#
+CONFIG_VIDEO_BT819=m
+CONFIG_VIDEO_BT856=m
+CONFIG_VIDEO_BT866=m
+CONFIG_VIDEO_KS0127=m
+CONFIG_VIDEO_OV7670=m
+CONFIG_VIDEO_TCM825X=m
+CONFIG_VIDEO_SAA7110=m
+CONFIG_VIDEO_SAA7111=m
+CONFIG_VIDEO_SAA7114=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA717X=m
+CONFIG_VIDEO_SAA7191=m
+CONFIG_VIDEO_TVP5150=m
+CONFIG_VIDEO_VPX3220=m
+
+#
+# Video and audio decoders
+#
+CONFIG_VIDEO_CX25840=m
+
+#
+# MPEG video encoders
+#
+CONFIG_VIDEO_CX2341X=m
+
+#
+# Video encoders
+#
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_SAA7185=m
+CONFIG_VIDEO_ADV7170=m
+CONFIG_VIDEO_ADV7175=m
+
+#
+# Video improvement chips
+#
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+# CONFIG_VIDEO_VIVI is not set
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_SAA6588=m
+# CONFIG_VIDEO_PMS is not set
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+CONFIG_VIDEO_W9966=m
+CONFIG_VIDEO_CPIA=m
+CONFIG_VIDEO_CPIA_PP=m
+CONFIG_VIDEO_CPIA_USB=m
+CONFIG_VIDEO_CPIA2=m
+CONFIG_VIDEO_SAA5246A=m
+CONFIG_VIDEO_SAA5249=m
+CONFIG_TUNER_3036=m
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_DPC=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX23885=m
+CONFIG_VIDEO_AU0828=m
+CONFIG_VIDEO_IVTV=m
+CONFIG_VIDEO_FB_IVTV=m
+CONFIG_VIDEO_CX18=m
+# CONFIG_VIDEO_CAFE_CCIC is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_VIDEO_USBVISION=m
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+CONFIG_USB_ET61X251=m
+CONFIG_VIDEO_OVCAMCHIP=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+CONFIG_USB_ZC0301=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_SOC_CAMERA=m
+CONFIG_SOC_CAMERA_MT9M001=m
+# CONFIG_MT9M001_PCA9536_SWITCH is not set
+CONFIG_SOC_CAMERA_MT9V022=m
+# CONFIG_MT9V022_PCA9536_SWITCH is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+CONFIG_RADIO_GEMTEK_PCI=m
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
+CONFIG_USB_DSBR=m
+CONFIG_USB_SI470X=m
+CONFIG_DVB_CAPTURE_DRIVERS=y
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_TTPCI_EEPROM=m
+CONFIG_DVB_AV7110=m
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET_CORE=m
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_CINERGYT2=m
+CONFIG_DVB_CINERGYT2_TUNING=y
+CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32
+CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512
+CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250
+CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y
+CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+CONFIG_DVB_PLUTO2=m
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_S5H1420=m
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_S5H1411=m
+
+#
+# Digital terrestrial only tuners/PLL
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+
+#
+# SEC control devices for DVB-S
+#
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6405=m
+CONFIG_DVB_ISL6421=m
+CONFIG_DAB=y
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+CONFIG_AGP=y
+CONFIG_AGP_UNINORTH=y
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+CONFIG_VGASTATE=y
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB_DDC=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_SVGALIB=m
+CONFIG_FB_MACMODES=y
+CONFIG_FB_BACKLIGHT=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+CONFIG_FB_CIRRUS=m
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+CONFIG_FB_OF=y
+# CONFIG_FB_CONTROL is not set
+CONFIG_FB_PLATINUM=y
+CONFIG_FB_VALKYRIE=y
+CONFIG_FB_CT65550=y
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_NVIDIA=y
+CONFIG_FB_NVIDIA_I2C=y
+# CONFIG_FB_NVIDIA_DEBUG is not set
+CONFIG_FB_NVIDIA_BACKLIGHT=y
+CONFIG_FB_RIVA=m
+# CONFIG_FB_RIVA_I2C is not set
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_RIVA_BACKLIGHT=y
+CONFIG_FB_MATROX=y
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
+CONFIG_FB_MATROX_MULTIHEAD=y
+CONFIG_FB_RADEON=y
+CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=y
+CONFIG_FB_ATY128_BACKLIGHT=y
+CONFIG_FB_ATY=y
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_ATY_BACKLIGHT=y
+CONFIG_FB_S3=m
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+# CONFIG_FB_SIS is not set
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_VOODOO1=m
+# CONFIG_FB_VT8623 is not set
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_TRIDENT_ACCEL=y
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_FSL_DIU is not set
+CONFIG_FB_SM501=m
+CONFIG_FB_IBM_GXT4500=y
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_CORGI is not set
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=m
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=m
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+CONFIG_SND_DEBUG_VERBOSE=y
+CONFIG_SND_PCM_XRUN_DEBUG=y
+CONFIG_SND_VMASTER=y
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_DRIVERS=y
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+CONFIG_SND_MTS64=m
+CONFIG_SND_SERIAL_U16550=m
+CONFIG_SND_MPU401=m
+CONFIG_SND_PORTMAN2X4=m
+CONFIG_SND_AC97_POWER_SAVE=y
+CONFIG_SND_AC97_POWER_SAVE_DEFAULT=5
+CONFIG_SND_SB_COMMON=m
+CONFIG_SND_SB16_DSP=m
+CONFIG_SND_ISA=y
+# CONFIG_SND_ADLIB is not set
+# CONFIG_SND_AD1816A is not set
+# CONFIG_SND_AD1848 is not set
+# CONFIG_SND_ALS100 is not set
+# CONFIG_SND_AZT2320 is not set
+# CONFIG_SND_CMI8330 is not set
+# CONFIG_SND_CS4231 is not set
+# CONFIG_SND_CS4232 is not set
+# CONFIG_SND_CS4236 is not set
+# CONFIG_SND_DT019X is not set
+# CONFIG_SND_ES968 is not set
+# CONFIG_SND_ES1688 is not set
+# CONFIG_SND_ES18XX is not set
+# CONFIG_SND_SC6000 is not set
+# CONFIG_SND_GUSCLASSIC is not set
+# CONFIG_SND_GUSEXTREME is not set
+# CONFIG_SND_GUSMAX is not set
+# CONFIG_SND_INTERWAVE is not set
+# CONFIG_SND_INTERWAVE_STB is not set
+# CONFIG_SND_OPL3SA2 is not set
+# CONFIG_SND_OPTI92X_AD1848 is not set
+# CONFIG_SND_OPTI92X_CS4231 is not set
+# CONFIG_SND_OPTI93X is not set
+# CONFIG_SND_MIRO is not set
+# CONFIG_SND_SB8 is not set
+# CONFIG_SND_SB16 is not set
+# CONFIG_SND_SBAWE is not set
+# CONFIG_SND_SGALAXY is not set
+# CONFIG_SND_SSCAPE is not set
+# CONFIG_SND_WAVEFRONT is not set
+CONFIG_SND_PCI=y
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AW2=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_OXYGEN_LIB=m
+CONFIG_SND_OXYGEN=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS5530=m
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_FM801=m
+CONFIG_SND_FM801_TEA575X_BOOL=y
+CONFIG_SND_FM801_TEA575X=m
+# CONFIG_SND_HDA_INTEL is not set
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_HIFIER=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+CONFIG_SND_KORG1212=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VIRTUOSO=m
+CONFIG_SND_VX222=m
+# CONFIG_SND_YMFPCI is not set
+CONFIG_SND_PPC=y
+CONFIG_SND_POWERMAC=m
+CONFIG_SND_POWERMAC_AUTO_DRC=y
+CONFIG_SND_AOA=m
+CONFIG_SND_AOA_FABRIC_LAYOUT=m
+CONFIG_SND_AOA_ONYX=m
+CONFIG_SND_AOA_TAS=m
+CONFIG_SND_AOA_TOONIE=m
+CONFIG_SND_AOA_SOUNDBUS=m
+CONFIG_SND_AOA_SOUNDBUS_I2S=m
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+# CONFIG_SND_PCMCIA is not set
+# CONFIG_SND_SOC is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HID_DEBUG=y
+CONFIG_HIDRAW=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT_POWERBOOK=y
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_LOGIRUMBLEPAD2_FF=y
+CONFIG_PANTHERLORD_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_ZEROPLUS_FF=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_EHCI_FSL=y
+CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_OHCI_HCD_PPC_SOC=y
+CONFIG_USB_OHCI_HCD_PPC_OF=y
+CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
+CONFIG_USB_OHCI_HCD_PCI=y
+# CONFIG_USB_OHCI_HCD_SSB is not set
+CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_U132_HCD=m
+CONFIG_USB_SL811_HCD=m
+# CONFIG_USB_SL811_CS is not set
+# CONFIG_USB_R8A66597_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+# CONFIG_USB_STORAGE_ISD200 is not set
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_AIRPRIME=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+# CONFIG_USB_SERIAL_GARMIN is not set
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_DEBUG=m
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_ADUTUX=m
+CONFIG_USB_AUERSWALD=m
+# CONFIG_USB_RIO500 is not set
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_BERRY_CHARGE=m
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+CONFIG_USB_PHIDGET=m
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETMOTORCONTROL=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TRANCEVIBRATOR=m
+CONFIG_USB_IOWARRIOR=m
+# CONFIG_USB_TEST is not set
+CONFIG_USB_ISIGHTFW=m
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_GPIO is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+CONFIG_ACCESSIBILITY=y
+CONFIG_A11Y_BRAILLE_CONSOLE=y
+# CONFIG_INFINIBAND is not set
+CONFIG_EDAC=y
+
+#
+# Reporting subsystems
+#
+# CONFIG_EDAC_DEBUG is not set
+CONFIG_EDAC_MM_EDAC=m
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_HCTOSYS is not set
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1374=m
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_MAX6900=m
+CONFIG_RTC_DRV_RS5C372=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_M41T80=m
+CONFIG_RTC_DRV_M41T80_WDT=y
+# CONFIG_RTC_DRV_S35390A is not set
+CONFIG_RTC_DRV_FM3130=m
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=y
+CONFIG_RTC_DRV_DS1511=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_STK17TA8=m
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_M48T59=m
+CONFIG_RTC_DRV_V3020=m
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_PPC=y
+CONFIG_DMADEVICES=y
+
+#
+# DMA Devices
+#
+# CONFIG_FSL_DMA is not set
+CONFIG_AUXDISPLAY=y
+CONFIG_KS0108=m
+CONFIG_KS0108_PORT=0x378
+CONFIG_KS0108_DELAY=2
+CONFIG_UIO=m
+CONFIG_UIO_CIF=m
+CONFIG_UIO_SMX=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4DEV_FS=m
+CONFIG_EXT4DEV_FS_XATTR=y
+CONFIG_EXT4DEV_FS_POSIX_ACL=y
+CONFIG_EXT4DEV_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=m
+CONFIG_JBD2_DEBUG=y
+CONFIG_FS_MBCACHE=m
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=m
+CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_FS_O2CB=m
+CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+# CONFIG_OCFS2_DEBUG_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+CONFIG_AFFS_FS=m
+CONFIG_ECRYPT_FS=m
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+CONFIG_VXFS_FS=m
+CONFIG_MINIX_FS=m
+# CONFIG_HPFS_FS is not set
+CONFIG_QNX4FS_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_SUNRPC_BIND34=y
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+CONFIG_CIFS_EXPERIMENTAL=y
+CONFIG_CIFS_UPCALL=y
+CONFIG_CIFS_DFS_UPCALL=y
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+CONFIG_DLM=m
+CONFIG_DLM_DEBUG=y
+CONFIG_QE_GPIO=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC_T10DIF=m
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_LZO_COMPRESS=m
+CONFIG_LZO_DECOMPRESS=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_FS=y
+CONFIG_HEADERS_CHECK=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_OBJECTS=y
+# CONFIG_DEBUG_OBJECTS_SELFTEST is not set
+CONFIG_DEBUG_OBJECTS_FREE=y
+CONFIG_DEBUG_OBJECTS_TIMERS=y
+CONFIG_SLUB_DEBUG_ON=y
+# CONFIG_SLUB_STATS is not set
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_PI_LIST=y
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_HIGHMEM=y
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_VM=y
+CONFIG_DEBUG_WRITECOUNT=y
+CONFIG_DEBUG_LIST=y
+CONFIG_DEBUG_SG=y
+CONFIG_FRAME_POINTER=y
+CONFIG_BOOT_PRINTK_DELAY=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_KPROBES_SANITY_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_LKDTM is not set
+CONFIG_FAULT_INJECTION=y
+CONFIG_FAILSLAB=y
+CONFIG_FAIL_PAGE_ALLOC=y
+CONFIG_FAIL_MAKE_REQUEST=y
+CONFIG_FAULT_INJECTION_DEBUG_FS=y
+CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
+CONFIG_LATENCYTOP=y
+CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_TRACER_MAX_TRACE=y
+CONFIG_TRACING=y
+CONFIG_FTRACE=y
+CONFIG_SCHED_TRACER=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_DYNAMIC_FTRACE=y
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_FIREWIRE_OHCI_REMOTE_DMA is not set
+# CONFIG_SAMPLES is not set
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUGGER=y
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_KGDB_CONSOLE is not set
+CONFIG_XMON=y
+# CONFIG_XMON_DEFAULT is not set
+CONFIG_XMON_DISASSEMBLY=y
+CONFIG_IRQSTACKS=y
+# CONFIG_VIRQ_DEBUG is not set
+# CONFIG_BDI_SWITCH is not set
+CONFIG_BOOTX_TEXT=y
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_NETWORK_XFRM=y
+CONFIG_SECURITY_FILE_CAPABILITIES=y
+# CONFIG_SECURITY_ROOTPLUG is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=65536
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT=y
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+# CONFIG_SECURITY_SMACK is not set
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_DEV_HIFN_795X=m
+CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y
+CONFIG_CRYPTO_DEV_TALITOS=m
+CONFIG_PPC_CLOCK=y
+CONFIG_PPC_LIB_RHEAP=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_VIRTIO=m
+CONFIG_VIRTIO_RING=m
+CONFIG_VIRTIO_PCI=m
+CONFIG_VIRTIO_BALLOON=m
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig
index 71d79e4..f9a3d3b 100644
--- a/arch/powerpc/configs/ps3_defconfig
+++ b/arch/powerpc/configs/ps3_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.25
-# Mon Apr 28 12:39:10 2008
+# Linux kernel version: 2.6.26
+# Wed Jul 16 13:59:24 2008
 #
 CONFIG_PPC64=y
 
@@ -14,8 +14,9 @@
 CONFIG_TUNE_CELL=y
 CONFIG_PPC_FPU=y
 CONFIG_ALTIVEC=y
+# CONFIG_VSX is not set
 CONFIG_PPC_STD_MMU=y
-# CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_MM_SLICES=y
 CONFIG_VIRT_CPU_ACCOUNTING=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
@@ -31,6 +32,7 @@
 CONFIG_HAVE_SETUP_PER_CPU_AREA=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
@@ -90,6 +92,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
 CONFIG_SYSCTL_SYSCALL=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
@@ -117,12 +120,15 @@
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
 CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 # CONFIG_MODVERSIONS is not set
@@ -132,6 +138,7 @@
 CONFIG_BLOCK=y
 # CONFIG_BLK_DEV_IO_TRACE is not set
 CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_INTEGRITY is not set
 CONFIG_BLOCK_COMPAT=y
 
 #
@@ -152,13 +159,8 @@
 # Platform support
 #
 CONFIG_PPC_MULTIPLATFORM=y
-# CONFIG_PPC_82xx is not set
-# CONFIG_PPC_83xx is not set
-# CONFIG_PPC_86xx is not set
 # CONFIG_PPC_PSERIES is not set
 # CONFIG_PPC_ISERIES is not set
-# CONFIG_PPC_MPC512x is not set
-# CONFIG_PPC_MPC5121 is not set
 # CONFIG_PPC_PMAC is not set
 # CONFIG_PPC_MAPLE is not set
 # CONFIG_PPC_PASEMI is not set
@@ -187,6 +189,7 @@
 # Cell Broadband Engine options
 #
 CONFIG_SPU_FS=y
+CONFIG_SPU_FS_64K_LS=y
 CONFIG_SPU_BASE=y
 # CONFIG_PQ2ADS is not set
 # CONFIG_IPIC is not set
@@ -222,6 +225,7 @@
 CONFIG_BINFMT_ELF=y
 CONFIG_COMPAT_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
+CONFIG_HUGETLB_PAGE_SIZE_VARIABLE=y
 # CONFIG_IOMMU_VMERGE is not set
 CONFIG_IOMMU_HELPER=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
@@ -248,18 +252,22 @@
 # CONFIG_SPARSEMEM_VMEMMAP is not set
 CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTPLUG_SPARSE=y
+CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_RESOURCES_64BIT=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_ARCH_MEMORY_PROBE=y
-# CONFIG_PPC_HAS_HASH_64K is not set
+CONFIG_PPC_HAS_HASH_64K=y
 # CONFIG_PPC_64K_PAGES is not set
 CONFIG_FORCE_MAX_ZONEORDER=13
-# CONFIG_SCHED_SMT is not set
+CONFIG_SCHED_SMT=y
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
-# CONFIG_PM is not set
+CONFIG_EXTRA_TARGETS=""
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_VERBOSE is not set
 # CONFIG_SECCOMP is not set
 CONFIG_ISA_DMA_API=y
 
@@ -273,6 +281,7 @@
 # CONFIG_PCI_SYSCALL is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 # CONFIG_PCCARD is not set
+# CONFIG_HAS_RAPIDIO is not set
 CONFIG_PAGE_OFFSET=0xc000000000000000
 CONFIG_KERNEL_START=0xc000000000000000
 CONFIG_PHYSICAL_START=0x00000000
@@ -412,6 +421,8 @@
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=m
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_DEBUG_DRIVER is not set
 # CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
@@ -478,6 +489,7 @@
 # CONFIG_SCSI_SAS_LIBSAS is not set
 # CONFIG_SCSI_SRP_ATTRS is not set
 # CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
@@ -533,8 +545,18 @@
 # CONFIG_USB_NET_CDC_SUBSET is not set
 # CONFIG_USB_NET_ZAURUS is not set
 # CONFIG_WAN is not set
-# CONFIG_PPP is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=m
+# CONFIG_PPPOL2TP is not set
 # CONFIG_SLIP is not set
+CONFIG_SLHC=m
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
@@ -603,6 +625,7 @@
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
 CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -618,23 +641,17 @@
 CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_IPMI_HANDLER is not set
 # CONFIG_HW_RANDOM is not set
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_HANGCHECK_TIMER is not set
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
-
-#
-# SPI support
-#
 # CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
 # CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
 
 #
@@ -652,8 +669,17 @@
 #
 # Multimedia devices
 #
+
+#
+# Multimedia core support
+#
 # CONFIG_VIDEO_DEV is not set
 # CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
 # CONFIG_DAB is not set
 
 #
@@ -671,8 +697,8 @@
 CONFIG_FB_SYS_FILLRECT=y
 CONFIG_FB_SYS_COPYAREA=y
 CONFIG_FB_SYS_IMAGEBLIT=y
+# CONFIG_FB_FOREIGN_ENDIAN is not set
 CONFIG_FB_SYS_FOPS=y
-CONFIG_FB_DEFERRED_IO=y
 # CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
@@ -712,18 +738,12 @@
 # CONFIG_LOGO_LINUX_MONO is not set
 # CONFIG_LOGO_LINUX_VGA16 is not set
 CONFIG_LOGO_LINUX_CLUT224=y
-
-#
-# Sound
-#
 CONFIG_SOUND=m
-
-#
-# Advanced Linux Sound Architecture
-#
 CONFIG_SND=m
 CONFIG_SND_TIMER=m
 CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
 # CONFIG_SND_SEQUENCER is not set
 # CONFIG_SND_MIXER_OSS is not set
 # CONFIG_SND_PCM_OSS is not set
@@ -732,53 +752,20 @@
 CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
-# CONFIG_SND_DUMMY is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-
-#
-# ALSA PowerMac devices
-#
-
-#
-# ALSA PowerMac requires I2C
-#
-
-#
-# ALSA PowerPC devices
-#
+# CONFIG_SND_DRIVERS is not set
+CONFIG_SND_PPC=y
 CONFIG_SND_PS3=m
 CONFIG_SND_PS3_DEFAULT_START_DELAY=2000
-
-#
-# USB devices
-#
-# CONFIG_SND_USB_AUDIO is not set
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=m
 # CONFIG_SND_USB_USX2Y is not set
 # CONFIG_SND_USB_CAIAQ is not set
-
-#
-# System on Chip audio support
-#
 # CONFIG_SND_SOC is not set
-
-#
-# ALSA SoC audio for Freescale SOCs
-#
-
-#
-# Open Sound System
-#
 # CONFIG_SOUND_PRIME is not set
 CONFIG_HID_SUPPORT=y
 CONFIG_HID=y
 # CONFIG_HID_DEBUG is not set
-# CONFIG_HIDRAW is not set
+CONFIG_HIDRAW=y
 
 #
 # USB Input Devices
@@ -807,17 +794,20 @@
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_DEVICE_CLASS is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
 # CONFIG_USB_OTG is not set
 
 #
 # USB Host Controller Drivers
 #
+# CONFIG_USB_C67X00_HCD is not set
 CONFIG_USB_EHCI_HCD=m
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
 CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y
 # CONFIG_USB_EHCI_HCD_PPC_OF is not set
 # CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=m
 # CONFIG_USB_OHCI_HCD_PPC_OF is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
@@ -831,6 +821,7 @@
 #
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
 
 #
 # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -890,12 +881,45 @@
 # CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
 # CONFIG_USB_GADGET is not set
 # CONFIG_MMC is not set
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
 # CONFIG_EDAC is not set
-# CONFIG_RTC_CLASS is not set
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_PPC=m
 # CONFIG_DMADEVICES is not set
 # CONFIG_UIO is not set
 
@@ -911,6 +935,7 @@
 # CONFIG_EXT3_FS_SECURITY is not set
 # CONFIG_EXT4DEV_FS is not set
 CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
@@ -959,8 +984,8 @@
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
 # CONFIG_TMPFS_POSIX_ACL is not set
-# CONFIG_HUGETLBFS is not set
-# CONFIG_HUGETLB_PAGE is not set
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1059,12 +1084,15 @@
 #
 CONFIG_BITREVERSE=y
 # CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_CRC_CCITT is not set
+CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
 CONFIG_CRC_ITU_T=m
 CONFIG_CRC32=y
 # CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
 CONFIG_LZO_COMPRESS=m
 CONFIG_LZO_DECOMPRESS=m
 CONFIG_PLIST=y
@@ -1082,7 +1110,7 @@
 CONFIG_FRAME_WARN=2048
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
@@ -1090,33 +1118,49 @@
 CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS 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=y
 CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_LOCK_ALLOC is not set
-# CONFIG_PROVE_LOCKING is not set
+CONFIG_DEBUG_LOCK_ALLOC=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_LOCKDEP=y
 # CONFIG_LOCK_STAT is not set
+CONFIG_DEBUG_LOCKDEP=y
+CONFIG_TRACE_IRQFLAGS=y
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
 # CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_VM is not set
-# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_WRITECOUNT=y
 CONFIG_DEBUG_LIST=y
 # CONFIG_DEBUG_SG is not set
+CONFIG_FRAME_POINTER=y
 # CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+# CONFIG_FTRACE is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
 # CONFIG_SAMPLES is not set
 CONFIG_DEBUG_STACKOVERFLOW=y
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_DEBUG_PAGEALLOC is not set
 # CONFIG_DEBUGGER is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
 CONFIG_IRQSTACKS=y
+# CONFIG_VIRQ_DEBUG is not set
 # CONFIG_BOOTX_TEXT is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
 
@@ -1172,6 +1216,10 @@
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
 # CONFIG_CRYPTO_SHA1 is not set
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index bf0b1fd..1a40947 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -74,6 +74,7 @@
 				   misc_$(CONFIG_WORD_SIZE).o
 obj-$(CONFIG_PPC32)		+= entry_32.o setup_32.o
 obj-$(CONFIG_PPC64)		+= dma_64.o iommu.o
+obj-$(CONFIG_KGDB)		+= kgdb.o
 obj-$(CONFIG_PPC_MULTIPLATFORM)	+= prom_init.o
 obj-$(CONFIG_MODULES)		+= ppc_ksyms.o
 obj-$(CONFIG_BOOTX_TEXT)	+= btext.o
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index f7f3c21..b936a1dd 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -355,6 +355,7 @@
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.machine_check		= machine_check_generic,
+		.oprofile_cpu_type	= "ppc64/compat-power5+",
 		.platform		= "power5+",
 	},
 	{	/* Power6 */
@@ -386,6 +387,7 @@
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.machine_check		= machine_check_generic,
+		.oprofile_cpu_type	= "ppc64/compat-power6",
 		.platform		= "power6",
 	},
 	{	/* 2.06-compliant processor, i.e. Power7 "architected" mode */
@@ -397,6 +399,7 @@
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.machine_check		= machine_check_generic,
+		.oprofile_cpu_type	= "ppc64/compat-power7",
 		.platform		= "power7",
 	},
 	{	/* Power7 */
@@ -1629,6 +1632,23 @@
 				t->cpu_setup = s->cpu_setup;
 				t->cpu_restore = s->cpu_restore;
 				t->platform = s->platform;
+				/*
+				 * If we have passed through this logic once
+				 * before and have pulled the default case
+				 * because the real PVR was not found inside
+				 * cpu_specs[], then we are possibly running in
+				 * compatibility mode. In that case, let the
+				 * oprofiler know which set of compatibility
+				 * counters to pull from by making sure the
+				 * oprofile_cpu_type string is set to that of
+				 * compatibility mode. If the oprofile_cpu_type
+				 * already has a value, then we are possibly
+				 * overriding a real PVR with a logical one, and,
+				 * in that case, keep the current value for
+				 * oprofile_cpu_type.
+				 */
+				if (t->oprofile_cpu_type == NULL)
+					t->oprofile_cpu_type = s->oprofile_cpu_type;
 			} else
 				*t = *s;
 			*PTRRELOC(&cur_cpu_spec) = &the_cpu_spec;
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index c426850..3cb52fa 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -151,16 +151,11 @@
 	/* Invalidate TLB0 */
 	li	r6,0x04
 	tlbivax 0,r6
-#ifdef CONFIG_SMP
-	tlbsync
-#endif
+	TLBSYNC
 	/* Invalidate TLB1 */
 	li	r6,0x0c
 	tlbivax 0,r6
-#ifdef CONFIG_SMP
-	tlbsync
-#endif
-	msync
+	TLBSYNC
 
 /* 3. Setup a temp mapping and jump to it */
 	andi.	r5, r3, 0x1	/* Find an entry not used and is non-zero */
@@ -238,10 +233,7 @@
 	/* Invalidate TLB1 */
 	li	r9,0x0c
 	tlbivax 0,r9
-#ifdef CONFIG_SMP
-	tlbsync
-#endif
-	msync
+	TLBSYNC
 
 /* 6. Setup KERNELBASE mapping in TLB1[0] */
 	lis	r6,0x1000		/* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */
@@ -283,10 +275,7 @@
 	/* Invalidate TLB1 */
 	li	r9,0x0c
 	tlbivax 0,r9
-#ifdef CONFIG_SMP
-	tlbsync
-#endif
-	msync
+	TLBSYNC
 
 	/* Establish the interrupt vector offsets */
 	SET_IVOR(0,  CriticalInput);
@@ -483,90 +472,16 @@
 
 	/* Data Storage Interrupt */
 	START_EXCEPTION(DataStorage)
-	mtspr	SPRN_SPRG0, r10		/* Save some working registers */
-	mtspr	SPRN_SPRG1, r11
-	mtspr	SPRN_SPRG4W, r12
-	mtspr	SPRN_SPRG5W, r13
-	mfcr	r11
-	mtspr	SPRN_SPRG7W, r11
-
-	/*
-	 * Check if it was a store fault, if not then bail
-	 * because a user tried to access a kernel or
-	 * read-protected page.  Otherwise, get the
-	 * offending address and handle it.
-	 */
-	mfspr	r10, SPRN_ESR
-	andis.	r10, r10, ESR_ST@h
-	beq	2f
-
-	mfspr	r10, SPRN_DEAR		/* Get faulting address */
-
-	/* If we are faulting a kernel address, we have to use the
-	 * kernel page tables.
-	 */
-	lis	r11, PAGE_OFFSET@h
-	cmplw	0, r10, r11
-	bge	2f
-
-	/* Get the PGD for the current thread */
-3:
-	mfspr	r11,SPRN_SPRG3
-	lwz	r11,PGDIR(r11)
-4:
-	FIND_PTE
-
-	/* Are _PAGE_USER & _PAGE_RW set & _PAGE_HWWRITE not? */
-	andi.	r13, r11, _PAGE_RW|_PAGE_USER|_PAGE_HWWRITE
-	cmpwi	0, r13, _PAGE_RW|_PAGE_USER
-	bne	2f			/* Bail if not */
-
-	/* Update 'changed'. */
-	ori	r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
-	stw	r11, PTE_FLAGS_OFFSET(r12) /* Update Linux page table */
-
-	/* MAS2 not updated as the entry does exist in the tlb, this
-	   fault taken to detect state transition (eg: COW -> DIRTY)
-	 */
-	andi.	r11, r11, _PAGE_HWEXEC
-	rlwimi	r11, r11, 31, 27, 27	/* SX <- _PAGE_HWEXEC */
-	ori	r11, r11, (MAS3_UW|MAS3_SW|MAS3_UR|MAS3_SR)@l /* set static perms */
-
-	/* update search PID in MAS6, AS = 0 */
-	mfspr	r12, SPRN_PID0
-	slwi	r12, r12, 16
-	mtspr	SPRN_MAS6, r12
-
-	/* find the TLB index that caused the fault.  It has to be here. */
-	tlbsx	0, r10
-
-	/* only update the perm bits, assume the RPN is fine */
-	mfspr	r12, SPRN_MAS3
-	rlwimi	r12, r11, 0, 20, 31
-	mtspr	SPRN_MAS3,r12
-	tlbwe
-
-	/* Done...restore registers and get out of here.  */
-	mfspr	r11, SPRN_SPRG7R
-	mtcr	r11
-	mfspr	r13, SPRN_SPRG5R
-	mfspr	r12, SPRN_SPRG4R
-	mfspr	r11, SPRN_SPRG1
-	mfspr	r10, SPRN_SPRG0
-	rfi			/* Force context change */
-
-2:
-	/*
-	 * The bailout.  Restore registers to pre-exception conditions
-	 * and call the heavyweights to help us out.
-	 */
-	mfspr	r11, SPRN_SPRG7R
-	mtcr	r11
-	mfspr	r13, SPRN_SPRG5R
-	mfspr	r12, SPRN_SPRG4R
-	mfspr	r11, SPRN_SPRG1
-	mfspr	r10, SPRN_SPRG0
-	b	data_access
+	NORMAL_EXCEPTION_PROLOG
+	mfspr	r5,SPRN_ESR		/* Grab the ESR, save it, pass arg3 */
+	stw	r5,_ESR(r11)
+	mfspr	r4,SPRN_DEAR		/* Grab the DEAR, save it, pass arg2 */
+	andis.	r10,r5,(ESR_ILK|ESR_DLK)@h
+	bne	1f
+	EXC_XFER_EE_LITE(0x0300, handle_page_fault)
+1:
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	EXC_XFER_EE_LITE(0x0300, CacheLockingException)
 
 	/* Instruction Storage Interrupt */
 	INSTRUCTION_STORAGE_EXCEPTION
@@ -645,15 +560,30 @@
 	lwz	r11,PGDIR(r11)
 
 4:
+	/* Mask of required permission bits. Note that while we
+	 * do copy ESR:ST to _PAGE_RW position as trying to write
+	 * to an RO page is pretty common, we don't do it with
+	 * _PAGE_DIRTY. We could do it, but it's a fairly rare
+	 * event so I'd rather take the overhead when it happens
+	 * rather than adding an instruction here. We should measure
+	 * whether the whole thing is worth it in the first place
+	 * as we could avoid loading SPRN_ESR completely in the first
+	 * place...
+	 *
+	 * TODO: Is it worth doing that mfspr & rlwimi in the first
+	 *       place or can we save a couple of instructions here ?
+	 */
+	mfspr	r12,SPRN_ESR
+	li	r13,_PAGE_PRESENT|_PAGE_ACCESSED
+	rlwimi	r13,r12,11,29,29
+
 	FIND_PTE
-	andi.	r13, r11, _PAGE_PRESENT	/* Is the page present? */
-	beq	2f			/* Bail if not present */
+	andc.	r13,r13,r11		/* Check permission */
+	bne	2f			/* Bail if permission mismach */
 
 #ifdef CONFIG_PTE_64BIT
 	lwz	r13, 0(r12)
 #endif
-	ori	r11, r11, _PAGE_ACCESSED
-	stw	r11, PTE_FLAGS_OFFSET(r12)
 
 	 /* Jump to common tlb load */
 	b	finish_tlb_load
@@ -667,7 +597,7 @@
 	mfspr	r12, SPRN_SPRG4R
 	mfspr	r11, SPRN_SPRG1
 	mfspr	r10, SPRN_SPRG0
-	b	data_access
+	b	DataStorage
 
 	/* Instruction TLB Error Interrupt */
 	/*
@@ -705,15 +635,16 @@
 	lwz	r11,PGDIR(r11)
 
 4:
+	/* Make up the required permissions */
+	li	r13,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_HWEXEC
+
 	FIND_PTE
-	andi.	r13, r11, _PAGE_PRESENT	/* Is the page present? */
-	beq	2f			/* Bail if not present */
+	andc.	r13,r13,r11		/* Check permission */
+	bne	2f			/* Bail if permission mismach */
 
 #ifdef CONFIG_PTE_64BIT
 	lwz	r13, 0(r12)
 #endif
-	ori	r11, r11, _PAGE_ACCESSED
-	stw	r11, PTE_FLAGS_OFFSET(r12)
 
 	/* Jump to common TLB load point */
 	b	finish_tlb_load
@@ -768,29 +699,13 @@
  * Local functions
  */
 
-	/*
-	 * Data TLB exceptions will bail out to this point
-	 * if they can't resolve the lightweight TLB fault.
-	 */
-data_access:
-	NORMAL_EXCEPTION_PROLOG
-	mfspr	r5,SPRN_ESR		/* Grab the ESR, save it, pass arg3 */
-	stw	r5,_ESR(r11)
-	mfspr	r4,SPRN_DEAR		/* Grab the DEAR, save it, pass arg2 */
-	andis.	r10,r5,(ESR_ILK|ESR_DLK)@h
-	bne	1f
-	EXC_XFER_EE_LITE(0x0300, handle_page_fault)
-1:
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	EXC_XFER_EE_LITE(0x0300, CacheLockingException)
-
 /*
-
  * Both the instruction and data TLB miss get to this
  * point to load the TLB.
  *	r10 - EA of fault
  *	r11 - TLB (info from Linux PTE)
- *	r12, r13 - available to use
+ *	r12 - available to use
+ *	r13 - upper bits of PTE (if PTE_64BIT) or available to use
  *	CR5 - results of addr >= PAGE_OFFSET
  *	MAS0, MAS1 - loaded with proper value when we get here
  *	MAS2, MAS3 - will need additional info from Linux PTE
@@ -812,20 +727,14 @@
 #endif
 	mtspr	SPRN_MAS2, r12
 
-	bge	5, 1f
-
-	/* is user addr */
-	andi.	r12, r11, (_PAGE_USER | _PAGE_HWWRITE | _PAGE_HWEXEC)
+	li	r10, (_PAGE_HWEXEC | _PAGE_PRESENT)
+	rlwimi	r10, r11, 31, 29, 29	/* extract _PAGE_DIRTY into SW */
+	and	r12, r11, r10
 	andi.	r10, r11, _PAGE_USER	/* Test for _PAGE_USER */
-	srwi	r10, r12, 1
-	or	r12, r12, r10	/* Copy user perms into supervisor */
-	iseleq	r12, 0, r12
-	b	2f
-
-	/* is kernel addr */
-1:	rlwinm	r12, r11, 31, 29, 29	/* Extract _PAGE_HWWRITE into SW */
-	ori	r12, r12, (MAS3_SX | MAS3_SR)
-
+	slwi	r10, r12, 1
+	or	r10, r10, r12
+	iseleq	r12, r12, r10
+	
 #ifdef CONFIG_PTE_64BIT
 2:	rlwimi	r12, r13, 24, 0, 7	/* grab RPN[32:39] */
 	rlwimi	r12, r11, 24, 8, 19	/* grab RPN[40:51] */
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index 8c68ee9..2385f68 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -186,7 +186,8 @@
 static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
 			      void *page, unsigned int npages,
 			      enum dma_data_direction direction,
-			      unsigned long mask, unsigned int align_order)
+			      unsigned long mask, unsigned int align_order,
+			      struct dma_attrs *attrs)
 {
 	unsigned long entry, flags;
 	dma_addr_t ret = DMA_ERROR_CODE;
@@ -205,7 +206,7 @@
 
 	/* Put the TCEs in the HW table */
 	ppc_md.tce_build(tbl, entry, npages, (unsigned long)page & IOMMU_PAGE_MASK,
-			 direction);
+			 direction, attrs);
 
 
 	/* Flush/invalidate TLB caches if necessary */
@@ -336,7 +337,8 @@
 			    npages, entry, dma_addr);
 
 		/* Insert into HW table */
-		ppc_md.tce_build(tbl, entry, npages, vaddr & IOMMU_PAGE_MASK, direction);
+		ppc_md.tce_build(tbl, entry, npages, vaddr & IOMMU_PAGE_MASK,
+				 direction, attrs);
 
 		/* If we are in an open segment, try merging */
 		if (segstart != s) {
@@ -573,7 +575,8 @@
 			align = PAGE_SHIFT - IOMMU_PAGE_SHIFT;
 
 		dma_handle = iommu_alloc(dev, tbl, vaddr, npages, direction,
-					 mask >> IOMMU_PAGE_SHIFT, align);
+					 mask >> IOMMU_PAGE_SHIFT, align,
+					 attrs);
 		if (dma_handle == DMA_ERROR_CODE) {
 			if (printk_ratelimit())  {
 				printk(KERN_INFO "iommu_alloc failed, "
@@ -642,7 +645,7 @@
 	nio_pages = size >> IOMMU_PAGE_SHIFT;
 	io_order = get_iommu_order(size);
 	mapping = iommu_alloc(dev, tbl, ret, nio_pages, DMA_BIDIRECTIONAL,
-			      mask >> IOMMU_PAGE_SHIFT, io_order);
+			      mask >> IOMMU_PAGE_SHIFT, io_order, NULL);
 	if (mapping == DMA_ERROR_CODE) {
 		free_pages((unsigned long)ret, order);
 		return NULL;
diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c
new file mode 100644
index 0000000..b4fdf2f
--- /dev/null
+++ b/arch/powerpc/kernel/kgdb.c
@@ -0,0 +1,410 @@
+/*
+ * PowerPC backend to the KGDB stub.
+ *
+ * 1998 (c) Michael AK Tesch (tesch@cs.wisc.edu)
+ * Copyright (C) 2003 Timesys Corporation.
+ * Copyright (C) 2004-2006 MontaVista Software, Inc.
+ * PPC64 Mods (C) 2005 Frank Rowand (frowand@mvista.com)
+ * PPC32 support restored by Vitaly Wool <vwool@ru.mvista.com> and
+ * Sergei Shtylyov <sshtylyov@ru.mvista.com>
+ * Copyright (C) 2007-2008 Wind River Systems, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program as licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/kgdb.h>
+#include <linux/smp.h>
+#include <linux/signal.h>
+#include <linux/ptrace.h>
+#include <asm/current.h>
+#include <asm/processor.h>
+#include <asm/machdep.h>
+
+/*
+ * This table contains the mapping between PowerPC hardware trap types, and
+ * signals, which are primarily what GDB understands.  GDB and the kernel
+ * don't always agree on values, so we use constants taken from gdb-6.2.
+ */
+static struct hard_trap_info
+{
+	unsigned int tt;		/* Trap type code for powerpc */
+	unsigned char signo;		/* Signal that we map this trap into */
+} hard_trap_info[] = {
+	{ 0x0100, 0x02 /* SIGINT */  },		/* system reset */
+	{ 0x0200, 0x0b /* SIGSEGV */ },		/* machine check */
+	{ 0x0300, 0x0b /* SIGSEGV */ },		/* data access */
+	{ 0x0400, 0x0b /* SIGSEGV */ },		/* instruction access */
+	{ 0x0500, 0x02 /* SIGINT */  },		/* external interrupt */
+	{ 0x0600, 0x0a /* SIGBUS */  },		/* alignment */
+	{ 0x0700, 0x05 /* SIGTRAP */ },		/* program check */
+	{ 0x0800, 0x08 /* SIGFPE */  },		/* fp unavailable */
+	{ 0x0900, 0x0e /* SIGALRM */ },		/* decrementer */
+	{ 0x0c00, 0x14 /* SIGCHLD */ },		/* system call */
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+	{ 0x2002, 0x05 /* SIGTRAP */ },		/* debug */
+#if defined(CONFIG_FSL_BOOKE)
+	{ 0x2010, 0x08 /* SIGFPE */  },		/* spe unavailable */
+	{ 0x2020, 0x08 /* SIGFPE */  },		/* spe unavailable */
+	{ 0x2030, 0x08 /* SIGFPE */  },		/* spe fp data */
+	{ 0x2040, 0x08 /* SIGFPE */  },		/* spe fp data */
+	{ 0x2050, 0x08 /* SIGFPE */  },		/* spe fp round */
+	{ 0x2060, 0x0e /* SIGILL */  },		/* performace monitor */
+	{ 0x2900, 0x08 /* SIGFPE */  },		/* apu unavailable */
+	{ 0x3100, 0x0e /* SIGALRM */ },		/* fixed interval timer */
+	{ 0x3200, 0x02 /* SIGINT */  }, 	/* watchdog */
+#else /* ! CONFIG_FSL_BOOKE */
+	{ 0x1000, 0x0e /* SIGALRM */ },		/* prog interval timer */
+	{ 0x1010, 0x0e /* SIGALRM */ },		/* fixed interval timer */
+	{ 0x1020, 0x02 /* SIGINT */  }, 	/* watchdog */
+	{ 0x2010, 0x08 /* SIGFPE */  },		/* fp unavailable */
+	{ 0x2020, 0x08 /* SIGFPE */  },		/* ap unavailable */
+#endif
+#else /* ! (defined(CONFIG_40x) || defined(CONFIG_BOOKE)) */
+	{ 0x0d00, 0x05 /* SIGTRAP */ },		/* single-step */
+#if defined(CONFIG_8xx)
+	{ 0x1000, 0x04 /* SIGILL */  },		/* software emulation */
+#else /* ! CONFIG_8xx */
+	{ 0x0f00, 0x04 /* SIGILL */  },		/* performance monitor */
+	{ 0x0f20, 0x08 /* SIGFPE */  },		/* altivec unavailable */
+	{ 0x1300, 0x05 /* SIGTRAP */ }, 	/* instruction address break */
+#if defined(CONFIG_PPC64)
+	{ 0x1200, 0x05 /* SIGILL */  },		/* system error */
+	{ 0x1500, 0x04 /* SIGILL */  },		/* soft patch */
+	{ 0x1600, 0x04 /* SIGILL */  },		/* maintenance */
+	{ 0x1700, 0x08 /* SIGFPE */  },		/* altivec assist */
+	{ 0x1800, 0x04 /* SIGILL */  },		/* thermal */
+#else /* ! CONFIG_PPC64 */
+	{ 0x1400, 0x02 /* SIGINT */  },		/* SMI */
+	{ 0x1600, 0x08 /* SIGFPE */  },		/* altivec assist */
+	{ 0x1700, 0x04 /* SIGILL */  },		/* TAU */
+	{ 0x2000, 0x05 /* SIGTRAP */ },		/* run mode */
+#endif
+#endif
+#endif
+	{ 0x0000, 0x00 }			/* Must be last */
+};
+
+static int computeSignal(unsigned int tt)
+{
+	struct hard_trap_info *ht;
+
+	for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+		if (ht->tt == tt)
+			return ht->signo;
+
+	return SIGHUP;		/* default for things we don't know about */
+}
+
+static int kgdb_call_nmi_hook(struct pt_regs *regs)
+{
+	kgdb_nmicallback(raw_smp_processor_id(), regs);
+	return 0;
+}
+
+#ifdef CONFIG_SMP
+void kgdb_roundup_cpus(unsigned long flags)
+{
+	smp_send_debugger_break(MSG_ALL_BUT_SELF);
+}
+#endif
+
+/* KGDB functions to use existing PowerPC64 hooks. */
+static int kgdb_debugger(struct pt_regs *regs)
+{
+	return kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs);
+}
+
+static int kgdb_handle_breakpoint(struct pt_regs *regs)
+{
+	if (user_mode(regs))
+		return 0;
+
+	if (kgdb_handle_exception(0, SIGTRAP, 0, regs) != 0)
+		return 0;
+
+	if (*(u32 *) (regs->nip) == *(u32 *) (&arch_kgdb_ops.gdb_bpt_instr))
+		regs->nip += 4;
+
+	return 1;
+}
+
+static int kgdb_singlestep(struct pt_regs *regs)
+{
+	struct thread_info *thread_info, *exception_thread_info;
+
+	if (user_mode(regs))
+		return 0;
+
+	/*
+	 * On Book E and perhaps other processsors, singlestep is handled on
+	 * the critical exception stack.  This causes current_thread_info()
+	 * to fail, since it it locates the thread_info by masking off
+	 * the low bits of the current stack pointer.  We work around
+	 * this issue by copying the thread_info from the kernel stack
+	 * before calling kgdb_handle_exception, and copying it back
+	 * afterwards.  On most processors the copy is avoided since
+	 * exception_thread_info == thread_info.
+	 */
+	thread_info = (struct thread_info *)(regs->gpr[1] & ~(THREAD_SIZE-1));
+	exception_thread_info = current_thread_info();
+
+	if (thread_info != exception_thread_info)
+		memcpy(exception_thread_info, thread_info, sizeof *thread_info);
+
+	kgdb_handle_exception(0, SIGTRAP, 0, regs);
+
+	if (thread_info != exception_thread_info)
+		memcpy(thread_info, exception_thread_info, sizeof *thread_info);
+
+	return 1;
+}
+
+static int kgdb_iabr_match(struct pt_regs *regs)
+{
+	if (user_mode(regs))
+		return 0;
+
+	if (kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs) != 0)
+		return 0;
+	return 1;
+}
+
+static int kgdb_dabr_match(struct pt_regs *regs)
+{
+	if (user_mode(regs))
+		return 0;
+
+	if (kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs) != 0)
+		return 0;
+	return 1;
+}
+
+#define PACK64(ptr, src) do { *(ptr++) = (src); } while (0)
+
+#define PACK32(ptr, src) do {          \
+	u32 *ptr32;                   \
+	ptr32 = (u32 *)ptr;           \
+	*(ptr32++) = (src);           \
+	ptr = (unsigned long *)ptr32; \
+	} while (0)
+
+
+void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+	unsigned long *ptr = gdb_regs;
+	int reg;
+
+	memset(gdb_regs, 0, NUMREGBYTES);
+
+	for (reg = 0; reg < 32; reg++)
+		PACK64(ptr, regs->gpr[reg]);
+
+#ifdef CONFIG_FSL_BOOKE
+#ifdef CONFIG_SPE
+	for (reg = 0; reg < 32; reg++)
+		PACK64(ptr, current->thread.evr[reg]);
+#else
+	ptr += 32;
+#endif
+#else
+	/* fp registers not used by kernel, leave zero */
+	ptr += 32 * 8 / sizeof(long);
+#endif
+
+	PACK64(ptr, regs->nip);
+	PACK64(ptr, regs->msr);
+	PACK32(ptr, regs->ccr);
+	PACK64(ptr, regs->link);
+	PACK64(ptr, regs->ctr);
+	PACK32(ptr, regs->xer);
+
+	BUG_ON((unsigned long)ptr >
+	       (unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
+}
+
+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
+{
+	struct pt_regs *regs = (struct pt_regs *)(p->thread.ksp +
+						  STACK_FRAME_OVERHEAD);
+	unsigned long *ptr = gdb_regs;
+	int reg;
+
+	memset(gdb_regs, 0, NUMREGBYTES);
+
+	/* Regs GPR0-2 */
+	for (reg = 0; reg < 3; reg++)
+		PACK64(ptr, regs->gpr[reg]);
+
+	/* Regs GPR3-13 are caller saved, not in regs->gpr[] */
+	ptr += 11;
+
+	/* Regs GPR14-31 */
+	for (reg = 14; reg < 32; reg++)
+		PACK64(ptr, regs->gpr[reg]);
+
+#ifdef CONFIG_FSL_BOOKE
+#ifdef CONFIG_SPE
+	for (reg = 0; reg < 32; reg++)
+		PACK64(ptr, p->thread.evr[reg]);
+#else
+	ptr += 32;
+#endif
+#else
+	/* fp registers not used by kernel, leave zero */
+	ptr += 32 * 8 / sizeof(long);
+#endif
+
+	PACK64(ptr, regs->nip);
+	PACK64(ptr, regs->msr);
+	PACK32(ptr, regs->ccr);
+	PACK64(ptr, regs->link);
+	PACK64(ptr, regs->ctr);
+	PACK32(ptr, regs->xer);
+
+	BUG_ON((unsigned long)ptr >
+	       (unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
+}
+
+#define UNPACK64(dest, ptr) do { dest = *(ptr++); } while (0)
+
+#define UNPACK32(dest, ptr) do {       \
+	u32 *ptr32;                   \
+	ptr32 = (u32 *)ptr;           \
+	dest = *(ptr32++);            \
+	ptr = (unsigned long *)ptr32; \
+	} while (0)
+
+void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+	unsigned long *ptr = gdb_regs;
+	int reg;
+#ifdef CONFIG_SPE
+	union {
+		u32 v32[2];
+		u64 v64;
+	} acc;
+#endif
+
+	for (reg = 0; reg < 32; reg++)
+		UNPACK64(regs->gpr[reg], ptr);
+
+#ifdef CONFIG_FSL_BOOKE
+#ifdef CONFIG_SPE
+	for (reg = 0; reg < 32; reg++)
+		UNPACK64(current->thread.evr[reg], ptr);
+#else
+	ptr += 32;
+#endif
+#else
+	/* fp registers not used by kernel, leave zero */
+	ptr += 32 * 8 / sizeof(int);
+#endif
+
+	UNPACK64(regs->nip, ptr);
+	UNPACK64(regs->msr, ptr);
+	UNPACK32(regs->ccr, ptr);
+	UNPACK64(regs->link, ptr);
+	UNPACK64(regs->ctr, ptr);
+	UNPACK32(regs->xer, ptr);
+
+	BUG_ON((unsigned long)ptr >
+	       (unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
+}
+
+/*
+ * This function does PowerPC specific procesing for interfacing to gdb.
+ */
+int kgdb_arch_handle_exception(int vector, int signo, int err_code,
+			       char *remcom_in_buffer, char *remcom_out_buffer,
+			       struct pt_regs *linux_regs)
+{
+	char *ptr = &remcom_in_buffer[1];
+	unsigned long addr;
+
+	switch (remcom_in_buffer[0]) {
+		/*
+		 * sAA..AA   Step one instruction from AA..AA
+		 * This will return an error to gdb ..
+		 */
+	case 's':
+	case 'c':
+		/* handle the optional parameter */
+		if (kgdb_hex2long(&ptr, &addr))
+			linux_regs->nip = addr;
+
+		atomic_set(&kgdb_cpu_doing_single_step, -1);
+		/* set the trace bit if we're stepping */
+		if (remcom_in_buffer[0] == 's') {
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+			mtspr(SPRN_DBCR0,
+			      mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
+			linux_regs->msr |= MSR_DE;
+#else
+			linux_regs->msr |= MSR_SE;
+#endif
+			kgdb_single_step = 1;
+			if (kgdb_contthread)
+				atomic_set(&kgdb_cpu_doing_single_step,
+					   raw_smp_processor_id());
+		}
+		return 0;
+	}
+
+	return -1;
+}
+
+/*
+ * Global data
+ */
+struct kgdb_arch arch_kgdb_ops = {
+	.gdb_bpt_instr = {0x7d, 0x82, 0x10, 0x08},
+};
+
+static int kgdb_not_implemented(struct pt_regs *regs)
+{
+	return 0;
+}
+
+static void *old__debugger_ipi;
+static void *old__debugger;
+static void *old__debugger_bpt;
+static void *old__debugger_sstep;
+static void *old__debugger_iabr_match;
+static void *old__debugger_dabr_match;
+static void *old__debugger_fault_handler;
+
+int kgdb_arch_init(void)
+{
+	old__debugger_ipi = __debugger_ipi;
+	old__debugger = __debugger;
+	old__debugger_bpt = __debugger_bpt;
+	old__debugger_sstep = __debugger_sstep;
+	old__debugger_iabr_match = __debugger_iabr_match;
+	old__debugger_dabr_match = __debugger_dabr_match;
+	old__debugger_fault_handler = __debugger_fault_handler;
+
+	__debugger_ipi = kgdb_call_nmi_hook;
+	__debugger = kgdb_debugger;
+	__debugger_bpt = kgdb_handle_breakpoint;
+	__debugger_sstep = kgdb_singlestep;
+	__debugger_iabr_match = kgdb_iabr_match;
+	__debugger_dabr_match = kgdb_dabr_match;
+	__debugger_fault_handler = kgdb_not_implemented;
+
+	return 0;
+}
+
+void kgdb_arch_exit(void)
+{
+	__debugger_ipi = old__debugger_ipi;
+	__debugger = old__debugger;
+	__debugger_bpt = old__debugger_bpt;
+	__debugger_sstep = old__debugger_sstep;
+	__debugger_iabr_match = old__debugger_iabr_match;
+	__debugger_dabr_match = old__debugger_dabr_match;
+	__debugger_fault_handler = old__debugger_fault_handler;
+}
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 063cdd4..224e9a1 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -598,6 +598,7 @@
 			res->start = pci_addr;
 			break;
 		case 2:		/* PCI Memory space */
+		case 3:		/* PCI 64 bits Memory space */
 			printk(KERN_INFO
 			       " MEM 0x%016llx..0x%016llx -> 0x%016llx %s\n",
 			       cpu_addr, cpu_addr + size - 1, pci_addr,
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
index 90eb3a3..bc1fb27 100644
--- a/arch/powerpc/kernel/prom_parse.c
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -128,31 +128,6 @@
 		*sizec = 2;
 }
 
-static u64 of_bus_pci_map(u32 *addr, const u32 *range, int na, int ns, int pna)
-{
-	u64 cp, s, da;
-
-	/* Check address type match */
-	if ((addr[0] ^ range[0]) & 0x03000000)
-		return OF_BAD_ADDR;
-
-	/* Read address values, skipping high cell */
-	cp = of_read_number(range + 1, na - 1);
-	s  = of_read_number(range + na + pna, ns);
-	da = of_read_number(addr + 1, na - 1);
-
-	DBG("OF: PCI map, cp="PRu64", s="PRu64", da="PRu64"\n", cp, s, da);
-
-	if (da < cp || da >= (cp + s))
-		return OF_BAD_ADDR;
-	return da - cp;
-}
-
-static int of_bus_pci_translate(u32 *addr, u64 offset, int na)
-{
-	return of_bus_default_translate(addr + 1, offset, na - 1);
-}
-
 static unsigned int of_bus_pci_get_flags(const u32 *addr)
 {
 	unsigned int flags = 0;
@@ -172,6 +147,35 @@
 	return flags;
 }
 
+static u64 of_bus_pci_map(u32 *addr, const u32 *range, int na, int ns, int pna)
+{
+	u64 cp, s, da;
+	unsigned int af, rf;
+
+	af = of_bus_pci_get_flags(addr);
+	rf = of_bus_pci_get_flags(range);
+
+	/* Check address type match */
+	if ((af ^ rf) & (IORESOURCE_MEM | IORESOURCE_IO))
+		return OF_BAD_ADDR;
+
+	/* Read address values, skipping high cell */
+	cp = of_read_number(range + 1, na - 1);
+	s  = of_read_number(range + na + pna, ns);
+	da = of_read_number(addr + 1, na - 1);
+
+	DBG("OF: PCI map, cp="PRu64", s="PRu64", da="PRu64"\n", cp, s, da);
+
+	if (da < cp || da >= (cp + s))
+		return OF_BAD_ADDR;
+	return da - cp;
+}
+
+static int of_bus_pci_translate(u32 *addr, u64 offset, int na)
+{
+	return of_bus_default_translate(addr + 1, offset, na - 1);
+}
+
 const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
 			unsigned int *flags)
 {
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 4efebe8..066e65c 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -43,10 +43,6 @@
 
 #define DBG(fmt...)
 
-#if defined CONFIG_KGDB
-#include <asm/kgdb.h>
-#endif
-
 extern void bootx_init(unsigned long r4, unsigned long phys);
 
 int boot_cpuid;
@@ -302,18 +298,6 @@
 
 	xmon_setup();
 
-#if defined(CONFIG_KGDB)
-	if (ppc_md.kgdb_map_scc)
-		ppc_md.kgdb_map_scc();
-	set_debug_traps();
-	if (strstr(cmd_line, "gdb")) {
-		if (ppc_md.progress)
-			ppc_md.progress("setup_arch: kgdb breakpoint", 0x4000);
-		printk("kgdb breakpoint activated\n");
-		breakpoint();
-	}
-#endif
-
 	/*
 	 * Set cache line size based on type of cpu as a default.
 	 * Systems with OF can look in the properties on the cpu node(s)
diff --git a/arch/powerpc/kernel/stacktrace.c b/arch/powerpc/kernel/stacktrace.c
index 071bee3..f258964 100644
--- a/arch/powerpc/kernel/stacktrace.c
+++ b/arch/powerpc/kernel/stacktrace.c
@@ -59,6 +59,6 @@
 
 void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
 {
-	save_context_stack(trace, tsk->thread.regs->gpr[1], tsk, 0);
+	save_context_stack(trace, tsk->thread.ksp, tsk, 0);
 }
 EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index c8127f8..aba0ba9 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -28,7 +28,9 @@
 /* Time in microseconds we delay before sleeping in the idle loop */
 DEFINE_PER_CPU(unsigned long, smt_snooze_delay) = { 100 };
 
-static ssize_t store_smt_snooze_delay(struct sys_device *dev, const char *buf,
+static ssize_t store_smt_snooze_delay(struct sys_device *dev,
+				      struct sysdev_attribute *attr,
+				      const char *buf,
 				      size_t count)
 {
 	struct cpu *cpu = container_of(dev, struct cpu, sysdev);
@@ -44,7 +46,9 @@
 	return count;
 }
 
-static ssize_t show_smt_snooze_delay(struct sys_device *dev, char *buf)
+static ssize_t show_smt_snooze_delay(struct sys_device *dev,
+				     struct sysdev_attribute *attr,
+				     char *buf)
 {
 	struct cpu *cpu = container_of(dev, struct cpu, sysdev);
 
@@ -152,14 +156,17 @@
 	mtspr(ADDRESS, val); \
 	return 0; \
 } \
-static ssize_t show_##NAME(struct sys_device *dev, char *buf) \
+static ssize_t show_##NAME(struct sys_device *dev, \
+			struct sysdev_attribute *attr, \
+			char *buf) \
 { \
 	struct cpu *cpu = container_of(dev, struct cpu, sysdev); \
 	unsigned long val = run_on_cpu(cpu->sysdev.id, read_##NAME, 0); \
 	return sprintf(buf, "%lx\n", val); \
 } \
 static ssize_t __used \
-	store_##NAME(struct sys_device *dev, const char *buf, size_t count) \
+	store_##NAME(struct sys_device *dev, struct sysdev_attribute *attr, \
+			const char *buf, size_t count) \
 { \
 	struct cpu *cpu = container_of(dev, struct cpu, sysdev); \
 	unsigned long val; \
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 87a72c6..a914411 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -9,6 +9,25 @@
 
 ENTRY(_stext)
 
+PHDRS {
+	kernel PT_LOAD FLAGS(7); /* RWX */
+	notes PT_NOTE FLAGS(0);
+	dummy PT_NOTE FLAGS(0);
+
+	/* binutils < 2.18 has a bug that makes it misbehave when taking an
+	   ELF file with all segments at load address 0 as input.  This
+	   happens when running "strip" on vmlinux, because of the AT() magic
+	   in this linker script.  People using GCC >= 4.2 won't run into
+	   this problem, because the "build-id" support will put some data
+	   into the "notes" segment (at a non-zero load address).
+
+	   To work around this, we force some data into both the "dummy"
+	   segment and the kernel segment, so the dummy segment will get a
+	   non-zero load address.  It's not enough to always create the
+	   "notes" segment, since if nothing gets assigned to it, its load
+	   address will be zero.  */
+}
+
 #ifdef CONFIG_PPC64
 OUTPUT_ARCH(powerpc:common64)
 jiffies = jiffies_64;
@@ -50,7 +69,7 @@
 		. = ALIGN(PAGE_SIZE);
 		_etext = .;
 		PROVIDE32 (etext = .);
-	}
+	} :kernel
 
 	/* Read-only data */
 	RODATA
@@ -62,7 +81,13 @@
 		__stop___ex_table = .;
 	}
 
-	NOTES
+	NOTES :kernel :notes
+
+	/* The dummy segment contents for the bug workaround mentioned above
+	   near PHDRS.  */
+	.dummy : {
+		LONG(0xf177)
+	} :kernel :dummy
 
 /*
  * Init sections discarded at runtime
@@ -74,7 +99,7 @@
 		_sinittext = .;
 		INIT_TEXT
 		_einittext = .;
-	}
+	} :kernel
 
 	/* .exit.text is discarded at runtime, not link time,
 	 * to deal with references from __bug_table
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
index 4e43702..8c5a03b 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -99,7 +99,7 @@
 
 	for (; fcur < fend; fcur++) {
 		if (patch_feature_section(value, fcur)) {
-			__WARN();
+			WARN_ON(1);
 			printk("Unable to patch feature section at %p - %p" \
 				" with %p - %p\n",
 				calc_addr(fcur, fcur->start_off),
diff --git a/arch/powerpc/lib/string.S b/arch/powerpc/lib/string.S
index 49eb1f1..64e2e49 100644
--- a/arch/powerpc/lib/string.S
+++ b/arch/powerpc/lib/string.S
@@ -13,13 +13,7 @@
 #include <asm/ppc_asm.h>
 
 	.section __ex_table,"a"
-#ifdef CONFIG_PPC64
-	.align	3
-#define EXTBL	.llong
-#else
-	.align	2
-#define EXTBL	.long
-#endif
+	PPC_LONG_ALIGN
 	.text
 	
 _GLOBAL(strcpy)
@@ -160,9 +154,9 @@
 	blr
 
 	.section __ex_table,"a"
-	EXTBL	11b,90b
-	EXTBL	1b,91b
-	EXTBL	8b,92b
+	PPC_LONG	11b,90b
+	PPC_LONG	1b,91b
+	PPC_LONG	8b,92b
 	.text
 
 _GLOBAL(__strncpy_from_user)
@@ -183,7 +177,7 @@
 	blr
 
 	.section __ex_table,"a"
-	EXTBL	1b,99b
+	PPC_LONG	1b,99b
 	.text
 
 /* r3 = str, r4 = len (> 0), r5 = top (highest addr) */
@@ -208,4 +202,4 @@
 	blr
 
 	.section __ex_table,"a"
-	EXTBL	1b,99b
+	PPC_LONG	1b,99b
diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig
index acd2fc8..d664b1b 100644
--- a/arch/powerpc/platforms/52xx/Kconfig
+++ b/arch/powerpc/platforms/52xx/Kconfig
@@ -3,6 +3,7 @@
 	depends on PPC_MULTIPLATFORM && PPC32
 	select FSL_SOC
 	select PPC_CLOCK
+	select PPC_PCI_CHOICE
 
 config PPC_MPC5200_SIMPLE
 	bool "Generic support for simple MPC5200 based boards"
diff --git a/arch/powerpc/platforms/82xx/Kconfig b/arch/powerpc/platforms/82xx/Kconfig
index 1c8034b..75eb1ed 100644
--- a/arch/powerpc/platforms/82xx/Kconfig
+++ b/arch/powerpc/platforms/82xx/Kconfig
@@ -30,6 +30,7 @@
 	select 8272
 	select 8260
 	select FSL_SOC
+	select PHYLIB
 	select MDIO_BITBANG
 	help
 	  This enables support for the Embedded Planet EP8248E board.
diff --git a/arch/powerpc/platforms/82xx/ep8248e.c b/arch/powerpc/platforms/82xx/ep8248e.c
index 373e993..d5770fd 100644
--- a/arch/powerpc/platforms/82xx/ep8248e.c
+++ b/arch/powerpc/platforms/82xx/ep8248e.c
@@ -59,7 +59,6 @@
 	of_node_put(np);
 }
 
-#ifdef CONFIG_FS_ENET_MDIO_FCC
 static void ep8248e_set_mdc(struct mdiobb_ctrl *ctrl, int level)
 {
 	if (level)
@@ -165,7 +164,6 @@
 	.probe = ep8248e_mdio_probe,
 	.remove = ep8248e_mdio_remove,
 };
-#endif
 
 struct cpm_pin {
 	int port, pin, flags;
@@ -298,9 +296,7 @@
 static int __init declare_of_platform_devices(void)
 {
 	of_platform_bus_probe(NULL, of_bus_ids, NULL);
-#ifdef CONFIG_FS_ENET_MDIO_FCC
 	of_register_platform_driver(&ep8248e_mdio_driver);
-#endif
 
 	return 0;
 }
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index 27d9bf8..6159c5d 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -2,7 +2,8 @@
 	bool "83xx-based boards"
 	depends on 6xx && PPC_MULTIPLATFORM
 	select PPC_UDBG_16550
-	select PPC_INDIRECT_PCI
+	select PPC_PCI_CHOICE
+	select FSL_PCI if PCI
 	select FSL_SOC
 	select IPIC
 
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile
index f331fd7..ba5028e 100644
--- a/arch/powerpc/platforms/83xx/Makefile
+++ b/arch/powerpc/platforms/83xx/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the PowerPC 83xx linux kernel.
 #
 obj-y				:= misc.o usb.o
-obj-$(CONFIG_PCI)		+= pci.o
+obj-$(CONFIG_SUSPEND)		+= suspend.o suspend-asm.o
 obj-$(CONFIG_MPC831x_RDB)	+= mpc831x_rdb.o
 obj-$(CONFIG_MPC832x_RDB)	+= mpc832x_rdb.o
 obj-$(CONFIG_MPC834x_MDS)	+= mpc834x_mds.o
diff --git a/arch/powerpc/platforms/83xx/mpc831x_rdb.c b/arch/powerpc/platforms/83xx/mpc831x_rdb.c
index c4db517..a428f8d 100644
--- a/arch/powerpc/platforms/83xx/mpc831x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc831x_rdb.c
@@ -19,6 +19,7 @@
 #include <asm/time.h>
 #include <asm/ipic.h>
 #include <asm/udbg.h>
+#include <sysdev/fsl_pci.h>
 
 #include "mpc83xx.h"
 
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c
index 6dbc6ea..dd4be4a 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c
@@ -36,6 +36,7 @@
 #include <asm/prom.h>
 #include <asm/udbg.h>
 #include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
 #include <asm/qe.h>
 #include <asm/qe_ic.h>
 
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
index e7f706b..f049d692 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
@@ -27,6 +27,7 @@
 #include <asm/qe.h>
 #include <asm/qe_ic.h>
 #include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
 
 #include "mpc83xx.h"
 
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index 50e8f63..7301d77 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -35,6 +35,7 @@
 #include <asm/prom.h>
 #include <asm/udbg.h>
 #include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
 
 #include "mpc83xx.h"
 
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c
index 2b8a0a3..30d509a 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c
@@ -35,6 +35,7 @@
 #include <asm/prom.h>
 #include <asm/udbg.h>
 #include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
 
 #include "mpc83xx.h"
 
diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c
index c2e5de6..75b80e8 100644
--- a/arch/powerpc/platforms/83xx/mpc836x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c
@@ -42,6 +42,7 @@
 #include <asm/prom.h>
 #include <asm/udbg.h>
 #include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
 #include <asm/qe.h>
 #include <asm/qe_ic.h>
 
diff --git a/arch/powerpc/platforms/83xx/mpc836x_rdk.c b/arch/powerpc/platforms/83xx/mpc836x_rdk.c
index c10dec4..a5273bb 100644
--- a/arch/powerpc/platforms/83xx/mpc836x_rdk.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_rdk.c
@@ -23,6 +23,7 @@
 #include <asm/qe.h>
 #include <asm/qe_ic.h>
 #include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
 
 #include "mpc83xx.h"
 
diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c
index 64d17b0..be62de2 100644
--- a/arch/powerpc/platforms/83xx/mpc837x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c
@@ -19,6 +19,7 @@
 #include <asm/ipic.h>
 #include <asm/udbg.h>
 #include <asm/prom.h>
+#include <sysdev/fsl_pci.h>
 
 #include "mpc83xx.h"
 
diff --git a/arch/powerpc/platforms/83xx/mpc837x_rdb.c b/arch/powerpc/platforms/83xx/mpc837x_rdb.c
index c00356b..da030af 100644
--- a/arch/powerpc/platforms/83xx/mpc837x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc837x_rdb.c
@@ -17,6 +17,7 @@
 #include <asm/time.h>
 #include <asm/ipic.h>
 #include <asm/udbg.h>
+#include <sysdev/fsl_pci.h>
 
 #include "mpc83xx.h"
 
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h
index 88a3b5c..2a7cbab 100644
--- a/arch/powerpc/platforms/83xx/mpc83xx.h
+++ b/arch/powerpc/platforms/83xx/mpc83xx.h
@@ -26,6 +26,8 @@
 #define MPC834X_SICRL_USB1         0x20000000
 #define MPC831X_SICRL_USB_MASK     0x00000c00
 #define MPC831X_SICRL_USB_ULPI     0x00000800
+#define MPC8315_SICRL_USB_MASK     0x000000fc
+#define MPC8315_SICRL_USB_ULPI     0x00000054
 #define MPC837X_SICRL_USB_MASK     0xf0000000
 #define MPC837X_SICRL_USB_ULPI     0x50000000
 
@@ -34,6 +36,8 @@
 #define MPC834X_SICRH_USB_UTMI     0x00020000
 #define MPC831X_SICRH_USB_MASK     0x000000e0
 #define MPC831X_SICRH_USB_ULPI     0x000000a0
+#define MPC8315_SICRH_USB_MASK     0x0000ff00
+#define MPC8315_SICRH_USB_ULPI     0x00000000
 
 /* USB Control Register */
 #define FSL_USB2_CONTROL_OFFS      0x500
@@ -55,7 +59,6 @@
  * mpc83xx_* files. Mostly for use by mpc83xx_setup
  */
 
-extern int mpc83xx_add_bridge(struct device_node *dev);
 extern void mpc83xx_restart(char *cmd);
 extern long mpc83xx_time_init(void);
 extern int mpc834x_usb_cfg(void);
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c
deleted file mode 100644
index 14f1080..0000000
--- a/arch/powerpc/platforms/83xx/pci.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * FSL SoC setup code
- *
- * Maintained by Kumar Gala (see MAINTAINERS for contact information)
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <linux/module.h>
-
-#include <asm/system.h>
-#include <asm/atomic.h>
-#include <asm/io.h>
-#include <asm/pci-bridge.h>
-#include <asm/prom.h>
-#include <sysdev/fsl_soc.h>
-
-#undef DEBUG
-
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
-int __init mpc83xx_add_bridge(struct device_node *dev)
-{
-	int len;
-	struct pci_controller *hose;
-	struct resource rsrc;
-	const int *bus_range;
-	int primary = 1, has_address = 0;
-	phys_addr_t immr = get_immrbase();
-
-	DBG("Adding PCI host bridge %s\n", dev->full_name);
-
-	/* Fetch host bridge registers address */
-	has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
-
-	/* Get bus range if any */
-	bus_range = of_get_property(dev, "bus-range", &len);
-	if (bus_range == NULL || len < 2 * sizeof(int)) {
-		printk(KERN_WARNING "Can't get bus-range for %s, assume"
-		       " bus 0\n", dev->full_name);
-	}
-
-	ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
-	hose = pcibios_alloc_controller(dev);
-	if (!hose)
-		return -ENOMEM;
-
-	hose->first_busno = bus_range ? bus_range[0] : 0;
-	hose->last_busno = bus_range ? bus_range[1] : 0xff;
-
-	/* MPC83xx supports up to two host controllers one at 0x8500 from immrbar
-	 * the other at 0x8600, we consider the 0x8500 the primary controller
-	 */
-	/* PCI 1 */
-	if ((rsrc.start & 0xfffff) == 0x8500) {
-		setup_indirect_pci(hose, immr + 0x8300, immr + 0x8304, 0);
-	}
-	/* PCI 2 */
-	if ((rsrc.start & 0xfffff) == 0x8600) {
-		setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384, 0);
-		primary = 0;
-	}
-
-	printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%016llx. "
-	       "Firmware bus number: %d->%d\n",
-	       (unsigned long long)rsrc.start, hose->first_busno,
-	       hose->last_busno);
-
-	DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
-	    hose, hose->cfg_addr, hose->cfg_data);
-
-	/* Interpret the "ranges" property */
-	/* This also maps the I/O region and sets isa_io/mem_base */
-	pci_process_bridge_OF_ranges(hose, dev, primary);
-
-	return 0;
-}
diff --git a/arch/powerpc/platforms/83xx/sbc834x.c b/arch/powerpc/platforms/83xx/sbc834x.c
index cf382474..fc21f5c 100644
--- a/arch/powerpc/platforms/83xx/sbc834x.c
+++ b/arch/powerpc/platforms/83xx/sbc834x.c
@@ -37,6 +37,7 @@
 #include <asm/prom.h>
 #include <asm/udbg.h>
 #include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
 
 #include "mpc83xx.h"
 
diff --git a/arch/powerpc/platforms/83xx/suspend-asm.S b/arch/powerpc/platforms/83xx/suspend-asm.S
new file mode 100644
index 0000000..1930543
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/suspend-asm.S
@@ -0,0 +1,533 @@
+/*
+ * Enter and leave deep sleep state on MPC83xx
+ *
+ * Copyright (c) 2006-2008 Freescale Semiconductor, Inc.
+ * Author: Scott Wood <scottwood@freescale.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 <asm/page.h>
+#include <asm/ppc_asm.h>
+#include <asm/reg.h>
+#include <asm/asm-offsets.h>
+
+#define SS_MEMSAVE	0x00 /* First 8 bytes of RAM */
+#define SS_HID		0x08 /* 3 HIDs */
+#define SS_IABR		0x14 /* 2 IABRs */
+#define SS_IBCR		0x1c
+#define SS_DABR		0x20 /* 2 DABRs */
+#define SS_DBCR		0x28
+#define SS_SP		0x2c
+#define SS_SR		0x30 /* 16 segment registers */
+#define SS_R2		0x70
+#define SS_MSR		0x74
+#define SS_SDR1		0x78
+#define SS_LR		0x7c
+#define SS_SPRG		0x80 /* 4 SPRGs */
+#define SS_DBAT		0x90 /* 8 DBATs */
+#define SS_IBAT		0xd0 /* 8 IBATs */
+#define SS_TB		0x110
+#define SS_CR		0x118
+#define SS_GPREG	0x11c /* r12-r31 */
+#define STATE_SAVE_SIZE 0x16c
+
+	.section .data
+	.align	5
+
+mpc83xx_sleep_save_area:
+	.space	STATE_SAVE_SIZE
+immrbase:
+	.long	0
+
+	.section .text
+	.align	5
+
+	/* r3 = physical address of IMMR */
+_GLOBAL(mpc83xx_enter_deep_sleep)
+	lis	r4, immrbase@ha
+	stw	r3, immrbase@l(r4)
+
+	/* The first 2 words of memory are used to communicate with the
+	 * bootloader, to tell it how to resume.
+	 *
+	 * The first word is the magic number 0xf5153ae5, and the second
+	 * is the pointer to mpc83xx_deep_resume.
+	 *
+	 * The original content of these two words is saved in SS_MEMSAVE.
+	 */
+
+	lis	r3, mpc83xx_sleep_save_area@h
+	ori	r3, r3, mpc83xx_sleep_save_area@l
+
+	lis	r4, KERNELBASE@h
+	lwz	r5, 0(r4)
+	lwz	r6, 4(r4)
+
+	stw	r5, SS_MEMSAVE+0(r3)
+	stw	r6, SS_MEMSAVE+4(r3)
+
+	mfspr	r5, SPRN_HID0
+	mfspr	r6, SPRN_HID1
+	mfspr	r7, SPRN_HID2
+
+	stw	r5, SS_HID+0(r3)
+	stw	r6, SS_HID+4(r3)
+	stw	r7, SS_HID+8(r3)
+
+	mfspr	r4, SPRN_IABR
+	mfspr	r5, SPRN_IABR2
+	mfspr	r6, SPRN_IBCR
+	mfspr	r7, SPRN_DABR
+	mfspr	r8, SPRN_DABR2
+	mfspr	r9, SPRN_DBCR
+
+	stw	r4, SS_IABR+0(r3)
+	stw	r5, SS_IABR+4(r3)
+	stw	r6, SS_IBCR(r3)
+	stw	r7, SS_DABR+0(r3)
+	stw	r8, SS_DABR+4(r3)
+	stw	r9, SS_DBCR(r3)
+
+	mfspr	r4, SPRN_SPRG0
+	mfspr	r5, SPRN_SPRG1
+	mfspr	r6, SPRN_SPRG2
+	mfspr	r7, SPRN_SPRG3
+	mfsdr1	r8
+
+	stw	r4, SS_SPRG+0(r3)
+	stw	r5, SS_SPRG+4(r3)
+	stw	r6, SS_SPRG+8(r3)
+	stw	r7, SS_SPRG+12(r3)
+	stw	r8, SS_SDR1(r3)
+
+	mfspr	r4, SPRN_DBAT0U
+	mfspr	r5, SPRN_DBAT0L
+	mfspr	r6, SPRN_DBAT1U
+	mfspr	r7, SPRN_DBAT1L
+
+	stw	r4, SS_DBAT+0x00(r3)
+	stw	r5, SS_DBAT+0x04(r3)
+	stw	r6, SS_DBAT+0x08(r3)
+	stw	r7, SS_DBAT+0x0c(r3)
+
+	mfspr	r4, SPRN_DBAT2U
+	mfspr	r5, SPRN_DBAT2L
+	mfspr	r6, SPRN_DBAT3U
+	mfspr	r7, SPRN_DBAT3L
+
+	stw	r4, SS_DBAT+0x10(r3)
+	stw	r5, SS_DBAT+0x14(r3)
+	stw	r6, SS_DBAT+0x18(r3)
+	stw	r7, SS_DBAT+0x1c(r3)
+
+	mfspr	r4, SPRN_DBAT4U
+	mfspr	r5, SPRN_DBAT4L
+	mfspr	r6, SPRN_DBAT5U
+	mfspr	r7, SPRN_DBAT5L
+
+	stw	r4, SS_DBAT+0x20(r3)
+	stw	r5, SS_DBAT+0x24(r3)
+	stw	r6, SS_DBAT+0x28(r3)
+	stw	r7, SS_DBAT+0x2c(r3)
+
+	mfspr	r4, SPRN_DBAT6U
+	mfspr	r5, SPRN_DBAT6L
+	mfspr	r6, SPRN_DBAT7U
+	mfspr	r7, SPRN_DBAT7L
+
+	stw	r4, SS_DBAT+0x30(r3)
+	stw	r5, SS_DBAT+0x34(r3)
+	stw	r6, SS_DBAT+0x38(r3)
+	stw	r7, SS_DBAT+0x3c(r3)
+
+	mfspr	r4, SPRN_IBAT0U
+	mfspr	r5, SPRN_IBAT0L
+	mfspr	r6, SPRN_IBAT1U
+	mfspr	r7, SPRN_IBAT1L
+
+	stw	r4, SS_IBAT+0x00(r3)
+	stw	r5, SS_IBAT+0x04(r3)
+	stw	r6, SS_IBAT+0x08(r3)
+	stw	r7, SS_IBAT+0x0c(r3)
+
+	mfspr	r4, SPRN_IBAT2U
+	mfspr	r5, SPRN_IBAT2L
+	mfspr	r6, SPRN_IBAT3U
+	mfspr	r7, SPRN_IBAT3L
+
+	stw	r4, SS_IBAT+0x10(r3)
+	stw	r5, SS_IBAT+0x14(r3)
+	stw	r6, SS_IBAT+0x18(r3)
+	stw	r7, SS_IBAT+0x1c(r3)
+
+	mfspr	r4, SPRN_IBAT4U
+	mfspr	r5, SPRN_IBAT4L
+	mfspr	r6, SPRN_IBAT5U
+	mfspr	r7, SPRN_IBAT5L
+
+	stw	r4, SS_IBAT+0x20(r3)
+	stw	r5, SS_IBAT+0x24(r3)
+	stw	r6, SS_IBAT+0x28(r3)
+	stw	r7, SS_IBAT+0x2c(r3)
+
+	mfspr	r4, SPRN_IBAT6U
+	mfspr	r5, SPRN_IBAT6L
+	mfspr	r6, SPRN_IBAT7U
+	mfspr	r7, SPRN_IBAT7L
+
+	stw	r4, SS_IBAT+0x30(r3)
+	stw	r5, SS_IBAT+0x34(r3)
+	stw	r6, SS_IBAT+0x38(r3)
+	stw	r7, SS_IBAT+0x3c(r3)
+
+	mfmsr	r4
+	mflr	r5
+	mfcr	r6
+
+	stw	r4, SS_MSR(r3)
+	stw	r5, SS_LR(r3)
+	stw	r6, SS_CR(r3)
+	stw	r1, SS_SP(r3)
+	stw	r2, SS_R2(r3)
+
+1:	mftbu	r4
+	mftb	r5
+	mftbu	r6
+	cmpw	r4, r6
+	bne	1b
+
+	stw	r4, SS_TB+0(r3)
+	stw	r5, SS_TB+4(r3)
+
+	stmw	r12, SS_GPREG(r3)
+
+	li	r4, 0
+	addi	r6, r3, SS_SR-4
+1:	mfsrin	r5, r4
+	stwu	r5, 4(r6)
+	addis	r4, r4, 0x1000
+	cmpwi	r4, 0
+	bne	1b
+
+	/* Disable machine checks and critical exceptions */
+	mfmsr	r4
+	rlwinm	r4, r4, 0, ~MSR_CE
+	rlwinm	r4, r4, 0, ~MSR_ME
+	mtmsr	r4
+	isync
+
+#define TMP_VIRT_IMMR		0xf0000000
+#define DEFAULT_IMMR_VALUE	0xff400000
+#define IMMRBAR_BASE		0x0000
+
+	lis	r4, immrbase@ha
+	lwz	r4, immrbase@l(r4)
+
+	/* Use DBAT0 to address the current IMMR space */
+
+	ori	r4, r4, 0x002a
+	mtspr	SPRN_DBAT0L, r4
+	lis	r8, TMP_VIRT_IMMR@h
+	ori	r4, r8, 0x001e	/* 1 MByte accessable from Kernel Space only */
+	mtspr	SPRN_DBAT0U, r4
+	isync
+
+	/* Use DBAT1 to address the original IMMR space */
+
+	lis	r4, DEFAULT_IMMR_VALUE@h
+	ori	r4, r4, 0x002a
+	mtspr	SPRN_DBAT1L, r4
+	lis	r9, (TMP_VIRT_IMMR + 0x01000000)@h
+	ori	r4, r9, 0x001e	/* 1 MByte accessable from Kernel Space only */
+	mtspr	SPRN_DBAT1U, r4
+	isync
+
+	/* Use DBAT2 to address the beginning of RAM.  This isn't done
+	 * using the normal virtual mapping, because with page debugging
+	 * enabled it will be read-only.
+	 */
+
+	li	r4, 0x0002
+	mtspr	SPRN_DBAT2L, r4
+	lis	r4, KERNELBASE@h
+	ori	r4, r4, 0x001e	/* 1 MByte accessable from Kernel Space only */
+	mtspr	SPRN_DBAT2U, r4
+	isync
+
+	/* Flush the cache with our BAT, as there will be TLB misses
+	 * otherwise if page debugging is enabled, and these misses
+	 * will disturb the PLRU algorithm.
+	 */
+
+	bl	__flush_disable_L1
+
+	/* Keep the i-cache enabled, so the hack below for low-boot
+	 * flash will work.
+	 */
+	mfspr	r3, SPRN_HID0
+	ori	r3, r3, HID0_ICE
+	mtspr	SPRN_HID0, r3
+	isync
+
+	lis	r6, 0xf515
+	ori	r6, r6, 0x3ae5
+
+	lis	r7, mpc83xx_deep_resume@h
+	ori	r7, r7, mpc83xx_deep_resume@l
+	tophys(r7, r7)
+
+	lis	r5, KERNELBASE@h
+	stw	r6, 0(r5)
+	stw	r7, 4(r5)
+
+	/* Reset BARs */
+
+	li	r4, 0
+	stw	r4, 0x0024(r8)
+	stw	r4, 0x002c(r8)
+	stw	r4, 0x0034(r8)
+	stw	r4, 0x003c(r8)
+	stw	r4, 0x0064(r8)
+	stw	r4, 0x006c(r8)
+
+	/* Rev 1 of the 8313 has problems with wakeup events that are
+	 * pending during the transition to deep sleep state (such as if
+	 * the PCI host sets the state to D3 and then D0 in rapid
+	 * succession).  This check shrinks the race window somewhat.
+	 *
+	 * See erratum PCI23, though the problem is not limited
+	 * to PCI.
+	 */
+
+	lwz	r3, 0x0b04(r8)
+	andi.	r3, r3, 1
+	bne-	mpc83xx_deep_resume
+
+	/* Move IMMR back to the default location, following the
+	 * procedure specified in the MPC8313 manual.
+	 */
+	lwz	r4, IMMRBAR_BASE(r8)
+	isync
+	lis	r4, DEFAULT_IMMR_VALUE@h
+	stw	r4, IMMRBAR_BASE(r8)
+	lis	r4, KERNELBASE@h
+	lwz	r4, 0(r4)
+	isync
+	lwz	r4, IMMRBAR_BASE(r9)
+	mr	r8, r9
+	isync
+
+	/* Check the Reset Configuration Word to see whether flash needs
+	 * to be mapped at a low address or a high address.
+	 */
+
+	lwz	r4, 0x0904(r8)
+	andis.	r4, r4, 0x0400
+	li	r4, 0
+	beq	boot_low
+	lis	r4, 0xff80
+boot_low:
+	stw	r4, 0x0020(r8)
+	lis	r7, 0x8000
+	ori	r7, r7, 0x0016
+
+	mfspr	r5, SPRN_HID0
+	rlwinm	r5, r5, 0, ~(HID0_DOZE | HID0_NAP)
+	oris	r5, r5, HID0_SLEEP@h
+	mtspr	SPRN_HID0, r5
+	isync
+
+	mfmsr	r5
+	oris	r5, r5, MSR_POW@h
+
+	/* Enable the flash mapping at the appropriate address.  This
+	 * mapping will override the RAM mapping if booting low, so there's
+	 * no need to disable the latter.  This must be done inside the same
+	 * cache line as setting MSR_POW, so that no instruction fetches
+	 * from RAM happen after the flash mapping is turned on.
+	 */
+
+	.align	5
+	stw	r7, 0x0024(r8)
+	sync
+	isync
+	mtmsr	r5
+	isync
+1:	b	1b
+
+mpc83xx_deep_resume:
+	lis	r4, 1f@h
+	ori	r4, r4, 1f@l
+	tophys(r4, r4)
+	mtsrr0	r4
+
+	mfmsr	r4
+	rlwinm	r4, r4, 0, ~(MSR_IR | MSR_DR)
+	mtsrr1	r4
+
+	rfi
+
+1:	tlbia
+	bl	__inval_enable_L1
+
+	lis	r3, mpc83xx_sleep_save_area@h
+	ori	r3, r3, mpc83xx_sleep_save_area@l
+	tophys(r3, r3)
+
+	lwz	r5, SS_MEMSAVE+0(r3)
+	lwz	r6, SS_MEMSAVE+4(r3)
+
+	stw	r5, 0(0)
+	stw	r6, 4(0)
+
+	lwz	r5, SS_HID+0(r3)
+	lwz	r6, SS_HID+4(r3)
+	lwz	r7, SS_HID+8(r3)
+
+	mtspr	SPRN_HID0, r5
+	mtspr	SPRN_HID1, r6
+	mtspr	SPRN_HID2, r7
+
+	lwz	r4, SS_IABR+0(r3)
+	lwz	r5, SS_IABR+4(r3)
+	lwz	r6, SS_IBCR(r3)
+	lwz	r7, SS_DABR+0(r3)
+	lwz	r8, SS_DABR+4(r3)
+	lwz	r9, SS_DBCR(r3)
+
+	mtspr	SPRN_IABR, r4
+	mtspr	SPRN_IABR2, r5
+	mtspr	SPRN_IBCR, r6
+	mtspr	SPRN_DABR, r7
+	mtspr	SPRN_DABR2, r8
+	mtspr	SPRN_DBCR, r9
+
+	li	r4, 0
+	addi	r6, r3, SS_SR-4
+1:	lwzu	r5, 4(r6)
+	mtsrin	r5, r4
+	addis	r4, r4, 0x1000
+	cmpwi	r4, 0
+	bne	1b
+
+	lwz	r4, SS_DBAT+0x00(r3)
+	lwz	r5, SS_DBAT+0x04(r3)
+	lwz	r6, SS_DBAT+0x08(r3)
+	lwz	r7, SS_DBAT+0x0c(r3)
+
+	mtspr	SPRN_DBAT0U, r4
+	mtspr	SPRN_DBAT0L, r5
+	mtspr	SPRN_DBAT1U, r6
+	mtspr	SPRN_DBAT1L, r7
+
+	lwz	r4, SS_DBAT+0x10(r3)
+	lwz	r5, SS_DBAT+0x14(r3)
+	lwz	r6, SS_DBAT+0x18(r3)
+	lwz	r7, SS_DBAT+0x1c(r3)
+
+	mtspr	SPRN_DBAT2U, r4
+	mtspr	SPRN_DBAT2L, r5
+	mtspr	SPRN_DBAT3U, r6
+	mtspr	SPRN_DBAT3L, r7
+
+	lwz	r4, SS_DBAT+0x20(r3)
+	lwz	r5, SS_DBAT+0x24(r3)
+	lwz	r6, SS_DBAT+0x28(r3)
+	lwz	r7, SS_DBAT+0x2c(r3)
+
+	mtspr	SPRN_DBAT4U, r4
+	mtspr	SPRN_DBAT4L, r5
+	mtspr	SPRN_DBAT5U, r6
+	mtspr	SPRN_DBAT5L, r7
+
+	lwz	r4, SS_DBAT+0x30(r3)
+	lwz	r5, SS_DBAT+0x34(r3)
+	lwz	r6, SS_DBAT+0x38(r3)
+	lwz	r7, SS_DBAT+0x3c(r3)
+
+	mtspr	SPRN_DBAT6U, r4
+	mtspr	SPRN_DBAT6L, r5
+	mtspr	SPRN_DBAT7U, r6
+	mtspr	SPRN_DBAT7L, r7
+
+	lwz	r4, SS_IBAT+0x00(r3)
+	lwz	r5, SS_IBAT+0x04(r3)
+	lwz	r6, SS_IBAT+0x08(r3)
+	lwz	r7, SS_IBAT+0x0c(r3)
+
+	mtspr	SPRN_IBAT0U, r4
+	mtspr	SPRN_IBAT0L, r5
+	mtspr	SPRN_IBAT1U, r6
+	mtspr	SPRN_IBAT1L, r7
+
+	lwz	r4, SS_IBAT+0x10(r3)
+	lwz	r5, SS_IBAT+0x14(r3)
+	lwz	r6, SS_IBAT+0x18(r3)
+	lwz	r7, SS_IBAT+0x1c(r3)
+
+	mtspr	SPRN_IBAT2U, r4
+	mtspr	SPRN_IBAT2L, r5
+	mtspr	SPRN_IBAT3U, r6
+	mtspr	SPRN_IBAT3L, r7
+
+	lwz	r4, SS_IBAT+0x20(r3)
+	lwz	r5, SS_IBAT+0x24(r3)
+	lwz	r6, SS_IBAT+0x28(r3)
+	lwz	r7, SS_IBAT+0x2c(r3)
+
+	mtspr	SPRN_IBAT4U, r4
+	mtspr	SPRN_IBAT4L, r5
+	mtspr	SPRN_IBAT5U, r6
+	mtspr	SPRN_IBAT5L, r7
+
+	lwz	r4, SS_IBAT+0x30(r3)
+	lwz	r5, SS_IBAT+0x34(r3)
+	lwz	r6, SS_IBAT+0x38(r3)
+	lwz	r7, SS_IBAT+0x3c(r3)
+
+	mtspr	SPRN_IBAT6U, r4
+	mtspr	SPRN_IBAT6L, r5
+	mtspr	SPRN_IBAT7U, r6
+	mtspr	SPRN_IBAT7L, r7
+
+	lwz	r4, SS_SPRG+0(r3)
+	lwz	r5, SS_SPRG+4(r3)
+	lwz	r6, SS_SPRG+8(r3)
+	lwz	r7, SS_SPRG+12(r3)
+	lwz	r8, SS_SDR1(r3)
+
+	mtspr	SPRN_SPRG0, r4
+	mtspr	SPRN_SPRG1, r5
+	mtspr	SPRN_SPRG2, r6
+	mtspr	SPRN_SPRG3, r7
+	mtsdr1	r8
+
+	lwz	r4, SS_MSR(r3)
+	lwz	r5, SS_LR(r3)
+	lwz	r6, SS_CR(r3)
+	lwz	r1, SS_SP(r3)
+	lwz	r2, SS_R2(r3)
+
+	mtsrr1	r4
+	mtsrr0	r5
+	mtcr	r6
+
+	li	r4, 0
+	mtspr	SPRN_TBWL, r4
+
+	lwz	r4, SS_TB+0(r3)
+	lwz	r5, SS_TB+4(r3)
+
+	mtspr	SPRN_TBWU, r4
+	mtspr	SPRN_TBWL, r5
+
+	lmw	r12, SS_GPREG(r3)
+
+	/* Kick decrementer */
+	li	r0, 1
+	mtdec	r0
+
+	rfi
diff --git a/arch/powerpc/platforms/83xx/suspend.c b/arch/powerpc/platforms/83xx/suspend.c
new file mode 100644
index 0000000..08e65fc
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/suspend.c
@@ -0,0 +1,388 @@
+/*
+ * MPC83xx suspend support
+ *
+ * Author: Scott Wood <scottwood@freescale.com>
+ *
+ * Copyright (c) 2006-2007 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/suspend.h>
+#include <linux/fsl_devices.h>
+#include <linux/of_platform.h>
+
+#include <asm/reg.h>
+#include <asm/io.h>
+#include <asm/time.h>
+#include <asm/mpc6xx.h>
+
+#include <sysdev/fsl_soc.h>
+
+#define PMCCR1_NEXT_STATE       0x0C /* Next state for power management */
+#define PMCCR1_NEXT_STATE_SHIFT 2
+#define PMCCR1_CURR_STATE       0x03 /* Current state for power management*/
+#define IMMR_RCW_OFFSET         0x900
+#define RCW_PCI_HOST            0x80000000
+
+void mpc83xx_enter_deep_sleep(phys_addr_t immrbase);
+
+struct mpc83xx_pmc {
+	u32 config;
+#define PMCCR_DLPEN 2 /* DDR SDRAM low power enable */
+#define PMCCR_SLPEN 1 /* System low power enable */
+
+	u32 event;
+	u32 mask;
+/* All but PMCI are deep-sleep only */
+#define PMCER_GPIO   0x100
+#define PMCER_PCI    0x080
+#define PMCER_USB    0x040
+#define PMCER_ETSEC1 0x020
+#define PMCER_ETSEC2 0x010
+#define PMCER_TIMER  0x008
+#define PMCER_INT1   0x004
+#define PMCER_INT2   0x002
+#define PMCER_PMCI   0x001
+#define PMCER_ALL    0x1FF
+
+	/* deep-sleep only */
+	u32 config1;
+#define PMCCR1_USE_STATE  0x80000000
+#define PMCCR1_PME_EN     0x00000080
+#define PMCCR1_ASSERT_PME 0x00000040
+#define PMCCR1_POWER_OFF  0x00000020
+
+	/* deep-sleep only */
+	u32 config2;
+};
+
+struct mpc83xx_rcw {
+	u32 rcwlr;
+	u32 rcwhr;
+};
+
+struct mpc83xx_clock {
+	u32 spmr;
+	u32 occr;
+	u32 sccr;
+};
+
+struct pmc_type {
+	int has_deep_sleep;
+};
+
+static struct of_device *pmc_dev;
+static int has_deep_sleep, deep_sleeping;
+static int pmc_irq;
+static struct mpc83xx_pmc __iomem *pmc_regs;
+static struct mpc83xx_clock __iomem *clock_regs;
+static int is_pci_agent, wake_from_pci;
+static phys_addr_t immrbase;
+static int pci_pm_state;
+static DECLARE_WAIT_QUEUE_HEAD(agent_wq);
+
+int fsl_deep_sleep(void)
+{
+	return deep_sleeping;
+}
+
+static int mpc83xx_change_state(void)
+{
+	u32 curr_state;
+	u32 reg_cfg1 = in_be32(&pmc_regs->config1);
+
+	if (is_pci_agent) {
+		pci_pm_state = (reg_cfg1 & PMCCR1_NEXT_STATE) >>
+		               PMCCR1_NEXT_STATE_SHIFT;
+		curr_state = reg_cfg1 & PMCCR1_CURR_STATE;
+
+		if (curr_state != pci_pm_state) {
+			reg_cfg1 &= ~PMCCR1_CURR_STATE;
+			reg_cfg1 |= pci_pm_state;
+			out_be32(&pmc_regs->config1, reg_cfg1);
+
+			wake_up(&agent_wq);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+static irqreturn_t pmc_irq_handler(int irq, void *dev_id)
+{
+	u32 event = in_be32(&pmc_regs->event);
+	int ret = IRQ_NONE;
+
+	if (mpc83xx_change_state())
+		ret = IRQ_HANDLED;
+
+	if (event) {
+		out_be32(&pmc_regs->event, event);
+		ret = IRQ_HANDLED;
+	}
+
+	return ret;
+}
+
+static int mpc83xx_suspend_enter(suspend_state_t state)
+{
+	int ret = -EAGAIN;
+
+	/* Don't go to sleep if there's a race where pci_pm_state changes
+	 * between the agent thread checking it and the PM code disabling
+	 * interrupts.
+	 */
+	if (wake_from_pci) {
+		if (pci_pm_state != (deep_sleeping ? 3 : 2))
+			goto out;
+
+		out_be32(&pmc_regs->config1,
+		         in_be32(&pmc_regs->config1) | PMCCR1_PME_EN);
+	}
+
+	/* Put the system into low-power mode and the RAM
+	 * into self-refresh mode once the core goes to
+	 * sleep.
+	 */
+
+	out_be32(&pmc_regs->config, PMCCR_SLPEN | PMCCR_DLPEN);
+
+	/* If it has deep sleep (i.e. it's an 831x or compatible),
+	 * disable power to the core upon entering sleep mode.  This will
+	 * require going through the boot firmware upon a wakeup event.
+	 */
+
+	if (deep_sleeping) {
+		out_be32(&pmc_regs->mask, PMCER_ALL);
+
+		out_be32(&pmc_regs->config1,
+		         in_be32(&pmc_regs->config1) | PMCCR1_POWER_OFF);
+
+		enable_kernel_fp();
+
+		mpc83xx_enter_deep_sleep(immrbase);
+
+		out_be32(&pmc_regs->config1,
+		         in_be32(&pmc_regs->config1) & ~PMCCR1_POWER_OFF);
+
+		out_be32(&pmc_regs->mask, PMCER_PMCI);
+	} else {
+		out_be32(&pmc_regs->mask, PMCER_PMCI);
+
+		mpc6xx_enter_standby();
+	}
+
+	ret = 0;
+
+out:
+	out_be32(&pmc_regs->config1,
+	         in_be32(&pmc_regs->config1) & ~PMCCR1_PME_EN);
+
+	return ret;
+}
+
+static void mpc83xx_suspend_finish(void)
+{
+	deep_sleeping = 0;
+}
+
+static int mpc83xx_suspend_valid(suspend_state_t state)
+{
+	return state == PM_SUSPEND_STANDBY || state == PM_SUSPEND_MEM;
+}
+
+static int mpc83xx_suspend_begin(suspend_state_t state)
+{
+	switch (state) {
+		case PM_SUSPEND_STANDBY:
+			deep_sleeping = 0;
+			return 0;
+
+		case PM_SUSPEND_MEM:
+			if (has_deep_sleep)
+				deep_sleeping = 1;
+
+			return 0;
+
+		default:
+			return -EINVAL;
+	}
+}
+
+static int agent_thread_fn(void *data)
+{
+	while (1) {
+		wait_event_interruptible(agent_wq, pci_pm_state >= 2);
+		try_to_freeze();
+
+		if (signal_pending(current) || pci_pm_state < 2)
+			continue;
+
+		/* With a preemptible kernel (or SMP), this could race with
+		 * a userspace-driven suspend request.  It's probably best
+		 * to avoid mixing the two with such a configuration (or
+		 * else fix it by adding a mutex to state_store that we can
+		 * synchronize with).
+		 */
+
+		wake_from_pci = 1;
+
+		pm_suspend(pci_pm_state == 3 ? PM_SUSPEND_MEM :
+		                               PM_SUSPEND_STANDBY);
+
+		wake_from_pci = 0;
+	}
+
+	return 0;
+}
+
+static void mpc83xx_set_agent(void)
+{
+	out_be32(&pmc_regs->config1, PMCCR1_USE_STATE);
+	out_be32(&pmc_regs->mask, PMCER_PMCI);
+
+	kthread_run(agent_thread_fn, NULL, "PCI power mgt");
+}
+
+static int mpc83xx_is_pci_agent(void)
+{
+	struct mpc83xx_rcw __iomem *rcw_regs;
+	int ret;
+
+	rcw_regs = ioremap(get_immrbase() + IMMR_RCW_OFFSET,
+	                   sizeof(struct mpc83xx_rcw));
+
+	if (!rcw_regs)
+		return -ENOMEM;
+
+	ret = !(in_be32(&rcw_regs->rcwhr) & RCW_PCI_HOST);
+
+	iounmap(rcw_regs);
+	return ret;
+}
+
+static struct platform_suspend_ops mpc83xx_suspend_ops = {
+	.valid = mpc83xx_suspend_valid,
+	.begin = mpc83xx_suspend_begin,
+	.enter = mpc83xx_suspend_enter,
+	.finish = mpc83xx_suspend_finish,
+};
+
+static int pmc_probe(struct of_device *ofdev,
+                     const struct of_device_id *match)
+{
+	struct device_node *np = ofdev->node;
+	struct resource res;
+	struct pmc_type *type = match->data;
+	int ret = 0;
+
+	if (!of_device_is_available(np))
+		return -ENODEV;
+
+	has_deep_sleep = type->has_deep_sleep;
+	immrbase = get_immrbase();
+	pmc_dev = ofdev;
+
+	is_pci_agent = mpc83xx_is_pci_agent();
+	if (is_pci_agent < 0)
+		return is_pci_agent;
+
+	ret = of_address_to_resource(np, 0, &res);
+	if (ret)
+		return -ENODEV;
+
+	pmc_irq = irq_of_parse_and_map(np, 0);
+	if (pmc_irq != NO_IRQ) {
+		ret = request_irq(pmc_irq, pmc_irq_handler, IRQF_SHARED,
+		                  "pmc", ofdev);
+
+		if (ret)
+			return -EBUSY;
+	}
+
+	pmc_regs = ioremap(res.start, sizeof(struct mpc83xx_pmc));
+
+	if (!pmc_regs) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = of_address_to_resource(np, 1, &res);
+	if (ret) {
+		ret = -ENODEV;
+		goto out_pmc;
+	}
+
+	clock_regs = ioremap(res.start, sizeof(struct mpc83xx_pmc));
+
+	if (!clock_regs) {
+		ret = -ENOMEM;
+		goto out_pmc;
+	}
+
+	if (is_pci_agent)
+		mpc83xx_set_agent();
+
+	suspend_set_ops(&mpc83xx_suspend_ops);
+	return 0;
+
+out_pmc:
+	iounmap(pmc_regs);
+out:
+	if (pmc_irq != NO_IRQ)
+		free_irq(pmc_irq, ofdev);
+
+	return ret;
+}
+
+static int pmc_remove(struct of_device *ofdev)
+{
+	return -EPERM;
+};
+
+static struct pmc_type pmc_types[] = {
+	{
+		.has_deep_sleep = 1,
+	},
+	{
+		.has_deep_sleep = 0,
+	}
+};
+
+static struct of_device_id pmc_match[] = {
+	{
+		.compatible = "fsl,mpc8313-pmc",
+		.data = &pmc_types[0],
+	},
+	{
+		.compatible = "fsl,mpc8349-pmc",
+		.data = &pmc_types[1],
+	},
+	{}
+};
+
+static struct of_platform_driver pmc_driver = {
+	.name = "mpc83xx-pmc",
+	.match_table = pmc_match,
+	.probe = pmc_probe,
+	.remove = pmc_remove
+};
+
+static int pmc_init(void)
+{
+	return of_register_platform_driver(&pmc_driver);
+}
+
+module_init(pmc_init);
diff --git a/arch/powerpc/platforms/83xx/usb.c b/arch/powerpc/platforms/83xx/usb.c
index 64bcf0a..cc99c28 100644
--- a/arch/powerpc/platforms/83xx/usb.c
+++ b/arch/powerpc/platforms/83xx/usb.c
@@ -137,15 +137,21 @@
 
 	/* Configure pin mux for ULPI.  There is no pin mux for UTMI */
 	if (prop && !strcmp(prop, "ulpi")) {
-		temp = in_be32(immap + MPC83XX_SICRL_OFFS);
-		temp &= ~MPC831X_SICRL_USB_MASK;
-		temp |= MPC831X_SICRL_USB_ULPI;
-		out_be32(immap + MPC83XX_SICRL_OFFS, temp);
-
-		temp = in_be32(immap + MPC83XX_SICRH_OFFS);
-		temp &= ~MPC831X_SICRH_USB_MASK;
-		temp |= MPC831X_SICRH_USB_ULPI;
-		out_be32(immap + MPC83XX_SICRH_OFFS, temp);
+		if (of_device_is_compatible(immr_node, "fsl,mpc8315-immr")) {
+			clrsetbits_be32(immap + MPC83XX_SICRL_OFFS,
+					MPC8315_SICRL_USB_MASK,
+					MPC8315_SICRL_USB_ULPI);
+			clrsetbits_be32(immap + MPC83XX_SICRH_OFFS,
+					MPC8315_SICRH_USB_MASK,
+					MPC8315_SICRH_USB_ULPI);
+		} else {
+			clrsetbits_be32(immap + MPC83XX_SICRL_OFFS,
+					MPC831X_SICRL_USB_MASK,
+					MPC831X_SICRL_USB_ULPI);
+			clrsetbits_be32(immap + MPC83XX_SICRH_OFFS,
+					MPC831X_SICRH_USB_MASK,
+					MPC831X_SICRH_USB_ULPI);
+		}
 	}
 
 	iounmap(immap);
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index cebea5c..291675b 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -2,8 +2,8 @@
 	bool "Machine Type"
 	depends on PPC_85xx
 	select PPC_UDBG_16550
-	select PPC_INDIRECT_PCI if PCI
 	select MPIC
+	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select SERIAL_8250_SHARE_IRQ if SERIAL_8250
 	default y
@@ -86,7 +86,6 @@
 	help
 	  This option enables support for the TQ Components TQM8548 board.
 	select DEFAULT_UIMAGE
-	select PPC_CPM_NEW_BINDING
 	select TQM85xx
 
 config TQM8555
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
index 25f41cd2..00c5358 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
@@ -115,7 +115,6 @@
 
 #ifdef CONFIG_PCI
 static int primary_phb_addr;
-extern int uses_fsl_uli_m1575;
 extern int uli_exclude_device(struct pci_controller *hose,
 				u_char bus, u_char devfn);
 
@@ -161,7 +160,6 @@
 		}
 	}
 
-	uses_fsl_uli_m1575 = 1;
 	ppc_md.pci_exclude_device = mpc85xx_exclude_device;
 #endif
 
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig
index 80a81e0..9355a52 100644
--- a/arch/powerpc/platforms/86xx/Kconfig
+++ b/arch/powerpc/platforms/86xx/Kconfig
@@ -27,6 +27,7 @@
 config MPC8610_HPCD
 	bool "Freescale MPC8610 HPCD"
 	select DEFAULT_UIMAGE
+	select FSL_ULI1575
 	help
 	  This option enables support for the MPC8610 HPCD board.
 
@@ -34,6 +35,7 @@
 
 config MPC8641
 	bool
+	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select PPC_UDBG_16550
 	select MPIC
@@ -41,6 +43,7 @@
 
 config MPC8610
 	bool
+	select PPC_PCI_CHOICE
 	select FSL_PCI if PCI
 	select PPC_UDBG_16550
 	select MPIC
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
index 3072530..5eedb71 100644
--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -58,93 +58,6 @@
 }
 machine_device_initcall(mpc86xx_hpcd, mpc8610_declare_of_platform_devices);
 
-#ifdef CONFIG_PCI
-static void __devinit quirk_uli1575(struct pci_dev *dev)
-{
-	u32 temp32;
-
-	/* Disable INTx */
-	pci_read_config_dword(dev, 0x48, &temp32);
-	pci_write_config_dword(dev, 0x48, (temp32 | 1<<26));
-
-	/* Enable sideband interrupt */
-	pci_read_config_dword(dev, 0x90, &temp32);
-	pci_write_config_dword(dev, 0x90, (temp32 | 1<<22));
-}
-
-static void __devinit quirk_uli5288(struct pci_dev *dev)
-{
-	unsigned char c;
-	unsigned short temp;
-
-	/* Interrupt Disable, Needed when SATA disabled */
-	pci_read_config_word(dev, PCI_COMMAND, &temp);
-	temp |= 1<<10;
-	pci_write_config_word(dev, PCI_COMMAND, temp);
-
-	pci_read_config_byte(dev, 0x83, &c);
-	c |= 0x80;
-	pci_write_config_byte(dev, 0x83, c);
-
-	pci_write_config_byte(dev, PCI_CLASS_PROG, 0x01);
-	pci_write_config_byte(dev, PCI_CLASS_DEVICE, 0x06);
-
-	pci_read_config_byte(dev, 0x83, &c);
-	c &= 0x7f;
-	pci_write_config_byte(dev, 0x83, c);
-}
-
-/*
- * Since 8259PIC was disabled on the board, the IDE device can not
- * use the legacy IRQ, we need to let the IDE device work under
- * native mode and use the interrupt line like other PCI devices.
- * IRQ14 is a sideband interrupt from IDE device to CPU and we use this
- * as the interrupt for IDE device.
- */
-static void __devinit quirk_uli5229(struct pci_dev *dev)
-{
-	unsigned char c;
-
-	pci_read_config_byte(dev, 0x4b, &c);
-	c |= 0x10;
-	pci_write_config_byte(dev, 0x4b, c);
-}
-
-/*
- * SATA interrupt pin bug fix
- * There's a chip bug for 5288, The interrupt pin should be 2,
- * not the read only value 1, So it use INTB#, not INTA# which
- * actually used by the IDE device 5229.
- * As of this bug, during the PCI initialization, 5288 read the
- * irq of IDE device from the device tree, this function fix this
- * bug by re-assigning a correct irq to 5288.
- *
- */
-static void __devinit final_uli5288(struct pci_dev *dev)
-{
-	struct pci_controller *hose = pci_bus_to_host(dev->bus);
-	struct device_node *hosenode = hose ? hose->dn : NULL;
-	struct of_irq oirq;
-	int virq, pin = 2;
-	u32 laddr[3];
-
-	if (!hosenode)
-		return;
-
-	laddr[0] = (hose->first_busno << 16) | (PCI_DEVFN(31, 0) << 8);
-	laddr[1] = laddr[2] = 0;
-	of_irq_map_raw(hosenode, &pin, 1, laddr, &oirq);
-	virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
-				     oirq.size);
-	dev->irq = virq;
-}
-
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, quirk_uli1575);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, quirk_uli5288);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 0x5288, final_uli5288);
-#endif /* CONFIG_PCI */
-
 #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
 
 static u32 get_busfreq(void)
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index 7916599..f712d9c 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -45,7 +45,6 @@
 #endif
 
 #ifdef CONFIG_PCI
-extern int uses_fsl_uli_m1575;
 extern int uli_exclude_device(struct pci_controller *hose,
 				u_char bus, u_char devfn);
 
@@ -87,7 +86,6 @@
 			fsl_add_bridge(np, 0);
 	}
 
-	uses_fsl_uli_m1575 = 1;
 	ppc_md.pci_exclude_device = mpc86xx_exclude_device;
 
 #endif
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index 690c1f4..1d09687 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -253,17 +253,13 @@
 	depends on MPC85xx || 8260
 	select CPM
 	select PPC_LIB_RHEAP
+	select PPC_PCI_CHOICE
 	help
 	  The CPM2 (Communications Processor Module) is a coprocessor on
 	  embedded CPUs made by Freescale.  Selecting this option means that
 	  you wish to build a kernel for a machine with a CPM2 coprocessor
 	  on it (826x, 827x, 8560).
 
-config PPC_CPM_NEW_BINDING
-	bool
-	depends on CPM1 || CPM2
-	default y
-
 config AXON_RAM
 	tristate "Axon DDR2 memory device driver"
 	depends on PPC_IBM_CELL_BLADE
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 5bc4b611..7f65127 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -42,12 +42,14 @@
 	select PPC_DCR_NATIVE
 	select PPC_UDBG_16550
 	select 4xx_SOC
+	select PPC_PCI_CHOICE
 
 config 44x
 	bool "AMCC 44x"
 	select PPC_DCR_NATIVE
 	select PPC_UDBG_16550
 	select 4xx_SOC
+	select PPC_PCI_CHOICE
 
 config E200
 	bool "Freescale e200"
@@ -84,9 +86,6 @@
 	  machines. When building a kernel that is supposed to run only
 	  on Cell, you should also select the POWER4_ONLY option.
 
-config 6xx
-	bool
-
 # this is temp to handle compat with arch=ppc
 config 8xx
 	bool
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index 3959fcf..c14d7d8 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -83,6 +83,22 @@
 	depends on PPC_CELL_NATIVE
 	default y
 
+config PPC_IBM_CELL_RESETBUTTON
+	bool "IBM Cell Blade Pinhole reset button"
+	depends on CBE_RAS && PPC_IBM_CELL_BLADE
+	default y
+	help
+	  Support Pinhole Resetbutton on IBM Cell blades.
+	  This adds a method to trigger system reset via front panel pinhole button.
+
+config PPC_IBM_CELL_POWERBUTTON
+	tristate "IBM Cell Blade power button"
+	depends on PPC_IBM_CELL_BLADE && PPC_PMI && INPUT_EVDEV
+	default y
+	help
+	  Support Powerbutton on IBM Cell blades.
+	  This will enable the powerbutton as an input device.
+
 config CBE_THERM
 	tristate "CBE thermal support"
 	default m
@@ -107,6 +123,15 @@
 	  processor will not only be able to run at lower speed,
 	  but also at lower core voltage.
 
+config CBE_CPUFREQ_SPU_GOVERNOR
+	tristate "CBE frequency scaling based on SPU usage"
+	depends on SPU_FS && CPU_FREQ
+	default m
+	help
+	  This governor checks for spu usage to adjust the cpu frequency.
+	  If no spu is running on a given cpu, that cpu will be throttled to
+	  the minimal possible frequency.
+
 endmenu
 
 config OPROFILE_CELL
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
index c2a7e4e..7fd8308 100644
--- a/arch/powerpc/platforms/cell/Makefile
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -8,6 +8,9 @@
 obj-$(CONFIG_CBE_CPUFREQ_PMI)		+= cbe_cpufreq_pmi.o
 obj-$(CONFIG_CBE_CPUFREQ)		+= cbe-cpufreq.o
 cbe-cpufreq-y				+= cbe_cpufreq_pervasive.o cbe_cpufreq.o
+obj-$(CONFIG_CBE_CPUFREQ_SPU_GOVERNOR)	+= cpufreq_spudemand.o
+
+obj-$(CONFIG_PPC_IBM_CELL_POWERBUTTON)	+= cbe_powerbutton.o
 
 ifeq ($(CONFIG_SMP),y)
 obj-$(CONFIG_PPC_CELL_NATIVE)		+= smp.o
diff --git a/arch/powerpc/platforms/cell/cbe_powerbutton.c b/arch/powerpc/platforms/cell/cbe_powerbutton.c
new file mode 100644
index 0000000..dcddaa5
--- /dev/null
+++ b/arch/powerpc/platforms/cell/cbe_powerbutton.c
@@ -0,0 +1,117 @@
+/*
+ * driver for powerbutton on IBM cell blades
+ *
+ * (C) Copyright IBM Corp. 2005-2008
+ *
+ * Author: Christian Krafft <krafft@de.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <asm/pmi.h>
+#include <asm/prom.h>
+
+static struct input_dev *button_dev;
+static struct platform_device *button_pdev;
+
+static void cbe_powerbutton_handle_pmi(pmi_message_t pmi_msg)
+{
+	BUG_ON(pmi_msg.type != PMI_TYPE_POWER_BUTTON);
+
+	input_report_key(button_dev, KEY_POWER, 1);
+	input_sync(button_dev);
+	input_report_key(button_dev, KEY_POWER, 0);
+	input_sync(button_dev);
+}
+
+static struct pmi_handler cbe_pmi_handler = {
+	.type			= PMI_TYPE_POWER_BUTTON,
+	.handle_pmi_message	= cbe_powerbutton_handle_pmi,
+};
+
+static int __init cbe_powerbutton_init(void)
+{
+	int ret = 0;
+	struct input_dev *dev;
+
+	if (!machine_is_compatible("IBM,CBPLUS-1.0")) {
+		printk(KERN_ERR "%s: Not a cell blade.\n", __func__);
+		ret = -ENODEV;
+		goto out;
+	}
+
+	dev = input_allocate_device();
+	if (!dev) {
+		ret = -ENOMEM;
+		printk(KERN_ERR "%s: Not enough memory.\n", __func__);
+		goto out;
+	}
+
+	set_bit(EV_KEY, dev->evbit);
+	set_bit(KEY_POWER, dev->keybit);
+
+	dev->name = "Power Button";
+	dev->id.bustype = BUS_HOST;
+
+	/* this makes the button look like an acpi power button
+	 * no clue whether anyone relies on that though */
+	dev->id.product = 0x02;
+	dev->phys = "LNXPWRBN/button/input0";
+
+	button_pdev = platform_device_register_simple("power_button", 0, NULL, 0);
+	if (IS_ERR(button_pdev)) {
+		ret = PTR_ERR(button_pdev);
+		goto out_free_input;
+	}
+
+	dev->dev.parent = &button_pdev->dev;
+	ret = input_register_device(dev);
+	if (ret) {
+		printk(KERN_ERR "%s: Failed to register device\n", __func__);
+		goto out_free_pdev;
+	}
+
+	button_dev = dev;
+
+	ret = pmi_register_handler(&cbe_pmi_handler);
+	if (ret) {
+		printk(KERN_ERR "%s: Failed to register with pmi.\n", __func__);
+		goto out_free_pdev;
+	}
+
+	goto out;
+
+out_free_pdev:
+	platform_device_unregister(button_pdev);
+out_free_input:
+	input_free_device(dev);
+out:
+	return ret;
+}
+
+static void __exit cbe_powerbutton_exit(void)
+{
+	pmi_unregister_handler(&cbe_pmi_handler);
+	platform_device_unregister(button_pdev);
+	input_free_device(button_dev);
+}
+
+module_init(cbe_powerbutton_init);
+module_exit(cbe_powerbutton_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>");
diff --git a/arch/powerpc/platforms/cell/cbe_thermal.c b/arch/powerpc/platforms/cell/cbe_thermal.c
index 4852bf3..4d4c8c1 100644
--- a/arch/powerpc/platforms/cell/cbe_thermal.c
+++ b/arch/powerpc/platforms/cell/cbe_thermal.c
@@ -97,7 +97,8 @@
 	return value.spe[spu->spe_id];
 }
 
-static ssize_t spu_show_temp(struct sys_device *sysdev, char *buf)
+static ssize_t spu_show_temp(struct sys_device *sysdev, struct sysdev_attribute *attr,
+			char *buf)
 {
 	u8 value;
 	struct cbe_pmd_regs __iomem *pmd_regs;
@@ -146,32 +147,38 @@
 	return size;
 }
 
-static ssize_t spu_show_throttle_end(struct sys_device *sysdev, char *buf)
+static ssize_t spu_show_throttle_end(struct sys_device *sysdev,
+			struct sysdev_attribute *attr, char *buf)
 {
 	return show_throttle(get_pmd_regs(sysdev), buf, 0);
 }
 
-static ssize_t spu_show_throttle_begin(struct sys_device *sysdev, char *buf)
+static ssize_t spu_show_throttle_begin(struct sys_device *sysdev,
+			struct sysdev_attribute *attr, char *buf)
 {
 	return show_throttle(get_pmd_regs(sysdev), buf, 8);
 }
 
-static ssize_t spu_show_throttle_full_stop(struct sys_device *sysdev, char *buf)
+static ssize_t spu_show_throttle_full_stop(struct sys_device *sysdev,
+			struct sysdev_attribute *attr, char *buf)
 {
 	return show_throttle(get_pmd_regs(sysdev), buf, 16);
 }
 
-static ssize_t spu_store_throttle_end(struct sys_device *sysdev, const char *buf, size_t size)
+static ssize_t spu_store_throttle_end(struct sys_device *sysdev,
+			struct sysdev_attribute *attr, const char *buf, size_t size)
 {
 	return store_throttle(get_pmd_regs(sysdev), buf, size, 0);
 }
 
-static ssize_t spu_store_throttle_begin(struct sys_device *sysdev, const char *buf, size_t size)
+static ssize_t spu_store_throttle_begin(struct sys_device *sysdev,
+			struct sysdev_attribute *attr, const char *buf, size_t size)
 {
 	return store_throttle(get_pmd_regs(sysdev), buf, size, 8);
 }
 
-static ssize_t spu_store_throttle_full_stop(struct sys_device *sysdev, const char *buf, size_t size)
+static ssize_t spu_store_throttle_full_stop(struct sys_device *sysdev,
+			struct sysdev_attribute *attr, const char *buf, size_t size)
 {
 	return store_throttle(get_pmd_regs(sysdev), buf, size, 16);
 }
@@ -192,43 +199,51 @@
 
 /* shows the temperature of the DTS on the PPE,
  * located near the linear thermal sensor */
-static ssize_t ppe_show_temp0(struct sys_device *sysdev, char *buf)
+static ssize_t ppe_show_temp0(struct sys_device *sysdev,
+			struct sysdev_attribute *attr, char *buf)
 {
 	return ppe_show_temp(sysdev, buf, 32);
 }
 
 /* shows the temperature of the second DTS on the PPE */
-static ssize_t ppe_show_temp1(struct sys_device *sysdev, char *buf)
+static ssize_t ppe_show_temp1(struct sys_device *sysdev,
+			struct sysdev_attribute *attr, char *buf)
 {
 	return ppe_show_temp(sysdev, buf, 0);
 }
 
-static ssize_t ppe_show_throttle_end(struct sys_device *sysdev, char *buf)
+static ssize_t ppe_show_throttle_end(struct sys_device *sysdev,
+			struct sysdev_attribute *attr, char *buf)
 {
 	return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 32);
 }
 
-static ssize_t ppe_show_throttle_begin(struct sys_device *sysdev, char *buf)
+static ssize_t ppe_show_throttle_begin(struct sys_device *sysdev,
+			struct sysdev_attribute *attr, char *buf)
 {
 	return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 40);
 }
 
-static ssize_t ppe_show_throttle_full_stop(struct sys_device *sysdev, char *buf)
+static ssize_t ppe_show_throttle_full_stop(struct sys_device *sysdev,
+			struct sysdev_attribute *attr, char *buf)
 {
 	return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 48);
 }
 
-static ssize_t ppe_store_throttle_end(struct sys_device *sysdev, const char *buf, size_t size)
+static ssize_t ppe_store_throttle_end(struct sys_device *sysdev,
+			struct sysdev_attribute *attr, const char *buf, size_t size)
 {
 	return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 32);
 }
 
-static ssize_t ppe_store_throttle_begin(struct sys_device *sysdev, const char *buf, size_t size)
+static ssize_t ppe_store_throttle_begin(struct sys_device *sysdev,
+			struct sysdev_attribute *attr, const char *buf, size_t size)
 {
 	return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 40);
 }
 
-static ssize_t ppe_store_throttle_full_stop(struct sys_device *sysdev, const char *buf, size_t size)
+static ssize_t ppe_store_throttle_full_stop(struct sys_device *sysdev,
+			struct sysdev_attribute *attr, const char *buf, size_t size)
 {
 	return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 48);
 }
diff --git a/arch/powerpc/platforms/cell/cpufreq_spudemand.c b/arch/powerpc/platforms/cell/cpufreq_spudemand.c
new file mode 100644
index 0000000..a3c6c01
--- /dev/null
+++ b/arch/powerpc/platforms/cell/cpufreq_spudemand.c
@@ -0,0 +1,184 @@
+/*
+ * spu aware cpufreq governor for the cell processor
+ *
+ * © Copyright IBM Corporation 2006-2008
+ *
+ * Author: Christian Krafft <krafft@de.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/cpufreq.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+#include <asm/atomic.h>
+#include <asm/machdep.h>
+#include <asm/spu.h>
+
+#define POLL_TIME	100000		/* in µs */
+#define EXP		753		/* exp(-1) in fixed-point */
+
+struct spu_gov_info_struct {
+	unsigned long busy_spus;	/* fixed-point */
+	struct cpufreq_policy *policy;
+	struct delayed_work work;
+	unsigned int poll_int;		/* µs */
+};
+static DEFINE_PER_CPU(struct spu_gov_info_struct, spu_gov_info);
+
+static struct workqueue_struct *kspugov_wq;
+
+static int calc_freq(struct spu_gov_info_struct *info)
+{
+	int cpu;
+	int busy_spus;
+
+	cpu = info->policy->cpu;
+	busy_spus = atomic_read(&cbe_spu_info[cpu_to_node(cpu)].busy_spus);
+
+	CALC_LOAD(info->busy_spus, EXP, busy_spus * FIXED_1);
+	pr_debug("cpu %d: busy_spus=%d, info->busy_spus=%ld\n",
+			cpu, busy_spus, info->busy_spus);
+
+	return info->policy->max * info->busy_spus / FIXED_1;
+}
+
+static void spu_gov_work(struct work_struct *work)
+{
+	struct spu_gov_info_struct *info;
+	int delay;
+	unsigned long target_freq;
+
+	info = container_of(work, struct spu_gov_info_struct, work.work);
+
+	/* after cancel_delayed_work_sync we unset info->policy */
+	BUG_ON(info->policy == NULL);
+
+	target_freq = calc_freq(info);
+	__cpufreq_driver_target(info->policy, target_freq, CPUFREQ_RELATION_H);
+
+	delay = usecs_to_jiffies(info->poll_int);
+	queue_delayed_work_on(info->policy->cpu, kspugov_wq, &info->work, delay);
+}
+
+static void spu_gov_init_work(struct spu_gov_info_struct *info)
+{
+	int delay = usecs_to_jiffies(info->poll_int);
+	INIT_DELAYED_WORK_DEFERRABLE(&info->work, spu_gov_work);
+	queue_delayed_work_on(info->policy->cpu, kspugov_wq, &info->work, delay);
+}
+
+static void spu_gov_cancel_work(struct spu_gov_info_struct *info)
+{
+	cancel_delayed_work_sync(&info->work);
+}
+
+static int spu_gov_govern(struct cpufreq_policy *policy, unsigned int event)
+{
+	unsigned int cpu = policy->cpu;
+	struct spu_gov_info_struct *info, *affected_info;
+	int i;
+	int ret = 0;
+
+	info = &per_cpu(spu_gov_info, cpu);
+
+	switch (event) {
+	case CPUFREQ_GOV_START:
+		if (!cpu_online(cpu)) {
+			printk(KERN_ERR "cpu %d is not online\n", cpu);
+			ret = -EINVAL;
+			break;
+		}
+
+		if (!policy->cur) {
+			printk(KERN_ERR "no cpu specified in policy\n");
+			ret = -EINVAL;
+			break;
+		}
+
+		/* initialize spu_gov_info for all affected cpus */
+		for_each_cpu_mask(i, policy->cpus) {
+			affected_info = &per_cpu(spu_gov_info, i);
+			affected_info->policy = policy;
+		}
+
+		info->poll_int = POLL_TIME;
+
+		/* setup timer */
+		spu_gov_init_work(info);
+
+		break;
+
+	case CPUFREQ_GOV_STOP:
+		/* cancel timer */
+		spu_gov_cancel_work(info);
+
+		/* clean spu_gov_info for all affected cpus */
+		for_each_cpu_mask (i, policy->cpus) {
+			info = &per_cpu(spu_gov_info, i);
+			info->policy = NULL;
+		}
+
+		break;
+	}
+
+	return ret;
+}
+
+static struct cpufreq_governor spu_governor = {
+	.name = "spudemand",
+	.governor = spu_gov_govern,
+	.owner = THIS_MODULE,
+};
+
+/*
+ * module init and destoy
+ */
+
+static int __init spu_gov_init(void)
+{
+	int ret;
+
+	kspugov_wq = create_workqueue("kspugov");
+	if (!kspugov_wq) {
+		printk(KERN_ERR "creation of kspugov failed\n");
+		ret = -EFAULT;
+		goto out;
+	}
+
+	ret = cpufreq_register_governor(&spu_governor);
+	if (ret) {
+		printk(KERN_ERR "registration of governor failed\n");
+		destroy_workqueue(kspugov_wq);
+		goto out;
+	}
+out:
+	return ret;
+}
+
+static void __exit spu_gov_exit(void)
+{
+	cpufreq_unregister_governor(&spu_governor);
+	destroy_workqueue(kspugov_wq);
+}
+
+
+module_init(spu_gov_init);
+module_exit(spu_gov_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>");
+
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index eeacb3a..208005c 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -173,7 +173,8 @@
 }
 
 static void tce_build_cell(struct iommu_table *tbl, long index, long npages,
-		unsigned long uaddr, enum dma_data_direction direction)
+		unsigned long uaddr, enum dma_data_direction direction,
+		struct dma_attrs *attrs)
 {
 	int i;
 	unsigned long *io_pte, base_pte;
@@ -198,6 +199,8 @@
 	base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M | IOPTE_SO_RW |
 		(window->ioid & IOPTE_IOID_Mask);
 #endif
+	if (unlikely(dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs)))
+		base_pte &= ~IOPTE_SO_RW;
 
 	io_pte = (unsigned long *)tbl->it_base + (index - tbl->it_offset);
 
@@ -519,7 +522,7 @@
 
 	__set_bit(0, window->table.it_map);
 	tce_build_cell(&window->table, window->table.it_offset, 1,
-		       (unsigned long)iommu->pad_page, DMA_TO_DEVICE);
+		       (unsigned long)iommu->pad_page, DMA_TO_DEVICE, NULL);
 	window->table.it_hint = window->table.it_blocksize;
 
 	return window;
@@ -538,7 +541,9 @@
 static unsigned long cell_dma_direct_offset;
 
 static unsigned long dma_iommu_fixed_base;
-struct dma_mapping_ops dma_iommu_fixed_ops;
+
+/* iommu_fixed_is_weak is set if booted with iommu_fixed=weak */
+static int iommu_fixed_is_weak;
 
 static struct iommu_table *cell_get_iommu_table(struct device *dev)
 {
@@ -562,6 +567,98 @@
 	return &window->table;
 }
 
+/* A coherent allocation implies strong ordering */
+
+static void *dma_fixed_alloc_coherent(struct device *dev, size_t size,
+				      dma_addr_t *dma_handle, gfp_t flag)
+{
+	if (iommu_fixed_is_weak)
+		return iommu_alloc_coherent(dev, cell_get_iommu_table(dev),
+					    size, dma_handle,
+					    device_to_mask(dev), flag,
+					    dev->archdata.numa_node);
+	else
+		return dma_direct_ops.alloc_coherent(dev, size, dma_handle,
+						     flag);
+}
+
+static void dma_fixed_free_coherent(struct device *dev, size_t size,
+				    void *vaddr, dma_addr_t dma_handle)
+{
+	if (iommu_fixed_is_weak)
+		iommu_free_coherent(cell_get_iommu_table(dev), size, vaddr,
+				    dma_handle);
+	else
+		dma_direct_ops.free_coherent(dev, size, vaddr, dma_handle);
+}
+
+static dma_addr_t dma_fixed_map_single(struct device *dev, void *ptr,
+				       size_t size,
+				       enum dma_data_direction direction,
+				       struct dma_attrs *attrs)
+{
+	if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
+		return dma_direct_ops.map_single(dev, ptr, size, direction,
+						 attrs);
+	else
+		return iommu_map_single(dev, cell_get_iommu_table(dev), ptr,
+					size, device_to_mask(dev), direction,
+					attrs);
+}
+
+static void dma_fixed_unmap_single(struct device *dev, dma_addr_t dma_addr,
+				   size_t size,
+				   enum dma_data_direction direction,
+				   struct dma_attrs *attrs)
+{
+	if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
+		dma_direct_ops.unmap_single(dev, dma_addr, size, direction,
+					    attrs);
+	else
+		iommu_unmap_single(cell_get_iommu_table(dev), dma_addr, size,
+				   direction, attrs);
+}
+
+static int dma_fixed_map_sg(struct device *dev, struct scatterlist *sg,
+			   int nents, enum dma_data_direction direction,
+			   struct dma_attrs *attrs)
+{
+	if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
+		return dma_direct_ops.map_sg(dev, sg, nents, direction, attrs);
+	else
+		return iommu_map_sg(dev, cell_get_iommu_table(dev), sg, nents,
+				    device_to_mask(dev), direction, attrs);
+}
+
+static void dma_fixed_unmap_sg(struct device *dev, struct scatterlist *sg,
+			       int nents, enum dma_data_direction direction,
+			       struct dma_attrs *attrs)
+{
+	if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
+		dma_direct_ops.unmap_sg(dev, sg, nents, direction, attrs);
+	else
+		iommu_unmap_sg(cell_get_iommu_table(dev), sg, nents, direction,
+			       attrs);
+}
+
+static int dma_fixed_dma_supported(struct device *dev, u64 mask)
+{
+	return mask == DMA_64BIT_MASK;
+}
+
+static int dma_set_mask_and_switch(struct device *dev, u64 dma_mask);
+
+struct dma_mapping_ops dma_iommu_fixed_ops = {
+	.alloc_coherent = dma_fixed_alloc_coherent,
+	.free_coherent  = dma_fixed_free_coherent,
+	.map_single     = dma_fixed_map_single,
+	.unmap_single   = dma_fixed_unmap_single,
+	.map_sg         = dma_fixed_map_sg,
+	.unmap_sg       = dma_fixed_unmap_sg,
+	.dma_supported  = dma_fixed_dma_supported,
+	.set_dma_mask   = dma_set_mask_and_switch,
+};
+
 static void cell_dma_dev_setup_fixed(struct device *dev);
 
 static void cell_dma_dev_setup(struct device *dev)
@@ -918,9 +1015,16 @@
 
 	pr_debug("iommu: mapping 0x%lx pages from 0x%lx\n", fsize, fbase);
 
-	base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M | IOPTE_SO_RW
+	base_pte = IOPTE_PP_W | IOPTE_PP_R | IOPTE_M
 		    | (cell_iommu_get_ioid(np) & IOPTE_IOID_Mask);
 
+	if (iommu_fixed_is_weak)
+		pr_info("IOMMU: Using weak ordering for fixed mapping\n");
+	else {
+		pr_info("IOMMU: Using strong ordering for fixed mapping\n");
+		base_pte |= IOPTE_SO_RW;
+	}
+
 	for (uaddr = 0; uaddr < fsize; uaddr += (1 << 24)) {
 		/* Don't touch the dynamic region */
 		ioaddr = uaddr + fbase;
@@ -1036,9 +1140,6 @@
 		cell_iommu_setup_window(iommu, np, dbase, dsize, 0);
 	}
 
-	dma_iommu_fixed_ops = dma_direct_ops;
-	dma_iommu_fixed_ops.set_dma_mask = dma_set_mask_and_switch;
-
 	dma_iommu_ops.set_dma_mask = dma_set_mask_and_switch;
 	set_pci_dma_ops(&dma_iommu_ops);
 
@@ -1052,6 +1153,9 @@
 	if (strcmp(str, "off") == 0)
 		iommu_fixed_disabled = 1;
 
+	else if (strcmp(str, "weak") == 0)
+		iommu_fixed_is_weak = 1;
+
 	return 1;
 }
 __setup("iommu_fixed=", setup_iommu_fixed);
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c
index 8a3631c..efdacc8 100644
--- a/arch/powerpc/platforms/cell/pervasive.c
+++ b/arch/powerpc/platforms/cell/pervasive.c
@@ -38,8 +38,6 @@
 
 #include "pervasive.h"
 
-static int sysreset_hack;
-
 static void cbe_power_save(void)
 {
 	unsigned long ctrl, thread_switch_control;
@@ -87,9 +85,6 @@
 
 static int cbe_system_reset_exception(struct pt_regs *regs)
 {
-	int cpu;
-	struct cbe_pmd_regs __iomem *pmd;
-
 	switch (regs->msr & SRR1_WAKEMASK) {
 	case SRR1_WAKEEE:
 		do_IRQ(regs);
@@ -98,19 +93,7 @@
 		timer_interrupt(regs);
 		break;
 	case SRR1_WAKEMT:
-		/*
-		 * The BMC can inject user triggered system reset exceptions,
-		 * but cannot set the system reset reason in srr1,
-		 * so check an extra register here.
-		 */
-		if (sysreset_hack && (cpu = smp_processor_id()) == 0) {
-			pmd = cbe_get_cpu_pmd_regs(cpu);
-			if (in_be64(&pmd->ras_esc_0) & 0xffff) {
-				out_be64(&pmd->ras_esc_0, 0);
-				return 0;
-			}
-		}
-		break;
+		return cbe_sysreset_hack();
 #ifdef CONFIG_CBE_RAS
 	case SRR1_WAKESYSERR:
 		cbe_system_error_exception(regs);
@@ -134,8 +117,6 @@
 	if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO))
 		return;
 
-	sysreset_hack = machine_is_compatible("IBM,CBPLUS-1.0");
-
 	for_each_possible_cpu(cpu) {
 		struct cbe_pmd_regs __iomem *regs = cbe_get_cpu_pmd_regs(cpu);
 		if (!regs)
@@ -144,12 +125,6 @@
 		 /* Enable Pause(0) control bit */
 		out_be64(&regs->pmcr, in_be64(&regs->pmcr) |
 					    CBE_PMD_PAUSE_ZERO_CONTROL);
-
-		/* Enable JTAG system-reset hack */
-		if (sysreset_hack)
-			out_be32(&regs->fir_mode_reg,
-				in_be32(&regs->fir_mode_reg) |
-				CBE_PMD_FIR_MODE_M8);
 	}
 
 	ppc_md.power_save = cbe_power_save;
diff --git a/arch/powerpc/platforms/cell/pervasive.h b/arch/powerpc/platforms/cell/pervasive.h
index 7b50947..fd4d7b7 100644
--- a/arch/powerpc/platforms/cell/pervasive.h
+++ b/arch/powerpc/platforms/cell/pervasive.h
@@ -30,4 +30,13 @@
 extern void cbe_maintenance_exception(struct pt_regs *regs);
 extern void cbe_thermal_exception(struct pt_regs *regs);
 
+#ifdef CONFIG_PPC_IBM_CELL_RESETBUTTON
+extern int cbe_sysreset_hack(void);
+#else
+static inline int cbe_sysreset_hack(void)
+{
+	return 1;
+}
+#endif /* CONFIG_PPC_IBM_CELL_RESETBUTTON */
+
 #endif
diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c
index 505f9b9..2a14b05 100644
--- a/arch/powerpc/platforms/cell/ras.c
+++ b/arch/powerpc/platforms/cell/ras.c
@@ -236,6 +236,52 @@
 	.notifier_call = cbe_ptcal_notify_reboot
 };
 
+#ifdef CONFIG_PPC_IBM_CELL_RESETBUTTON
+static int sysreset_hack;
+
+static int __init cbe_sysreset_init(void)
+{
+	struct cbe_pmd_regs __iomem *regs;
+
+	sysreset_hack = machine_is_compatible("IBM,CBPLUS-1.0");
+	if (!sysreset_hack)
+		return 0;
+
+	regs = cbe_get_cpu_pmd_regs(0);
+	if (!regs)
+		return 0;
+
+	/* Enable JTAG system-reset hack */
+	out_be32(&regs->fir_mode_reg,
+		in_be32(&regs->fir_mode_reg) |
+		CBE_PMD_FIR_MODE_M8);
+
+	return 0;
+}
+device_initcall(cbe_sysreset_init);
+
+int cbe_sysreset_hack(void)
+{
+	struct cbe_pmd_regs __iomem *regs;
+
+	/*
+	 * The BMC can inject user triggered system reset exceptions,
+	 * but cannot set the system reset reason in srr1,
+	 * so check an extra register here.
+	 */
+	if (sysreset_hack && (smp_processor_id() == 0)) {
+		regs = cbe_get_cpu_pmd_regs(0);
+		if (!regs)
+			return 0;
+		if (in_be64(&regs->ras_esc_0) & 0x0000ffff) {
+			out_be64(&regs->ras_esc_0, 0);
+			return 0;
+		}
+	}
+	return 1;
+}
+#endif /* CONFIG_PPC_IBM_CELL_RESETBUTTON */
+
 int __init cbe_ptcal_init(void)
 {
 	int ret;
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index 78f905b..a5bdb89 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -703,7 +703,8 @@
 }
 
 
-static ssize_t spu_stat_show(struct sys_device *sysdev, char *buf)
+static ssize_t spu_stat_show(struct sys_device *sysdev,
+				struct sysdev_attribute *attr, char *buf)
 {
 	struct spu *spu = container_of(sysdev, struct spu, sysdev);
 
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c
index 609c46d..768c262 100644
--- a/arch/powerpc/platforms/chrp/pci.c
+++ b/arch/powerpc/platforms/chrp/pci.c
@@ -367,7 +367,7 @@
 	viaisa = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, NULL);
 	if (!viaisa)
 		return;
-	printk("Fixing VIA IDE, force legacy mode on '%s'\n", viaide->dev.bus_id);
+	dev_info(&viaide->dev, "Fixing VIA IDE, force legacy mode on\n");
 
 	pci_read_config_byte(viaide, PCI_CLASS_PROG, &progif);
 	pci_write_config_byte(viaide, PCI_CLASS_PROG, progif & ~0x5);
diff --git a/arch/powerpc/platforms/fsl_uli1575.c b/arch/powerpc/platforms/fsl_uli1575.c
index afc9141..ef74a07 100644
--- a/arch/powerpc/platforms/fsl_uli1575.c
+++ b/arch/powerpc/platforms/fsl_uli1575.c
@@ -51,15 +51,13 @@
 	ULI_8259_NONE,		/* PIRQH */
 };
 
-/* set in board code if you want this quirks to do something */
-int uses_fsl_uli_m1575;
-
 /* Bridge */
 static void __devinit early_uli5249(struct pci_dev *dev)
 {
 	unsigned char temp;
 
-	if (!uses_fsl_uli_m1575)
+	if (!machine_is(mpc86xx_hpcn) && !machine_is(mpc8544_ds) &&
+			!machine_is(mpc8572_ds))
 		return;
 
 	pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_IO |
@@ -82,7 +80,8 @@
 {
 	int i;
 
-	if (!uses_fsl_uli_m1575)
+	if (!machine_is(mpc86xx_hpcn) && !machine_is(mpc8544_ds) &&
+			!machine_is(mpc8572_ds))
 		return;
 
 	/*
@@ -150,7 +149,8 @@
 	 * IRQ 14: Edge
 	 * IRQ 15: Edge
 	 */
-	if (!uses_fsl_uli_m1575)
+	if (!machine_is(mpc86xx_hpcn) && !machine_is(mpc8544_ds) &&
+			!machine_is(mpc8572_ds))
 		return;
 
 	outb(0xfa, 0x4d0);
@@ -176,7 +176,8 @@
 	unsigned char c;
 	unsigned int d;
 
-	if (!uses_fsl_uli_m1575)
+	if (!machine_is(mpc86xx_hpcn) && !machine_is(mpc8544_ds) &&
+			!machine_is(mpc8572_ds))
 		return;
 
 	/* read/write lock */
@@ -200,7 +201,8 @@
 {
 	unsigned short temp;
 
-	if (!uses_fsl_uli_m1575)
+	if (!machine_is(mpc86xx_hpcn) && !machine_is(mpc8544_ds) &&
+			!machine_is(mpc8572_ds))
 		return;
 
 	pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE |
@@ -221,7 +223,7 @@
 	for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
 		if ((bus->resource[i]) &&
 			(bus->resource[i]->flags & IORESOURCE_MEM)) {
-			dummy = ioremap(bus->resource[i]->start, 0x4);
+			dummy = ioremap(bus->resource[i]->end - 3, 0x4);
 			if (dummy) {
 				in_8(dummy);
 				iounmap(dummy);
@@ -238,6 +240,103 @@
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 0x5249, quirk_final_uli5249);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 0x1575, quirk_final_uli1575);
 
+static void __devinit hpcd_quirk_uli1575(struct pci_dev *dev)
+{
+	u32 temp32;
+
+	if (!machine_is(mpc86xx_hpcd))
+		return;
+
+	/* Disable INTx */
+	pci_read_config_dword(dev, 0x48, &temp32);
+	pci_write_config_dword(dev, 0x48, (temp32 | 1<<26));
+
+	/* Enable sideband interrupt */
+	pci_read_config_dword(dev, 0x90, &temp32);
+	pci_write_config_dword(dev, 0x90, (temp32 | 1<<22));
+}
+
+static void __devinit hpcd_quirk_uli5288(struct pci_dev *dev)
+{
+	unsigned char c;
+	unsigned short temp;
+
+	if (!machine_is(mpc86xx_hpcd))
+		return;
+
+	/* Interrupt Disable, Needed when SATA disabled */
+	pci_read_config_word(dev, PCI_COMMAND, &temp);
+	temp |= 1<<10;
+	pci_write_config_word(dev, PCI_COMMAND, temp);
+
+	pci_read_config_byte(dev, 0x83, &c);
+	c |= 0x80;
+	pci_write_config_byte(dev, 0x83, c);
+
+	pci_write_config_byte(dev, PCI_CLASS_PROG, 0x01);
+	pci_write_config_byte(dev, PCI_CLASS_DEVICE, 0x06);
+
+	pci_read_config_byte(dev, 0x83, &c);
+	c &= 0x7f;
+	pci_write_config_byte(dev, 0x83, c);
+}
+
+/*
+ * Since 8259PIC was disabled on the board, the IDE device can not
+ * use the legacy IRQ, we need to let the IDE device work under
+ * native mode and use the interrupt line like other PCI devices.
+ * IRQ14 is a sideband interrupt from IDE device to CPU and we use this
+ * as the interrupt for IDE device.
+ */
+static void __devinit hpcd_quirk_uli5229(struct pci_dev *dev)
+{
+	unsigned char c;
+
+	if (!machine_is(mpc86xx_hpcd))
+		return;
+
+	pci_read_config_byte(dev, 0x4b, &c);
+	c |= 0x10;
+	pci_write_config_byte(dev, 0x4b, c);
+}
+
+/*
+ * SATA interrupt pin bug fix
+ * There's a chip bug for 5288, The interrupt pin should be 2,
+ * not the read only value 1, So it use INTB#, not INTA# which
+ * actually used by the IDE device 5229.
+ * As of this bug, during the PCI initialization, 5288 read the
+ * irq of IDE device from the device tree, this function fix this
+ * bug by re-assigning a correct irq to 5288.
+ *
+ */
+static void __devinit hpcd_final_uli5288(struct pci_dev *dev)
+{
+	struct pci_controller *hose = pci_bus_to_host(dev->bus);
+	struct device_node *hosenode = hose ? hose->dn : NULL;
+	struct of_irq oirq;
+	int virq, pin = 2;
+	u32 laddr[3];
+
+	if (!machine_is(mpc86xx_hpcd))
+		return;
+
+	if (!hosenode)
+		return;
+
+	laddr[0] = (hose->first_busno << 16) | (PCI_DEVFN(31, 0) << 8);
+	laddr[1] = laddr[2] = 0;
+	of_irq_map_raw(hosenode, &pin, 1, laddr, &oirq);
+	virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+				     oirq.size);
+	dev->irq = virq;
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, hpcd_quirk_uli1575);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, hpcd_quirk_uli5288);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, hpcd_quirk_uli5229);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 0x5288, hpcd_final_uli5288);
+
 int uli_exclude_device(struct pci_controller *hose,
 			u_char bus, u_char devfn)
 {
diff --git a/arch/powerpc/platforms/iseries/Kconfig b/arch/powerpc/platforms/iseries/Kconfig
index 761d9e9..ea3e541 100644
--- a/arch/powerpc/platforms/iseries/Kconfig
+++ b/arch/powerpc/platforms/iseries/Kconfig
@@ -2,6 +2,7 @@
 	bool "IBM Legacy iSeries"
 	depends on PPC_MULTIPLATFORM && PPC64
 	select PPC_INDIRECT_IO
+	select PPC_PCI_CHOICE if EMBEDDED
 
 menu "iSeries device drivers"
 	depends on PPC_ISERIES
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index ab5d868..bc818e4 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -42,7 +42,8 @@
 #include <asm/iseries/iommu.h>
 
 static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
-		unsigned long uaddr, enum dma_data_direction direction)
+		unsigned long uaddr, enum dma_data_direction direction,
+		struct dma_attrs *attrs)
 {
 	u64 rc;
 	u64 tce, rpn;
diff --git a/arch/powerpc/platforms/pasemi/iommu.c b/arch/powerpc/platforms/pasemi/iommu.c
index 86967bd..70541b7 100644
--- a/arch/powerpc/platforms/pasemi/iommu.c
+++ b/arch/powerpc/platforms/pasemi/iommu.c
@@ -85,7 +85,8 @@
 
 static void iobmap_build(struct iommu_table *tbl, long index,
 			 long npages, unsigned long uaddr,
-			 enum dma_data_direction direction)
+			 enum dma_data_direction direction,
+			 struct dma_attrs *attrs)
 {
 	u32 *ip;
 	u32 rpn;
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 00bd016..3163544 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -97,8 +97,6 @@
 int sccdbg;
 #endif
 
-extern void zs_kgdb_hook(int tty_num);
-
 sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN;
 EXPORT_SYMBOL(sys_ctrler);
 
@@ -329,10 +327,6 @@
 	l2cr_init();
 #endif /* CONFIG_PPC32 */
 
-#ifdef CONFIG_KGDB
-	zs_kgdb_hook(0);
-#endif
-
 	find_via_cuda();
 	find_via_pmu();
 	smu_init();
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig
index a5f4e95..920cf7a 100644
--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -8,6 +8,7 @@
 	select USB_ARCH_HAS_EHCI
 	select USB_EHCI_BIG_ENDIAN_MMIO
 	select MEMORY_HOTPLUG
+	select PPC_PCI_CHOICE
 	help
 	  This option enables support for the Sony PS3 game console
 	  and other platforms using the PS3 hypervisor.  Enabling this
diff --git a/arch/powerpc/platforms/ps3/device-init.c b/arch/powerpc/platforms/ps3/device-init.c
index 3866deb..ffdd8e9 100644
--- a/arch/powerpc/platforms/ps3/device-init.c
+++ b/arch/powerpc/platforms/ps3/device-init.c
@@ -486,6 +486,7 @@
 		return -ENOMEM;
 
 	p->dev.match_id = PS3_MATCH_ID_GRAPHICS;
+	p->dev.match_sub_id = PS3_MATCH_SUB_ID_FB;
 	p->dev.dev_type = PS3_DEVICE_TYPE_IOC0;
 
 	result = ps3_system_bus_device_register(&p->dev);
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c
index d66c362..280ee88 100644
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -347,16 +347,23 @@
 	struct ps3_system_bus_driver *drv = ps3_drv_to_system_bus_drv(_drv);
 	struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 
-	result = dev->match_id == drv->match_id;
+	if (!dev->match_sub_id)
+		result = dev->match_id == drv->match_id;
+	else
+		result = dev->match_sub_id == drv->match_sub_id &&
+			dev->match_id == drv->match_id;
 
 	if (result)
-		pr_info("%s:%d: dev=%u(%s), drv=%u(%s): match\n", __func__,
-			__LINE__, dev->match_id, dev->core.bus_id,
-			drv->match_id, drv->core.name);
+		pr_info("%s:%d: dev=%u.%u(%s), drv=%u.%u(%s): match\n",
+			__func__, __LINE__,
+			dev->match_id, dev->match_sub_id, dev->core.bus_id,
+			drv->match_id, drv->match_sub_id, drv->core.name);
 	else
-		pr_debug("%s:%d: dev=%u(%s), drv=%u(%s): miss\n", __func__,
-			__LINE__, dev->match_id, dev->core.bus_id,
-			drv->match_id, drv->core.name);
+		pr_debug("%s:%d: dev=%u.%u(%s), drv=%u.%u(%s): miss\n",
+			__func__, __LINE__,
+			dev->match_id, dev->match_sub_id, dev->core.bus_id,
+			drv->match_id, drv->match_sub_id, drv->core.name);
+
 	return result;
 }
 
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
index 07fe5b6..757c029 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -7,6 +7,7 @@
 	select RTAS_ERROR_LOGGING
 	select PPC_UDBG_16550
 	select PPC_NATIVE
+	select PPC_PCI_CHOICE if EMBEDDED
 	default y
 
 config PPC_SPLPAR
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index c027f0a7..54816d7 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -75,9 +75,9 @@
  */
 
 /* If a device driver keeps reading an MMIO register in an interrupt
- * handler after a slot isolation event has occurred, we assume it
- * is broken and panic.  This sets the threshold for how many read
- * attempts we allow before panicking.
+ * handler after a slot isolation event, it might be broken.
+ * This sets the threshold for how many read attempts we allow
+ * before printing an error message.
  */
 #define EEH_MAX_FAILS	2100000
 
@@ -470,6 +470,7 @@
 	unsigned long flags;
 	struct pci_dn *pdn;
 	int rc = 0;
+	const char *location;
 
 	total_mmio_ffs++;
 
@@ -509,18 +510,15 @@
 	rc = 1;
 	if (pdn->eeh_mode & EEH_MODE_ISOLATED) {
 		pdn->eeh_check_count ++;
-		if (pdn->eeh_check_count >= EEH_MAX_FAILS) {
-			printk (KERN_ERR "EEH: Device driver ignored %d bad reads, panicing\n",
-			        pdn->eeh_check_count);
+		if (pdn->eeh_check_count % EEH_MAX_FAILS == 0) {
+			location = of_get_property(dn, "ibm,loc-code", NULL);
+			printk (KERN_ERR "EEH: %d reads ignored for recovering device at "
+				"location=%s driver=%s pci addr=%s\n",
+				pdn->eeh_check_count, location,
+				dev->driver->name, pci_name(dev));
+			printk (KERN_ERR "EEH: Might be infinite loop in %s driver\n",
+				dev->driver->name);
 			dump_stack();
-			msleep(5000);
-			
-			/* re-read the slot reset state */
-			if (read_slot_reset_state(pdn, rets) != 0)
-				rets[0] = -1;	/* reset state unknown */
-
-			/* If we are here, then we hit an infinite loop. Stop. */
-			panic("EEH: MMIO halt (%d) on device:%s\n", rets[0], pci_name(dev));
 		}
 		goto dn_unlock;
 	}
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 9a12908..5377dd4 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -50,7 +50,8 @@
 
 static void tce_build_pSeries(struct iommu_table *tbl, long index,
 			      long npages, unsigned long uaddr,
-			      enum dma_data_direction direction)
+			      enum dma_data_direction direction,
+			      struct dma_attrs *attrs)
 {
 	u64 proto_tce;
 	u64 *tcep;
@@ -95,7 +96,8 @@
 
 static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
 				long npages, unsigned long uaddr,
-				enum dma_data_direction direction)
+				enum dma_data_direction direction,
+				struct dma_attrs *attrs)
 {
 	u64 rc;
 	u64 proto_tce, tce;
@@ -127,7 +129,8 @@
 
 static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
 				     long npages, unsigned long uaddr,
-				     enum dma_data_direction direction)
+				     enum dma_data_direction direction,
+				     struct dma_attrs *attrs)
 {
 	u64 rc;
 	u64 proto_tce;
@@ -136,7 +139,8 @@
 	long l, limit;
 
 	if (npages == 1) {
-		tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, direction);
+		tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
+				    direction, attrs);
 		return;
 	}
 
@@ -150,7 +154,7 @@
 		/* If allocation fails, fall back to the loop implementation */
 		if (!tcep) {
 			tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
-					    direction);
+					    direction, attrs);
 			return;
 		}
 		__get_cpu_var(tce_page) = tcep;
diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c
index 7f59188..9e105cb 100644
--- a/arch/powerpc/sysdev/axonram.c
+++ b/arch/powerpc/sysdev/axonram.c
@@ -57,6 +57,8 @@
 #define AXON_RAM_SECTOR_SIZE		1 << AXON_RAM_SECTOR_SHIFT
 #define AXON_RAM_IRQ_FLAGS		IRQF_SHARED | IRQF_TRIGGER_RISING
 
+static int azfs_major, azfs_minor;
+
 struct axon_ram_bank {
 	struct of_device	*device;
 	struct gendisk		*disk;
@@ -148,7 +150,10 @@
 	struct axon_ram_bank *bank = device->bd_disk->private_data;
 	loff_t offset;
 
-	offset = sector << AXON_RAM_SECTOR_SHIFT;
+	offset = sector;
+	if (device->bd_part != NULL)
+		offset += device->bd_part->start_sect;
+	offset <<= AXON_RAM_SECTOR_SHIFT;
 	if (offset >= bank->size) {
 		dev_err(&bank->device->dev, "Access outside of address space\n");
 		return -ERANGE;
@@ -227,19 +232,14 @@
 		goto failed;
 	}
 
-	bank->disk->first_minor = 0;
+	bank->disk->major = azfs_major;
+	bank->disk->first_minor = azfs_minor;
 	bank->disk->fops = &axon_ram_devops;
 	bank->disk->private_data = bank;
 	bank->disk->driverfs_dev = &device->dev;
 
 	sprintf(bank->disk->disk_name, "%s%d",
 			AXON_RAM_DEVICE_NAME, axon_ram_bank_id);
-	bank->disk->major = register_blkdev(0, bank->disk->disk_name);
-	if (bank->disk->major < 0) {
-		dev_err(&device->dev, "Cannot register block device\n");
-		rc = -EFAULT;
-		goto failed;
-	}
 
 	bank->disk->queue = blk_alloc_queue(GFP_KERNEL);
 	if (bank->disk->queue == NULL) {
@@ -276,6 +276,8 @@
 		goto failed;
 	}
 
+	azfs_minor += bank->disk->minors;
+
 	return 0;
 
 failed:
@@ -310,7 +312,6 @@
 
 	device_remove_file(&device->dev, &dev_attr_ecc);
 	free_irq(bank->irq_id, device);
-	unregister_blkdev(bank->disk->major, bank->disk->disk_name);
 	del_gendisk(bank->disk);
 	iounmap((void __iomem *) bank->io_addr);
 	kfree(bank);
@@ -341,6 +342,14 @@
 static int __init
 axon_ram_init(void)
 {
+	azfs_major = register_blkdev(azfs_major, AXON_RAM_DEVICE_NAME);
+	if (azfs_major < 0) {
+		printk(KERN_ERR "%s cannot become block device major number\n",
+				AXON_RAM_MODULE_NAME);
+		return -EFAULT;
+	}
+	azfs_minor = 0;
+
 	return of_register_platform_driver(&axon_ram_driver);
 }
 
@@ -351,6 +360,7 @@
 axon_ram_exit(void)
 {
 	of_unregister_platform_driver(&axon_ram_driver);
+	unregister_blkdev(azfs_major, AXON_RAM_DEVICE_NAME);
 }
 
 module_init(axon_ram_init);
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 005c2ec..de8c8b5 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -149,7 +149,8 @@
 
 static void dart_build(struct iommu_table *tbl, long index,
 		       long npages, unsigned long uaddr,
-		       enum dma_data_direction direction)
+		       enum dma_data_direction direction,
+		       struct dma_attrs *attrs)
 {
 	unsigned int *dp;
 	unsigned int rpn;
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 87b0aa1..61e6d77 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -27,6 +27,7 @@
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
 
+#if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx)
 /* atmu setup for fsl pci/pcie controller */
 void __init setup_pci_atmu(struct pci_controller *hose, struct resource *rsrc)
 {
@@ -248,3 +249,63 @@
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641D, quirk_fsl_pcie_header);
 DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8610, quirk_fsl_pcie_header);
+#endif /* CONFIG_PPC_85xx || CONFIG_PPC_86xx */
+
+#if defined(CONFIG_PPC_83xx)
+int __init mpc83xx_add_bridge(struct device_node *dev)
+{
+	int len;
+	struct pci_controller *hose;
+	struct resource rsrc;
+	const int *bus_range;
+	int primary = 1, has_address = 0;
+	phys_addr_t immr = get_immrbase();
+
+	pr_debug("Adding PCI host bridge %s\n", dev->full_name);
+
+	/* Fetch host bridge registers address */
+	has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
+
+	/* Get bus range if any */
+	bus_range = of_get_property(dev, "bus-range", &len);
+	if (bus_range == NULL || len < 2 * sizeof(int)) {
+		printk(KERN_WARNING "Can't get bus-range for %s, assume"
+		       " bus 0\n", dev->full_name);
+	}
+
+	ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
+	hose = pcibios_alloc_controller(dev);
+	if (!hose)
+		return -ENOMEM;
+
+	hose->first_busno = bus_range ? bus_range[0] : 0;
+	hose->last_busno = bus_range ? bus_range[1] : 0xff;
+
+	/* MPC83xx supports up to two host controllers one at 0x8500 from immrbar
+	 * the other at 0x8600, we consider the 0x8500 the primary controller
+	 */
+	/* PCI 1 */
+	if ((rsrc.start & 0xfffff) == 0x8500) {
+		setup_indirect_pci(hose, immr + 0x8300, immr + 0x8304, 0);
+	}
+	/* PCI 2 */
+	if ((rsrc.start & 0xfffff) == 0x8600) {
+		setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384, 0);
+		primary = 0;
+	}
+
+	printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%016llx. "
+	       "Firmware bus number: %d->%d\n",
+	       (unsigned long long)rsrc.start, hose->first_busno,
+	       hose->last_busno);
+
+	pr_debug(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
+	    hose, hose->cfg_addr, hose->cfg_data);
+
+	/* Interpret the "ranges" property */
+	/* This also maps the I/O region and sets isa_io/mem_base */
+	pci_process_bridge_OF_ranges(hose, dev, primary);
+
+	return 0;
+}
+#endif /* CONFIG_PPC_83xx */
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index 37b04ad..13f30c2 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -83,6 +83,7 @@
 
 extern int fsl_add_bridge(struct device_node *dev, int is_primary);
 extern void fsl_pcibios_fixup_bus(struct pci_bus *bus);
+extern int mpc83xx_add_bridge(struct device_node *dev);
 
 #endif /* __POWERPC_FSL_PCI_H */
 #endif /* __KERNEL__ */
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index ebcec73..214388e 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -207,68 +207,60 @@
 arch_initcall(of_add_fixed_phys);
 #endif /* CONFIG_FIXED_PHY */
 
-static int __init gfar_mdio_of_init(void)
+static int gfar_mdio_of_init_one(struct device_node *np)
 {
-	struct device_node *np = NULL;
+	int k;
+	struct device_node *child = NULL;
+	struct gianfar_mdio_data mdio_data;
 	struct platform_device *mdio_dev;
 	struct resource res;
 	int ret;
 
-	np = of_find_compatible_node(np, NULL, "fsl,gianfar-mdio");
+	memset(&res, 0, sizeof(res));
+	memset(&mdio_data, 0, sizeof(mdio_data));
 
-	/* try the deprecated version */
-	if (!np)
-		np = of_find_compatible_node(np, "mdio", "gianfar");
+	ret = of_address_to_resource(np, 0, &res);
+	if (ret)
+		return ret;
 
-	if (np) {
-		int k;
-		struct device_node *child = NULL;
-		struct gianfar_mdio_data mdio_data;
+	mdio_dev = platform_device_register_simple("fsl-gianfar_mdio",
+			res.start&0xfffff, &res, 1);
+	if (IS_ERR(mdio_dev))
+		return PTR_ERR(mdio_dev);
 
-		memset(&res, 0, sizeof(res));
-		memset(&mdio_data, 0, sizeof(mdio_data));
+	for (k = 0; k < 32; k++)
+		mdio_data.irq[k] = PHY_POLL;
 
-		ret = of_address_to_resource(np, 0, &res);
-		if (ret)
-			goto err;
-
-		mdio_dev =
-		    platform_device_register_simple("fsl-gianfar_mdio",
-						    res.start, &res, 1);
-		if (IS_ERR(mdio_dev)) {
-			ret = PTR_ERR(mdio_dev);
-			goto err;
+	while ((child = of_get_next_child(np, child)) != NULL) {
+		int irq = irq_of_parse_and_map(child, 0);
+		if (irq != NO_IRQ) {
+			const u32 *id = of_get_property(child, "reg", NULL);
+			mdio_data.irq[*id] = irq;
 		}
-
-		for (k = 0; k < 32; k++)
-			mdio_data.irq[k] = PHY_POLL;
-
-		while ((child = of_get_next_child(np, child)) != NULL) {
-			int irq = irq_of_parse_and_map(child, 0);
-			if (irq != NO_IRQ) {
-				const u32 *id = of_get_property(child,
-							"reg", NULL);
-				mdio_data.irq[*id] = irq;
-			}
-		}
-
-		ret =
-		    platform_device_add_data(mdio_dev, &mdio_data,
-					     sizeof(struct gianfar_mdio_data));
-		if (ret)
-			goto unreg;
 	}
 
-	of_node_put(np);
-	return 0;
+	ret = platform_device_add_data(mdio_dev, &mdio_data,
+				sizeof(struct gianfar_mdio_data));
+	if (ret)
+		platform_device_unregister(mdio_dev);
 
-unreg:
-	platform_device_unregister(mdio_dev);
-err:
-	of_node_put(np);
 	return ret;
 }
 
+static int __init gfar_mdio_of_init(void)
+{
+	struct device_node *np = NULL;
+
+	for_each_compatible_node(np, NULL, "fsl,gianfar-mdio")
+		gfar_mdio_of_init_one(np);
+
+	/* try the deprecated version */
+	for_each_compatible_node(np, "mdio", "gianfar");
+		gfar_mdio_of_init_one(np);
+
+	return 0;
+}
+
 arch_initcall(gfar_mdio_of_init);
 
 static const char *gfar_tx_intr = "tx";
@@ -296,6 +288,9 @@
 		const phandle *ph;
 		int n_res = 2;
 
+		if (!of_device_is_available(np))
+			continue;
+
 		memset(r, 0, sizeof(r));
 		memset(&gfar_data, 0, sizeof(gfar_data));
 
@@ -357,6 +352,9 @@
 		else
 			gfar_data.interface = PHY_INTERFACE_MODE_MII;
 
+		if (of_get_property(np, "fsl,magic-packet", NULL))
+			gfar_data.device_flags |= FSL_GIANFAR_DEV_HAS_MAGIC_PACKET;
+
 		ph = of_get_property(np, "phy-handle", NULL);
 		if (ph == NULL) {
 			u32 *fixed_link;
@@ -390,7 +388,7 @@
 
 			gfar_data.phy_id = *id;
 			snprintf(gfar_data.bus_id, MII_BUS_ID_SIZE, "%llx",
-				 (unsigned long long)res.start);
+				 (unsigned long long)res.start&0xfffff);
 
 			of_node_put(phy);
 			of_node_put(mdio);
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index 52c831f..0242998 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -10,6 +10,7 @@
 extern u32 fsl_get_sys_freq(void);
 
 struct spi_board_info;
+struct device_node;
 
 extern int fsl_spi_init(struct spi_board_info *board_infos,
 			unsigned int num_board_infos,
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index caba1c0..88a983ec 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -22,6 +22,7 @@
 #include <linux/device.h>
 #include <linux/bootmem.h>
 #include <linux/spinlock.h>
+#include <linux/fsl_devices.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/prom.h>
@@ -889,8 +890,78 @@
 	return irq_linear_revmap(primary_ipic->irqhost, irq);
 }
 
+#ifdef CONFIG_PM
+static struct {
+	u32 sicfr;
+	u32 siprr[2];
+	u32 simsr[2];
+	u32 sicnr;
+	u32 smprr[2];
+	u32 semsr;
+	u32 secnr;
+	u32 sermr;
+	u32 sercr;
+} ipic_saved_state;
+
+static int ipic_suspend(struct sys_device *sdev, pm_message_t state)
+{
+	struct ipic *ipic = primary_ipic;
+
+	ipic_saved_state.sicfr = ipic_read(ipic->regs, IPIC_SICFR);
+	ipic_saved_state.siprr[0] = ipic_read(ipic->regs, IPIC_SIPRR_A);
+	ipic_saved_state.siprr[1] = ipic_read(ipic->regs, IPIC_SIPRR_D);
+	ipic_saved_state.simsr[0] = ipic_read(ipic->regs, IPIC_SIMSR_H);
+	ipic_saved_state.simsr[1] = ipic_read(ipic->regs, IPIC_SIMSR_L);
+	ipic_saved_state.sicnr = ipic_read(ipic->regs, IPIC_SICNR);
+	ipic_saved_state.smprr[0] = ipic_read(ipic->regs, IPIC_SMPRR_A);
+	ipic_saved_state.smprr[1] = ipic_read(ipic->regs, IPIC_SMPRR_B);
+	ipic_saved_state.semsr = ipic_read(ipic->regs, IPIC_SEMSR);
+	ipic_saved_state.secnr = ipic_read(ipic->regs, IPIC_SECNR);
+	ipic_saved_state.sermr = ipic_read(ipic->regs, IPIC_SERMR);
+	ipic_saved_state.sercr = ipic_read(ipic->regs, IPIC_SERCR);
+
+	if (fsl_deep_sleep()) {
+		/* In deep sleep, make sure there can be no
+		 * pending interrupts, as this can cause
+		 * problems on 831x.
+		 */
+		ipic_write(ipic->regs, IPIC_SIMSR_H, 0);
+		ipic_write(ipic->regs, IPIC_SIMSR_L, 0);
+		ipic_write(ipic->regs, IPIC_SEMSR, 0);
+		ipic_write(ipic->regs, IPIC_SERMR, 0);
+	}
+
+	return 0;
+}
+
+static int ipic_resume(struct sys_device *sdev)
+{
+	struct ipic *ipic = primary_ipic;
+
+	ipic_write(ipic->regs, IPIC_SICFR, ipic_saved_state.sicfr);
+	ipic_write(ipic->regs, IPIC_SIPRR_A, ipic_saved_state.siprr[0]);
+	ipic_write(ipic->regs, IPIC_SIPRR_D, ipic_saved_state.siprr[1]);
+	ipic_write(ipic->regs, IPIC_SIMSR_H, ipic_saved_state.simsr[0]);
+	ipic_write(ipic->regs, IPIC_SIMSR_L, ipic_saved_state.simsr[1]);
+	ipic_write(ipic->regs, IPIC_SICNR, ipic_saved_state.sicnr);
+	ipic_write(ipic->regs, IPIC_SMPRR_A, ipic_saved_state.smprr[0]);
+	ipic_write(ipic->regs, IPIC_SMPRR_B, ipic_saved_state.smprr[1]);
+	ipic_write(ipic->regs, IPIC_SEMSR, ipic_saved_state.semsr);
+	ipic_write(ipic->regs, IPIC_SECNR, ipic_saved_state.secnr);
+	ipic_write(ipic->regs, IPIC_SERMR, ipic_saved_state.sermr);
+	ipic_write(ipic->regs, IPIC_SERCR, ipic_saved_state.sercr);
+
+	return 0;
+}
+#else
+#define ipic_suspend NULL
+#define ipic_resume NULL
+#endif
+
 static struct sysdev_class ipic_sysclass = {
 	.name = "ipic",
+	.suspend = ipic_suspend,
+	.resume = ipic_resume,
 };
 
 static struct sys_device device_ipic = {
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index 9e82d7e..b3b73ae5 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -64,7 +64,7 @@
 phys_addr_t get_qe_base(void)
 {
 	struct device_node *qe;
-	unsigned int size;
+	int size;
 	const u32 *prop;
 
 	if (qebase != -1)
@@ -158,7 +158,7 @@
 unsigned int qe_get_brg_clk(void)
 {
 	struct device_node *qe;
-	unsigned int size;
+	int size;
 	const u32 *prop;
 
 	if (brg_clk)
@@ -305,7 +305,7 @@
 
 static int qe_sdma_init(void)
 {
-	struct sdma *sdma = &qe_immr->sdma;
+	struct sdma __iomem *sdma = &qe_immr->sdma;
 	unsigned long sdma_buf_offset;
 
 	if (!sdma)
diff --git a/arch/powerpc/sysdev/qe_lib/ucc.c b/arch/powerpc/sysdev/qe_lib/ucc.c
index d3c7f5a..1d78071 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc.c
@@ -88,7 +88,7 @@
 	return 0;
 }
 
-static void get_cmxucr_reg(unsigned int ucc_num, __be32 **cmxucr,
+static void get_cmxucr_reg(unsigned int ucc_num, __be32 __iomem **cmxucr,
 	unsigned int *reg_num, unsigned int *shift)
 {
 	unsigned int cmx = ((ucc_num & 1) << 1) + (ucc_num > 3);
@@ -100,7 +100,7 @@
 
 int ucc_mux_set_grant_tsa_bkpt(unsigned int ucc_num, int set, u32 mask)
 {
-	__be32 *cmxucr;
+	__be32 __iomem *cmxucr;
 	unsigned int reg_num;
 	unsigned int shift;
 
@@ -121,7 +121,7 @@
 int ucc_set_qe_mux_rxtx(unsigned int ucc_num, enum qe_clock clock,
 	enum comm_dir mode)
 {
-	__be32 *cmxucr;
+	__be32 __iomem *cmxucr;
 	unsigned int reg_num;
 	unsigned int shift;
 	u32 clock_bits = 0;
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
index bcf88e6..1aecb07 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_fast.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
@@ -46,7 +46,7 @@
 	printk(KERN_INFO "uccm  : addr=0x%p, val=0x%08x\n",
 		  &uccf->uf_regs->uccm, in_be32(&uccf->uf_regs->uccm));
 	printk(KERN_INFO "uccs  : addr=0x%p, val=0x%02x\n",
-		  &uccf->uf_regs->uccs, uccf->uf_regs->uccs);
+		  &uccf->uf_regs->uccs, in_8(&uccf->uf_regs->uccs));
 	printk(KERN_INFO "urfb  : addr=0x%p, val=0x%08x\n",
 		  &uccf->uf_regs->urfb, in_be32(&uccf->uf_regs->urfb));
 	printk(KERN_INFO "urfs  : addr=0x%p, val=0x%04x\n",
@@ -68,7 +68,7 @@
 	printk(KERN_INFO "urtry : addr=0x%p, val=0x%08x\n",
 		  &uccf->uf_regs->urtry, in_be32(&uccf->uf_regs->urtry));
 	printk(KERN_INFO "guemr : addr=0x%p, val=0x%02x\n",
-		  &uccf->uf_regs->guemr, uccf->uf_regs->guemr);
+		  &uccf->uf_regs->guemr, in_8(&uccf->uf_regs->guemr));
 }
 EXPORT_SYMBOL(ucc_fast_dump_regs);
 
@@ -96,7 +96,7 @@
 
 void ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode)
 {
-	struct ucc_fast *uf_regs;
+	struct ucc_fast __iomem *uf_regs;
 	u32 gumr;
 
 	uf_regs = uccf->uf_regs;
@@ -117,7 +117,7 @@
 
 void ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode)
 {
-	struct ucc_fast *uf_regs;
+	struct ucc_fast __iomem *uf_regs;
 	u32 gumr;
 
 	uf_regs = uccf->uf_regs;
@@ -139,7 +139,7 @@
 int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** uccf_ret)
 {
 	struct ucc_fast_private *uccf;
-	struct ucc_fast *uf_regs;
+	struct ucc_fast __iomem *uf_regs;
 	u32 gumr;
 	int ret;
 
@@ -216,10 +216,10 @@
 	uccf->stopped_tx = 0;
 	uccf->stopped_rx = 0;
 	uf_regs = uccf->uf_regs;
-	uccf->p_ucce = (u32 *) & (uf_regs->ucce);
-	uccf->p_uccm = (u32 *) & (uf_regs->uccm);
+	uccf->p_ucce = &uf_regs->ucce;
+	uccf->p_uccm = &uf_regs->uccm;
 #ifdef CONFIG_UGETH_TX_ON_DEMAND
-	uccf->p_utodr = (u16 *) & (uf_regs->utodr);
+	uccf->p_utodr = &uf_regs->utodr;
 #endif
 #ifdef STATISTICS
 	uccf->tx_frames = 0;
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index b678103..b795b3e 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -864,7 +864,8 @@
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-static ssize_t cpu_configure_show(struct sys_device *dev, char *buf)
+static ssize_t cpu_configure_show(struct sys_device *dev,
+				struct sysdev_attribute *attr, char *buf)
 {
 	ssize_t count;
 
@@ -874,8 +875,9 @@
 	return count;
 }
 
-static ssize_t cpu_configure_store(struct sys_device *dev, const char *buf,
-				   size_t count)
+static ssize_t cpu_configure_store(struct sys_device *dev,
+				  struct sysdev_attribute *attr,
+				  const char *buf, size_t count)
 {
 	int cpu = dev->id;
 	int val, rc;
@@ -922,7 +924,8 @@
 static SYSDEV_ATTR(configure, 0644, cpu_configure_show, cpu_configure_store);
 #endif /* CONFIG_HOTPLUG_CPU */
 
-static ssize_t cpu_polarization_show(struct sys_device *dev, char *buf)
+static ssize_t cpu_polarization_show(struct sys_device *dev,
+				     struct sysdev_attribute *attr, char *buf)
 {
 	int cpu = dev->id;
 	ssize_t count;
@@ -950,7 +953,8 @@
 }
 static SYSDEV_ATTR(polarization, 0444, cpu_polarization_show, NULL);
 
-static ssize_t show_cpu_address(struct sys_device *dev, char *buf)
+static ssize_t show_cpu_address(struct sys_device *dev,
+				struct sysdev_attribute *attr, char *buf)
 {
 	return sprintf(buf, "%d\n", __cpu_logical_map[dev->id]);
 }
@@ -970,7 +974,8 @@
 	.attrs = cpu_common_attrs,
 };
 
-static ssize_t show_capability(struct sys_device *dev, char *buf)
+static ssize_t show_capability(struct sys_device *dev,
+				struct sysdev_attribute *attr, char *buf)
 {
 	unsigned int capability;
 	int rc;
@@ -982,7 +987,8 @@
 }
 static SYSDEV_ATTR(capability, 0444, show_capability, NULL);
 
-static ssize_t show_idle_count(struct sys_device *dev, char *buf)
+static ssize_t show_idle_count(struct sys_device *dev,
+				struct sysdev_attribute *attr, char *buf)
 {
 	struct s390_idle_data *idle;
 	unsigned long long idle_count;
@@ -995,7 +1001,8 @@
 }
 static SYSDEV_ATTR(idle_count, 0444, show_idle_count, NULL);
 
-static ssize_t show_idle_time(struct sys_device *dev, char *buf)
+static ssize_t show_idle_time(struct sys_device *dev,
+				struct sysdev_attribute *attr, char *buf)
 {
 	struct s390_idle_data *idle;
 	unsigned long long new_time;
@@ -1112,7 +1119,9 @@
 	return rc;
 }
 
-static ssize_t __ref rescan_store(struct sys_device *dev, const char *buf,
+static ssize_t __ref rescan_store(struct sys_device *dev,
+				  struct sysdev_attribute *attr,
+				  const char *buf,
 				  size_t count)
 {
 	int rc;
@@ -1123,7 +1132,9 @@
 static SYSDEV_ATTR(rescan, 0200, NULL, rescan_store);
 #endif /* CONFIG_HOTPLUG_CPU */
 
-static ssize_t dispatching_show(struct sys_device *dev, char *buf)
+static ssize_t dispatching_show(struct sys_device *dev,
+				struct sysdev_attribute *attr,
+				char *buf)
 {
 	ssize_t count;
 
@@ -1133,8 +1144,9 @@
 	return count;
 }
 
-static ssize_t dispatching_store(struct sys_device *dev, const char *buf,
-				 size_t count)
+static ssize_t dispatching_store(struct sys_device *dev,
+				 struct sysdev_attribute *attr,
+				 const char *buf, size_t count)
 {
 	int val, rc;
 	char delim;
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index f2cede3..ab70d9b 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -1100,7 +1100,9 @@
 		return etr_port1_online ? &etr_port1 : NULL;
 }
 
-static ssize_t etr_online_show(struct sys_device *dev, char *buf)
+static ssize_t etr_online_show(struct sys_device *dev,
+				struct sysdev_attribute *attr,
+				char *buf)
 {
 	unsigned int online;
 
@@ -1109,7 +1111,8 @@
 }
 
 static ssize_t etr_online_store(struct sys_device *dev,
-			      const char *buf, size_t count)
+				struct sysdev_attribute *attr,
+				const char *buf, size_t count)
 {
 	unsigned int value;
 
@@ -1136,7 +1139,9 @@
 
 static SYSDEV_ATTR(online, 0600, etr_online_show, etr_online_store);
 
-static ssize_t etr_stepping_control_show(struct sys_device *dev, char *buf)
+static ssize_t etr_stepping_control_show(struct sys_device *dev,
+					struct sysdev_attribute *attr,
+					char *buf)
 {
 	return sprintf(buf, "%i\n", (dev == &etr_port0_dev) ?
 		       etr_eacr.e0 : etr_eacr.e1);
@@ -1144,7 +1149,8 @@
 
 static SYSDEV_ATTR(stepping_control, 0400, etr_stepping_control_show, NULL);
 
-static ssize_t etr_mode_code_show(struct sys_device *dev, char *buf)
+static ssize_t etr_mode_code_show(struct sys_device *dev,
+				struct sysdev_attribute *attr, char *buf)
 {
 	if (!etr_port0_online && !etr_port1_online)
 		/* Status word is not uptodate if both ports are offline. */
@@ -1155,7 +1161,8 @@
 
 static SYSDEV_ATTR(state_code, 0400, etr_mode_code_show, NULL);
 
-static ssize_t etr_untuned_show(struct sys_device *dev, char *buf)
+static ssize_t etr_untuned_show(struct sys_device *dev,
+				struct sysdev_attribute *attr, char *buf)
 {
 	struct etr_aib *aib = etr_aib_from_dev(dev);
 
@@ -1166,7 +1173,8 @@
 
 static SYSDEV_ATTR(untuned, 0400, etr_untuned_show, NULL);
 
-static ssize_t etr_network_id_show(struct sys_device *dev, char *buf)
+static ssize_t etr_network_id_show(struct sys_device *dev,
+				struct sysdev_attribute *attr, char *buf)
 {
 	struct etr_aib *aib = etr_aib_from_dev(dev);
 
@@ -1177,7 +1185,8 @@
 
 static SYSDEV_ATTR(network, 0400, etr_network_id_show, NULL);
 
-static ssize_t etr_id_show(struct sys_device *dev, char *buf)
+static ssize_t etr_id_show(struct sys_device *dev,
+			struct sysdev_attribute *attr, char *buf)
 {
 	struct etr_aib *aib = etr_aib_from_dev(dev);
 
@@ -1188,7 +1197,8 @@
 
 static SYSDEV_ATTR(id, 0400, etr_id_show, NULL);
 
-static ssize_t etr_port_number_show(struct sys_device *dev, char *buf)
+static ssize_t etr_port_number_show(struct sys_device *dev,
+			struct sysdev_attribute *attr, char *buf)
 {
 	struct etr_aib *aib = etr_aib_from_dev(dev);
 
@@ -1199,7 +1209,8 @@
 
 static SYSDEV_ATTR(port, 0400, etr_port_number_show, NULL);
 
-static ssize_t etr_coupled_show(struct sys_device *dev, char *buf)
+static ssize_t etr_coupled_show(struct sys_device *dev,
+			struct sysdev_attribute *attr, char *buf)
 {
 	struct etr_aib *aib = etr_aib_from_dev(dev);
 
@@ -1210,7 +1221,8 @@
 
 static SYSDEV_ATTR(coupled, 0400, etr_coupled_show, NULL);
 
-static ssize_t etr_local_time_show(struct sys_device *dev, char *buf)
+static ssize_t etr_local_time_show(struct sys_device *dev,
+			struct sysdev_attribute *attr, char *buf)
 {
 	struct etr_aib *aib = etr_aib_from_dev(dev);
 
@@ -1221,7 +1233,8 @@
 
 static SYSDEV_ATTR(local_time, 0400, etr_local_time_show, NULL);
 
-static ssize_t etr_utc_offset_show(struct sys_device *dev, char *buf)
+static ssize_t etr_utc_offset_show(struct sys_device *dev,
+			struct sysdev_attribute *attr, char *buf)
 {
 	struct etr_aib *aib = etr_aib_from_dev(dev);
 
diff --git a/arch/sh/boards/renesas/migor/setup.c b/arch/sh/boards/renesas/migor/setup.c
index 01af442..963c993 100644
--- a/arch/sh/boards/renesas/migor/setup.c
+++ b/arch/sh/boards/renesas/migor/setup.c
@@ -30,7 +30,6 @@
 
 static struct smc91x_platdata smc91x_info = {
 	.flags = SMC91X_USE_16BIT,
-	.irq_flags = IRQF_TRIGGER_HIGH,
 };
 
 static struct resource smc91x_eth_resources[] = {
@@ -42,7 +41,7 @@
 	},
 	[1] = {
 		.start  = 32, /* IRQ0 */
-		.flags  = IORESOURCE_IRQ,
+		.flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
 	},
 };
 
diff --git a/arch/sh/drivers/dma/dma-sysfs.c b/arch/sh/drivers/dma/dma-sysfs.c
index 51b57c0..347ee11 100644
--- a/arch/sh/drivers/dma/dma-sysfs.c
+++ b/arch/sh/drivers/dma/dma-sysfs.c
@@ -23,7 +23,8 @@
 };
 EXPORT_SYMBOL(dma_sysclass);
 
-static ssize_t dma_show_devices(struct sys_device *dev, char *buf)
+static ssize_t dma_show_devices(struct sys_device *dev,
+				struct sysdev_attribute *attr, char *buf)
 {
 	ssize_t len = 0;
 	int i;
@@ -57,13 +58,15 @@
 }
 postcore_initcall(dma_sysclass_init);
 
-static ssize_t dma_show_dev_id(struct sys_device *dev, char *buf)
+static ssize_t dma_show_dev_id(struct sys_device *dev,
+				struct sysdev_attribute *attr, char *buf)
 {
 	struct dma_channel *channel = to_dma_channel(dev);
 	return sprintf(buf, "%s\n", channel->dev_id);
 }
 
 static ssize_t dma_store_dev_id(struct sys_device *dev,
+				struct sysdev_attribute *attr,
 				const char *buf, size_t count)
 {
 	struct dma_channel *channel = to_dma_channel(dev);
@@ -74,6 +77,7 @@
 static SYSDEV_ATTR(dev_id, S_IRUGO | S_IWUSR, dma_show_dev_id, dma_store_dev_id);
 
 static ssize_t dma_store_config(struct sys_device *dev,
+				struct sysdev_attribute *attr,
 				const char *buf, size_t count)
 {
 	struct dma_channel *channel = to_dma_channel(dev);
@@ -87,13 +91,15 @@
 
 static SYSDEV_ATTR(config, S_IWUSR, NULL, dma_store_config);
 
-static ssize_t dma_show_mode(struct sys_device *dev, char *buf)
+static ssize_t dma_show_mode(struct sys_device *dev,
+				struct sysdev_attribute *attr, char *buf)
 {
 	struct dma_channel *channel = to_dma_channel(dev);
 	return sprintf(buf, "0x%08x\n", channel->mode);
 }
 
 static ssize_t dma_store_mode(struct sys_device *dev,
+			      struct sysdev_attribute *attr,
 			      const char *buf, size_t count)
 {
 	struct dma_channel *channel = to_dma_channel(dev);
@@ -104,7 +110,8 @@
 static SYSDEV_ATTR(mode, S_IRUGO | S_IWUSR, dma_show_mode, dma_store_mode);
 
 #define dma_ro_attr(field, fmt)						\
-static ssize_t dma_show_##field(struct sys_device *dev, char *buf)	\
+static ssize_t dma_show_##field(struct sys_device *dev, 		\
+				struct sysdev_attribute *attr, char *buf)\
 {									\
 	struct dma_channel *channel = to_dma_channel(dev);		\
 	return sprintf(buf, fmt, channel->field);			\
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index fef28e2..6668e60 100644
--- a/arch/sparc/Makefile
+++ b/arch/sparc/Makefile
@@ -18,6 +18,7 @@
 #KBUILD_CFLAGS += -g -pipe -fcall-used-g5 -fcall-used-g7
 KBUILD_CFLAGS += -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
 KBUILD_AFLAGS += -m32
+CPPFLAGS_vmlinux.lds += -m32
 
 #LDFLAGS_vmlinux = -N -Ttext 0xf0004000
 #  Since 2.5.40, the first stage is left not btfix-ed.
diff --git a/arch/sparc/kernel/apc.c b/arch/sparc/kernel/apc.c
index 6707422..5267d48 100644
--- a/arch/sparc/kernel/apc.c
+++ b/arch/sparc/kernel/apc.c
@@ -56,7 +56,7 @@
  * CPU idle callback function
  * See .../arch/sparc/kernel/process.c
  */
-void apc_swift_idle(void)
+static void apc_swift_idle(void)
 {
 #ifdef APC_DEBUG_LED
 	set_auxio(0x00, AUXIO_LED); 
@@ -85,54 +85,70 @@
 	return 0;
 }
 
-static int apc_ioctl(struct inode *inode, struct file *f, 
-		     unsigned int cmd, unsigned long __arg)
+static long apc_ioctl(struct file *f, unsigned int cmd, unsigned long __arg)
 {
 	__u8 inarg, __user *arg;
 
 	arg = (__u8 __user *) __arg;
+
+	lock_kernel();
+
 	switch (cmd) {
 	case APCIOCGFANCTL:
-		if (put_user(apc_readb(APC_FANCTL_REG) & APC_REGMASK, arg))
-				return -EFAULT;
+		if (put_user(apc_readb(APC_FANCTL_REG) & APC_REGMASK, arg)) {
+			unlock_kernel();
+			return -EFAULT;
+		}
 		break;
 
 	case APCIOCGCPWR:
-		if (put_user(apc_readb(APC_CPOWER_REG) & APC_REGMASK, arg))
+		if (put_user(apc_readb(APC_CPOWER_REG) & APC_REGMASK, arg)) {
+			unlock_kernel();
 			return -EFAULT;
+		}
 		break;
 
 	case APCIOCGBPORT:
-		if (put_user(apc_readb(APC_BPORT_REG) & APC_BPMASK, arg))
+		if (put_user(apc_readb(APC_BPORT_REG) & APC_BPMASK, arg)) {
+			unlock_kernel();
 			return -EFAULT;
+		}
 		break;
 
 	case APCIOCSFANCTL:
-		if (get_user(inarg, arg))
+		if (get_user(inarg, arg)) {
+			unlock_kernel();
 			return -EFAULT;
+		}
 		apc_writeb(inarg & APC_REGMASK, APC_FANCTL_REG);
 		break;
 	case APCIOCSCPWR:
-		if (get_user(inarg, arg))
+		if (get_user(inarg, arg)) {
+			unlock_kernel();
 			return -EFAULT;
+		}
 		apc_writeb(inarg & APC_REGMASK, APC_CPOWER_REG);
 		break;
 	case APCIOCSBPORT:
-		if (get_user(inarg, arg))
+		if (get_user(inarg, arg)) {
+			unlock_kernel();
 			return -EFAULT;
+		}
 		apc_writeb(inarg & APC_BPMASK, APC_BPORT_REG);
 		break;
 	default:
+		unlock_kernel();
 		return -EINVAL;
 	};
 
+	unlock_kernel();
 	return 0;
 }
 
 static const struct file_operations apc_fops = {
-	.ioctl =	apc_ioctl,
-	.open =		apc_open,
-	.release =	apc_release,
+	.unlocked_ioctl =	apc_ioctl,
+	.open =			apc_open,
+	.release =		apc_release,
 };
 
 static struct miscdevice apc_miscdev = { APC_MINOR, APC_DEVNAME, &apc_fops };
diff --git a/arch/sparc/kernel/asm-offsets.c b/arch/sparc/kernel/asm-offsets.c
index cd3f769..b5bb99e 100644
--- a/arch/sparc/kernel/asm-offsets.c
+++ b/arch/sparc/kernel/asm-offsets.c
@@ -18,18 +18,6 @@
 {
 	DEFINE(AOFF_task_thread, offsetof(struct task_struct, thread));
 	BLANK();
-	/* XXX This is the stuff for sclow.S, kill it. */
-	DEFINE(AOFF_task_pid, offsetof(struct task_struct, pid));
-	DEFINE(AOFF_task_uid, offsetof(struct task_struct, uid));
-	DEFINE(AOFF_task_gid, offsetof(struct task_struct, gid));
-	DEFINE(AOFF_task_euid, offsetof(struct task_struct, euid));
-	DEFINE(AOFF_task_egid, offsetof(struct task_struct, egid));
-	/* DEFINE(THREAD_INFO, offsetof(struct task_struct, stack)); */
-	DEFINE(ASIZ_task_uid,	sizeof(current->uid));
-	DEFINE(ASIZ_task_gid,	sizeof(current->gid));
-	DEFINE(ASIZ_task_euid,	sizeof(current->euid));
-	DEFINE(ASIZ_task_egid,	sizeof(current->egid));
-	BLANK();
 	DEFINE(AOFF_thread_fork_kpsr,
 			offsetof(struct thread_struct, fork_kpsr));
 	BLANK();
diff --git a/arch/sparc/kernel/ebus.c b/arch/sparc/kernel/ebus.c
index 92c6fc0..9729423 100644
--- a/arch/sparc/kernel/ebus.c
+++ b/arch/sparc/kernel/ebus.c
@@ -69,7 +69,7 @@
 
 /*
  */
-int __init ebus_blacklist_irq(const char *name)
+static int __init ebus_blacklist_irq(const char *name)
 {
 	struct ebus_device_irq *dp;
 
@@ -83,8 +83,8 @@
 	return 0;
 }
 
-void __init fill_ebus_child(struct device_node *dp,
-			    struct linux_ebus_child *dev)
+static void __init fill_ebus_child(struct device_node *dp,
+				   struct linux_ebus_child *dev)
 {
 	const int *regs;
 	const int *irqs;
@@ -144,7 +144,8 @@
 	}
 }
 
-void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev)
+static void __init fill_ebus_device(struct device_node *dp,
+				    struct linux_ebus_device *dev)
 {
 	const struct linux_prom_registers *regs;
 	struct linux_ebus_child *child;
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index 4bcfe54..2f96256 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -19,6 +19,7 @@
 #include <asm/vaddrs.h>
 #include <asm/memreg.h>
 #include <asm/page.h>
+#include <asm/pgtable.h>
 #ifdef CONFIG_SUN4
 #include <asm/pgtsun4.h>
 #else
@@ -1317,7 +1318,6 @@
 	bne	linux_fast_syscall
 	 /* Just do first insn from SAVE_ALL in the delay slot */
 
-	.globl	syscall_is_too_hard
 syscall_is_too_hard:
 	SAVE_ALL_HEAD
 	 rd	%wim, %l3
@@ -1544,8 +1544,7 @@
 #endif
 
 	.align	4
-	.globl	__handle_exception, flush_patch_exception
-__handle_exception:
+	.globl	flush_patch_exception
 flush_patch_exception:
 	FLUSH_ALL_KERNEL_WINDOWS;
 	ldd	[%o0], %o6
diff --git a/arch/sparc/kernel/etrap.S b/arch/sparc/kernel/etrap.S
index f37d961..e806fcd 100644
--- a/arch/sparc/kernel/etrap.S
+++ b/arch/sparc/kernel/etrap.S
@@ -228,7 +228,6 @@
 	 */
 #define glob_tmp     g1
 
-	.globl	tsetup_sun4c_stackchk
 tsetup_sun4c_stackchk:
 	/* Done by caller: andcc %sp, 0x7, %g0 */
 	bne	trap_setup_user_stack_is_bolixed
diff --git a/arch/sparc/kernel/head.S b/arch/sparc/kernel/head.S
index 3bfd608..50d9a16 100644
--- a/arch/sparc/kernel/head.S
+++ b/arch/sparc/kernel/head.S
@@ -32,7 +32,6 @@
  */
 
 	.align 4
-        .globl  cputyp
 cputyp:
         .word   1
 
@@ -1280,7 +1279,6 @@
  * gets initialized in c-code so all routines can use it.
  */
 
-	.globl	prom_vector_p
 prom_vector_p:
 		.word 0
 
diff --git a/arch/sparc/kernel/idprom.c b/arch/sparc/kernel/idprom.c
index 7220562..fc511f3 100644
--- a/arch/sparc/kernel/idprom.c
+++ b/arch/sparc/kernel/idprom.c
@@ -24,7 +24,7 @@
  * of the Sparc CPU and have a meaningful IDPROM machtype value that we
  * know about.  See asm-sparc/machines.h for empirical constants.
  */
-struct Sun_Machine_Models Sun_Machines[NUM_SUN_MACHINES] = {
+static struct Sun_Machine_Models Sun_Machines[NUM_SUN_MACHINES] = {
 /* First, Sun4's */
 { "Sun 4/100 Series", (SM_SUN4 | SM_4_110) },
 { "Sun 4/200 Series", (SM_SUN4 | SM_4_260) },
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 7b17522..4879609 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -49,13 +49,16 @@
 
 #define mmu_inval_dma_area(p, l)	/* Anton pulled it out for 2.4.0-xx */
 
-struct resource *_sparc_find_resource(struct resource *r, unsigned long);
+static struct resource *_sparc_find_resource(struct resource *r,
+					     unsigned long);
 
 static void __iomem *_sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz);
 static void __iomem *_sparc_alloc_io(unsigned int busno, unsigned long phys,
     unsigned long size, char *name);
 static void _sparc_free_io(struct resource *res);
 
+static void register_proc_sparc_ioport(void);
+
 /* This points to the next to use virtual memory for DVMA mappings */
 static struct resource _sparc_dvma = {
 	.name = "sparc_dvma", .start = DVMA_VADDR, .end = DVMA_END - 1
@@ -539,8 +542,6 @@
 
 int __init sbus_arch_preinit(void)
 {
-	extern void register_proc_sparc_ioport(void);
-
 	register_proc_sparc_ioport();
 
 #ifdef CONFIG_SUN4
@@ -853,8 +854,8 @@
  * XXX Too slow. Can have 8192 DVMA pages on sun4m in the worst case.
  * This probably warrants some sort of hashing.
  */
-struct resource *
-_sparc_find_resource(struct resource *root, unsigned long hit)
+static struct resource *_sparc_find_resource(struct resource *root,
+					     unsigned long hit)
 {
         struct resource *tmp;
 
@@ -865,7 +866,7 @@
 	return NULL;
 }
 
-void register_proc_sparc_ioport(void)
+static void register_proc_sparc_ioport(void)
 {
 #ifdef CONFIG_PROC_FS
 	create_proc_read_entry("io_map",0,NULL,_sparc_io_get_info,&sparc_iomap);
diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c
index 087390b0..93e1d1c 100644
--- a/arch/sparc/kernel/irq.c
+++ b/arch/sparc/kernel/irq.c
@@ -154,7 +154,7 @@
 struct irqaction static_irqaction[MAX_STATIC_ALLOC];
 int static_irq_count;
 
-struct {
+static struct {
 	struct irqaction *action;
 	int flags;
 } sparc_irq[NR_IRQS];
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
index da48d24..4bb4309 100644
--- a/arch/sparc/kernel/process.c
+++ b/arch/sparc/kernel/process.c
@@ -1,6 +1,6 @@
 /*  linux/arch/sparc/kernel/process.c
  *
- *  Copyright (C) 1995 David S. Miller (davem@davemloft.net)
+ *  Copyright (C) 1995, 2008 David S. Miller (davem@davemloft.net)
  *  Copyright (C) 1996 Eddie C. Dost   (ecd@skynet.be)
  */
 
@@ -14,7 +14,6 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
-#include <linux/kallsyms.h>
 #include <linux/mm.h>
 #include <linux/stddef.h>
 #include <linux/ptrace.h>
@@ -177,6 +176,8 @@
 	machine_halt();
 }
 
+#if 0
+
 static DEFINE_SPINLOCK(sparc_backtrace_lock);
 
 void __show_backtrace(unsigned long fp)
@@ -196,7 +197,7 @@
 		       rw->ins[4], rw->ins[5],
 		       rw->ins[6],
 		       rw->ins[7]);
-		print_symbol("%s\n", rw->ins[7]);
+		printk("%pS\n", (void *) rw->ins[7]);
 		rw = (struct reg_window *) rw->ins[6];
 	}
 	spin_unlock_irqrestore(&sparc_backtrace_lock, flags);
@@ -228,7 +229,6 @@
 }
 #endif
 
-#if 0
 void show_stackframe(struct sparc_stackf *sf)
 {
 	unsigned long size;
@@ -264,14 +264,14 @@
 
         printk("PSR: %08lx PC: %08lx NPC: %08lx Y: %08lx    %s\n",
 	       r->psr, r->pc, r->npc, r->y, print_tainted());
-	print_symbol("PC: <%s>\n", r->pc);
+	printk("PC: <%pS>\n", (void *) r->pc);
 	printk("%%G: %08lx %08lx  %08lx %08lx  %08lx %08lx  %08lx %08lx\n",
 	       r->u_regs[0], r->u_regs[1], r->u_regs[2], r->u_regs[3],
 	       r->u_regs[4], r->u_regs[5], r->u_regs[6], r->u_regs[7]);
 	printk("%%O: %08lx %08lx  %08lx %08lx  %08lx %08lx  %08lx %08lx\n",
 	       r->u_regs[8], r->u_regs[9], r->u_regs[10], r->u_regs[11],
 	       r->u_regs[12], r->u_regs[13], r->u_regs[14], r->u_regs[15]);
-	print_symbol("RPC: <%s>\n", r->u_regs[15]);
+	printk("RPC: <%pS>\n", (void *) r->u_regs[15]);
 
 	printk("%%L: %08lx %08lx  %08lx %08lx  %08lx %08lx  %08lx %08lx\n",
 	       rw->locals[0], rw->locals[1], rw->locals[2], rw->locals[3],
@@ -306,7 +306,7 @@
 		rw = (struct reg_window *) fp;
 		pc = rw->ins[7];
 		printk("[%08lx : ", pc);
-		print_symbol("%s ] ", pc);
+		printk("%pS ] ", (void *) pc);
 		fp = rw->ins[6];
 	} while (++count < 16);
 	printk("\n");
diff --git a/arch/sparc/kernel/rtrap.S b/arch/sparc/kernel/rtrap.S
index ce30082..891f460 100644
--- a/arch/sparc/kernel/rtrap.S
+++ b/arch/sparc/kernel/rtrap.S
@@ -224,8 +224,6 @@
 	b	signal_p
 	 ld	[%curptr + TI_FLAGS], %g2
 
-
-	.globl	sun4c_rett_stackchk
 sun4c_rett_stackchk:
 	be	1f
 	 and	%fp, 0xfff, %g1		! delay slot
diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c
index a0ea0bc..9e451b2 100644
--- a/arch/sparc/kernel/setup.c
+++ b/arch/sparc/kernel/setup.c
@@ -67,7 +67,7 @@
 extern unsigned long trapbase;
 
 /* Pretty sick eh? */
-void prom_sync_me(void)
+static void prom_sync_me(void)
 {
 	unsigned long prom_tbr, flags;
 
@@ -97,7 +97,7 @@
 	return;
 }
 
-unsigned int boot_flags __initdata = 0;
+static unsigned int boot_flags __initdata = 0;
 #define BOOTME_DEBUG  0x1
 
 /* Exported for mm/init.c:paging_init. */
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
index 6724ab9..1619ec1 100644
--- a/arch/sparc/kernel/smp.c
+++ b/arch/sparc/kernel/smp.c
@@ -35,13 +35,9 @@
 
 #include "irq.h"
 
-int smp_num_cpus = 1;
 volatile unsigned long cpu_callin_map[NR_CPUS] __initdata = {0,};
 unsigned char boot_cpu_id = 0;
 unsigned char boot_cpu_id4 = 0; /* boot_cpu_id << 2 */
-int smp_activated = 0;
-volatile int __cpu_number_map[NR_CPUS];
-volatile int __cpu_logical_map[NR_CPUS];
 
 cpumask_t cpu_online_map = CPU_MASK_NONE;
 cpumask_t phys_cpu_present_map = CPU_MASK_NONE;
@@ -55,9 +51,6 @@
  * instruction which is much better...
  */
 
-/* Used to make bitops atomic */
-unsigned char bitops_spinlock = 0;
-
 void __cpuinit smp_store_cpu_info(int id)
 {
 	int cpu_node;
diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c
index c6ac9fc..340fc39 100644
--- a/arch/sparc/kernel/sun4c_irq.c
+++ b/arch/sparc/kernel/sun4c_irq.c
@@ -68,7 +68,8 @@
 
 static int sun4c_pil_map[] = { 0, 1, 2, 3, 5, 7, 8, 9 };
 
-unsigned int sun4c_sbint_to_irq(struct sbus_dev *sdev, unsigned int sbint)
+static unsigned int sun4c_sbint_to_irq(struct sbus_dev *sdev,
+				       unsigned int sbint)
 {
 	if (sbint >= sizeof(sun4c_pil_map)) {
 		printk(KERN_ERR "%s: bogus SBINT %d\n", sdev->prom_name, sbint);
diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c
index 8ac5661..1290b59 100644
--- a/arch/sparc/kernel/sun4d_irq.c
+++ b/arch/sparc/kernel/sun4d_irq.c
@@ -52,13 +52,13 @@
 extern int static_irq_count;
 unsigned char cpu_leds[32];
 #ifdef CONFIG_SMP
-unsigned char sbus_tid[32];
+static unsigned char sbus_tid[32];
 #endif
 
 static struct irqaction *irq_action[NR_IRQS];
 extern spinlock_t irq_action_lock;
 
-struct sbus_action {
+static struct sbus_action {
 	struct irqaction *action;
 	/* For SMP this needs to be extended */
 } *sbus_actions;
@@ -267,7 +267,8 @@
 		return irq;
 }
 
-unsigned int sun4d_sbint_to_irq(struct sbus_dev *sdev, unsigned int sbint)
+static unsigned int sun4d_sbint_to_irq(struct sbus_dev *sdev,
+				       unsigned int sbint)
 {
 	if (sbint >= sizeof(sbus_to_pil)) {
 		printk(KERN_ERR "%s: bogus SBINT %d\n", sdev->prom_name, sbint);
diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c
index b92d6d2..94e02de 100644
--- a/arch/sparc/kernel/sun4m_irq.c
+++ b/arch/sparc/kernel/sun4m_irq.c
@@ -154,7 +154,8 @@
 
 static int sun4m_pil_map[] = { 0, 2, 3, 5, 7, 9, 11, 13 };
 
-unsigned int sun4m_sbint_to_irq(struct sbus_dev *sdev, unsigned int sbint) 
+static unsigned int sun4m_sbint_to_irq(struct sbus_dev *sdev,
+				       unsigned int sbint)
 {
 	if (sbint >= sizeof(sun4m_pil_map)) {
 		printk(KERN_ERR "%s: bogus SBINT %d\n", sdev->prom_name, sbint);
@@ -163,7 +164,7 @@
 	return sun4m_pil_map[sbint] | 0x30;
 }
 
-inline unsigned long sun4m_get_irqmask(unsigned int irq)
+static unsigned long sun4m_get_irqmask(unsigned int irq)
 {
 	unsigned long mask;
     
@@ -281,7 +282,7 @@
 #define TIMER_IRQ  	(OBIO_INTR | 10)
 #define PROFILE_IRQ	(OBIO_INTR | 14)
 
-struct sun4m_timer_regs *sun4m_timers;
+static struct sun4m_timer_regs *sun4m_timers;
 unsigned int lvl14_resolution = (((1000000/HZ) + 1) << 10);
 
 static void sun4m_clear_clock_irq(void)
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index ffb875a..406ac1a 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -244,8 +244,9 @@
 static DEFINE_SPINLOCK(cross_call_lock);
 
 /* Cross calls must be serialized, at least currently. */
-void smp4m_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2,
-		    unsigned long arg3, unsigned long arg4, unsigned long arg5)
+static void smp4m_cross_call(smpfunc_t func, unsigned long arg1,
+			     unsigned long arg2, unsigned long arg3,
+			     unsigned long arg4, unsigned long arg5)
 {
 		register int ncpus = SUN4M_NCPUS;
 		unsigned long flags;
@@ -344,7 +345,7 @@
 		enable_pil_irq(14);
 }
 
-void __init smp4m_blackbox_id(unsigned *addr)
+static void __init smp4m_blackbox_id(unsigned *addr)
 {
 	int rd = *addr & 0x3e000000;
 	int rs1 = rd >> 11;
@@ -354,7 +355,7 @@
 	addr[2] = 0x80082003 | rd | rs1;	/* and reg, 3, reg */
 }
 
-void __init smp4m_blackbox_current(unsigned *addr)
+static void __init smp4m_blackbox_current(unsigned *addr)
 {
 	int rd = *addr & 0x3e000000;
 	int rs1 = rd >> 11;
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
index 53caacb..ab3dd0b 100644
--- a/arch/sparc/kernel/time.c
+++ b/arch/sparc/kernel/time.c
@@ -46,7 +46,7 @@
 #include "irq.h"
 
 DEFINE_SPINLOCK(rtc_lock);
-enum sparc_clock_type sp_clock_typ;
+static enum sparc_clock_type sp_clock_typ;
 DEFINE_SPINLOCK(mostek_lock);
 void __iomem *mstk48t02_regs = NULL;
 static struct mostek48t08 __iomem *mstk48t08_regs = NULL;
@@ -366,7 +366,7 @@
 fs_initcall(clock_init);
 #endif /* !CONFIG_SUN4 */
 
-void __init sbus_time_init(void)
+static void __init sbus_time_init(void)
 {
 
 	BTFIXUPSET_CALL(bus_do_settimeofday, sbus_do_settimeofday, BTFIXUPCALL_NORM);
diff --git a/arch/sparc/kernel/traps.c b/arch/sparc/kernel/traps.c
index 978e9d8..5d45d5f 100644
--- a/arch/sparc/kernel/traps.c
+++ b/arch/sparc/kernel/traps.c
@@ -1,7 +1,7 @@
 /*
  * arch/sparc/kernel/traps.c
  *
- * Copyright 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright 1995, 2008 David S. Miller (davem@davemloft.net)
  * Copyright 2000 Jakub Jelinek (jakub@redhat.com)
  */
 
@@ -11,7 +11,6 @@
 
 #include <linux/sched.h>  /* for jiffies */
 #include <linux/kernel.h>
-#include <linux/kallsyms.h>
 #include <linux/signal.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
@@ -33,9 +32,6 @@
 	unsigned long type;
 };
 
-int trap_curbuf = 0;
-struct trap_trace_entry trapbuf[1024];
-
 void syscall_trace_entry(struct pt_regs *regs)
 {
 	printk("%s[%d]: ", current->comm, task_pid_nr(current));
@@ -72,7 +68,7 @@
 	prom_halt();
 }
 
-void instruction_dump (unsigned long *pc)
+static void instruction_dump(unsigned long *pc)
 {
 	int i;
 	
@@ -119,8 +115,8 @@
 		      count++ < 30				&&
                       (((unsigned long) rw) >= PAGE_OFFSET)	&&
 		      !(((unsigned long) rw) & 0x7)) {
-			printk("Caller[%08lx]", rw->ins[7]);
-			print_symbol(": %s\n", rw->ins[7]);
+			printk("Caller[%08lx]: %pS\n", rw->ins[7],
+			       (void *) rw->ins[7]);
 			rw = (struct reg_window *)rw->ins[6];
 		}
 	}
@@ -479,10 +475,6 @@
 
 extern void sparc_cpu_startup(void);
 
-int linux_smp_still_initting;
-unsigned int thiscpus_tbr;
-int thiscpus_mid;
-
 void trap_init(void)
 {
 	extern void thread_info_offsets_are_bolixed_pete(void);
diff --git a/arch/sparc/kernel/wof.S b/arch/sparc/kernel/wof.S
index 4bce38d..3bbcd8d 100644
--- a/arch/sparc/kernel/wof.S
+++ b/arch/sparc/kernel/wof.S
@@ -306,7 +306,6 @@
  * As noted above %curptr cannot be touched by this routine at all.
  */
 
-	.globl	spwin_sun4c_stackchk
 spwin_sun4c_stackchk:
 	/* LOCATION: Window to be saved on the stack */
 
diff --git a/arch/sparc/kernel/wuf.S b/arch/sparc/kernel/wuf.S
index 82e5145..779ff750 100644
--- a/arch/sparc/kernel/wuf.S
+++ b/arch/sparc/kernel/wuf.S
@@ -243,7 +243,6 @@
 	 */
 
 	.align	4
-	.globl	sun4c_fwin_stackchk
 sun4c_fwin_stackchk:
 	/* LOCATION: Window 'W' */
 
diff --git a/arch/sparc/mm/fault.c b/arch/sparc/mm/fault.c
index 0a3cd8f..3604c2e 100644
--- a/arch/sparc/mm/fault.c
+++ b/arch/sparc/mm/fault.c
@@ -451,7 +451,7 @@
 }
 
 /* This always deals with user addresses. */
-inline void force_user_fault(unsigned long address, int write)
+static void force_user_fault(unsigned long address, int write)
 {
 	struct vm_area_struct *vma;
 	struct task_struct *tsk = current;
diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c
index 7794ecb..e103f1b 100644
--- a/arch/sparc/mm/init.c
+++ b/arch/sparc/mm/init.c
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/highmem.h>
 #include <linux/bootmem.h>
+#include <linux/pagemap.h>
 
 #include <asm/system.h>
 #include <asm/vac-ops.h>
@@ -128,7 +129,7 @@
 	return nr;
 }
 
-unsigned long calc_max_low_pfn(void)
+static unsigned long calc_max_low_pfn(void)
 {
 	int i;
 	unsigned long tmp = pfn_base + (SRMMU_MAXMEM >> PAGE_SHIFT);
@@ -292,7 +293,7 @@
  *
  * We simply copy the 2.4 implementation for now.
  */
-int pgt_cache_water[2] = { 25, 50 };
+static int pgt_cache_water[2] = { 25, 50 };
 
 void check_pgt_cache(void)
 {
@@ -356,8 +357,6 @@
 	device_scan();
 }
 
-struct cache_palias *sparc_aliases;
-
 static void __init taint_real_pages(void)
 {
 	int i;
@@ -375,7 +374,7 @@
 	}
 }
 
-void map_high_region(unsigned long start_pfn, unsigned long end_pfn)
+static void map_high_region(unsigned long start_pfn, unsigned long end_pfn)
 {
 	unsigned long tmp;
 
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index 23d3291..c624e04 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -50,7 +50,7 @@
 #include <asm/btfixup.h>
 
 enum mbus_module srmmu_modtype;
-unsigned int hwbug_bitmask;
+static unsigned int hwbug_bitmask;
 int vac_cache_size;
 int vac_line_size;
 
@@ -60,7 +60,7 @@
 
 extern unsigned long page_kernel;
 
-pgd_t *srmmu_swapper_pg_dir;
+static pgd_t *srmmu_swapper_pg_dir;
 
 #ifdef CONFIG_SMP
 #define FLUSH_BEGIN(mm)
@@ -83,12 +83,12 @@
 char *srmmu_name;
 
 ctxd_t *srmmu_ctx_table_phys;
-ctxd_t *srmmu_context_table;
+static ctxd_t *srmmu_context_table;
 
 int viking_mxcc_present;
 static DEFINE_SPINLOCK(srmmu_context_spinlock);
 
-int is_hypersparc;
+static int is_hypersparc;
 
 /*
  * In general all page table modifications should use the V8 atomic
@@ -112,11 +112,11 @@
 	return ((x & 0xF0000000) != 0);
 }
 
-int srmmu_cache_pagetables;
+static int srmmu_cache_pagetables;
 
 /* these will be initialized in srmmu_nocache_calcsize() */
-unsigned long srmmu_nocache_size;
-unsigned long srmmu_nocache_end;
+static unsigned long srmmu_nocache_size;
+static unsigned long srmmu_nocache_end;
 
 /* 1 bit <=> 256 bytes of nocache <=> 64 PTEs */
 #define SRMMU_NOCACHE_BITMAP_SHIFT (PAGE_SHIFT - 4)
@@ -324,7 +324,7 @@
 	return (SRMMU_NOCACHE_VADDR + (offset << SRMMU_NOCACHE_BITMAP_SHIFT));
 }
 
-unsigned inline long srmmu_get_nocache(int size, int align)
+static unsigned long srmmu_get_nocache(int size, int align)
 {
 	unsigned long tmp;
 
@@ -336,7 +336,7 @@
 	return tmp;
 }
 
-void srmmu_free_nocache(unsigned long vaddr, int size)
+static void srmmu_free_nocache(unsigned long vaddr, int size)
 {
 	int offset;
 
@@ -369,7 +369,8 @@
 	bit_map_clear(&srmmu_nocache_map, offset, size);
 }
 
-void srmmu_early_allocate_ptable_skeleton(unsigned long start, unsigned long end);
+static void srmmu_early_allocate_ptable_skeleton(unsigned long start,
+						 unsigned long end);
 
 extern unsigned long probe_memory(void);	/* in fault.c */
 
@@ -377,7 +378,7 @@
  * Reserve nocache dynamically proportionally to the amount of
  * system RAM. -- Tomas Szepe <szepe@pinerecords.com>, June 2002
  */
-void srmmu_nocache_calcsize(void)
+static void srmmu_nocache_calcsize(void)
 {
 	unsigned long sysmemavail = probe_memory() / 1024;
 	int srmmu_nocache_npages;
@@ -398,7 +399,7 @@
 	srmmu_nocache_end = SRMMU_NOCACHE_VADDR + srmmu_nocache_size;
 }
 
-void __init srmmu_nocache_init(void)
+static void __init srmmu_nocache_init(void)
 {
 	unsigned int bitmap_bits;
 	pgd_t *pgd;
@@ -645,7 +646,7 @@
  * mappings on the kernel stack without any special code as we did
  * need on the sun4c.
  */
-struct thread_info *srmmu_alloc_thread_info(void)
+static struct thread_info *srmmu_alloc_thread_info(void)
 {
 	struct thread_info *ret;
 
@@ -1045,13 +1046,14 @@
  *       around 8mb mapped for us.
  */
 
-void __init early_pgtable_allocfail(char *type)
+static void __init early_pgtable_allocfail(char *type)
 {
 	prom_printf("inherit_prom_mappings: Cannot alloc kernel %s.\n", type);
 	prom_halt();
 }
 
-void __init srmmu_early_allocate_ptable_skeleton(unsigned long start, unsigned long end)
+static void __init srmmu_early_allocate_ptable_skeleton(unsigned long start,
+							unsigned long end)
 {
 	pgd_t *pgdp;
 	pmd_t *pmdp;
@@ -1081,7 +1083,8 @@
 	}
 }
 
-void __init srmmu_allocate_ptable_skeleton(unsigned long start, unsigned long end)
+static void __init srmmu_allocate_ptable_skeleton(unsigned long start,
+						  unsigned long end)
 {
 	pgd_t *pgdp;
 	pmd_t *pmdp;
@@ -1116,7 +1119,8 @@
  * looking at the prom's page table directly which is what most
  * other OS's do.  Yuck... this is much better.
  */
-void __init srmmu_inherit_prom_mappings(unsigned long start,unsigned long end)
+static void __init srmmu_inherit_prom_mappings(unsigned long start,
+					       unsigned long end)
 {
 	pgd_t *pgdp;
 	pmd_t *pmdp;
diff --git a/arch/sparc/mm/tsunami.S b/arch/sparc/mm/tsunami.S
index db0d6de..4e55e8f 100644
--- a/arch/sparc/mm/tsunami.S
+++ b/arch/sparc/mm/tsunami.S
@@ -93,7 +93,6 @@
 	ldd	[src + offset + 0x00], t2; \
 	std	t2, [dst + offset + 0x00];
 
-	.globl	tsunami_copy_1page
 tsunami_copy_1page:
 /* NOTE: This routine has to be shorter than 70insns --jj */
 	or	%g0, (PAGE_SIZE >> 8), %g1
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index fca9246..7c88263 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -16,6 +16,7 @@
 	select HAVE_IDE
 	select HAVE_LMB
 	select HAVE_ARCH_KGDB
+	select USE_GENERIC_SMP_HELPERS if SMP
 
 config GENERIC_TIME
 	bool
@@ -81,6 +82,10 @@
 	bool
 	def_bool y
 
+source "init/Kconfig"
+
+menu "Processor type and features"
+
 choice
 	prompt "Kernel page size"
 	default SPARC64_PAGE_SIZE_8KB
@@ -93,19 +98,11 @@
 	  8KB and 64KB work quite well, since SPARC ELF sections
 	  provide for up to 64KB alignment.
 
-	  Therefore, 512KB and 4MB are for expert hackers only.
-
 	  If you don't know what to do, choose 8KB.
 
 config SPARC64_PAGE_SIZE_64KB
 	bool "64KB"
 
-config SPARC64_PAGE_SIZE_512KB
-	bool "512KB"
-
-config SPARC64_PAGE_SIZE_4MB
-	bool "4MB"
-
 endchoice
 
 config SECCOMP
@@ -136,14 +133,10 @@
 	  can be controlled through /sys/devices/system/cpu/cpu#.
 	  Say N if you want to disable CPU hotplug.
 
-source "init/Kconfig"
-
 config GENERIC_HARDIRQS
 	bool
 	default y
 
-menu "General machine setup"
-
 source "kernel/time/Kconfig"
 
 config SMP
@@ -225,11 +218,10 @@
 	bool "4MB"
 
 config HUGETLB_PAGE_SIZE_512K
-	depends on !SPARC64_PAGE_SIZE_4MB && !SPARC64_PAGE_SIZE_512KB
 	bool "512K"
 
 config HUGETLB_PAGE_SIZE_64K
-	depends on !SPARC64_PAGE_SIZE_4MB && !SPARC64_PAGE_SIZE_512KB && !SPARC64_PAGE_SIZE_64KB
+	depends on !SPARC64_PAGE_SIZE_64KB
 	bool "64K"
 
 endchoice
diff --git a/arch/sparc64/Makefile b/arch/sparc64/Makefile
index 4b8f2b08..b785a39 100644
--- a/arch/sparc64/Makefile
+++ b/arch/sparc64/Makefile
@@ -9,7 +9,9 @@
 
 CHECKFLAGS	+= -D__sparc__ -D__sparc_v9__ -m64
 
-CPPFLAGS_vmlinux.lds += -Usparc
+# Undefine sparc when processing vmlinux.lds - it is used
+# And teach CPP we are doing 64 bit builds (for this case)
+CPPFLAGS_vmlinux.lds += -m64 -Usparc
 
 LDFLAGS		:= -m elf64_sparc
 
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 76eb832..82cab5c 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.26-rc2
-# Fri May 16 13:36:07 2008
+# Linux kernel version: 2.6.26
+# Fri Jul 18 00:47:07 2008
 #
 CONFIG_SPARC=y
 CONFIG_SPARC64=y
@@ -22,18 +22,6 @@
 CONFIG_ARCH_NO_VIRT_TO_BUS=y
 CONFIG_OF=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
-CONFIG_SPARC64_PAGE_SIZE_8KB=y
-# CONFIG_SPARC64_PAGE_SIZE_64KB is not set
-# CONFIG_SPARC64_PAGE_SIZE_512KB is not set
-# CONFIG_SPARC64_PAGE_SIZE_4MB is not set
-CONFIG_SECCOMP=y
-CONFIG_HZ_100=y
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_300 is not set
-# CONFIG_HZ_1000 is not set
-CONFIG_HZ=100
-# CONFIG_SCHED_HRTICK is not set
-CONFIG_HOTPLUG_CPU=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -105,6 +93,7 @@
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 # CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_USE_GENERIC_SMP_HELPERS=y
 CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -121,6 +110,7 @@
 CONFIG_BLOCK=y
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_INTEGRITY is not set
 CONFIG_BLOCK_COMPAT=y
 
 #
@@ -136,11 +126,21 @@
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
 CONFIG_CLASSIC_RCU=y
-CONFIG_GENERIC_HARDIRQS=y
 
 #
-# General machine setup
+# Processor type and features
 #
+CONFIG_SPARC64_PAGE_SIZE_8KB=y
+# CONFIG_SPARC64_PAGE_SIZE_64KB is not set
+CONFIG_SECCOMP=y
+CONFIG_HZ_100=y
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_HOTPLUG_CPU=y
+CONFIG_GENERIC_HARDIRQS=y
 CONFIG_TICK_ONESHOT=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -342,6 +342,8 @@
 CONFIG_STANDALONE=y
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_DEBUG_DRIVER is not set
 # CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
@@ -366,6 +368,7 @@
 CONFIG_CDROM_PKTCDVD_WCACHE=y
 CONFIG_ATA_OVER_ETH=m
 CONFIG_SUNVDC=m
+# CONFIG_BLK_DEV_HD is not set
 CONFIG_MISC_DEVICES=y
 # CONFIG_PHANTOM is not set
 # CONFIG_EEPROM_93CX6 is not set
@@ -379,6 +382,7 @@
 #
 # Please see Documentation/ide/ide.txt for help/info on IDE drives
 #
+CONFIG_IDE_TIMINGS=y
 # CONFIG_BLK_DEV_IDE_SATA is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
@@ -429,8 +433,6 @@
 # CONFIG_BLK_DEV_VIA82CXXX is not set
 # CONFIG_BLK_DEV_TC86C001 is not set
 CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_BLK_DEV_HD_ONLY is not set
-# CONFIG_BLK_DEV_HD is not set
 
 #
 # SCSI device support
@@ -504,6 +506,7 @@
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SUNESP is not set
 # CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_DH is not set
 # CONFIG_ATA is not set
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=m
@@ -529,6 +532,10 @@
 #
 # IEEE 1394 (FireWire) support
 #
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
@@ -745,7 +752,8 @@
 CONFIG_UNIX98_PTYS=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_IPMI_HANDLER is not set
-# CONFIG_HW_RANDOM is not set
+CONFIG_HW_RANDOM=m
+CONFIG_HW_RANDOM_N2RNG=m
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
 # CONFIG_RAW_DRIVER is not set
@@ -759,38 +767,58 @@
 #
 # I2C Hardware Bus support
 #
+
+#
+# PC SMBus host controller drivers
+#
 # 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_ISCH is not set
 # CONFIG_I2C_PIIX4 is not set
 # CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_I2C_SIMTEC is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_TINY_USB is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
 # CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
 # CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
 
 #
 # Miscellaneous I2C Chip support
 #
 # CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
 # CONFIG_SENSORS_EEPROM is not set
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_PCF8591 is not set
 # CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
@@ -856,6 +884,7 @@
 # CONFIG_SENSORS_W83627EHF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 # CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
 
 #
@@ -985,15 +1014,7 @@
 # CONFIG_LOGO_LINUX_VGA16 is not set
 # CONFIG_LOGO_LINUX_CLUT224 is not set
 CONFIG_LOGO_SUN_CLUT224=y
-
-#
-# Sound
-#
 CONFIG_SOUND=m
-
-#
-# Advanced Linux Sound Architecture
-#
 CONFIG_SND=m
 CONFIG_SND_TIMER=m
 CONFIG_SND_PCM=m
@@ -1010,21 +1031,17 @@
 CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
+CONFIG_SND_VMASTER=y
 CONFIG_SND_MPU401_UART=m
 CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_DRIVERS=y
 CONFIG_SND_DUMMY=m
 CONFIG_SND_VIRMIDI=m
 CONFIG_SND_MTPAV=m
 # CONFIG_SND_SERIAL_U16550 is not set
 # CONFIG_SND_MPU401 is not set
-
-#
-# PCI devices
-#
+# CONFIG_SND_AC97_POWER_SAVE is not set
+CONFIG_SND_PCI=y
 # CONFIG_SND_AD1889 is not set
 # CONFIG_SND_ALS300 is not set
 CONFIG_SND_ALI5451=m
@@ -1084,37 +1101,14 @@
 # CONFIG_SND_VIRTUOSO is not set
 # CONFIG_SND_VX222 is not set
 # CONFIG_SND_YMFPCI is not set
-# CONFIG_SND_AC97_POWER_SAVE is not set
-
-#
-# USB devices
-#
+CONFIG_SND_USB=y
 # CONFIG_SND_USB_AUDIO is not set
 # CONFIG_SND_USB_CAIAQ is not set
-
-#
-# ALSA Sparc devices
-#
+CONFIG_SND_SPARC=y
 # CONFIG_SND_SUN_AMD7930 is not set
 CONFIG_SND_SUN_CS4231=m
 # CONFIG_SND_SUN_DBRI is not set
-
-#
-# System on Chip audio support
-#
 # CONFIG_SND_SOC is not set
-
-#
-# ALSA SoC audio for Freescale SOCs
-#
-
-#
-# SoC Audio for the Texas Instruments OMAP
-#
-
-#
-# Open Sound System
-#
 # CONFIG_SOUND_PRIME is not set
 CONFIG_AC97_BUS=m
 CONFIG_HID_SUPPORT=y
@@ -1167,6 +1161,7 @@
 #
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
 
 #
 # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -1226,6 +1221,7 @@
 # CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
 # CONFIG_USB_GADGET is not set
 # CONFIG_MMC is not set
 # CONFIG_MEMSTICK is not set
@@ -1420,6 +1416,12 @@
 # CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_LKDTM is not set
 # CONFIG_FAULT_INJECTION is not set
+CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+# CONFIG_FTRACE is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
@@ -1486,6 +1488,10 @@
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
 CONFIG_CRYPTO_SHA1=y
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
@@ -1527,6 +1533,7 @@
 # CONFIG_GENERIC_FIND_FIRST_BIT is not set
 CONFIG_CRC_CCITT=m
 CONFIG_CRC16=m
+# CONFIG_CRC_T10DIF is not set
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_CRC7 is not set
diff --git a/arch/sparc64/kernel/central.c b/arch/sparc64/kernel/central.c
index b61b8df..f2e87d0 100644
--- a/arch/sparc64/kernel/central.c
+++ b/arch/sparc64/kernel/central.c
@@ -16,8 +16,8 @@
 #include <asm/fhc.h>
 #include <asm/starfire.h>
 
-struct linux_central *central_bus = NULL;
-struct linux_fhc *fhc_list = NULL;
+static struct linux_central *central_bus = NULL;
+static struct linux_fhc *fhc_list = NULL;
 
 #define IS_CENTRAL_FHC(__fhc)	((__fhc) == central_bus->child)
 
@@ -79,9 +79,9 @@
 }
 
 /* Apply probed fhc ranges to registers passed, if no ranges return. */
-void apply_fhc_ranges(struct linux_fhc *fhc,
-		      struct linux_prom_registers *regs,
-		      int nregs)
+static void apply_fhc_ranges(struct linux_fhc *fhc,
+			     struct linux_prom_registers *regs,
+			     int nregs)
 {
 	if (fhc->num_fhc_ranges)
 		adjust_regs(regs, nregs, fhc->fhc_ranges,
@@ -89,8 +89,8 @@
 }
 
 /* Apply probed central ranges to registers passed, if no ranges return. */
-void apply_central_ranges(struct linux_central *central,
-			  struct linux_prom_registers *regs, int nregs)
+static void apply_central_ranges(struct linux_central *central,
+				 struct linux_prom_registers *regs, int nregs)
 {
 	if (central->num_central_ranges)
 		adjust_regs(regs, nregs, central->central_ranges,
diff --git a/arch/sparc64/kernel/ds.c b/arch/sparc64/kernel/ds.c
index edb74f5..d0fa5aa 100644
--- a/arch/sparc64/kernel/ds.c
+++ b/arch/sparc64/kernel/ds.c
@@ -159,7 +159,7 @@
 			struct ds_cap_state *cp,
 			void *buf, int len);
 
-struct ds_cap_state ds_states_template[] = {
+static struct ds_cap_state ds_states_template[] = {
 	{
 		.service_id	= "md-update",
 		.data		= md_update_data,
diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c
index c49d038..4d58d7c 100644
--- a/arch/sparc64/kernel/ebus.c
+++ b/arch/sparc64/kernel/ebus.c
@@ -401,7 +401,7 @@
 	dev->ofdev.node = dp;
 	dev->ofdev.dev.parent = &dev->bus->ofdev.dev;
 	dev->ofdev.dev.bus = &ebus_bus_type;
-	sprintf(dev->ofdev.dev.bus_id, "ebus[%08x]", dp->node);
+	dev_set_name(&dev->ofdev.dev, "ebus[%08x]", dp->node);
 
 	/* Register with core */
 	if (of_device_register(&dev->ofdev) != 0)
@@ -501,7 +501,7 @@
 		ebus->ofdev.node = dp;
 		ebus->ofdev.dev.parent = &pdev->dev;
 		ebus->ofdev.dev.bus = &ebus_bus_type;
-		sprintf(ebus->ofdev.dev.bus_id, "ebus%d", num_ebus);
+		dev_set_name(&ebus->ofdev.dev, "ebus%d", num_ebus);
 
 		/* Register with core */
 		if (of_device_register(&ebus->ofdev) != 0)
diff --git a/arch/sparc64/kernel/hvapi.c b/arch/sparc64/kernel/hvapi.c
index f34f5d6..691760b 100644
--- a/arch/sparc64/kernel/hvapi.c
+++ b/arch/sparc64/kernel/hvapi.c
@@ -34,8 +34,12 @@
 	{ .group = HV_GRP_LDOM,					},
 	{ .group = HV_GRP_SVC_CHAN,	.flags = FLAG_PRE_API	},
 	{ .group = HV_GRP_NCS,		.flags = FLAG_PRE_API	},
+	{ .group = HV_GRP_RNG,					},
 	{ .group = HV_GRP_NIAG_PERF,	.flags = FLAG_PRE_API	},
 	{ .group = HV_GRP_FIRE_PERF,				},
+	{ .group = HV_GRP_N2_CPU,				},
+	{ .group = HV_GRP_NIU,					},
+	{ .group = HV_GRP_VF_CPU,				},
 	{ .group = HV_GRP_DIAG,		.flags = FLAG_PRE_API	},
 };
 
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
index d569f60..4fd48ab 100644
--- a/arch/sparc64/kernel/of_device.c
+++ b/arch/sparc64/kernel/of_device.c
@@ -797,9 +797,9 @@
 	op->dev.parent = parent;
 	op->dev.bus = &of_platform_bus_type;
 	if (!parent)
-		strcpy(op->dev.bus_id, "root");
+		dev_set_name(&op->dev, "root");
 	else
-		sprintf(op->dev.bus_id, "%08x", dp->node);
+		dev_set_name(&op->dev, "%08x", dp->node);
 
 	if (of_device_register(op)) {
 		printk("%s: Could not register of device.\n",
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index d00a365..5509619 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -408,7 +408,7 @@
 	dev->class = class >> 8;
 	dev->revision = class & 0xff;
 
-	sprintf(dev->dev.bus_id, "%04x:%02x:%02x.%d", pci_domain_nr(bus),
+	dev_set_name(&dev->dev, "%04x:%02x:%02x.%d", pci_domain_nr(bus),
 		dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
 
 	if (ofpci_verbose)
diff --git a/arch/sparc64/kernel/pci_msi.c b/arch/sparc64/kernel/pci_msi.c
index db5e8fd..60c71e3 100644
--- a/arch/sparc64/kernel/pci_msi.c
+++ b/arch/sparc64/kernel/pci_msi.c
@@ -120,9 +120,9 @@
 	/* XXX affinity XXX */
 };
 
-int sparc64_setup_msi_irq(unsigned int *virt_irq_p,
-			  struct pci_dev *pdev,
-			  struct msi_desc *entry)
+static int sparc64_setup_msi_irq(unsigned int *virt_irq_p,
+				 struct pci_dev *pdev,
+				 struct msi_desc *entry)
 {
 	struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
 	const struct sparc64_msiq_ops *ops = pbm->msi_ops;
@@ -179,8 +179,8 @@
 	return err;
 }
 
-void sparc64_teardown_msi_irq(unsigned int virt_irq,
-			      struct pci_dev *pdev)
+static void sparc64_teardown_msi_irq(unsigned int virt_irq,
+				     struct pci_dev *pdev)
 {
 	struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
 	const struct sparc64_msiq_ops *ops = pbm->msi_ops;
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index e2bb979..a104c80 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -531,7 +531,7 @@
 	/* Nothing to do... */
 }
 
-const struct dma_ops sun4v_dma_ops = {
+static const struct dma_ops sun4v_dma_ops = {
 	.alloc_coherent			= dma_4v_alloc_coherent,
 	.free_coherent			= dma_4v_free_coherent,
 	.map_single			= dma_4v_map_single,
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index 2084f81..31ea752 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -15,7 +15,6 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
-#include <linux/kallsyms.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/smp.h>
@@ -211,7 +210,7 @@
 	printk("i4: %016lx i5: %016lx i6: %016lx i7: %016lx\n",
 	       rwk->ins[4], rwk->ins[5], rwk->ins[6], rwk->ins[7]);
 	if (regs->tstate & TSTATE_PRIV)
-		print_symbol("I7: <%s>\n", rwk->ins[7]);
+		printk("I7: <%pS>\n", (void *) rwk->ins[7]);
 }
 
 #ifdef CONFIG_SMP
@@ -232,7 +231,7 @@
 #endif
 	printk("TSTATE: %016lx TPC: %016lx TNPC: %016lx Y: %08x    %s\n", regs->tstate,
 	       regs->tpc, regs->tnpc, regs->y, print_tainted());
-	print_symbol("TPC: <%s>\n", regs->tpc);
+	printk("TPC: <%pS>\n", (void *) regs->tpc);
 	printk("g0: %016lx g1: %016lx g2: %016lx g3: %016lx\n",
 	       regs->u_regs[0], regs->u_regs[1], regs->u_regs[2],
 	       regs->u_regs[3]);
@@ -245,7 +244,7 @@
 	printk("o4: %016lx o5: %016lx sp: %016lx ret_pc: %016lx\n",
 	       regs->u_regs[12], regs->u_regs[13], regs->u_regs[14],
 	       regs->u_regs[15]);
-	print_symbol("RPC: <%s>\n", regs->u_regs[15]);
+	printk("RPC: <%pS>\n", (void *) regs->u_regs[15]);
 	show_regwindow(regs);
 #ifdef CONFIG_SMP
 	spin_unlock(&regdump_lock);
@@ -346,9 +345,6 @@
 {
 	struct thread_info *tp = current_thread_info();
 	struct pt_regs *regs = get_irq_regs();
-#ifdef CONFIG_KALLSYMS
-	char buffer[KSYM_SYMBOL_LEN];
-#endif
 	unsigned long flags;
 	int this_cpu, cpu;
 
@@ -377,17 +373,13 @@
 		       gp->tstate, gp->tpc, gp->tnpc,
 		       ((tp && tp->task) ? tp->task->comm : "NULL"),
 		       ((tp && tp->task) ? tp->task->pid : -1));
-#ifdef CONFIG_KALLSYMS
+
 		if (gp->tstate & TSTATE_PRIV) {
-			sprint_symbol(buffer, gp->tpc);
-			printk("             TPC[%s] ", buffer);
-			sprint_symbol(buffer, gp->o7);
-			printk("O7[%s] ", buffer);
-			sprint_symbol(buffer, gp->i7);
-			printk("I7[%s]\n", buffer);
-		} else
-#endif
-		{
+			printk("             TPC[%pS] O7[%pS] I7[%pS]\n",
+			       (void *) gp->tpc,
+			       (void *) gp->o7,
+			       (void *) gp->i7);
+		} else {
 			printk("             TPC[%lx] O7[%lx] I7[%lx]\n",
 			       gp->tpc, gp->o7, gp->i7);
 		}
@@ -691,9 +683,9 @@
 		  ((unsigned long) child_sf) - STACK_BIAS;
 
 		/* Special case, if we are spawning a kernel thread from
-		 * a userspace task (via KMOD, NFS, or similar) we must
-		 * disable performance counters in the child because the
-		 * address space and protection realm are changing.
+		 * a userspace task (usermode helper, NFS or similar), we
+		 * must disable performance counters in the child because
+		 * the address space and protection realm are changing.
 		 */
 		if (t->flags & _TIF_PERFCTR) {
 			t->user_cntd0 = t->user_cntd1 = NULL;
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index c099d96..7cf72b4 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -788,89 +788,36 @@
 			      0, 0, 0, mask);
 }
 
+extern unsigned long xcall_call_function;
+
+void arch_send_call_function_ipi(cpumask_t mask)
+{
+	smp_cross_call_masked(&xcall_call_function, 0, 0, 0, mask);
+}
+
+extern unsigned long xcall_call_function_single;
+
+void arch_send_call_function_single_ipi(int cpu)
+{
+	cpumask_t mask = cpumask_of_cpu(cpu);
+
+	smp_cross_call_masked(&xcall_call_function_single, 0, 0, 0, mask);
+}
+
 /* Send cross call to all processors except self. */
 #define smp_cross_call(func, ctx, data1, data2) \
 	smp_cross_call_masked(func, ctx, data1, data2, cpu_online_map)
 
-struct call_data_struct {
-	void (*func) (void *info);
-	void *info;
-	atomic_t finished;
-	int wait;
-};
-
-static struct call_data_struct *call_data;
-
-extern unsigned long xcall_call_function;
-
-/**
- * smp_call_function(): Run a function on all other CPUs.
- * @func: The function to run. This must be fast and non-blocking.
- * @info: An arbitrary pointer to pass to the function.
- * @wait: If true, wait (atomically) until function has completed on other CPUs.
- *
- * Returns 0 on success, else a negative status code. Does not return until
- * remote CPUs are nearly ready to execute <<func>> or are or have executed.
- *
- * You must not call this function with disabled interrupts or from a
- * hardware interrupt handler or from a bottom half handler.
- */
-static int sparc64_smp_call_function_mask(void (*func)(void *info), void *info,
-					  int wait, cpumask_t mask)
-{
-	struct call_data_struct data;
-	int cpus;
-
-	/* Can deadlock when called with interrupts disabled */
-	WARN_ON(irqs_disabled());
-
-	data.func = func;
-	data.info = info;
-	atomic_set(&data.finished, 0);
-	data.wait = wait;
-
-	spin_lock(&call_lock);
-
-	cpu_clear(smp_processor_id(), mask);
-	cpus = cpus_weight(mask);
-	if (!cpus)
-		goto out_unlock;
-
-	call_data = &data;
-	mb();
-
-	smp_cross_call_masked(&xcall_call_function, 0, 0, 0, mask);
-
-	/* Wait for response */
-	while (atomic_read(&data.finished) != cpus)
-		cpu_relax();
-
-out_unlock:
-	spin_unlock(&call_lock);
-
-	return 0;
-}
-
-int smp_call_function(void (*func)(void *info), void *info, int wait)
-{
-	return sparc64_smp_call_function_mask(func, info, wait, cpu_online_map);
-}
-
 void smp_call_function_client(int irq, struct pt_regs *regs)
 {
-	void (*func) (void *info) = call_data->func;
-	void *info = call_data->info;
-
 	clear_softint(1 << irq);
-	if (call_data->wait) {
-		/* let initiator proceed only after completion */
-		func(info);
-		atomic_inc(&call_data->finished);
-	} else {
-		/* let initiator proceed after getting data */
-		atomic_inc(&call_data->finished);
-		func(info);
-	}
+	generic_smp_call_function_interrupt();
+}
+
+void smp_call_function_single_client(int irq, struct pt_regs *regs)
+{
+	clear_softint(1 << irq);
+	generic_smp_call_function_single_interrupt();
 }
 
 static void tsb_sync(void *info)
@@ -890,7 +837,7 @@
 
 void smp_tsb_sync(struct mm_struct *mm)
 {
-	sparc64_smp_call_function_mask(tsb_sync, mm, 1, mm->cpu_vm_mask);
+	smp_call_function_mask(mm->cpu_vm_mask, tsb_sync, mm, 1);
 }
 
 extern unsigned long xcall_flush_tlb_mm;
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index 49d3ea50..504e678 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -108,8 +108,6 @@
 EXPORT_SYMBOL(__write_lock);
 EXPORT_SYMBOL(__write_unlock);
 EXPORT_SYMBOL(__write_trylock);
-
-EXPORT_SYMBOL(smp_call_function);
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_MCOUNT
diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
index ac1bff5..e1f4eba 100644
--- a/arch/sparc64/kernel/sys_sparc.c
+++ b/arch/sparc64/kernel/sys_sparc.c
@@ -542,7 +542,7 @@
 	return ret;
 }
 
-int sparc64_mmap_check(unsigned long addr, unsigned long len)
+int sparc_mmap_check(unsigned long addr, unsigned long len)
 {
 	if (test_thread_flag(TIF_32BIT)) {
 		if (len >= STACK_TOP32)
@@ -614,9 +614,9 @@
 		goto out;
 	if (unlikely(new_len >= VA_EXCLUDE_START))
 		goto out;
-	if (unlikely(sparc64_mmap_check(addr, old_len)))
+	if (unlikely(sparc_mmap_check(addr, old_len)))
 		goto out;
-	if (unlikely(sparc64_mmap_check(new_addr, new_len)))
+	if (unlikely(sparc_mmap_check(new_addr, new_len)))
 		goto out;
 
 	down_write(&current->mm->mmap_sem);
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index ba5bd62..97b77fb 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -359,7 +359,8 @@
 	return err;
 }
 
-int cp_compat_stat64(struct kstat *stat, struct compat_stat64 __user *statbuf)
+static int cp_compat_stat64(struct kstat *stat,
+			    struct compat_stat64 __user *statbuf)
 {
 	int err;
 
@@ -870,9 +871,9 @@
 	unsigned long ret = -EINVAL;
 	unsigned long new_addr = __new_addr;
 
-	if (unlikely(sparc64_mmap_check(addr, old_len)))
+	if (unlikely(sparc_mmap_check(addr, old_len)))
 		goto out;
-	if (unlikely(sparc64_mmap_check(new_addr, new_len)))
+	if (unlikely(sparc_mmap_check(new_addr, new_len)))
 		goto out;
 	down_write(&current->mm->mmap_sem);
 	ret = do_mremap(addr, old_len, new_len, flags, new_addr);
diff --git a/arch/sparc64/kernel/sysfs.c b/arch/sparc64/kernel/sysfs.c
index e885034..84e5ce1 100644
--- a/arch/sparc64/kernel/sysfs.c
+++ b/arch/sparc64/kernel/sysfs.c
@@ -14,7 +14,8 @@
 static DEFINE_PER_CPU(struct hv_mmu_statistics, mmu_stats) __attribute__((aligned(64)));
 
 #define SHOW_MMUSTAT_ULONG(NAME) \
-static ssize_t show_##NAME(struct sys_device *dev, char *buf) \
+static ssize_t show_##NAME(struct sys_device *dev, \
+			struct sysdev_attribute *attr, char *buf) \
 { \
 	struct hv_mmu_statistics *p = &per_cpu(mmu_stats, dev->id); \
 	return sprintf(buf, "%lu\n", p->NAME); \
@@ -135,13 +136,16 @@
 	return sun4v_mmustat_conf(ra, &orig_ra);
 }
 
-static ssize_t show_mmustat_enable(struct sys_device *s, char *buf)
+static ssize_t show_mmustat_enable(struct sys_device *s,
+				struct sysdev_attribute *attr, char *buf)
 {
 	unsigned long val = run_on_cpu(s->id, read_mmustat_enable, 0);
 	return sprintf(buf, "%lx\n", val);
 }
 
-static ssize_t store_mmustat_enable(struct sys_device *s, const char *buf, size_t count)
+static ssize_t store_mmustat_enable(struct sys_device *s,
+			struct sysdev_attribute *attr, const char *buf,
+			size_t count)
 {
 	unsigned long val, err;
 	int ret = sscanf(buf, "%ld", &val);
@@ -179,14 +183,16 @@
 #endif
 
 #define SHOW_CPUDATA_ULONG_NAME(NAME, MEMBER) \
-static ssize_t show_##NAME(struct sys_device *dev, char *buf) \
+static ssize_t show_##NAME(struct sys_device *dev, \
+		struct sysdev_attribute *attr, char *buf) \
 { \
 	cpuinfo_sparc *c = &cpu_data(dev->id); \
 	return sprintf(buf, "%lu\n", c->MEMBER); \
 }
 
 #define SHOW_CPUDATA_UINT_NAME(NAME, MEMBER) \
-static ssize_t show_##NAME(struct sys_device *dev, char *buf) \
+static ssize_t show_##NAME(struct sys_device *dev, \
+		struct sysdev_attribute *attr, char *buf) \
 { \
 	cpuinfo_sparc *c = &cpu_data(dev->id); \
 	return sprintf(buf, "%u\n", c->MEMBER); \
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 3697492..bd30ecb 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -1,6 +1,6 @@
 /* arch/sparc64/kernel/traps.c
  *
- * Copyright (C) 1995,1997 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1995,1997,2008 David S. Miller (davem@davemloft.net)
  * Copyright (C) 1997,1999,2000 Jakub Jelinek (jakub@redhat.com)
  */
 
@@ -11,7 +11,6 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
-#include <linux/kallsyms.h>
 #include <linux/signal.h>
 #include <linux/smp.h>
 #include <linux/mm.h>
@@ -37,9 +36,6 @@
 #include <asm/processor.h>
 #include <asm/timer.h>
 #include <asm/head.h>
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
 #include <asm/prom.h>
 
 #include "entry.h"
@@ -74,7 +70,7 @@
 		       i + 1,
 		       p->trapstack[i].tstate, p->trapstack[i].tpc,
 		       p->trapstack[i].tnpc, p->trapstack[i].tt);
-		print_symbol("TRAPLOG: TPC<%s>\n", p->trapstack[i].tpc);
+		printk("TRAPLOG: TPC<%pS>\n", (void *) p->trapstack[i].tpc);
 	}
 }
 
@@ -1081,7 +1077,7 @@
 	       regs->tpc, regs->tnpc, regs->u_regs[UREG_I7], regs->tstate);
 	printk("%s" "ERROR(%d): ",
 	       (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id());
-	print_symbol("TPC<%s>\n", regs->tpc);
+	printk("TPC<%pS>\n", (void *) regs->tpc);
 	printk("%s" "ERROR(%d): M_SYND(%lx),  E_SYND(%lx)%s%s\n",
 	       (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
 	       (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT,
@@ -1689,7 +1685,7 @@
 		       smp_processor_id(),
 		       (type & 0x1) ? 'I' : 'D',
 		       regs->tpc);
-		print_symbol(KERN_EMERG "TPC<%s>\n", regs->tpc);
+		printk(KERN_EMERG "TPC<%pS>\n", (void *) regs->tpc);
 		panic("Irrecoverable Cheetah+ parity error.");
 	}
 
@@ -1697,7 +1693,7 @@
 	       smp_processor_id(),
 	       (type & 0x1) ? 'I' : 'D',
 	       regs->tpc);
-	print_symbol(KERN_WARNING "TPC<%s>\n", regs->tpc);
+	printk(KERN_WARNING "TPC<%pS>\n", (void *) regs->tpc);
 }
 
 struct sun4v_error_entry {
@@ -1904,9 +1900,10 @@
 
 	printk(KERN_EMERG "SUN4V-ITLB: Error at TPC[%lx], tl %d\n",
 	       regs->tpc, tl);
-	print_symbol(KERN_EMERG "SUN4V-ITLB: TPC<%s>\n", regs->tpc);
+	printk(KERN_EMERG "SUN4V-ITLB: TPC<%pS>\n", (void *) regs->tpc);
 	printk(KERN_EMERG "SUN4V-ITLB: O7[%lx]\n", regs->u_regs[UREG_I7]);
-	print_symbol(KERN_EMERG "SUN4V-ITLB: O7<%s>\n", regs->u_regs[UREG_I7]);
+	printk(KERN_EMERG "SUN4V-ITLB: O7<%pS>\n",
+	       (void *) regs->u_regs[UREG_I7]);
 	printk(KERN_EMERG "SUN4V-ITLB: vaddr[%lx] ctx[%lx] "
 	       "pte[%lx] error[%lx]\n",
 	       sun4v_err_itlb_vaddr, sun4v_err_itlb_ctx,
@@ -1927,9 +1924,10 @@
 
 	printk(KERN_EMERG "SUN4V-DTLB: Error at TPC[%lx], tl %d\n",
 	       regs->tpc, tl);
-	print_symbol(KERN_EMERG "SUN4V-DTLB: TPC<%s>\n", regs->tpc);
+	printk(KERN_EMERG "SUN4V-DTLB: TPC<%pS>\n", (void *) regs->tpc);
 	printk(KERN_EMERG "SUN4V-DTLB: O7[%lx]\n", regs->u_regs[UREG_I7]);
-	print_symbol(KERN_EMERG "SUN4V-DTLB: O7<%s>\n", regs->u_regs[UREG_I7]);
+	printk(KERN_EMERG "SUN4V-DTLB: O7<%pS>\n",
+	       (void *) regs->u_regs[UREG_I7]);
 	printk(KERN_EMERG "SUN4V-DTLB: vaddr[%lx] ctx[%lx] "
 	       "pte[%lx] error[%lx]\n",
 	       sun4v_err_dtlb_vaddr, sun4v_err_dtlb_ctx,
@@ -2111,10 +2109,7 @@
 	fp = ksp + STACK_BIAS;
 	thread_base = (unsigned long) tp;
 
-	printk("Call Trace:");
-#ifdef CONFIG_KALLSYMS
-	printk("\n");
-#endif
+	printk("Call Trace:\n");
 	do {
 		struct sparc_stackf *sf;
 		struct pt_regs *regs;
@@ -2137,12 +2132,8 @@
 			fp = (unsigned long)sf->fp + STACK_BIAS;
 		}
 
-		printk(" [%016lx] ", pc);
-		print_symbol("%s\n", pc);
+		printk(" [%016lx] %pS\n", pc, (void *) pc);
 	} while (++count < 16);
-#ifndef CONFIG_KALLSYMS
-	printk("\n");
-#endif
 }
 
 void dump_stack(void)
@@ -2211,9 +2202,8 @@
 		while (rw &&
 		       count++ < 30&&
 		       is_kernel_stack(current, rw)) {
-			printk("Caller[%016lx]", rw->ins[7]);
-			print_symbol(": %s", rw->ins[7]);
-			printk("\n");
+			printk("Caller[%016lx]: %pS\n", rw->ins[7],
+			       (void *) rw->ins[7]);
 
 			rw = kernel_stack_up(rw);
 		}
diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S
index 450053a..1ade3d6 100644
--- a/arch/sparc64/kernel/ttable.S
+++ b/arch/sparc64/kernel/ttable.S
@@ -58,7 +58,12 @@
 tl0_irq4:	BTRAP(0x44)
 #endif
 tl0_irq5:	TRAP_IRQ(handler_irq, 5)
-tl0_irq6:	BTRAP(0x46) BTRAP(0x47) BTRAP(0x48) BTRAP(0x49)
+#ifdef CONFIG_SMP
+tl0_irq6:	TRAP_IRQ(smp_call_function_single_client, 6)
+#else
+tl0_irq6:	BTRAP(0x46)
+#endif
+tl0_irq7:	BTRAP(0x47) BTRAP(0x48) BTRAP(0x49)
 tl0_irq10:	BTRAP(0x4a) BTRAP(0x4b) BTRAP(0x4c) BTRAP(0x4d)
 tl0_irq14:	TRAP_IRQ(timer_interrupt, 14)
 tl0_irq15:	TRAP_IRQ(handler_irq, 15)
diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c
index afa7fc4..203ddfa 100644
--- a/arch/sparc64/kernel/unaligned.c
+++ b/arch/sparc64/kernel/unaligned.c
@@ -2,7 +2,7 @@
  * unaligned.c: Unaligned load/store trap handling with special
  *              cases for the kernel to do them more quickly.
  *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996,2008 David S. Miller (davem@davemloft.net)
  * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  */
 
@@ -20,7 +20,6 @@
 #include <asm/uaccess.h>
 #include <linux/smp.h>
 #include <linux/bitops.h>
-#include <linux/kallsyms.h>
 #include <asm/fpumacro.h>
 
 /* #define DEBUG_MNA */
@@ -289,8 +288,8 @@
 	if (count < 5) {
 		last_time = jiffies;
 		count++;
-		printk("Kernel unaligned access at TPC[%lx] ", regs->tpc);
-		print_symbol("%s\n", regs->tpc);
+		printk("Kernel unaligned access at TPC[%lx] %pS\n",
+		       regs->tpc, (void *) regs->tpc);
 	}
 }
 
diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c
index e78b351..a490077 100644
--- a/arch/sparc64/kernel/vio.c
+++ b/arch/sparc64/kernel/vio.c
@@ -224,7 +224,7 @@
 	if (!strcmp(type, "domain-services-port"))
 		bus_id_name = "ds";
 
-	if (strlen(bus_id_name) >= KOBJ_NAME_LEN - 4) {
+	if (strlen(bus_id_name) >= BUS_ID_SIZE - 4) {
 		printk(KERN_ERR "VIO: bus_id_name [%s] is too long.\n",
 		       bus_id_name);
 		return NULL;
@@ -260,16 +260,14 @@
 	vio_fill_channel_info(hp, mp, vdev);
 
 	if (!id) {
-		snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s",
-			 bus_id_name);
+		dev_set_name(&vdev->dev, "%s", bus_id_name);
 		vdev->dev_no = ~(u64)0;
 	} else if (!cfg_handle) {
-		snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s-%lu",
-			 bus_id_name, *id);
+		dev_set_name(&vdev->dev, "%s-%lu", bus_id_name, *id);
 		vdev->dev_no = *id;
 	} else {
-		snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s-%lu-%lu",
-			 bus_id_name, *cfg_handle, *id);
+		dev_set_name(&vdev->dev, "%s-%lu-%lu", bus_id_name,
+			     *cfg_handle, *id);
 		vdev->dev_no = *cfg_handle;
 	}
 
@@ -292,12 +290,12 @@
 	}
 	vdev->dp = dp;
 
-	printk(KERN_INFO "VIO: Adding device %s\n", vdev->dev.bus_id);
+	printk(KERN_INFO "VIO: Adding device %s\n", dev_name(&vdev->dev));
 
 	err = device_register(&vdev->dev);
 	if (err) {
 		printk(KERN_ERR "VIO: Could not register device %s, err=%d\n",
-		       vdev->dev.bus_id, err);
+		       dev_name(&vdev->dev), err);
 		kfree(vdev);
 		return NULL;
 	}
@@ -330,7 +328,7 @@
 	dev = device_find_child(&root_vdev->dev, (void *) node,
 				vio_md_node_match);
 	if (dev) {
-		printk(KERN_INFO "VIO: Removing device %s\n", dev->bus_id);
+		printk(KERN_INFO "VIO: Removing device %s\n", dev_name(dev));
 
 		device_unregister(dev);
 	}
diff --git a/arch/sparc64/lib/copy_page.S b/arch/sparc64/lib/copy_page.S
index 3746066..b243d3b 100644
--- a/arch/sparc64/lib/copy_page.S
+++ b/arch/sparc64/lib/copy_page.S
@@ -25,9 +25,9 @@
 
 #define	DCACHE_SIZE	(PAGE_SIZE * 2)
 
-#if (PAGE_SHIFT == 13) || (PAGE_SHIFT == 19)
+#if (PAGE_SHIFT == 13)
 #define PAGE_SIZE_REM	0x80
-#elif (PAGE_SHIFT == 16) || (PAGE_SHIFT == 22)
+#elif (PAGE_SHIFT == 16)
 #define PAGE_SIZE_REM	0x100
 #else
 #error Wrong PAGE_SHIFT specified
@@ -198,7 +198,7 @@
 	cmp		%o2, PAGE_SIZE_REM
 	bne,pt		%xcc, 1b
 	 add		%o0, 0x40, %o0
-#if (PAGE_SHIFT == 16) || (PAGE_SHIFT == 22)
+#if (PAGE_SHIFT == 16)
 	TOUCH(f0, f2, f4, f6, f8, f10, f12, f14)
 	ldda		[%o1] ASI_BLK_P, %f32
 	stda		%f48, [%o0] %asi
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index 236f4d2..ea7d7ae 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -1,7 +1,7 @@
 /*
  * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc.
  *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996, 2008 David S. Miller (davem@davemloft.net)
  * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
  */
 
@@ -18,7 +18,6 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/kprobes.h>
-#include <linux/kallsyms.h>
 #include <linux/kdebug.h>
 
 #include <asm/page.h>
@@ -115,7 +114,7 @@
 	printk(KERN_CRIT "OOPS: Bogus kernel PC [%016lx] in fault handler\n",
 	       regs->tpc);
 	printk(KERN_CRIT "OOPS: RPC [%016lx]\n", regs->u_regs[15]);
-	print_symbol("RPC: <%s>\n", regs->u_regs[15]);
+	printk("OOPS: RPC <%pS>\n", (void *) regs->u_regs[15]);
 	printk(KERN_CRIT "OOPS: Fault was to vaddr[%lx]\n", vaddr);
 	dump_stack();
 	unhandled_fault(regs->tpc, current, regs);
diff --git a/arch/sparc64/mm/tsb.c b/arch/sparc64/mm/tsb.c
index fe70c8a..3547937 100644
--- a/arch/sparc64/mm/tsb.c
+++ b/arch/sparc64/mm/tsb.c
@@ -96,12 +96,6 @@
 #elif defined(CONFIG_SPARC64_PAGE_SIZE_64KB)
 #define HV_PGSZ_IDX_BASE	HV_PGSZ_IDX_64K
 #define HV_PGSZ_MASK_BASE	HV_PGSZ_MASK_64K
-#elif defined(CONFIG_SPARC64_PAGE_SIZE_512KB)
-#define HV_PGSZ_IDX_BASE	HV_PGSZ_IDX_512K
-#define HV_PGSZ_MASK_BASE	HV_PGSZ_MASK_512K
-#elif defined(CONFIG_SPARC64_PAGE_SIZE_4MB)
-#define HV_PGSZ_IDX_BASE	HV_PGSZ_IDX_4MB
-#define HV_PGSZ_MASK_BASE	HV_PGSZ_MASK_4MB
 #else
 #error Broken base page size setting...
 #endif
diff --git a/arch/sparc64/mm/ultra.S b/arch/sparc64/mm/ultra.S
index 9bb2d90..4c8ca13 100644
--- a/arch/sparc64/mm/ultra.S
+++ b/arch/sparc64/mm/ultra.S
@@ -688,6 +688,11 @@
 	wr		%g0, (1 << PIL_SMP_CALL_FUNC), %set_softint
 	retry
 
+	.globl		xcall_call_function_single
+xcall_call_function_single:
+	wr		%g0, (1 << PIL_SMP_CALL_FUNC_SNGL), %set_softint
+	retry
+
 	.globl		xcall_receive_signal
 xcall_receive_signal:
 	wr		%g0, (1 << PIL_SMP_RECEIVE_SIGNAL), %set_softint
diff --git a/arch/um/include/init.h b/arch/um/include/init.h
index b00a9574..37dd097 100644
--- a/arch/um/include/init.h
+++ b/arch/um/include/init.h
@@ -45,6 +45,8 @@
 # define __section(S) __attribute__ ((__section__(#S)))
 #endif
 
+#if __GNUC__ == 3
+
 #if __GNUC_MINOR__ >= 3
 # define __used			__attribute__((__used__))
 #else
@@ -52,6 +54,12 @@
 #endif
 
 #else
+#if __GNUC__ == 4
+# define __used			__attribute__((__used__))
+#endif
+#endif
+
+#else
 #include <linux/compiler.h>
 #endif
 /* These are for everybody (although not all archs will actually
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 96e0c2e..03980cb 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -447,7 +447,6 @@
 
 config MEMTEST
 	bool "Memtest"
-	depends on X86_64
 	help
 	  This option adds a kernel parameter 'memtest', which allows memtest
 	  to be set.
diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu
index abff1b8..2c518fb 100644
--- a/arch/x86/Kconfig.cpu
+++ b/arch/x86/Kconfig.cpu
@@ -362,10 +362,6 @@
 	def_bool y
 	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
 
-config X86_GOOD_APIC
-	def_bool y
-	depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 || MEFFICEON || MCORE2 || MVIAC7 || X86_64
-
 config X86_INTEL_USERCOPY
 	def_bool y
 	depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 || MEFFICEON || MCORE2
@@ -418,4 +414,4 @@
 
 config X86_DEBUGCTLMSR
 	def_bool y
-	depends on !(M586MMX || M586TSC || M586 || M486 || M386)
+	depends on !(MK6 || MWINCHIPC6 || MWINCHIP2 || MWINCHIP3D || MCYRIXIII || M586MMX || M586TSC || M586 || M486 || M386)
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index ae36bfa..092f019 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -5,13 +5,15 @@
 
 source "lib/Kconfig.debug"
 
-config NONPROMISC_DEVMEM
+config STRICT_DEVMEM
 	bool "Filter access to /dev/mem"
 	help
-	  If this option is left off, you allow userspace access to all
+	  If this option is disabled, you allow userspace (root) access to all
 	  of memory, including kernel and userspace memory. Accidental
 	  access to this is obviously disastrous, but specific access can
-	  be used by people debugging the kernel.
+	  be used by people debugging the kernel. Note that with PAT support
+	  enabled, even in this case there are restrictions on /dev/mem
+	  use due to the cache aliasing requirements.
 
 	  If this option is switched on, the /dev/mem file only allows
 	  userspace access to PCI space and the BIOS code and data regions.
@@ -287,7 +289,6 @@
 
 config OPTIMIZE_INLINING
 	bool "Allow gcc to uninline functions marked 'inline'"
-	depends on BROKEN
 	help
 	  This option determines if the kernel forces gcc to inline the functions
 	  developers have marked 'inline'. Doing so takes away freedom from gcc to
@@ -298,5 +299,7 @@
 	  become the default in the future, until then this option is there to
 	  test gcc for this.
 
+	  If unsure, say N.
+
 endmenu
 
diff --git a/arch/x86/boot/edd.c b/arch/x86/boot/edd.c
index 03399d6..d93cbc6 100644
--- a/arch/x86/boot/edd.c
+++ b/arch/x86/boot/edd.c
@@ -167,9 +167,8 @@
 		 * Scan the BIOS-supported hard disks and query EDD
 		 * information...
 		 */
-		get_edd_info(devno, &ei);
-
-		if (boot_params.eddbuf_entries < EDDMAXNR) {
+		if (!get_edd_info(devno, &ei)
+		    && boot_params.eddbuf_entries < EDDMAXNR) {
 			memcpy(edp, &ei, sizeof ei);
 			edp++;
 			boot_params.eddbuf_entries++;
diff --git a/arch/x86/boot/pm.c b/arch/x86/boot/pm.c
index 328956f..85a1cd8 100644
--- a/arch/x86/boot/pm.c
+++ b/arch/x86/boot/pm.c
@@ -98,12 +98,6 @@
 /*
  * Set up the GDT
  */
-#define GDT_ENTRY(flags, base, limit)		\
-	(((u64)(base & 0xff000000) << 32) |	\
-	 ((u64)flags << 40) |			\
-	 ((u64)(limit & 0x00ff0000) << 32) |	\
-	 ((u64)(base & 0x00ffffff) << 16) |	\
-	 ((u64)(limit & 0x0000ffff)))
 
 struct gdt_ptr {
 	u16 len;
diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig
index 9bc34e2..4d73f53 100644
--- a/arch/x86/configs/i386_defconfig
+++ b/arch/x86/configs/i386_defconfig
@@ -2047,7 +2047,7 @@
 # CONFIG_SAMPLES is not set
 # CONFIG_KGDB is not set
 CONFIG_HAVE_ARCH_KGDB=y
-# CONFIG_NONPROMISC_DEVMEM is not set
+# CONFIG_STRICT_DEVMEM is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DEBUG_STACK_USAGE=y
diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig
index ae5124e..a404524 100644
--- a/arch/x86/configs/x86_64_defconfig
+++ b/arch/x86/configs/x86_64_defconfig
@@ -2012,7 +2012,7 @@
 # CONFIG_SAMPLES is not set
 # CONFIG_KGDB is not set
 CONFIG_HAVE_ARCH_KGDB=y
-# CONFIG_NONPROMISC_DEVMEM is not set
+# CONFIG_STRICT_DEVMEM is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DEBUG_STACK_USAGE=y
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
index cb3856a..20af4c7 100644
--- a/arch/x86/ia32/ia32_signal.c
+++ b/arch/x86/ia32/ia32_signal.c
@@ -36,6 +36,11 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
+#define FIX_EFLAGS	(X86_EFLAGS_AC | X86_EFLAGS_OF | \
+			 X86_EFLAGS_DF | X86_EFLAGS_TF | X86_EFLAGS_SF | \
+			 X86_EFLAGS_ZF | X86_EFLAGS_AF | X86_EFLAGS_PF | \
+			 X86_EFLAGS_CF)
+
 asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
 void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
 
@@ -248,7 +253,7 @@
 	regs->ss |= 3;
 
 	err |= __get_user(tmpflags, &sc->flags);
-	regs->flags = (regs->flags & ~0x40DD5) | (tmpflags & 0x40DD5);
+	regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
 	/* disable syscall checks */
 	regs->orig_ax = -1;
 
@@ -515,7 +520,6 @@
 			compat_sigset_t *set, struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame;
-	struct exec_domain *ed = current_thread_info()->exec_domain;
 	void __user *restorer;
 	int err = 0;
 
@@ -538,8 +542,7 @@
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		goto give_sigsegv;
 
-	err |= __put_user((ed && ed->signal_invmap && sig < 32
-			   ? ed->signal_invmap[sig] : sig), &frame->sig);
+	err |= __put_user(sig, &frame->sig);
 	err |= __put_user(ptr_to_compat(&frame->info), &frame->pinfo);
 	err |= __put_user(ptr_to_compat(&frame->uc), &frame->puc);
 	err |= copy_siginfo_to_user32(&frame->info, info);
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 20371d0..23d146c 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -37,6 +37,11 @@
 	movq	%rax,R8(%rsp)
 	.endm
 
+	/*
+	 * Reload arg registers from stack in case ptrace changed them.
+	 * We don't reload %eax because syscall_trace_enter() returned
+	 * the value it wants us to use in the table lookup.
+	 */
 	.macro LOAD_ARGS32 offset
 	movl \offset(%rsp),%r11d
 	movl \offset+8(%rsp),%r10d
@@ -46,7 +51,6 @@
 	movl \offset+48(%rsp),%edx
 	movl \offset+56(%rsp),%esi
 	movl \offset+64(%rsp),%edi
-	movl \offset+72(%rsp),%eax
 	.endm
 	
 	.macro CFI_STARTPROC32 simple
@@ -137,13 +141,12 @@
  	.previous	
 	GET_THREAD_INFO(%r10)
 	orl    $TS_COMPAT,TI_status(%r10)
-	testl  $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP), \
-		 TI_flags(%r10)
+	testl  $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
 	CFI_REMEMBER_STATE
 	jnz  sysenter_tracesys
-sysenter_do_call:	
 	cmpl	$(IA32_NR_syscalls-1),%eax
 	ja	ia32_badsys
+sysenter_do_call:
 	IA32_ARG_FIXUP 1
 	call	*ia32_sys_call_table(,%rax,8)
 	movq	%rax,RAX-ARGOFFSET(%rsp)
@@ -242,8 +245,7 @@
 	.previous	
 	GET_THREAD_INFO(%r10)
 	orl   $TS_COMPAT,TI_status(%r10)
-	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP), \
-		TI_flags(%r10)
+	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
 	CFI_REMEMBER_STATE
 	jnz   cstar_tracesys
 cstar_do_call:	
@@ -321,6 +323,7 @@
 	/*CFI_REL_OFFSET	rflags,EFLAGS-RIP*/
 	/*CFI_REL_OFFSET	cs,CS-RIP*/
 	CFI_REL_OFFSET	rip,RIP-RIP
+	PARAVIRT_ADJUST_EXCEPTION_FRAME
 	SWAPGS
 	/*
 	 * No need to follow this irqs on/off section: the syscall
@@ -336,8 +339,7 @@
 	SAVE_ARGS 0,0,1
 	GET_THREAD_INFO(%r10)
 	orl   $TS_COMPAT,TI_status(%r10)
-	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP), \
-		TI_flags(%r10)
+	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
 	jnz ia32_tracesys
 ia32_do_syscall:	
 	cmpl $(IA32_NR_syscalls-1),%eax
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index da14061..3db651f 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -7,9 +7,10 @@
 CPPFLAGS_vmlinux.lds += -U$(UTS_MACHINE)
 
 ifdef CONFIG_FTRACE
-# Do not profile debug utilities
+# Do not profile debug and lowlevel utilities
 CFLAGS_REMOVE_tsc.o = -pg
 CFLAGS_REMOVE_rtc.o = -pg
+CFLAGS_REMOVE_paravirt.o = -pg
 endif
 
 #
@@ -102,6 +103,7 @@
 # 64 bit specific files
 ifeq ($(CONFIG_X86_64),y)
         obj-y				+= genapic_64.o genapic_flat_64.o genx2apic_uv_x.o tlb_uv.o
+	obj-y				+= bios_uv.o
         obj-$(CONFIG_X86_PM_TIMER)	+= pmtimer_64.o
         obj-$(CONFIG_AUDIT)		+= audit_64.o
 
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index f489d7a..fa88a1d 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -1021,7 +1021,7 @@
 	mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA;
 #endif
 	set_bit(MP_ISA_BUS, mp_bus_not_pci);
-	Dprintk("Bus #%d is ISA\n", MP_ISA_BUS);
+	pr_debug("Bus #%d is ISA\n", MP_ISA_BUS);
 
 #ifdef CONFIG_X86_ES7000
 	/*
@@ -1127,8 +1127,8 @@
 		return gsi;
 	}
 	if (test_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed)) {
-		Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
-			mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
+		pr_debug(KERN_DEBUG "Pin %d-%d already programmed\n",
+			 mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
 #ifdef CONFIG_X86_32
 		return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]);
 #else
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
index 868de3d..a3ddad1 100644
--- a/arch/x86/kernel/acpi/sleep.c
+++ b/arch/x86/kernel/acpi/sleep.c
@@ -9,6 +9,7 @@
 #include <linux/bootmem.h>
 #include <linux/dmi.h>
 #include <linux/cpumask.h>
+#include <asm/segment.h>
 
 #include "realmode/wakeup.h"
 #include "sleep.h"
@@ -23,15 +24,6 @@
 static char temp_stack[10240];
 #endif
 
-/* XXX: this macro should move to asm-x86/segment.h and be shared with the
-   boot code... */
-#define GDT_ENTRY(flags, base, limit)		\
-	(((u64)(base & 0xff000000) << 32) |	\
-	 ((u64)flags << 40) |			\
-	 ((u64)(limit & 0x00ff0000) << 32) |	\
-	 ((u64)(base & 0x00ffffff) << 16) |	\
-	 ((u64)(limit & 0x0000ffff)))
-
 /**
  * acpi_save_state_mem - save kernel state
  *
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index f2766d8..c25210e 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -23,7 +23,7 @@
 #include <linux/scatterlist.h>
 #include <linux/iommu-helper.h>
 #include <asm/proto.h>
-#include <asm/gart.h>
+#include <asm/iommu.h>
 #include <asm/amd_iommu_types.h>
 #include <asm/amd_iommu.h>
 
@@ -32,21 +32,37 @@
 #define to_pages(addr, size) \
 	 (round_up(((addr) & ~PAGE_MASK) + (size), PAGE_SIZE) >> PAGE_SHIFT)
 
+#define EXIT_LOOP_COUNT 10000000
+
 static DEFINE_RWLOCK(amd_iommu_devtable_lock);
 
-struct command {
+/*
+ * general struct to manage commands send to an IOMMU
+ */
+struct iommu_cmd {
 	u32 data[4];
 };
 
 static int dma_ops_unity_map(struct dma_ops_domain *dma_dom,
 			     struct unity_map_entry *e);
 
+/* returns !0 if the IOMMU is caching non-present entries in its TLB */
 static int iommu_has_npcache(struct amd_iommu *iommu)
 {
 	return iommu->cap & IOMMU_CAP_NPCACHE;
 }
 
-static int __iommu_queue_command(struct amd_iommu *iommu, struct command *cmd)
+/****************************************************************************
+ *
+ * IOMMU command queuing functions
+ *
+ ****************************************************************************/
+
+/*
+ * Writes the command to the IOMMUs command buffer and informs the
+ * hardware about the new command. Must be called with iommu->lock held.
+ */
+static int __iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
 {
 	u32 tail, head;
 	u8 *target;
@@ -63,7 +79,11 @@
 	return 0;
 }
 
-static int iommu_queue_command(struct amd_iommu *iommu, struct command *cmd)
+/*
+ * General queuing function for commands. Takes iommu->lock and calls
+ * __iommu_queue_command().
+ */
+static int iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
 {
 	unsigned long flags;
 	int ret;
@@ -75,16 +95,24 @@
 	return ret;
 }
 
+/*
+ * This function is called whenever we need to ensure that the IOMMU has
+ * completed execution of all commands we sent. It sends a
+ * COMPLETION_WAIT command and waits for it to finish. The IOMMU informs
+ * us about that by writing a value to a physical address we pass with
+ * the command.
+ */
 static int iommu_completion_wait(struct amd_iommu *iommu)
 {
 	int ret;
-	struct command cmd;
+	struct iommu_cmd cmd;
 	volatile u64 ready = 0;
 	unsigned long ready_phys = virt_to_phys(&ready);
+	unsigned long i = 0;
 
 	memset(&cmd, 0, sizeof(cmd));
 	cmd.data[0] = LOW_U32(ready_phys) | CMD_COMPL_WAIT_STORE_MASK;
-	cmd.data[1] = HIGH_U32(ready_phys);
+	cmd.data[1] = upper_32_bits(ready_phys);
 	cmd.data[2] = 1; /* value written to 'ready' */
 	CMD_SET_TYPE(&cmd, CMD_COMPL_WAIT);
 
@@ -95,15 +123,23 @@
 	if (ret)
 		return ret;
 
-	while (!ready)
+	while (!ready && (i < EXIT_LOOP_COUNT)) {
+		++i;
 		cpu_relax();
+	}
+
+	if (unlikely((i == EXIT_LOOP_COUNT) && printk_ratelimit()))
+		printk(KERN_WARNING "AMD IOMMU: Completion wait loop failed\n");
 
 	return 0;
 }
 
+/*
+ * Command send function for invalidating a device table entry
+ */
 static int iommu_queue_inv_dev_entry(struct amd_iommu *iommu, u16 devid)
 {
-	struct command cmd;
+	struct iommu_cmd cmd;
 
 	BUG_ON(iommu == NULL);
 
@@ -116,20 +152,23 @@
 	return iommu_queue_command(iommu, &cmd);
 }
 
+/*
+ * Generic command send function for invalidaing TLB entries
+ */
 static int iommu_queue_inv_iommu_pages(struct amd_iommu *iommu,
 		u64 address, u16 domid, int pde, int s)
 {
-	struct command cmd;
+	struct iommu_cmd cmd;
 
 	memset(&cmd, 0, sizeof(cmd));
 	address &= PAGE_MASK;
 	CMD_SET_TYPE(&cmd, CMD_INV_IOMMU_PAGES);
 	cmd.data[1] |= domid;
 	cmd.data[2] = LOW_U32(address);
-	cmd.data[3] = HIGH_U32(address);
-	if (s)
+	cmd.data[3] = upper_32_bits(address);
+	if (s) /* size bit - we flush more than one 4kb page */
 		cmd.data[2] |= CMD_INV_IOMMU_PAGES_SIZE_MASK;
-	if (pde)
+	if (pde) /* PDE bit - we wan't flush everything not only the PTEs */
 		cmd.data[2] |= CMD_INV_IOMMU_PAGES_PDE_MASK;
 
 	iommu->need_sync = 1;
@@ -137,6 +176,11 @@
 	return iommu_queue_command(iommu, &cmd);
 }
 
+/*
+ * TLB invalidation function which is called from the mapping functions.
+ * It invalidates a single PTE if the range to flush is within a single
+ * page. Otherwise it flushes the whole TLB of the IOMMU.
+ */
 static int iommu_flush_pages(struct amd_iommu *iommu, u16 domid,
 		u64 address, size_t size)
 {
@@ -159,6 +203,20 @@
 	return 0;
 }
 
+/****************************************************************************
+ *
+ * The functions below are used the create the page table mappings for
+ * unity mapped regions.
+ *
+ ****************************************************************************/
+
+/*
+ * Generic mapping functions. It maps a physical address into a DMA
+ * address space. It allocates the page table pages if necessary.
+ * In the future it can be extended to a generic mapping function
+ * supporting all features of AMD IOMMU page tables like level skipping
+ * and full 64 bit address spaces.
+ */
 static int iommu_map(struct protection_domain *dom,
 		     unsigned long bus_addr,
 		     unsigned long phys_addr,
@@ -209,6 +267,10 @@
 	return 0;
 }
 
+/*
+ * This function checks if a specific unity mapping entry is needed for
+ * this specific IOMMU.
+ */
 static int iommu_for_unity_map(struct amd_iommu *iommu,
 			       struct unity_map_entry *entry)
 {
@@ -223,6 +285,12 @@
 	return 0;
 }
 
+/*
+ * Init the unity mappings for a specific IOMMU in the system
+ *
+ * Basically iterates over all unity mapping entries and applies them to
+ * the default domain DMA of that IOMMU if necessary.
+ */
 static int iommu_init_unity_mappings(struct amd_iommu *iommu)
 {
 	struct unity_map_entry *entry;
@@ -239,6 +307,10 @@
 	return 0;
 }
 
+/*
+ * This function actually applies the mapping to the page table of the
+ * dma_ops domain.
+ */
 static int dma_ops_unity_map(struct dma_ops_domain *dma_dom,
 			     struct unity_map_entry *e)
 {
@@ -261,6 +333,9 @@
 	return 0;
 }
 
+/*
+ * Inits the unity mappings required for a specific device
+ */
 static int init_unity_mappings_for_device(struct dma_ops_domain *dma_dom,
 					  u16 devid)
 {
@@ -278,12 +353,26 @@
 	return 0;
 }
 
+/****************************************************************************
+ *
+ * The next functions belong to the address allocator for the dma_ops
+ * interface functions. They work like the allocators in the other IOMMU
+ * drivers. Its basically a bitmap which marks the allocated pages in
+ * the aperture. Maybe it could be enhanced in the future to a more
+ * efficient allocator.
+ *
+ ****************************************************************************/
 static unsigned long dma_mask_to_pages(unsigned long mask)
 {
 	return (mask >> PAGE_SHIFT) +
 		(PAGE_ALIGN(mask & ~PAGE_MASK) >> PAGE_SHIFT);
 }
 
+/*
+ * The address allocator core function.
+ *
+ * called with domain->lock held
+ */
 static unsigned long dma_ops_alloc_addresses(struct device *dev,
 					     struct dma_ops_domain *dom,
 					     unsigned int pages)
@@ -317,6 +406,11 @@
 	return address;
 }
 
+/*
+ * The address free function.
+ *
+ * called with domain->lock held
+ */
 static void dma_ops_free_addresses(struct dma_ops_domain *dom,
 				   unsigned long address,
 				   unsigned int pages)
@@ -325,6 +419,16 @@
 	iommu_area_free(dom->bitmap, address, pages);
 }
 
+/****************************************************************************
+ *
+ * The next functions belong to the domain allocation. A domain is
+ * allocated for every IOMMU as the default domain. If device isolation
+ * is enabled, every device get its own domain. The most important thing
+ * about domains is the page table mapping the DMA address space they
+ * contain.
+ *
+ ****************************************************************************/
+
 static u16 domain_id_alloc(void)
 {
 	unsigned long flags;
@@ -342,6 +446,10 @@
 	return id;
 }
 
+/*
+ * Used to reserve address ranges in the aperture (e.g. for exclusion
+ * ranges.
+ */
 static void dma_ops_reserve_addresses(struct dma_ops_domain *dom,
 				      unsigned long start_page,
 				      unsigned int pages)
@@ -382,6 +490,10 @@
 	free_page((unsigned long)p1);
 }
 
+/*
+ * Free a domain, only used if something went wrong in the
+ * allocation path and we need to free an already allocated page table
+ */
 static void dma_ops_domain_free(struct dma_ops_domain *dom)
 {
 	if (!dom)
@@ -396,6 +508,11 @@
 	kfree(dom);
 }
 
+/*
+ * Allocates a new protection domain usable for the dma_ops functions.
+ * It also intializes the page table and the address allocator data
+ * structures required for the dma_ops interface
+ */
 static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu,
 						   unsigned order)
 {
@@ -436,6 +553,7 @@
 	dma_dom->bitmap[0] = 1;
 	dma_dom->next_bit = 0;
 
+	/* Intialize the exclusion range if necessary */
 	if (iommu->exclusion_start &&
 	    iommu->exclusion_start < dma_dom->aperture_size) {
 		unsigned long startpage = iommu->exclusion_start >> PAGE_SHIFT;
@@ -444,6 +562,11 @@
 		dma_ops_reserve_addresses(dma_dom, startpage, pages);
 	}
 
+	/*
+	 * At the last step, build the page tables so we don't need to
+	 * allocate page table pages in the dma_ops mapping/unmapping
+	 * path.
+	 */
 	num_pte_pages = dma_dom->aperture_size / (PAGE_SIZE * 512);
 	dma_dom->pte_pages = kzalloc(num_pte_pages * sizeof(void *),
 			GFP_KERNEL);
@@ -472,6 +595,10 @@
 	return NULL;
 }
 
+/*
+ * Find out the protection domain structure for a given PCI device. This
+ * will give us the pointer to the page table root for example.
+ */
 static struct protection_domain *domain_for_device(u16 devid)
 {
 	struct protection_domain *dom;
@@ -484,6 +611,10 @@
 	return dom;
 }
 
+/*
+ * If a device is not yet associated with a domain, this function does
+ * assigns it visible for the hardware
+ */
 static void set_device_domain(struct amd_iommu *iommu,
 			      struct protection_domain *domain,
 			      u16 devid)
@@ -508,6 +639,19 @@
 	iommu->need_sync = 1;
 }
 
+/*****************************************************************************
+ *
+ * The next functions belong to the dma_ops mapping/unmapping code.
+ *
+ *****************************************************************************/
+
+/*
+ * In the dma_ops path we only have the struct device. This function
+ * finds the corresponding IOMMU, the protection domain and the
+ * requestor id for a given device.
+ * If the device is not yet associated with a domain this is also done
+ * in this function.
+ */
 static int get_device_resources(struct device *dev,
 				struct amd_iommu **iommu,
 				struct protection_domain **domain,
@@ -520,8 +664,9 @@
 	BUG_ON(!dev || dev->bus != &pci_bus_type || !dev->dma_mask);
 
 	pcidev = to_pci_dev(dev);
-	_bdf = (pcidev->bus->number << 8) | pcidev->devfn;
+	_bdf = calc_devid(pcidev->bus->number, pcidev->devfn);
 
+	/* device not translated by any IOMMU in the system? */
 	if (_bdf >= amd_iommu_last_bdf) {
 		*iommu = NULL;
 		*domain = NULL;
@@ -547,6 +692,10 @@
 	return 1;
 }
 
+/*
+ * This is the generic map function. It maps one 4kb page at paddr to
+ * the given address in the DMA address space for the domain.
+ */
 static dma_addr_t dma_ops_domain_map(struct amd_iommu *iommu,
 				     struct dma_ops_domain *dom,
 				     unsigned long address,
@@ -578,6 +727,9 @@
 	return (dma_addr_t)address;
 }
 
+/*
+ * The generic unmapping function for on page in the DMA address space.
+ */
 static void dma_ops_domain_unmap(struct amd_iommu *iommu,
 				 struct dma_ops_domain *dom,
 				 unsigned long address)
@@ -597,6 +749,12 @@
 	*pte = 0ULL;
 }
 
+/*
+ * This function contains common code for mapping of a physically
+ * contiguous memory region into DMA address space. It is uses by all
+ * mapping functions provided by this IOMMU driver.
+ * Must be called with the domain lock held.
+ */
 static dma_addr_t __map_single(struct device *dev,
 			       struct amd_iommu *iommu,
 			       struct dma_ops_domain *dma_dom,
@@ -628,6 +786,10 @@
 	return address;
 }
 
+/*
+ * Does the reverse of the __map_single function. Must be called with
+ * the domain lock held too
+ */
 static void __unmap_single(struct amd_iommu *iommu,
 			   struct dma_ops_domain *dma_dom,
 			   dma_addr_t dma_addr,
@@ -652,6 +814,9 @@
 	dma_ops_free_addresses(dma_dom, dma_addr, pages);
 }
 
+/*
+ * The exported map_single function for dma_ops.
+ */
 static dma_addr_t map_single(struct device *dev, phys_addr_t paddr,
 			     size_t size, int dir)
 {
@@ -664,6 +829,7 @@
 	get_device_resources(dev, &iommu, &domain, &devid);
 
 	if (iommu == NULL || domain == NULL)
+		/* device not handled by any AMD IOMMU */
 		return (dma_addr_t)paddr;
 
 	spin_lock_irqsave(&domain->lock, flags);
@@ -683,6 +849,9 @@
 	return addr;
 }
 
+/*
+ * The exported unmap_single function for dma_ops.
+ */
 static void unmap_single(struct device *dev, dma_addr_t dma_addr,
 			 size_t size, int dir)
 {
@@ -692,6 +861,7 @@
 	u16 devid;
 
 	if (!get_device_resources(dev, &iommu, &domain, &devid))
+		/* device not handled by any AMD IOMMU */
 		return;
 
 	spin_lock_irqsave(&domain->lock, flags);
@@ -706,6 +876,10 @@
 	spin_unlock_irqrestore(&domain->lock, flags);
 }
 
+/*
+ * This is a special map_sg function which is used if we should map a
+ * device which is not handled by an AMD IOMMU in the system.
+ */
 static int map_sg_no_iommu(struct device *dev, struct scatterlist *sglist,
 			   int nelems, int dir)
 {
@@ -720,6 +894,10 @@
 	return nelems;
 }
 
+/*
+ * The exported map_sg function for dma_ops (handles scatter-gather
+ * lists).
+ */
 static int map_sg(struct device *dev, struct scatterlist *sglist,
 		  int nelems, int dir)
 {
@@ -775,6 +953,10 @@
 	goto out;
 }
 
+/*
+ * The exported map_sg function for dma_ops (handles scatter-gather
+ * lists).
+ */
 static void unmap_sg(struct device *dev, struct scatterlist *sglist,
 		     int nelems, int dir)
 {
@@ -804,6 +986,9 @@
 	spin_unlock_irqrestore(&domain->lock, flags);
 }
 
+/*
+ * The exported alloc_coherent function for dma_ops.
+ */
 static void *alloc_coherent(struct device *dev, size_t size,
 			    dma_addr_t *dma_addr, gfp_t flag)
 {
@@ -851,6 +1036,11 @@
 	return virt_addr;
 }
 
+/*
+ * The exported free_coherent function for dma_ops.
+ * FIXME: fix the generic x86 DMA layer so that it actually calls that
+ *        function.
+ */
 static void free_coherent(struct device *dev, size_t size,
 			  void *virt_addr, dma_addr_t dma_addr)
 {
@@ -879,6 +1069,8 @@
 }
 
 /*
+ * The function for pre-allocating protection domains.
+ *
  * If the driver core informs the DMA layer if a driver grabs a device
  * we don't need to preallocate the protection domains anymore.
  * For now we have to.
@@ -921,12 +1113,20 @@
 	.unmap_sg = unmap_sg,
 };
 
+/*
+ * The function which clues the AMD IOMMU driver into dma_ops.
+ */
 int __init amd_iommu_init_dma_ops(void)
 {
 	struct amd_iommu *iommu;
 	int order = amd_iommu_aperture_order;
 	int ret;
 
+	/*
+	 * first allocate a default protection domain for every IOMMU we
+	 * found in the system. Devices not assigned to any other
+	 * protection domain will be assigned to the default one.
+	 */
 	list_for_each_entry(iommu, &amd_iommu_list, list) {
 		iommu->default_dom = dma_ops_domain_alloc(iommu, order);
 		if (iommu->default_dom == NULL)
@@ -936,6 +1136,10 @@
 			goto free_domains;
 	}
 
+	/*
+	 * If device isolation is enabled, pre-allocate the protection
+	 * domains for each device.
+	 */
 	if (amd_iommu_isolate)
 		prealloc_protection_domains();
 
@@ -947,6 +1151,7 @@
 	gart_iommu_aperture = 0;
 #endif
 
+	/* Make the driver finally visible to the drivers */
 	dma_ops = &amd_iommu_dma_ops;
 
 	return 0;
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
index 2a13e43..c9d8ff2 100644
--- a/arch/x86/kernel/amd_iommu_init.c
+++ b/arch/x86/kernel/amd_iommu_init.c
@@ -25,20 +25,13 @@
 #include <asm/pci-direct.h>
 #include <asm/amd_iommu_types.h>
 #include <asm/amd_iommu.h>
-#include <asm/gart.h>
+#include <asm/iommu.h>
 
 /*
  * definitions for the ACPI scanning code
  */
-#define UPDATE_LAST_BDF(x) do {\
-	if ((x) > amd_iommu_last_bdf) \
-		amd_iommu_last_bdf = (x); \
-	} while (0);
-
-#define DEVID(bus, devfn) (((bus) << 8) | (devfn))
 #define PCI_BUS(x) (((x) >> 8) & 0xff)
 #define IVRS_HEADER_LENGTH 48
-#define TBL_SIZE(x) (1 << (PAGE_SHIFT + get_order(amd_iommu_last_bdf * (x))))
 
 #define ACPI_IVHD_TYPE                  0x10
 #define ACPI_IVMD_TYPE_ALL              0x20
@@ -71,6 +64,17 @@
 #define ACPI_DEVFLAG_LINT1              0x80
 #define ACPI_DEVFLAG_ATSDIS             0x10000000
 
+/*
+ * ACPI table definitions
+ *
+ * These data structures are laid over the table to parse the important values
+ * out of it.
+ */
+
+/*
+ * structure describing one IOMMU in the ACPI table. Typically followed by one
+ * or more ivhd_entrys.
+ */
 struct ivhd_header {
 	u8 type;
 	u8 flags;
@@ -83,6 +87,10 @@
 	u32 reserved;
 } __attribute__((packed));
 
+/*
+ * A device entry describing which devices a specific IOMMU translates and
+ * which requestor ids they use.
+ */
 struct ivhd_entry {
 	u8 type;
 	u16 devid;
@@ -90,6 +98,10 @@
 	u32 ext;
 } __attribute__((packed));
 
+/*
+ * An AMD IOMMU memory definition structure. It defines things like exclusion
+ * ranges for devices and regions that should be unity mapped.
+ */
 struct ivmd_header {
 	u8 type;
 	u8 flags;
@@ -103,22 +115,80 @@
 
 static int __initdata amd_iommu_detected;
 
-u16 amd_iommu_last_bdf;
-struct list_head amd_iommu_unity_map;
-unsigned amd_iommu_aperture_order = 26;
-int amd_iommu_isolate;
+u16 amd_iommu_last_bdf;			/* largest PCI device id we have
+					   to handle */
+LIST_HEAD(amd_iommu_unity_map);		/* a list of required unity mappings
+					   we find in ACPI */
+unsigned amd_iommu_aperture_order = 26; /* size of aperture in power of 2 */
+int amd_iommu_isolate;			/* if 1, device isolation is enabled */
 
-struct list_head amd_iommu_list;
+LIST_HEAD(amd_iommu_list);		/* list of all AMD IOMMUs in the
+					   system */
+
+/*
+ * Pointer to the device table which is shared by all AMD IOMMUs
+ * it is indexed by the PCI device id or the HT unit id and contains
+ * information about the domain the device belongs to as well as the
+ * page table root pointer.
+ */
 struct dev_table_entry *amd_iommu_dev_table;
+
+/*
+ * The alias table is a driver specific data structure which contains the
+ * mappings of the PCI device ids to the actual requestor ids on the IOMMU.
+ * More than one device can share the same requestor id.
+ */
 u16 *amd_iommu_alias_table;
+
+/*
+ * The rlookup table is used to find the IOMMU which is responsible
+ * for a specific device. It is also indexed by the PCI device id.
+ */
 struct amd_iommu **amd_iommu_rlookup_table;
+
+/*
+ * The pd table (protection domain table) is used to find the protection domain
+ * data structure a device belongs to. Indexed with the PCI device id too.
+ */
 struct protection_domain **amd_iommu_pd_table;
+
+/*
+ * AMD IOMMU allows up to 2^16 differend protection domains. This is a bitmap
+ * to know which ones are already in use.
+ */
 unsigned long *amd_iommu_pd_alloc_bitmap;
 
-static u32 dev_table_size;
-static u32 alias_table_size;
-static u32 rlookup_table_size;
+static u32 dev_table_size;	/* size of the device table */
+static u32 alias_table_size;	/* size of the alias table */
+static u32 rlookup_table_size;	/* size if the rlookup table */
 
+static inline void update_last_devid(u16 devid)
+{
+	if (devid > amd_iommu_last_bdf)
+		amd_iommu_last_bdf = devid;
+}
+
+static inline unsigned long tbl_size(int entry_size)
+{
+	unsigned shift = PAGE_SHIFT +
+			 get_order(amd_iommu_last_bdf * entry_size);
+
+	return 1UL << shift;
+}
+
+/****************************************************************************
+ *
+ * AMD IOMMU MMIO register space handling functions
+ *
+ * These functions are used to program the IOMMU device registers in
+ * MMIO space required for that driver.
+ *
+ ****************************************************************************/
+
+/*
+ * This function set the exclusion range in the IOMMU. DMA accesses to the
+ * exclusion range are passed through untranslated
+ */
 static void __init iommu_set_exclusion_range(struct amd_iommu *iommu)
 {
 	u64 start = iommu->exclusion_start & PAGE_MASK;
@@ -137,6 +207,7 @@
 			&entry, sizeof(entry));
 }
 
+/* Programs the physical address of the device table into the IOMMU hardware */
 static void __init iommu_set_device_table(struct amd_iommu *iommu)
 {
 	u32 entry;
@@ -149,6 +220,7 @@
 			&entry, sizeof(entry));
 }
 
+/* Generic functions to enable/disable certain features of the IOMMU. */
 static void __init iommu_feature_enable(struct amd_iommu *iommu, u8 bit)
 {
 	u32 ctrl;
@@ -167,6 +239,7 @@
 	writel(ctrl, iommu->mmio_base + MMIO_CONTROL_OFFSET);
 }
 
+/* Function to enable the hardware */
 void __init iommu_enable(struct amd_iommu *iommu)
 {
 	printk(KERN_INFO "AMD IOMMU: Enabling IOMMU at ");
@@ -176,6 +249,10 @@
 	iommu_feature_enable(iommu, CONTROL_IOMMU_EN);
 }
 
+/*
+ * mapping and unmapping functions for the IOMMU MMIO space. Each AMD IOMMU in
+ * the system has one.
+ */
 static u8 * __init iommu_map_mmio_space(u64 address)
 {
 	u8 *ret;
@@ -199,16 +276,33 @@
 	release_mem_region(iommu->mmio_phys, MMIO_REGION_LENGTH);
 }
 
+/****************************************************************************
+ *
+ * The functions below belong to the first pass of AMD IOMMU ACPI table
+ * parsing. In this pass we try to find out the highest device id this
+ * code has to handle. Upon this information the size of the shared data
+ * structures is determined later.
+ *
+ ****************************************************************************/
+
+/*
+ * This function reads the last device id the IOMMU has to handle from the PCI
+ * capability header for this IOMMU
+ */
 static int __init find_last_devid_on_pci(int bus, int dev, int fn, int cap_ptr)
 {
 	u32 cap;
 
 	cap = read_pci_config(bus, dev, fn, cap_ptr+MMIO_RANGE_OFFSET);
-	UPDATE_LAST_BDF(DEVID(MMIO_GET_BUS(cap), MMIO_GET_LD(cap)));
+	update_last_devid(calc_devid(MMIO_GET_BUS(cap), MMIO_GET_LD(cap)));
 
 	return 0;
 }
 
+/*
+ * After reading the highest device id from the IOMMU PCI capability header
+ * this function looks if there is a higher device id defined in the ACPI table
+ */
 static int __init find_last_devid_from_ivhd(struct ivhd_header *h)
 {
 	u8 *p = (void *)h, *end = (void *)h;
@@ -229,7 +323,8 @@
 		case IVHD_DEV_RANGE_END:
 		case IVHD_DEV_ALIAS:
 		case IVHD_DEV_EXT_SELECT:
-			UPDATE_LAST_BDF(dev->devid);
+			/* all the above subfield types refer to device ids */
+			update_last_devid(dev->devid);
 			break;
 		default:
 			break;
@@ -242,6 +337,11 @@
 	return 0;
 }
 
+/*
+ * Iterate over all IVHD entries in the ACPI table and find the highest device
+ * id which we need to handle. This is the first of three functions which parse
+ * the ACPI table. So we check the checksum here.
+ */
 static int __init find_last_devid_acpi(struct acpi_table_header *table)
 {
 	int i;
@@ -277,19 +377,31 @@
 	return 0;
 }
 
+/****************************************************************************
+ *
+ * The following functions belong the the code path which parses the ACPI table
+ * the second time. In this ACPI parsing iteration we allocate IOMMU specific
+ * data structures, initialize the device/alias/rlookup table and also
+ * basically initialize the hardware.
+ *
+ ****************************************************************************/
+
+/*
+ * Allocates the command buffer. This buffer is per AMD IOMMU. We can
+ * write commands to that buffer later and the IOMMU will execute them
+ * asynchronously
+ */
 static u8 * __init alloc_command_buffer(struct amd_iommu *iommu)
 {
-	u8 *cmd_buf = (u8 *)__get_free_pages(GFP_KERNEL,
+	u8 *cmd_buf = (u8 *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
 			get_order(CMD_BUFFER_SIZE));
-	u64 entry = 0;
+	u64 entry;
 
 	if (cmd_buf == NULL)
 		return NULL;
 
 	iommu->cmd_buf_size = CMD_BUFFER_SIZE;
 
-	memset(cmd_buf, 0, CMD_BUFFER_SIZE);
-
 	entry = (u64)virt_to_phys(cmd_buf);
 	entry |= MMIO_CMD_SIZE_512;
 	memcpy_toio(iommu->mmio_base + MMIO_CMD_BUF_OFFSET,
@@ -302,11 +414,10 @@
 
 static void __init free_command_buffer(struct amd_iommu *iommu)
 {
-	if (iommu->cmd_buf)
-		free_pages((unsigned long)iommu->cmd_buf,
-				get_order(CMD_BUFFER_SIZE));
+	free_pages((unsigned long)iommu->cmd_buf, get_order(CMD_BUFFER_SIZE));
 }
 
+/* sets a specific bit in the device table entry. */
 static void set_dev_entry_bit(u16 devid, u8 bit)
 {
 	int i = (bit >> 5) & 0x07;
@@ -315,7 +426,18 @@
 	amd_iommu_dev_table[devid].data[i] |= (1 << _bit);
 }
 
-static void __init set_dev_entry_from_acpi(u16 devid, u32 flags, u32 ext_flags)
+/* Writes the specific IOMMU for a device into the rlookup table */
+static void __init set_iommu_for_device(struct amd_iommu *iommu, u16 devid)
+{
+	amd_iommu_rlookup_table[devid] = iommu;
+}
+
+/*
+ * This function takes the device specific flags read from the ACPI
+ * table and sets up the device table entry with that information
+ */
+static void __init set_dev_entry_from_acpi(struct amd_iommu *iommu,
+					   u16 devid, u32 flags, u32 ext_flags)
 {
 	if (flags & ACPI_DEVFLAG_INITPASS)
 		set_dev_entry_bit(devid, DEV_ENTRY_INIT_PASS);
@@ -331,13 +453,14 @@
 		set_dev_entry_bit(devid, DEV_ENTRY_LINT0_PASS);
 	if (flags & ACPI_DEVFLAG_LINT1)
 		set_dev_entry_bit(devid, DEV_ENTRY_LINT1_PASS);
+
+	set_iommu_for_device(iommu, devid);
 }
 
-static void __init set_iommu_for_device(struct amd_iommu *iommu, u16 devid)
-{
-	amd_iommu_rlookup_table[devid] = iommu;
-}
-
+/*
+ * Reads the device exclusion range from ACPI and initialize IOMMU with
+ * it
+ */
 static void __init set_device_exclusion_range(u16 devid, struct ivmd_header *m)
 {
 	struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
@@ -346,12 +469,22 @@
 		return;
 
 	if (iommu) {
+		/*
+		 * We only can configure exclusion ranges per IOMMU, not
+		 * per device. But we can enable the exclusion range per
+		 * device. This is done here
+		 */
 		set_dev_entry_bit(m->devid, DEV_ENTRY_EX);
 		iommu->exclusion_start = m->range_start;
 		iommu->exclusion_length = m->range_length;
 	}
 }
 
+/*
+ * This function reads some important data from the IOMMU PCI space and
+ * initializes the driver data structure with it. It reads the hardware
+ * capabilities and the first/last device entries
+ */
 static void __init init_iommu_from_pci(struct amd_iommu *iommu)
 {
 	int bus = PCI_BUS(iommu->devid);
@@ -363,10 +496,16 @@
 	iommu->cap = read_pci_config(bus, dev, fn, cap_ptr+MMIO_CAP_HDR_OFFSET);
 
 	range = read_pci_config(bus, dev, fn, cap_ptr+MMIO_RANGE_OFFSET);
-	iommu->first_device = DEVID(MMIO_GET_BUS(range), MMIO_GET_FD(range));
-	iommu->last_device = DEVID(MMIO_GET_BUS(range), MMIO_GET_LD(range));
+	iommu->first_device = calc_devid(MMIO_GET_BUS(range),
+					 MMIO_GET_FD(range));
+	iommu->last_device = calc_devid(MMIO_GET_BUS(range),
+					MMIO_GET_LD(range));
 }
 
+/*
+ * Takes a pointer to an AMD IOMMU entry in the ACPI table and
+ * initializes the hardware and our data structures with it.
+ */
 static void __init init_iommu_from_acpi(struct amd_iommu *iommu,
 					struct ivhd_header *h)
 {
@@ -374,7 +513,7 @@
 	u8 *end = p, flags = 0;
 	u16 dev_i, devid = 0, devid_start = 0, devid_to = 0;
 	u32 ext_flags = 0;
-	bool alias = 0;
+	bool alias = false;
 	struct ivhd_entry *e;
 
 	/*
@@ -414,22 +553,23 @@
 		case IVHD_DEV_ALL:
 			for (dev_i = iommu->first_device;
 					dev_i <= iommu->last_device; ++dev_i)
-				set_dev_entry_from_acpi(dev_i, e->flags, 0);
+				set_dev_entry_from_acpi(iommu, dev_i,
+							e->flags, 0);
 			break;
 		case IVHD_DEV_SELECT:
 			devid = e->devid;
-			set_dev_entry_from_acpi(devid, e->flags, 0);
+			set_dev_entry_from_acpi(iommu, devid, e->flags, 0);
 			break;
 		case IVHD_DEV_SELECT_RANGE_START:
 			devid_start = e->devid;
 			flags = e->flags;
 			ext_flags = 0;
-			alias = 0;
+			alias = false;
 			break;
 		case IVHD_DEV_ALIAS:
 			devid = e->devid;
 			devid_to = e->ext >> 8;
-			set_dev_entry_from_acpi(devid, e->flags, 0);
+			set_dev_entry_from_acpi(iommu, devid, e->flags, 0);
 			amd_iommu_alias_table[devid] = devid_to;
 			break;
 		case IVHD_DEV_ALIAS_RANGE:
@@ -437,24 +577,25 @@
 			flags = e->flags;
 			devid_to = e->ext >> 8;
 			ext_flags = 0;
-			alias = 1;
+			alias = true;
 			break;
 		case IVHD_DEV_EXT_SELECT:
 			devid = e->devid;
-			set_dev_entry_from_acpi(devid, e->flags, e->ext);
+			set_dev_entry_from_acpi(iommu, devid, e->flags,
+						e->ext);
 			break;
 		case IVHD_DEV_EXT_SELECT_RANGE:
 			devid_start = e->devid;
 			flags = e->flags;
 			ext_flags = e->ext;
-			alias = 0;
+			alias = false;
 			break;
 		case IVHD_DEV_RANGE_END:
 			devid = e->devid;
 			for (dev_i = devid_start; dev_i <= devid; ++dev_i) {
 				if (alias)
 					amd_iommu_alias_table[dev_i] = devid_to;
-				set_dev_entry_from_acpi(
+				set_dev_entry_from_acpi(iommu,
 						amd_iommu_alias_table[dev_i],
 						flags, ext_flags);
 			}
@@ -467,6 +608,7 @@
 	}
 }
 
+/* Initializes the device->iommu mapping for the driver */
 static int __init init_iommu_devices(struct amd_iommu *iommu)
 {
 	u16 i;
@@ -494,6 +636,11 @@
 	}
 }
 
+/*
+ * This function clues the initialization function for one IOMMU
+ * together and also allocates the command buffer and programs the
+ * hardware. It does NOT enable the IOMMU. This is done afterwards.
+ */
 static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
 {
 	spin_lock_init(&iommu->lock);
@@ -521,6 +668,10 @@
 	return 0;
 }
 
+/*
+ * Iterates over all IOMMU entries in the ACPI table, allocates the
+ * IOMMU structure and initializes it with init_iommu_one()
+ */
 static int __init init_iommu_all(struct acpi_table_header *table)
 {
 	u8 *p = (u8 *)table, *end = (u8 *)table;
@@ -528,8 +679,6 @@
 	struct amd_iommu *iommu;
 	int ret;
 
-	INIT_LIST_HEAD(&amd_iommu_list);
-
 	end += table->length;
 	p += IVRS_HEADER_LENGTH;
 
@@ -555,6 +704,14 @@
 	return 0;
 }
 
+/****************************************************************************
+ *
+ * The next functions belong to the third pass of parsing the ACPI
+ * table. In this last pass the memory mapping requirements are
+ * gathered (like exclusion and unity mapping reanges).
+ *
+ ****************************************************************************/
+
 static void __init free_unity_maps(void)
 {
 	struct unity_map_entry *entry, *next;
@@ -565,6 +722,7 @@
 	}
 }
 
+/* called when we find an exclusion range definition in ACPI */
 static int __init init_exclusion_range(struct ivmd_header *m)
 {
 	int i;
@@ -588,6 +746,7 @@
 	return 0;
 }
 
+/* called for unity map ACPI definition */
 static int __init init_unity_map_range(struct ivmd_header *m)
 {
 	struct unity_map_entry *e = 0;
@@ -619,13 +778,12 @@
 	return 0;
 }
 
+/* iterates over all memory definitions we find in the ACPI table */
 static int __init init_memory_definitions(struct acpi_table_header *table)
 {
 	u8 *p = (u8 *)table, *end = (u8 *)table;
 	struct ivmd_header *m;
 
-	INIT_LIST_HEAD(&amd_iommu_unity_map);
-
 	end += table->length;
 	p += IVRS_HEADER_LENGTH;
 
@@ -642,6 +800,10 @@
 	return 0;
 }
 
+/*
+ * This function finally enables all IOMMUs found in the system after
+ * they have been initialized
+ */
 static void __init enable_iommus(void)
 {
 	struct amd_iommu *iommu;
@@ -678,6 +840,34 @@
 	.cls = &amd_iommu_sysdev_class,
 };
 
+/*
+ * This is the core init function for AMD IOMMU hardware in the system.
+ * This function is called from the generic x86 DMA layer initialization
+ * code.
+ *
+ * This function basically parses the ACPI table for AMD IOMMU (IVRS)
+ * three times:
+ *
+ *	1 pass) Find the highest PCI device id the driver has to handle.
+ *		Upon this information the size of the data structures is
+ *		determined that needs to be allocated.
+ *
+ *	2 pass) Initialize the data structures just allocated with the
+ *		information in the ACPI table about available AMD IOMMUs
+ *		in the system. It also maps the PCI devices in the
+ *		system to specific IOMMUs
+ *
+ *	3 pass) After the basic data structures are allocated and
+ *		initialized we update them with information about memory
+ *		remapping requirements parsed out of the ACPI table in
+ *		this last pass.
+ *
+ * After that the hardware is initialized and ready to go. In the last
+ * step we do some Linux specific things like registering the driver in
+ * the dma_ops interface and initializing the suspend/resume support
+ * functions. Finally it prints some information about AMD IOMMUs and
+ * the driver state and enables the hardware.
+ */
 int __init amd_iommu_init(void)
 {
 	int i, ret = 0;
@@ -699,14 +889,14 @@
 	if (acpi_table_parse("IVRS", find_last_devid_acpi) != 0)
 		return -ENODEV;
 
-	dev_table_size     = TBL_SIZE(DEV_TABLE_ENTRY_SIZE);
-	alias_table_size   = TBL_SIZE(ALIAS_TABLE_ENTRY_SIZE);
-	rlookup_table_size = TBL_SIZE(RLOOKUP_TABLE_ENTRY_SIZE);
+	dev_table_size     = tbl_size(DEV_TABLE_ENTRY_SIZE);
+	alias_table_size   = tbl_size(ALIAS_TABLE_ENTRY_SIZE);
+	rlookup_table_size = tbl_size(RLOOKUP_TABLE_ENTRY_SIZE);
 
 	ret = -ENOMEM;
 
 	/* Device table - directly used by all IOMMUs */
-	amd_iommu_dev_table = (void *)__get_free_pages(GFP_KERNEL,
+	amd_iommu_dev_table = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
 				      get_order(dev_table_size));
 	if (amd_iommu_dev_table == NULL)
 		goto out;
@@ -730,27 +920,23 @@
 	 * Protection Domain table - maps devices to protection domains
 	 * This table has the same size as the rlookup_table
 	 */
-	amd_iommu_pd_table = (void *)__get_free_pages(GFP_KERNEL,
+	amd_iommu_pd_table = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
 				     get_order(rlookup_table_size));
 	if (amd_iommu_pd_table == NULL)
 		goto free;
 
-	amd_iommu_pd_alloc_bitmap = (void *)__get_free_pages(GFP_KERNEL,
+	amd_iommu_pd_alloc_bitmap = (void *)__get_free_pages(
+					    GFP_KERNEL | __GFP_ZERO,
 					    get_order(MAX_DOMAIN_ID/8));
 	if (amd_iommu_pd_alloc_bitmap == NULL)
 		goto free;
 
 	/*
-	 * memory is allocated now; initialize the device table with all zeroes
-	 * and let all alias entries point to itself
+	 * let all alias entries point to itself
 	 */
-	memset(amd_iommu_dev_table, 0, dev_table_size);
 	for (i = 0; i < amd_iommu_last_bdf; ++i)
 		amd_iommu_alias_table[i] = i;
 
-	memset(amd_iommu_pd_table, 0, rlookup_table_size);
-	memset(amd_iommu_pd_alloc_bitmap, 0, MAX_DOMAIN_ID / 8);
-
 	/*
 	 * never allocate domain 0 because its used as the non-allocated and
 	 * error value placeholder
@@ -795,24 +981,19 @@
 	return ret;
 
 free:
-	if (amd_iommu_pd_alloc_bitmap)
-		free_pages((unsigned long)amd_iommu_pd_alloc_bitmap, 1);
+	free_pages((unsigned long)amd_iommu_pd_alloc_bitmap, 1);
 
-	if (amd_iommu_pd_table)
-		free_pages((unsigned long)amd_iommu_pd_table,
-				get_order(rlookup_table_size));
+	free_pages((unsigned long)amd_iommu_pd_table,
+		   get_order(rlookup_table_size));
 
-	if (amd_iommu_rlookup_table)
-		free_pages((unsigned long)amd_iommu_rlookup_table,
-				get_order(rlookup_table_size));
+	free_pages((unsigned long)amd_iommu_rlookup_table,
+		   get_order(rlookup_table_size));
 
-	if (amd_iommu_alias_table)
-		free_pages((unsigned long)amd_iommu_alias_table,
-				get_order(alias_table_size));
+	free_pages((unsigned long)amd_iommu_alias_table,
+		   get_order(alias_table_size));
 
-	if (amd_iommu_dev_table)
-		free_pages((unsigned long)amd_iommu_dev_table,
-				get_order(dev_table_size));
+	free_pages((unsigned long)amd_iommu_dev_table,
+		   get_order(dev_table_size));
 
 	free_iommu_all();
 
@@ -821,6 +1002,13 @@
 	goto out;
 }
 
+/****************************************************************************
+ *
+ * Early detect code. This code runs at IOMMU detection time in the DMA
+ * layer. It just looks if there is an IVRS ACPI table to detect AMD
+ * IOMMUs
+ *
+ ****************************************************************************/
 static int __init early_amd_iommu_detect(struct acpi_table_header *table)
 {
 	return 0;
@@ -828,7 +1016,7 @@
 
 void __init amd_iommu_detect(void)
 {
-	if (swiotlb || no_iommu || iommu_detected)
+	if (swiotlb || no_iommu || (iommu_detected && !gart_iommu_aperture))
 		return;
 
 	if (acpi_table_parse("IVRS", early_amd_iommu_detect) == 0) {
@@ -841,6 +1029,13 @@
 	}
 }
 
+/****************************************************************************
+ *
+ * Parsing functions for the AMD IOMMU specific kernel command line
+ * options.
+ *
+ ****************************************************************************/
+
 static int __init parse_amd_iommu_options(char *str)
 {
 	for (; *str; ++str) {
@@ -853,20 +1048,10 @@
 
 static int __init parse_amd_iommu_size_options(char *str)
 {
-	for (; *str; ++str) {
-		if (strcmp(str, "32M") == 0)
-			amd_iommu_aperture_order = 25;
-		if (strcmp(str, "64M") == 0)
-			amd_iommu_aperture_order = 26;
-		if (strcmp(str, "128M") == 0)
-			amd_iommu_aperture_order = 27;
-		if (strcmp(str, "256M") == 0)
-			amd_iommu_aperture_order = 28;
-		if (strcmp(str, "512M") == 0)
-			amd_iommu_aperture_order = 29;
-		if (strcmp(str, "1G") == 0)
-			amd_iommu_aperture_order = 30;
-	}
+	unsigned order = PAGE_SHIFT + get_order(memparse(str, &str));
+
+	if ((order > 24) && (order < 31))
+		amd_iommu_aperture_order = order;
 
 	return 1;
 }
diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c
index 9f90780..44e2182 100644
--- a/arch/x86/kernel/aperture_64.c
+++ b/arch/x86/kernel/aperture_64.c
@@ -21,6 +21,7 @@
 #include <linux/suspend.h>
 #include <asm/e820.h>
 #include <asm/io.h>
+#include <asm/iommu.h>
 #include <asm/gart.h>
 #include <asm/pci-direct.h>
 #include <asm/dma.h>
diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c
index a437d02..d6c8983 100644
--- a/arch/x86/kernel/apic_32.c
+++ b/arch/x86/kernel/apic_32.c
@@ -75,7 +75,7 @@
 /*
  * Debug level, exported for io_apic.c
  */
-int apic_verbosity;
+unsigned int apic_verbosity;
 
 int pic_mode;
 
@@ -177,7 +177,7 @@
 	/* Level triggered for 82489DX */
 	if (!lapic_is_integrated())
 		v |= APIC_LVT_LEVEL_TRIGGER;
-	apic_write_around(APIC_LVT0, v);
+	apic_write(APIC_LVT0, v);
 }
 
 /**
@@ -212,9 +212,6 @@
  * this function twice on the boot CPU, once with a bogus timeout
  * value, second time for real. The other (noncalibrating) CPUs
  * call this function only once, with the real, calibrated value.
- *
- * We do reads before writes even if unnecessary, to get around the
- * P5 APIC double write bug.
  */
 static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
 {
@@ -229,18 +226,18 @@
 	if (!irqen)
 		lvtt_value |= APIC_LVT_MASKED;
 
-	apic_write_around(APIC_LVTT, lvtt_value);
+	apic_write(APIC_LVTT, lvtt_value);
 
 	/*
 	 * Divide PICLK by 16
 	 */
 	tmp_value = apic_read(APIC_TDCR);
-	apic_write_around(APIC_TDCR, (tmp_value
-				& ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE))
-				| APIC_TDR_DIV_16);
+	apic_write(APIC_TDCR,
+		   (tmp_value & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) |
+		   APIC_TDR_DIV_16);
 
 	if (!oneshot)
-		apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR);
+		apic_write(APIC_TMICT, clocks / APIC_DIVISOR);
 }
 
 /*
@@ -249,7 +246,7 @@
 static int lapic_next_event(unsigned long delta,
 			    struct clock_event_device *evt)
 {
-	apic_write_around(APIC_TMICT, delta);
+	apic_write(APIC_TMICT, delta);
 	return 0;
 }
 
@@ -278,7 +275,7 @@
 	case CLOCK_EVT_MODE_SHUTDOWN:
 		v = apic_read(APIC_LVTT);
 		v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
-		apic_write_around(APIC_LVTT, v);
+		apic_write(APIC_LVTT, v);
 		break;
 	case CLOCK_EVT_MODE_RESUME:
 		/* Nothing to do here */
@@ -372,12 +369,7 @@
 	}
 }
 
-/*
- * Setup the boot APIC
- *
- * Calibrate and verify the result.
- */
-void __init setup_boot_APIC_clock(void)
+static int __init calibrate_APIC_clock(void)
 {
 	struct clock_event_device *levt = &__get_cpu_var(lapic_events);
 	const long pm_100ms = PMTMR_TICKS_PER_SEC/10;
@@ -387,24 +379,6 @@
 	long delta, deltapm;
 	int pm_referenced = 0;
 
-	/*
-	 * The local apic timer can be disabled via the kernel
-	 * commandline or from the CPU detection code. Register the lapic
-	 * timer as a dummy clock event source on SMP systems, so the
-	 * broadcast mechanism is used. On UP systems simply ignore it.
-	 */
-	if (local_apic_timer_disabled) {
-		/* No broadcast on UP ! */
-		if (num_possible_cpus() > 1) {
-			lapic_clockevent.mult = 1;
-			setup_APIC_timer();
-		}
-		return;
-	}
-
-	apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"
-		    "calibrating APIC timer ...\n");
-
 	local_irq_disable();
 
 	/* Replace the global interrupt handler */
@@ -489,8 +463,6 @@
 		    calibration_result / (1000000 / HZ),
 		    calibration_result % (1000000 / HZ));
 
-	local_apic_timer_verify_ok = 1;
-
 	/*
 	 * Do a sanity check on the APIC calibration result
 	 */
@@ -498,12 +470,11 @@
 		local_irq_enable();
 		printk(KERN_WARNING
 		       "APIC frequency too slow, disabling apic timer\n");
-		/* No broadcast on UP ! */
-		if (num_possible_cpus() > 1)
-			setup_APIC_timer();
-		return;
+		return -1;
 	}
 
+	local_apic_timer_verify_ok = 1;
+
 	/* We trust the pm timer based calibration */
 	if (!pm_referenced) {
 		apic_printk(APIC_VERBOSE, "... verify APIC timer\n");
@@ -543,22 +514,55 @@
 	if (!local_apic_timer_verify_ok) {
 		printk(KERN_WARNING
 		       "APIC timer disabled due to verification failure.\n");
-		/* No broadcast on UP ! */
-		if (num_possible_cpus() == 1)
-			return;
-	} else {
-		/*
-		 * If nmi_watchdog is set to IO_APIC, we need the
-		 * PIT/HPET going.  Otherwise register lapic as a dummy
-		 * device.
-		 */
-		if (nmi_watchdog != NMI_IO_APIC)
-			lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
-		else
-			printk(KERN_WARNING "APIC timer registered as dummy,"
-				" due to nmi_watchdog=%d!\n", nmi_watchdog);
+			return -1;
 	}
 
+	return 0;
+}
+
+/*
+ * Setup the boot APIC
+ *
+ * Calibrate and verify the result.
+ */
+void __init setup_boot_APIC_clock(void)
+{
+	/*
+	 * The local apic timer can be disabled via the kernel
+	 * commandline or from the CPU detection code. Register the lapic
+	 * timer as a dummy clock event source on SMP systems, so the
+	 * broadcast mechanism is used. On UP systems simply ignore it.
+	 */
+	if (local_apic_timer_disabled) {
+		/* No broadcast on UP ! */
+		if (num_possible_cpus() > 1) {
+			lapic_clockevent.mult = 1;
+			setup_APIC_timer();
+		}
+		return;
+	}
+
+	apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"
+		    "calibrating APIC timer ...\n");
+
+	if (calibrate_APIC_clock()) {
+		/* No broadcast on UP ! */
+		if (num_possible_cpus() > 1)
+			setup_APIC_timer();
+		return;
+	}
+
+	/*
+	 * If nmi_watchdog is set to IO_APIC, we need the
+	 * PIT/HPET going.  Otherwise register lapic as a dummy
+	 * device.
+	 */
+	if (nmi_watchdog != NMI_IO_APIC)
+		lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
+	else
+		printk(KERN_WARNING "APIC timer registered as dummy,"
+			" due to nmi_watchdog=%d!\n", nmi_watchdog);
+
 	/* Setup the lapic or request the broadcast */
 	setup_APIC_timer();
 }
@@ -693,44 +697,44 @@
 	 */
 	if (maxlvt >= 3) {
 		v = ERROR_APIC_VECTOR; /* any non-zero vector will do */
-		apic_write_around(APIC_LVTERR, v | APIC_LVT_MASKED);
+		apic_write(APIC_LVTERR, v | APIC_LVT_MASKED);
 	}
 	/*
 	 * Careful: we have to set masks only first to deassert
 	 * any level-triggered sources.
 	 */
 	v = apic_read(APIC_LVTT);
-	apic_write_around(APIC_LVTT, v | APIC_LVT_MASKED);
+	apic_write(APIC_LVTT, v | APIC_LVT_MASKED);
 	v = apic_read(APIC_LVT0);
-	apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED);
+	apic_write(APIC_LVT0, v | APIC_LVT_MASKED);
 	v = apic_read(APIC_LVT1);
-	apic_write_around(APIC_LVT1, v | APIC_LVT_MASKED);
+	apic_write(APIC_LVT1, v | APIC_LVT_MASKED);
 	if (maxlvt >= 4) {
 		v = apic_read(APIC_LVTPC);
-		apic_write_around(APIC_LVTPC, v | APIC_LVT_MASKED);
+		apic_write(APIC_LVTPC, v | APIC_LVT_MASKED);
 	}
 
 	/* lets not touch this if we didn't frob it */
 #ifdef CONFIG_X86_MCE_P4THERMAL
 	if (maxlvt >= 5) {
 		v = apic_read(APIC_LVTTHMR);
-		apic_write_around(APIC_LVTTHMR, v | APIC_LVT_MASKED);
+		apic_write(APIC_LVTTHMR, v | APIC_LVT_MASKED);
 	}
 #endif
 	/*
 	 * Clean APIC state for other OSs:
 	 */
-	apic_write_around(APIC_LVTT, APIC_LVT_MASKED);
-	apic_write_around(APIC_LVT0, APIC_LVT_MASKED);
-	apic_write_around(APIC_LVT1, APIC_LVT_MASKED);
+	apic_write(APIC_LVTT, APIC_LVT_MASKED);
+	apic_write(APIC_LVT0, APIC_LVT_MASKED);
+	apic_write(APIC_LVT1, APIC_LVT_MASKED);
 	if (maxlvt >= 3)
-		apic_write_around(APIC_LVTERR, APIC_LVT_MASKED);
+		apic_write(APIC_LVTERR, APIC_LVT_MASKED);
 	if (maxlvt >= 4)
-		apic_write_around(APIC_LVTPC, APIC_LVT_MASKED);
+		apic_write(APIC_LVTPC, APIC_LVT_MASKED);
 
 #ifdef CONFIG_X86_MCE_P4THERMAL
 	if (maxlvt >= 5)
-		apic_write_around(APIC_LVTTHMR, APIC_LVT_MASKED);
+		apic_write(APIC_LVTTHMR, APIC_LVT_MASKED);
 #endif
 	/* Integrated APIC (!82489DX) ? */
 	if (lapic_is_integrated()) {
@@ -756,7 +760,7 @@
 	 */
 	value = apic_read(APIC_SPIV);
 	value &= ~APIC_SPIV_APIC_ENABLED;
-	apic_write_around(APIC_SPIV, value);
+	apic_write(APIC_SPIV, value);
 
 	/*
 	 * When LAPIC was disabled by the BIOS and enabled by the kernel,
@@ -865,8 +869,8 @@
 	apic_wait_icr_idle();
 
 	apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n");
-	apic_write_around(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG
-				| APIC_DM_INIT);
+	apic_write(APIC_ICR,
+		   APIC_DEST_ALLINC | APIC_INT_LEVELTRIG | APIC_DM_INIT);
 }
 
 /*
@@ -902,16 +906,16 @@
 	else
 		value |= APIC_SPIV_FOCUS_DISABLED;
 	value |= SPURIOUS_APIC_VECTOR;
-	apic_write_around(APIC_SPIV, value);
+	apic_write(APIC_SPIV, value);
 
 	/*
 	 * Set up the virtual wire mode.
 	 */
-	apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
+	apic_write(APIC_LVT0, APIC_DM_EXTINT);
 	value = APIC_DM_NMI;
 	if (!lapic_is_integrated())		/* 82489DX */
 		value |= APIC_LVT_LEVEL_TRIGGER;
-	apic_write_around(APIC_LVT1, value);
+	apic_write(APIC_LVT1, value);
 }
 
 static void __cpuinit lapic_setup_esr(void)
@@ -926,7 +930,7 @@
 
 		/* enables sending errors */
 		value = ERROR_APIC_VECTOR;
-		apic_write_around(APIC_LVTERR, value);
+		apic_write(APIC_LVTERR, value);
 		/*
 		 * spec says clear errors after enabling vector.
 		 */
@@ -989,7 +993,7 @@
 	 */
 	value = apic_read(APIC_TASKPRI);
 	value &= ~APIC_TPRI_MASK;
-	apic_write_around(APIC_TASKPRI, value);
+	apic_write(APIC_TASKPRI, value);
 
 	/*
 	 * After a crash, we no longer service the interrupts and a pending
@@ -1047,7 +1051,7 @@
 	 * Set spurious IRQ vector
 	 */
 	value |= SPURIOUS_APIC_VECTOR;
-	apic_write_around(APIC_SPIV, value);
+	apic_write(APIC_SPIV, value);
 
 	/*
 	 * Set up LVT0, LVT1:
@@ -1069,7 +1073,7 @@
 		apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n",
 				smp_processor_id());
 	}
-	apic_write_around(APIC_LVT0, value);
+	apic_write(APIC_LVT0, value);
 
 	/*
 	 * only the BP should see the LINT1 NMI signal, obviously.
@@ -1080,7 +1084,7 @@
 		value = APIC_DM_NMI | APIC_LVT_MASKED;
 	if (!integrated)		/* 82489DX */
 		value |= APIC_LVT_LEVEL_TRIGGER;
-	apic_write_around(APIC_LVT1, value);
+	apic_write(APIC_LVT1, value);
 }
 
 void __cpuinit end_local_APIC_setup(void)
@@ -1091,7 +1095,7 @@
 	/* Disable the local apic timer */
 	value = apic_read(APIC_LVTT);
 	value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
-	apic_write_around(APIC_LVTT, value);
+	apic_write(APIC_LVTT, value);
 
 	setup_apic_nmi_watchdog(NULL);
 	apic_pm_activate();
@@ -1214,9 +1218,6 @@
 
 int __init APIC_init_uniprocessor(void)
 {
-	if (disable_apic)
-		clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
-
 	if (!smp_found_config && !cpu_has_apic)
 		return -1;
 
@@ -1419,7 +1420,7 @@
 		value &= ~APIC_VECTOR_MASK;
 		value |= APIC_SPIV_APIC_ENABLED;
 		value |= 0xf;
-		apic_write_around(APIC_SPIV, value);
+		apic_write(APIC_SPIV, value);
 
 		if (!virt_wire_setup) {
 			/*
@@ -1432,10 +1433,10 @@
 				APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
 			value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
 			value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT);
-			apic_write_around(APIC_LVT0, value);
+			apic_write(APIC_LVT0, value);
 		} else {
 			/* Disable LVT0 */
-			apic_write_around(APIC_LVT0, APIC_LVT_MASKED);
+			apic_write(APIC_LVT0, APIC_LVT_MASKED);
 		}
 
 		/*
@@ -1449,7 +1450,7 @@
 			APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
 		value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
 		value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI);
-		apic_write_around(APIC_LVT1, value);
+		apic_write(APIC_LVT1, value);
 	}
 }
 
@@ -1700,7 +1701,7 @@
 static int __init parse_nolapic(char *arg)
 {
 	disable_apic = 1;
-	clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
+	setup_clear_cpu_cap(X86_FEATURE_APIC);
 	return 0;
 }
 early_param("nolapic", parse_nolapic);
diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c
index 1e3d32e..7f1f030 100644
--- a/arch/x86/kernel/apic_64.c
+++ b/arch/x86/kernel/apic_64.c
@@ -54,7 +54,7 @@
 /*
  * Debug level, exported for io_apic.c
  */
-int apic_verbosity;
+unsigned int apic_verbosity;
 
 /* Have we found an MP table */
 int smp_found_config;
@@ -314,7 +314,7 @@
 
 #define TICK_COUNT 100000000
 
-static void __init calibrate_APIC_clock(void)
+static int __init calibrate_APIC_clock(void)
 {
 	unsigned apic, apic_start;
 	unsigned long tsc, tsc_start;
@@ -368,6 +368,17 @@
 		clockevent_delta2ns(0xF, &lapic_clockevent);
 
 	calibration_result = result / HZ;
+
+	/*
+	 * Do a sanity check on the APIC calibration result
+	 */
+	if (calibration_result < (1000000 / HZ)) {
+		printk(KERN_WARNING
+			"APIC frequency too slow, disabling apic timer\n");
+		return -1;
+	}
+
+	return 0;
 }
 
 /*
@@ -394,14 +405,7 @@
 	}
 
 	printk(KERN_INFO "Using local APIC timer interrupts.\n");
-	calibrate_APIC_clock();
-
-	/*
-	 * Do a sanity check on the APIC calibration result
-	 */
-	if (calibration_result < (1000000 / HZ)) {
-		printk(KERN_WARNING
-		       "APIC frequency too slow, disabling apic timer\n");
+	if (calibrate_APIC_clock()) {
 		/* No broadcast on UP ! */
 		if (num_possible_cpus() > 1)
 			setup_APIC_timer();
@@ -1337,7 +1341,7 @@
 static __init int setup_disableapic(char *str)
 {
 	disable_apic = 1;
-	clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
+	setup_clear_cpu_cap(X86_FEATURE_APIC);
 	return 0;
 }
 early_param("disableapic", setup_disableapic);
diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c
index bacf5de..aa89387 100644
--- a/arch/x86/kernel/asm-offsets_64.c
+++ b/arch/x86/kernel/asm-offsets_64.c
@@ -18,6 +18,8 @@
 #include <asm/ia32.h>
 #include <asm/bootparam.h>
 
+#include <xen/interface/xen.h>
+
 #define __NO_STUBS 1
 #undef __SYSCALL
 #undef _ASM_X86_64_UNISTD_H_
@@ -131,5 +133,14 @@
 	OFFSET(BP_loadflags, boot_params, hdr.loadflags);
 	OFFSET(BP_hardware_subarch, boot_params, hdr.hardware_subarch);
 	OFFSET(BP_version, boot_params, hdr.version);
+
+	BLANK();
+	DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
+#ifdef CONFIG_XEN
+	BLANK();
+	OFFSET(XEN_vcpu_info_mask, vcpu_info, evtchn_upcall_mask);
+	OFFSET(XEN_vcpu_info_pending, vcpu_info, evtchn_upcall_pending);
+#undef ENTRY
+#endif
 	return 0;
 }
diff --git a/arch/x86/kernel/bios_uv.c b/arch/x86/kernel/bios_uv.c
new file mode 100644
index 0000000..c639bd55
--- /dev/null
+++ b/arch/x86/kernel/bios_uv.c
@@ -0,0 +1,48 @@
+/*
+ * BIOS run time interface routines.
+ *
+ *  Copyright (c) 2008 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  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 <asm/uv/bios.h>
+
+const char *
+x86_bios_strerror(long status)
+{
+	const char *str;
+	switch (status) {
+	case  0: str = "Call completed without error"; break;
+	case -1: str = "Not implemented"; break;
+	case -2: str = "Invalid argument"; break;
+	case -3: str = "Call completed with error"; break;
+	default: str = "Unknown BIOS status code"; break;
+	}
+	return str;
+}
+
+long
+x86_bios_freq_base(unsigned long which, unsigned long *ticks_per_second,
+		   unsigned long *drift_info)
+{
+	struct uv_bios_retval isrv;
+
+	BIOS_CALL(isrv, BIOS_FREQ_BASE, which, 0, 0, 0, 0, 0, 0);
+	*ticks_per_second = isrv.v0;
+	*drift_info = isrv.v1;
+	return isrv.status;
+}
+EXPORT_SYMBOL_GPL(x86_bios_freq_base);
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 81a07ca..cae9cab 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -24,8 +24,6 @@
 extern void vide(void);
 __asm__(".align 4\nvide: ret");
 
-int force_mwait __cpuinitdata;
-
 static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
 {
 	if (cpuid_eax(0x80000000) >= 0x80000007) {
diff --git a/arch/x86/kernel/cpu/amd_64.c b/arch/x86/kernel/cpu/amd_64.c
index 7c36fb8..d1692b2 100644
--- a/arch/x86/kernel/cpu/amd_64.c
+++ b/arch/x86/kernel/cpu/amd_64.c
@@ -115,6 +115,8 @@
 	/* c->x86_power is 8000_0007 edx. Bit 8 is constant TSC */
 	if (c->x86_power & (1<<8))
 		set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
+
+	set_cpu_cap(c, X86_FEATURE_SYSCALL32);
 }
 
 static void __cpuinit init_amd(struct cpuinfo_x86 *c)
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 1b1c56b..c9b58a8 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -131,13 +131,7 @@
  *   (for due to lack of "invlpg" and working WP on a i386)
  * - In order to run on anything without a TSC, we need to be
  *   compiled for a i486.
- * - In order to support the local APIC on a buggy Pentium machine,
- *   we need to be compiled with CONFIG_X86_GOOD_APIC disabled,
- *   which happens implicitly if compiled for a Pentium or lower
- *   (unless an advanced selection of CPU features is used) as an
- *   otherwise config implies a properly working local APIC without
- *   the need to do extra reads from the APIC.
-*/
+ */
 
 static void __init check_config(void)
 {
@@ -151,21 +145,6 @@
 	if (boot_cpu_data.x86 == 3)
 		panic("Kernel requires i486+ for 'invlpg' and other features");
 #endif
-
-/*
- * If we were told we had a good local APIC, check for buggy Pentia,
- * i.e. all B steppings and the C2 stepping of P54C when using their
- * integrated APIC (see 11AP erratum in "Pentium Processor
- * Specification Update").
- */
-#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_GOOD_APIC)
-	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL
-	    && cpu_has_apic
-	    && boot_cpu_data.x86 == 5
-	    && boot_cpu_data.x86_model == 2
-	    && (boot_cpu_data.x86_mask < 6 || boot_cpu_data.x86_mask == 11))
-		panic("Kernel compiled for PMMX+, assumes a local APIC without the read-before-write bug!");
-#endif
 }
 
 
diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c
index 7b8cc72..dd6e3f1 100644
--- a/arch/x86/kernel/cpu/common_64.c
+++ b/arch/x86/kernel/cpu/common_64.c
@@ -7,15 +7,13 @@
 #include <linux/module.h>
 #include <linux/kgdb.h>
 #include <linux/topology.h>
-#include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/smp.h>
-#include <linux/module.h>
 #include <linux/percpu.h>
-#include <asm/processor.h>
 #include <asm/i387.h>
 #include <asm/msr.h>
 #include <asm/io.h>
+#include <asm/linkage.h>
 #include <asm/mmu_context.h>
 #include <asm/mtrr.h>
 #include <asm/mce.h>
@@ -305,7 +303,6 @@
 			c->x86_capability[2] = cpuid_edx(0x80860001);
 	}
 
-	c->extended_cpuid_level = cpuid_eax(0x80000000);
 	if (c->extended_cpuid_level >= 0x80000007)
 		c->x86_power = cpuid_edx(0x80000007);
 
@@ -316,18 +313,11 @@
 		c->x86_phys_bits = eax & 0xff;
 	}
 
-	/* Assume all 64-bit CPUs support 32-bit syscall */
-	set_cpu_cap(c, X86_FEATURE_SYSCALL32);
-
 	if (c->x86_vendor != X86_VENDOR_UNKNOWN &&
 	    cpu_devs[c->x86_vendor]->c_early_init)
 		cpu_devs[c->x86_vendor]->c_early_init(c);
 
 	validate_pat_support(c);
-
-	/* early_param could clear that, but recall get it set again */
-	if (disable_apic)
-		clear_cpu_cap(c, X86_FEATURE_APIC);
 }
 
 /*
@@ -517,8 +507,7 @@
 }
 
 char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ +
-			   DEBUG_STKSZ]
-__attribute__((section(".bss.page_aligned")));
+			   DEBUG_STKSZ] __page_aligned_bss;
 
 extern asmlinkage void ignore_sysret(void);
 
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k7.h b/arch/x86/kernel/cpu/cpufreq/powernow-k7.h
index f8a63b3..35fb4ea 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k7.h
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k7.h
@@ -1,5 +1,4 @@
 /*
- *  $Id: powernow-k7.h,v 1.2 2003/02/10 18:26:01 davej Exp $
  *  (C) 2003 Dave Jones.
  *
  *  Licensed under the terms of the GNU GPL License version 2.
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 70609ef..b75f256 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -227,6 +227,16 @@
 	if (cpu_has_bts)
 		ds_init_intel(c);
 
+	/*
+	 * See if we have a good local APIC by checking for buggy Pentia,
+	 * i.e. all B steppings and the C2 stepping of P54C when using their
+	 * integrated APIC (see 11AP erratum in "Pentium Processor
+	 * Specification Update").
+	 */
+	if (cpu_has_apic && (c->x86<<8 | c->x86_model<<4) == 0x520 &&
+	    (c->x86_mask < 0x6 || c->x86_mask == 0xb))
+		set_cpu_cap(c, X86_FEATURE_11AP);
+
 #ifdef CONFIG_X86_NUMAQ
 	numaq_tsc_disable();
 #endif
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
index e4b8d18..650d40f 100644
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -781,15 +781,14 @@
 			}
 			kobject_put(per_cpu(cache_kobject, cpu));
 			cpuid4_cache_sysfs_exit(cpu);
-			break;
+			return retval;
 		}
 		kobject_uevent(&(this_object->kobj), KOBJ_ADD);
 	}
-	if (!retval)
-		cpu_set(cpu, cache_dev_map);
+	cpu_set(cpu, cache_dev_map);
 
 	kobject_uevent(per_cpu(cache_kobject, cpu), KOBJ_ADD);
-	return retval;
+	return 0;
 }
 
 static void __cpuinit cache_remove_dev(struct sys_device * sys_dev)
diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c
index 2fe06ab..65a3396 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_64.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_64.c
@@ -762,10 +762,14 @@
 
 /* Why are there no generic functions for this? */
 #define ACCESSOR(name, var, start) \
-	static ssize_t show_ ## name(struct sys_device *s, char *buf) {	\
+	static ssize_t show_ ## name(struct sys_device *s,		\
+				     struct sysdev_attribute *attr,	\
+				     char *buf) {			\
 		return sprintf(buf, "%lx\n", (unsigned long)var);	\
 	}								\
-	static ssize_t set_ ## name(struct sys_device *s,const char *buf,size_t siz) { \
+	static ssize_t set_ ## name(struct sys_device *s,		\
+				    struct sysdev_attribute *attr,	\
+				    const char *buf, size_t siz) {	\
 		char *end;						\
 		unsigned long new = simple_strtoul(buf, &end, 0);	\
 		if (end == buf) return -EINVAL;				\
@@ -786,14 +790,16 @@
 ACCESSOR(bank4ctl,bank[4],mce_restart())
 ACCESSOR(bank5ctl,bank[5],mce_restart())
 
-static ssize_t show_trigger(struct sys_device *s, char *buf)
+static ssize_t show_trigger(struct sys_device *s, struct sysdev_attribute *attr,
+				char *buf)
 {
 	strcpy(buf, trigger);
 	strcat(buf, "\n");
 	return strlen(trigger) + 1;
 }
 
-static ssize_t set_trigger(struct sys_device *s,const char *buf,size_t siz)
+static ssize_t set_trigger(struct sys_device *s, struct sysdev_attribute *attr,
+				const char *buf,size_t siz)
 {
 	char *p;
 	int len;
@@ -806,12 +812,12 @@
 }
 
 static SYSDEV_ATTR(trigger, 0644, show_trigger, set_trigger);
-ACCESSOR(tolerant,tolerant,)
+static SYSDEV_INT_ATTR(tolerant, 0644, tolerant);
 ACCESSOR(check_interval,check_interval,mce_restart())
 static struct sysdev_attribute *mce_attributes[] = {
 	&attr_bank0ctl, &attr_bank1ctl, &attr_bank2ctl,
 	&attr_bank3ctl, &attr_bank4ctl, &attr_bank5ctl,
-	&attr_tolerant, &attr_check_interval, &attr_trigger,
+	&attr_tolerant.attr, &attr_check_interval, &attr_trigger,
 	NULL
 };
 
diff --git a/arch/x86/kernel/cpu/mcheck/p4.c b/arch/x86/kernel/cpu/mcheck/p4.c
index eef001a..9b60fce 100644
--- a/arch/x86/kernel/cpu/mcheck/p4.c
+++ b/arch/x86/kernel/cpu/mcheck/p4.c
@@ -102,7 +102,7 @@
 	/* The temperature transition interrupt handler setup */
 	h = THERMAL_APIC_VECTOR;		/* our delivery vector */
 	h |= (APIC_DM_FIXED | APIC_LVT_MASKED);	/* we'll mask till we're ready */
-	apic_write_around(APIC_LVTTHMR, h);
+	apic_write(APIC_LVTTHMR, h);
 
 	rdmsr(MSR_IA32_THERM_INTERRUPT, l, h);
 	wrmsr(MSR_IA32_THERM_INTERRUPT, l | 0x03 , h);
@@ -114,7 +114,7 @@
 	wrmsr(MSR_IA32_MISC_ENABLE, l | (1<<3), h);
 
 	l = apic_read(APIC_LVTTHMR);
-	apic_write_around(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
+	apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
 	printk(KERN_INFO "CPU%d: Thermal monitoring enabled\n", cpu);
 
 	/* enable thermal throttle processing */
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c
index 1f4cc48..d5ae224 100644
--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c
@@ -35,6 +35,7 @@
 
 #define define_therm_throt_sysdev_show_func(name)                            \
 static ssize_t therm_throt_sysdev_show_##name(struct sys_device *dev,        \
+					struct sysdev_attribute *attr,	     \
                                               char *buf)                     \
 {                                                                            \
 	unsigned int cpu = dev->id;                                          \
diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c
index 6d4bdc0..de7439f 100644
--- a/arch/x86/kernel/cpu/perfctr-watchdog.c
+++ b/arch/x86/kernel/cpu/perfctr-watchdog.c
@@ -250,7 +250,7 @@
 
 	do_div(count, nmi_hz);
 	if(descr)
-		Dprintk("setting %s to -0x%08Lx\n", descr, count);
+		pr_debug("setting %s to -0x%08Lx\n", descr, count);
 	wrmsrl(perfctr_msr, 0 - count);
 }
 
@@ -261,7 +261,7 @@
 
 	do_div(count, nmi_hz);
 	if(descr)
-		Dprintk("setting %s to -0x%08Lx\n", descr, count);
+		pr_debug("setting %s to -0x%08Lx\n", descr, count);
 	wrmsr(perfctr_msr, (u32)(-count), 0);
 }
 
diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c
index 2de5fa2..14b11b3 100644
--- a/arch/x86/kernel/cpuid.c
+++ b/arch/x86/kernel/cpuid.c
@@ -141,8 +141,8 @@
 {
 	struct device *dev;
 
-	dev = device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, cpu),
-			    "cpu%d", cpu);
+	dev = device_create_drvdata(cpuid_class, NULL, MKDEV(CPUID_MAJOR, cpu),
+				    NULL, "cpu%d", cpu);
 	return IS_ERR(dev) ? PTR_ERR(dev) : 0;
 }
 
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 28c2918..9af8907 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -877,7 +877,8 @@
 	for (i = 0; i < MAX_EARLY_RES && early_res[i].end; i++)
 		count++;
 
-	printk(KERN_INFO "(%d early reservations) ==> bootmem\n", count);
+	printk(KERN_INFO "(%d early reservations) ==> bootmem [%010llx - %010llx]\n",
+			 count, start, end);
 	for (i = 0; i < count; i++) {
 		struct early_res *r = &early_res[i];
 		printk(KERN_INFO "  #%d [%010llx - %010llx] %16s", i,
@@ -1298,11 +1299,6 @@
 	}
 }
 
-/*
- * Non-standard memory setup can be specified via this quirk:
- */
-char * (*arch_memory_setup_quirk)(void);
-
 char *__init default_machine_specific_memory_setup(void)
 {
 	char *who = "BIOS-e820";
@@ -1343,8 +1339,8 @@
 
 char *__init __attribute__((weak)) machine_specific_memory_setup(void)
 {
-	if (arch_memory_setup_quirk) {
-		char *who = arch_memory_setup_quirk();
+	if (x86_quirks->arch_memory_setup) {
+		char *who = x86_quirks->arch_memory_setup();
 
 		if (who)
 			return who;
@@ -1367,24 +1363,3 @@
 	printk(KERN_INFO "BIOS-provided physical RAM map:\n");
 	e820_print_map(who);
 }
-
-#ifdef CONFIG_X86_64
-int __init arch_get_ram_range(int slot, u64 *addr, u64 *size)
-{
-	int i;
-
-	if (slot < 0 || slot >= e820.nr_map)
-		return -1;
-	for (i = slot; i < e820.nr_map; i++) {
-		if (e820.map[i].type != E820_RAM)
-			continue;
-		break;
-	}
-	if (i == e820.nr_map || e820.map[i].addr > (max_pfn << PAGE_SHIFT))
-		return -1;
-	*addr = e820.map[i].addr;
-	*size = min_t(u64, e820.map[i].size + e820.map[i].addr,
-		max_pfn << PAGE_SHIFT) - *addr;
-	return i + 1;
-}
-#endif
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c
index a0e11c0..4353cf5 100644
--- a/arch/x86/kernel/early-quirks.c
+++ b/arch/x86/kernel/early-quirks.c
@@ -16,10 +16,7 @@
 #include <asm/dma.h>
 #include <asm/io_apic.h>
 #include <asm/apic.h>
-
-#ifdef CONFIG_GART_IOMMU
-#include <asm/gart.h>
-#endif
+#include <asm/iommu.h>
 
 static void __init fix_hypertransport_config(int num, int slot, int func)
 {
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index 6bc07f0..cdfd94c 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -332,7 +332,7 @@
 	GET_THREAD_INFO(%ebp)
 
 	/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
-	testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
+	testw $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
 	jnz syscall_trace_entry
 	cmpl $(nr_syscalls), %eax
 	jae syscall_badsys
@@ -370,7 +370,7 @@
 	GET_THREAD_INFO(%ebp)
 					# system call tracing in operation / emulation
 	/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
-	testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
+	testw $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
 	jnz syscall_trace_entry
 	cmpl $(nr_syscalls), %eax
 	jae syscall_badsys
@@ -383,10 +383,6 @@
 					# setting need_resched or sigpending
 					# between sampling and the iret
 	TRACE_IRQS_OFF
-	testl $X86_EFLAGS_TF,PT_EFLAGS(%esp)	# If tracing set singlestep flag on exit
-	jz no_singlestep
-	orl $_TIF_SINGLESTEP,TI_flags(%ebp)
-no_singlestep:
 	movl TI_flags(%ebp), %ecx
 	testw $_TIF_ALLWORK_MASK, %cx	# current->work
 	jne syscall_exit_work
@@ -514,12 +510,8 @@
 syscall_trace_entry:
 	movl $-ENOSYS,PT_EAX(%esp)
 	movl %esp, %eax
-	xorl %edx,%edx
-	call do_syscall_trace
-	cmpl $0, %eax
-	jne resume_userspace		# ret != 0 -> running under PTRACE_SYSEMU,
-					# so must skip actual syscall
-	movl PT_ORIG_EAX(%esp), %eax
+	call syscall_trace_enter
+	/* What it returned is what we'll actually use.  */
 	cmpl $(nr_syscalls), %eax
 	jnae syscall_call
 	jmp syscall_exit
@@ -528,14 +520,13 @@
 	# perform syscall exit tracing
 	ALIGN
 syscall_exit_work:
-	testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl
+	testb $_TIF_WORK_SYSCALL_EXIT, %cl
 	jz work_pending
 	TRACE_IRQS_ON
-	ENABLE_INTERRUPTS(CLBR_ANY)	# could let do_syscall_trace() call
+	ENABLE_INTERRUPTS(CLBR_ANY)	# could let syscall_trace_leave() call
 					# schedule() instead
 	movl %esp, %eax
-	movl $1, %edx
-	call do_syscall_trace
+	call syscall_trace_leave
 	jmp resume_userspace
 END(syscall_exit_work)
 	CFI_ENDPROC
@@ -1024,6 +1015,7 @@
 ENTRY(xen_sysenter_target)
 	RING0_INT_FRAME
 	addl $5*4, %esp		/* remove xen-provided frame */
+	CFI_ADJUST_CFA_OFFSET -5*4
 	jmp sysenter_past_esp
 	CFI_ENDPROC
 
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index ae63e58..8410e26 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -349,8 +349,7 @@
 	movq  %rcx,RIP-ARGOFFSET(%rsp)
 	CFI_REL_OFFSET rip,RIP-ARGOFFSET
 	GET_THREAD_INFO(%rcx)
-	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP), \
-		TI_flags(%rcx)
+	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%rcx)
 	jnz tracesys
 	cmpq $__NR_syscall_max,%rax
 	ja badsys
@@ -430,7 +429,12 @@
 	FIXUP_TOP_OF_STACK %rdi
 	movq %rsp,%rdi
 	call syscall_trace_enter
-	LOAD_ARGS ARGOFFSET  /* reload args from stack in case ptrace changed it */
+	/*
+	 * Reload arg registers from stack in case ptrace changed them.
+	 * We don't reload %rax because syscall_trace_enter() returned
+	 * the value it wants us to use in the table lookup.
+	 */
+	LOAD_ARGS ARGOFFSET, 1
 	RESTORE_REST
 	cmpq $__NR_syscall_max,%rax
 	ja   int_ret_from_sys_call	/* RAX(%rsp) set to -ENOSYS above */
@@ -483,7 +487,7 @@
 	ENABLE_INTERRUPTS(CLBR_NONE)
 	SAVE_REST
 	/* Check for syscall exit trace */	
-	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edx
+	testl $_TIF_WORK_SYSCALL_EXIT,%edx
 	jz int_signal
 	pushq %rdi
 	CFI_ADJUST_CFA_OFFSET 8
@@ -491,7 +495,7 @@
 	call syscall_trace_leave
 	popq %rdi
 	CFI_ADJUST_CFA_OFFSET -8
-	andl $~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edi
+	andl $~(_TIF_WORK_SYSCALL_EXIT|_TIF_SYSCALL_EMU),%edi
 	jmp int_restore_rest
 	
 int_signal:
@@ -1189,6 +1193,7 @@
 	/* runs on exception stack */
 KPROBE_ENTRY(debug)
  	INTR_FRAME
+	PARAVIRT_ADJUST_EXCEPTION_FRAME
 	pushq $0
 	CFI_ADJUST_CFA_OFFSET 8		
 	paranoidentry do_debug, DEBUG_STACK
@@ -1198,6 +1203,7 @@
 	/* runs on exception stack */	
 KPROBE_ENTRY(nmi)
 	INTR_FRAME
+	PARAVIRT_ADJUST_EXCEPTION_FRAME
 	pushq $-1
 	CFI_ADJUST_CFA_OFFSET 8
 	paranoidentry do_nmi, 0, 0
@@ -1211,6 +1217,7 @@
 
 KPROBE_ENTRY(int3)
  	INTR_FRAME
+	PARAVIRT_ADJUST_EXCEPTION_FRAME
  	pushq $0
  	CFI_ADJUST_CFA_OFFSET 8
  	paranoidentry do_int3, DEBUG_STACK
@@ -1237,6 +1244,7 @@
 	/* runs on exception stack */
 ENTRY(double_fault)
 	XCPT_FRAME
+	PARAVIRT_ADJUST_EXCEPTION_FRAME
 	paranoidentry do_double_fault
 	jmp paranoid_exit1
 	CFI_ENDPROC
@@ -1253,6 +1261,7 @@
 	/* runs on exception stack */
 ENTRY(stack_segment)
 	XCPT_FRAME
+	PARAVIRT_ADJUST_EXCEPTION_FRAME
 	paranoidentry do_stack_segment
 	jmp paranoid_exit1
 	CFI_ENDPROC
@@ -1278,6 +1287,7 @@
 	/* runs on exception stack */
 ENTRY(machine_check)
 	INTR_FRAME
+	PARAVIRT_ADJUST_EXCEPTION_FRAME
 	pushq $0
 	CFI_ADJUST_CFA_OFFSET 8	
 	paranoidentry do_machine_check
@@ -1312,3 +1322,103 @@
 	sysret
 	CFI_ENDPROC
 ENDPROC(ignore_sysret)
+
+#ifdef CONFIG_XEN
+ENTRY(xen_hypervisor_callback)
+	zeroentry xen_do_hypervisor_callback
+END(xen_hypervisor_callback)
+
+/*
+# A note on the "critical region" in our callback handler.
+# We want to avoid stacking callback handlers due to events occurring
+# during handling of the last event. To do this, we keep events disabled
+# until we've done all processing. HOWEVER, we must enable events before
+# popping the stack frame (can't be done atomically) and so it would still
+# be possible to get enough handler activations to overflow the stack.
+# Although unlikely, bugs of that kind are hard to track down, so we'd
+# like to avoid the possibility.
+# So, on entry to the handler we detect whether we interrupted an
+# existing activation in its critical region -- if so, we pop the current
+# activation and restart the handler using the previous one.
+*/
+ENTRY(xen_do_hypervisor_callback)   # do_hypervisor_callback(struct *pt_regs)
+	CFI_STARTPROC
+/* Since we don't modify %rdi, evtchn_do_upall(struct *pt_regs) will
+   see the correct pointer to the pt_regs */
+	movq %rdi, %rsp            # we don't return, adjust the stack frame
+	CFI_ENDPROC
+	CFI_DEFAULT_STACK
+11:	incl %gs:pda_irqcount
+	movq %rsp,%rbp
+	CFI_DEF_CFA_REGISTER rbp
+	cmovzq %gs:pda_irqstackptr,%rsp
+	pushq %rbp			# backlink for old unwinder
+	call xen_evtchn_do_upcall
+	popq %rsp
+	CFI_DEF_CFA_REGISTER rsp
+	decl %gs:pda_irqcount
+	jmp  error_exit
+	CFI_ENDPROC
+END(do_hypervisor_callback)
+
+/*
+# Hypervisor uses this for application faults while it executes.
+# We get here for two reasons:
+#  1. Fault while reloading DS, ES, FS or GS
+#  2. Fault while executing IRET
+# Category 1 we do not need to fix up as Xen has already reloaded all segment
+# registers that could be reloaded and zeroed the others.
+# Category 2 we fix up by killing the current process. We cannot use the
+# normal Linux return path in this case because if we use the IRET hypercall
+# to pop the stack frame we end up in an infinite loop of failsafe callbacks.
+# We distinguish between categories by comparing each saved segment register
+# with its current contents: any discrepancy means we in category 1.
+*/
+ENTRY(xen_failsafe_callback)
+	framesz = (RIP-0x30)	/* workaround buggy gas */
+	_frame framesz
+	CFI_REL_OFFSET rcx, 0
+	CFI_REL_OFFSET r11, 8
+	movw %ds,%cx
+	cmpw %cx,0x10(%rsp)
+	CFI_REMEMBER_STATE
+	jne 1f
+	movw %es,%cx
+	cmpw %cx,0x18(%rsp)
+	jne 1f
+	movw %fs,%cx
+	cmpw %cx,0x20(%rsp)
+	jne 1f
+	movw %gs,%cx
+	cmpw %cx,0x28(%rsp)
+	jne 1f
+	/* All segments match their saved values => Category 2 (Bad IRET). */
+	movq (%rsp),%rcx
+	CFI_RESTORE rcx
+	movq 8(%rsp),%r11
+	CFI_RESTORE r11
+	addq $0x30,%rsp
+	CFI_ADJUST_CFA_OFFSET -0x30
+	pushq $0
+	CFI_ADJUST_CFA_OFFSET 8
+	pushq %r11
+	CFI_ADJUST_CFA_OFFSET 8
+	pushq %rcx
+	CFI_ADJUST_CFA_OFFSET 8
+	jmp general_protection
+	CFI_RESTORE_STATE
+1:	/* Segment mismatch => Category 1 (Bad segment). Retry the IRET. */
+	movq (%rsp),%rcx
+	CFI_RESTORE rcx
+	movq 8(%rsp),%r11
+	CFI_RESTORE r11
+	addq $0x30,%rsp
+	CFI_ADJUST_CFA_OFFSET -0x30
+	pushq $0
+	CFI_ADJUST_CFA_OFFSET 8
+	SAVE_ALL
+	jmp error_exit
+	CFI_ENDPROC
+END(xen_failsafe_callback)
+
+#endif /* CONFIG_XEN */
diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c
index 3e5d7b8..2cfcbde 100644
--- a/arch/x86/kernel/genx2apic_uv_x.c
+++ b/arch/x86/kernel/genx2apic_uv_x.c
@@ -24,6 +24,7 @@
 #include <asm/pgtable.h>
 #include <asm/uv/uv_mmrs.h>
 #include <asm/uv/uv_hub.h>
+#include <asm/uv/bios.h>
 
 DEFINE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
 EXPORT_PER_CPU_SYMBOL_GPL(__uv_hub_info);
@@ -40,6 +41,9 @@
 short uv_possible_blades;
 EXPORT_SYMBOL_GPL(uv_possible_blades);
 
+unsigned long sn_rtc_cycles_per_second;
+EXPORT_SYMBOL(sn_rtc_cycles_per_second);
+
 /* Start with all IRQs pointing to boot CPU.  IRQ balancing will shift them. */
 
 static cpumask_t uv_target_cpus(void)
@@ -272,6 +276,23 @@
 		map_high("MMIOH", mmioh.s.base, shift, map_uc);
 }
 
+static __init void uv_rtc_init(void)
+{
+	long status, ticks_per_sec, drift;
+
+	status =
+	    x86_bios_freq_base(BIOS_FREQ_BASE_REALTIME_CLOCK, &ticks_per_sec,
+					&drift);
+	if (status != 0 || ticks_per_sec < 100000) {
+		printk(KERN_WARNING
+			"unable to determine platform RTC clock frequency, "
+			"guessing.\n");
+		/* BIOS gives wrong value for clock freq. so guess */
+		sn_rtc_cycles_per_second = 1000000000000UL / 30000UL;
+	} else
+		sn_rtc_cycles_per_second = ticks_per_sec;
+}
+
 static __init void uv_system_init(void)
 {
 	union uvh_si_addr_map_config_u m_n_config;
@@ -326,6 +347,8 @@
 	gnode_upper = (((unsigned long)node_id.s.node_id) &
 		       ~((1 << n_val) - 1)) << m_val;
 
+	uv_rtc_init();
+
 	for_each_present_cpu(cpu) {
 		nid = cpu_to_node(cpu);
 		pnode = uv_apicid_to_pnode(per_cpu(x86_cpu_to_apicid, cpu));
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index c978198..1b318e9 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -39,6 +39,13 @@
 static struct x8664_pda *__cpu_pda[NR_CPUS] __read_mostly;
 #endif
 
+void __init x86_64_init_pda(void)
+{
+	_cpu_pda = __cpu_pda;
+	cpu_pda(0) = &_boot_cpu_pda;
+	pda_init(0);
+}
+
 static void __init zap_identity_mappings(void)
 {
 	pgd_t *pgd = pgd_offset_k(0UL);
@@ -102,9 +109,7 @@
 
 	early_printk("Kernel alive\n");
 
-	_cpu_pda = __cpu_pda;
-	cpu_pda(0) = &_boot_cpu_pda;
-	pda_init(0);
+	x86_64_init_pda();
 
 	early_printk("Kernel really alive\n");
 
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index b07ac7b..db3280a 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -407,6 +407,7 @@
 	/* This must match the first entry in level2_kernel_pgt */
 	.quad   0x0000000000000000
 
+#include "../../x86/xen/xen-head.S"
 	
 	.section .bss, "aw", @nobits
 	.align L1_CACHE_BYTES
diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c
index 558abf4..de9aa0e 100644
--- a/arch/x86/kernel/io_apic_32.c
+++ b/arch/x86/kernel/io_apic_32.c
@@ -756,7 +756,7 @@
 	/*
 	 * Send the IPI. The write to APIC_ICR fires this off.
 	 */
-	apic_write_around(APIC_ICR, cfg);
+	apic_write(APIC_ICR, cfg);
 }
 #endif /* !CONFIG_SMP */
 
@@ -2030,7 +2030,7 @@
 	unsigned long v;
 
 	v = apic_read(APIC_LVT0);
-	apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED);
+	apic_write(APIC_LVT0, v | APIC_LVT_MASKED);
 }
 
 static void unmask_lapic_irq(unsigned int irq)
@@ -2038,7 +2038,7 @@
 	unsigned long v;
 
 	v = apic_read(APIC_LVT0);
-	apic_write_around(APIC_LVT0, v & ~APIC_LVT_MASKED);
+	apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED);
 }
 
 static struct irq_chip lapic_chip __read_mostly = {
@@ -2168,7 +2168,7 @@
 	 * The AEOI mode will finish them in the 8259A
 	 * automatically.
 	 */
-	apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
+	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
 	init_8259A(1);
 	timer_ack = (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver));
 
@@ -2177,8 +2177,9 @@
 	pin2  = ioapic_i8259.pin;
 	apic2 = ioapic_i8259.apic;
 
-	printk(KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
-		vector, apic1, pin1, apic2, pin2);
+	apic_printk(APIC_QUIET, KERN_INFO "..TIMER: vector=0x%02X "
+		    "apic1=%d pin1=%d apic2=%d pin2=%d\n",
+		    vector, apic1, pin1, apic2, pin2);
 
 	/*
 	 * Some BIOS writers are clueless and report the ExtINTA
@@ -2216,12 +2217,13 @@
 		}
 		clear_IO_APIC_pin(apic1, pin1);
 		if (!no_pin1)
-			printk(KERN_ERR "..MP-BIOS bug: "
-			       "8254 timer not connected to IO-APIC\n");
+			apic_printk(APIC_QUIET, KERN_ERR "..MP-BIOS bug: "
+				    "8254 timer not connected to IO-APIC\n");
 
-		printk(KERN_INFO "...trying to set up timer (IRQ0) "
-		       "through the 8259A ... ");
-		printk("\n..... (found pin %d) ...", pin2);
+		apic_printk(APIC_QUIET, KERN_INFO "...trying to set up timer "
+			    "(IRQ0) through the 8259A ...\n");
+		apic_printk(APIC_QUIET, KERN_INFO
+			    "..... (found apic %d pin %d) ...\n", apic2, pin2);
 		/*
 		 * legacy devices should be connected to IO APIC #0
 		 */
@@ -2230,7 +2232,7 @@
 		unmask_IO_APIC_irq(0);
 		enable_8259A_irq(0);
 		if (timer_irq_works()) {
-			printk("works.\n");
+			apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
 			timer_through_8259 = 1;
 			if (nmi_watchdog == NMI_IO_APIC) {
 				disable_8259A_irq(0);
@@ -2244,44 +2246,47 @@
 		 */
 		disable_8259A_irq(0);
 		clear_IO_APIC_pin(apic2, pin2);
-		printk(" failed.\n");
+		apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n");
 	}
 
 	if (nmi_watchdog == NMI_IO_APIC) {
-		printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n");
+		apic_printk(APIC_QUIET, KERN_WARNING "timer doesn't work "
+			    "through the IO-APIC - disabling NMI Watchdog!\n");
 		nmi_watchdog = NMI_NONE;
 	}
 	timer_ack = 0;
 
-	printk(KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");
+	apic_printk(APIC_QUIET, KERN_INFO
+		    "...trying to set up timer as Virtual Wire IRQ...\n");
 
 	lapic_register_intr(0, vector);
-	apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector);	/* Fixed mode */
+	apic_write(APIC_LVT0, APIC_DM_FIXED | vector);	/* Fixed mode */
 	enable_8259A_irq(0);
 
 	if (timer_irq_works()) {
-		printk(" works.\n");
+		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
 		goto out;
 	}
 	disable_8259A_irq(0);
-	apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
-	printk(" failed.\n");
+	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
+	apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n");
 
-	printk(KERN_INFO "...trying to set up timer as ExtINT IRQ...");
+	apic_printk(APIC_QUIET, KERN_INFO
+		    "...trying to set up timer as ExtINT IRQ...\n");
 
 	init_8259A(0);
 	make_8259A_irq(0);
-	apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
+	apic_write(APIC_LVT0, APIC_DM_EXTINT);
 
 	unlock_ExtINT_logic();
 
 	if (timer_irq_works()) {
-		printk(" works.\n");
+		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
 		goto out;
 	}
-	printk(" failed :(.\n");
+	apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n");
 	panic("IO-APIC + timer doesn't work!  Boot with apic=debug and send a "
-		"report.  Then try booting with the 'noapic' option");
+		"report.  Then try booting with the 'noapic' option.\n");
 out:
 	local_irq_restore(flags);
 }
diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c
index a85db79..8269434 100644
--- a/arch/x86/kernel/io_apic_64.c
+++ b/arch/x86/kernel/io_apic_64.c
@@ -45,6 +45,7 @@
 #include <asm/proto.h>
 #include <asm/acpi.h>
 #include <asm/dma.h>
+#include <asm/i8259.h>
 #include <asm/nmi.h>
 #include <asm/msidef.h>
 #include <asm/hypertransport.h>
@@ -1694,8 +1695,9 @@
 	pin2  = ioapic_i8259.pin;
 	apic2 = ioapic_i8259.apic;
 
-	apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
-		cfg->vector, apic1, pin1, apic2, pin2);
+	apic_printk(APIC_QUIET, KERN_INFO "..TIMER: vector=0x%02X "
+		    "apic1=%d pin1=%d apic2=%d pin2=%d\n",
+		    cfg->vector, apic1, pin1, apic2, pin2);
 
 	/*
 	 * Some BIOS writers are clueless and report the ExtINTA
@@ -1733,14 +1735,13 @@
 		}
 		clear_IO_APIC_pin(apic1, pin1);
 		if (!no_pin1)
-			apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: "
+			apic_printk(APIC_QUIET, KERN_ERR "..MP-BIOS bug: "
 				    "8254 timer not connected to IO-APIC\n");
 
-		apic_printk(APIC_VERBOSE,KERN_INFO
-			"...trying to set up timer (IRQ0) "
-			"through the 8259A ... ");
-		apic_printk(APIC_VERBOSE,"\n..... (found apic %d pin %d) ...",
-			apic2, pin2);
+		apic_printk(APIC_QUIET, KERN_INFO "...trying to set up timer "
+			    "(IRQ0) through the 8259A ...\n");
+		apic_printk(APIC_QUIET, KERN_INFO
+			    "..... (found apic %d pin %d) ...\n", apic2, pin2);
 		/*
 		 * legacy devices should be connected to IO APIC #0
 		 */
@@ -1749,7 +1750,7 @@
 		unmask_IO_APIC_irq(0);
 		enable_8259A_irq(0);
 		if (timer_irq_works()) {
-			apic_printk(APIC_VERBOSE," works.\n");
+			apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
 			timer_through_8259 = 1;
 			if (nmi_watchdog == NMI_IO_APIC) {
 				disable_8259A_irq(0);
@@ -1763,29 +1764,32 @@
 		 */
 		disable_8259A_irq(0);
 		clear_IO_APIC_pin(apic2, pin2);
-		apic_printk(APIC_VERBOSE," failed.\n");
+		apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n");
 	}
 
 	if (nmi_watchdog == NMI_IO_APIC) {
-		printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n");
+		apic_printk(APIC_QUIET, KERN_WARNING "timer doesn't work "
+			    "through the IO-APIC - disabling NMI Watchdog!\n");
 		nmi_watchdog = NMI_NONE;
 	}
 
-	apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");
+	apic_printk(APIC_QUIET, KERN_INFO
+		    "...trying to set up timer as Virtual Wire IRQ...\n");
 
 	lapic_register_intr(0);
 	apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector);	/* Fixed mode */
 	enable_8259A_irq(0);
 
 	if (timer_irq_works()) {
-		apic_printk(APIC_VERBOSE," works.\n");
+		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
 		goto out;
 	}
 	disable_8259A_irq(0);
 	apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
-	apic_printk(APIC_VERBOSE," failed.\n");
+	apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n");
 
-	apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as ExtINT IRQ...");
+	apic_printk(APIC_QUIET, KERN_INFO
+		    "...trying to set up timer as ExtINT IRQ...\n");
 
 	init_8259A(0);
 	make_8259A_irq(0);
@@ -1794,11 +1798,12 @@
 	unlock_ExtINT_logic();
 
 	if (timer_irq_works()) {
-		apic_printk(APIC_VERBOSE," works.\n");
+		apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
 		goto out;
 	}
-	apic_printk(APIC_VERBOSE," failed :(.\n");
-	panic("IO-APIC + timer doesn't work! Try using the 'noapic' kernel parameter\n");
+	apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n");
+	panic("IO-APIC + timer doesn't work!  Boot with apic=debug and send a "
+		"report.  Then try booting with the 'noapic' option.\n");
 out:
 	local_irq_restore(flags);
 }
diff --git a/arch/x86/kernel/io_delay.c b/arch/x86/kernel/io_delay.c
index 5921e5f..1c3a66a6 100644
--- a/arch/x86/kernel/io_delay.c
+++ b/arch/x86/kernel/io_delay.c
@@ -103,6 +103,9 @@
 
 static int __init io_delay_param(char *s)
 {
+	if (!s)
+		return -EINVAL;
+
 	if (!strcmp(s, "0x80"))
 		io_delay_type = CONFIG_IO_DELAY_TYPE_0X80;
 	else if (!strcmp(s, "0xed"))
diff --git a/arch/x86/kernel/ipi.c b/arch/x86/kernel/ipi.c
index 9d98cda..3f7537b 100644
--- a/arch/x86/kernel/ipi.c
+++ b/arch/x86/kernel/ipi.c
@@ -70,7 +70,7 @@
 	/*
 	 * Send the IPI. The write to APIC_ICR fires this off.
 	 */
-	apic_write_around(APIC_ICR, cfg);
+	apic_write(APIC_ICR, cfg);
 }
 
 void send_IPI_self(int vector)
@@ -98,7 +98,7 @@
 	 * prepare target chip field
 	 */
 	cfg = __prepare_ICR2(mask);
-	apic_write_around(APIC_ICR2, cfg);
+	apic_write(APIC_ICR2, cfg);
 
 	/*
 	 * program the ICR
@@ -108,7 +108,7 @@
 	/*
 	 * Send the IPI. The write to APIC_ICR fires this off.
 	 */
-	apic_write_around(APIC_ICR, cfg);
+	apic_write(APIC_ICR, cfg);
 }
 
 /*
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c
index 47a6f6f..1cf8c1f 100644
--- a/arch/x86/kernel/irq_32.c
+++ b/arch/x86/kernel/irq_32.c
@@ -83,11 +83,8 @@
 static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly;
 static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly;
 
-static char softirq_stack[NR_CPUS * THREAD_SIZE]
-		__attribute__((__section__(".bss.page_aligned")));
-
-static char hardirq_stack[NR_CPUS * THREAD_SIZE]
-		__attribute__((__section__(".bss.page_aligned")));
+static char softirq_stack[NR_CPUS * THREAD_SIZE] __page_aligned_bss;
+static char hardirq_stack[NR_CPUS * THREAD_SIZE] __page_aligned_bss;
 
 static void call_on_stack(void *func, void *stack)
 {
diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c
index c032059..f2d43bc 100644
--- a/arch/x86/kernel/kdebugfs.c
+++ b/arch/x86/kernel/kdebugfs.c
@@ -12,9 +12,13 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/mm.h>
+#include <linux/module.h>
 
 #include <asm/setup.h>
 
+struct dentry *arch_debugfs_dir;
+EXPORT_SYMBOL(arch_debugfs_dir);
+
 #ifdef CONFIG_DEBUG_BOOT_PARAMS
 struct setup_data_node {
 	u64 paddr;
@@ -209,6 +213,10 @@
 {
 	int error = 0;
 
+	arch_debugfs_dir = debugfs_create_dir("x86", NULL);
+	if (!arch_debugfs_dir)
+		return -ENOMEM;
+
 #ifdef CONFIG_DEBUG_BOOT_PARAMS
 	error = boot_params_kdebugfs_init();
 #endif
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
index b8c6743..43c019f 100644
--- a/arch/x86/kernel/kprobes.c
+++ b/arch/x86/kernel/kprobes.c
@@ -860,7 +860,6 @@
 
 	resume_execution(cur, regs, kcb);
 	regs->flags |= kcb->kprobe_saved_flags;
-	trace_hardirqs_fixup_flags(regs->flags);
 
 	if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
 		kcb->kprobe_status = KPROBE_HIT_SSDONE;
diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c
index 5852016..6994c75 100644
--- a/arch/x86/kernel/microcode.c
+++ b/arch/x86/kernel/microcode.c
@@ -648,7 +648,9 @@
 	mutex_unlock(&microcode_mutex);
 }
 
-static ssize_t reload_store(struct sys_device *dev, const char *buf, size_t sz)
+static ssize_t reload_store(struct sys_device *dev,
+			    struct sysdev_attribute *attr,
+			    const char *buf, size_t sz)
 {
 	struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
 	char *end;
@@ -679,14 +681,16 @@
 	return sz;
 }
 
-static ssize_t version_show(struct sys_device *dev, char *buf)
+static ssize_t version_show(struct sys_device *dev,
+			struct sysdev_attribute *attr, char *buf)
 {
 	struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
 
 	return sprintf(buf, "0x%x\n", uci->rev);
 }
 
-static ssize_t pf_show(struct sys_device *dev, char *buf)
+static ssize_t pf_show(struct sys_device *dev,
+			struct sysdev_attribute *attr, char *buf)
 {
 	struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
 
diff --git a/arch/x86/kernel/module_64.c b/arch/x86/kernel/module_64.c
index a888e67..0e86767 100644
--- a/arch/x86/kernel/module_64.c
+++ b/arch/x86/kernel/module_64.c
@@ -150,7 +150,8 @@
                     const Elf_Shdr *sechdrs,
                     struct module *me)
 {
-	const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL;
+	const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL,
+		*para = NULL;
 	char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
 
 	for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
@@ -160,6 +161,8 @@
 			alt = s;
 		if (!strcmp(".smp_locks", secstrings + s->sh_name))
 			locks= s;
+		if (!strcmp(".parainstructions", secstrings + s->sh_name))
+			para = s;
 	}
 
 	if (alt) {
@@ -175,6 +178,11 @@
 					    tseg, tseg + text->sh_size);
 	}
 
+	if (para) {
+		void *pseg = (void *)para->sh_addr;
+		apply_paravirt(pseg, pseg + para->sh_size);
+	}
+
 	return module_bug_finalize(hdr, sechdrs, me);
 }
 
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index 3b25e49..6ae005c 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -27,6 +27,7 @@
 #include <asm/bios_ebda.h>
 #include <asm/e820.h>
 #include <asm/trampoline.h>
+#include <asm/setup.h>
 
 #include <mach_apic.h>
 #ifdef CONFIG_X86_32
@@ -48,76 +49,6 @@
 	return sum & 0xFF;
 }
 
-#ifdef CONFIG_X86_NUMAQ
-int found_numaq;
-/*
- * Have to match translation table entries to main table entries by counter
- * hence the mpc_record variable .... can't see a less disgusting way of
- * doing this ....
- */
-struct mpc_config_translation {
-	unsigned char mpc_type;
-	unsigned char trans_len;
-	unsigned char trans_type;
-	unsigned char trans_quad;
-	unsigned char trans_global;
-	unsigned char trans_local;
-	unsigned short trans_reserved;
-};
-
-
-static int mpc_record;
-static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY]
-    __cpuinitdata;
-
-static inline int generate_logical_apicid(int quad, int phys_apicid)
-{
-	return (quad << 4) + (phys_apicid ? phys_apicid << 1 : 1);
-}
-
-
-static inline int mpc_apic_id(struct mpc_config_processor *m,
-			struct mpc_config_translation *translation_record)
-{
-	int quad = translation_record->trans_quad;
-	int logical_apicid = generate_logical_apicid(quad, m->mpc_apicid);
-
-	printk(KERN_DEBUG "Processor #%d %u:%u APIC version %d (quad %d, apic %d)\n",
-	       m->mpc_apicid,
-	       (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8,
-	       (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4,
-	       m->mpc_apicver, quad, logical_apicid);
-	return logical_apicid;
-}
-
-int mp_bus_id_to_node[MAX_MP_BUSSES];
-
-int mp_bus_id_to_local[MAX_MP_BUSSES];
-
-static void mpc_oem_bus_info(struct mpc_config_bus *m, char *name,
-	struct mpc_config_translation *translation)
-{
-	int quad = translation->trans_quad;
-	int local = translation->trans_local;
-
-	mp_bus_id_to_node[m->mpc_busid] = quad;
-	mp_bus_id_to_local[m->mpc_busid] = local;
-	printk(KERN_INFO "Bus #%d is %s (node %d)\n",
-	       m->mpc_busid, name, quad);
-}
-
-int quad_local_to_mp_bus_id [NR_CPUS/4][4];
-static void mpc_oem_pci_bus(struct mpc_config_bus *m,
-	struct mpc_config_translation *translation)
-{
-	int quad = translation->trans_quad;
-	int local = translation->trans_local;
-
-	quad_local_to_mp_bus_id[quad][local] = m->mpc_busid;
-}
-
-#endif
-
 static void __cpuinit MP_processor_info(struct mpc_config_processor *m)
 {
 	int apicid;
@@ -127,14 +58,12 @@
 		disabled_cpus++;
 		return;
 	}
-#ifdef CONFIG_X86_NUMAQ
-	if (found_numaq)
-		apicid = mpc_apic_id(m, translation_table[mpc_record]);
+
+	if (x86_quirks->mpc_apic_id)
+		apicid = x86_quirks->mpc_apic_id(m);
 	else
 		apicid = m->mpc_apicid;
-#else
-	apicid = m->mpc_apicid;
-#endif
+
 	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
 		bootup_cpu = " (Bootup-CPU)";
 		boot_cpu_physical_apicid = m->mpc_apicid;
@@ -151,12 +80,10 @@
 	memcpy(str, m->mpc_bustype, 6);
 	str[6] = 0;
 
-#ifdef CONFIG_X86_NUMAQ
-	if (found_numaq)
-		mpc_oem_bus_info(m, str, translation_table[mpc_record]);
-#else
-	printk(KERN_INFO "Bus #%d is %s\n", m->mpc_busid, str);
-#endif
+	if (x86_quirks->mpc_oem_bus_info)
+		x86_quirks->mpc_oem_bus_info(m, str);
+	else
+		printk(KERN_INFO "Bus #%d is %s\n", m->mpc_busid, str);
 
 #if MAX_MP_BUSSES < 256
 	if (m->mpc_busid >= MAX_MP_BUSSES) {
@@ -173,10 +100,9 @@
 		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
 #endif
 	} else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI) - 1) == 0) {
-#ifdef CONFIG_X86_NUMAQ
-		if (found_numaq)
-			mpc_oem_pci_bus(m, translation_table[mpc_record]);
-#endif
+		if (x86_quirks->mpc_oem_pci_bus)
+			x86_quirks->mpc_oem_pci_bus(m);
+
 		clear_bit(m->mpc_busid, mp_bus_not_pci);
 #if defined(CONFIG_EISA) || defined (CONFIG_MCA)
 		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
@@ -316,83 +242,6 @@
 		m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
 }
 
-#ifdef CONFIG_X86_NUMAQ
-static void __init MP_translation_info(struct mpc_config_translation *m)
-{
-	printk(KERN_INFO
-	       "Translation: record %d, type %d, quad %d, global %d, local %d\n",
-	       mpc_record, m->trans_type, m->trans_quad, m->trans_global,
-	       m->trans_local);
-
-	if (mpc_record >= MAX_MPC_ENTRY)
-		printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n");
-	else
-		translation_table[mpc_record] = m;	/* stash this for later */
-	if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad))
-		node_set_online(m->trans_quad);
-}
-
-/*
- * Read/parse the MPC oem tables
- */
-
-static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable,
-				    unsigned short oemsize)
-{
-	int count = sizeof(*oemtable);	/* the header size */
-	unsigned char *oemptr = ((unsigned char *)oemtable) + count;
-
-	mpc_record = 0;
-	printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n",
-	       oemtable);
-	if (memcmp(oemtable->oem_signature, MPC_OEM_SIGNATURE, 4)) {
-		printk(KERN_WARNING
-		       "SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
-		       oemtable->oem_signature[0], oemtable->oem_signature[1],
-		       oemtable->oem_signature[2], oemtable->oem_signature[3]);
-		return;
-	}
-	if (mpf_checksum((unsigned char *)oemtable, oemtable->oem_length)) {
-		printk(KERN_WARNING "SMP oem mptable: checksum error!\n");
-		return;
-	}
-	while (count < oemtable->oem_length) {
-		switch (*oemptr) {
-		case MP_TRANSLATION:
-			{
-				struct mpc_config_translation *m =
-				    (struct mpc_config_translation *)oemptr;
-				MP_translation_info(m);
-				oemptr += sizeof(*m);
-				count += sizeof(*m);
-				++mpc_record;
-				break;
-			}
-		default:
-			{
-				printk(KERN_WARNING
-				       "Unrecognised OEM table entry type! - %d\n",
-				       (int)*oemptr);
-				return;
-			}
-		}
-	}
-}
-
-void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem,
-				 char *productid)
-{
-	if (strncmp(oem, "IBM NUMA", 8))
-		printk("Warning!  Not a NUMA-Q system!\n");
-	else
-		found_numaq = 1;
-
-	if (mpc->mpc_oemptr)
-		smp_read_mpc_oem((struct mp_config_oemtable *)mpc->mpc_oemptr,
-				 mpc->mpc_oemsize);
-}
-#endif /* CONFIG_X86_NUMAQ */
-
 /*
  * Read/parse the MPC
  */
@@ -457,7 +306,6 @@
 	} else
 		mps_oem_check(mpc, oem, str);
 #endif
-
 	/* save the local APIC address, it might be non-default */
 	if (!acpi_lapic)
 		mp_lapic_addr = mpc->mpc_lapic;
@@ -465,12 +313,17 @@
 	if (early)
 		return 1;
 
+	if (mpc->mpc_oemptr && x86_quirks->smp_read_mpc_oem) {
+		struct mp_config_oemtable *oem_table = (struct mp_config_oemtable *)(unsigned long)mpc->mpc_oemptr;
+		x86_quirks->smp_read_mpc_oem(oem_table, mpc->mpc_oemsize);
+	}
+
 	/*
 	 *      Now process the configuration blocks.
 	 */
-#ifdef CONFIG_X86_NUMAQ
-	mpc_record = 0;
-#endif
+	if (x86_quirks->mpc_record)
+		*x86_quirks->mpc_record = 0;
+
 	while (count < mpc->mpc_length) {
 		switch (*mpt) {
 		case MP_PROCESSOR:
@@ -536,9 +389,8 @@
 			count = mpc->mpc_length;
 			break;
 		}
-#ifdef CONFIG_X86_NUMAQ
-		++mpc_record;
-#endif
+		if (x86_quirks->mpc_record)
+			(*x86_quirks->mpc_record)++;
 	}
 
 #ifdef CONFIG_X86_GENERICARCH
@@ -726,20 +578,14 @@
 static struct intel_mp_floating *mpf_found;
 
 /*
- * Machine specific quirk for finding the SMP config before other setup
- * activities destroy the table:
- */
-int (*mach_get_smp_config_quirk)(unsigned int early);
-
-/*
  * Scan the memory blocks for an SMP configuration block.
  */
 static void __init __get_smp_config(unsigned int early)
 {
 	struct intel_mp_floating *mpf = mpf_found;
 
-	if (mach_get_smp_config_quirk) {
-		if (mach_get_smp_config_quirk(early))
+	if (x86_quirks->mach_get_smp_config) {
+		if (x86_quirks->mach_get_smp_config(early))
 			return;
 	}
 	if (acpi_lapic && early)
@@ -899,14 +745,12 @@
 	return 0;
 }
 
-int (*mach_find_smp_config_quirk)(unsigned int reserve);
-
 static void __init __find_smp_config(unsigned int reserve)
 {
 	unsigned int address;
 
-	if (mach_find_smp_config_quirk) {
-		if (mach_find_smp_config_quirk(reserve))
+	if (x86_quirks->mach_find_smp_config) {
+		if (x86_quirks->mach_find_smp_config(reserve))
 			return;
 	}
 	/*
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
index a153b39..9fd80955 100644
--- a/arch/x86/kernel/msr.c
+++ b/arch/x86/kernel/msr.c
@@ -149,8 +149,8 @@
 {
 	struct device *dev;
 
-	dev = device_create(msr_class, NULL, MKDEV(MSR_MAJOR, cpu),
-			    "msr%d", cpu);
+	dev = device_create_drvdata(msr_class, NULL, MKDEV(MSR_MAJOR, cpu),
+				    NULL, "msr%d", cpu);
 	return IS_ERR(dev) ? PTR_ERR(dev) : 0;
 }
 
diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c
index ec024b3..ac6d512 100644
--- a/arch/x86/kernel/nmi.c
+++ b/arch/x86/kernel/nmi.c
@@ -263,7 +263,7 @@
 
 static void __acpi_nmi_enable(void *__unused)
 {
-	apic_write_around(APIC_LVT0, APIC_DM_NMI);
+	apic_write(APIC_LVT0, APIC_DM_NMI);
 }
 
 /*
@@ -277,7 +277,7 @@
 
 static void __acpi_nmi_disable(void *__unused)
 {
-	apic_write_around(APIC_LVT0, APIC_DM_NMI | APIC_LVT_MASKED);
+	apic_write(APIC_LVT0, APIC_DM_NMI | APIC_LVT_MASKED);
 }
 
 /*
@@ -448,6 +448,13 @@
 
 #ifdef CONFIG_SYSCTL
 
+static int __init setup_unknown_nmi_panic(char *str)
+{
+	unknown_nmi_panic = 1;
+	return 1;
+}
+__setup("unknown_nmi_panic", setup_unknown_nmi_panic);
+
 static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu)
 {
 	unsigned char reason = get_nmi_reason();
diff --git a/arch/x86/kernel/numaq_32.c b/arch/x86/kernel/numaq_32.c
index a23e823..b8c4561 100644
--- a/arch/x86/kernel/numaq_32.c
+++ b/arch/x86/kernel/numaq_32.c
@@ -33,6 +33,7 @@
 #include <asm/processor.h>
 #include <asm/mpspec.h>
 #include <asm/e820.h>
+#include <asm/setup.h>
 
 #define	MB_TO_PAGES(addr) ((addr) << (20 - PAGE_SHIFT))
 
@@ -71,6 +72,188 @@
 	}
 }
 
+
+void __init numaq_tsc_disable(void)
+{
+	if (!found_numaq)
+		return;
+
+	if (num_online_nodes() > 1) {
+		printk(KERN_DEBUG "NUMAQ: disabling TSC\n");
+		setup_clear_cpu_cap(X86_FEATURE_TSC);
+	}
+}
+
+static int __init numaq_pre_time_init(void)
+{
+	numaq_tsc_disable();
+	return 0;
+}
+
+int found_numaq;
+/*
+ * Have to match translation table entries to main table entries by counter
+ * hence the mpc_record variable .... can't see a less disgusting way of
+ * doing this ....
+ */
+struct mpc_config_translation {
+	unsigned char mpc_type;
+	unsigned char trans_len;
+	unsigned char trans_type;
+	unsigned char trans_quad;
+	unsigned char trans_global;
+	unsigned char trans_local;
+	unsigned short trans_reserved;
+};
+
+/* x86_quirks member */
+static int mpc_record;
+static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY]
+    __cpuinitdata;
+
+static inline int generate_logical_apicid(int quad, int phys_apicid)
+{
+	return (quad << 4) + (phys_apicid ? phys_apicid << 1 : 1);
+}
+
+/* x86_quirks member */
+static int mpc_apic_id(struct mpc_config_processor *m)
+{
+	int quad = translation_table[mpc_record]->trans_quad;
+	int logical_apicid = generate_logical_apicid(quad, m->mpc_apicid);
+
+	printk(KERN_DEBUG "Processor #%d %u:%u APIC version %d (quad %d, apic %d)\n",
+	       m->mpc_apicid,
+	       (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8,
+	       (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4,
+	       m->mpc_apicver, quad, logical_apicid);
+	return logical_apicid;
+}
+
+int mp_bus_id_to_node[MAX_MP_BUSSES];
+
+int mp_bus_id_to_local[MAX_MP_BUSSES];
+
+/* x86_quirks member */
+static void mpc_oem_bus_info(struct mpc_config_bus *m, char *name)
+{
+	int quad = translation_table[mpc_record]->trans_quad;
+	int local = translation_table[mpc_record]->trans_local;
+
+	mp_bus_id_to_node[m->mpc_busid] = quad;
+	mp_bus_id_to_local[m->mpc_busid] = local;
+	printk(KERN_INFO "Bus #%d is %s (node %d)\n",
+	       m->mpc_busid, name, quad);
+}
+
+int quad_local_to_mp_bus_id [NR_CPUS/4][4];
+
+/* x86_quirks member */
+static void mpc_oem_pci_bus(struct mpc_config_bus *m)
+{
+	int quad = translation_table[mpc_record]->trans_quad;
+	int local = translation_table[mpc_record]->trans_local;
+
+	quad_local_to_mp_bus_id[quad][local] = m->mpc_busid;
+}
+
+static void __init MP_translation_info(struct mpc_config_translation *m)
+{
+	printk(KERN_INFO
+	       "Translation: record %d, type %d, quad %d, global %d, local %d\n",
+	       mpc_record, m->trans_type, m->trans_quad, m->trans_global,
+	       m->trans_local);
+
+	if (mpc_record >= MAX_MPC_ENTRY)
+		printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n");
+	else
+		translation_table[mpc_record] = m;	/* stash this for later */
+	if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad))
+		node_set_online(m->trans_quad);
+}
+
+static int __init mpf_checksum(unsigned char *mp, int len)
+{
+	int sum = 0;
+
+	while (len--)
+		sum += *mp++;
+
+	return sum & 0xFF;
+}
+
+/*
+ * Read/parse the MPC oem tables
+ */
+
+static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable,
+				    unsigned short oemsize)
+{
+	int count = sizeof(*oemtable);	/* the header size */
+	unsigned char *oemptr = ((unsigned char *)oemtable) + count;
+
+	mpc_record = 0;
+	printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n",
+	       oemtable);
+	if (memcmp(oemtable->oem_signature, MPC_OEM_SIGNATURE, 4)) {
+		printk(KERN_WARNING
+		       "SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
+		       oemtable->oem_signature[0], oemtable->oem_signature[1],
+		       oemtable->oem_signature[2], oemtable->oem_signature[3]);
+		return;
+	}
+	if (mpf_checksum((unsigned char *)oemtable, oemtable->oem_length)) {
+		printk(KERN_WARNING "SMP oem mptable: checksum error!\n");
+		return;
+	}
+	while (count < oemtable->oem_length) {
+		switch (*oemptr) {
+		case MP_TRANSLATION:
+			{
+				struct mpc_config_translation *m =
+				    (struct mpc_config_translation *)oemptr;
+				MP_translation_info(m);
+				oemptr += sizeof(*m);
+				count += sizeof(*m);
+				++mpc_record;
+				break;
+			}
+		default:
+			{
+				printk(KERN_WARNING
+				       "Unrecognised OEM table entry type! - %d\n",
+				       (int)*oemptr);
+				return;
+			}
+		}
+	}
+}
+
+static struct x86_quirks numaq_x86_quirks __initdata = {
+	.arch_pre_time_init	= numaq_pre_time_init,
+	.arch_time_init		= NULL,
+	.arch_pre_intr_init	= NULL,
+	.arch_memory_setup	= NULL,
+	.arch_intr_init		= NULL,
+	.arch_trap_init		= NULL,
+	.mach_get_smp_config	= NULL,
+	.mach_find_smp_config	= NULL,
+	.mpc_record		= &mpc_record,
+	.mpc_apic_id		= mpc_apic_id,
+	.mpc_oem_bus_info	= mpc_oem_bus_info,
+	.mpc_oem_pci_bus	= mpc_oem_pci_bus,
+	.smp_read_mpc_oem	= smp_read_mpc_oem,
+};
+
+void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem,
+				 char *productid)
+{
+	if (strncmp(oem, "IBM NUMA", 8))
+		printk("Warning!  Not a NUMA-Q system!\n");
+	else
+		found_numaq = 1;
+}
+
 static __init void early_check_numaq(void)
 {
 	/*
@@ -82,6 +265,9 @@
 	 */
 	if (smp_found_config)
 		early_get_smp_config();
+
+	if (found_numaq)
+		x86_quirks = &numaq_x86_quirks;
 }
 
 int __init get_memcfg_numaq(void)
@@ -92,14 +278,3 @@
 	smp_dump_qct();
 	return 1;
 }
-
-void __init numaq_tsc_disable(void)
-{
-	if (!found_numaq)
-		return;
-
-	if (num_online_nodes() > 1) {
-		printk(KERN_DEBUG "NUMAQ: disabling TSC\n");
-		setup_clear_cpu_cap(X86_FEATURE_TSC);
-	}
-}
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index e0f571d..94da4d52 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -29,6 +29,7 @@
 #include <asm/desc.h>
 #include <asm/setup.h>
 #include <asm/arch_hooks.h>
+#include <asm/pgtable.h>
 #include <asm/time.h>
 #include <asm/pgalloc.h>
 #include <asm/irq.h>
@@ -123,6 +124,7 @@
 		.pv_irq_ops = pv_irq_ops,
 		.pv_apic_ops = pv_apic_ops,
 		.pv_mmu_ops = pv_mmu_ops,
+		.pv_lock_ops = pv_lock_ops,
 	};
 	return *((void **)&tmpl + type);
 }
@@ -266,6 +268,17 @@
 	return __get_cpu_var(paravirt_lazy_mode);
 }
 
+void __init paravirt_use_bytelocks(void)
+{
+#ifdef CONFIG_SMP
+	pv_lock_ops.spin_is_locked = __byte_spin_is_locked;
+	pv_lock_ops.spin_is_contended = __byte_spin_is_contended;
+	pv_lock_ops.spin_lock = __byte_spin_lock;
+	pv_lock_ops.spin_trylock = __byte_spin_trylock;
+	pv_lock_ops.spin_unlock = __byte_spin_unlock;
+#endif
+}
+
 struct pv_info pv_info = {
 	.name = "bare hardware",
 	.paravirt_enabled = 0,
@@ -361,7 +374,6 @@
 struct pv_apic_ops pv_apic_ops = {
 #ifdef CONFIG_X86_LOCAL_APIC
 	.apic_write = native_apic_write,
-	.apic_write_atomic = native_apic_write_atomic,
 	.apic_read = native_apic_read,
 	.setup_boot_clock = setup_boot_APIC_clock,
 	.setup_secondary_clock = setup_secondary_APIC_clock,
@@ -373,6 +385,9 @@
 #ifndef CONFIG_X86_64
 	.pagetable_setup_start = native_pagetable_setup_start,
 	.pagetable_setup_done = native_pagetable_setup_done,
+#else
+	.pagetable_setup_start = paravirt_nop,
+	.pagetable_setup_done = paravirt_nop,
 #endif
 
 	.read_cr2 = native_read_cr2,
@@ -428,7 +443,7 @@
 #endif /* PAGETABLE_LEVELS >= 3 */
 
 	.pte_val = native_pte_val,
-	.pte_flags = native_pte_val,
+	.pte_flags = native_pte_flags,
 	.pgd_val = native_pgd_val,
 
 	.make_pte = native_make_pte,
@@ -446,6 +461,18 @@
 	.set_fixmap = native_set_fixmap,
 };
 
+struct pv_lock_ops pv_lock_ops = {
+#ifdef CONFIG_SMP
+	.spin_is_locked = __ticket_spin_is_locked,
+	.spin_is_contended = __ticket_spin_is_contended,
+
+	.spin_lock = __ticket_spin_lock,
+	.spin_trylock = __ticket_spin_trylock,
+	.spin_unlock = __ticket_spin_unlock,
+#endif
+};
+EXPORT_SYMBOL_GPL(pv_lock_ops);
+
 EXPORT_SYMBOL_GPL(pv_time_ops);
 EXPORT_SYMBOL    (pv_cpu_ops);
 EXPORT_SYMBOL    (pv_mmu_ops);
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index 6959b5c..151f2d1 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -36,7 +36,7 @@
 #include <linux/delay.h>
 #include <linux/scatterlist.h>
 #include <linux/iommu-helper.h>
-#include <asm/gart.h>
+#include <asm/iommu.h>
 #include <asm/calgary.h>
 #include <asm/tce.h>
 #include <asm/pci-direct.h>
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index 8467ec2..cbecb05 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -5,12 +5,11 @@
 
 #include <asm/proto.h>
 #include <asm/dma.h>
-#include <asm/gart.h>
+#include <asm/iommu.h>
 #include <asm/calgary.h>
 #include <asm/amd_iommu.h>
 
-int forbid_dac __read_mostly;
-EXPORT_SYMBOL(forbid_dac);
+static int forbid_dac __read_mostly;
 
 const struct dma_mapping_ops *dma_ops;
 EXPORT_SYMBOL(dma_ops);
@@ -114,21 +113,15 @@
 	 * The order of these functions is important for
 	 * fall-back/fail-over reasons
 	 */
-#ifdef CONFIG_GART_IOMMU
 	gart_iommu_hole_init();
-#endif
 
-#ifdef CONFIG_CALGARY_IOMMU
 	detect_calgary();
-#endif
 
 	detect_intel_iommu();
 
 	amd_iommu_detect();
 
-#ifdef CONFIG_SWIOTLB
 	pci_swiotlb_init();
-#endif
 }
 #endif
 
@@ -184,9 +177,7 @@
 			swiotlb = 1;
 #endif
 
-#ifdef CONFIG_GART_IOMMU
 		gart_parse_options(p);
-#endif
 
 #ifdef CONFIG_CALGARY_IOMMU
 		if (!strncmp(p, "calgary", 7))
@@ -323,8 +314,7 @@
 {
 #ifdef CONFIG_PCI
 	if (mask > 0xffffffff && forbid_dac > 0) {
-		printk(KERN_INFO "PCI: Disallowing DAC for device %s\n",
-				 dev->bus_id);
+		dev_info(dev, "PCI: Disallowing DAC for device\n");
 		return 0;
 	}
 #endif
@@ -351,8 +341,7 @@
 	   type. Normally this doesn't make any difference, but gives
 	   more gentle handling of IOMMU overflow. */
 	if (iommu_sac_force && (mask >= DMA_40BIT_MASK)) {
-		printk(KERN_INFO "%s: Force SAC with mask %Lx\n",
-				 dev->bus_id, mask);
+		dev_info(dev, "Force SAC with mask %Lx\n", mask);
 		return 0;
 	}
 
@@ -500,17 +489,13 @@
 
 static int __init pci_iommu_init(void)
 {
-#ifdef CONFIG_CALGARY_IOMMU
 	calgary_iommu_init();
-#endif
 
 	intel_iommu_init();
 
 	amd_iommu_init();
 
-#ifdef CONFIG_GART_IOMMU
 	gart_iommu_init();
-#endif
 
 	no_iommu_init();
 	return 0;
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index c3fe784..df5f142 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -32,6 +32,7 @@
 #include <asm/mtrr.h>
 #include <asm/pgtable.h>
 #include <asm/proto.h>
+#include <asm/iommu.h>
 #include <asm/gart.h>
 #include <asm/cacheflush.h>
 #include <asm/swiotlb.h>
@@ -197,9 +198,7 @@
 	 * out. Hopefully no network devices use single mappings that big.
 	 */
 
-	printk(KERN_ERR
-		"PCI-DMA: Out of IOMMU space for %lu bytes at device %s\n",
-		size, dev->bus_id);
+	dev_err(dev, "PCI-DMA: Out of IOMMU space for %lu bytes\n", size);
 
 	if (size > PAGE_SIZE*EMERGENCY_PAGES) {
 		if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL)
diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c
index aec43d5..792b917 100644
--- a/arch/x86/kernel/pci-nommu.c
+++ b/arch/x86/kernel/pci-nommu.c
@@ -7,7 +7,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/scatterlist.h>
 
-#include <asm/gart.h>
+#include <asm/iommu.h>
 #include <asm/processor.h>
 #include <asm/dma.h>
 
diff --git a/arch/x86/kernel/pci-swiotlb_64.c b/arch/x86/kernel/pci-swiotlb_64.c
index 82299cd..20df839 100644
--- a/arch/x86/kernel/pci-swiotlb_64.c
+++ b/arch/x86/kernel/pci-swiotlb_64.c
@@ -5,7 +5,7 @@
 #include <linux/module.h>
 #include <linux/dma-mapping.h>
 
-#include <asm/gart.h>
+#include <asm/iommu.h>
 #include <asm/swiotlb.h>
 #include <asm/dma.h>
 
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 4d629c6..7fc4d5b 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -15,6 +15,7 @@
 EXPORT_SYMBOL(idle_nomwait);
 
 struct kmem_cache *task_xstate_cachep;
+static int force_mwait __cpuinitdata;
 
 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 {
@@ -199,6 +200,7 @@
  *
  * idle=mwait overrides this decision and forces the usage of mwait.
  */
+static int __cpuinitdata force_mwait;
 
 #define MWAIT_INFO			0x05
 #define MWAIT_ECX_EXTENDED_INFO		0x01
@@ -326,6 +328,9 @@
 
 static int __init idle_setup(char *str)
 {
+	if (!str)
+		return -EINVAL;
+
 	if (!strcmp(str, "poll")) {
 		printk("using polling idle threads.\n");
 		pm_idle = poll_idle;
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index a8e5362..e8a8e1b 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -537,8 +537,8 @@
 struct task_struct *
 __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
 {
-	struct thread_struct *prev = &prev_p->thread,
-				 *next = &next_p->thread;
+	struct thread_struct *prev = &prev_p->thread;
+	struct thread_struct *next = &next_p->thread;
 	int cpu = smp_processor_id();
 	struct tss_struct *tss = &per_cpu(init_tss, cpu);
 	unsigned fsindex, gsindex;
@@ -586,35 +586,34 @@
 
 	/* 
 	 * Switch FS and GS.
+	 *
+	 * Segment register != 0 always requires a reload.  Also
+	 * reload when it has changed.  When prev process used 64bit
+	 * base always reload to avoid an information leak.
 	 */
-	{ 
-		/* segment register != 0 always requires a reload. 
-		   also reload when it has changed. 
-		   when prev process used 64bit base always reload
-		   to avoid an information leak. */
-		if (unlikely(fsindex | next->fsindex | prev->fs)) {
-			loadsegment(fs, next->fsindex);
-			/* check if the user used a selector != 0
-	                 * if yes clear 64bit base, since overloaded base
-                         * is always mapped to the Null selector
-                         */
-			if (fsindex)
+	if (unlikely(fsindex | next->fsindex | prev->fs)) {
+		loadsegment(fs, next->fsindex);
+		/* 
+		 * Check if the user used a selector != 0; if yes
+		 *  clear 64bit base, since overloaded base is always
+		 *  mapped to the Null selector
+		 */
+		if (fsindex)
 			prev->fs = 0;				
-		}
-		/* when next process has a 64bit base use it */
-		if (next->fs) 
-			wrmsrl(MSR_FS_BASE, next->fs); 
-		prev->fsindex = fsindex;
-
-		if (unlikely(gsindex | next->gsindex | prev->gs)) {
-			load_gs_index(next->gsindex);
-			if (gsindex)
-			prev->gs = 0;				
-		}
-		if (next->gs)
-			wrmsrl(MSR_KERNEL_GS_BASE, next->gs); 
-		prev->gsindex = gsindex;
 	}
+	/* when next process has a 64bit base use it */
+	if (next->fs)
+		wrmsrl(MSR_FS_BASE, next->fs);
+	prev->fsindex = fsindex;
+
+	if (unlikely(gsindex | next->gsindex | prev->gs)) {
+		load_gs_index(next->gsindex);
+		if (gsindex)
+			prev->gs = 0;				
+	}
+	if (next->gs)
+		wrmsrl(MSR_KERNEL_GS_BASE, next->gs);
+	prev->gsindex = gsindex;
 
 	/* Must be after DS reload */
 	unlazy_fpu(prev_p);
@@ -627,7 +626,8 @@
 	write_pda(pcurrent, next_p); 
 
 	write_pda(kernelstack,
-	(unsigned long)task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET);
+		  (unsigned long)task_stack_page(next_p) +
+		  THREAD_SIZE - PDA_STACKOFFSET);
 #ifdef CONFIG_CC_STACKPROTECTOR
 	write_pda(stack_canary, next_p->stack_canary);
 	/*
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 77040b6..e37dccc 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -1357,8 +1357,6 @@
 #endif
 }
 
-#ifdef CONFIG_X86_32
-
 void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code)
 {
 	struct siginfo info;
@@ -1377,89 +1375,10 @@
 	force_sig_info(SIGTRAP, &info, tsk);
 }
 
-/* notification of system call entry/exit
- * - triggered by current->work.syscall_trace
- */
-int do_syscall_trace(struct pt_regs *regs, int entryexit)
-{
-	int is_sysemu = test_thread_flag(TIF_SYSCALL_EMU);
-	/*
-	 * With TIF_SYSCALL_EMU set we want to ignore TIF_SINGLESTEP for syscall
-	 * interception
-	 */
-	int is_singlestep = !is_sysemu && test_thread_flag(TIF_SINGLESTEP);
-	int ret = 0;
-
-	/* do the secure computing check first */
-	if (!entryexit)
-		secure_computing(regs->orig_ax);
-
-	if (unlikely(current->audit_context)) {
-		if (entryexit)
-			audit_syscall_exit(AUDITSC_RESULT(regs->ax),
-						regs->ax);
-		/* Debug traps, when using PTRACE_SINGLESTEP, must be sent only
-		 * on the syscall exit path. Normally, when TIF_SYSCALL_AUDIT is
-		 * not used, entry.S will call us only on syscall exit, not
-		 * entry; so when TIF_SYSCALL_AUDIT is used we must avoid
-		 * calling send_sigtrap() on syscall entry.
-		 *
-		 * Note that when PTRACE_SYSEMU_SINGLESTEP is used,
-		 * is_singlestep is false, despite his name, so we will still do
-		 * the correct thing.
-		 */
-		else if (is_singlestep)
-			goto out;
-	}
-
-	if (!(current->ptrace & PT_PTRACED))
-		goto out;
-
-	/* If a process stops on the 1st tracepoint with SYSCALL_TRACE
-	 * and then is resumed with SYSEMU_SINGLESTEP, it will come in
-	 * here. We have to check this and return */
-	if (is_sysemu && entryexit)
-		return 0;
-
-	/* Fake a debug trap */
-	if (is_singlestep)
-		send_sigtrap(current, regs, 0);
-
- 	if (!test_thread_flag(TIF_SYSCALL_TRACE) && !is_sysemu)
-		goto out;
-
-	/* the 0x80 provides a way for the tracing parent to distinguish
-	   between a syscall stop and SIGTRAP delivery */
-	/* Note that the debugger could change the result of test_thread_flag!*/
-	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80:0));
-
-	/*
-	 * this isn't the same as continuing with a signal, but it will do
-	 * for normal use.  strace only continues with a signal if the
-	 * stopping signal is not SIGTRAP.  -brl
-	 */
-	if (current->exit_code) {
-		send_sig(current->exit_code, current, 1);
-		current->exit_code = 0;
-	}
-	ret = is_sysemu;
-out:
-	if (unlikely(current->audit_context) && !entryexit)
-		audit_syscall_entry(AUDIT_ARCH_I386, regs->orig_ax,
-				    regs->bx, regs->cx, regs->dx, regs->si);
-	if (ret == 0)
-		return 0;
-
-	regs->orig_ax = -1; /* force skip of syscall restarting */
-	if (unlikely(current->audit_context))
-		audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax);
-	return 1;
-}
-
-#else  /* CONFIG_X86_64 */
-
 static void syscall_trace(struct pt_regs *regs)
 {
+	if (!(current->ptrace & PT_PTRACED))
+		return;
 
 #if 0
 	printk("trace %s ip %lx sp %lx ax %d origrax %d caller %lx tiflags %x ptrace %x\n",
@@ -1481,39 +1400,81 @@
 	}
 }
 
-asmlinkage void syscall_trace_enter(struct pt_regs *regs)
+#ifdef CONFIG_X86_32
+# define IS_IA32	1
+#elif defined CONFIG_IA32_EMULATION
+# define IS_IA32	test_thread_flag(TIF_IA32)
+#else
+# define IS_IA32	0
+#endif
+
+/*
+ * We must return the syscall number to actually look up in the table.
+ * This can be -1L to skip running any syscall at all.
+ */
+asmregparm long syscall_trace_enter(struct pt_regs *regs)
 {
+	long ret = 0;
+
+	/*
+	 * If we stepped into a sysenter/syscall insn, it trapped in
+	 * kernel mode; do_debug() cleared TF and set TIF_SINGLESTEP.
+	 * If user-mode had set TF itself, then it's still clear from
+	 * do_debug() and we need to set it again to restore the user
+	 * state.  If we entered on the slow path, TF was already set.
+	 */
+	if (test_thread_flag(TIF_SINGLESTEP))
+		regs->flags |= X86_EFLAGS_TF;
+
 	/* do the secure computing check first */
 	secure_computing(regs->orig_ax);
 
-	if (test_thread_flag(TIF_SYSCALL_TRACE)
-	    && (current->ptrace & PT_PTRACED))
+	if (unlikely(test_thread_flag(TIF_SYSCALL_EMU)))
+		ret = -1L;
+
+	if (ret || test_thread_flag(TIF_SYSCALL_TRACE))
 		syscall_trace(regs);
 
 	if (unlikely(current->audit_context)) {
-		if (test_thread_flag(TIF_IA32)) {
+		if (IS_IA32)
 			audit_syscall_entry(AUDIT_ARCH_I386,
 					    regs->orig_ax,
 					    regs->bx, regs->cx,
 					    regs->dx, regs->si);
-		} else {
+#ifdef CONFIG_X86_64
+		else
 			audit_syscall_entry(AUDIT_ARCH_X86_64,
 					    regs->orig_ax,
 					    regs->di, regs->si,
 					    regs->dx, regs->r10);
-		}
+#endif
 	}
+
+	return ret ?: regs->orig_ax;
 }
 
-asmlinkage void syscall_trace_leave(struct pt_regs *regs)
+asmregparm void syscall_trace_leave(struct pt_regs *regs)
 {
 	if (unlikely(current->audit_context))
 		audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax);
 
-	if ((test_thread_flag(TIF_SYSCALL_TRACE)
-	     || test_thread_flag(TIF_SINGLESTEP))
-	    && (current->ptrace & PT_PTRACED))
+	if (test_thread_flag(TIF_SYSCALL_TRACE))
 		syscall_trace(regs);
-}
 
-#endif	/* CONFIG_X86_32 */
+	/*
+	 * If TIF_SYSCALL_EMU is set, we only get here because of
+	 * TIF_SINGLESTEP (i.e. this is PTRACE_SYSEMU_SINGLESTEP).
+	 * We already reported this syscall instruction in
+	 * syscall_trace_enter(), so don't do any more now.
+	 */
+	if (unlikely(test_thread_flag(TIF_SYSCALL_EMU)))
+		return;
+
+	/*
+	 * If we are single-stepping, synthesize a trap to follow the
+	 * system call instruction.
+	 */
+	if (test_thread_flag(TIF_SINGLESTEP) &&
+	    (current->ptrace & PT_PTRACED))
+		send_sigtrap(current, regs, 0);
+}
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 214bbdf..06a9f64 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -177,6 +177,14 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"),
 		},
 	},
+	{	/* Handle problems with rebooting on Dell T5400's */
+		.callback = set_bios_reboot,
+		.ident = "Dell Precision T5400",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T5400"),
+		},
+	},
 	{	/* Handle problems with rebooting on HP laptops */
 		.callback = set_bios_reboot,
 		.ident = "HP Compaq Laptop",
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 531b55b..b4aacb9 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -57,12 +57,8 @@
 #include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/delay.h>
-#include <linux/highmem.h>
 
 #include <linux/kallsyms.h>
-#include <linux/edd.h>
-#include <linux/iscsi_ibft.h>
-#include <linux/kexec.h>
 #include <linux/cpufreq.h>
 #include <linux/dma-mapping.h>
 #include <linux/ctype.h>
@@ -96,7 +92,7 @@
 #include <asm/smp.h>
 #include <asm/desc.h>
 #include <asm/dma.h>
-#include <asm/gart.h>
+#include <asm/iommu.h>
 #include <asm/mmu_context.h>
 #include <asm/proto.h>
 
@@ -104,7 +100,6 @@
 #include <asm/paravirt.h>
 
 #include <asm/percpu.h>
-#include <asm/sections.h>
 #include <asm/topology.h>
 #include <asm/apicdef.h>
 #ifdef CONFIG_X86_64
@@ -579,6 +574,10 @@
 early_param("elfcorehdr", setup_elfcorehdr);
 #endif
 
+static struct x86_quirks default_x86_quirks __initdata;
+
+struct x86_quirks *x86_quirks __initdata = &default_x86_quirks;
+
 /*
  * Determine if we were loaded by an EFI loader.  If so, then we have also been
  * passed the efi memmap, systab, etc., so we should use these data structures
@@ -681,7 +680,7 @@
 #ifdef CONFIG_X86_LOCAL_APIC
 		disable_apic = 1;
 #endif
-		clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
+		setup_clear_cpu_cap(X86_FEATURE_APIC);
 	}
 
 #ifdef CONFIG_PCI
@@ -824,7 +823,10 @@
 	vmi_init();
 #endif
 
+	paravirt_pagetable_setup_start(swapper_pg_dir);
 	paging_init();
+	paravirt_pagetable_setup_done(swapper_pg_dir);
+	paravirt_post_allocator_init();
 
 #ifdef CONFIG_X86_64
 	map_vsyscall();
@@ -854,14 +856,6 @@
 	init_cpu_to_node();
 #endif
 
-#ifdef CONFIG_X86_NUMAQ
-	/*
-	 * need to check online nodes num, call it
-	 * here before time_init/tsc_init
-	 */
-	numaq_tsc_disable();
-#endif
-
 	init_apic_mappings();
 	ioapic_init_mappings();
 
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
index cac6843..f7745f9 100644
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -227,8 +227,8 @@
 	/* allocate the map */
 	map = alloc_bootmem_low(nr_node_ids * sizeof(cpumask_t));
 
-	Dprintk(KERN_DEBUG "Node to cpumask map at %p for %d nodes\n",
-		map, nr_node_ids);
+	pr_debug(KERN_DEBUG "Node to cpumask map at %p for %d nodes\n",
+		 map, nr_node_ids);
 
 	/* node_to_cpumask() will now work */
 	node_to_cpumask_map = map;
@@ -248,7 +248,7 @@
 		per_cpu(x86_cpu_to_node_map, cpu) = node;
 
 	else
-		Dprintk(KERN_INFO "Setting node for non-present cpu %d\n", cpu);
+		pr_debug("Setting node for non-present cpu %d\n", cpu);
 }
 
 void __cpuinit numa_clear_node(int cpu)
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c
index d923736..07faaa5 100644
--- a/arch/x86/kernel/signal_32.c
+++ b/arch/x86/kernel/signal_32.c
@@ -212,7 +212,7 @@
 
 badframe:
 	if (show_unhandled_signals && printk_ratelimit()) {
-		printk(KERN_INFO "%s%s[%d] bad frame in sigreturn frame:"
+		printk("%s%s[%d] bad frame in sigreturn frame:"
 			"%p ip:%lx sp:%lx oeax:%lx",
 		    task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG,
 		    current->comm, task_pid_nr(current), frame, regs->ip,
@@ -657,12 +657,6 @@
 void
 do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
 {
-	/* Pending single-step? */
-	if (thread_info_flags & _TIF_SINGLESTEP) {
-		regs->flags |= X86_EFLAGS_TF;
-		clear_thread_flag(TIF_SINGLESTEP);
-	}
-
 	/* deal with pending signal delivery */
 	if (thread_info_flags & _TIF_SIGPENDING)
 		do_signal(regs);
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c
index e53b267..bf87684 100644
--- a/arch/x86/kernel/signal_64.c
+++ b/arch/x86/kernel/signal_64.c
@@ -487,12 +487,6 @@
 void do_notify_resume(struct pt_regs *regs, void *unused,
 		      __u32 thread_info_flags)
 {
-	/* Pending single-step? */
-	if (thread_info_flags & _TIF_SINGLESTEP) {
-		regs->flags |= X86_EFLAGS_TF;
-		clear_thread_flag(TIF_SINGLESTEP);
-	}
-
 #ifdef CONFIG_X86_MCE
 	/* notify userspace of pending MCEs */
 	if (thread_info_flags & _TIF_MCE_NOTIFY)
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 09b98cd..3325127 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -216,7 +216,7 @@
 		panic("%s: phys CPU#%d, CPU#%d already present??\n", __func__,
 					phys_id, cpuid);
 	}
-	Dprintk("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id);
+	pr_debug("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id);
 
 	/*
 	 * STARTUP IPIs are fragile beasts as they might sometimes
@@ -251,7 +251,7 @@
 	 * boards)
 	 */
 
-	Dprintk("CALLIN, before setup_local_APIC().\n");
+	pr_debug("CALLIN, before setup_local_APIC().\n");
 	smp_callin_clear_local_apic();
 	setup_local_APIC();
 	end_local_APIC_setup();
@@ -266,7 +266,7 @@
 	local_irq_enable();
 	calibrate_delay();
 	local_irq_disable();
-	Dprintk("Stack at about %p\n", &cpuid);
+	pr_debug("Stack at about %p\n", &cpuid);
 
 	/*
 	 * Save our processor parameters
@@ -513,7 +513,7 @@
 	/*
 	 * Allow the user to impress friends.
 	 */
-	Dprintk("Before bogomips.\n");
+	pr_debug("Before bogomips.\n");
 	for_each_possible_cpu(cpu)
 		if (cpu_isset(cpu, cpu_callout_map))
 			bogosum += cpu_data(cpu).loops_per_jiffy;
@@ -523,7 +523,7 @@
 		bogosum/(500000/HZ),
 		(bogosum/(5000/HZ))%100);
 
-	Dprintk("Before bogocount - setting activated=1.\n");
+	pr_debug("Before bogocount - setting activated=1.\n");
 }
 
 static inline void __inquire_remote_apic(int apicid)
@@ -546,8 +546,8 @@
 			printk(KERN_CONT
 			       "a previous APIC delivery may have failed\n");
 
-		apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
-		apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]);
+		apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
+		apic_write(APIC_ICR, APIC_DM_REMRD | regs[i]);
 
 		timeout = 0;
 		do {
@@ -579,29 +579,24 @@
 	int maxlvt;
 
 	/* Target chip */
-	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(logical_apicid));
+	apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(logical_apicid));
 
 	/* Boot on the stack */
 	/* Kick the second */
-	apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL);
+	apic_write(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL);
 
-	Dprintk("Waiting for send to finish...\n");
+	pr_debug("Waiting for send to finish...\n");
 	send_status = safe_apic_wait_icr_idle();
 
 	/*
 	 * Give the other CPU some time to accept the IPI.
 	 */
 	udelay(200);
-	/*
-	 * Due to the Pentium erratum 3AP.
-	 */
 	maxlvt = lapic_get_maxlvt();
-	if (maxlvt > 3) {
-		apic_read_around(APIC_SPIV);
+	if (maxlvt > 3)			/* Due to the Pentium erratum 3AP.  */
 		apic_write(APIC_ESR, 0);
-	}
 	accept_status = (apic_read(APIC_ESR) & 0xEF);
-	Dprintk("NMI sent.\n");
+	pr_debug("NMI sent.\n");
 
 	if (send_status)
 		printk(KERN_ERR "APIC never delivered???\n");
@@ -625,42 +620,44 @@
 		return send_status;
 	}
 
+	maxlvt = lapic_get_maxlvt();
+
 	/*
 	 * Be paranoid about clearing APIC errors.
 	 */
 	if (APIC_INTEGRATED(apic_version[phys_apicid])) {
-		apic_read_around(APIC_SPIV);
-		apic_write(APIC_ESR, 0);
+		if (maxlvt > 3)		/* Due to the Pentium erratum 3AP.  */
+			apic_write(APIC_ESR, 0);
 		apic_read(APIC_ESR);
 	}
 
-	Dprintk("Asserting INIT.\n");
+	pr_debug("Asserting INIT.\n");
 
 	/*
 	 * Turn INIT on target chip
 	 */
-	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+	apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
 
 	/*
 	 * Send IPI
 	 */
-	apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
-				| APIC_DM_INIT);
+	apic_write(APIC_ICR,
+		   APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT);
 
-	Dprintk("Waiting for send to finish...\n");
+	pr_debug("Waiting for send to finish...\n");
 	send_status = safe_apic_wait_icr_idle();
 
 	mdelay(10);
 
-	Dprintk("Deasserting INIT.\n");
+	pr_debug("Deasserting INIT.\n");
 
 	/* Target chip */
-	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+	apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
 
 	/* Send IPI */
-	apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
+	apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
 
-	Dprintk("Waiting for send to finish...\n");
+	pr_debug("Waiting for send to finish...\n");
 	send_status = safe_apic_wait_icr_idle();
 
 	mb();
@@ -687,55 +684,47 @@
 	/*
 	 * Run STARTUP IPI loop.
 	 */
-	Dprintk("#startup loops: %d.\n", num_starts);
-
-	maxlvt = lapic_get_maxlvt();
+	pr_debug("#startup loops: %d.\n", num_starts);
 
 	for (j = 1; j <= num_starts; j++) {
-		Dprintk("Sending STARTUP #%d.\n", j);
-		apic_read_around(APIC_SPIV);
-		apic_write(APIC_ESR, 0);
+		pr_debug("Sending STARTUP #%d.\n", j);
+		if (maxlvt > 3)		/* Due to the Pentium erratum 3AP.  */
+			apic_write(APIC_ESR, 0);
 		apic_read(APIC_ESR);
-		Dprintk("After apic_write.\n");
+		pr_debug("After apic_write.\n");
 
 		/*
 		 * STARTUP IPI
 		 */
 
 		/* Target chip */
-		apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+		apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
 
 		/* Boot on the stack */
 		/* Kick the second */
-		apic_write_around(APIC_ICR, APIC_DM_STARTUP
-					| (start_eip >> 12));
+		apic_write(APIC_ICR, APIC_DM_STARTUP | (start_eip >> 12));
 
 		/*
 		 * Give the other CPU some time to accept the IPI.
 		 */
 		udelay(300);
 
-		Dprintk("Startup point 1.\n");
+		pr_debug("Startup point 1.\n");
 
-		Dprintk("Waiting for send to finish...\n");
+		pr_debug("Waiting for send to finish...\n");
 		send_status = safe_apic_wait_icr_idle();
 
 		/*
 		 * Give the other CPU some time to accept the IPI.
 		 */
 		udelay(200);
-		/*
-		 * Due to the Pentium erratum 3AP.
-		 */
-		if (maxlvt > 3) {
-			apic_read_around(APIC_SPIV);
+		if (maxlvt > 3)		/* Due to the Pentium erratum 3AP.  */
 			apic_write(APIC_ESR, 0);
-		}
 		accept_status = (apic_read(APIC_ESR) & 0xEF);
 		if (send_status || accept_status)
 			break;
 	}
-	Dprintk("After Startup.\n");
+	pr_debug("After Startup.\n");
 
 	if (send_status)
 		printk(KERN_ERR "APIC never delivered???\n");
@@ -768,7 +757,7 @@
  *
  * Must be called after the _cpu_pda pointer table is initialized.
  */
-static int __cpuinit get_local_pda(int cpu)
+int __cpuinit get_local_pda(int cpu)
 {
 	struct x8664_pda *oldpda, *newpda;
 	unsigned long size = sizeof(struct x8664_pda);
@@ -886,7 +875,7 @@
 
 	if (get_uv_system_type() != UV_NON_UNIQUE_APIC) {
 
-		Dprintk("Setting warm reset code and vector.\n");
+		pr_debug("Setting warm reset code and vector.\n");
 
 		store_NMI_vector(&nmi_high, &nmi_low);
 
@@ -907,9 +896,9 @@
 		/*
 		 * allow APs to start initializing.
 		 */
-		Dprintk("Before Callout %d.\n", cpu);
+		pr_debug("Before Callout %d.\n", cpu);
 		cpu_set(cpu, cpu_callout_map);
-		Dprintk("After Callout %d.\n", cpu);
+		pr_debug("After Callout %d.\n", cpu);
 
 		/*
 		 * Wait 5s total for a response
@@ -922,10 +911,10 @@
 
 		if (cpu_isset(cpu, cpu_callin_map)) {
 			/* number CPUs logically, starting from 1 (BSP is 0) */
-			Dprintk("OK.\n");
+			pr_debug("OK.\n");
 			printk(KERN_INFO "CPU%d: ", cpu);
 			print_cpu_info(&cpu_data(cpu));
-			Dprintk("CPU has booted.\n");
+			pr_debug("CPU has booted.\n");
 		} else {
 			boot_error = 1;
 			if (*((volatile unsigned char *)trampoline_base)
@@ -970,7 +959,7 @@
 
 	WARN_ON(irqs_disabled());
 
-	Dprintk("++++++++++++++++++++=_---CPU UP  %u\n", cpu);
+	pr_debug("++++++++++++++++++++=_---CPU UP  %u\n", cpu);
 
 	if (apicid == BAD_APICID || apicid == boot_cpu_physical_apicid ||
 	    !physid_isset(apicid, phys_cpu_present_map)) {
@@ -982,7 +971,7 @@
 	 * Already booted CPU?
 	 */
 	if (cpu_isset(cpu, cpu_callin_map)) {
-		Dprintk("do_boot_cpu %d Already started\n", cpu);
+		pr_debug("do_boot_cpu %d Already started\n", cpu);
 		return -ENOSYS;
 	}
 
@@ -1009,7 +998,7 @@
 	err = do_boot_cpu(apicid, cpu);
 #endif
 	if (err) {
-		Dprintk("do_boot_cpu failed %d\n", err);
+		pr_debug("do_boot_cpu failed %d\n", err);
 		return -EIO;
 	}
 
@@ -1213,7 +1202,7 @@
 
 void __init native_smp_cpus_done(unsigned int max_cpus)
 {
-	Dprintk("Boot done.\n");
+	pr_debug("Boot done.\n");
 
 	impress_friends();
 	smp_checks();
@@ -1311,7 +1300,7 @@
 	cpu_clear(cpu, cpu_callout_map);
 	cpu_clear(cpu, cpu_callin_map);
 	/* was set by cpu_init() */
-	clear_bit(cpu, (unsigned long *)&cpu_initialized);
+	cpu_clear(cpu, cpu_initialized);
 	numa_remove_cpu(cpu);
 }
 
@@ -1390,7 +1379,8 @@
 {
 	extern unsigned int maxcpus;
 
-	maxcpus = simple_strtoul(arg, NULL, 0);
+	if (arg)
+		maxcpus = simple_strtoul(arg, NULL, 0);
 	return 0;
 }
 early_param("maxcpus", parse_maxcpus);
diff --git a/arch/x86/kernel/smpcommon_32.c b/arch/x86/kernel/smpcommon_32.c
deleted file mode 100644
index 8b13789..0000000
--- a/arch/x86/kernel/smpcommon_32.c
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c
index 92c20fe..e8b9863 100644
--- a/arch/x86/kernel/step.c
+++ b/arch/x86/kernel/step.c
@@ -105,6 +105,20 @@
 static int enable_single_step(struct task_struct *child)
 {
 	struct pt_regs *regs = task_pt_regs(child);
+	unsigned long oflags;
+
+	/*
+	 * If we stepped into a sysenter/syscall insn, it trapped in
+	 * kernel mode; do_debug() cleared TF and set TIF_SINGLESTEP.
+	 * If user-mode had set TF itself, then it's still clear from
+	 * do_debug() and we need to set it again to restore the user
+	 * state so we don't wrongly set TIF_FORCED_TF below.
+	 * If enable_single_step() was used last and that is what
+	 * set TIF_SINGLESTEP, then both TF and TIF_FORCED_TF are
+	 * already set and our bookkeeping is fine.
+	 */
+	if (unlikely(test_tsk_thread_flag(child, TIF_SINGLESTEP)))
+		regs->flags |= X86_EFLAGS_TF;
 
 	/*
 	 * Always set TIF_SINGLESTEP - this guarantees that
@@ -113,11 +127,7 @@
 	 */
 	set_tsk_thread_flag(child, TIF_SINGLESTEP);
 
-	/*
-	 * If TF was already set, don't do anything else
-	 */
-	if (regs->flags & X86_EFLAGS_TF)
-		return 0;
+	oflags = regs->flags;
 
 	/* Set TF on the kernel stack.. */
 	regs->flags |= X86_EFLAGS_TF;
@@ -126,9 +136,22 @@
 	 * ..but if TF is changed by the instruction we will trace,
 	 * don't mark it as being "us" that set it, so that we
 	 * won't clear it by hand later.
+	 *
+	 * Note that if we don't actually execute the popf because
+	 * of a signal arriving right now or suchlike, we will lose
+	 * track of the fact that it really was "us" that set it.
 	 */
-	if (is_setting_trap_flag(child, regs))
+	if (is_setting_trap_flag(child, regs)) {
+		clear_tsk_thread_flag(child, TIF_FORCED_TF);
 		return 0;
+	}
+
+	/*
+	 * If TF was already set, check whether it was us who set it.
+	 * If not, we should never attempt a block step.
+	 */
+	if (oflags & X86_EFLAGS_TF)
+		return test_tsk_thread_flag(child, TIF_FORCED_TF);
 
 	set_tsk_thread_flag(child, TIF_FORCED_TF);
 
diff --git a/arch/x86/kernel/time_32.c b/arch/x86/kernel/time_32.c
index 059ca6e..ffe3c66 100644
--- a/arch/x86/kernel/time_32.c
+++ b/arch/x86/kernel/time_32.c
@@ -129,6 +129,7 @@
  */
 void __init time_init(void)
 {
+	pre_time_init_hook();
 	tsc_init();
 	late_time_init = choose_time_init();
 }
diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c
index 8a76897..03df8e4 100644
--- a/arch/x86/kernel/traps_32.c
+++ b/arch/x86/kernel/traps_32.c
@@ -58,6 +58,7 @@
 #include <asm/nmi.h>
 #include <asm/smp.h>
 #include <asm/io.h>
+#include <asm/traps.h>
 
 #include "mach_traps.h"
 
@@ -77,26 +78,6 @@
 gate_desc idt_table[256]
 	__attribute__((__section__(".data.idt"))) = { { { { 0, 0 } } }, };
 
-asmlinkage void divide_error(void);
-asmlinkage void debug(void);
-asmlinkage void nmi(void);
-asmlinkage void int3(void);
-asmlinkage void overflow(void);
-asmlinkage void bounds(void);
-asmlinkage void invalid_op(void);
-asmlinkage void device_not_available(void);
-asmlinkage void coprocessor_segment_overrun(void);
-asmlinkage void invalid_TSS(void);
-asmlinkage void segment_not_present(void);
-asmlinkage void stack_segment(void);
-asmlinkage void general_protection(void);
-asmlinkage void page_fault(void);
-asmlinkage void coprocessor_error(void);
-asmlinkage void simd_coprocessor_error(void);
-asmlinkage void alignment_check(void);
-asmlinkage void spurious_interrupt_bug(void);
-asmlinkage void machine_check(void);
-
 int panic_on_unrecovered_nmi;
 int kstack_depth_to_print = 24;
 static unsigned int code_bytes = 64;
@@ -256,7 +237,7 @@
 
 static void
 show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
-		   unsigned long *stack, unsigned long bp, char *log_lvl)
+		unsigned long *stack, unsigned long bp, char *log_lvl)
 {
 	dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl);
 	printk("%s =======================\n", log_lvl);
@@ -383,6 +364,54 @@
 	return ud2 == 0x0b0f;
 }
 
+static raw_spinlock_t die_lock = __RAW_SPIN_LOCK_UNLOCKED;
+static int die_owner = -1;
+static unsigned int die_nest_count;
+
+unsigned __kprobes long oops_begin(void)
+{
+	unsigned long flags;
+
+	oops_enter();
+
+	if (die_owner != raw_smp_processor_id()) {
+		console_verbose();
+		raw_local_irq_save(flags);
+		__raw_spin_lock(&die_lock);
+		die_owner = smp_processor_id();
+		die_nest_count = 0;
+		bust_spinlocks(1);
+	} else {
+		raw_local_irq_save(flags);
+	}
+	die_nest_count++;
+	return flags;
+}
+
+void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr)
+{
+	bust_spinlocks(0);
+	die_owner = -1;
+	add_taint(TAINT_DIE);
+	__raw_spin_unlock(&die_lock);
+	raw_local_irq_restore(flags);
+
+	if (!regs)
+		return;
+
+	if (kexec_should_crash(current))
+		crash_kexec(regs);
+
+	if (in_interrupt())
+		panic("Fatal exception in interrupt");
+
+	if (panic_on_oops)
+		panic("Fatal exception");
+
+	oops_exit();
+	do_exit(signr);
+}
+
 int __kprobes __die(const char *str, struct pt_regs *regs, long err)
 {
 	unsigned short ss;
@@ -423,31 +452,9 @@
  */
 void die(const char *str, struct pt_regs *regs, long err)
 {
-	static struct {
-		raw_spinlock_t lock;
-		u32 lock_owner;
-		int lock_owner_depth;
-	} die = {
-		.lock =			__RAW_SPIN_LOCK_UNLOCKED,
-		.lock_owner =		-1,
-		.lock_owner_depth =	0
-	};
-	unsigned long flags;
+	unsigned long flags = oops_begin();
 
-	oops_enter();
-
-	if (die.lock_owner != raw_smp_processor_id()) {
-		console_verbose();
-		raw_local_irq_save(flags);
-		__raw_spin_lock(&die.lock);
-		die.lock_owner = smp_processor_id();
-		die.lock_owner_depth = 0;
-		bust_spinlocks(1);
-	} else {
-		raw_local_irq_save(flags);
-	}
-
-	if (++die.lock_owner_depth < 3) {
+	if (die_nest_count < 3) {
 		report_bug(regs->ip, regs);
 
 		if (__die(str, regs, err))
@@ -456,26 +463,7 @@
 		printk(KERN_EMERG "Recursive die() failure, output suppressed\n");
 	}
 
-	bust_spinlocks(0);
-	die.lock_owner = -1;
-	add_taint(TAINT_DIE);
-	__raw_spin_unlock(&die.lock);
-	raw_local_irq_restore(flags);
-
-	if (!regs)
-		return;
-
-	if (kexec_should_crash(current))
-		crash_kexec(regs);
-
-	if (in_interrupt())
-		panic("Fatal exception in interrupt");
-
-	if (panic_on_oops)
-		panic("Fatal exception");
-
-	oops_exit();
-	do_exit(SIGSEGV);
+	oops_end(flags, regs, SIGSEGV);
 }
 
 static inline void
diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c
index 2696a68..3f18d73 100644
--- a/arch/x86/kernel/traps_64.c
+++ b/arch/x86/kernel/traps_64.c
@@ -51,30 +51,10 @@
 #include <asm/pgalloc.h>
 #include <asm/proto.h>
 #include <asm/pda.h>
+#include <asm/traps.h>
 
 #include <mach_traps.h>
 
-asmlinkage void divide_error(void);
-asmlinkage void debug(void);
-asmlinkage void nmi(void);
-asmlinkage void int3(void);
-asmlinkage void overflow(void);
-asmlinkage void bounds(void);
-asmlinkage void invalid_op(void);
-asmlinkage void device_not_available(void);
-asmlinkage void double_fault(void);
-asmlinkage void coprocessor_segment_overrun(void);
-asmlinkage void invalid_TSS(void);
-asmlinkage void segment_not_present(void);
-asmlinkage void stack_segment(void);
-asmlinkage void general_protection(void);
-asmlinkage void page_fault(void);
-asmlinkage void coprocessor_error(void);
-asmlinkage void simd_coprocessor_error(void);
-asmlinkage void alignment_check(void);
-asmlinkage void spurious_interrupt_bug(void);
-asmlinkage void machine_check(void);
-
 int panic_on_unrecovered_nmi;
 int kstack_depth_to_print = 12;
 static unsigned int code_bytes = 64;
@@ -355,17 +335,24 @@
 	.address = print_trace_address,
 };
 
-void show_trace(struct task_struct *task, struct pt_regs *regs,
-		unsigned long *stack, unsigned long bp)
+static void
+show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
+		unsigned long *stack, unsigned long bp, char *log_lvl)
 {
 	printk("\nCall Trace:\n");
-	dump_trace(task, regs, stack, bp, &print_trace_ops, NULL);
+	dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl);
 	printk("\n");
 }
 
+void show_trace(struct task_struct *task, struct pt_regs *regs,
+		unsigned long *stack, unsigned long bp)
+{
+	show_trace_log_lvl(task, regs, stack, bp, "");
+}
+
 static void
-_show_stack(struct task_struct *task, struct pt_regs *regs,
-		unsigned long *sp, unsigned long bp)
+show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
+		unsigned long *sp, unsigned long bp, char *log_lvl)
 {
 	unsigned long *stack;
 	int i;
@@ -399,12 +386,12 @@
 		printk(" %016lx", *stack++);
 		touch_nmi_watchdog();
 	}
-	show_trace(task, regs, sp, bp);
+	show_trace_log_lvl(task, regs, sp, bp, log_lvl);
 }
 
 void show_stack(struct task_struct *task, unsigned long *sp)
 {
-	_show_stack(task, NULL, sp, 0);
+	show_stack_log_lvl(task, NULL, sp, 0, "");
 }
 
 /*
@@ -454,7 +441,8 @@
 		u8 *ip;
 
 		printk("Stack: ");
-		_show_stack(NULL, regs, (unsigned long *)sp, regs->bp);
+		show_stack_log_lvl(NULL, regs, (unsigned long *)sp,
+				regs->bp, "");
 		printk("\n");
 
 		printk(KERN_EMERG "Code: ");
@@ -518,7 +506,7 @@
 }
 
 void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr)
-{ 
+{
 	die_owner = -1;
 	bust_spinlocks(0);
 	die_nest_count--;
diff --git a/arch/x86/kernel/visws_quirks.c b/arch/x86/kernel/visws_quirks.c
index e94bdb6..41e01b1 100644
--- a/arch/x86/kernel/visws_quirks.c
+++ b/arch/x86/kernel/visws_quirks.c
@@ -73,7 +73,7 @@
 	return visws_board_type >= 0;
 }
 
-static int __init visws_time_init_quirk(void)
+static int __init visws_time_init(void)
 {
 	printk(KERN_INFO "Starting Cobalt Timer system clock\n");
 
@@ -93,7 +93,7 @@
 	return 0;
 }
 
-static int __init visws_pre_intr_init_quirk(void)
+static int __init visws_pre_intr_init(void)
 {
 	init_VISWS_APIC_irqs();
 
@@ -114,7 +114,7 @@
 
 long long mem_size __initdata = 0;
 
-static char * __init visws_memory_setup_quirk(void)
+static char * __init visws_memory_setup(void)
 {
 	long long gfx_mem_size = 8 * MB;
 
@@ -176,7 +176,7 @@
 	outl(PIIX_SPECIAL_STOP, 0xCFC);
 }
 
-static int __init visws_get_smp_config_quirk(unsigned int early)
+static int __init visws_get_smp_config(unsigned int early)
 {
 	/*
 	 * Prevent MP-table parsing by the generic code:
@@ -192,7 +192,7 @@
  * No problem for Linux.
  */
 
-static void __init MP_processor_info (struct mpc_config_processor *m)
+static void __init MP_processor_info(struct mpc_config_processor *m)
 {
 	int ver, logical_apicid;
 	physid_mask_t apic_cpus;
@@ -232,7 +232,7 @@
 	apic_version[m->mpc_apicid] = ver;
 }
 
-int __init visws_find_smp_config_quirk(unsigned int reserve)
+static int __init visws_find_smp_config(unsigned int reserve)
 {
 	struct mpc_config_processor *mp = phys_to_virt(CO_CPU_TAB_PHYS);
 	unsigned short ncpus = readw(phys_to_virt(CO_CPU_NUM_PHYS));
@@ -258,7 +258,17 @@
 	return 1;
 }
 
-extern int visws_trap_init_quirk(void);
+static int visws_trap_init(void);
+
+static struct x86_quirks visws_x86_quirks __initdata = {
+	.arch_time_init		= visws_time_init,
+	.arch_pre_intr_init	= visws_pre_intr_init,
+	.arch_memory_setup	= visws_memory_setup,
+	.arch_intr_init		= NULL,
+	.arch_trap_init		= visws_trap_init,
+	.mach_get_smp_config	= visws_get_smp_config,
+	.mach_find_smp_config	= visws_find_smp_config,
+};
 
 void __init visws_early_detect(void)
 {
@@ -272,16 +282,10 @@
 
 	/*
 	 * Install special quirks for timer, interrupt and memory setup:
-	 */
-	arch_time_init_quirk		= visws_time_init_quirk;
-	arch_pre_intr_init_quirk	= visws_pre_intr_init_quirk;
-	arch_memory_setup_quirk		= visws_memory_setup_quirk;
-
-	/*
 	 * Fall back to generic behavior for traps:
+	 * Override generic MP-table parsing:
 	 */
-	arch_intr_init_quirk		= NULL;
-	arch_trap_init_quirk		= visws_trap_init_quirk;
+	x86_quirks = &visws_x86_quirks;
 
 	/*
 	 * Install reboot quirks:
@@ -294,12 +298,6 @@
 	 */
 	no_broadcast = 0;
 
-	/*
-	 * Override generic MP-table parsing:
-	 */
-	mach_get_smp_config_quirk	= visws_get_smp_config_quirk;
-	mach_find_smp_config_quirk	= visws_find_smp_config_quirk;
-
 #ifdef CONFIG_X86_IO_APIC
 	/*
 	 * Turn off IO-APIC detection and initialization:
@@ -426,7 +424,7 @@
 		co_apic_read(CO_APIC_ID));
 }
 
-int __init visws_trap_init_quirk(void)
+static int __init visws_trap_init(void)
 {
 	lithium_init();
 	cobalt_init();
diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c
index b153460..0a1b1a9 100644
--- a/arch/x86/kernel/vmi_32.c
+++ b/arch/x86/kernel/vmi_32.c
@@ -906,7 +906,6 @@
 #ifdef CONFIG_X86_LOCAL_APIC
 	para_fill(pv_apic_ops.apic_read, APICRead);
 	para_fill(pv_apic_ops.apic_write, APICWrite);
-	para_fill(pv_apic_ops.apic_write_atomic, APICWrite);
 #endif
 
 	/*
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index 50dad44..0313a5e 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -991,7 +991,6 @@
 #ifdef CONFIG_X86_LOCAL_APIC
 	/* apic read/write intercepts */
 	pv_apic_ops.apic_write = lguest_apic_write;
-	pv_apic_ops.apic_write_atomic = lguest_apic_write;
 	pv_apic_ops.apic_read = lguest_apic_read;
 #endif
 
diff --git a/arch/x86/mach-default/setup.c b/arch/x86/mach-default/setup.c
index 48278fa..3d31783 100644
--- a/arch/x86/mach-default/setup.c
+++ b/arch/x86/mach-default/setup.c
@@ -10,14 +10,6 @@
 #include <asm/e820.h>
 #include <asm/setup.h>
 
-/*
- * Any quirks to be performed to initialize timers/irqs/etc?
- */
-int (*arch_time_init_quirk)(void);
-int (*arch_pre_intr_init_quirk)(void);
-int (*arch_intr_init_quirk)(void);
-int (*arch_trap_init_quirk)(void);
-
 #ifdef CONFIG_HOTPLUG_CPU
 #define DEFAULT_SEND_IPI	(1)
 #else
@@ -37,8 +29,8 @@
  **/
 void __init pre_intr_init_hook(void)
 {
-	if (arch_pre_intr_init_quirk) {
-		if (arch_pre_intr_init_quirk())
+	if (x86_quirks->arch_pre_intr_init) {
+		if (x86_quirks->arch_pre_intr_init())
 			return;
 	}
 	init_ISA_irqs();
@@ -64,8 +56,8 @@
  **/
 void __init intr_init_hook(void)
 {
-	if (arch_intr_init_quirk) {
-		if (arch_intr_init_quirk())
+	if (x86_quirks->arch_intr_init) {
+		if (x86_quirks->arch_intr_init())
 			return;
 	}
 #ifdef CONFIG_X86_LOCAL_APIC
@@ -97,8 +89,8 @@
  **/
 void __init trap_init_hook(void)
 {
-	if (arch_trap_init_quirk) {
-		if (arch_trap_init_quirk())
+	if (x86_quirks->arch_trap_init) {
+		if (x86_quirks->arch_trap_init())
 			return;
 	}
 }
@@ -111,6 +103,16 @@
 };
 
 /**
+ * pre_time_init_hook - do any specific initialisations before.
+ *
+ **/
+void __init pre_time_init_hook(void)
+{
+	if (x86_quirks->arch_pre_time_init)
+		x86_quirks->arch_pre_time_init();
+}
+
+/**
  * time_init_hook - do any specific initialisations for the system timer.
  *
  * Description:
@@ -119,13 +121,13 @@
  **/
 void __init time_init_hook(void)
 {
-	if (arch_time_init_quirk) {
+	if (x86_quirks->arch_time_init) {
 		/*
 		 * A nonzero return code does not mean failure, it means
 		 * that the architecture quirk does not want any
 		 * generic (timer) setup to be performed after this:
 		 */
-		if (arch_time_init_quirk())
+		if (x86_quirks->arch_time_init())
 			return;
 	}
 
diff --git a/arch/x86/mach-es7000/es7000plat.c b/arch/x86/mach-es7000/es7000plat.c
index 4354ce8..50189af 100644
--- a/arch/x86/mach-es7000/es7000plat.c
+++ b/arch/x86/mach-es7000/es7000plat.c
@@ -130,10 +130,10 @@
 			mip_addr = val;
 			mip = (struct mip_reg *)val;
 			mip_reg = __va(mip);
-			Dprintk("es7000_mipcfg: host_reg = 0x%lx \n",
-				(unsigned long)host_reg);
-			Dprintk("es7000_mipcfg: mip_reg = 0x%lx \n",
-				(unsigned long)mip_reg);
+			pr_debug("es7000_mipcfg: host_reg = 0x%lx \n",
+				 (unsigned long)host_reg);
+			pr_debug("es7000_mipcfg: mip_reg = 0x%lx \n",
+				 (unsigned long)mip_reg);
 			success++;
 			break;
 		case MIP_PSAI_REG:
diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile
index 9873716..1fbb844 100644
--- a/arch/x86/mm/Makefile
+++ b/arch/x86/mm/Makefile
@@ -21,3 +21,4 @@
 endif
 obj-$(CONFIG_ACPI_NUMA)		+= srat_$(BITS).o
 
+obj-$(CONFIG_MEMTEST)		+= memtest.o
diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c
index 0bb0cae..a20d1fa 100644
--- a/arch/x86/mm/dump_pagetables.c
+++ b/arch/x86/mm/dump_pagetables.c
@@ -148,8 +148,8 @@
 	 * we have now. "break" is either changing perms, levels or
 	 * address space marker.
 	 */
-	prot = pgprot_val(new_prot) & ~(PTE_MASK);
-	cur = pgprot_val(st->current_prot) & ~(PTE_MASK);
+	prot = pgprot_val(new_prot) & ~(PTE_PFN_MASK);
+	cur = pgprot_val(st->current_prot) & ~(PTE_PFN_MASK);
 
 	if (!st->level) {
 		/* First entry */
@@ -221,7 +221,7 @@
 	for (i = 0; i < PTRS_PER_PMD; i++) {
 		st->current_address = normalize_addr(P + i * PMD_LEVEL_MULT);
 		if (!pmd_none(*start)) {
-			pgprotval_t prot = pmd_val(*start) & ~PTE_MASK;
+			pgprotval_t prot = pmd_val(*start) & PTE_FLAGS_MASK;
 
 			if (pmd_large(*start) || !pmd_present(*start))
 				note_page(m, st, __pgprot(prot), 3);
@@ -253,7 +253,7 @@
 	for (i = 0; i < PTRS_PER_PUD; i++) {
 		st->current_address = normalize_addr(P + i * PUD_LEVEL_MULT);
 		if (!pud_none(*start)) {
-			pgprotval_t prot = pud_val(*start) & ~PTE_MASK;
+			pgprotval_t prot = pud_val(*start) & PTE_FLAGS_MASK;
 
 			if (pud_large(*start) || !pud_present(*start))
 				note_page(m, st, __pgprot(prot), 2);
@@ -288,7 +288,7 @@
 	for (i = 0; i < PTRS_PER_PGD; i++) {
 		st.current_address = normalize_addr(i * PGD_LEVEL_MULT);
 		if (!pgd_none(*start)) {
-			pgprotval_t prot = pgd_val(*start) & ~PTE_MASK;
+			pgprotval_t prot = pgd_val(*start) & PTE_FLAGS_MASK;
 
 			if (pgd_large(*start) || !pgd_present(*start))
 				note_page(m, &st, __pgprot(prot), 1);
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index 9689a51..d37f293 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -844,6 +844,9 @@
 		reserve_early(table_start << PAGE_SHIFT,
 				 table_end << PAGE_SHIFT, "PGTABLE");
 
+	if (!after_init_bootmem)
+		early_memtest(start, end);
+
 	return end >> PAGE_SHIFT;
 }
 
@@ -868,8 +871,6 @@
 	 */
 	sparse_init();
 	zone_sizes_init();
-
-	paravirt_post_allocator_init();
 }
 
 /*
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 306049e..ec37121 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -517,118 +517,6 @@
 		direct_gbpages = 0;
 }
 
-#ifdef CONFIG_MEMTEST
-
-static void __init memtest(unsigned long start_phys, unsigned long size,
-				 unsigned pattern)
-{
-	unsigned long i;
-	unsigned long *start;
-	unsigned long start_bad;
-	unsigned long last_bad;
-	unsigned long val;
-	unsigned long start_phys_aligned;
-	unsigned long count;
-	unsigned long incr;
-
-	switch (pattern) {
-	case 0:
-		val = 0UL;
-		break;
-	case 1:
-		val = -1UL;
-		break;
-	case 2:
-		val = 0x5555555555555555UL;
-		break;
-	case 3:
-		val = 0xaaaaaaaaaaaaaaaaUL;
-		break;
-	default:
-		return;
-	}
-
-	incr = sizeof(unsigned long);
-	start_phys_aligned = ALIGN(start_phys, incr);
-	count = (size - (start_phys_aligned - start_phys))/incr;
-	start = __va(start_phys_aligned);
-	start_bad = 0;
-	last_bad = 0;
-
-	for (i = 0; i < count; i++)
-		start[i] = val;
-	for (i = 0; i < count; i++, start++, start_phys_aligned += incr) {
-		if (*start != val) {
-			if (start_phys_aligned == last_bad + incr) {
-				last_bad += incr;
-			} else {
-				if (start_bad) {
-					printk(KERN_CONT "\n  %016lx bad mem addr %016lx - %016lx reserved",
-						val, start_bad, last_bad + incr);
-					reserve_early(start_bad, last_bad - start_bad, "BAD RAM");
-				}
-				start_bad = last_bad = start_phys_aligned;
-			}
-		}
-	}
-	if (start_bad) {
-		printk(KERN_CONT "\n  %016lx bad mem addr %016lx - %016lx reserved",
-			val, start_bad, last_bad + incr);
-		reserve_early(start_bad, last_bad - start_bad, "BAD RAM");
-	}
-
-}
-
-/* default is disabled */
-static int memtest_pattern __initdata;
-
-static int __init parse_memtest(char *arg)
-{
-	if (arg)
-		memtest_pattern = simple_strtoul(arg, NULL, 0);
-	return 0;
-}
-
-early_param("memtest", parse_memtest);
-
-static void __init early_memtest(unsigned long start, unsigned long end)
-{
-	u64 t_start, t_size;
-	unsigned pattern;
-
-	if (!memtest_pattern)
-		return;
-
-	printk(KERN_INFO "early_memtest: pattern num %d", memtest_pattern);
-	for (pattern = 0; pattern < memtest_pattern; pattern++) {
-		t_start = start;
-		t_size = 0;
-		while (t_start < end) {
-			t_start = find_e820_area_size(t_start, &t_size, 1);
-
-			/* done ? */
-			if (t_start >= end)
-				break;
-			if (t_start + t_size > end)
-				t_size = end - t_start;
-
-			printk(KERN_CONT "\n  %016llx - %016llx pattern %d",
-				(unsigned long long)t_start,
-				(unsigned long long)t_start + t_size, pattern);
-
-			memtest(t_start, t_size, pattern);
-
-			t_start += t_size;
-		}
-	}
-	printk(KERN_CONT "\n");
-}
-#else
-static void __init early_memtest(unsigned long start, unsigned long end)
-{
-}
-#endif
-
 static unsigned long __init kernel_physical_mapping_init(unsigned long start,
 						unsigned long end,
 						unsigned long page_size_mask)
diff --git a/arch/x86/mm/memtest.c b/arch/x86/mm/memtest.c
new file mode 100644
index 0000000..672e17f
--- /dev/null
+++ b/arch/x86/mm/memtest.c
@@ -0,0 +1,123 @@
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/pfn.h>
+
+#include <asm/e820.h>
+
+static void __init memtest(unsigned long start_phys, unsigned long size,
+				 unsigned pattern)
+{
+	unsigned long i;
+	unsigned long *start;
+	unsigned long start_bad;
+	unsigned long last_bad;
+	unsigned long val;
+	unsigned long start_phys_aligned;
+	unsigned long count;
+	unsigned long incr;
+
+	switch (pattern) {
+	case 0:
+		val = 0UL;
+		break;
+	case 1:
+		val = -1UL;
+		break;
+	case 2:
+#ifdef CONFIG_X86_64
+		val = 0x5555555555555555UL;
+#else
+		val = 0x55555555UL;
+#endif
+		break;
+	case 3:
+#ifdef CONFIG_X86_64
+		val = 0xaaaaaaaaaaaaaaaaUL;
+#else
+		val = 0xaaaaaaaaUL;
+#endif
+		break;
+	default:
+		return;
+	}
+
+	incr = sizeof(unsigned long);
+	start_phys_aligned = ALIGN(start_phys, incr);
+	count = (size - (start_phys_aligned - start_phys))/incr;
+	start = __va(start_phys_aligned);
+	start_bad = 0;
+	last_bad = 0;
+
+	for (i = 0; i < count; i++)
+		start[i] = val;
+	for (i = 0; i < count; i++, start++, start_phys_aligned += incr) {
+		if (*start != val) {
+			if (start_phys_aligned == last_bad + incr) {
+				last_bad += incr;
+			} else {
+				if (start_bad) {
+					printk(KERN_CONT "\n  %010lx bad mem addr %010lx - %010lx reserved",
+						val, start_bad, last_bad + incr);
+					reserve_early(start_bad, last_bad - start_bad, "BAD RAM");
+				}
+				start_bad = last_bad = start_phys_aligned;
+			}
+		}
+	}
+	if (start_bad) {
+		printk(KERN_CONT "\n  %016lx bad mem addr %010lx - %010lx reserved",
+			val, start_bad, last_bad + incr);
+		reserve_early(start_bad, last_bad - start_bad, "BAD RAM");
+	}
+
+}
+
+/* default is disabled */
+static int memtest_pattern __initdata;
+
+static int __init parse_memtest(char *arg)
+{
+	if (arg)
+		memtest_pattern = simple_strtoul(arg, NULL, 0);
+	return 0;
+}
+
+early_param("memtest", parse_memtest);
+
+void __init early_memtest(unsigned long start, unsigned long end)
+{
+	u64 t_start, t_size;
+	unsigned pattern;
+
+	if (!memtest_pattern)
+		return;
+
+	printk(KERN_INFO "early_memtest: pattern num %d", memtest_pattern);
+	for (pattern = 0; pattern < memtest_pattern; pattern++) {
+		t_start = start;
+		t_size = 0;
+		while (t_start < end) {
+			t_start = find_e820_area_size(t_start, &t_size, 1);
+
+			/* done ? */
+			if (t_start >= end)
+				break;
+			if (t_start + t_size > end)
+				t_size = end - t_start;
+
+			printk(KERN_CONT "\n  %010llx - %010llx pattern %d",
+				(unsigned long long)t_start,
+				(unsigned long long)t_start + t_size, pattern);
+
+			memtest(t_start, t_size, pattern);
+
+			t_start += t_size;
+		}
+	}
+	printk(KERN_CONT "\n");
+}
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c
index b432d57..9782f42 100644
--- a/arch/x86/mm/numa_64.c
+++ b/arch/x86/mm/numa_64.c
@@ -20,10 +20,6 @@
 #include <asm/acpi.h>
 #include <asm/k8.h>
 
-#ifndef Dprintk
-#define Dprintk(x...)
-#endif
-
 struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
 EXPORT_SYMBOL(node_data);
 
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index d458507..2fe30916 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -12,6 +12,8 @@
 #include <linux/gfp.h>
 #include <linux/fs.h>
 #include <linux/bootmem.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 
 #include <asm/msr.h>
 #include <asm/tlbflush.h>
@@ -373,8 +375,8 @@
 	return vma_prot;
 }
 
-#ifdef CONFIG_NONPROMISC_DEVMEM
-/* This check is done in drivers/char/mem.c in case of NONPROMISC_DEVMEM*/
+#ifdef CONFIG_STRICT_DEVMEM
+/* This check is done in drivers/char/mem.c in case of STRICT_DEVMEM*/
 static inline int range_is_allowed(unsigned long pfn, unsigned long size)
 {
 	return 1;
@@ -398,7 +400,7 @@
 	}
 	return 1;
 }
-#endif /* CONFIG_NONPROMISC_DEVMEM */
+#endif /* CONFIG_STRICT_DEVMEM */
 
 int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
 				unsigned long size, pgprot_t *vma_prot)
@@ -489,3 +491,89 @@
 
 	free_memtype(addr, addr + size);
 }
+
+#if defined(CONFIG_DEBUG_FS)
+
+/* get Nth element of the linked list */
+static struct memtype *memtype_get_idx(loff_t pos)
+{
+	struct memtype *list_node, *print_entry;
+	int i = 1;
+
+	print_entry  = kmalloc(sizeof(struct memtype), GFP_KERNEL);
+	if (!print_entry)
+		return NULL;
+
+	spin_lock(&memtype_lock);
+	list_for_each_entry(list_node, &memtype_list, nd) {
+		if (pos == i) {
+			*print_entry = *list_node;
+			spin_unlock(&memtype_lock);
+			return print_entry;
+		}
+		++i;
+	}
+	spin_unlock(&memtype_lock);
+	kfree(print_entry);
+	return NULL;
+}
+
+static void *memtype_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	if (*pos == 0) {
+		++*pos;
+		seq_printf(seq, "PAT memtype list:\n");
+	}
+
+	return memtype_get_idx(*pos);
+}
+
+static void *memtype_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	++*pos;
+	return memtype_get_idx(*pos);
+}
+
+static void memtype_seq_stop(struct seq_file *seq, void *v)
+{
+}
+
+static int memtype_seq_show(struct seq_file *seq, void *v)
+{
+	struct memtype *print_entry = (struct memtype *)v;
+
+	seq_printf(seq, "%s @ 0x%Lx-0x%Lx\n", cattr_name(print_entry->type),
+			print_entry->start, print_entry->end);
+	kfree(print_entry);
+	return 0;
+}
+
+static struct seq_operations memtype_seq_ops = {
+	.start = memtype_seq_start,
+	.next  = memtype_seq_next,
+	.stop  = memtype_seq_stop,
+	.show  = memtype_seq_show,
+};
+
+static int memtype_seq_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &memtype_seq_ops);
+}
+
+static const struct file_operations memtype_fops = {
+	.open    = memtype_seq_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release,
+};
+
+static int __init pat_memtype_list_init(void)
+{
+	debugfs_create_file("pat_memtype_list", S_IRUSR, arch_debugfs_dir,
+				NULL, &memtype_fops);
+	return 0;
+}
+
+late_initcall(pat_memtype_list_init);
+
+#endif /* CONFIG_DEBUG_FS */
diff --git a/arch/x86/pci/Makefile b/arch/x86/pci/Makefile
index e515e8d..d49202e 100644
--- a/arch/x86/pci/Makefile
+++ b/arch/x86/pci/Makefile
@@ -5,13 +5,13 @@
 obj-$(CONFIG_PCI_DIRECT)	+= direct.o
 obj-$(CONFIG_PCI_OLPC)		+= olpc.o
 
-pci-y				:= fixup.o
-pci-$(CONFIG_ACPI)		+= acpi.o
-pci-y				+= legacy.o irq.o
+obj-y				+= fixup.o
+obj-$(CONFIG_ACPI)		+= acpi.o
+obj-y				+= legacy.o irq.o
 
-pci-$(CONFIG_X86_VISWS)		+= visws.o
+obj-$(CONFIG_X86_VISWS)		+= visws.o
 
-pci-$(CONFIG_X86_NUMAQ)		+= numa.o
+obj-$(CONFIG_X86_NUMAQ)		+= numaq_32.o
 
-obj-y				+= $(pci-y) common.o early.o
+obj-y				+= common.o early.o
 obj-y				+= amd_bus.o
diff --git a/arch/x86/pci/early.c b/arch/x86/pci/early.c
index 858dbe3..86631cc 100644
--- a/arch/x86/pci/early.c
+++ b/arch/x86/pci/early.c
@@ -7,15 +7,13 @@
 /* Direct PCI access. This is used for PCI accesses in early boot before
    the PCI subsystem works. */
 
-#define PDprintk(x...)
-
 u32 read_pci_config(u8 bus, u8 slot, u8 func, u8 offset)
 {
 	u32 v;
 	outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
 	v = inl(0xcfc);
 	if (v != 0xffffffff)
-		PDprintk("%x reading 4 from %x: %x\n", slot, offset, v);
+		pr_debug("%x reading 4 from %x: %x\n", slot, offset, v);
 	return v;
 }
 
@@ -24,7 +22,7 @@
 	u8 v;
 	outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
 	v = inb(0xcfc + (offset&3));
-	PDprintk("%x reading 1 from %x: %x\n", slot, offset, v);
+	pr_debug("%x reading 1 from %x: %x\n", slot, offset, v);
 	return v;
 }
 
@@ -33,28 +31,28 @@
 	u16 v;
 	outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
 	v = inw(0xcfc + (offset&2));
-	PDprintk("%x reading 2 from %x: %x\n", slot, offset, v);
+	pr_debug("%x reading 2 from %x: %x\n", slot, offset, v);
 	return v;
 }
 
 void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset,
 				    u32 val)
 {
-	PDprintk("%x writing to %x: %x\n", slot, offset, val);
+	pr_debug("%x writing to %x: %x\n", slot, offset, val);
 	outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
 	outl(val, 0xcfc);
 }
 
 void write_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset, u8 val)
 {
-	PDprintk("%x writing to %x: %x\n", slot, offset, val);
+	pr_debug("%x writing to %x: %x\n", slot, offset, val);
 	outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
 	outb(val, 0xcfc + (offset&3));
 }
 
 void write_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset, u16 val)
 {
-	PDprintk("%x writing to %x: %x\n", slot, offset, val);
+	pr_debug("%x writing to %x: %x\n", slot, offset, val);
 	outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
 	outw(val, 0xcfc + (offset&2));
 }
@@ -71,7 +69,7 @@
 	int j;
 	u32 val;
 
-	printk("PCI: %02x:%02x:%02x", bus, slot, func);
+	printk(KERN_INFO "PCI: %02x:%02x:%02x", bus, slot, func);
 
 	for (i = 0; i < 256; i += 4) {
 		if (!(i & 0x0f))
diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c
index 132876c..ec9ce35e4 100644
--- a/arch/x86/pci/legacy.c
+++ b/arch/x86/pci/legacy.c
@@ -57,14 +57,17 @@
 
 int __init pci_subsys_init(void)
 {
+#ifdef CONFIG_X86_NUMAQ
+	pci_numaq_init();
+#endif
 #ifdef CONFIG_ACPI
 	pci_acpi_init();
 #endif
+#ifdef CONFIG_X86_VISWS
+	pci_visws_init();
+#endif
 	pci_legacy_init();
 	pcibios_irq_init();
-#ifdef CONFIG_X86_NUMAQ
-	pci_numa_init();
-#endif
 	pcibios_init();
 
 	return 0;
diff --git a/arch/x86/pci/numa.c b/arch/x86/pci/numaq_32.c
similarity index 97%
rename from arch/x86/pci/numa.c
rename to arch/x86/pci/numaq_32.c
index 8b5ca19..f4b16dc 100644
--- a/arch/x86/pci/numa.c
+++ b/arch/x86/pci/numaq_32.c
@@ -1,5 +1,5 @@
 /*
- * numa.c - Low-level PCI access for NUMA-Q machines
+ * numaq_32.c - Low-level PCI access for NUMA-Q machines
  */
 
 #include <linux/pci.h>
@@ -151,7 +151,7 @@
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx);
 
-int __init pci_numa_init(void)
+int __init pci_numaq_init(void)
 {
 	int quad;
 
diff --git a/arch/x86/pci/pci.h b/arch/x86/pci/pci.h
index 3e25deb..15b9cf6b 100644
--- a/arch/x86/pci/pci.h
+++ b/arch/x86/pci/pci.h
@@ -108,7 +108,8 @@
 /* some common used subsys_initcalls */
 extern int __init pci_acpi_init(void);
 extern int __init pcibios_irq_init(void);
-extern int __init pci_numa_init(void);
+extern int __init pci_visws_init(void);
+extern int __init pci_numaq_init(void);
 extern int __init pcibios_init(void);
 
 /* pci-mmconfig.c */
diff --git a/arch/x86/pci/visws.c b/arch/x86/pci/visws.c
index 1a7bed4..42f4cb1 100644
--- a/arch/x86/pci/visws.c
+++ b/arch/x86/pci/visws.c
@@ -86,8 +86,14 @@
 	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
 }
 
-static int __init pci_visws_init(void)
+int __init pci_visws_init(void)
 {
+	if (!is_visws_box())
+		return -1;
+
+	pcibios_enable_irq = &pci_visws_enable_irq;
+	pcibios_disable_irq = &pci_visws_disable_irq;
+
 	/* The VISWS supports configuration access type 1 only */
 	pci_probe = (pci_probe | PCI_PROBE_CONF1) &
 		    ~(PCI_PROBE_BIOS | PCI_PROBE_CONF2);
@@ -105,18 +111,3 @@
 	pcibios_resource_survey();
 	return 0;
 }
-
-static __init int pci_subsys_init(void)
-{
-	if (!is_visws_box())
-		return -1;
-
-	pcibios_enable_irq = &pci_visws_enable_irq;
-	pcibios_disable_irq = &pci_visws_disable_irq;
-
-	pci_visws_init();
-	pcibios_init();
-
-	return 0;
-}
-subsys_initcall(pci_subsys_init);
diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile
index b7ad9f8..4d6ef0a 100644
--- a/arch/x86/vdso/Makefile
+++ b/arch/x86/vdso/Makefile
@@ -62,7 +62,7 @@
 # Build multiple 32-bit vDSO images to choose from at boot time.
 #
 obj-$(VDSO32-y)			+= vdso32-syms.lds
-vdso32.so-$(CONFIG_X86_32)	+= int80
+vdso32.so-$(VDSO32-y)		+= int80
 vdso32.so-$(CONFIG_COMPAT)	+= syscall
 vdso32.so-$(VDSO32-y)		+= sysenter
 
diff --git a/arch/x86/vdso/vdso32-setup.c b/arch/x86/vdso/vdso32-setup.c
index 0bce542..513f330 100644
--- a/arch/x86/vdso/vdso32-setup.c
+++ b/arch/x86/vdso/vdso32-setup.c
@@ -193,17 +193,12 @@
 	}
 }
 
-/*
- * These symbols are defined by vdso32.S to mark the bounds
- * of the ELF DSO images included therein.
- */
-extern const char vdso32_default_start, vdso32_default_end;
-extern const char vdso32_sysenter_start, vdso32_sysenter_end;
 static struct page *vdso32_pages[1];
 
 #ifdef CONFIG_X86_64
 
 #define	vdso32_sysenter()	(boot_cpu_has(X86_FEATURE_SYSENTER32))
+#define	vdso32_syscall()	(boot_cpu_has(X86_FEATURE_SYSCALL32))
 
 /* May not be __init: called during resume */
 void syscall32_cpu_init(void)
@@ -226,6 +221,7 @@
 #else  /* CONFIG_X86_32 */
 
 #define vdso32_sysenter()	(boot_cpu_has(X86_FEATURE_SEP))
+#define vdso32_syscall()	(0)
 
 void enable_sep_cpu(void)
 {
@@ -296,12 +292,15 @@
 	gate_vma_init();
 #endif
 
-	if (!vdso32_sysenter()) {
-		vsyscall = &vdso32_default_start;
-		vsyscall_len = &vdso32_default_end - &vdso32_default_start;
-	} else {
+	if (vdso32_syscall()) {
+		vsyscall = &vdso32_syscall_start;
+		vsyscall_len = &vdso32_syscall_end - &vdso32_syscall_start;
+	} else if (vdso32_sysenter()){
 		vsyscall = &vdso32_sysenter_start;
 		vsyscall_len = &vdso32_sysenter_end - &vdso32_sysenter_start;
+	} else {
+		vsyscall = &vdso32_int80_start;
+		vsyscall_len = &vdso32_int80_end - &vdso32_int80_start;
 	}
 
 	memcpy(syscall_page, vsyscall, vsyscall_len);
diff --git a/arch/x86/vdso/vdso32.S b/arch/x86/vdso/vdso32.S
index 1e36f72..2ce5f82 100644
--- a/arch/x86/vdso/vdso32.S
+++ b/arch/x86/vdso/vdso32.S
@@ -2,14 +2,17 @@
 
 __INITDATA
 
-	.globl vdso32_default_start, vdso32_default_end
-vdso32_default_start:
-#ifdef CONFIG_X86_32
+	.globl vdso32_int80_start, vdso32_int80_end
+vdso32_int80_start:
 	.incbin "arch/x86/vdso/vdso32-int80.so"
-#else
+vdso32_int80_end:
+
+	.globl vdso32_syscall_start, vdso32_syscall_end
+vdso32_syscall_start:
+#ifdef CONFIG_COMPAT
 	.incbin "arch/x86/vdso/vdso32-syscall.so"
 #endif
-vdso32_default_end:
+vdso32_syscall_end:
 
 	.globl vdso32_sysenter_start, vdso32_sysenter_end
 vdso32_sysenter_start:
diff --git a/arch/x86/vdso/vma.c b/arch/x86/vdso/vma.c
index 19a6cfa..257ba4a 100644
--- a/arch/x86/vdso/vma.c
+++ b/arch/x86/vdso/vma.c
@@ -21,7 +21,8 @@
 extern char vdso_start[], vdso_end[];
 extern unsigned short vdso_sync_cpuid;
 
-struct page **vdso_pages;
+static struct page **vdso_pages;
+static unsigned vdso_size;
 
 static inline void *var_ref(void *p, char *name)
 {
@@ -38,6 +39,7 @@
 	int i;
 	char *vbase;
 
+	vdso_size = npages << PAGE_SHIFT;
 	vdso_pages = kmalloc(sizeof(struct page *) * npages, GFP_KERNEL);
 	if (!vdso_pages)
 		goto oom;
@@ -101,20 +103,19 @@
 	struct mm_struct *mm = current->mm;
 	unsigned long addr;
 	int ret;
-	unsigned len = round_up(vdso_end - vdso_start, PAGE_SIZE);
 
 	if (!vdso_enabled)
 		return 0;
 
 	down_write(&mm->mmap_sem);
-	addr = vdso_addr(mm->start_stack, len);
-	addr = get_unmapped_area(NULL, addr, len, 0, 0);
+	addr = vdso_addr(mm->start_stack, vdso_size);
+	addr = get_unmapped_area(NULL, addr, vdso_size, 0, 0);
 	if (IS_ERR_VALUE(addr)) {
 		ret = addr;
 		goto up_fail;
 	}
 
-	ret = install_special_mapping(mm, addr, len,
+	ret = install_special_mapping(mm, addr, vdso_size,
 				      VM_READ|VM_EXEC|
 				      VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
 				      VM_ALWAYSDUMP,
diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig
index c2cc995..3815e42 100644
--- a/arch/x86/xen/Kconfig
+++ b/arch/x86/xen/Kconfig
@@ -6,8 +6,8 @@
 	bool "Xen guest support"
 	select PARAVIRT
 	select PARAVIRT_CLOCK
-	depends on X86_32
-	depends on X86_CMPXCHG && X86_TSC && X86_PAE && !(X86_VISWS || X86_VOYAGER)
+	depends on X86_64 || (X86_32 && X86_PAE && !(X86_VISWS || X86_VOYAGER))
+	depends on X86_CMPXCHG && X86_TSC
 	help
 	  This is the Linux Xen port.  Enabling this will allow the
 	  kernel to boot in a paravirtualized environment under the
@@ -15,10 +15,16 @@
 
 config XEN_MAX_DOMAIN_MEMORY
        int "Maximum allowed size of a domain in gigabytes"
-       default 8
+       default 8 if X86_32
+       default 32 if X86_64
        depends on XEN
        help
          The pseudo-physical to machine address array is sized
          according to the maximum possible memory size of a Xen
          domain.  This array uses 1 page per gigabyte, so there's no
-         need to be too stingy here.
\ No newline at end of file
+         need to be too stingy here.
+
+config XEN_SAVE_RESTORE
+       bool
+       depends on PM
+       default y
\ No newline at end of file
diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile
index 2ba2d16..59c1e53 100644
--- a/arch/x86/xen/Makefile
+++ b/arch/x86/xen/Makefile
@@ -1,4 +1,4 @@
 obj-y		:= enlighten.o setup.o multicalls.o mmu.o \
-			time.o xen-asm.o grant-table.o suspend.o
+			time.o xen-asm_$(BITS).o grant-table.o suspend.o
 
 obj-$(CONFIG_SMP)	+= smp.o
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index bb50845..9ff6e3c 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -33,6 +33,7 @@
 #include <xen/interface/sched.h>
 #include <xen/features.h>
 #include <xen/page.h>
+#include <xen/hvc-console.h>
 
 #include <asm/paravirt.h>
 #include <asm/page.h>
@@ -40,12 +41,12 @@
 #include <asm/xen/hypervisor.h>
 #include <asm/fixmap.h>
 #include <asm/processor.h>
+#include <asm/msr-index.h>
 #include <asm/setup.h>
 #include <asm/desc.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
 #include <asm/reboot.h>
-#include <asm/pgalloc.h>
 
 #include "xen-ops.h"
 #include "mmu.h"
@@ -57,6 +58,18 @@
 DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info);
 
 /*
+ * Identity map, in addition to plain kernel map.  This needs to be
+ * large enough to allocate page table pages to allocate the rest.
+ * Each page can map 2MB.
+ */
+static pte_t level1_ident_pgt[PTRS_PER_PTE * 4] __page_aligned_bss;
+
+#ifdef CONFIG_X86_64
+/* l3 pud for userspace vsyscall mapping */
+static pud_t level3_user_vsyscall[PTRS_PER_PUD] __page_aligned_bss;
+#endif /* CONFIG_X86_64 */
+
+/*
  * Note about cr3 (pagetable base) values:
  *
  * xen_cr3 contains the current logical cr3 value; it contains the
@@ -167,10 +180,14 @@
 
 static void __init xen_banner(void)
 {
+	unsigned version = HYPERVISOR_xen_version(XENVER_version, NULL);
+	struct xen_extraversion extra;
+	HYPERVISOR_xen_version(XENVER_extraversion, &extra);
+
 	printk(KERN_INFO "Booting paravirtualized kernel on %s\n",
 	       pv_info.name);
-	printk(KERN_INFO "Hypervisor signature: %s%s\n",
-	       xen_start_info->magic,
+	printk(KERN_INFO "Xen version: %d.%d%s%s\n",
+	       version >> 16, version & 0xffff, extra.extraversion,
 	       xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : "");
 }
 
@@ -363,14 +380,6 @@
 
 static void xen_load_tls(struct thread_struct *t, unsigned int cpu)
 {
-	xen_mc_batch();
-
-	load_TLS_descriptor(t, cpu, 0);
-	load_TLS_descriptor(t, cpu, 1);
-	load_TLS_descriptor(t, cpu, 2);
-
-	xen_mc_issue(PARAVIRT_LAZY_CPU);
-
 	/*
 	 * XXX sleazy hack: If we're being called in a lazy-cpu zone,
 	 * it means we're in a context switch, and %gs has just been
@@ -379,11 +388,40 @@
 	 * Either way, it has been saved, and the new value will get
 	 * loaded properly.  This will go away as soon as Xen has been
 	 * modified to not save/restore %gs for normal hypercalls.
+	 *
+	 * On x86_64, this hack is not used for %gs, because gs points
+	 * to KERNEL_GS_BASE (and uses it for PDA references), so we
+	 * must not zero %gs on x86_64
+	 *
+	 * For x86_64, we need to zero %fs, otherwise we may get an
+	 * exception between the new %fs descriptor being loaded and
+	 * %fs being effectively cleared at __switch_to().
 	 */
-	if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_CPU)
+	if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_CPU) {
+#ifdef CONFIG_X86_32
 		loadsegment(gs, 0);
+#else
+		loadsegment(fs, 0);
+#endif
+	}
+
+	xen_mc_batch();
+
+	load_TLS_descriptor(t, cpu, 0);
+	load_TLS_descriptor(t, cpu, 1);
+	load_TLS_descriptor(t, cpu, 2);
+
+	xen_mc_issue(PARAVIRT_LAZY_CPU);
 }
 
+#ifdef CONFIG_X86_64
+static void xen_load_gs_index(unsigned int idx)
+{
+	if (HYPERVISOR_set_segment_base(SEGBASE_GS_USER_SEL, idx))
+		BUG();
+}
+#endif
+
 static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum,
 				const void *ptr)
 {
@@ -400,23 +438,18 @@
 	preempt_enable();
 }
 
-static int cvt_gate_to_trap(int vector, u32 low, u32 high,
+static int cvt_gate_to_trap(int vector, const gate_desc *val,
 			    struct trap_info *info)
 {
-	u8 type, dpl;
-
-	type = (high >> 8) & 0x1f;
-	dpl = (high >> 13) & 3;
-
-	if (type != 0xf && type != 0xe)
+	if (val->type != 0xf && val->type != 0xe)
 		return 0;
 
 	info->vector = vector;
-	info->address = (high & 0xffff0000) | (low & 0x0000ffff);
-	info->cs = low >> 16;
-	info->flags = dpl;
+	info->address = gate_offset(*val);
+	info->cs = gate_segment(*val);
+	info->flags = val->dpl;
 	/* interrupt gates clear IF */
-	if (type == 0xe)
+	if (val->type == 0xe)
 		info->flags |= 4;
 
 	return 1;
@@ -443,11 +476,10 @@
 
 	if (p >= start && (p + 8) <= end) {
 		struct trap_info info[2];
-		u32 *desc = (u32 *)g;
 
 		info[1].address = 0;
 
-		if (cvt_gate_to_trap(entrynum, desc[0], desc[1], &info[0]))
+		if (cvt_gate_to_trap(entrynum, g, &info[0]))
 			if (HYPERVISOR_set_trap_table(info))
 				BUG();
 	}
@@ -460,13 +492,13 @@
 {
 	unsigned in, out, count;
 
-	count = (desc->size+1) / 8;
+	count = (desc->size+1) / sizeof(gate_desc);
 	BUG_ON(count > 256);
 
 	for (in = out = 0; in < count; in++) {
-		const u32 *entry = (u32 *)(desc->address + in * 8);
+		gate_desc *entry = (gate_desc*)(desc->address) + in;
 
-		if (cvt_gate_to_trap(in, entry[0], entry[1], &traps[out]))
+		if (cvt_gate_to_trap(in, entry, &traps[out]))
 			out++;
 	}
 	traps[out].address = 0;
@@ -695,33 +727,89 @@
 	x86_write_percpu(xen_current_cr3, (unsigned long)v);
 }
 
-static void xen_write_cr3(unsigned long cr3)
+static void __xen_write_cr3(bool kernel, unsigned long cr3)
 {
 	struct mmuext_op *op;
 	struct multicall_space mcs;
-	unsigned long mfn = pfn_to_mfn(PFN_DOWN(cr3));
+	unsigned long mfn;
 
+	if (cr3)
+		mfn = pfn_to_mfn(PFN_DOWN(cr3));
+	else
+		mfn = 0;
+
+	WARN_ON(mfn == 0 && kernel);
+
+	mcs = __xen_mc_entry(sizeof(*op));
+
+	op = mcs.args;
+	op->cmd = kernel ? MMUEXT_NEW_BASEPTR : MMUEXT_NEW_USER_BASEPTR;
+	op->arg1.mfn = mfn;
+
+	MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
+
+	if (kernel) {
+		x86_write_percpu(xen_cr3, cr3);
+
+		/* Update xen_current_cr3 once the batch has actually
+		   been submitted. */
+		xen_mc_callback(set_current_cr3, (void *)cr3);
+	}
+}
+
+static void xen_write_cr3(unsigned long cr3)
+{
 	BUG_ON(preemptible());
 
-	mcs = xen_mc_entry(sizeof(*op));  /* disables interrupts */
+	xen_mc_batch();  /* disables interrupts */
 
 	/* Update while interrupts are disabled, so its atomic with
 	   respect to ipis */
 	x86_write_percpu(xen_cr3, cr3);
 
-	op = mcs.args;
-	op->cmd = MMUEXT_NEW_BASEPTR;
-	op->arg1.mfn = mfn;
+	__xen_write_cr3(true, cr3);
 
-	MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
-
-	/* Update xen_update_cr3 once the batch has actually
-	   been submitted. */
-	xen_mc_callback(set_current_cr3, (void *)cr3);
+#ifdef CONFIG_X86_64
+	{
+		pgd_t *user_pgd = xen_get_user_pgd(__va(cr3));
+		if (user_pgd)
+			__xen_write_cr3(false, __pa(user_pgd));
+		else
+			__xen_write_cr3(false, 0);
+	}
+#endif
 
 	xen_mc_issue(PARAVIRT_LAZY_CPU);  /* interrupts restored */
 }
 
+static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
+{
+	int ret;
+
+	ret = 0;
+
+	switch(msr) {
+#ifdef CONFIG_X86_64
+		unsigned which;
+		u64 base;
+
+	case MSR_FS_BASE:		which = SEGBASE_FS; goto set;
+	case MSR_KERNEL_GS_BASE:	which = SEGBASE_GS_USER; goto set;
+	case MSR_GS_BASE:		which = SEGBASE_GS_KERNEL; goto set;
+
+	set:
+		base = ((u64)high << 32) | low;
+		if (HYPERVISOR_set_segment_base(which, base) != 0)
+			ret = -EFAULT;
+		break;
+#endif
+	default:
+		ret = native_write_msr_safe(msr, low, high);
+	}
+
+	return ret;
+}
+
 /* Early in boot, while setting up the initial pagetable, assume
    everything is pinned. */
 static __init void xen_alloc_pte_init(struct mm_struct *mm, u32 pfn)
@@ -778,6 +866,48 @@
 	xen_alloc_ptpage(mm, pfn, PT_PMD);
 }
 
+static int xen_pgd_alloc(struct mm_struct *mm)
+{
+	pgd_t *pgd = mm->pgd;
+	int ret = 0;
+
+	BUG_ON(PagePinned(virt_to_page(pgd)));
+
+#ifdef CONFIG_X86_64
+	{
+		struct page *page = virt_to_page(pgd);
+		pgd_t *user_pgd;
+
+		BUG_ON(page->private != 0);
+
+		ret = -ENOMEM;
+
+		user_pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
+		page->private = (unsigned long)user_pgd;
+
+		if (user_pgd != NULL) {
+			user_pgd[pgd_index(VSYSCALL_START)] =
+				__pgd(__pa(level3_user_vsyscall) | _PAGE_TABLE);
+			ret = 0;
+		}
+
+		BUG_ON(PagePinned(virt_to_page(xen_get_user_pgd(pgd))));
+	}
+#endif
+
+	return ret;
+}
+
+static void xen_pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+#ifdef CONFIG_X86_64
+	pgd_t *user_pgd = xen_get_user_pgd(pgd);
+
+	if (user_pgd)
+		free_page((unsigned long)user_pgd);
+#endif
+}
+
 /* This should never happen until we're OK to use struct page */
 static void xen_release_ptpage(u32 pfn, unsigned level)
 {
@@ -803,6 +933,18 @@
 	xen_release_ptpage(pfn, PT_PMD);
 }
 
+#if PAGETABLE_LEVELS == 4
+static void xen_alloc_pud(struct mm_struct *mm, u32 pfn)
+{
+	xen_alloc_ptpage(mm, pfn, PT_PUD);
+}
+
+static void xen_release_pud(u32 pfn)
+{
+	xen_release_ptpage(pfn, PT_PUD);
+}
+#endif
+
 #ifdef CONFIG_HIGHPTE
 static void *xen_kmap_atomic_pte(struct page *page, enum km_type type)
 {
@@ -841,68 +983,16 @@
 
 static __init void xen_pagetable_setup_start(pgd_t *base)
 {
-	pgd_t *xen_pgd = (pgd_t *)xen_start_info->pt_base;
-	int i;
-
-	/* special set_pte for pagetable initialization */
-	pv_mmu_ops.set_pte = xen_set_pte_init;
-
-	init_mm.pgd = base;
-	/*
-	 * copy top-level of Xen-supplied pagetable into place.  This
-	 * is a stand-in while we copy the pmd pages.
-	 */
-	memcpy(base, xen_pgd, PTRS_PER_PGD * sizeof(pgd_t));
-
-	/*
-	 * For PAE, need to allocate new pmds, rather than
-	 * share Xen's, since Xen doesn't like pmd's being
-	 * shared between address spaces.
-	 */
-	for (i = 0; i < PTRS_PER_PGD; i++) {
-		if (pgd_val_ma(xen_pgd[i]) & _PAGE_PRESENT) {
-			pmd_t *pmd = (pmd_t *)alloc_bootmem_low_pages(PAGE_SIZE);
-
-			memcpy(pmd, (void *)pgd_page_vaddr(xen_pgd[i]),
-			       PAGE_SIZE);
-
-			make_lowmem_page_readonly(pmd);
-
-			set_pgd(&base[i], __pgd(1 + __pa(pmd)));
-		} else
-			pgd_clear(&base[i]);
-	}
-
-	/* make sure zero_page is mapped RO so we can use it in pagetables */
-	make_lowmem_page_readonly(empty_zero_page);
-	make_lowmem_page_readonly(base);
-	/*
-	 * Switch to new pagetable.  This is done before
-	 * pagetable_init has done anything so that the new pages
-	 * added to the table can be prepared properly for Xen.
-	 */
-	xen_write_cr3(__pa(base));
-
-	/* Unpin initial Xen pagetable */
-	pin_pagetable_pfn(MMUEXT_UNPIN_TABLE,
-			  PFN_DOWN(__pa(xen_start_info->pt_base)));
 }
 
 void xen_setup_shared_info(void)
 {
 	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
-		unsigned long addr = fix_to_virt(FIX_PARAVIRT_BOOTMAP);
+		set_fixmap(FIX_PARAVIRT_BOOTMAP,
+			   xen_start_info->shared_info);
 
-		/*
-		 * Create a mapping for the shared info page.
-		 * Should be set_fixmap(), but shared_info is a machine
-		 * address with no corresponding pseudo-phys address.
-		 */
-		set_pte_mfn(addr,
-			    PFN_DOWN(xen_start_info->shared_info),
-			    PAGE_KERNEL);
-
-		HYPERVISOR_shared_info = (struct shared_info *)addr;
+		HYPERVISOR_shared_info =
+			(struct shared_info *)fix_to_virt(FIX_PARAVIRT_BOOTMAP);
 	} else
 		HYPERVISOR_shared_info =
 			(struct shared_info *)__va(xen_start_info->shared_info);
@@ -917,26 +1007,32 @@
 
 static __init void xen_pagetable_setup_done(pgd_t *base)
 {
+	xen_setup_shared_info();
+}
+
+static __init void xen_post_allocator_init(void)
+{
+	pv_mmu_ops.set_pte = xen_set_pte;
+	pv_mmu_ops.set_pmd = xen_set_pmd;
+	pv_mmu_ops.set_pud = xen_set_pud;
+#if PAGETABLE_LEVELS == 4
+	pv_mmu_ops.set_pgd = xen_set_pgd;
+#endif
+
 	/* This will work as long as patching hasn't happened yet
 	   (which it hasn't) */
 	pv_mmu_ops.alloc_pte = xen_alloc_pte;
 	pv_mmu_ops.alloc_pmd = xen_alloc_pmd;
 	pv_mmu_ops.release_pte = xen_release_pte;
 	pv_mmu_ops.release_pmd = xen_release_pmd;
-	pv_mmu_ops.set_pte = xen_set_pte;
+#if PAGETABLE_LEVELS == 4
+	pv_mmu_ops.alloc_pud = xen_alloc_pud;
+	pv_mmu_ops.release_pud = xen_release_pud;
+#endif
 
-	xen_setup_shared_info();
-
-	/* Actually pin the pagetable down, but we can't set PG_pinned
-	   yet because the page structures don't exist yet. */
-	pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(base)));
-}
-
-static __init void xen_post_allocator_init(void)
-{
-	pv_mmu_ops.set_pmd = xen_set_pmd;
-	pv_mmu_ops.set_pud = xen_set_pud;
-
+#ifdef CONFIG_X86_64
+	SetPagePinned(virt_to_page(level3_user_vsyscall));
+#endif
 	xen_mark_init_mm_pinned();
 }
 
@@ -950,6 +1046,7 @@
 
 	/* xen_vcpu_setup managed to place the vcpu_info within the
 	   percpu area for all cpus, so make use of it */
+#ifdef CONFIG_X86_32
 	if (have_vcpu_info_placement) {
 		printk(KERN_INFO "Xen: using vcpu_info placement\n");
 
@@ -959,6 +1056,7 @@
 		pv_irq_ops.irq_enable = xen_irq_enable_direct;
 		pv_mmu_ops.read_cr2 = xen_read_cr2_direct;
 	}
+#endif
 }
 
 static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf,
@@ -979,10 +1077,12 @@
 	goto patch_site
 
 	switch (type) {
+#ifdef CONFIG_X86_32
 		SITE(pv_irq_ops, irq_enable);
 		SITE(pv_irq_ops, irq_disable);
 		SITE(pv_irq_ops, save_fl);
 		SITE(pv_irq_ops, restore_fl);
+#endif /* CONFIG_X86_32 */
 #undef SITE
 
 	patch_site:
@@ -1025,8 +1125,15 @@
 #ifdef CONFIG_X86_F00F_BUG
 	case FIX_F00F_IDT:
 #endif
+#ifdef CONFIG_X86_32
 	case FIX_WP_TEST:
 	case FIX_VDSO:
+# ifdef CONFIG_HIGHMEM
+	case FIX_KMAP_BEGIN ... FIX_KMAP_END:
+# endif
+#else
+	case VSYSCALL_LAST_PAGE ... VSYSCALL_FIRST_PAGE:
+#endif
 #ifdef CONFIG_X86_LOCAL_APIC
 	case FIX_APIC_BASE:	/* maps dummy local APIC */
 #endif
@@ -1039,6 +1146,15 @@
 	}
 
 	__native_set_fixmap(idx, pte);
+
+#ifdef CONFIG_X86_64
+	/* Replicate changes to map the vsyscall page into the user
+	   pagetable vsyscall mapping. */
+	if (idx >= VSYSCALL_LAST_PAGE && idx <= VSYSCALL_FIRST_PAGE) {
+		unsigned long vaddr = __fix_to_virt(idx);
+		set_pte_vaddr_pud(level3_user_vsyscall, vaddr, pte);
+	}
+#endif
 }
 
 static const struct pv_info xen_info __initdata = {
@@ -1084,18 +1200,25 @@
 	.wbinvd = native_wbinvd,
 
 	.read_msr = native_read_msr_safe,
-	.write_msr = native_write_msr_safe,
+	.write_msr = xen_write_msr_safe,
 	.read_tsc = native_read_tsc,
 	.read_pmc = native_read_pmc,
 
 	.iret = xen_iret,
 	.irq_enable_sysexit = xen_sysexit,
+#ifdef CONFIG_X86_64
+	.usergs_sysret32 = xen_sysret32,
+	.usergs_sysret64 = xen_sysret64,
+#endif
 
 	.load_tr_desc = paravirt_nop,
 	.set_ldt = xen_set_ldt,
 	.load_gdt = xen_load_gdt,
 	.load_idt = xen_load_idt,
 	.load_tls = xen_load_tls,
+#ifdef CONFIG_X86_64
+	.load_gs_index = xen_load_gs_index,
+#endif
 
 	.store_gdt = native_store_gdt,
 	.store_idt = native_store_idt,
@@ -1109,14 +1232,34 @@
 	.set_iopl_mask = xen_set_iopl_mask,
 	.io_delay = xen_io_delay,
 
+	/* Xen takes care of %gs when switching to usermode for us */
+	.swapgs = paravirt_nop,
+
 	.lazy_mode = {
 		.enter = paravirt_enter_lazy_cpu,
 		.leave = xen_leave_lazy,
 	},
 };
 
+static void __init __xen_init_IRQ(void)
+{
+#ifdef CONFIG_X86_64
+	int i;
+
+	/* Create identity vector->irq map */
+	for(i = 0; i < NR_VECTORS; i++) {
+		int cpu;
+
+		for_each_possible_cpu(cpu)
+			per_cpu(vector_irq, cpu)[i] = i;
+	}
+#endif	/* CONFIG_X86_64 */
+
+	xen_init_IRQ();
+}
+
 static const struct pv_irq_ops xen_irq_ops __initdata = {
-	.init_IRQ = xen_init_IRQ,
+	.init_IRQ = __xen_init_IRQ,
 	.save_fl = xen_save_fl,
 	.restore_fl = xen_restore_fl,
 	.irq_disable = xen_irq_disable,
@@ -1124,14 +1267,13 @@
 	.safe_halt = xen_safe_halt,
 	.halt = xen_halt,
 #ifdef CONFIG_X86_64
-	.adjust_exception_frame = paravirt_nop,
+	.adjust_exception_frame = xen_adjust_exception_frame,
 #endif
 };
 
 static const struct pv_apic_ops xen_apic_ops __initdata = {
 #ifdef CONFIG_X86_LOCAL_APIC
 	.apic_write = xen_apic_write,
-	.apic_write_atomic = xen_apic_write,
 	.apic_read = xen_apic_read,
 	.setup_boot_clock = paravirt_nop,
 	.setup_secondary_clock = paravirt_nop,
@@ -1157,8 +1299,8 @@
 	.pte_update = paravirt_nop,
 	.pte_update_defer = paravirt_nop,
 
-	.pgd_alloc = __paravirt_pgd_alloc,
-	.pgd_free = paravirt_nop,
+	.pgd_alloc = xen_pgd_alloc,
+	.pgd_free = xen_pgd_free,
 
 	.alloc_pte = xen_alloc_pte_init,
 	.release_pte = xen_release_pte_init,
@@ -1170,7 +1312,11 @@
 	.kmap_atomic_pte = xen_kmap_atomic_pte,
 #endif
 
-	.set_pte = NULL,	/* see xen_pagetable_setup_* */
+#ifdef CONFIG_X86_64
+	.set_pte = xen_set_pte,
+#else
+	.set_pte = xen_set_pte_init,
+#endif
 	.set_pte_at = xen_set_pte_at,
 	.set_pmd = xen_set_pmd_hyper,
 
@@ -1184,15 +1330,26 @@
 	.make_pte = xen_make_pte,
 	.make_pgd = xen_make_pgd,
 
+#ifdef CONFIG_X86_PAE
 	.set_pte_atomic = xen_set_pte_atomic,
 	.set_pte_present = xen_set_pte_at,
-	.set_pud = xen_set_pud_hyper,
 	.pte_clear = xen_pte_clear,
 	.pmd_clear = xen_pmd_clear,
+#endif	/* CONFIG_X86_PAE */
+	.set_pud = xen_set_pud_hyper,
 
 	.make_pmd = xen_make_pmd,
 	.pmd_val = xen_pmd_val,
 
+#if PAGETABLE_LEVELS == 4
+	.pud_val = xen_pud_val,
+	.make_pud = xen_make_pud,
+	.set_pgd = xen_set_pgd_hyper,
+
+	.alloc_pud = xen_alloc_pte_init,
+	.release_pud = xen_release_pte_init,
+#endif	/* PAGETABLE_LEVELS == 4 */
+
 	.activate_mm = xen_activate_mm,
 	.dup_mmap = xen_dup_mmap,
 	.exit_mmap = xen_exit_mmap,
@@ -1205,21 +1362,6 @@
 	.set_fixmap = xen_set_fixmap,
 };
 
-#ifdef CONFIG_SMP
-static const struct smp_ops xen_smp_ops __initdata = {
-	.smp_prepare_boot_cpu = xen_smp_prepare_boot_cpu,
-	.smp_prepare_cpus = xen_smp_prepare_cpus,
-	.cpu_up = xen_cpu_up,
-	.smp_cpus_done = xen_smp_cpus_done,
-
-	.smp_send_stop = xen_smp_send_stop,
-	.smp_send_reschedule = xen_smp_send_reschedule,
-
-	.send_call_func_ipi = xen_smp_send_call_function_ipi,
-	.send_call_func_single_ipi = xen_smp_send_call_function_single_ipi,
-};
-#endif	/* CONFIG_SMP */
-
 static void xen_reboot(int reason)
 {
 	struct sched_shutdown r = { .reason = reason };
@@ -1264,6 +1406,7 @@
 
 static void __init xen_reserve_top(void)
 {
+#ifdef CONFIG_X86_32
 	unsigned long top = HYPERVISOR_VIRT_START;
 	struct xen_platform_parameters pp;
 
@@ -1271,8 +1414,248 @@
 		top = pp.virt_start;
 
 	reserve_top_address(-top + 2 * PAGE_SIZE);
+#endif	/* CONFIG_X86_32 */
 }
 
+/*
+ * Like __va(), but returns address in the kernel mapping (which is
+ * all we have until the physical memory mapping has been set up.
+ */
+static void *__ka(phys_addr_t paddr)
+{
+#ifdef CONFIG_X86_64
+	return (void *)(paddr + __START_KERNEL_map);
+#else
+	return __va(paddr);
+#endif
+}
+
+/* Convert a machine address to physical address */
+static unsigned long m2p(phys_addr_t maddr)
+{
+	phys_addr_t paddr;
+
+	maddr &= PTE_PFN_MASK;
+	paddr = mfn_to_pfn(maddr >> PAGE_SHIFT) << PAGE_SHIFT;
+
+	return paddr;
+}
+
+/* Convert a machine address to kernel virtual */
+static void *m2v(phys_addr_t maddr)
+{
+	return __ka(m2p(maddr));
+}
+
+#ifdef CONFIG_X86_64
+static void walk(pgd_t *pgd, unsigned long addr)
+{
+	unsigned l4idx = pgd_index(addr);
+	unsigned l3idx = pud_index(addr);
+	unsigned l2idx = pmd_index(addr);
+	unsigned l1idx = pte_index(addr);
+	pgd_t l4;
+	pud_t l3;
+	pmd_t l2;
+	pte_t l1;
+
+	xen_raw_printk("walk %p, %lx -> %d %d %d %d\n",
+		       pgd, addr, l4idx, l3idx, l2idx, l1idx);
+
+	l4 = pgd[l4idx];
+	xen_raw_printk("  l4: %016lx\n", l4.pgd);
+	xen_raw_printk("      %016lx\n", pgd_val(l4));
+
+	l3 = ((pud_t *)(m2v(l4.pgd)))[l3idx];
+	xen_raw_printk("  l3: %016lx\n", l3.pud);
+	xen_raw_printk("      %016lx\n", pud_val(l3));
+
+	l2 = ((pmd_t *)(m2v(l3.pud)))[l2idx];
+	xen_raw_printk("  l2: %016lx\n", l2.pmd);
+	xen_raw_printk("      %016lx\n", pmd_val(l2));
+
+	l1 = ((pte_t *)(m2v(l2.pmd)))[l1idx];
+	xen_raw_printk("  l1: %016lx\n", l1.pte);
+	xen_raw_printk("      %016lx\n", pte_val(l1));
+}
+#endif
+
+static void set_page_prot(void *addr, pgprot_t prot)
+{
+	unsigned long pfn = __pa(addr) >> PAGE_SHIFT;
+	pte_t pte = pfn_pte(pfn, prot);
+
+	xen_raw_printk("addr=%p pfn=%lx mfn=%lx prot=%016llx pte=%016llx\n",
+		       addr, pfn, get_phys_to_machine(pfn),
+		       pgprot_val(prot), pte.pte);
+
+	if (HYPERVISOR_update_va_mapping((unsigned long)addr, pte, 0))
+		BUG();
+}
+
+static __init void xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn)
+{
+	unsigned pmdidx, pteidx;
+	unsigned ident_pte;
+	unsigned long pfn;
+
+	ident_pte = 0;
+	pfn = 0;
+	for(pmdidx = 0; pmdidx < PTRS_PER_PMD && pfn < max_pfn; pmdidx++) {
+		pte_t *pte_page;
+
+		/* Reuse or allocate a page of ptes */
+		if (pmd_present(pmd[pmdidx]))
+			pte_page = m2v(pmd[pmdidx].pmd);
+		else {
+			/* Check for free pte pages */
+			if (ident_pte == ARRAY_SIZE(level1_ident_pgt))
+				break;
+
+			pte_page = &level1_ident_pgt[ident_pte];
+			ident_pte += PTRS_PER_PTE;
+
+			pmd[pmdidx] = __pmd(__pa(pte_page) | _PAGE_TABLE);
+		}
+
+		/* Install mappings */
+		for(pteidx = 0; pteidx < PTRS_PER_PTE; pteidx++, pfn++) {
+			pte_t pte;
+
+			if (pfn > max_pfn_mapped)
+				max_pfn_mapped = pfn;
+
+			if (!pte_none(pte_page[pteidx]))
+				continue;
+
+			pte = pfn_pte(pfn, PAGE_KERNEL_EXEC);
+			pte_page[pteidx] = pte;
+		}
+	}
+
+	for(pteidx = 0; pteidx < ident_pte; pteidx += PTRS_PER_PTE)
+		set_page_prot(&level1_ident_pgt[pteidx], PAGE_KERNEL_RO);
+
+	set_page_prot(pmd, PAGE_KERNEL_RO);
+}
+
+#ifdef CONFIG_X86_64
+static void convert_pfn_mfn(void *v)
+{
+	pte_t *pte = v;
+	int i;
+
+	/* All levels are converted the same way, so just treat them
+	   as ptes. */
+	for(i = 0; i < PTRS_PER_PTE; i++)
+		pte[i] = xen_make_pte(pte[i].pte);
+}
+
+/*
+ * Set up the inital kernel pagetable.
+ *
+ * We can construct this by grafting the Xen provided pagetable into
+ * head_64.S's preconstructed pagetables.  We copy the Xen L2's into
+ * level2_ident_pgt, level2_kernel_pgt and level2_fixmap_pgt.  This
+ * means that only the kernel has a physical mapping to start with -
+ * but that's enough to get __va working.  We need to fill in the rest
+ * of the physical mapping once some sort of allocator has been set
+ * up.
+ */
+static __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
+{
+	pud_t *l3;
+	pmd_t *l2;
+
+	/* Zap identity mapping */
+	init_level4_pgt[0] = __pgd(0);
+
+	/* Pre-constructed entries are in pfn, so convert to mfn */
+	convert_pfn_mfn(init_level4_pgt);
+	convert_pfn_mfn(level3_ident_pgt);
+	convert_pfn_mfn(level3_kernel_pgt);
+
+	l3 = m2v(pgd[pgd_index(__START_KERNEL_map)].pgd);
+	l2 = m2v(l3[pud_index(__START_KERNEL_map)].pud);
+
+	memcpy(level2_ident_pgt, l2, sizeof(pmd_t) * PTRS_PER_PMD);
+	memcpy(level2_kernel_pgt, l2, sizeof(pmd_t) * PTRS_PER_PMD);
+
+	l3 = m2v(pgd[pgd_index(__START_KERNEL_map + PMD_SIZE)].pgd);
+	l2 = m2v(l3[pud_index(__START_KERNEL_map + PMD_SIZE)].pud);
+	memcpy(level2_fixmap_pgt, l2, sizeof(pmd_t) * PTRS_PER_PMD);
+
+	/* Set up identity map */
+	xen_map_identity_early(level2_ident_pgt, max_pfn);
+
+	/* Make pagetable pieces RO */
+	set_page_prot(init_level4_pgt, PAGE_KERNEL_RO);
+	set_page_prot(level3_ident_pgt, PAGE_KERNEL_RO);
+	set_page_prot(level3_kernel_pgt, PAGE_KERNEL_RO);
+	set_page_prot(level3_user_vsyscall, PAGE_KERNEL_RO);
+	set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO);
+	set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO);
+
+	/* Pin down new L4 */
+	pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE,
+			  PFN_DOWN(__pa_symbol(init_level4_pgt)));
+
+	/* Unpin Xen-provided one */
+	pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd)));
+
+	/* Switch over */
+	pgd = init_level4_pgt;
+
+	/*
+	 * At this stage there can be no user pgd, and no page
+	 * structure to attach it to, so make sure we just set kernel
+	 * pgd.
+	 */
+	xen_mc_batch();
+	__xen_write_cr3(true, __pa(pgd));
+	xen_mc_issue(PARAVIRT_LAZY_CPU);
+
+	reserve_early(__pa(xen_start_info->pt_base),
+		      __pa(xen_start_info->pt_base +
+			   xen_start_info->nr_pt_frames * PAGE_SIZE),
+		      "XEN PAGETABLES");
+
+	return pgd;
+}
+#else	/* !CONFIG_X86_64 */
+static pmd_t level2_kernel_pgt[PTRS_PER_PMD] __page_aligned_bss;
+
+static __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
+{
+	pmd_t *kernel_pmd;
+
+	init_pg_tables_start = __pa(pgd);
+	init_pg_tables_end = __pa(pgd) + xen_start_info->nr_pt_frames*PAGE_SIZE;
+	max_pfn_mapped = PFN_DOWN(init_pg_tables_end + 512*1024);
+
+	kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd);
+	memcpy(level2_kernel_pgt, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD);
+
+	xen_map_identity_early(level2_kernel_pgt, max_pfn);
+
+	memcpy(swapper_pg_dir, pgd, sizeof(pgd_t) * PTRS_PER_PGD);
+	set_pgd(&swapper_pg_dir[KERNEL_PGD_BOUNDARY],
+			__pgd(__pa(level2_kernel_pgt) | _PAGE_PRESENT));
+
+	set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO);
+	set_page_prot(swapper_pg_dir, PAGE_KERNEL_RO);
+	set_page_prot(empty_zero_page, PAGE_KERNEL_RO);
+
+	pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd)));
+
+	xen_write_cr3(__pa(swapper_pg_dir));
+
+	pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(swapper_pg_dir)));
+
+	return swapper_pg_dir;
+}
+#endif	/* CONFIG_X86_64 */
+
 /* First C function to be called on Xen boot */
 asmlinkage void __init xen_start_kernel(void)
 {
@@ -1301,53 +1684,56 @@
 
 	machine_ops = xen_machine_ops;
 
-#ifdef CONFIG_SMP
-	smp_ops = xen_smp_ops;
+#ifdef CONFIG_X86_64
+	/* Disable until direct per-cpu data access. */
+	have_vcpu_info_placement = 0;
+	x86_64_init_pda();
 #endif
 
+	xen_smp_init();
+
 	/* Get mfn list */
 	if (!xen_feature(XENFEAT_auto_translated_physmap))
 		xen_build_dynamic_phys_to_machine();
 
 	pgd = (pgd_t *)xen_start_info->pt_base;
 
-	init_pg_tables_start = __pa(pgd);
-	init_pg_tables_end = __pa(pgd) + xen_start_info->nr_pt_frames*PAGE_SIZE;
-	max_pfn_mapped = (init_pg_tables_end + 512*1024) >> PAGE_SHIFT;
-
-	init_mm.pgd = pgd; /* use the Xen pagetables to start */
-
-	/* keep using Xen gdt for now; no urgent need to change it */
-
-	x86_write_percpu(xen_cr3, __pa(pgd));
-	x86_write_percpu(xen_current_cr3, __pa(pgd));
-
-	/* Don't do the full vcpu_info placement stuff until we have a
-	   possible map and a non-dummy shared_info. */
-	per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];
-
-	pv_info.kernel_rpl = 1;
-	if (xen_feature(XENFEAT_supervisor_mode_kernel))
-		pv_info.kernel_rpl = 0;
-
 	/* Prevent unwanted bits from being set in PTEs. */
 	__supported_pte_mask &= ~_PAGE_GLOBAL;
 	if (!is_initial_xendomain())
 		__supported_pte_mask &= ~(_PAGE_PWT | _PAGE_PCD);
 
+	/* Don't do the full vcpu_info placement stuff until we have a
+	   possible map and a non-dummy shared_info. */
+	per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];
+
+	xen_raw_console_write("mapping kernel into physical memory\n");
+	pgd = xen_setup_kernel_pagetable(pgd, xen_start_info->nr_pages);
+
+	init_mm.pgd = pgd;
+
+	/* keep using Xen gdt for now; no urgent need to change it */
+
+	pv_info.kernel_rpl = 1;
+	if (xen_feature(XENFEAT_supervisor_mode_kernel))
+		pv_info.kernel_rpl = 0;
+
 	/* set the limit of our address space */
 	xen_reserve_top();
 
+#ifdef CONFIG_X86_32
 	/* set up basic CPUID stuff */
 	cpu_detect(&new_cpu_data);
 	new_cpu_data.hard_math = 1;
 	new_cpu_data.x86_capability[0] = cpuid_edx(1);
+#endif
 
 	/* Poke various useful things into boot_params */
 	boot_params.hdr.type_of_loader = (9 << 4) | 0;
 	boot_params.hdr.ramdisk_image = xen_start_info->mod_start
 		? __pa(xen_start_info->mod_start) : 0;
 	boot_params.hdr.ramdisk_size = xen_start_info->mod_len;
+	boot_params.hdr.cmd_line_ptr = __pa(xen_start_info->cmd_line);
 
 	if (!is_initial_xendomain()) {
 		add_preferred_console("xenboot", 0, NULL);
@@ -1355,6 +1741,21 @@
 		add_preferred_console("hvc", 0, NULL);
 	}
 
+	xen_raw_console_write("about to get started...\n");
+
+#if 0
+	xen_raw_printk("&boot_params=%p __pa(&boot_params)=%lx __va(__pa(&boot_params))=%lx\n",
+		       &boot_params, __pa_symbol(&boot_params),
+		       __va(__pa_symbol(&boot_params)));
+
+	walk(pgd, &boot_params);
+	walk(pgd, __va(__pa(&boot_params)));
+#endif
+
 	/* Start the world */
+#ifdef CONFIG_X86_32
 	i386_start_kernel();
+#else
+	x86_64_start_reservations((char *)__pa_symbol(&boot_params));
+#endif
 }
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index ff0aa74..aa37469 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -44,8 +44,10 @@
 
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
+#include <asm/fixmap.h>
 #include <asm/mmu_context.h>
 #include <asm/paravirt.h>
+#include <asm/linkage.h>
 
 #include <asm/xen/hypercall.h>
 #include <asm/xen/hypervisor.h>
@@ -56,26 +58,29 @@
 #include "multicalls.h"
 #include "mmu.h"
 
+/*
+ * Just beyond the highest usermode address.  STACK_TOP_MAX has a
+ * redzone above it, so round it up to a PGD boundary.
+ */
+#define USER_LIMIT	((STACK_TOP_MAX + PGDIR_SIZE - 1) & PGDIR_MASK)
+
+
 #define P2M_ENTRIES_PER_PAGE	(PAGE_SIZE / sizeof(unsigned long))
 #define TOP_ENTRIES		(MAX_DOMAIN_PAGES / P2M_ENTRIES_PER_PAGE)
 
 /* Placeholder for holes in the address space */
-static unsigned long p2m_missing[P2M_ENTRIES_PER_PAGE]
-	__attribute__((section(".data.page_aligned"))) =
+static unsigned long p2m_missing[P2M_ENTRIES_PER_PAGE] __page_aligned_data =
 		{ [ 0 ... P2M_ENTRIES_PER_PAGE-1 ] = ~0UL };
 
  /* Array of pointers to pages containing p2m entries */
-static unsigned long *p2m_top[TOP_ENTRIES]
-	__attribute__((section(".data.page_aligned"))) =
+static unsigned long *p2m_top[TOP_ENTRIES] __page_aligned_data =
 		{ [ 0 ... TOP_ENTRIES - 1] = &p2m_missing[0] };
 
 /* Arrays of p2m arrays expressed in mfns used for save/restore */
-static unsigned long p2m_top_mfn[TOP_ENTRIES]
-	__attribute__((section(".bss.page_aligned")));
+static unsigned long p2m_top_mfn[TOP_ENTRIES] __page_aligned_bss;
 
-static unsigned long p2m_top_mfn_list[
-			PAGE_ALIGN(TOP_ENTRIES / P2M_ENTRIES_PER_PAGE)]
-	__attribute__((section(".bss.page_aligned")));
+static unsigned long p2m_top_mfn_list[TOP_ENTRIES / P2M_ENTRIES_PER_PAGE]
+	__page_aligned_bss;
 
 static inline unsigned p2m_top_index(unsigned long pfn)
 {
@@ -181,15 +186,16 @@
 	p2m_top[topidx][idx] = mfn;
 }
 
-xmaddr_t arbitrary_virt_to_machine(unsigned long address)
+xmaddr_t arbitrary_virt_to_machine(void *vaddr)
 {
+	unsigned long address = (unsigned long)vaddr;
 	unsigned int level;
 	pte_t *pte = lookup_address(address, &level);
 	unsigned offset = address & ~PAGE_MASK;
 
 	BUG_ON(pte == NULL);
 
-	return XMADDR((pte_mfn(*pte) << PAGE_SHIFT) + offset);
+	return XMADDR(((phys_addr_t)pte_mfn(*pte) << PAGE_SHIFT) + offset);
 }
 
 void make_lowmem_page_readonly(void *vaddr)
@@ -256,7 +262,8 @@
 
 	xen_mc_batch();
 
-	u.ptr = virt_to_machine(ptr).maddr;
+	/* ptr may be ioremapped for 64-bit pagetable setup */
+	u.ptr = arbitrary_virt_to_machine(ptr).maddr;
 	u.val = pmd_val_ma(val);
 	extend_mmu_update(&u);
 
@@ -283,35 +290,7 @@
  */
 void set_pte_mfn(unsigned long vaddr, unsigned long mfn, pgprot_t flags)
 {
-	pgd_t *pgd;
-	pud_t *pud;
-	pmd_t *pmd;
-	pte_t *pte;
-
-	pgd = swapper_pg_dir + pgd_index(vaddr);
-	if (pgd_none(*pgd)) {
-		BUG();
-		return;
-	}
-	pud = pud_offset(pgd, vaddr);
-	if (pud_none(*pud)) {
-		BUG();
-		return;
-	}
-	pmd = pmd_offset(pud, vaddr);
-	if (pmd_none(*pmd)) {
-		BUG();
-		return;
-	}
-	pte = pte_offset_kernel(pmd, vaddr);
-	/* <mfn,flags> stored as-is, to permit clearing entries */
-	xen_set_pte(pte, mfn_pte(mfn, flags));
-
-	/*
-	 * It's enough to flush this one mapping.
-	 * (PGE mappings get flushed as well)
-	 */
-	__flush_tlb_one(vaddr);
+	set_pte_vaddr(vaddr, mfn_pte(mfn, flags));
 }
 
 void xen_set_pte_at(struct mm_struct *mm, unsigned long addr,
@@ -364,8 +343,8 @@
 static pteval_t pte_mfn_to_pfn(pteval_t val)
 {
 	if (val & _PAGE_PRESENT) {
-		unsigned long mfn = (val & PTE_MASK) >> PAGE_SHIFT;
-		pteval_t flags = val & ~PTE_MASK;
+		unsigned long mfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT;
+		pteval_t flags = val & PTE_FLAGS_MASK;
 		val = ((pteval_t)mfn_to_pfn(mfn) << PAGE_SHIFT) | flags;
 	}
 
@@ -375,8 +354,8 @@
 static pteval_t pte_pfn_to_mfn(pteval_t val)
 {
 	if (val & _PAGE_PRESENT) {
-		unsigned long pfn = (val & PTE_MASK) >> PAGE_SHIFT;
-		pteval_t flags = val & ~PTE_MASK;
+		unsigned long pfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT;
+		pteval_t flags = val & PTE_FLAGS_MASK;
 		val = ((pteval_t)pfn_to_mfn(pfn) << PAGE_SHIFT) | flags;
 	}
 
@@ -418,7 +397,8 @@
 
 	xen_mc_batch();
 
-	u.ptr = virt_to_machine(ptr).maddr;
+	/* ptr may be ioremapped for 64-bit pagetable setup */
+	u.ptr = arbitrary_virt_to_machine(ptr).maddr;
 	u.val = pud_val_ma(val);
 	extend_mmu_update(&u);
 
@@ -441,14 +421,19 @@
 
 void xen_set_pte(pte_t *ptep, pte_t pte)
 {
+#ifdef CONFIG_X86_PAE
 	ptep->pte_high = pte.pte_high;
 	smp_wmb();
 	ptep->pte_low = pte.pte_low;
+#else
+	*ptep = pte;
+#endif
 }
 
+#ifdef CONFIG_X86_PAE
 void xen_set_pte_atomic(pte_t *ptep, pte_t pte)
 {
-	set_64bit((u64 *)ptep, pte_val_ma(pte));
+	set_64bit((u64 *)ptep, native_pte_val(pte));
 }
 
 void xen_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
@@ -462,6 +447,7 @@
 {
 	set_pmd(pmdp, __pmd(0));
 }
+#endif	/* CONFIG_X86_PAE */
 
 pmd_t xen_make_pmd(pmdval_t pmd)
 {
@@ -469,78 +455,189 @@
 	return native_make_pmd(pmd);
 }
 
+#if PAGETABLE_LEVELS == 4
+pudval_t xen_pud_val(pud_t pud)
+{
+	return pte_mfn_to_pfn(pud.pud);
+}
+
+pud_t xen_make_pud(pudval_t pud)
+{
+	pud = pte_pfn_to_mfn(pud);
+
+	return native_make_pud(pud);
+}
+
+pgd_t *xen_get_user_pgd(pgd_t *pgd)
+{
+	pgd_t *pgd_page = (pgd_t *)(((unsigned long)pgd) & PAGE_MASK);
+	unsigned offset = pgd - pgd_page;
+	pgd_t *user_ptr = NULL;
+
+	if (offset < pgd_index(USER_LIMIT)) {
+		struct page *page = virt_to_page(pgd_page);
+		user_ptr = (pgd_t *)page->private;
+		if (user_ptr)
+			user_ptr += offset;
+	}
+
+	return user_ptr;
+}
+
+static void __xen_set_pgd_hyper(pgd_t *ptr, pgd_t val)
+{
+	struct mmu_update u;
+
+	u.ptr = virt_to_machine(ptr).maddr;
+	u.val = pgd_val_ma(val);
+	extend_mmu_update(&u);
+}
+
 /*
-  (Yet another) pagetable walker.  This one is intended for pinning a
-  pagetable.  This means that it walks a pagetable and calls the
-  callback function on each page it finds making up the page table,
-  at every level.  It walks the entire pagetable, but it only bothers
-  pinning pte pages which are below pte_limit.  In the normal case
-  this will be TASK_SIZE, but at boot we need to pin up to
-  FIXADDR_TOP.  But the important bit is that we don't pin beyond
-  there, because then we start getting into Xen's ptes.
-*/
-static int pgd_walk(pgd_t *pgd_base, int (*func)(struct page *, enum pt_level),
+ * Raw hypercall-based set_pgd, intended for in early boot before
+ * there's a page structure.  This implies:
+ *  1. The only existing pagetable is the kernel's
+ *  2. It is always pinned
+ *  3. It has no user pagetable attached to it
+ */
+void __init xen_set_pgd_hyper(pgd_t *ptr, pgd_t val)
+{
+	preempt_disable();
+
+	xen_mc_batch();
+
+	__xen_set_pgd_hyper(ptr, val);
+
+	xen_mc_issue(PARAVIRT_LAZY_MMU);
+
+	preempt_enable();
+}
+
+void xen_set_pgd(pgd_t *ptr, pgd_t val)
+{
+	pgd_t *user_ptr = xen_get_user_pgd(ptr);
+
+	/* If page is not pinned, we can just update the entry
+	   directly */
+	if (!page_pinned(ptr)) {
+		*ptr = val;
+		if (user_ptr) {
+			WARN_ON(page_pinned(user_ptr));
+			*user_ptr = val;
+		}
+		return;
+	}
+
+	/* If it's pinned, then we can at least batch the kernel and
+	   user updates together. */
+	xen_mc_batch();
+
+	__xen_set_pgd_hyper(ptr, val);
+	if (user_ptr)
+		__xen_set_pgd_hyper(user_ptr, val);
+
+	xen_mc_issue(PARAVIRT_LAZY_MMU);
+}
+#endif	/* PAGETABLE_LEVELS == 4 */
+
+/*
+ * (Yet another) pagetable walker.  This one is intended for pinning a
+ * pagetable.  This means that it walks a pagetable and calls the
+ * callback function on each page it finds making up the page table,
+ * at every level.  It walks the entire pagetable, but it only bothers
+ * pinning pte pages which are below limit.  In the normal case this
+ * will be STACK_TOP_MAX, but at boot we need to pin up to
+ * FIXADDR_TOP.
+ *
+ * For 32-bit the important bit is that we don't pin beyond there,
+ * because then we start getting into Xen's ptes.
+ *
+ * For 64-bit, we must skip the Xen hole in the middle of the address
+ * space, just after the big x86-64 virtual hole.
+ */
+static int pgd_walk(pgd_t *pgd, int (*func)(struct page *, enum pt_level),
 		    unsigned long limit)
 {
-	pgd_t *pgd = pgd_base;
 	int flush = 0;
-	unsigned long addr = 0;
-	unsigned long pgd_next;
+	unsigned hole_low, hole_high;
+	unsigned pgdidx_limit, pudidx_limit, pmdidx_limit;
+	unsigned pgdidx, pudidx, pmdidx;
 
-	BUG_ON(limit > FIXADDR_TOP);
+	/* The limit is the last byte to be touched */
+	limit--;
+	BUG_ON(limit >= FIXADDR_TOP);
 
 	if (xen_feature(XENFEAT_auto_translated_physmap))
 		return 0;
 
-	for (; addr != FIXADDR_TOP; pgd++, addr = pgd_next) {
+	/*
+	 * 64-bit has a great big hole in the middle of the address
+	 * space, which contains the Xen mappings.  On 32-bit these
+	 * will end up making a zero-sized hole and so is a no-op.
+	 */
+	hole_low = pgd_index(USER_LIMIT);
+	hole_high = pgd_index(PAGE_OFFSET);
+
+	pgdidx_limit = pgd_index(limit);
+#if PTRS_PER_PUD > 1
+	pudidx_limit = pud_index(limit);
+#else
+	pudidx_limit = 0;
+#endif
+#if PTRS_PER_PMD > 1
+	pmdidx_limit = pmd_index(limit);
+#else
+	pmdidx_limit = 0;
+#endif
+
+	flush |= (*func)(virt_to_page(pgd), PT_PGD);
+
+	for (pgdidx = 0; pgdidx <= pgdidx_limit; pgdidx++) {
 		pud_t *pud;
-		unsigned long pud_limit, pud_next;
 
-		pgd_next = pud_limit = pgd_addr_end(addr, FIXADDR_TOP);
-
-		if (!pgd_val(*pgd))
+		if (pgdidx >= hole_low && pgdidx < hole_high)
 			continue;
 
-		pud = pud_offset(pgd, 0);
+		if (!pgd_val(pgd[pgdidx]))
+			continue;
+
+		pud = pud_offset(&pgd[pgdidx], 0);
 
 		if (PTRS_PER_PUD > 1) /* not folded */
 			flush |= (*func)(virt_to_page(pud), PT_PUD);
 
-		for (; addr != pud_limit; pud++, addr = pud_next) {
+		for (pudidx = 0; pudidx < PTRS_PER_PUD; pudidx++) {
 			pmd_t *pmd;
-			unsigned long pmd_limit;
 
-			pud_next = pud_addr_end(addr, pud_limit);
+			if (pgdidx == pgdidx_limit &&
+			    pudidx > pudidx_limit)
+				goto out;
 
-			if (pud_next < limit)
-				pmd_limit = pud_next;
-			else
-				pmd_limit = limit;
-
-			if (pud_none(*pud))
+			if (pud_none(pud[pudidx]))
 				continue;
 
-			pmd = pmd_offset(pud, 0);
+			pmd = pmd_offset(&pud[pudidx], 0);
 
 			if (PTRS_PER_PMD > 1) /* not folded */
 				flush |= (*func)(virt_to_page(pmd), PT_PMD);
 
-			for (; addr != pmd_limit; pmd++) {
-				addr += (PAGE_SIZE * PTRS_PER_PTE);
-				if ((pmd_limit-1) < (addr-1)) {
-					addr = pmd_limit;
-					break;
-				}
+			for (pmdidx = 0; pmdidx < PTRS_PER_PMD; pmdidx++) {
+				struct page *pte;
 
-				if (pmd_none(*pmd))
+				if (pgdidx == pgdidx_limit &&
+				    pudidx == pudidx_limit &&
+				    pmdidx > pmdidx_limit)
+					goto out;
+
+				if (pmd_none(pmd[pmdidx]))
 					continue;
 
-				flush |= (*func)(pmd_page(*pmd), PT_PTE);
+				pte = pmd_page(pmd[pmdidx]);
+				flush |= (*func)(pte, PT_PTE);
 			}
 		}
 	}
-
-	flush |= (*func)(virt_to_page(pgd_base), PT_PGD);
+out:
 
 	return flush;
 }
@@ -622,14 +719,31 @@
 {
 	xen_mc_batch();
 
-	if (pgd_walk(pgd, pin_page, TASK_SIZE)) {
+	if (pgd_walk(pgd, pin_page, USER_LIMIT)) {
 		/* re-enable interrupts for kmap_flush_unused */
 		xen_mc_issue(0);
 		kmap_flush_unused();
 		xen_mc_batch();
 	}
 
+#ifdef CONFIG_X86_64
+	{
+		pgd_t *user_pgd = xen_get_user_pgd(pgd);
+
+		xen_do_pin(MMUEXT_PIN_L4_TABLE, PFN_DOWN(__pa(pgd)));
+
+		if (user_pgd) {
+			pin_page(virt_to_page(user_pgd), PT_PGD);
+			xen_do_pin(MMUEXT_PIN_L4_TABLE, PFN_DOWN(__pa(user_pgd)));
+		}
+	}
+#else /* CONFIG_X86_32 */
+#ifdef CONFIG_X86_PAE
+	/* Need to make sure unshared kernel PMD is pinnable */
+	pin_page(virt_to_page(pgd_page(pgd[pgd_index(TASK_SIZE)])), PT_PMD);
+#endif
 	xen_do_pin(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(pgd)));
+#endif /* CONFIG_X86_64 */
 	xen_mc_issue(0);
 }
 
@@ -656,9 +770,11 @@
 	spin_unlock_irqrestore(&pgd_lock, flags);
 }
 
-/* The init_mm pagetable is really pinned as soon as its created, but
-   that's before we have page structures to store the bits.  So do all
-   the book-keeping now. */
+/*
+ * The init_mm pagetable is really pinned as soon as its created, but
+ * that's before we have page structures to store the bits.  So do all
+ * the book-keeping now.
+ */
 static __init int mark_pinned(struct page *page, enum pt_level level)
 {
 	SetPagePinned(page);
@@ -708,7 +824,23 @@
 
 	xen_do_pin(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd)));
 
-	pgd_walk(pgd, unpin_page, TASK_SIZE);
+#ifdef CONFIG_X86_64
+	{
+		pgd_t *user_pgd = xen_get_user_pgd(pgd);
+
+		if (user_pgd) {
+			xen_do_pin(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(user_pgd)));
+			unpin_page(virt_to_page(user_pgd), PT_PGD);
+		}
+	}
+#endif
+
+#ifdef CONFIG_X86_PAE
+	/* Need to make sure unshared kernel PMD is unpinned */
+	pin_page(virt_to_page(pgd_page(pgd[pgd_index(TASK_SIZE)])), PT_PMD);
+#endif
+
+	pgd_walk(pgd, unpin_page, USER_LIMIT);
 
 	xen_mc_issue(0);
 }
@@ -727,7 +859,6 @@
 	list_for_each_entry(page, &pgd_list, lru) {
 		if (PageSavePinned(page)) {
 			BUG_ON(!PagePinned(page));
-			printk("unpinning pinned %p\n", page_address(page));
 			xen_pgd_unpin((pgd_t *)page_address(page));
 			ClearPageSavePinned(page);
 		}
@@ -757,8 +888,15 @@
 static void drop_other_mm_ref(void *info)
 {
 	struct mm_struct *mm = info;
+	struct mm_struct *active_mm;
 
-	if (__get_cpu_var(cpu_tlbstate).active_mm == mm)
+#ifdef CONFIG_X86_64
+	active_mm = read_pda(active_mm);
+#else
+	active_mm = __get_cpu_var(cpu_tlbstate).active_mm;
+#endif
+
+	if (active_mm == mm)
 		leave_mm(smp_processor_id());
 
 	/* If this cpu still has a stale cr3 reference, then make sure
diff --git a/arch/x86/xen/mmu.h b/arch/x86/xen/mmu.h
index 297bf9f..0f59bd0 100644
--- a/arch/x86/xen/mmu.h
+++ b/arch/x86/xen/mmu.h
@@ -10,18 +10,6 @@
 	PT_PTE
 };
 
-/*
- * Page-directory addresses above 4GB do not fit into architectural %cr3.
- * When accessing %cr3, or equivalent field in vcpu_guest_context, guests
- * must use the following accessor macros to pack/unpack valid MFNs.
- *
- * Note that Xen is using the fact that the pagetable base is always
- * page-aligned, and putting the 12 MSB of the address into the 12 LSB
- * of cr3.
- */
-#define xen_pfn_to_cr3(pfn) (((unsigned)(pfn) << 12) | ((unsigned)(pfn) >> 20))
-#define xen_cr3_to_pfn(cr3) (((unsigned)(cr3) >> 12) | ((unsigned)(cr3) << 20))
-
 
 void set_pte_mfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags);
 
@@ -44,13 +32,26 @@
 void xen_set_pte(pte_t *ptep, pte_t pteval);
 void xen_set_pte_at(struct mm_struct *mm, unsigned long addr,
 		    pte_t *ptep, pte_t pteval);
+
+#ifdef CONFIG_X86_PAE
 void xen_set_pte_atomic(pte_t *ptep, pte_t pte);
+void xen_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
+void xen_pmd_clear(pmd_t *pmdp);
+#endif	/* CONFIG_X86_PAE */
+
 void xen_set_pmd(pmd_t *pmdp, pmd_t pmdval);
 void xen_set_pud(pud_t *ptr, pud_t val);
 void xen_set_pmd_hyper(pmd_t *pmdp, pmd_t pmdval);
 void xen_set_pud_hyper(pud_t *ptr, pud_t val);
-void xen_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
-void xen_pmd_clear(pmd_t *pmdp);
+
+#if PAGETABLE_LEVELS == 4
+pudval_t xen_pud_val(pud_t pud);
+pud_t xen_make_pud(pudval_t pudval);
+void xen_set_pgd(pgd_t *pgdp, pgd_t pgd);
+void xen_set_pgd_hyper(pgd_t *pgdp, pgd_t pgd);
+#endif
+
+pgd_t *xen_get_user_pgd(pgd_t *pgd);
 
 pte_t xen_ptep_modify_prot_start(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
 void  xen_ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr,
diff --git a/arch/x86/xen/multicalls.c b/arch/x86/xen/multicalls.c
index 3c63c4da..9efd1c6 100644
--- a/arch/x86/xen/multicalls.c
+++ b/arch/x86/xen/multicalls.c
@@ -76,6 +76,7 @@
 		if (ret) {
 			printk(KERN_ERR "%d multicall(s) failed: cpu %d\n",
 			       ret, smp_processor_id());
+			dump_stack();
 			for (i = 0; i < b->mcidx; i++) {
 				printk("  call %2d/%d: op=%lu arg=[%lx] result=%ld\n",
 				       i+1, b->mcidx,
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index e0a3959..b6acc3a 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -83,30 +83,72 @@
 
 /*
  * Set the bit indicating "nosegneg" library variants should be used.
+ * We only need to bother in pure 32-bit mode; compat 32-bit processes
+ * can have un-truncated segments, so wrapping around is allowed.
  */
 static void __init fiddle_vdso(void)
 {
-	extern const char vdso32_default_start;
-	u32 *mask = VDSO32_SYMBOL(&vdso32_default_start, NOTE_MASK);
+#ifdef CONFIG_X86_32
+	u32 *mask;
+	mask = VDSO32_SYMBOL(&vdso32_int80_start, NOTE_MASK);
 	*mask |= 1 << VDSO_NOTE_NONEGSEG_BIT;
+	mask = VDSO32_SYMBOL(&vdso32_sysenter_start, NOTE_MASK);
+	*mask |= 1 << VDSO_NOTE_NONEGSEG_BIT;
+#endif
 }
 
-void xen_enable_sysenter(void)
+static __cpuinit int register_callback(unsigned type, const void *func)
 {
-	int cpu = smp_processor_id();
-	extern void xen_sysenter_target(void);
-	/* Mask events on entry, even though they get enabled immediately */
-	static struct callback_register sysenter = {
-		.type = CALLBACKTYPE_sysenter,
-		.address = { __KERNEL_CS, (unsigned long)xen_sysenter_target },
+	struct callback_register callback = {
+		.type = type,
+		.address = XEN_CALLBACK(__KERNEL_CS, func),
 		.flags = CALLBACKF_mask_events,
 	};
 
-	if (!boot_cpu_has(X86_FEATURE_SEP) ||
-	    HYPERVISOR_callback_op(CALLBACKOP_register, &sysenter) != 0) {
-		clear_cpu_cap(&cpu_data(cpu), X86_FEATURE_SEP);
-		clear_cpu_cap(&boot_cpu_data, X86_FEATURE_SEP);
+	return HYPERVISOR_callback_op(CALLBACKOP_register, &callback);
+}
+
+void __cpuinit xen_enable_sysenter(void)
+{
+	extern void xen_sysenter_target(void);
+	int ret;
+	unsigned sysenter_feature;
+
+#ifdef CONFIG_X86_32
+	sysenter_feature = X86_FEATURE_SEP;
+#else
+	sysenter_feature = X86_FEATURE_SYSENTER32;
+#endif
+
+	if (!boot_cpu_has(sysenter_feature))
+		return;
+
+	ret = register_callback(CALLBACKTYPE_sysenter, xen_sysenter_target);
+	if(ret != 0)
+		setup_clear_cpu_cap(sysenter_feature);
+}
+
+void __cpuinit xen_enable_syscall(void)
+{
+#ifdef CONFIG_X86_64
+	int ret;
+	extern void xen_syscall_target(void);
+	extern void xen_syscall32_target(void);
+
+	ret = register_callback(CALLBACKTYPE_syscall, xen_syscall_target);
+	if (ret != 0) {
+		printk(KERN_ERR "Failed to set syscall callback: %d\n", ret);
+		/* Pretty fatal; 64-bit userspace has no other
+		   mechanism for syscalls. */
 	}
+
+	if (boot_cpu_has(X86_FEATURE_SYSCALL32)) {
+		ret = register_callback(CALLBACKTYPE_syscall32,
+					xen_syscall32_target);
+		if (ret != 0)
+			setup_clear_cpu_cap(X86_FEATURE_SYSCALL32);
+	}
+#endif /* CONFIG_X86_64 */
 }
 
 void __init xen_arch_setup(void)
@@ -120,10 +162,12 @@
 	if (!xen_feature(XENFEAT_auto_translated_physmap))
 		HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_pae_extended_cr3);
 
-	HYPERVISOR_set_callbacks(__KERNEL_CS, (unsigned long)xen_hypervisor_callback,
-				 __KERNEL_CS, (unsigned long)xen_failsafe_callback);
+	if (register_callback(CALLBACKTYPE_event, xen_hypervisor_callback) ||
+	    register_callback(CALLBACKTYPE_failsafe, xen_failsafe_callback))
+		BUG();
 
 	xen_enable_sysenter();
+	xen_enable_syscall();
 
 	set_iopl.iopl = 1;
 	rc = HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl);
@@ -143,11 +187,6 @@
 
 	pm_idle = xen_idle;
 
-#ifdef CONFIG_SMP
-	/* fill cpus_possible with all available cpus */
-	xen_fill_possible_map();
-#endif
-
 	paravirt_disable_iospace();
 
 	fiddle_vdso();
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index 463adec..d8faf79 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -15,6 +15,7 @@
  * This does not handle HOTPLUG_CPU yet.
  */
 #include <linux/sched.h>
+#include <linux/kernel_stat.h>
 #include <linux/err.h>
 #include <linux/smp.h>
 
@@ -35,6 +36,8 @@
 #include "xen-ops.h"
 #include "mmu.h"
 
+static void __cpuinit xen_init_lock_cpu(int cpu);
+
 cpumask_t xen_cpu_initialized_map;
 
 static DEFINE_PER_CPU(int, resched_irq);
@@ -66,13 +69,22 @@
 	int cpu = smp_processor_id();
 
 	cpu_init();
-	xen_enable_sysenter();
-
 	preempt_disable();
-	per_cpu(cpu_state, cpu) = CPU_ONLINE;
+
+	xen_enable_sysenter();
+	xen_enable_syscall();
+
+	cpu = smp_processor_id();
+	smp_store_cpu_info(cpu);
+	cpu_data(cpu).x86_max_cores = 1;
+	set_cpu_sibling_map(cpu);
 
 	xen_setup_cpu_clockevents();
 
+	cpu_set(cpu, cpu_online_map);
+	x86_write_percpu(cpu_state, CPU_ONLINE);
+	wmb();
+
 	/* We can take interrupts now: we're officially "up". */
 	local_irq_enable();
 
@@ -141,56 +153,39 @@
 	return rc;
 }
 
-void __init xen_fill_possible_map(void)
+static void __init xen_fill_possible_map(void)
 {
 	int i, rc;
 
 	for (i = 0; i < NR_CPUS; i++) {
 		rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL);
-		if (rc >= 0)
+		if (rc >= 0) {
+			num_processors++;
 			cpu_set(i, cpu_possible_map);
+		}
 	}
 }
 
-void __init xen_smp_prepare_boot_cpu(void)
+static void __init xen_smp_prepare_boot_cpu(void)
 {
-	int cpu;
-
 	BUG_ON(smp_processor_id() != 0);
 	native_smp_prepare_boot_cpu();
 
 	/* We've switched to the "real" per-cpu gdt, so make sure the
 	   old memory can be recycled */
-	make_lowmem_page_readwrite(&per_cpu__gdt_page);
-
-	for_each_possible_cpu(cpu) {
-		cpus_clear(per_cpu(cpu_sibling_map, cpu));
-		/*
-		 * cpu_core_map lives in a per cpu area that is cleared
-		 * when the per cpu array is allocated.
-		 *
-		 * cpus_clear(per_cpu(cpu_core_map, cpu));
-		 */
-	}
+	make_lowmem_page_readwrite(&per_cpu_var(gdt_page));
 
 	xen_setup_vcpu_info_placement();
 }
 
-void __init xen_smp_prepare_cpus(unsigned int max_cpus)
+static void __init xen_smp_prepare_cpus(unsigned int max_cpus)
 {
 	unsigned cpu;
 
-	for_each_possible_cpu(cpu) {
-		cpus_clear(per_cpu(cpu_sibling_map, cpu));
-		/*
-		 * cpu_core_ map will be zeroed when the per
-		 * cpu area is allocated.
-		 *
-		 * cpus_clear(per_cpu(cpu_core_map, cpu));
-		 */
-	}
+	xen_init_lock_cpu(0);
 
 	smp_store_cpu_info(0);
+	cpu_data(0).x86_max_cores = 1;
 	set_cpu_sibling_map(0);
 
 	if (xen_smp_intr_init(0))
@@ -225,7 +220,7 @@
 cpu_initialize_context(unsigned int cpu, struct task_struct *idle)
 {
 	struct vcpu_guest_context *ctxt;
-	struct gdt_page *gdt = &per_cpu(gdt_page, cpu);
+	struct desc_struct *gdt;
 
 	if (cpu_test_and_set(cpu, xen_cpu_initialized_map))
 		return 0;
@@ -234,12 +229,15 @@
 	if (ctxt == NULL)
 		return -ENOMEM;
 
+	gdt = get_cpu_gdt_table(cpu);
+
 	ctxt->flags = VGCF_IN_KERNEL;
 	ctxt->user_regs.ds = __USER_DS;
 	ctxt->user_regs.es = __USER_DS;
-	ctxt->user_regs.fs = __KERNEL_PERCPU;
-	ctxt->user_regs.gs = 0;
 	ctxt->user_regs.ss = __KERNEL_DS;
+#ifdef CONFIG_X86_32
+	ctxt->user_regs.fs = __KERNEL_PERCPU;
+#endif
 	ctxt->user_regs.eip = (unsigned long)cpu_bringup_and_idle;
 	ctxt->user_regs.eflags = 0x1000; /* IOPL_RING1 */
 
@@ -249,11 +247,11 @@
 
 	ctxt->ldt_ents = 0;
 
-	BUG_ON((unsigned long)gdt->gdt & ~PAGE_MASK);
-	make_lowmem_page_readonly(gdt->gdt);
+	BUG_ON((unsigned long)gdt & ~PAGE_MASK);
+	make_lowmem_page_readonly(gdt);
 
-	ctxt->gdt_frames[0] = virt_to_mfn(gdt->gdt);
-	ctxt->gdt_ents      = ARRAY_SIZE(gdt->gdt);
+	ctxt->gdt_frames[0] = virt_to_mfn(gdt);
+	ctxt->gdt_ents      = GDT_ENTRIES;
 
 	ctxt->user_regs.cs = __KERNEL_CS;
 	ctxt->user_regs.esp = idle->thread.sp0 - sizeof(struct pt_regs);
@@ -261,9 +259,11 @@
 	ctxt->kernel_ss = __KERNEL_DS;
 	ctxt->kernel_sp = idle->thread.sp0;
 
+#ifdef CONFIG_X86_32
 	ctxt->event_callback_cs     = __KERNEL_CS;
-	ctxt->event_callback_eip    = (unsigned long)xen_hypervisor_callback;
 	ctxt->failsafe_callback_cs  = __KERNEL_CS;
+#endif
+	ctxt->event_callback_eip    = (unsigned long)xen_hypervisor_callback;
 	ctxt->failsafe_callback_eip = (unsigned long)xen_failsafe_callback;
 
 	per_cpu(xen_cr3, cpu) = __pa(swapper_pg_dir);
@@ -276,7 +276,7 @@
 	return 0;
 }
 
-int __cpuinit xen_cpu_up(unsigned int cpu)
+static int __cpuinit xen_cpu_up(unsigned int cpu)
 {
 	struct task_struct *idle = idle_task(cpu);
 	int rc;
@@ -287,10 +287,28 @@
 		return rc;
 #endif
 
+#ifdef CONFIG_X86_64
+	/* Allocate node local memory for AP pdas */
+	WARN_ON(cpu == 0);
+	if (cpu > 0) {
+		rc = get_local_pda(cpu);
+		if (rc)
+			return rc;
+	}
+#endif
+
+#ifdef CONFIG_X86_32
 	init_gdt(cpu);
 	per_cpu(current_task, cpu) = idle;
 	irq_ctx_init(cpu);
+#else
+	cpu_pda(cpu)->pcurrent = idle;
+	clear_tsk_thread_flag(idle, TIF_FORK);
+#endif
 	xen_setup_timer(cpu);
+	xen_init_lock_cpu(cpu);
+
+	per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
 
 	/* make sure interrupts start blocked */
 	per_cpu(xen_vcpu, cpu)->evtchn_upcall_mask = 1;
@@ -306,20 +324,18 @@
 	if (rc)
 		return rc;
 
-	smp_store_cpu_info(cpu);
-	set_cpu_sibling_map(cpu);
-	/* This must be done before setting cpu_online_map */
-	wmb();
-
-	cpu_set(cpu, cpu_online_map);
-
 	rc = HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL);
 	BUG_ON(rc);
 
+	while(per_cpu(cpu_state, cpu) != CPU_ONLINE) {
+		HYPERVISOR_sched_op(SCHEDOP_yield, 0);
+		barrier();
+	}
+
 	return 0;
 }
 
-void xen_smp_cpus_done(unsigned int max_cpus)
+static void xen_smp_cpus_done(unsigned int max_cpus)
 {
 }
 
@@ -335,12 +351,12 @@
 	BUG();
 }
 
-void xen_smp_send_stop(void)
+static void xen_smp_send_stop(void)
 {
 	smp_call_function(stop_self, NULL, 0);
 }
 
-void xen_smp_send_reschedule(int cpu)
+static void xen_smp_send_reschedule(int cpu)
 {
 	xen_send_IPI_one(cpu, XEN_RESCHEDULE_VECTOR);
 }
@@ -355,7 +371,7 @@
 		xen_send_IPI_one(cpu, vector);
 }
 
-void xen_smp_send_call_function_ipi(cpumask_t mask)
+static void xen_smp_send_call_function_ipi(cpumask_t mask)
 {
 	int cpu;
 
@@ -370,7 +386,7 @@
 	}
 }
 
-void xen_smp_send_call_function_single_ipi(int cpu)
+static void xen_smp_send_call_function_single_ipi(int cpu)
 {
 	xen_send_IPI_mask(cpumask_of_cpu(cpu), XEN_CALL_FUNCTION_SINGLE_VECTOR);
 }
@@ -379,7 +395,11 @@
 {
 	irq_enter();
 	generic_smp_call_function_interrupt();
+#ifdef CONFIG_X86_32
 	__get_cpu_var(irq_stat).irq_call_count++;
+#else
+	add_pda(irq_call_count, 1);
+#endif
 	irq_exit();
 
 	return IRQ_HANDLED;
@@ -389,8 +409,196 @@
 {
 	irq_enter();
 	generic_smp_call_function_single_interrupt();
+#ifdef CONFIG_X86_32
 	__get_cpu_var(irq_stat).irq_call_count++;
+#else
+	add_pda(irq_call_count, 1);
+#endif
 	irq_exit();
 
 	return IRQ_HANDLED;
 }
+
+struct xen_spinlock {
+	unsigned char lock;		/* 0 -> free; 1 -> locked */
+	unsigned short spinners;	/* count of waiting cpus */
+};
+
+static int xen_spin_is_locked(struct raw_spinlock *lock)
+{
+	struct xen_spinlock *xl = (struct xen_spinlock *)lock;
+
+	return xl->lock != 0;
+}
+
+static int xen_spin_is_contended(struct raw_spinlock *lock)
+{
+	struct xen_spinlock *xl = (struct xen_spinlock *)lock;
+
+	/* Not strictly true; this is only the count of contended
+	   lock-takers entering the slow path. */
+	return xl->spinners != 0;
+}
+
+static int xen_spin_trylock(struct raw_spinlock *lock)
+{
+	struct xen_spinlock *xl = (struct xen_spinlock *)lock;
+	u8 old = 1;
+
+	asm("xchgb %b0,%1"
+	    : "+q" (old), "+m" (xl->lock) : : "memory");
+
+	return old == 0;
+}
+
+static DEFINE_PER_CPU(int, lock_kicker_irq) = -1;
+static DEFINE_PER_CPU(struct xen_spinlock *, lock_spinners);
+
+static inline void spinning_lock(struct xen_spinlock *xl)
+{
+	__get_cpu_var(lock_spinners) = xl;
+	wmb();			/* set lock of interest before count */
+	asm(LOCK_PREFIX " incw %0"
+	    : "+m" (xl->spinners) : : "memory");
+}
+
+static inline void unspinning_lock(struct xen_spinlock *xl)
+{
+	asm(LOCK_PREFIX " decw %0"
+	    : "+m" (xl->spinners) : : "memory");
+	wmb();			/* decrement count before clearing lock */
+	__get_cpu_var(lock_spinners) = NULL;
+}
+
+static noinline int xen_spin_lock_slow(struct raw_spinlock *lock)
+{
+	struct xen_spinlock *xl = (struct xen_spinlock *)lock;
+	int irq = __get_cpu_var(lock_kicker_irq);
+	int ret;
+
+	/* If kicker interrupts not initialized yet, just spin */
+	if (irq == -1)
+		return 0;
+
+	/* announce we're spinning */
+	spinning_lock(xl);
+
+	/* clear pending */
+	xen_clear_irq_pending(irq);
+
+	/* check again make sure it didn't become free while
+	   we weren't looking  */
+	ret = xen_spin_trylock(lock);
+	if (ret)
+		goto out;
+
+	/* block until irq becomes pending */
+	xen_poll_irq(irq);
+	kstat_this_cpu.irqs[irq]++;
+
+out:
+	unspinning_lock(xl);
+	return ret;
+}
+
+static void xen_spin_lock(struct raw_spinlock *lock)
+{
+	struct xen_spinlock *xl = (struct xen_spinlock *)lock;
+	int timeout;
+	u8 oldval;
+
+	do {
+		timeout = 1 << 10;
+
+		asm("1: xchgb %1,%0\n"
+		    "   testb %1,%1\n"
+		    "   jz 3f\n"
+		    "2: rep;nop\n"
+		    "   cmpb $0,%0\n"
+		    "   je 1b\n"
+		    "   dec %2\n"
+		    "   jnz 2b\n"
+		    "3:\n"
+		    : "+m" (xl->lock), "=q" (oldval), "+r" (timeout)
+		    : "1" (1)
+		    : "memory");
+
+	} while (unlikely(oldval != 0 && !xen_spin_lock_slow(lock)));
+}
+
+static noinline void xen_spin_unlock_slow(struct xen_spinlock *xl)
+{
+	int cpu;
+
+	for_each_online_cpu(cpu) {
+		/* XXX should mix up next cpu selection */
+		if (per_cpu(lock_spinners, cpu) == xl) {
+			xen_send_IPI_one(cpu, XEN_SPIN_UNLOCK_VECTOR);
+			break;
+		}
+	}
+}
+
+static void xen_spin_unlock(struct raw_spinlock *lock)
+{
+	struct xen_spinlock *xl = (struct xen_spinlock *)lock;
+
+	smp_wmb();		/* make sure no writes get moved after unlock */
+	xl->lock = 0;		/* release lock */
+
+	/* make sure unlock happens before kick */
+	barrier();
+
+	if (unlikely(xl->spinners))
+		xen_spin_unlock_slow(xl);
+}
+
+static __cpuinit void xen_init_lock_cpu(int cpu)
+{
+	int irq;
+	const char *name;
+
+	name = kasprintf(GFP_KERNEL, "spinlock%d", cpu);
+	irq = bind_ipi_to_irqhandler(XEN_SPIN_UNLOCK_VECTOR,
+				     cpu,
+				     xen_reschedule_interrupt,
+				     IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING,
+				     name,
+				     NULL);
+
+	if (irq >= 0) {
+		disable_irq(irq); /* make sure it's never delivered */
+		per_cpu(lock_kicker_irq, cpu) = irq;
+	}
+
+	printk("cpu %d spinlock event irq %d\n", cpu, irq);
+}
+
+static void __init xen_init_spinlocks(void)
+{
+	pv_lock_ops.spin_is_locked = xen_spin_is_locked;
+	pv_lock_ops.spin_is_contended = xen_spin_is_contended;
+	pv_lock_ops.spin_lock = xen_spin_lock;
+	pv_lock_ops.spin_trylock = xen_spin_trylock;
+	pv_lock_ops.spin_unlock = xen_spin_unlock;
+}
+
+static const struct smp_ops xen_smp_ops __initdata = {
+	.smp_prepare_boot_cpu = xen_smp_prepare_boot_cpu,
+	.smp_prepare_cpus = xen_smp_prepare_cpus,
+	.cpu_up = xen_cpu_up,
+	.smp_cpus_done = xen_smp_cpus_done,
+
+	.smp_send_stop = xen_smp_send_stop,
+	.smp_send_reschedule = xen_smp_send_reschedule,
+
+	.send_call_func_ipi = xen_smp_send_call_function_ipi,
+	.send_call_func_single_ipi = xen_smp_send_call_function_single_ipi,
+};
+
+void __init xen_smp_init(void)
+{
+	smp_ops = xen_smp_ops;
+	xen_fill_possible_map();
+	xen_init_spinlocks();
+}
diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c
index 251669a..2a234db 100644
--- a/arch/x86/xen/suspend.c
+++ b/arch/x86/xen/suspend.c
@@ -38,8 +38,11 @@
 		xen_cpu_initialized_map = cpu_online_map;
 #endif
 		xen_vcpu_restore();
-		xen_timer_resume();
 	}
 
 }
 
+void xen_arch_resume(void)
+{
+	/* nothing */
+}
diff --git a/arch/x86/xen/xen-asm.S b/arch/x86/xen/xen-asm_32.S
similarity index 100%
rename from arch/x86/xen/xen-asm.S
rename to arch/x86/xen/xen-asm_32.S
diff --git a/arch/x86/xen/xen-asm_64.S b/arch/x86/xen/xen-asm_64.S
new file mode 100644
index 0000000..4038cbf
--- /dev/null
+++ b/arch/x86/xen/xen-asm_64.S
@@ -0,0 +1,271 @@
+/*
+	Asm versions of Xen pv-ops, suitable for either direct use or inlining.
+	The inline versions are the same as the direct-use versions, with the
+	pre- and post-amble chopped off.
+
+	This code is encoded for size rather than absolute efficiency,
+	with a view to being able to inline as much as possible.
+
+	We only bother with direct forms (ie, vcpu in pda) of the operations
+	here; the indirect forms are better handled in C, since they're
+	generally too large to inline anyway.
+ */
+
+#include <linux/linkage.h>
+
+#include <asm/asm-offsets.h>
+#include <asm/processor-flags.h>
+#include <asm/errno.h>
+#include <asm/segment.h>
+
+#include <xen/interface/xen.h>
+
+#define RELOC(x, v)	.globl x##_reloc; x##_reloc=v
+#define ENDPATCH(x)	.globl x##_end; x##_end=.
+
+/* Pseudo-flag used for virtual NMI, which we don't implement yet */
+#define XEN_EFLAGS_NMI	0x80000000
+
+#if 0
+#include <asm/percpu.h>
+
+/*
+	Enable events.  This clears the event mask and tests the pending
+	event status with one and operation.  If there are pending
+	events, then enter the hypervisor to get them handled.
+ */
+ENTRY(xen_irq_enable_direct)
+	/* Unmask events */
+	movb $0, PER_CPU_VAR(xen_vcpu_info, XEN_vcpu_info_mask)
+
+	/* Preempt here doesn't matter because that will deal with
+	   any pending interrupts.  The pending check may end up being
+	   run on the wrong CPU, but that doesn't hurt. */
+
+	/* Test for pending */
+	testb $0xff, PER_CPU_VAR(xen_vcpu_info, XEN_vcpu_info_pending)
+	jz 1f
+
+2:	call check_events
+1:
+ENDPATCH(xen_irq_enable_direct)
+	ret
+	ENDPROC(xen_irq_enable_direct)
+	RELOC(xen_irq_enable_direct, 2b+1)
+
+/*
+	Disabling events is simply a matter of making the event mask
+	non-zero.
+ */
+ENTRY(xen_irq_disable_direct)
+	movb $1, PER_CPU_VAR(xen_vcpu_info, XEN_vcpu_info_mask)
+ENDPATCH(xen_irq_disable_direct)
+	ret
+	ENDPROC(xen_irq_disable_direct)
+	RELOC(xen_irq_disable_direct, 0)
+
+/*
+	(xen_)save_fl is used to get the current interrupt enable status.
+	Callers expect the status to be in X86_EFLAGS_IF, and other bits
+	may be set in the return value.  We take advantage of this by
+	making sure that X86_EFLAGS_IF has the right value (and other bits
+	in that byte are 0), but other bits in the return value are
+	undefined.  We need to toggle the state of the bit, because
+	Xen and x86 use opposite senses (mask vs enable).
+ */
+ENTRY(xen_save_fl_direct)
+	testb $0xff, PER_CPU_VAR(xen_vcpu_info, XEN_vcpu_info_mask)
+	setz %ah
+	addb %ah,%ah
+ENDPATCH(xen_save_fl_direct)
+	ret
+	ENDPROC(xen_save_fl_direct)
+	RELOC(xen_save_fl_direct, 0)
+
+/*
+	In principle the caller should be passing us a value return
+	from xen_save_fl_direct, but for robustness sake we test only
+	the X86_EFLAGS_IF flag rather than the whole byte. After
+	setting the interrupt mask state, it checks for unmasked
+	pending events and enters the hypervisor to get them delivered
+	if so.
+ */
+ENTRY(xen_restore_fl_direct)
+	testb $X86_EFLAGS_IF>>8, %ah
+	setz PER_CPU_VAR(xen_vcpu_info, XEN_vcpu_info_mask)
+	/* Preempt here doesn't matter because that will deal with
+	   any pending interrupts.  The pending check may end up being
+	   run on the wrong CPU, but that doesn't hurt. */
+
+	/* check for unmasked and pending */
+	cmpw $0x0001, PER_CPU_VAR(xen_vcpu_info, XEN_vcpu_info_pending)
+	jz 1f
+2:	call check_events
+1:
+ENDPATCH(xen_restore_fl_direct)
+	ret
+	ENDPROC(xen_restore_fl_direct)
+	RELOC(xen_restore_fl_direct, 2b+1)
+
+
+/*
+	Force an event check by making a hypercall,
+	but preserve regs before making the call.
+ */
+check_events:
+	push %rax
+	push %rcx
+	push %rdx
+	push %rsi
+	push %rdi
+	push %r8
+	push %r9
+	push %r10
+	push %r11
+	call force_evtchn_callback
+	pop %r11
+	pop %r10
+	pop %r9
+	pop %r8
+	pop %rdi
+	pop %rsi
+	pop %rdx
+	pop %rcx
+	pop %rax
+	ret
+#endif
+
+ENTRY(xen_adjust_exception_frame)
+	mov 8+0(%rsp),%rcx
+	mov 8+8(%rsp),%r11
+	ret $16
+
+hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32
+/*
+	Xen64 iret frame:
+
+	ss
+	rsp
+	rflags
+	cs
+	rip		<-- standard iret frame
+
+	flags
+
+	rcx		}
+	r11		}<-- pushed by hypercall page
+rsp ->	rax		}
+ */
+ENTRY(xen_iret)
+	pushq $0
+1:	jmp hypercall_iret
+ENDPATCH(xen_iret)
+RELOC(xen_iret, 1b+1)
+
+/*
+	sysexit is not used for 64-bit processes, so it's
+	only ever used to return to 32-bit compat userspace.
+ */
+ENTRY(xen_sysexit)
+	pushq $__USER32_DS
+	pushq %rcx
+	pushq $X86_EFLAGS_IF
+	pushq $__USER32_CS
+	pushq %rdx
+
+	pushq $VGCF_in_syscall
+1:	jmp hypercall_iret
+ENDPATCH(xen_sysexit)
+RELOC(xen_sysexit, 1b+1)
+
+ENTRY(xen_sysret64)
+	/* We're already on the usermode stack at this point, but still
+	   with the kernel gs, so we can easily switch back */
+	movq %rsp, %gs:pda_oldrsp
+	movq %gs:pda_kernelstack,%rsp
+
+	pushq $__USER_DS
+	pushq %gs:pda_oldrsp
+	pushq %r11
+	pushq $__USER_CS
+	pushq %rcx
+
+	pushq $VGCF_in_syscall
+1:	jmp hypercall_iret
+ENDPATCH(xen_sysret64)
+RELOC(xen_sysret64, 1b+1)
+
+ENTRY(xen_sysret32)
+	/* We're already on the usermode stack at this point, but still
+	   with the kernel gs, so we can easily switch back */
+	movq %rsp, %gs:pda_oldrsp
+	movq %gs:pda_kernelstack, %rsp
+
+	pushq $__USER32_DS
+	pushq %gs:pda_oldrsp
+	pushq %r11
+	pushq $__USER32_CS
+	pushq %rcx
+
+	pushq $VGCF_in_syscall
+1:	jmp hypercall_iret
+ENDPATCH(xen_sysret32)
+RELOC(xen_sysret32, 1b+1)
+
+/*
+	Xen handles syscall callbacks much like ordinary exceptions,
+	which means we have:
+	 - kernel gs
+	 - kernel rsp
+	 - an iret-like stack frame on the stack (including rcx and r11):
+		ss
+		rsp
+		rflags
+		cs
+		rip
+		r11
+	rsp->	rcx
+
+	In all the entrypoints, we undo all that to make it look
+	like a CPU-generated syscall/sysenter and jump to the normal
+	entrypoint.
+ */
+
+.macro undo_xen_syscall
+	mov 0*8(%rsp),%rcx
+	mov 1*8(%rsp),%r11
+	mov 5*8(%rsp),%rsp
+.endm
+
+/* Normal 64-bit system call target */
+ENTRY(xen_syscall_target)
+	undo_xen_syscall
+	jmp system_call_after_swapgs
+ENDPROC(xen_syscall_target)
+
+#ifdef CONFIG_IA32_EMULATION
+
+/* 32-bit compat syscall target */
+ENTRY(xen_syscall32_target)
+	undo_xen_syscall
+	jmp ia32_cstar_target
+ENDPROC(xen_syscall32_target)
+
+/* 32-bit compat sysenter target */
+ENTRY(xen_sysenter_target)
+	undo_xen_syscall
+	jmp ia32_sysenter_target
+ENDPROC(xen_sysenter_target)
+
+#else /* !CONFIG_IA32_EMULATION */
+
+ENTRY(xen_syscall32_target)
+ENTRY(xen_sysenter_target)
+	lea 16(%rsp), %rsp	/* strip %rcx,%r11 */
+	mov $-ENOSYS, %rax
+	pushq $VGCF_in_syscall
+	jmp hypercall_iret
+ENDPROC(xen_syscall32_target)
+ENDPROC(xen_sysenter_target)
+
+#endif	/* CONFIG_IA32_EMULATION */
diff --git a/arch/x86/xen/xen-head.S b/arch/x86/xen/xen-head.S
index 7c0cf63..63d49a5 100644
--- a/arch/x86/xen/xen-head.S
+++ b/arch/x86/xen/xen-head.S
@@ -5,15 +5,24 @@
 
 #include <linux/elfnote.h>
 #include <linux/init.h>
+
 #include <asm/boot.h>
+#include <asm/asm.h>
+#include <asm/page.h>
+
 #include <xen/interface/elfnote.h>
 #include <asm/xen/interface.h>
 
 	__INIT
 ENTRY(startup_xen)
-	movl %esi,xen_start_info
 	cld
-	movl $(init_thread_union+THREAD_SIZE),%esp
+#ifdef CONFIG_X86_32
+	mov %esi,xen_start_info
+	mov $init_thread_union+THREAD_SIZE,%esp
+#else
+	mov %rsi,xen_start_info
+	mov $init_thread_union+THREAD_SIZE,%rsp
+#endif
 	jmp xen_start_kernel
 
 	__FINIT
@@ -21,21 +30,26 @@
 .pushsection .text
 	.align PAGE_SIZE_asm
 ENTRY(hypercall_page)
-	.skip 0x1000
+	.skip PAGE_SIZE_asm
 .popsection
 
 	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS,       .asciz "linux")
 	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION,  .asciz "2.6")
 	ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION,    .asciz "xen-3.0")
-	ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE,      .long  __PAGE_OFFSET)
-	ELFNOTE(Xen, XEN_ELFNOTE_ENTRY,          .long  startup_xen)
-	ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .long  hypercall_page)
+#ifdef CONFIG_X86_32
+	ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE,      _ASM_PTR __PAGE_OFFSET)
+#else
+	ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE,      _ASM_PTR __START_KERNEL_map)
+#endif
+	ELFNOTE(Xen, XEN_ELFNOTE_ENTRY,          _ASM_PTR startup_xen)
+	ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, _ASM_PTR hypercall_page)
 	ELFNOTE(Xen, XEN_ELFNOTE_FEATURES,       .asciz "!writable_page_tables|pae_pgdir_above_4gb")
 	ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE,       .asciz "yes")
 	ELFNOTE(Xen, XEN_ELFNOTE_LOADER,         .asciz "generic")
 	ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,
 		.quad _PAGE_PRESENT; .quad _PAGE_PRESENT)
 	ELFNOTE(Xen, XEN_ELFNOTE_SUSPEND_CANCEL, .long 1)
-	ELFNOTE(Xen, XEN_ELFNOTE_HV_START_LOW,   .long __HYPERVISOR_VIRT_START)
+	ELFNOTE(Xen, XEN_ELFNOTE_HV_START_LOW,   _ASM_PTR __HYPERVISOR_VIRT_START)
+	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   _ASM_PTR 0)
 
 #endif /*CONFIG_XEN */
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index 6f4b104..dd3c231 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -26,6 +26,7 @@
 void __init xen_arch_setup(void);
 void __init xen_init_IRQ(void);
 void xen_enable_sysenter(void);
+void xen_enable_syscall(void);
 void xen_vcpu_restore(void);
 
 void __init xen_build_dynamic_phys_to_machine(void);
@@ -37,7 +38,6 @@
 unsigned long xen_get_wallclock(void);
 int xen_set_wallclock(unsigned long time);
 unsigned long long xen_sched_clock(void);
-void xen_timer_resume(void);
 
 irqreturn_t xen_debug_interrupt(int irq, void *dev_id);
 
@@ -45,20 +45,15 @@
 
 void xen_mark_init_mm_pinned(void);
 
-void __init xen_fill_possible_map(void);
-
 void __init xen_setup_vcpu_info_placement(void);
-void xen_smp_prepare_boot_cpu(void);
-void xen_smp_prepare_cpus(unsigned int max_cpus);
-int xen_cpu_up(unsigned int cpu);
-void xen_smp_cpus_done(unsigned int max_cpus);
 
-void xen_smp_send_stop(void);
-void xen_smp_send_reschedule(int cpu);
-void xen_smp_send_call_function_ipi(cpumask_t mask);
-void xen_smp_send_call_function_single_ipi(int cpu);
+#ifdef CONFIG_SMP
+void xen_smp_init(void);
 
 extern cpumask_t xen_cpu_initialized_map;
+#else
+static inline void xen_smp_init(void) {}
+#endif
 
 
 /* Declare an asm function, along with symbols needed to make it
@@ -73,7 +68,11 @@
 DECL_ASM(unsigned long, xen_save_fl_direct, void);
 DECL_ASM(void, xen_restore_fl_direct, unsigned long);
 
+/* These are not functions, and cannot be called normally */
 void xen_iret(void);
 void xen_sysexit(void);
+void xen_sysret32(void);
+void xen_sysret64(void);
+void xen_adjust_exception_frame(void);
 
 #endif /* XEN_OPS_H */
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 9fc8551..02e417d 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -194,8 +194,8 @@
 	plugged into slots found on all modern laptop computers.  Another
 	example, used on modern desktops as well as laptops, is USB.
 
-	Enable HOTPLUG and KMOD, and build a modular kernel.  Get agent
-	software (at <http://linux-hotplug.sourceforge.net/>) and install it.
+	Enable HOTPLUG and build a modular kernel.  Get agent software
+	(from <http://linux-hotplug.sourceforge.net/>) and install it.
 	Then your kernel will automatically call out to a user mode "policy
 	agent" (/sbin/hotplug) to load modules and set up software needed
 	to use devices as you hotplug them.
diff --git a/block/bsg.c b/block/bsg.c
index 5fb9b0b..5a68b09 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -1044,7 +1044,8 @@
 	bcd->release = release;
 	kref_init(&bcd->ref);
 	dev = MKDEV(bsg_major, bcd->minor);
-	class_dev = device_create(bsg_class, parent, dev, "%s", devname);
+	class_dev = device_create_drvdata(bsg_class, parent, dev, NULL,
+					  "%s", devname);
 	if (IS_ERR(class_dev)) {
 		ret = PTR_ERR(class_dev);
 		goto put_dev;
diff --git a/block/genhd.c b/block/genhd.c
index 9074f38..c13cc77 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -183,6 +183,7 @@
 void add_disk(struct gendisk *disk)
 {
 	struct backing_dev_info *bdi;
+	int retval;
 
 	disk->flags |= GENHD_FL_UP;
 	blk_register_region(MKDEV(disk->major, disk->first_minor),
@@ -193,7 +194,8 @@
 
 	bdi = &disk->queue->backing_dev_info;
 	bdi_register_dev(bdi, MKDEV(disk->major, disk->first_minor));
-	sysfs_create_link(&disk->dev.kobj, &bdi->dev->kobj, "bdi");
+	retval = sysfs_create_link(&disk->dev.kobj, &bdi->dev->kobj, "bdi");
+	WARN_ON(retval);
 }
 
 EXPORT_SYMBOL(add_disk);
@@ -225,89 +227,111 @@
 }
 
 /*
+ * print a partitions - intended for places where the root filesystem can't be
+ * mounted and thus to give the victim some idea of what went wrong
+ */
+static int printk_partition(struct device *dev, void *data)
+{
+	struct gendisk *sgp;
+	char buf[BDEVNAME_SIZE];
+	int n;
+
+	if (dev->type != &disk_type)
+		goto exit;
+
+	sgp = dev_to_disk(dev);
+	/*
+	 * Don't show empty devices or things that have been surpressed
+	 */
+	if (get_capacity(sgp) == 0 ||
+	    (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO))
+		goto exit;
+
+	/*
+	 * Note, unlike /proc/partitions, I am showing the numbers in
+	 * hex - the same format as the root= option takes.
+	 */
+	printk("%02x%02x %10llu %s",
+		sgp->major, sgp->first_minor,
+		(unsigned long long)get_capacity(sgp) >> 1,
+		disk_name(sgp, 0, buf));
+	if (sgp->driverfs_dev != NULL &&
+	    sgp->driverfs_dev->driver != NULL)
+		printk(" driver: %s\n",
+			sgp->driverfs_dev->driver->name);
+	else
+		printk(" (driver?)\n");
+
+	/* now show the partitions */
+	for (n = 0; n < sgp->minors - 1; ++n) {
+		if (sgp->part[n] == NULL)
+			goto exit;
+		if (sgp->part[n]->nr_sects == 0)
+			goto exit;
+		printk("  %02x%02x %10llu %s\n",
+			sgp->major, n + 1 + sgp->first_minor,
+			(unsigned long long)sgp->part[n]->nr_sects >> 1,
+			disk_name(sgp, n + 1, buf));
+	}
+exit:
+	return 0;
+}
+
+/*
  * print a full list of all partitions - intended for places where the root
  * filesystem can't be mounted and thus to give the victim some idea of what
  * went wrong
  */
 void __init printk_all_partitions(void)
 {
-	struct device *dev;
-	struct gendisk *sgp;
-	char buf[BDEVNAME_SIZE];
-	int n;
-
 	mutex_lock(&block_class_lock);
-	/* For each block device... */
-	list_for_each_entry(dev, &block_class.devices, node) {
-		if (dev->type != &disk_type)
-			continue;
-		sgp = dev_to_disk(dev);
-		/*
-		 * Don't show empty devices or things that have been surpressed
-		 */
-		if (get_capacity(sgp) == 0 ||
-		    (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO))
-			continue;
-
-		/*
-		 * Note, unlike /proc/partitions, I am showing the numbers in
-		 * hex - the same format as the root= option takes.
-		 */
-		printk("%02x%02x %10llu %s",
-			sgp->major, sgp->first_minor,
-			(unsigned long long)get_capacity(sgp) >> 1,
-			disk_name(sgp, 0, buf));
-		if (sgp->driverfs_dev != NULL &&
-		    sgp->driverfs_dev->driver != NULL)
-			printk(" driver: %s\n",
-				sgp->driverfs_dev->driver->name);
-		else
-			printk(" (driver?)\n");
-
-		/* now show the partitions */
-		for (n = 0; n < sgp->minors - 1; ++n) {
-			if (sgp->part[n] == NULL)
-				continue;
-			if (sgp->part[n]->nr_sects == 0)
-				continue;
-			printk("  %02x%02x %10llu %s\n",
-				sgp->major, n + 1 + sgp->first_minor,
-				(unsigned long long)sgp->part[n]->nr_sects >> 1,
-				disk_name(sgp, n + 1, buf));
-		}
-	}
-
+	class_for_each_device(&block_class, NULL, NULL, printk_partition);
 	mutex_unlock(&block_class_lock);
 }
 
 #ifdef CONFIG_PROC_FS
 /* iterator */
+static int find_start(struct device *dev, void *data)
+{
+	loff_t k = *(loff_t *)data;
+
+	if (dev->type != &disk_type)
+		return 0;
+	if (!k--)
+		return 1;
+	return 0;
+}
+
 static void *part_start(struct seq_file *part, loff_t *pos)
 {
-	loff_t k = *pos;
 	struct device *dev;
+	loff_t n = *pos;
+
+	if (!n)
+		seq_puts(part, "major minor  #blocks  name\n\n");
 
 	mutex_lock(&block_class_lock);
-	list_for_each_entry(dev, &block_class.devices, node) {
-		if (dev->type != &disk_type)
-			continue;
-		if (!k--)
-			return dev_to_disk(dev);
-	}
+	dev = class_find_device(&block_class, NULL, (void *)pos, find_start);
+	if (dev)
+		return dev_to_disk(dev);
 	return NULL;
 }
 
+static int find_next(struct device *dev, void *data)
+{
+	if (dev->type == &disk_type)
+		return 1;
+	return 0;
+}
+
 static void *part_next(struct seq_file *part, void *v, loff_t *pos)
 {
 	struct gendisk *gp = v;
 	struct device *dev;
 	++*pos;
-	list_for_each_entry(dev, &gp->dev.node, node) {
-		if (&dev->node == &block_class.devices)
-			return NULL;
-		if (dev->type == &disk_type)
-			return dev_to_disk(dev);
-	}
+	dev = class_find_device(&block_class, &gp->dev, NULL, find_next);
+	if (dev)
+		return dev_to_disk(dev);
 	return NULL;
 }
 
@@ -322,9 +346,6 @@
 	int n;
 	char buf[BDEVNAME_SIZE];
 
-	if (&sgp->dev.node == block_class.devices.next)
-		seq_puts(part, "major minor  #blocks  name\n\n");
-
 	/* Don't show non-partitionable removeable devices or empty devices */
 	if (!get_capacity(sgp) ||
 			(sgp->minors == 1 && (sgp->flags & GENHD_FL_REMOVABLE)))
@@ -370,7 +391,10 @@
 
 static int __init genhd_device_init(void)
 {
-	int error = class_register(&block_class);
+	int error;
+
+	block_class.dev_kobj = sysfs_dev_block_kobj;
+	error = class_register(&block_class);
 	if (unlikely(error))
 		return error;
 	bdev_map = kobj_map_init(base_probe, &block_class_lock);
@@ -532,6 +556,7 @@
 	.release	= disk_release,
 };
 
+#ifdef CONFIG_PROC_FS
 /*
  * aggregate disk stat collector.  Uses the same stats that the sysfs
  * entries do, above, but makes them available through one seq_file.
@@ -542,16 +567,12 @@
 
 static void *diskstats_start(struct seq_file *part, loff_t *pos)
 {
-	loff_t k = *pos;
 	struct device *dev;
 
 	mutex_lock(&block_class_lock);
-	list_for_each_entry(dev, &block_class.devices, node) {
-		if (dev->type != &disk_type)
-			continue;
-		if (!k--)
-			return dev_to_disk(dev);
-	}
+	dev = class_find_device(&block_class, NULL, (void *)pos, find_start);
+	if (dev)
+		return dev_to_disk(dev);
 	return NULL;
 }
 
@@ -561,12 +582,9 @@
 	struct device *dev;
 
 	++*pos;
-	list_for_each_entry(dev, &gp->dev.node, node) {
-		if (&dev->node == &block_class.devices)
-			return NULL;
-		if (dev->type == &disk_type)
-			return dev_to_disk(dev);
-	}
+	dev = class_find_device(&block_class, &gp->dev, NULL, find_next);
+	if (dev)
+		return dev_to_disk(dev);
 	return NULL;
 }
 
@@ -641,6 +659,7 @@
 	.stop	= diskstats_stop,
 	.show	= diskstats_show
 };
+#endif /* CONFIG_PROC_FS */
 
 static void media_change_notify_thread(struct work_struct *work)
 {
@@ -665,24 +684,38 @@
 EXPORT_SYMBOL_GPL(genhd_media_change_notify);
 #endif  /*  0  */
 
+struct find_block {
+	const char *name;
+	int part;
+};
+
+static int match_id(struct device *dev, void *data)
+{
+	struct find_block *find = data;
+
+	if (dev->type != &disk_type)
+		return 0;
+	if (strcmp(dev->bus_id, find->name) == 0) {
+		struct gendisk *disk = dev_to_disk(dev);
+		if (find->part < disk->minors)
+			return 1;
+	}
+	return 0;
+}
+
 dev_t blk_lookup_devt(const char *name, int part)
 {
 	struct device *dev;
 	dev_t devt = MKDEV(0, 0);
+	struct find_block find;
 
 	mutex_lock(&block_class_lock);
-	list_for_each_entry(dev, &block_class.devices, node) {
-		if (dev->type != &disk_type)
-			continue;
-		if (strcmp(dev->bus_id, name) == 0) {
-			struct gendisk *disk = dev_to_disk(dev);
-
-			if (part < disk->minors)
-				devt = MKDEV(MAJOR(dev->devt),
-					     MINOR(dev->devt) + part);
-			break;
-		}
-	}
+	find.name = name;
+	find.part = part;
+	dev = class_find_device(&block_class, NULL, (void *)&find, match_id);
+	if (dev)
+		devt = MKDEV(MAJOR(dev->devt),
+			     MINOR(dev->devt) + part);
 	mutex_unlock(&block_class_lock);
 
 	return devt;
diff --git a/crypto/async_tx/async_memcpy.c b/crypto/async_tx/async_memcpy.c
index a5eda80..ddccfb0 100644
--- a/crypto/async_tx/async_memcpy.c
+++ b/crypto/async_tx/async_memcpy.c
@@ -73,15 +73,7 @@
 		pr_debug("%s: (sync) len: %zu\n", __func__, len);
 
 		/* wait for any prerequisite operations */
-		if (depend_tx) {
-			/* if ack is already set then we cannot be sure
-			 * we are referring to the correct operation
-			 */
-			BUG_ON(async_tx_test_ack(depend_tx));
-			if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
-				panic("%s: DMA_ERROR waiting for depend_tx\n",
-					__func__);
-		}
+		async_tx_quiesce(&depend_tx);
 
 		dest_buf = kmap_atomic(dest, KM_USER0) + dest_offset;
 		src_buf = kmap_atomic(src, KM_USER1) + src_offset;
@@ -91,7 +83,7 @@
 		kunmap_atomic(dest_buf, KM_USER0);
 		kunmap_atomic(src_buf, KM_USER1);
 
-		async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+		async_tx_sync_epilog(cb_fn, cb_param);
 	}
 
 	return tx;
diff --git a/crypto/async_tx/async_memset.c b/crypto/async_tx/async_memset.c
index f5ff3906..5b5eb99 100644
--- a/crypto/async_tx/async_memset.c
+++ b/crypto/async_tx/async_memset.c
@@ -72,19 +72,11 @@
 		dest_buf = (void *) (((char *) page_address(dest)) + offset);
 
 		/* wait for any prerequisite operations */
-		if (depend_tx) {
-			/* if ack is already set then we cannot be sure
-			 * we are referring to the correct operation
-			 */
-			BUG_ON(depend_tx->ack);
-			if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
-				panic("%s: DMA_ERROR waiting for depend_tx\n",
-					__func__);
-		}
+		async_tx_quiesce(&depend_tx);
 
 		memset(dest_buf, val, len);
 
-		async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+		async_tx_sync_epilog(cb_fn, cb_param);
 	}
 
 	return tx;
diff --git a/crypto/async_tx/async_tx.c b/crypto/async_tx/async_tx.c
index 095c798..85eaf7b 100644
--- a/crypto/async_tx/async_tx.c
+++ b/crypto/async_tx/async_tx.c
@@ -295,7 +295,7 @@
 	case DMA_RESOURCE_REMOVED:
 		found = 0;
 		spin_lock_irqsave(&async_tx_lock, flags);
-		list_for_each_entry_rcu(ref, &async_tx_master_list, node)
+		list_for_each_entry(ref, &async_tx_master_list, node)
 			if (ref->chan == chan) {
 				/* permit backing devices to go away */
 				dma_chan_put(ref->chan);
@@ -608,23 +608,34 @@
 		pr_debug("%s: (sync)\n", __func__);
 
 		/* wait for any prerequisite operations */
-		if (depend_tx) {
-			/* if ack is already set then we cannot be sure
-			 * we are referring to the correct operation
-			 */
-			BUG_ON(async_tx_test_ack(depend_tx));
-			if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
-				panic("%s: DMA_ERROR waiting for depend_tx\n",
-					__func__);
-		}
+		async_tx_quiesce(&depend_tx);
 
-		async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+		async_tx_sync_epilog(cb_fn, cb_param);
 	}
 
 	return tx;
 }
 EXPORT_SYMBOL_GPL(async_trigger_callback);
 
+/**
+ * async_tx_quiesce - ensure tx is complete and freeable upon return
+ * @tx - transaction to quiesce
+ */
+void async_tx_quiesce(struct dma_async_tx_descriptor **tx)
+{
+	if (*tx) {
+		/* if ack is already set then we cannot be sure
+		 * we are referring to the correct operation
+		 */
+		BUG_ON(async_tx_test_ack(*tx));
+		if (dma_wait_for_async_tx(*tx) == DMA_ERROR)
+			panic("DMA_ERROR waiting for transaction\n");
+		async_tx_ack(*tx);
+		*tx = NULL;
+	}
+}
+EXPORT_SYMBOL_GPL(async_tx_quiesce);
+
 module_init(async_tx_init);
 module_exit(async_tx_exit);
 
diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c
index 3a0dddc..65974c6 100644
--- a/crypto/async_tx/async_xor.c
+++ b/crypto/async_tx/async_xor.c
@@ -35,74 +35,121 @@
  * 	when CONFIG_DMA_ENGINE=n
  */
 static __always_inline struct dma_async_tx_descriptor *
-do_async_xor(struct dma_device *device,
-	struct dma_chan *chan, struct page *dest, struct page **src_list,
-	unsigned int offset, unsigned int src_cnt, size_t len,
-	enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,
-	dma_async_tx_callback cb_fn, void *cb_param)
+do_async_xor(struct dma_chan *chan, struct page *dest, struct page **src_list,
+	     unsigned int offset, int src_cnt, size_t len,
+	     enum async_tx_flags flags,
+	     struct dma_async_tx_descriptor *depend_tx,
+	     dma_async_tx_callback cb_fn, void *cb_param)
 {
-	dma_addr_t dma_dest;
+	struct dma_device *dma = chan->device;
 	dma_addr_t *dma_src = (dma_addr_t *) src_list;
-	struct dma_async_tx_descriptor *tx;
+	struct dma_async_tx_descriptor *tx = NULL;
+	int src_off = 0;
 	int i;
-	unsigned long dma_prep_flags = cb_fn ? DMA_PREP_INTERRUPT : 0;
+	dma_async_tx_callback _cb_fn;
+	void *_cb_param;
+	enum async_tx_flags async_flags;
+	enum dma_ctrl_flags dma_flags;
+	int xor_src_cnt;
+	dma_addr_t dma_dest;
 
-	pr_debug("%s: len: %zu\n", __func__, len);
-
-	dma_dest = dma_map_page(device->dev, dest, offset, len,
-				DMA_FROM_DEVICE);
-
+	dma_dest = dma_map_page(dma->dev, dest, offset, len, DMA_FROM_DEVICE);
 	for (i = 0; i < src_cnt; i++)
-		dma_src[i] = dma_map_page(device->dev, src_list[i], offset,
+		dma_src[i] = dma_map_page(dma->dev, src_list[i], offset,
 					  len, DMA_TO_DEVICE);
 
-	/* Since we have clobbered the src_list we are committed
-	 * to doing this asynchronously.  Drivers force forward progress
-	 * in case they can not provide a descriptor
-	 */
-	tx = device->device_prep_dma_xor(chan, dma_dest, dma_src, src_cnt, len,
-					 dma_prep_flags);
-	if (!tx) {
-		if (depend_tx)
-			dma_wait_for_async_tx(depend_tx);
+	while (src_cnt) {
+		async_flags = flags;
+		dma_flags = 0;
+		xor_src_cnt = min(src_cnt, dma->max_xor);
+		/* if we are submitting additional xors, leave the chain open,
+		 * clear the callback parameters, and leave the destination
+		 * buffer mapped
+		 */
+		if (src_cnt > xor_src_cnt) {
+			async_flags &= ~ASYNC_TX_ACK;
+			dma_flags = DMA_COMPL_SKIP_DEST_UNMAP;
+			_cb_fn = NULL;
+			_cb_param = NULL;
+		} else {
+			_cb_fn = cb_fn;
+			_cb_param = cb_param;
+		}
+		if (_cb_fn)
+			dma_flags |= DMA_PREP_INTERRUPT;
 
-		while (!tx)
-			tx = device->device_prep_dma_xor(chan, dma_dest,
-							 dma_src, src_cnt, len,
-							 dma_prep_flags);
+		/* Since we have clobbered the src_list we are committed
+		 * to doing this asynchronously.  Drivers force forward progress
+		 * in case they can not provide a descriptor
+		 */
+		tx = dma->device_prep_dma_xor(chan, dma_dest, &dma_src[src_off],
+					      xor_src_cnt, len, dma_flags);
+
+		if (unlikely(!tx))
+			async_tx_quiesce(&depend_tx);
+
+		/* spin wait for the preceeding transactions to complete */
+		while (unlikely(!tx)) {
+			dma_async_issue_pending(chan);
+			tx = dma->device_prep_dma_xor(chan, dma_dest,
+						      &dma_src[src_off],
+						      xor_src_cnt, len,
+						      dma_flags);
+		}
+
+		async_tx_submit(chan, tx, async_flags, depend_tx, _cb_fn,
+				_cb_param);
+
+		depend_tx = tx;
+		flags |= ASYNC_TX_DEP_ACK;
+
+		if (src_cnt > xor_src_cnt) {
+			/* drop completed sources */
+			src_cnt -= xor_src_cnt;
+			src_off += xor_src_cnt;
+
+			/* use the intermediate result a source */
+			dma_src[--src_off] = dma_dest;
+			src_cnt++;
+		} else
+			break;
 	}
 
-	async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
-
 	return tx;
 }
 
 static void
 do_sync_xor(struct page *dest, struct page **src_list, unsigned int offset,
-	unsigned int src_cnt, size_t len, enum async_tx_flags flags,
-	struct dma_async_tx_descriptor *depend_tx,
-	dma_async_tx_callback cb_fn, void *cb_param)
+	    int src_cnt, size_t len, enum async_tx_flags flags,
+	    dma_async_tx_callback cb_fn, void *cb_param)
 {
-	void *_dest;
 	int i;
-
-	pr_debug("%s: len: %zu\n", __func__, len);
+	int xor_src_cnt;
+	int src_off = 0;
+	void *dest_buf;
+	void **srcs = (void **) src_list;
 
 	/* reuse the 'src_list' array to convert to buffer pointers */
 	for (i = 0; i < src_cnt; i++)
-		src_list[i] = (struct page *)
-			(page_address(src_list[i]) + offset);
+		srcs[i] = page_address(src_list[i]) + offset;
 
 	/* set destination address */
-	_dest = page_address(dest) + offset;
+	dest_buf = page_address(dest) + offset;
 
 	if (flags & ASYNC_TX_XOR_ZERO_DST)
-		memset(_dest, 0, len);
+		memset(dest_buf, 0, len);
 
-	xor_blocks(src_cnt, len, _dest,
-		(void **) src_list);
+	while (src_cnt > 0) {
+		/* process up to 'MAX_XOR_BLOCKS' sources */
+		xor_src_cnt = min(src_cnt, MAX_XOR_BLOCKS);
+		xor_blocks(xor_src_cnt, len, dest_buf, &srcs[src_off]);
 
-	async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+		/* drop completed sources */
+		src_cnt -= xor_src_cnt;
+		src_off += xor_src_cnt;
+	}
+
+	async_tx_sync_epilog(cb_fn, cb_param);
 }
 
 /**
@@ -132,106 +179,34 @@
 	struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_XOR,
 						      &dest, 1, src_list,
 						      src_cnt, len);
-	struct dma_device *device = chan ? chan->device : NULL;
-	struct dma_async_tx_descriptor *tx = NULL;
-	dma_async_tx_callback _cb_fn;
-	void *_cb_param;
-	unsigned long local_flags;
-	int xor_src_cnt;
-	int i = 0, src_off = 0;
-
 	BUG_ON(src_cnt <= 1);
 
-	while (src_cnt) {
-		local_flags = flags;
-		if (device) { /* run the xor asynchronously */
-			xor_src_cnt = min(src_cnt, device->max_xor);
-			/* if we are submitting additional xors
-			 * only set the callback on the last transaction
-			 */
-			if (src_cnt > xor_src_cnt) {
-				local_flags &= ~ASYNC_TX_ACK;
-				_cb_fn = NULL;
-				_cb_param = NULL;
-			} else {
-				_cb_fn = cb_fn;
-				_cb_param = cb_param;
-			}
+	if (chan) {
+		/* run the xor asynchronously */
+		pr_debug("%s (async): len: %zu\n", __func__, len);
 
-			tx = do_async_xor(device, chan, dest,
-					  &src_list[src_off], offset,
-					  xor_src_cnt, len, local_flags,
-					  depend_tx, _cb_fn, _cb_param);
-		} else { /* run the xor synchronously */
-			/* in the sync case the dest is an implied source
-			 * (assumes the dest is at the src_off index)
-			 */
-			if (flags & ASYNC_TX_XOR_DROP_DST) {
-				src_cnt--;
-				src_off++;
-			}
+		return do_async_xor(chan, dest, src_list, offset, src_cnt, len,
+				    flags, depend_tx, cb_fn, cb_param);
+	} else {
+		/* run the xor synchronously */
+		pr_debug("%s (sync): len: %zu\n", __func__, len);
 
-			/* process up to 'MAX_XOR_BLOCKS' sources */
-			xor_src_cnt = min(src_cnt, MAX_XOR_BLOCKS);
-
-			/* if we are submitting additional xors
-			 * only set the callback on the last transaction
-			 */
-			if (src_cnt > xor_src_cnt) {
-				local_flags &= ~ASYNC_TX_ACK;
-				_cb_fn = NULL;
-				_cb_param = NULL;
-			} else {
-				_cb_fn = cb_fn;
-				_cb_param = cb_param;
-			}
-
-			/* wait for any prerequisite operations */
-			if (depend_tx) {
-				/* if ack is already set then we cannot be sure
-				 * we are referring to the correct operation
-				 */
-				BUG_ON(async_tx_test_ack(depend_tx));
-				if (dma_wait_for_async_tx(depend_tx) ==
-					DMA_ERROR)
-					panic("%s: DMA_ERROR waiting for "
-						"depend_tx\n",
-						__func__);
-			}
-
-			do_sync_xor(dest, &src_list[src_off], offset,
-				xor_src_cnt, len, local_flags, depend_tx,
-				_cb_fn, _cb_param);
+		/* in the sync case the dest is an implied source
+		 * (assumes the dest is the first source)
+		 */
+		if (flags & ASYNC_TX_XOR_DROP_DST) {
+			src_cnt--;
+			src_list++;
 		}
 
-		/* the previous tx is hidden from the client,
-		 * so ack it
-		 */
-		if (i && depend_tx)
-			async_tx_ack(depend_tx);
+		/* wait for any prerequisite operations */
+		async_tx_quiesce(&depend_tx);
 
-		depend_tx = tx;
+		do_sync_xor(dest, src_list, offset, src_cnt, len,
+			    flags, cb_fn, cb_param);
 
-		if (src_cnt > xor_src_cnt) {
-			/* drop completed sources */
-			src_cnt -= xor_src_cnt;
-			src_off += xor_src_cnt;
-
-			/* unconditionally preserve the destination */
-			flags &= ~ASYNC_TX_XOR_ZERO_DST;
-
-			/* use the intermediate result a source, but remember
-			 * it's dropped, because it's implied, in the sync case
-			 */
-			src_list[--src_off] = dest;
-			src_cnt++;
-			flags |= ASYNC_TX_XOR_DROP_DST;
-		} else
-			src_cnt = 0;
-		i++;
+		return NULL;
 	}
-
-	return tx;
 }
 EXPORT_SYMBOL_GPL(async_xor);
 
@@ -285,11 +260,11 @@
 		tx = device->device_prep_dma_zero_sum(chan, dma_src, src_cnt,
 						      len, result,
 						      dma_prep_flags);
-		if (!tx) {
-			if (depend_tx)
-				dma_wait_for_async_tx(depend_tx);
+		if (unlikely(!tx)) {
+			async_tx_quiesce(&depend_tx);
 
 			while (!tx)
+				dma_async_issue_pending(chan);
 				tx = device->device_prep_dma_zero_sum(chan,
 					dma_src, src_cnt, len, result,
 					dma_prep_flags);
@@ -307,18 +282,11 @@
 		tx = async_xor(dest, src_list, offset, src_cnt, len, xor_flags,
 			depend_tx, NULL, NULL);
 
-		if (tx) {
-			if (dma_wait_for_async_tx(tx) == DMA_ERROR)
-				panic("%s: DMA_ERROR waiting for tx\n",
-					__func__);
-			async_tx_ack(tx);
-		}
+		async_tx_quiesce(&tx);
 
 		*result = page_is_zero(dest, offset, len) ? 0 : 1;
 
-		tx = NULL;
-
-		async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+		async_tx_sync_epilog(cb_fn, cb_param);
 	}
 
 	return tx;
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index 55c17af..2655bc1 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -263,22 +263,22 @@
 		goto end;
 	}
 
-	printk(KERN_INFO PREFIX
-		"%s is registered as cooling_device%d\n",
-		device->dev.bus_id, cdev->id);
+	dev_info(&device->dev, "registered as cooling_device%d\n", cdev->id);
 
 	acpi_driver_data(device) = cdev;
 	result = sysfs_create_link(&device->dev.kobj,
 				   &cdev->device.kobj,
 				   "thermal_cooling");
 	if (result)
-		printk(KERN_ERR PREFIX "Create sysfs link\n");
+		dev_err(&device->dev, "Failed to create sysfs link "
+			"'thermal_cooling'\n");
 
 	result = sysfs_create_link(&cdev->device.kobj,
 				   &device->dev.kobj,
 				   "device");
 	if (result)
-		printk(KERN_ERR PREFIX "Create sysfs link\n");
+		dev_err(&device->dev, "Failed to create sysfs link "
+			"'device'\n");
 
 	result = acpi_fan_add_fs(device);
 	if (result)
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 2f173e8..0841095 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -146,8 +146,7 @@
 	acpi_status status;
 
 	if (dev->archdata.acpi_handle) {
-		printk(KERN_WARNING PREFIX
-		       "Drivers changed 'acpi_handle' for %s\n", dev->bus_id);
+		dev_warn(dev, "Drivers changed 'acpi_handle'\n");
 		return -EINVAL;
 	}
 	get_device(dev);
@@ -195,8 +194,7 @@
 		/* acpi_bind_one increase refcnt by one */
 		put_device(dev);
 	} else {
-		printk(KERN_ERR PREFIX
-		       "Oops, 'acpi_handle' corrupt for %s\n", dev->bus_id);
+		dev_err(dev, "Oops, 'acpi_handle' corrupt\n");
 	}
 	return 0;
 }
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index ec0f2d58..e36422a 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -714,9 +714,8 @@
 		goto end;
 	}
 
-	printk(KERN_INFO PREFIX
-		"%s is registered as cooling_device%d\n",
-		device->dev.bus_id, pr->cdev->id);
+	dev_info(&device->dev, "registered as cooling_device%d\n",
+		 pr->cdev->id);
 
 	result = sysfs_create_link(&device->dev.kobj,
 				   &pr->cdev->device.kobj,
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index f3132aa..f6f52c1 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -471,7 +471,7 @@
 	device->dev.release = &acpi_device_release;
 	result = device_add(&device->dev);
 	if(result) {
-		printk(KERN_ERR PREFIX "Error adding device %s", device->dev.bus_id);
+		dev_err(&device->dev, "Error adding device\n");
 		goto end;
 	}
 
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 84c795f..30a3413 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -1179,8 +1179,8 @@
 
 	tz->tz_enabled = 1;
 
-	printk(KERN_INFO PREFIX "%s is registered as thermal_zone%d\n",
-			tz->device->dev.bus_id, tz->thermal_zone->id);
+	dev_info(&tz->device->dev, "registered as thermal_zone%d\n",
+		 tz->thermal_zone->id);
 	return 0;
 }
 
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 64c8893..37b9e16 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -762,9 +762,8 @@
 		if (IS_ERR(device->cdev))
 			return;
 
-		printk(KERN_INFO PREFIX
-			"%s is registered as cooling_device%d\n",
-			device->dev->dev.bus_id, device->cdev->id);
+		dev_info(&device->dev->dev, "registered as cooling_device%d\n",
+			 device->cdev->id);
 		result = sysfs_create_link(&device->dev->dev.kobj,
 				&device->cdev->device.kobj,
 				"thermal_cooling");
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index d47482f..6318f6b 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -27,8 +27,9 @@
 	  If unsure say Y here.
 
 config FW_LOADER
-	tristate "Userspace firmware loading support"
+	tristate "Userspace firmware loading support" if EMBEDDED
 	depends on HOTPLUG
+	default y
 	---help---
 	  This option is provided for the case where no in-kernel-tree modules
 	  require userspace firmware loading support, but a module built outside
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 2c9ae43..31dc0cd 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -36,6 +36,33 @@
 };
 #define to_driver(obj) container_of(obj, struct driver_private, kobj)
 
+
+/**
+ * struct class_private - structure to hold the private to the driver core portions of the class structure.
+ *
+ * @class_subsys - the struct kset that defines this class.  This is the main kobject
+ * @class_devices - list of devices associated with this class
+ * @class_interfaces - list of class_interfaces associated with this class
+ * @class_dirs - "glue" directory for virtual devices associated with this class
+ * @class_mutex - mutex to protect the children, devices, and interfaces lists.
+ * @class - pointer back to the struct class that this structure is associated
+ * with.
+ *
+ * This structure is the one that is the actual kobject allowing struct
+ * class to be statically allocated safely.  Nothing outside of the driver
+ * core should ever touch these fields.
+ */
+struct class_private {
+	struct kset class_subsys;
+	struct list_head class_devices;
+	struct list_head class_interfaces;
+	struct kset class_dirs;
+	struct mutex class_mutex;
+	struct class *class;
+};
+#define to_class(obj)	\
+	container_of(obj, struct class_private, class_subsys.kobj)
+
 /* initialisation functions */
 extern int devices_init(void);
 extern int buses_init(void);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index e085af0..839d27c 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -18,20 +18,20 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/genhd.h>
+#include <linux/mutex.h>
 #include "base.h"
 
 #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
-#define to_class(obj) container_of(obj, struct class, subsys.kobj)
 
 static ssize_t class_attr_show(struct kobject *kobj, struct attribute *attr,
 			       char *buf)
 {
 	struct class_attribute *class_attr = to_class_attr(attr);
-	struct class *dc = to_class(kobj);
+	struct class_private *cp = to_class(kobj);
 	ssize_t ret = -EIO;
 
 	if (class_attr->show)
-		ret = class_attr->show(dc, buf);
+		ret = class_attr->show(cp->class, buf);
 	return ret;
 }
 
@@ -39,17 +39,18 @@
 				const char *buf, size_t count)
 {
 	struct class_attribute *class_attr = to_class_attr(attr);
-	struct class *dc = to_class(kobj);
+	struct class_private *cp = to_class(kobj);
 	ssize_t ret = -EIO;
 
 	if (class_attr->store)
-		ret = class_attr->store(dc, buf, count);
+		ret = class_attr->store(cp->class, buf, count);
 	return ret;
 }
 
 static void class_release(struct kobject *kobj)
 {
-	struct class *class = to_class(kobj);
+	struct class_private *cp = to_class(kobj);
+	struct class *class = cp->class;
 
 	pr_debug("class '%s': release.\n", class->name);
 
@@ -70,7 +71,7 @@
 	.release	= class_release,
 };
 
-/* Hotplug events for classes go to the class_obj subsys */
+/* Hotplug events for classes go to the class class_subsys */
 static struct kset *class_kset;
 
 
@@ -78,7 +79,8 @@
 {
 	int error;
 	if (cls)
-		error = sysfs_create_file(&cls->subsys.kobj, &attr->attr);
+		error = sysfs_create_file(&cls->p->class_subsys.kobj,
+					  &attr->attr);
 	else
 		error = -EINVAL;
 	return error;
@@ -87,21 +89,20 @@
 void class_remove_file(struct class *cls, const struct class_attribute *attr)
 {
 	if (cls)
-		sysfs_remove_file(&cls->subsys.kobj, &attr->attr);
+		sysfs_remove_file(&cls->p->class_subsys.kobj, &attr->attr);
 }
 
 static struct class *class_get(struct class *cls)
 {
 	if (cls)
-		return container_of(kset_get(&cls->subsys),
-				    struct class, subsys);
-	return NULL;
+		kset_get(&cls->p->class_subsys);
+	return cls;
 }
 
 static void class_put(struct class *cls)
 {
 	if (cls)
-		kset_put(&cls->subsys);
+		kset_put(&cls->p->class_subsys);
 }
 
 static int add_class_attrs(struct class *cls)
@@ -134,42 +135,57 @@
 	}
 }
 
-int class_register(struct class *cls)
+int __class_register(struct class *cls, struct lock_class_key *key)
 {
+	struct class_private *cp;
 	int error;
 
 	pr_debug("device class '%s': registering\n", cls->name);
 
-	INIT_LIST_HEAD(&cls->devices);
-	INIT_LIST_HEAD(&cls->interfaces);
-	kset_init(&cls->class_dirs);
-	init_MUTEX(&cls->sem);
-	error = kobject_set_name(&cls->subsys.kobj, "%s", cls->name);
-	if (error)
+	cp = kzalloc(sizeof(*cp), GFP_KERNEL);
+	if (!cp)
+		return -ENOMEM;
+	INIT_LIST_HEAD(&cp->class_devices);
+	INIT_LIST_HEAD(&cp->class_interfaces);
+	kset_init(&cp->class_dirs);
+	__mutex_init(&cp->class_mutex, "struct class mutex", key);
+	error = kobject_set_name(&cp->class_subsys.kobj, "%s", cls->name);
+	if (error) {
+		kfree(cp);
 		return error;
+	}
+
+	/* set the default /sys/dev directory for devices of this class */
+	if (!cls->dev_kobj)
+		cls->dev_kobj = sysfs_dev_char_kobj;
 
 #if defined(CONFIG_SYSFS_DEPRECATED) && defined(CONFIG_BLOCK)
 	/* let the block class directory show up in the root of sysfs */
 	if (cls != &block_class)
-		cls->subsys.kobj.kset = class_kset;
+		cp->class_subsys.kobj.kset = class_kset;
 #else
-	cls->subsys.kobj.kset = class_kset;
+	cp->class_subsys.kobj.kset = class_kset;
 #endif
-	cls->subsys.kobj.ktype = &class_ktype;
+	cp->class_subsys.kobj.ktype = &class_ktype;
+	cp->class = cls;
+	cls->p = cp;
 
-	error = kset_register(&cls->subsys);
-	if (!error) {
-		error = add_class_attrs(class_get(cls));
-		class_put(cls);
+	error = kset_register(&cp->class_subsys);
+	if (error) {
+		kfree(cp);
+		return error;
 	}
+	error = add_class_attrs(class_get(cls));
+	class_put(cls);
 	return error;
 }
+EXPORT_SYMBOL_GPL(__class_register);
 
 void class_unregister(struct class *cls)
 {
 	pr_debug("device class '%s': unregistering\n", cls->name);
 	remove_class_attrs(cls);
-	kset_unregister(&cls->subsys);
+	kset_unregister(&cls->p->class_subsys);
 }
 
 static void class_create_release(struct class *cls)
@@ -189,7 +205,8 @@
  * Note, the pointer created here is to be destroyed when finished by
  * making a call to class_destroy().
  */
-struct class *class_create(struct module *owner, const char *name)
+struct class *__class_create(struct module *owner, const char *name,
+			     struct lock_class_key *key)
 {
 	struct class *cls;
 	int retval;
@@ -204,7 +221,7 @@
 	cls->owner = owner;
 	cls->class_release = class_create_release;
 
-	retval = class_register(cls);
+	retval = __class_register(cls, key);
 	if (retval)
 		goto error;
 
@@ -214,6 +231,7 @@
 	kfree(cls);
 	return ERR_PTR(retval);
 }
+EXPORT_SYMBOL_GPL(__class_create);
 
 /**
  * class_destroy - destroys a struct class structure
@@ -252,39 +270,44 @@
 /**
  * class_for_each_device - device iterator
  * @class: the class we're iterating
+ * @start: the device to start with in the list, if any.
  * @data: data for the callback
  * @fn: function to be called for each device
  *
  * Iterate over @class's list of devices, and call @fn for each,
- * passing it @data.
+ * passing it @data.  If @start is set, the list iteration will start
+ * there, otherwise if it is NULL, the iteration starts at the
+ * beginning of the list.
  *
  * We check the return of @fn each time. If it returns anything
  * other than 0, we break out and return that value.
  *
- * Note, we hold class->sem in this function, so it can not be
+ * Note, we hold class->class_mutex in this function, so it can not be
  * re-acquired in @fn, otherwise it will self-deadlocking. For
  * example, calls to add or remove class members would be verboten.
  */
-int class_for_each_device(struct class *class, void *data,
-			   int (*fn)(struct device *, void *))
+int class_for_each_device(struct class *class, struct device *start,
+			  void *data, int (*fn)(struct device *, void *))
 {
 	struct device *dev;
 	int error = 0;
 
 	if (!class)
 		return -EINVAL;
-	down(&class->sem);
-	list_for_each_entry(dev, &class->devices, node) {
+	mutex_lock(&class->p->class_mutex);
+	list_for_each_entry(dev, &class->p->class_devices, node) {
+		if (start) {
+			if (start == dev)
+				start = NULL;
+			continue;
+		}
 		dev = get_device(dev);
-		if (dev) {
-			error = fn(dev, data);
-			put_device(dev);
-		} else
-			error = -ENODEV;
+		error = fn(dev, data);
+		put_device(dev);
 		if (error)
 			break;
 	}
-	up(&class->sem);
+	mutex_unlock(&class->p->class_mutex);
 
 	return error;
 }
@@ -293,6 +316,7 @@
 /**
  * class_find_device - device iterator for locating a particular device
  * @class: the class we're iterating
+ * @start: Device to begin with
  * @data: data for the match function
  * @match: function to check device
  *
@@ -306,12 +330,13 @@
  *
  * Note, you will need to drop the reference with put_device() after use.
  *
- * We hold class->sem in this function, so it can not be
+ * We hold class->class_mutex in this function, so it can not be
  * re-acquired in @match, otherwise it will self-deadlocking. For
  * example, calls to add or remove class members would be verboten.
  */
-struct device *class_find_device(struct class *class, void *data,
-				   int (*match)(struct device *, void *))
+struct device *class_find_device(struct class *class, struct device *start,
+				 void *data,
+				 int (*match)(struct device *, void *))
 {
 	struct device *dev;
 	int found = 0;
@@ -319,19 +344,21 @@
 	if (!class)
 		return NULL;
 
-	down(&class->sem);
-	list_for_each_entry(dev, &class->devices, node) {
+	mutex_lock(&class->p->class_mutex);
+	list_for_each_entry(dev, &class->p->class_devices, node) {
+		if (start) {
+			if (start == dev)
+				start = NULL;
+			continue;
+		}
 		dev = get_device(dev);
-		if (dev) {
-			if (match(dev, data)) {
-				found = 1;
-				break;
-			} else
-				put_device(dev);
-		} else
+		if (match(dev, data)) {
+			found = 1;
 			break;
+		} else
+			put_device(dev);
 	}
-	up(&class->sem);
+	mutex_unlock(&class->p->class_mutex);
 
 	return found ? dev : NULL;
 }
@@ -349,13 +376,13 @@
 	if (!parent)
 		return -EINVAL;
 
-	down(&parent->sem);
-	list_add_tail(&class_intf->node, &parent->interfaces);
+	mutex_lock(&parent->p->class_mutex);
+	list_add_tail(&class_intf->node, &parent->p->class_interfaces);
 	if (class_intf->add_dev) {
-		list_for_each_entry(dev, &parent->devices, node)
+		list_for_each_entry(dev, &parent->p->class_devices, node)
 			class_intf->add_dev(dev, class_intf);
 	}
-	up(&parent->sem);
+	mutex_unlock(&parent->p->class_mutex);
 
 	return 0;
 }
@@ -368,13 +395,13 @@
 	if (!parent)
 		return;
 
-	down(&parent->sem);
+	mutex_lock(&parent->p->class_mutex);
 	list_del_init(&class_intf->node);
 	if (class_intf->remove_dev) {
-		list_for_each_entry(dev, &parent->devices, node)
+		list_for_each_entry(dev, &parent->p->class_devices, node)
 			class_intf->remove_dev(dev, class_intf);
 	}
-	up(&parent->sem);
+	mutex_unlock(&parent->p->class_mutex);
 
 	class_put(parent);
 }
@@ -389,9 +416,7 @@
 
 EXPORT_SYMBOL_GPL(class_create_file);
 EXPORT_SYMBOL_GPL(class_remove_file);
-EXPORT_SYMBOL_GPL(class_register);
 EXPORT_SYMBOL_GPL(class_unregister);
-EXPORT_SYMBOL_GPL(class_create);
 EXPORT_SYMBOL_GPL(class_destroy);
 
 EXPORT_SYMBOL_GPL(class_interface_register);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index ee0a51a..7d5c63c 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -21,12 +21,16 @@
 #include <linux/genhd.h>
 #include <linux/kallsyms.h>
 #include <linux/semaphore.h>
+#include <linux/mutex.h>
 
 #include "base.h"
 #include "power/power.h"
 
 int (*platform_notify)(struct device *dev) = NULL;
 int (*platform_notify_remove)(struct device *dev) = NULL;
+static struct kobject *dev_kobj;
+struct kobject *sysfs_dev_char_kobj;
+struct kobject *sysfs_dev_block_kobj;
 
 #ifdef CONFIG_BLOCK
 static inline int device_is_not_partition(struct device *dev)
@@ -548,7 +552,7 @@
 {
 	/* class devices without a parent live in /sys/class/<classname>/ */
 	if (dev->class && (!parent || parent->class != dev->class))
-		return &dev->class->subsys.kobj;
+		return &dev->class->p->class_subsys.kobj;
 	/* all other devices keep their parent */
 	else if (parent)
 		return &parent->kobj;
@@ -594,13 +598,13 @@
 			parent_kobj = &parent->kobj;
 
 		/* find our class-directory at the parent and reference it */
-		spin_lock(&dev->class->class_dirs.list_lock);
-		list_for_each_entry(k, &dev->class->class_dirs.list, entry)
+		spin_lock(&dev->class->p->class_dirs.list_lock);
+		list_for_each_entry(k, &dev->class->p->class_dirs.list, entry)
 			if (k->parent == parent_kobj) {
 				kobj = kobject_get(k);
 				break;
 			}
-		spin_unlock(&dev->class->class_dirs.list_lock);
+		spin_unlock(&dev->class->p->class_dirs.list_lock);
 		if (kobj)
 			return kobj;
 
@@ -608,7 +612,7 @@
 		k = kobject_create();
 		if (!k)
 			return NULL;
-		k->kset = &dev->class->class_dirs;
+		k->kset = &dev->class->p->class_dirs;
 		retval = kobject_add(k, parent_kobj, "%s", dev->class->name);
 		if (retval < 0) {
 			kobject_put(k);
@@ -627,7 +631,7 @@
 {
 	/* see if we live in a "glue" directory */
 	if (!glue_dir || !dev->class ||
-	    glue_dir->kset != &dev->class->class_dirs)
+	    glue_dir->kset != &dev->class->p->class_dirs)
 		return;
 
 	kobject_put(glue_dir);
@@ -654,17 +658,18 @@
 	if (!dev->class)
 		return 0;
 
-	error = sysfs_create_link(&dev->kobj, &dev->class->subsys.kobj,
+	error = sysfs_create_link(&dev->kobj,
+				  &dev->class->p->class_subsys.kobj,
 				  "subsystem");
 	if (error)
 		goto out;
 
 #ifdef CONFIG_SYSFS_DEPRECATED
 	/* stacked class devices need a symlink in the class directory */
-	if (dev->kobj.parent != &dev->class->subsys.kobj &&
+	if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
 	    device_is_not_partition(dev)) {
-		error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
-					  dev->bus_id);
+		error = sysfs_create_link(&dev->class->p->class_subsys.kobj,
+					  &dev->kobj, dev->bus_id);
 		if (error)
 			goto out_subsys;
 	}
@@ -701,13 +706,14 @@
 	if (dev->parent && device_is_not_partition(dev))
 		sysfs_remove_link(&dev->kobj, "device");
 out_busid:
-	if (dev->kobj.parent != &dev->class->subsys.kobj &&
+	if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
 	    device_is_not_partition(dev))
-		sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
+		sysfs_remove_link(&dev->class->p->class_subsys.kobj,
+				  dev->bus_id);
 #else
 	/* link in the class directory pointing to the device */
-	error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
-				  dev->bus_id);
+	error = sysfs_create_link(&dev->class->p->class_subsys.kobj,
+				  &dev->kobj, dev->bus_id);
 	if (error)
 		goto out_subsys;
 
@@ -720,7 +726,7 @@
 	return 0;
 
 out_busid:
-	sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
+	sysfs_remove_link(&dev->class->p->class_subsys.kobj, dev->bus_id);
 #endif
 
 out_subsys:
@@ -746,14 +752,15 @@
 		sysfs_remove_link(&dev->kobj, "device");
 	}
 
-	if (dev->kobj.parent != &dev->class->subsys.kobj &&
+	if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
 	    device_is_not_partition(dev))
-		sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
+		sysfs_remove_link(&dev->class->p->class_subsys.kobj,
+				  dev->bus_id);
 #else
 	if (dev->parent && device_is_not_partition(dev))
 		sysfs_remove_link(&dev->kobj, "device");
 
-	sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
+	sysfs_remove_link(&dev->class->p->class_subsys.kobj, dev->bus_id);
 #endif
 
 	sysfs_remove_link(&dev->kobj, "subsystem");
@@ -776,6 +783,54 @@
 EXPORT_SYMBOL_GPL(dev_set_name);
 
 /**
+ * device_to_dev_kobj - select a /sys/dev/ directory for the device
+ * @dev: device
+ *
+ * By default we select char/ for new entries.  Setting class->dev_obj
+ * to NULL prevents an entry from being created.  class->dev_kobj must
+ * be set (or cleared) before any devices are registered to the class
+ * otherwise device_create_sys_dev_entry() and
+ * device_remove_sys_dev_entry() will disagree about the the presence
+ * of the link.
+ */
+static struct kobject *device_to_dev_kobj(struct device *dev)
+{
+	struct kobject *kobj;
+
+	if (dev->class)
+		kobj = dev->class->dev_kobj;
+	else
+		kobj = sysfs_dev_char_kobj;
+
+	return kobj;
+}
+
+static int device_create_sys_dev_entry(struct device *dev)
+{
+	struct kobject *kobj = device_to_dev_kobj(dev);
+	int error = 0;
+	char devt_str[15];
+
+	if (kobj) {
+		format_dev_t(devt_str, dev->devt);
+		error = sysfs_create_link(kobj, &dev->kobj, devt_str);
+	}
+
+	return error;
+}
+
+static void device_remove_sys_dev_entry(struct device *dev)
+{
+	struct kobject *kobj = device_to_dev_kobj(dev);
+	char devt_str[15];
+
+	if (kobj) {
+		format_dev_t(devt_str, dev->devt);
+		sysfs_remove_link(kobj, devt_str);
+	}
+}
+
+/**
  * device_add - add device to device hierarchy.
  * @dev: device.
  *
@@ -829,6 +884,10 @@
 		error = device_create_file(dev, &devt_attr);
 		if (error)
 			goto ueventattrError;
+
+		error = device_create_sys_dev_entry(dev);
+		if (error)
+			goto devtattrError;
 	}
 
 	error = device_add_class_symlinks(dev);
@@ -849,15 +908,16 @@
 		klist_add_tail(&dev->knode_parent, &parent->klist_children);
 
 	if (dev->class) {
-		down(&dev->class->sem);
+		mutex_lock(&dev->class->p->class_mutex);
 		/* tie the class to the device */
-		list_add_tail(&dev->node, &dev->class->devices);
+		list_add_tail(&dev->node, &dev->class->p->class_devices);
 
 		/* notify any interfaces that the device is here */
-		list_for_each_entry(class_intf, &dev->class->interfaces, node)
+		list_for_each_entry(class_intf,
+				    &dev->class->p->class_interfaces, node)
 			if (class_intf->add_dev)
 				class_intf->add_dev(dev, class_intf);
-		up(&dev->class->sem);
+		mutex_unlock(&dev->class->p->class_mutex);
 	}
  Done:
 	put_device(dev);
@@ -873,6 +933,9 @@
 	device_remove_class_symlinks(dev);
  SymlinkError:
 	if (MAJOR(dev->devt))
+		device_remove_sys_dev_entry(dev);
+ devtattrError:
+	if (MAJOR(dev->devt))
 		device_remove_file(dev, &devt_attr);
  ueventattrError:
 	device_remove_file(dev, &uevent_attr);
@@ -948,19 +1011,22 @@
 	device_pm_remove(dev);
 	if (parent)
 		klist_del(&dev->knode_parent);
-	if (MAJOR(dev->devt))
+	if (MAJOR(dev->devt)) {
+		device_remove_sys_dev_entry(dev);
 		device_remove_file(dev, &devt_attr);
+	}
 	if (dev->class) {
 		device_remove_class_symlinks(dev);
 
-		down(&dev->class->sem);
+		mutex_lock(&dev->class->p->class_mutex);
 		/* notify any interfaces that the device is now gone */
-		list_for_each_entry(class_intf, &dev->class->interfaces, node)
+		list_for_each_entry(class_intf,
+				    &dev->class->p->class_interfaces, node)
 			if (class_intf->remove_dev)
 				class_intf->remove_dev(dev, class_intf);
 		/* remove the device from the class list */
 		list_del_init(&dev->node);
-		up(&dev->class->sem);
+		mutex_unlock(&dev->class->p->class_mutex);
 	}
 	device_remove_file(dev, &uevent_attr);
 	device_remove_attrs(dev);
@@ -1074,7 +1140,25 @@
 	devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
 	if (!devices_kset)
 		return -ENOMEM;
+	dev_kobj = kobject_create_and_add("dev", NULL);
+	if (!dev_kobj)
+		goto dev_kobj_err;
+	sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj);
+	if (!sysfs_dev_block_kobj)
+		goto block_kobj_err;
+	sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj);
+	if (!sysfs_dev_char_kobj)
+		goto char_kobj_err;
+
 	return 0;
+
+ char_kobj_err:
+	kobject_put(sysfs_dev_block_kobj);
+ block_kobj_err:
+	kobject_put(dev_kobj);
+ dev_kobj_err:
+	kset_unregister(devices_kset);
+	return -ENOMEM;
 }
 
 EXPORT_SYMBOL_GPL(device_for_each_child);
@@ -1158,7 +1242,7 @@
 EXPORT_SYMBOL_GPL(device_create_vargs);
 
 /**
- * device_create_drvdata - creates a device and registers it with sysfs
+ * device_create - creates a device and registers it with sysfs
  * @class: pointer to the struct class that this device should be registered to
  * @parent: pointer to the parent struct device of this new device, if any
  * @devt: the dev_t for the char device to be added
@@ -1179,11 +1263,8 @@
  * Note: the struct class passed to this function must have previously
  * been created with a call to class_create().
  */
-struct device *device_create_drvdata(struct class *class,
-				     struct device *parent,
-				     dev_t devt,
-				     void *drvdata,
-				     const char *fmt, ...)
+struct device *device_create(struct class *class, struct device *parent,
+			     dev_t devt, void *drvdata, const char *fmt, ...)
 {
 	va_list vargs;
 	struct device *dev;
@@ -1193,40 +1274,6 @@
 	va_end(vargs);
 	return dev;
 }
-EXPORT_SYMBOL_GPL(device_create_drvdata);
-
-/**
- * device_create - creates a device and registers it with sysfs
- * @class: pointer to the struct class that this device should be registered to
- * @parent: pointer to the parent struct device of this new device, if any
- * @devt: the dev_t for the char device to be added
- * @fmt: string for the device's name
- *
- * This function can be used by char device classes.  A struct device
- * will be created in sysfs, registered to the specified class.
- *
- * A "dev" file will be created, showing the dev_t for the device, if
- * the dev_t is not 0,0.
- * If a pointer to a parent struct device is passed in, the newly created
- * struct device will be a child of that device in sysfs.
- * The pointer to the struct device will be returned from the call.
- * Any further sysfs files that might be required can be created using this
- * pointer.
- *
- * Note: the struct class passed to this function must have previously
- * been created with a call to class_create().
- */
-struct device *device_create(struct class *class, struct device *parent,
-			     dev_t devt, const char *fmt, ...)
-{
-	va_list vargs;
-	struct device *dev;
-
-	va_start(vargs, fmt);
-	dev = device_create_vargs(class, parent, devt, NULL, fmt, vargs);
-	va_end(vargs);
-	return dev;
-}
 EXPORT_SYMBOL_GPL(device_create);
 
 static int __match_devt(struct device *dev, void *data)
@@ -1248,7 +1295,7 @@
 {
 	struct device *dev;
 
-	dev = class_find_device(class, &devt, __match_devt);
+	dev = class_find_device(class, NULL, &devt, __match_devt);
 	if (dev) {
 		put_device(dev);
 		device_unregister(dev);
@@ -1298,8 +1345,9 @@
 	if (old_class_name) {
 		new_class_name = make_class_name(dev->class->name, &dev->kobj);
 		if (new_class_name) {
-			error = sysfs_create_link(&dev->parent->kobj,
-						  &dev->kobj, new_class_name);
+			error = sysfs_create_link_nowarn(&dev->parent->kobj,
+							 &dev->kobj,
+							 new_class_name);
 			if (error)
 				goto out;
 			sysfs_remove_link(&dev->parent->kobj, old_class_name);
@@ -1307,11 +1355,12 @@
 	}
 #else
 	if (dev->class) {
-		error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
-					  dev->bus_id);
+		error = sysfs_create_link_nowarn(&dev->class->p->class_subsys.kobj,
+						 &dev->kobj, dev->bus_id);
 		if (error)
 			goto out;
-		sysfs_remove_link(&dev->class->subsys.kobj, old_device_name);
+		sysfs_remove_link(&dev->class->p->class_subsys.kobj,
+				  old_device_name);
 	}
 #endif
 
@@ -1447,4 +1496,7 @@
 			dev->driver->shutdown(dev);
 		}
 	}
+	kobject_put(sysfs_dev_char_kobj);
+	kobject_put(sysfs_dev_block_kobj);
+	kobject_put(dev_kobj);
 }
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 5000402a..64f5d54 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -21,15 +21,16 @@
 static DEFINE_PER_CPU(struct sys_device *, cpu_sys_devices);
 
 #ifdef CONFIG_HOTPLUG_CPU
-static ssize_t show_online(struct sys_device *dev, char *buf)
+static ssize_t show_online(struct sys_device *dev, struct sysdev_attribute *attr,
+			   char *buf)
 {
 	struct cpu *cpu = container_of(dev, struct cpu, sysdev);
 
 	return sprintf(buf, "%u\n", !!cpu_online(cpu->sysdev.id));
 }
 
-static ssize_t __ref store_online(struct sys_device *dev, const char *buf,
-			    size_t count)
+static ssize_t __ref store_online(struct sys_device *dev, struct sysdev_attribute *attr,
+				 const char *buf, size_t count)
 {
 	struct cpu *cpu = container_of(dev, struct cpu, sysdev);
 	ssize_t ret;
@@ -80,7 +81,8 @@
 #ifdef CONFIG_KEXEC
 #include <linux/kexec.h>
 
-static ssize_t show_crash_notes(struct sys_device *dev, char *buf)
+static ssize_t show_crash_notes(struct sys_device *dev, struct sysdev_attribute *attr,
+				char *buf)
 {
 	struct cpu *cpu = container_of(dev, struct cpu, sysdev);
 	ssize_t rc;
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 937e825..4d4e0e7 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -92,7 +92,8 @@
  * uses.
  */
 
-static ssize_t show_mem_phys_index(struct sys_device *dev, char *buf)
+static ssize_t show_mem_phys_index(struct sys_device *dev,
+			struct sysdev_attribute *attr, char *buf)
 {
 	struct memory_block *mem =
 		container_of(dev, struct memory_block, sysdev);
@@ -102,7 +103,8 @@
 /*
  * online, offline, going offline, etc.
  */
-static ssize_t show_mem_state(struct sys_device *dev, char *buf)
+static ssize_t show_mem_state(struct sys_device *dev,
+			struct sysdev_attribute *attr, char *buf)
 {
 	struct memory_block *mem =
 		container_of(dev, struct memory_block, sysdev);
@@ -217,7 +219,8 @@
 }
 
 static ssize_t
-store_mem_state(struct sys_device *dev, const char *buf, size_t count)
+store_mem_state(struct sys_device *dev,
+		struct sysdev_attribute *attr, const char *buf, size_t count)
 {
 	struct memory_block *mem;
 	unsigned int phys_section_nr;
@@ -248,7 +251,8 @@
  * s.t. if I offline all of these sections I can then
  * remove the physical device?
  */
-static ssize_t show_phys_device(struct sys_device *dev, char *buf)
+static ssize_t show_phys_device(struct sys_device *dev,
+				struct sysdev_attribute *attr, char *buf)
 {
 	struct memory_block *mem =
 		container_of(dev, struct memory_block, sysdev);
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 0f867a0..5116b78 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -36,11 +36,13 @@
 	return len;
 }
 
-static inline ssize_t node_read_cpumask(struct sys_device *dev, char *buf)
+static inline ssize_t node_read_cpumask(struct sys_device *dev,
+				struct sysdev_attribute *attr, char *buf)
 {
 	return node_read_cpumap(dev, 0, buf);
 }
-static inline ssize_t node_read_cpulist(struct sys_device *dev, char *buf)
+static inline ssize_t node_read_cpulist(struct sys_device *dev,
+				struct sysdev_attribute *attr, char *buf)
 {
 	return node_read_cpumap(dev, 1, buf);
 }
@@ -49,7 +51,8 @@
 static SYSDEV_ATTR(cpulist, S_IRUGO, node_read_cpulist, NULL);
 
 #define K(x) ((x) << (PAGE_SHIFT - 10))
-static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
+static ssize_t node_read_meminfo(struct sys_device * dev,
+			struct sysdev_attribute *attr, char * buf)
 {
 	int n;
 	int nid = dev->id;
@@ -112,7 +115,8 @@
 #undef K
 static SYSDEV_ATTR(meminfo, S_IRUGO, node_read_meminfo, NULL);
 
-static ssize_t node_read_numastat(struct sys_device * dev, char * buf)
+static ssize_t node_read_numastat(struct sys_device * dev,
+				struct sysdev_attribute *attr, char * buf)
 {
 	return sprintf(buf,
 		       "numa_hit %lu\n"
@@ -130,7 +134,8 @@
 }
 static SYSDEV_ATTR(numastat, S_IRUGO, node_read_numastat, NULL);
 
-static ssize_t node_read_distance(struct sys_device * dev, char * buf)
+static ssize_t node_read_distance(struct sys_device * dev,
+			struct sysdev_attribute *attr, char * buf)
 {
 	int nid = dev->id;
 	int len = 0;
diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c
index 9b1b20b..2aa6e8f 100644
--- a/drivers/base/power/trace.c
+++ b/drivers/base/power/trace.c
@@ -194,7 +194,7 @@
 		struct device * dev = to_device(entry);
 		unsigned int hash = hash_string(DEVSEED, dev->bus_id, DEVHASH);
 		if (hash == value) {
-			printk("  hash matches device %s\n", dev->bus_id);
+			dev_info(dev, "hash matches\n");
 			match++;
 		}
 		entry = entry->prev;
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 358bb0b..40fc14f 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -36,7 +36,7 @@
 	struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr);
 
 	if (sysdev_attr->show)
-		return sysdev_attr->show(sysdev, buffer);
+		return sysdev_attr->show(sysdev, sysdev_attr, buffer);
 	return -EIO;
 }
 
@@ -49,7 +49,7 @@
 	struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr);
 
 	if (sysdev_attr->store)
-		return sysdev_attr->store(sysdev, buffer, count);
+		return sysdev_attr->store(sysdev, sysdev_attr, buffer, count);
 	return -EIO;
 }
 
@@ -130,8 +130,8 @@
 
 int sysdev_class_register(struct sysdev_class * cls)
 {
-	pr_debug("Registering sysdev class '%s'\n",
-		 kobject_name(&cls->kset.kobj));
+	pr_debug("Registering sysdev class '%s'\n", cls->name);
+
 	INIT_LIST_HEAD(&cls->drivers);
 	memset(&cls->kset.kobj, 0x00, sizeof(struct kobject));
 	cls->kset.kobj.parent = &system_kset->kobj;
@@ -241,7 +241,8 @@
 	if (!cls)
 		return -EINVAL;
 
-	pr_debug("Registering sys device '%s'\n", kobject_name(&sysdev->kobj));
+	pr_debug("Registering sys device of class '%s'\n",
+		 kobject_name(&cls->kset.kobj));
 
 	/* initialize the kobject to 0, in case it had previously been used */
 	memset(&sysdev->kobj, 0x00, sizeof(struct kobject));
@@ -257,6 +258,9 @@
 	if (!error) {
 		struct sysdev_driver * drv;
 
+		pr_debug("Registering sys device '%s'\n",
+			 kobject_name(&sysdev->kobj));
+
 		mutex_lock(&sysdev_drivers_lock);
 		/* Generic notification is implicit, because it's that
 		 * code that should have called us.
@@ -269,6 +273,7 @@
 		}
 		mutex_unlock(&sysdev_drivers_lock);
 	}
+
 	kobject_uevent(&sysdev->kobj, KOBJ_ADD);
 	return error;
 }
@@ -474,3 +479,52 @@
 
 EXPORT_SYMBOL_GPL(sysdev_register);
 EXPORT_SYMBOL_GPL(sysdev_unregister);
+
+#define to_ext_attr(x) container_of(x, struct sysdev_ext_attribute, attr)
+
+ssize_t sysdev_store_ulong(struct sys_device *sysdev,
+			   struct sysdev_attribute *attr,
+			   const char *buf, size_t size)
+{
+	struct sysdev_ext_attribute *ea = to_ext_attr(attr);
+	char *end;
+	unsigned long new = simple_strtoul(buf, &end, 0);
+	if (end == buf)
+		return -EINVAL;
+	*(unsigned long *)(ea->var) = new;
+	return end - buf;
+}
+EXPORT_SYMBOL_GPL(sysdev_store_ulong);
+
+ssize_t sysdev_show_ulong(struct sys_device *sysdev,
+			  struct sysdev_attribute *attr,
+			  char *buf)
+{
+	struct sysdev_ext_attribute *ea = to_ext_attr(attr);
+	return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var));
+}
+EXPORT_SYMBOL_GPL(sysdev_show_ulong);
+
+ssize_t sysdev_store_int(struct sys_device *sysdev,
+			   struct sysdev_attribute *attr,
+			   const char *buf, size_t size)
+{
+	struct sysdev_ext_attribute *ea = to_ext_attr(attr);
+	char *end;
+	long new = simple_strtol(buf, &end, 0);
+	if (end == buf || new > INT_MAX || new < INT_MIN)
+		return -EINVAL;
+	*(int *)(ea->var) = new;
+	return end - buf;
+}
+EXPORT_SYMBOL_GPL(sysdev_store_int);
+
+ssize_t sysdev_show_int(struct sys_device *sysdev,
+			  struct sysdev_attribute *attr,
+			  char *buf)
+{
+	struct sysdev_ext_attribute *ea = to_ext_attr(attr);
+	return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var));
+}
+EXPORT_SYMBOL_GPL(sysdev_show_int);
+
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index 3f6d9b0..199cd97 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -34,7 +34,8 @@
 static SYSDEV_ATTR(_name, 0444, show_##_name, NULL)
 
 #define define_id_show_func(name)				\
-static ssize_t show_##name(struct sys_device *dev, char *buf)	\
+static ssize_t show_##name(struct sys_device *dev,		\
+		struct sysdev_attribute *attr, char *buf)	\
 {								\
 	unsigned int cpu = dev->id;				\
 	return sprintf(buf, "%d\n", topology_##name(cpu));	\
@@ -59,14 +60,17 @@
 
 #ifdef arch_provides_topology_pointers
 #define define_siblings_show_map(name)					\
-static ssize_t show_##name(struct sys_device *dev, char *buf)	\
+static ssize_t show_##name(struct sys_device *dev,			\
+			   struct sysdev_attribute *attr, char *buf)	\
 {									\
 	unsigned int cpu = dev->id;					\
 	return show_cpumap(0, &(topology_##name(cpu)), buf);		\
 }
 
 #define define_siblings_show_list(name)					\
-static ssize_t show_##name##_list(struct sys_device *dev, char *buf) \
+static ssize_t show_##name##_list(struct sys_device *dev,		\
+				  struct sysdev_attribute *attr,	\
+				  char *buf)				\
 {									\
 	unsigned int cpu = dev->id;					\
 	return show_cpumap(1, &(topology_##name(cpu)), buf);		\
@@ -74,7 +78,8 @@
 
 #else
 #define define_siblings_show_map(name)					\
-static ssize_t show_##name(struct sys_device *dev, char *buf)	\
+static ssize_t show_##name(struct sys_device *dev,			\
+			   struct sysdev_attribute *attr, char *buf)	\
 {									\
 	unsigned int cpu = dev->id;					\
 	cpumask_t mask = topology_##name(cpu);				\
@@ -82,7 +87,9 @@
 }
 
 #define define_siblings_show_list(name)					\
-static ssize_t show_##name##_list(struct sys_device *dev, char *buf) \
+static ssize_t show_##name##_list(struct sys_device *dev,		\
+				  struct sysdev_attribute *attr,	\
+				  char *buf)				\
 {									\
 	unsigned int cpu = dev->id;					\
 	cpumask_t mask = topology_##name(cpu);				\
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index d1de68a..c04440c 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -277,8 +277,9 @@
 		return PTR_ERR(aoe_class);
 	}
 	for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
-		device_create(aoe_class, NULL,
-			      MKDEV(AOE_MAJOR, chardevs[i].minor), chardevs[i].name);
+		device_create_drvdata(aoe_class, NULL,
+				      MKDEV(AOE_MAJOR, chardevs[i].minor),
+				      NULL, chardevs[i].name);
 
 	return 0;
 }
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index 9d92636..d731ca4 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -686,8 +686,9 @@
 	for (unit = 0; unit < PG_UNITS; unit++) {
 		struct pg *dev = &devices[unit];
 		if (dev->present)
-			device_create(pg_class, NULL, MKDEV(major, unit),
-				      "pg%u", unit);
+			device_create_drvdata(pg_class, NULL,
+					      MKDEV(major, unit), NULL,
+					      "pg%u", unit);
 	}
 	err = 0;
 	goto out;
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 5c74c35..673b8b2 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -979,10 +979,12 @@
 
 	for (unit = 0; unit < PT_UNITS; unit++)
 		if (pt[unit].present) {
-			device_create(pt_class, NULL, MKDEV(major, unit),
-				      "pt%d", unit);
-			device_create(pt_class, NULL, MKDEV(major, unit + 128),
-				      "pt%dn", unit);
+			device_create_drvdata(pt_class, NULL,
+					      MKDEV(major, unit), NULL,
+					      "pt%d", unit);
+			device_create_drvdata(pt_class, NULL,
+					      MKDEV(major, unit + 128), NULL,
+					      "pt%dn", unit);
 		}
 	goto out;
 
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 45bee91..158eed4 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -303,7 +303,9 @@
 static void pkt_sysfs_dev_new(struct pktcdvd_device *pd)
 {
 	if (class_pktcdvd) {
-		pd->dev = device_create(class_pktcdvd, NULL, pd->pkt_dev, "%s", pd->name);
+		pd->dev = device_create_drvdata(class_pktcdvd, NULL,
+						pd->pkt_dev, NULL,
+						"%s", pd->name);
 		if (IS_ERR(pd->dev))
 			pd->dev = NULL;
 	}
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 650e6b4..e0bbbfb 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -300,16 +300,6 @@
 	  and compile this driver as kernel loadable module which will be
 	  called specialix.
 
-config SPECIALIX_RTSCTS
-	bool "Specialix DTR/RTS pin is RTS"
-	depends on SPECIALIX
-	help
-	  The Specialix IO8+ card can only support either RTS or DTR. If you
-	  say N here, the driver will use the pin as "DTR" when the tty is in
-	  software handshake mode.  If you say Y here or hardware handshake is
-	  on, it will always be RTS.  Read the file
-	  <file:Documentation/specialix.txt> for more information.
-
 config SX
 	tristate "Specialix SX (and SI) card support"
 	depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA)
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 0e0d12a..dc5a327 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -7,7 +7,7 @@
 #
 FONTMAPFILE = cp437.uni
 
-obj-y	 += mem.o random.o tty_io.o n_tty.o tty_ioctl.o
+obj-y	 += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o 
 
 obj-$(CONFIG_LEGACY_PTYS)	+= pty.o
 obj-$(CONFIG_UNIX98_PTYS)	+= pty.o
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 37457e5..3530ff4 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -1248,7 +1248,7 @@
 /*
  * rs_break() --- routine which turns the break handling on or off
  */
-static void rs_break(struct tty_struct *tty, int break_state)
+static int rs_break(struct tty_struct *tty, int break_state)
 {
 	struct async_struct * info = (struct async_struct *)tty->driver_data;
 	unsigned long flags;
@@ -1263,6 +1263,7 @@
 	  custom.adkcon = AC_UARTBRK;
 	mb();
 	local_irq_restore(flags);
+	return 0;
 }
 
 
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index e991dc85..fe6d774 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -3700,14 +3700,15 @@
 /*
  * cy_break() --- routine which turns the break handling on or off
  */
-static void cy_break(struct tty_struct *tty, int break_state)
+static int cy_break(struct tty_struct *tty, int break_state)
 {
 	struct cyclades_port *info = tty->driver_data;
 	struct cyclades_card *card;
 	unsigned long flags;
+	int retval = 0;
 
 	if (serial_paranoia_check(info, tty->name, "cy_break"))
-		return;
+		return -EINVAL;
 
 	card = info->card;
 
@@ -3736,8 +3737,6 @@
 			}
 		}
 	} else {
-		int retval;
-
 		if (break_state == -1) {
 			retval = cyz_issue_cmd(card,
 				info->line - card->first_line,
@@ -3758,6 +3757,7 @@
 		}
 	}
 	spin_unlock_irqrestore(&card->card_lock, flags);
+	return retval;
 }				/* cy_break */
 
 static int get_mon_info(struct cyclades_port *info,
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index b9a30c3..33c466a 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -500,7 +500,8 @@
 		err = PTR_ERR(dsp56k_class);
 		goto out_chrdev;
 	}
-	device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), "dsp56k");
+	device_create_drvdata(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0),
+			      NULL, "dsp56k");
 
 	printk(banner);
 	goto out;
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index ac9995f..456e4ed 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -184,9 +184,8 @@
 static void pc_start(struct tty_struct *);
 static void pc_throttle(struct tty_struct *tty);
 static void pc_unthrottle(struct tty_struct *tty);
-static void digi_send_break(struct channel *ch, int msec);
+static int pc_send_break(struct tty_struct *tty, int msec);
 static void setup_empty_event(struct tty_struct *tty, struct channel *ch);
-static void epca_setup(char *, int *);
 
 static int pc_write(struct tty_struct *, const unsigned char *, int);
 static int pc_init(void);
@@ -1040,6 +1039,7 @@
 	.throttle = pc_throttle,
 	.unthrottle = pc_unthrottle,
 	.hangup = pc_hangup,
+	.break_ctl = pc_send_break
 };
 
 static int info_open(struct tty_struct *tty, struct file *filp)
@@ -1132,7 +1132,7 @@
 	pc_driver->init_termios.c_lflag = 0;
 	pc_driver->init_termios.c_ispeed = 9600;
 	pc_driver->init_termios.c_ospeed = 9600;
-	pc_driver->flags = TTY_DRIVER_REAL_RAW;
+	pc_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_HARDWARE_BREAK;
 	tty_set_operations(pc_driver, &pc_ops);
 
 	pc_info->owner = THIS_MODULE;
@@ -2177,7 +2177,6 @@
 					unsigned int cmd, unsigned long arg)
 {
 	digiflow_t dflow;
-	int retval;
 	unsigned long flags;
 	unsigned int mflag, mstat;
 	unsigned char startc, stopc;
@@ -2189,37 +2188,7 @@
 		bc = ch->brdchan;
 	else
 		return -EINVAL;
-	/*
-	 * For POSIX compliance we need to add more ioctls. See tty_ioctl.c in
-	 * /usr/src/linux/drivers/char for a good example. In particular think
-	 * about adding TCSETAF, TCSETAW, TCSETA, TCSETSF, TCSETSW, TCSETS.
-	 */
 	switch (cmd) {
-	case TCSBRK:	/* SVID version: non-zero arg --> no break */
-		retval = tty_check_change(tty);
-		if (retval)
-			return retval;
-		/* Setup an event to indicate when the transmit
-		   buffer empties */
-		spin_lock_irqsave(&epca_lock, flags);
-		setup_empty_event(tty, ch);
-		spin_unlock_irqrestore(&epca_lock, flags);
-		tty_wait_until_sent(tty, 0);
-		if (!arg)
-			digi_send_break(ch, HZ / 4);    /* 1/4 second */
-		return 0;
-	case TCSBRKP:	/* support for POSIX tcsendbreak() */
-		retval = tty_check_change(tty);
-		if (retval)
-			return retval;
-		/* Setup an event to indicate when the transmit buffer
-		   empties */
-		spin_lock_irqsave(&epca_lock, flags);
-		setup_empty_event(tty, ch);
-		spin_unlock_irqrestore(&epca_lock, flags);
-		tty_wait_until_sent(tty, 0);
-		digi_send_break(ch, arg ? arg*(HZ/10) : HZ/4);
-		return 0;
 	case TIOCMODG:
 		mflag = pc_tiocmget(tty, file);
 		if (put_user(mflag, (unsigned long __user *)argp))
@@ -2505,10 +2474,14 @@
 	}
 }
 
-static void digi_send_break(struct channel *ch, int msec)
+static int pc_send_break(struct tty_struct *tty, int msec)
 {
+	struct channel *ch = (struct channel *) tty->driver_data;
 	unsigned long flags;
 
+	if (msec == -1)
+		return -EOPNOTSUPP;
+
 	spin_lock_irqsave(&epca_lock, flags);
 	globalwinon(ch);
 	/*
@@ -2521,6 +2494,7 @@
 	fepcmd(ch, SENDBREAK, msec, 0, 10, 0);
 	memoff(ch);
 	spin_unlock_irqrestore(&epca_lock, flags);
+	return 0;
 }
 
 /* Caller MUST hold the lock */
@@ -2538,7 +2512,8 @@
 	memoff(ch);
 }
 
-static void epca_setup(char *str, int *ints)
+#ifndef MODULE
+static void __init epca_setup(char *str, int *ints)
 {
 	struct board_info board;
 	int               index, loop, last;
@@ -2792,6 +2767,17 @@
 	num_cards++;
 }
 
+static int __init epca_real_setup(char *str)
+{
+	int ints[11];
+
+	epca_setup(get_options(str, 11, ints), ints);
+	return 1;
+}
+
+__setup("digiepca", epca_real_setup);
+#endif
+
 enum epic_board_types {
 	brd_xr = 0,
 	brd_xem,
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index 2eaf09f..7f077c0 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -1725,13 +1725,13 @@
 /*
  * rs_break() --- routine which turns the break handling on or off
  */
-static void esp_break(struct tty_struct *tty, int break_state)
+static int esp_break(struct tty_struct *tty, int break_state)
 {
 	struct esp_struct *info = tty->driver_data;
 	unsigned long flags;
 
 	if (serial_paranoia_check(info, tty->name, "esp_break"))
-		return;
+		return -EINVAL;
 
 	if (break_state == -1) {
 		spin_lock_irqsave(&info->lock, flags);
@@ -1747,6 +1747,7 @@
 		serial_out(info, UART_ESI_CMD2, 0x00);
 		spin_unlock_irqrestore(&info->lock, flags);
 	}
+	return 0;
 }
 
 static int rs_ioctl(struct tty_struct *tty, struct file *file,
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index efd0b4d..8822eca 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -59,6 +59,19 @@
 
 	  If unsure, say Y.
 
+config HW_RANDOM_N2RNG
+	tristate "Niagara2 Random Number Generator support"
+	depends on HW_RANDOM && SPARC64
+	default HW_RANDOM
+	---help---
+	  This driver provides kernel-side support for the Random Number
+	  Generator hardware found on Niagara2 cpus.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called n2-rng.
+
+	  If unsure, say Y.
+
 config HW_RANDOM_VIA
 	tristate "VIA HW Random Number Generator support"
 	depends on HW_RANDOM && X86_32
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index b4940dd..b6effb7 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -7,6 +7,8 @@
 obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o
 obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o
 obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o
+obj-$(CONFIG_HW_RANDOM_N2RNG) += n2-rng.o
+n2-rng-y := n2-drv.o n2-asm.o
 obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o
 obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o
 obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o
diff --git a/drivers/char/hw_random/n2-asm.S b/drivers/char/hw_random/n2-asm.S
new file mode 100644
index 0000000..9b6eb5c
--- /dev/null
+++ b/drivers/char/hw_random/n2-asm.S
@@ -0,0 +1,79 @@
+/* n2-asm.S: Niagara2 RNG hypervisor call assembler.
+ *
+ * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
+ */
+#include <linux/linkage.h>
+#include <asm/hypervisor.h>
+#include "n2rng.h"
+
+	.text
+
+ENTRY(sun4v_rng_get_diag_ctl)
+	mov	HV_FAST_RNG_GET_DIAG_CTL, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+ENDPROC(sun4v_rng_get_diag_ctl)
+
+ENTRY(sun4v_rng_ctl_read_v1)
+	mov	%o1, %o3
+	mov	%o2, %o4
+	mov	HV_FAST_RNG_CTL_READ, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%o3]
+	retl
+	 stx	%o2, [%o4]
+ENDPROC(sun4v_rng_ctl_read_v1)
+
+ENTRY(sun4v_rng_ctl_read_v2)
+	save	%sp, -192, %sp
+	mov	%i0, %o0
+	mov	%i1, %o1
+	mov	HV_FAST_RNG_CTL_READ, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%i2]
+	stx	%o2, [%i3]
+	stx	%o3, [%i4]
+	stx	%o4, [%i5]
+	ret
+	restore	%g0, %o0, %o0
+ENDPROC(sun4v_rng_ctl_read_v2)
+
+ENTRY(sun4v_rng_ctl_write_v1)
+	mov	%o3, %o4
+	mov	HV_FAST_RNG_CTL_WRITE, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 stx	%o1, [%o4]
+ENDPROC(sun4v_rng_ctl_write_v1)
+
+ENTRY(sun4v_rng_ctl_write_v2)
+	mov	HV_FAST_RNG_CTL_WRITE, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+ENDPROC(sun4v_rng_ctl_write_v2)
+
+ENTRY(sun4v_rng_data_read_diag_v1)
+	mov	%o2, %o4
+	mov	HV_FAST_RNG_DATA_READ_DIAG, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 stx	%o1, [%o4]
+ENDPROC(sun4v_rng_data_read_diag_v1)
+
+ENTRY(sun4v_rng_data_read_diag_v2)
+	mov	%o3, %o4
+	mov	HV_FAST_RNG_DATA_READ_DIAG, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 stx	%o1, [%o4]
+ENDPROC(sun4v_rng_data_read_diag_v2)
+
+ENTRY(sun4v_rng_data_read)
+	mov	%o1, %o4
+	mov	HV_FAST_RNG_DATA_READ, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 stx	%o1, [%o4]
+ENDPROC(sun4v_rng_data_read)
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c
new file mode 100644
index 0000000..5220f54
--- /dev/null
+++ b/drivers/char/hw_random/n2-drv.c
@@ -0,0 +1,771 @@
+/* n2-drv.c: Niagara-2 RNG driver.
+ *
+ * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/preempt.h>
+#include <linux/hw_random.h>
+
+#include <linux/of.h>
+#include <linux/of_device.h>
+
+#include <asm/hypervisor.h>
+
+#include "n2rng.h"
+
+#define DRV_MODULE_NAME		"n2rng"
+#define PFX DRV_MODULE_NAME	": "
+#define DRV_MODULE_VERSION	"0.1"
+#define DRV_MODULE_RELDATE	"May 15, 2008"
+
+static char version[] __devinitdata =
+	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+
+MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
+MODULE_DESCRIPTION("Niagara2 RNG driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+/* The Niagara2 RNG provides a 64-bit read-only random number
+ * register, plus a control register.  Access to the RNG is
+ * virtualized through the hypervisor so that both guests and control
+ * nodes can access the device.
+ *
+ * The entropy source consists of raw entropy sources, each
+ * constructed from a voltage controlled oscillator whose phase is
+ * jittered by thermal noise sources.
+ *
+ * The oscillator in each of the three raw entropy sources run at
+ * different frequencies.  Normally, all three generator outputs are
+ * gathered, xored together, and fed into a CRC circuit, the output of
+ * which is the 64-bit read-only register.
+ *
+ * Some time is necessary for all the necessary entropy to build up
+ * such that a full 64-bits of entropy are available in the register.
+ * In normal operating mode (RNG_CTL_LFSR is set), the chip implements
+ * an interlock which blocks register reads until sufficient entropy
+ * is available.
+ *
+ * A control register is provided for adjusting various aspects of RNG
+ * operation, and to enable diagnostic modes.  Each of the three raw
+ * entropy sources has an enable bit (RNG_CTL_ES{1,2,3}).  Also
+ * provided are fields for controlling the minimum time in cycles
+ * between read accesses to the register (RNG_CTL_WAIT, this controls
+ * the interlock described in the previous paragraph).
+ *
+ * The standard setting is to have the mode bit (RNG_CTL_LFSR) set,
+ * all three entropy sources enabled, and the interlock time set
+ * appropriately.
+ *
+ * The CRC polynomial used by the chip is:
+ *
+ * P(X) = x64 + x61 + x57 + x56 + x52 + x51 + x50 + x48 + x47 + x46 +
+ *        x43 + x42 + x41 + x39 + x38 + x37 + x35 + x32 + x28 + x25 +
+ *        x22 + x21 + x17 + x15 + x13 + x12 + x11 + x7 + x5 + x + 1
+ *
+ * The RNG_CTL_VCO value of each noise cell must be programmed
+ * seperately.  This is why 4 control register values must be provided
+ * to the hypervisor.  During a write, the hypervisor writes them all,
+ * one at a time, to the actual RNG_CTL register.  The first three
+ * values are used to setup the desired RNG_CTL_VCO for each entropy
+ * source, for example:
+ *
+ *	control 0: (1 << RNG_CTL_VCO_SHIFT) | RNG_CTL_ES1
+ *	control 1: (2 << RNG_CTL_VCO_SHIFT) | RNG_CTL_ES2
+ *	control 2: (3 << RNG_CTL_VCO_SHIFT) | RNG_CTL_ES3
+ *
+ * And then the fourth value sets the final chip state and enables
+ * desired.
+ */
+
+static int n2rng_hv_err_trans(unsigned long hv_err)
+{
+	switch (hv_err) {
+	case HV_EOK:
+		return 0;
+	case HV_EWOULDBLOCK:
+		return -EAGAIN;
+	case HV_ENOACCESS:
+		return -EPERM;
+	case HV_EIO:
+		return -EIO;
+	case HV_EBUSY:
+		return -EBUSY;
+	case HV_EBADALIGN:
+	case HV_ENORADDR:
+		return -EFAULT;
+	default:
+		return -EINVAL;
+	}
+}
+
+static unsigned long n2rng_generic_read_control_v2(unsigned long ra,
+						   unsigned long unit)
+{
+	unsigned long hv_err, state, ticks, watchdog_delta, watchdog_status;
+	int block = 0, busy = 0;
+
+	while (1) {
+		hv_err = sun4v_rng_ctl_read_v2(ra, unit, &state,
+					       &ticks,
+					       &watchdog_delta,
+					       &watchdog_status);
+		if (hv_err == HV_EOK)
+			break;
+
+		if (hv_err == HV_EBUSY) {
+			if (++busy >= N2RNG_BUSY_LIMIT)
+				break;
+
+			udelay(1);
+		} else if (hv_err == HV_EWOULDBLOCK) {
+			if (++block >= N2RNG_BLOCK_LIMIT)
+				break;
+
+			__delay(ticks);
+		} else
+			break;
+	}
+
+	return hv_err;
+}
+
+/* In multi-socket situations, the hypervisor might need to
+ * queue up the RNG control register write if it's for a unit
+ * that is on a cpu socket other than the one we are executing on.
+ *
+ * We poll here waiting for a successful read of that control
+ * register to make sure the write has been actually performed.
+ */
+static unsigned long n2rng_control_settle_v2(struct n2rng *np, int unit)
+{
+	unsigned long ra = __pa(&np->scratch_control[0]);
+
+	return n2rng_generic_read_control_v2(ra, unit);
+}
+
+static unsigned long n2rng_write_ctl_one(struct n2rng *np, int unit,
+					 unsigned long state,
+					 unsigned long control_ra,
+					 unsigned long watchdog_timeout,
+					 unsigned long *ticks)
+{
+	unsigned long hv_err;
+
+	if (np->hvapi_major == 1) {
+		hv_err = sun4v_rng_ctl_write_v1(control_ra, state,
+						watchdog_timeout, ticks);
+	} else {
+		hv_err = sun4v_rng_ctl_write_v2(control_ra, state,
+						watchdog_timeout, unit);
+		if (hv_err == HV_EOK)
+			hv_err = n2rng_control_settle_v2(np, unit);
+		*ticks = N2RNG_ACCUM_CYCLES_DEFAULT;
+	}
+
+	return hv_err;
+}
+
+static int n2rng_generic_read_data(unsigned long data_ra)
+{
+	unsigned long ticks, hv_err;
+	int block = 0, hcheck = 0;
+
+	while (1) {
+		hv_err = sun4v_rng_data_read(data_ra, &ticks);
+		if (hv_err == HV_EOK)
+			return 0;
+
+		if (hv_err == HV_EWOULDBLOCK) {
+			if (++block >= N2RNG_BLOCK_LIMIT)
+				return -EWOULDBLOCK;
+			__delay(ticks);
+		} else if (hv_err == HV_ENOACCESS) {
+			return -EPERM;
+		} else if (hv_err == HV_EIO) {
+			if (++hcheck >= N2RNG_HCHECK_LIMIT)
+				return -EIO;
+			udelay(10000);
+		} else
+			return -ENODEV;
+	}
+}
+
+static unsigned long n2rng_read_diag_data_one(struct n2rng *np,
+					      unsigned long unit,
+					      unsigned long data_ra,
+					      unsigned long data_len,
+					      unsigned long *ticks)
+{
+	unsigned long hv_err;
+
+	if (np->hvapi_major == 1) {
+		hv_err = sun4v_rng_data_read_diag_v1(data_ra, data_len, ticks);
+	} else {
+		hv_err = sun4v_rng_data_read_diag_v2(data_ra, data_len,
+						     unit, ticks);
+		if (!*ticks)
+			*ticks = N2RNG_ACCUM_CYCLES_DEFAULT;
+	}
+	return hv_err;
+}
+
+static int n2rng_generic_read_diag_data(struct n2rng *np,
+					unsigned long unit,
+					unsigned long data_ra,
+					unsigned long data_len)
+{
+	unsigned long ticks, hv_err;
+	int block = 0;
+
+	while (1) {
+		hv_err = n2rng_read_diag_data_one(np, unit,
+						  data_ra, data_len,
+						  &ticks);
+		if (hv_err == HV_EOK)
+			return 0;
+
+		if (hv_err == HV_EWOULDBLOCK) {
+			if (++block >= N2RNG_BLOCK_LIMIT)
+				return -EWOULDBLOCK;
+			__delay(ticks);
+		} else if (hv_err == HV_ENOACCESS) {
+			return -EPERM;
+		} else if (hv_err == HV_EIO) {
+			return -EIO;
+		} else
+			return -ENODEV;
+	}
+}
+
+
+static int n2rng_generic_write_control(struct n2rng *np,
+				       unsigned long control_ra,
+				       unsigned long unit,
+				       unsigned long state)
+{
+	unsigned long hv_err, ticks;
+	int block = 0, busy = 0;
+
+	while (1) {
+		hv_err = n2rng_write_ctl_one(np, unit, state, control_ra,
+					     np->wd_timeo, &ticks);
+		if (hv_err == HV_EOK)
+			return 0;
+
+		if (hv_err == HV_EWOULDBLOCK) {
+			if (++block >= N2RNG_BLOCK_LIMIT)
+				return -EWOULDBLOCK;
+			__delay(ticks);
+		} else if (hv_err == HV_EBUSY) {
+			if (++busy >= N2RNG_BUSY_LIMIT)
+				return -EBUSY;
+			udelay(1);
+		} else
+			return -ENODEV;
+	}
+}
+
+/* Just try to see if we can successfully access the control register
+ * of the RNG on the domain on which we are currently executing.
+ */
+static int n2rng_try_read_ctl(struct n2rng *np)
+{
+	unsigned long hv_err;
+	unsigned long x;
+
+	if (np->hvapi_major == 1) {
+		hv_err = sun4v_rng_get_diag_ctl();
+	} else {
+		/* We purposefully give invalid arguments, HV_NOACCESS
+		 * is higher priority than the errors we'd get from
+		 * these other cases, and that's the error we are
+		 * truly interested in.
+		 */
+		hv_err = sun4v_rng_ctl_read_v2(0UL, ~0UL, &x, &x, &x, &x);
+		switch (hv_err) {
+		case HV_EWOULDBLOCK:
+		case HV_ENOACCESS:
+			break;
+		default:
+			hv_err = HV_EOK;
+			break;
+		}
+	}
+
+	return n2rng_hv_err_trans(hv_err);
+}
+
+#define CONTROL_DEFAULT_BASE		\
+	((2 << RNG_CTL_ASEL_SHIFT) |	\
+	 (N2RNG_ACCUM_CYCLES_DEFAULT << RNG_CTL_WAIT_SHIFT) |	\
+	 RNG_CTL_LFSR)
+
+#define CONTROL_DEFAULT_0		\
+	(CONTROL_DEFAULT_BASE |		\
+	 (1 << RNG_CTL_VCO_SHIFT) |	\
+	 RNG_CTL_ES1)
+#define CONTROL_DEFAULT_1		\
+	(CONTROL_DEFAULT_BASE |		\
+	 (2 << RNG_CTL_VCO_SHIFT) |	\
+	 RNG_CTL_ES2)
+#define CONTROL_DEFAULT_2		\
+	(CONTROL_DEFAULT_BASE |		\
+	 (3 << RNG_CTL_VCO_SHIFT) |	\
+	 RNG_CTL_ES3)
+#define CONTROL_DEFAULT_3		\
+	(CONTROL_DEFAULT_BASE |		\
+	 RNG_CTL_ES1 | RNG_CTL_ES2 | RNG_CTL_ES3)
+
+static void n2rng_control_swstate_init(struct n2rng *np)
+{
+	int i;
+
+	np->flags |= N2RNG_FLAG_CONTROL;
+
+	np->health_check_sec = N2RNG_HEALTH_CHECK_SEC_DEFAULT;
+	np->accum_cycles = N2RNG_ACCUM_CYCLES_DEFAULT;
+	np->wd_timeo = N2RNG_WD_TIMEO_DEFAULT;
+
+	for (i = 0; i < np->num_units; i++) {
+		struct n2rng_unit *up = &np->units[i];
+
+		up->control[0] = CONTROL_DEFAULT_0;
+		up->control[1] = CONTROL_DEFAULT_1;
+		up->control[2] = CONTROL_DEFAULT_2;
+		up->control[3] = CONTROL_DEFAULT_3;
+	}
+
+	np->hv_state = HV_RNG_STATE_UNCONFIGURED;
+}
+
+static int n2rng_grab_diag_control(struct n2rng *np)
+{
+	int i, busy_count, err = -ENODEV;
+
+	busy_count = 0;
+	for (i = 0; i < 100; i++) {
+		err = n2rng_try_read_ctl(np);
+		if (err != -EAGAIN)
+			break;
+
+		if (++busy_count > 100) {
+			dev_err(&np->op->dev,
+				"Grab diag control timeout.\n");
+			return -ENODEV;
+		}
+
+		udelay(1);
+	}
+
+	return err;
+}
+
+static int n2rng_init_control(struct n2rng *np)
+{
+	int err = n2rng_grab_diag_control(np);
+
+	/* Not in the control domain, that's OK we are only a consumer
+	 * of the RNG data, we don't setup and program it.
+	 */
+	if (err == -EPERM)
+		return 0;
+	if (err)
+		return err;
+
+	n2rng_control_swstate_init(np);
+
+	return 0;
+}
+
+static int n2rng_data_read(struct hwrng *rng, u32 *data)
+{
+	struct n2rng *np = (struct n2rng *) rng->priv;
+	unsigned long ra = __pa(&np->test_data);
+	int len;
+
+	if (!(np->flags & N2RNG_FLAG_READY)) {
+		len = 0;
+	} else if (np->flags & N2RNG_FLAG_BUFFER_VALID) {
+		np->flags &= ~N2RNG_FLAG_BUFFER_VALID;
+		*data = np->buffer;
+		len = 4;
+	} else {
+		int err = n2rng_generic_read_data(ra);
+		if (!err) {
+			np->buffer = np->test_data >> 32;
+			*data = np->test_data & 0xffffffff;
+			len = 4;
+		} else {
+			dev_err(&np->op->dev, "RNG error, restesting\n");
+			np->flags &= ~N2RNG_FLAG_READY;
+			if (!(np->flags & N2RNG_FLAG_SHUTDOWN))
+				schedule_delayed_work(&np->work, 0);
+			len = 0;
+		}
+	}
+
+	return len;
+}
+
+/* On a guest node, just make sure we can read random data properly.
+ * If a control node reboots or reloads it's n2rng driver, this won't
+ * work during that time.  So we have to keep probing until the device
+ * becomes usable.
+ */
+static int n2rng_guest_check(struct n2rng *np)
+{
+	unsigned long ra = __pa(&np->test_data);
+
+	return n2rng_generic_read_data(ra);
+}
+
+static int n2rng_entropy_diag_read(struct n2rng *np, unsigned long unit,
+				   u64 *pre_control, u64 pre_state,
+				   u64 *buffer, unsigned long buf_len,
+				   u64 *post_control, u64 post_state)
+{
+	unsigned long post_ctl_ra = __pa(post_control);
+	unsigned long pre_ctl_ra = __pa(pre_control);
+	unsigned long buffer_ra = __pa(buffer);
+	int err;
+
+	err = n2rng_generic_write_control(np, pre_ctl_ra, unit, pre_state);
+	if (err)
+		return err;
+
+	err = n2rng_generic_read_diag_data(np, unit,
+					   buffer_ra, buf_len);
+
+	(void) n2rng_generic_write_control(np, post_ctl_ra, unit,
+					   post_state);
+
+	return err;
+}
+
+static u64 advance_polynomial(u64 poly, u64 val, int count)
+{
+	int i;
+
+	for (i = 0; i < count; i++) {
+		int highbit_set = ((s64)val < 0);
+
+		val <<= 1;
+		if (highbit_set)
+			val ^= poly;
+	}
+
+	return val;
+}
+
+static int n2rng_test_buffer_find(struct n2rng *np, u64 val)
+{
+	int i, count = 0;
+
+	/* Purposefully skip over the first word.  */
+	for (i = 1; i < SELFTEST_BUFFER_WORDS; i++) {
+		if (np->test_buffer[i] == val)
+			count++;
+	}
+	return count;
+}
+
+static void n2rng_dump_test_buffer(struct n2rng *np)
+{
+	int i;
+
+	for (i = 0; i < SELFTEST_BUFFER_WORDS; i++)
+		dev_err(&np->op->dev, "Test buffer slot %d [0x%016lx]\n",
+			i, np->test_buffer[i]);
+}
+
+static int n2rng_check_selftest_buffer(struct n2rng *np, unsigned long unit)
+{
+	u64 val = SELFTEST_VAL;
+	int err, matches, limit;
+
+	matches = 0;
+	for (limit = 0; limit < SELFTEST_LOOPS_MAX; limit++) {
+		matches += n2rng_test_buffer_find(np, val);
+		if (matches >= SELFTEST_MATCH_GOAL)
+			break;
+		val = advance_polynomial(SELFTEST_POLY, val, 1);
+	}
+
+	err = 0;
+	if (limit >= SELFTEST_LOOPS_MAX) {
+		err = -ENODEV;
+		dev_err(&np->op->dev, "Selftest failed on unit %lu\n", unit);
+		n2rng_dump_test_buffer(np);
+	} else
+		dev_info(&np->op->dev, "Selftest passed on unit %lu\n", unit);
+
+	return err;
+}
+
+static int n2rng_control_selftest(struct n2rng *np, unsigned long unit)
+{
+	int err;
+
+	np->test_control[0] = (0x2 << RNG_CTL_ASEL_SHIFT);
+	np->test_control[1] = (0x2 << RNG_CTL_ASEL_SHIFT);
+	np->test_control[2] = (0x2 << RNG_CTL_ASEL_SHIFT);
+	np->test_control[3] = ((0x2 << RNG_CTL_ASEL_SHIFT) |
+			       RNG_CTL_LFSR |
+			       ((SELFTEST_TICKS - 2) << RNG_CTL_WAIT_SHIFT));
+
+
+	err = n2rng_entropy_diag_read(np, unit, np->test_control,
+				      HV_RNG_STATE_HEALTHCHECK,
+				      np->test_buffer,
+				      sizeof(np->test_buffer),
+				      &np->units[unit].control[0],
+				      np->hv_state);
+	if (err)
+		return err;
+
+	return n2rng_check_selftest_buffer(np, unit);
+}
+
+static int n2rng_control_check(struct n2rng *np)
+{
+	int i;
+
+	for (i = 0; i < np->num_units; i++) {
+		int err = n2rng_control_selftest(np, i);
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
+/* The sanity checks passed, install the final configuration into the
+ * chip, it's ready to use.
+ */
+static int n2rng_control_configure_units(struct n2rng *np)
+{
+	int unit, err;
+
+	err = 0;
+	for (unit = 0; unit < np->num_units; unit++) {
+		struct n2rng_unit *up = &np->units[unit];
+		unsigned long ctl_ra = __pa(&up->control[0]);
+		int esrc;
+		u64 base;
+
+		base = ((np->accum_cycles << RNG_CTL_WAIT_SHIFT) |
+			(2 << RNG_CTL_ASEL_SHIFT) |
+			RNG_CTL_LFSR);
+
+		/* XXX This isn't the best.  We should fetch a bunch
+		 * XXX of words using each entropy source combined XXX
+		 * with each VCO setting, and see which combinations
+		 * XXX give the best random data.
+		 */
+		for (esrc = 0; esrc < 3; esrc++)
+			up->control[esrc] = base |
+				(esrc << RNG_CTL_VCO_SHIFT) |
+				(RNG_CTL_ES1 << esrc);
+
+		up->control[3] = base |
+			(RNG_CTL_ES1 | RNG_CTL_ES2 | RNG_CTL_ES3);
+
+		err = n2rng_generic_write_control(np, ctl_ra, unit,
+						  HV_RNG_STATE_CONFIGURED);
+		if (err)
+			break;
+	}
+
+	return err;
+}
+
+static void n2rng_work(struct work_struct *work)
+{
+	struct n2rng *np = container_of(work, struct n2rng, work.work);
+	int err = 0;
+
+	if (!(np->flags & N2RNG_FLAG_CONTROL)) {
+		err = n2rng_guest_check(np);
+	} else {
+		preempt_disable();
+		err = n2rng_control_check(np);
+		preempt_enable();
+
+		if (!err)
+			err = n2rng_control_configure_units(np);
+	}
+
+	if (!err) {
+		np->flags |= N2RNG_FLAG_READY;
+		dev_info(&np->op->dev, "RNG ready\n");
+	}
+
+	if (err && !(np->flags & N2RNG_FLAG_SHUTDOWN))
+		schedule_delayed_work(&np->work, HZ * 2);
+}
+
+static void __devinit n2rng_driver_version(void)
+{
+	static int n2rng_version_printed;
+
+	if (n2rng_version_printed++ == 0)
+		pr_info("%s", version);
+}
+
+static int __devinit n2rng_probe(struct of_device *op,
+				 const struct of_device_id *match)
+{
+	int victoria_falls = (match->data != NULL);
+	int err = -ENOMEM;
+	struct n2rng *np;
+
+	n2rng_driver_version();
+
+	np = kzalloc(sizeof(*np), GFP_KERNEL);
+	if (!np)
+		goto out;
+	np->op = op;
+
+	INIT_DELAYED_WORK(&np->work, n2rng_work);
+
+	if (victoria_falls)
+		np->flags |= N2RNG_FLAG_VF;
+
+	err = -ENODEV;
+	np->hvapi_major = 2;
+	if (sun4v_hvapi_register(HV_GRP_RNG,
+				 np->hvapi_major,
+				 &np->hvapi_minor)) {
+		np->hvapi_major = 1;
+		if (sun4v_hvapi_register(HV_GRP_RNG,
+					 np->hvapi_major,
+					 &np->hvapi_minor)) {
+			dev_err(&op->dev, "Cannot register suitable "
+				"HVAPI version.\n");
+			goto out_free;
+		}
+	}
+
+	if (np->flags & N2RNG_FLAG_VF) {
+		if (np->hvapi_major < 2) {
+			dev_err(&op->dev, "VF RNG requires HVAPI major "
+				"version 2 or later, got %lu\n",
+				np->hvapi_major);
+			goto out_hvapi_unregister;
+		}
+		np->num_units = of_getintprop_default(op->node,
+						      "rng-#units", 0);
+		if (!np->num_units) {
+			dev_err(&op->dev, "VF RNG lacks rng-#units property\n");
+			goto out_hvapi_unregister;
+		}
+	} else
+		np->num_units = 1;
+
+	dev_info(&op->dev, "Registered RNG HVAPI major %lu minor %lu\n",
+		 np->hvapi_major, np->hvapi_minor);
+
+	np->units = kzalloc(sizeof(struct n2rng_unit) * np->num_units,
+			    GFP_KERNEL);
+	err = -ENOMEM;
+	if (!np->units)
+		goto out_hvapi_unregister;
+
+	err = n2rng_init_control(np);
+	if (err)
+		goto out_free_units;
+
+	dev_info(&op->dev, "Found %s RNG, units: %d\n",
+		 ((np->flags & N2RNG_FLAG_VF) ?
+		  "Victoria Falls" : "Niagara2"),
+		 np->num_units);
+
+	np->hwrng.name = "n2rng";
+	np->hwrng.data_read = n2rng_data_read;
+	np->hwrng.priv = (unsigned long) np;
+
+	err = hwrng_register(&np->hwrng);
+	if (err)
+		goto out_free_units;
+
+	dev_set_drvdata(&op->dev, np);
+
+	schedule_delayed_work(&np->work, 0);
+
+	return 0;
+
+out_free_units:
+	kfree(np->units);
+	np->units = NULL;
+
+out_hvapi_unregister:
+	sun4v_hvapi_unregister(HV_GRP_RNG);
+
+out_free:
+	kfree(np);
+out:
+	return err;
+}
+
+static int __devexit n2rng_remove(struct of_device *op)
+{
+	struct n2rng *np = dev_get_drvdata(&op->dev);
+
+	np->flags |= N2RNG_FLAG_SHUTDOWN;
+
+	cancel_delayed_work_sync(&np->work);
+
+	hwrng_unregister(&np->hwrng);
+
+	sun4v_hvapi_unregister(HV_GRP_RNG);
+
+	kfree(np->units);
+	np->units = NULL;
+
+	kfree(np);
+
+	dev_set_drvdata(&op->dev, NULL);
+
+	return 0;
+}
+
+static struct of_device_id n2rng_match[] = {
+	{
+		.name		= "random-number-generator",
+		.compatible	= "SUNW,n2-rng",
+	},
+	{
+		.name		= "random-number-generator",
+		.compatible	= "SUNW,vf-rng",
+		.data		= (void *) 1,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, n2rng_match);
+
+static struct of_platform_driver n2rng_driver = {
+	.name		= "n2rng",
+	.match_table	= n2rng_match,
+	.probe		= n2rng_probe,
+	.remove		= __devexit_p(n2rng_remove),
+};
+
+static int __init n2rng_init(void)
+{
+	return of_register_driver(&n2rng_driver, &of_bus_type);
+}
+
+static void __exit n2rng_exit(void)
+{
+	of_unregister_driver(&n2rng_driver);
+}
+
+module_init(n2rng_init);
+module_exit(n2rng_exit);
diff --git a/drivers/char/hw_random/n2rng.h b/drivers/char/hw_random/n2rng.h
new file mode 100644
index 0000000..a2b81e7
--- /dev/null
+++ b/drivers/char/hw_random/n2rng.h
@@ -0,0 +1,118 @@
+/* n2rng.h: Niagara2 RNG defines.
+ *
+ * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
+ */
+
+#ifndef _N2RNG_H
+#define _N2RNG_H
+
+#define RNG_CTL_WAIT       0x0000000001fffe00ULL /* Minimum wait time       */
+#define RNG_CTL_WAIT_SHIFT 9
+#define RNG_CTL_BYPASS     0x0000000000000100ULL /* VCO voltage source      */
+#define RNG_CTL_VCO        0x00000000000000c0ULL /* VCO rate control        */
+#define RNG_CTL_VCO_SHIFT  6
+#define RNG_CTL_ASEL       0x0000000000000030ULL /* Analog MUX select       */
+#define RNG_CTL_ASEL_SHIFT 4
+#define RNG_CTL_LFSR       0x0000000000000008ULL /* Use LFSR or plain shift */
+#define RNG_CTL_ES3        0x0000000000000004ULL /* Enable entropy source 3 */
+#define RNG_CTL_ES2        0x0000000000000002ULL /* Enable entropy source 2 */
+#define RNG_CTL_ES1        0x0000000000000001ULL /* Enable entropy source 1 */
+
+#define HV_FAST_RNG_GET_DIAG_CTL	0x130
+#define HV_FAST_RNG_CTL_READ		0x131
+#define HV_FAST_RNG_CTL_WRITE		0x132
+#define HV_FAST_RNG_DATA_READ_DIAG	0x133
+#define HV_FAST_RNG_DATA_READ		0x134
+
+#define HV_RNG_STATE_UNCONFIGURED	0
+#define HV_RNG_STATE_CONFIGURED		1
+#define HV_RNG_STATE_HEALTHCHECK	2
+#define HV_RNG_STATE_ERROR		3
+
+#define HV_RNG_NUM_CONTROL		4
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_rng_get_diag_ctl(void);
+extern unsigned long sun4v_rng_ctl_read_v1(unsigned long ctl_regs_ra,
+					   unsigned long *state,
+					   unsigned long *tick_delta);
+extern unsigned long sun4v_rng_ctl_read_v2(unsigned long ctl_regs_ra,
+					   unsigned long unit,
+					   unsigned long *state,
+					   unsigned long *tick_delta,
+					   unsigned long *watchdog,
+					   unsigned long *write_status);
+extern unsigned long sun4v_rng_ctl_write_v1(unsigned long ctl_regs_ra,
+					    unsigned long state,
+					    unsigned long write_timeout,
+					    unsigned long *tick_delta);
+extern unsigned long sun4v_rng_ctl_write_v2(unsigned long ctl_regs_ra,
+					    unsigned long state,
+					    unsigned long write_timeout,
+					    unsigned long unit);
+extern unsigned long sun4v_rng_data_read_diag_v1(unsigned long data_ra,
+						 unsigned long len,
+						 unsigned long *tick_delta);
+extern unsigned long sun4v_rng_data_read_diag_v2(unsigned long data_ra,
+						 unsigned long len,
+						 unsigned long unit,
+						 unsigned long *tick_delta);
+extern unsigned long sun4v_rng_data_read(unsigned long data_ra,
+					 unsigned long *tick_delta);
+
+struct n2rng_unit {
+	u64			control[HV_RNG_NUM_CONTROL];
+};
+
+struct n2rng {
+	struct of_device	*op;
+
+	unsigned long		flags;
+#define N2RNG_FLAG_VF		0x00000001 /* Victoria Falls RNG, else N2 */
+#define N2RNG_FLAG_CONTROL	0x00000002 /* Operating in control domain */
+#define N2RNG_FLAG_READY	0x00000008 /* Ready for hw-rng layer      */
+#define N2RNG_FLAG_SHUTDOWN	0x00000010 /* Driver unregistering        */
+#define N2RNG_FLAG_BUFFER_VALID	0x00000020 /* u32 buffer holds valid data */
+
+	int			num_units;
+	struct n2rng_unit	*units;
+
+	struct hwrng		hwrng;
+	u32			buffer;
+
+	/* Registered hypervisor group API major and minor version.  */
+	unsigned long		hvapi_major;
+	unsigned long		hvapi_minor;
+
+	struct delayed_work	work;
+
+	unsigned long		hv_state; /* HV_RNG_STATE_foo */
+
+	unsigned long		health_check_sec;
+	unsigned long		accum_cycles;
+	unsigned long		wd_timeo;
+#define N2RNG_HEALTH_CHECK_SEC_DEFAULT	0
+#define N2RNG_ACCUM_CYCLES_DEFAULT	2048
+#define N2RNG_WD_TIMEO_DEFAULT		0
+
+	u64			scratch_control[HV_RNG_NUM_CONTROL];
+
+#define SELFTEST_TICKS		38859
+#define SELFTEST_VAL		((u64)0xB8820C7BD387E32C)
+#define SELFTEST_POLY		((u64)0x231DCEE91262B8A3)
+#define SELFTEST_MATCH_GOAL	6
+#define SELFTEST_LOOPS_MAX	40000
+#define SELFTEST_BUFFER_WORDS	8
+
+	u64			test_data;
+	u64			test_control[HV_RNG_NUM_CONTROL];
+	u64			test_buffer[SELFTEST_BUFFER_WORDS];
+};
+
+#define N2RNG_BLOCK_LIMIT	60000
+#define N2RNG_BUSY_LIMIT	100
+#define N2RNG_HCHECK_LIMIT	100
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* _N2RNG_H */
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index 5dc7440..9cb48fc 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -718,12 +718,12 @@
 			}
 
 			if ( NULL != ( pB = i2BoardPtrTable[i] ) ) {
-				device_create(ip2_class, NULL,
-						MKDEV(IP2_IPL_MAJOR, 4 * i),
-						"ipl%d", i);
-				device_create(ip2_class, NULL,
-						MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
-						"stat%d", i);
+				device_create_drvdata(ip2_class, NULL,
+						      MKDEV(IP2_IPL_MAJOR, 4 * i),
+						      NULL, "ipl%d", i);
+				device_create_drvdata(ip2_class, NULL,
+						      MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
+						      NULL, "stat%d", i);
 
 			    for ( box = 0; box < ABS_MAX_BOXES; ++box )
 			    {
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index c11a404..64e1c16 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -871,7 +871,7 @@
 	entry->dev = dev;
 
 	mutex_lock(&reg_list_mutex);
-	device_create(ipmi_class, device, dev, "ipmi%d", if_num);
+	device_create_drvdata(ipmi_class, device, dev, NULL, "ipmi%d", if_num);
 	list_add(&entry->link, &reg_list);
 	mutex_unlock(&reg_list_mutex);
 }
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index d4281df..8f7cc19 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -1181,14 +1181,17 @@
 }
 
 /* ioctl et all */
-static inline void isicom_send_break(struct isi_port *port,
-	unsigned long length)
+static int isicom_send_break(struct tty_struct *tty, int length)
 {
+	struct isi_port *port = tty->driver_data;
 	struct isi_board *card = port->card;
 	unsigned long base = card->base;
 
+	if (length == -1)
+		return -EOPNOTSUPP;
+
 	if (!lock_card(card))
-		return;
+		return -EINVAL;
 
 	outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base);
 	outw((length & 0xff) << 8 | 0x00, base);
@@ -1196,6 +1199,7 @@
 	InterruptTheCard(base);
 
 	unlock_card(card);
+	return 0;
 }
 
 static int isicom_tiocmget(struct tty_struct *tty, struct file *file)
@@ -1305,28 +1309,11 @@
 {
 	struct isi_port *port = tty->driver_data;
 	void __user *argp = (void __user *)arg;
-	int retval;
 
 	if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
 		return -ENODEV;
 
 	switch (cmd) {
-	case TCSBRK:
-		retval = tty_check_change(tty);
-		if (retval)
-			return retval;
-		tty_wait_until_sent(tty, 0);
-		if (!arg)
-			isicom_send_break(port, HZ/4);
-		return 0;
-
-	case TCSBRKP:
-		retval = tty_check_change(tty);
-		if (retval)
-			return retval;
-		tty_wait_until_sent(tty, 0);
-		isicom_send_break(port, arg ? arg * (HZ/10) : HZ/4);
-		return 0;
 	case TIOCGSERIAL:
 		return isicom_get_serial_info(port, argp);
 
@@ -1459,6 +1446,7 @@
 	.flush_buffer		= isicom_flush_buffer,
 	.tiocmget		= isicom_tiocmget,
 	.tiocmset		= isicom_tiocmset,
+	.break_ctl		= isicom_send_break,
 };
 
 static int __devinit reset_card(struct pci_dev *pdev,
@@ -1832,7 +1820,7 @@
 	isicom_normal->init_termios.c_cflag	= B9600 | CS8 | CREAD | HUPCL |
 		CLOCAL;
 	isicom_normal->flags			= TTY_DRIVER_REAL_RAW |
-		TTY_DRIVER_DYNAMIC_DEV;
+		TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK;
 	tty_set_operations(isicom_normal, &isicom_ops);
 
 	retval = tty_register_driver(isicom_normal);
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 6ef1c56..843a2af 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -598,7 +598,7 @@
 static int	stli_open(struct tty_struct *tty, struct file *filp);
 static void	stli_close(struct tty_struct *tty, struct file *filp);
 static int	stli_write(struct tty_struct *tty, const unsigned char *buf, int count);
-static void	stli_putchar(struct tty_struct *tty, unsigned char ch);
+static int	stli_putchar(struct tty_struct *tty, unsigned char ch);
 static void	stli_flushchars(struct tty_struct *tty);
 static int	stli_writeroom(struct tty_struct *tty);
 static int	stli_charsinbuffer(struct tty_struct *tty);
@@ -609,7 +609,7 @@
 static void	stli_stop(struct tty_struct *tty);
 static void	stli_start(struct tty_struct *tty);
 static void	stli_flushbuffer(struct tty_struct *tty);
-static void	stli_breakctl(struct tty_struct *tty, int state);
+static int	stli_breakctl(struct tty_struct *tty, int state);
 static void	stli_waituntilsent(struct tty_struct *tty, int timeout);
 static void	stli_sendxchar(struct tty_struct *tty, char ch);
 static void	stli_hangup(struct tty_struct *tty);
@@ -826,7 +826,7 @@
  */
 	portp->port.tty = tty;
 	tty->driver_data = portp;
-	portp->refcount++;
+	portp->port.count++;
 
 	wait_event_interruptible(portp->raw_wait,
 			!test_bit(ST_INITIALIZING, &portp->state));
@@ -888,9 +888,9 @@
 		spin_unlock_irqrestore(&stli_lock, flags);
 		return;
 	}
-	if ((tty->count == 1) && (portp->refcount != 1))
-		portp->refcount = 1;
-	if (portp->refcount-- > 1) {
+	if ((tty->count == 1) && (portp->port.count != 1))
+		portp->port.count = 1;
+	if (portp->port.count-- > 1) {
 		spin_unlock_irqrestore(&stli_lock, flags);
 		return;
 	}
@@ -925,8 +925,7 @@
 	clear_bit(ST_TXBUSY, &portp->state);
 	clear_bit(ST_RXSTOP, &portp->state);
 	set_bit(TTY_IO_ERROR, &tty->flags);
-	if (tty->ldisc.flush_buffer)
-		(tty->ldisc.flush_buffer)(tty);
+	tty_ldisc_flush(tty);
 	set_bit(ST_DOFLUSHRX, &portp->state);
 	stli_flushbuffer(tty);
 
@@ -1202,7 +1201,7 @@
 	spin_lock_irqsave(&stli_lock, flags);
 	portp->openwaitcnt++;
 	if (! tty_hung_up_p(filp))
-		portp->refcount--;
+		portp->port.count--;
 	spin_unlock_irqrestore(&stli_lock, flags);
 
 	for (;;) {
@@ -1231,7 +1230,7 @@
 
 	spin_lock_irqsave(&stli_lock, flags);
 	if (! tty_hung_up_p(filp))
-		portp->refcount++;
+		portp->port.count++;
 	portp->openwaitcnt--;
 	spin_unlock_irqrestore(&stli_lock, flags);
 
@@ -1333,7 +1332,7 @@
  *	first them do the new ports.
  */
 
-static void stli_putchar(struct tty_struct *tty, unsigned char ch)
+static int stli_putchar(struct tty_struct *tty, unsigned char ch)
 {
 	if (tty != stli_txcooktty) {
 		if (stli_txcooktty != NULL)
@@ -1342,6 +1341,7 @@
 	}
 
 	stli_txcookbuf[stli_txcooksize++] = ch;
+	return 0;
 }
 
 /*****************************************************************************/
@@ -1660,7 +1660,6 @@
 {
 	struct stliport *portp;
 	struct stlibrd *brdp;
-	unsigned int ival;
 	int rc;
 	void __user *argp = (void __user *)arg;
 
@@ -1857,7 +1856,7 @@
 	set_bit(TTY_IO_ERROR, &tty->flags);
 	portp->port.tty = NULL;
 	portp->port.flags &= ~ASYNC_NORMAL_ACTIVE;
-	portp->refcount = 0;
+	portp->port.count = 0;
 	spin_unlock_irqrestore(&stli_lock, flags);
 
 	wake_up_interruptible(&portp->port.open_wait);
@@ -1909,7 +1908,7 @@
 
 /*****************************************************************************/
 
-static void stli_breakctl(struct tty_struct *tty, int state)
+static int stli_breakctl(struct tty_struct *tty, int state)
 {
 	struct stlibrd	*brdp;
 	struct stliport	*portp;
@@ -1917,15 +1916,16 @@
 
 	portp = tty->driver_data;
 	if (portp == NULL)
-		return;
+		return -EINVAL;
 	if (portp->brdnr >= stli_nrbrds)
-		return;
+		return -EINVAL;
 	brdp = stli_brds[portp->brdnr];
 	if (brdp == NULL)
-		return;
+		return -EINVAL;
 
 	arg = (state == -1) ? BREAKON : BREAKOFF;
 	stli_cmdwait(brdp, portp, A_BREAK, &arg, sizeof(long), 0);
+	return 0;
 }
 
 /*****************************************************************************/
@@ -4246,7 +4246,7 @@
 	stli_comstats.panel = portp->panelnr;
 	stli_comstats.port = portp->portnr;
 	stli_comstats.state = portp->state;
-	stli_comstats.flags = portp->port.flag;
+	stli_comstats.flags = portp->port.flags;
 
 	spin_lock_irqsave(&brd_lock, flags);
 	if (portp->port.tty != NULL) {
@@ -4599,8 +4599,9 @@
 
 	istallion_class = class_create(THIS_MODULE, "staliomem");
 	for (i = 0; i < 4; i++)
-		device_create(istallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
-			      "staliomem%d", i);
+		device_create_drvdata(istallion_class, NULL,
+				      MKDEV(STL_SIOMEMMAJOR, i),
+				      NULL, "staliomem%d", i);
 
 	return 0;
 err_deinit:
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index d9a0a53..7b3a212 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -46,6 +46,8 @@
 
 extern void ctrl_alt_del(void);
 
+#define to_handle_h(n) container_of(n, struct input_handle, h_node)
+
 /*
  * Exported functions/variables
  */
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 71abb4c..3f2719b 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -813,7 +813,8 @@
 	if (reset)
 		lp_reset(nr);
 
-	device_create(lp_class, port->dev, MKDEV(LP_MAJOR, nr), "lp%d", nr);
+	device_create_drvdata(lp_class, port->dev, MKDEV(LP_MAJOR, nr), NULL,
+			      "lp%d", nr);
 
 	printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, 
 	       (port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven");
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 070e22e..c2dba82 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -80,7 +80,7 @@
 }
 #endif
 
-#ifdef CONFIG_NONPROMISC_DEVMEM
+#ifdef CONFIG_STRICT_DEVMEM
 static inline int range_is_allowed(unsigned long pfn, unsigned long size)
 {
 	u64 from = ((u64)pfn) << PAGE_SHIFT;
@@ -989,9 +989,9 @@
 
 	mem_class = class_create(THIS_MODULE, "mem");
 	for (i = 0; i < ARRAY_SIZE(devlist); i++)
-		device_create(mem_class, NULL,
-			      MKDEV(MEM_MAJOR, devlist[i].minor),
-			      devlist[i].name);
+		device_create_drvdata(mem_class, NULL,
+				      MKDEV(MEM_MAJOR, devlist[i].minor),
+				      NULL, devlist[i].name);
 
 	return 0;
 }
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 6e1563c..999aa77 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -217,8 +217,8 @@
 		misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);
 	dev = MKDEV(MISC_MAJOR, misc->minor);
 
-	misc->this_device = device_create(misc_class, misc->parent, dev,
-					  "%s", misc->name);
+	misc->this_device = device_create_drvdata(misc_class, misc->parent,
+						  dev, NULL, "%s", misc->name);
 	if (IS_ERR(misc->this_device)) {
 		err = PTR_ERR(misc->this_device);
 		goto out;
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
index 192961f..918711a 100644
--- a/drivers/char/mmtimer.c
+++ b/drivers/char/mmtimer.c
@@ -32,6 +32,7 @@
 #include <linux/interrupt.h>
 #include <linux/time.h>
 #include <linux/math64.h>
+#include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 #include <asm/sn/addrs.h>
@@ -57,8 +58,8 @@
 
 #define rtc_time()              (*RTC_COUNTER_ADDR)
 
-static int mmtimer_ioctl(struct inode *inode, struct file *file,
-			 unsigned int cmd, unsigned long arg);
+static long mmtimer_ioctl(struct file *file, unsigned int cmd,
+						unsigned long arg);
 static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma);
 
 /*
@@ -67,9 +68,9 @@
 static unsigned long mmtimer_femtoperiod = 0;
 
 static const struct file_operations mmtimer_fops = {
-	.owner =	THIS_MODULE,
-	.mmap =		mmtimer_mmap,
-	.ioctl =	mmtimer_ioctl,
+	.owner = THIS_MODULE,
+	.mmap =	mmtimer_mmap,
+	.unlocked_ioctl = mmtimer_ioctl,
 };
 
 /*
@@ -339,7 +340,6 @@
 
 /**
  * mmtimer_ioctl - ioctl interface for /dev/mmtimer
- * @inode: inode of the device
  * @file: file structure for the device
  * @cmd: command to execute
  * @arg: optional argument to command
@@ -365,11 +365,13 @@
  * %MMTIMER_GETCOUNTER - Gets the current value in the counter and places it
  * in the address specified by @arg.
  */
-static int mmtimer_ioctl(struct inode *inode, struct file *file,
-			 unsigned int cmd, unsigned long arg)
+static long mmtimer_ioctl(struct file *file, unsigned int cmd,
+						unsigned long arg)
 {
 	int ret = 0;
 
+	lock_kernel();
+
 	switch (cmd) {
 	case MMTIMER_GETOFFSET:	/* offset of the counter */
 		/*
@@ -384,15 +386,14 @@
 	case MMTIMER_GETRES: /* resolution of the clock in 10^-15 s */
 		if(copy_to_user((unsigned long __user *)arg,
 				&mmtimer_femtoperiod, sizeof(unsigned long)))
-			return -EFAULT;
+			ret = -EFAULT;
 		break;
 
 	case MMTIMER_GETFREQ: /* frequency in Hz */
 		if(copy_to_user((unsigned long __user *)arg,
 				&sn_rtc_cycles_per_second,
 				sizeof(unsigned long)))
-			return -EFAULT;
-		ret = 0;
+			ret = -EFAULT;
 		break;
 
 	case MMTIMER_GETBITS: /* number of bits in the clock */
@@ -406,13 +407,13 @@
 	case MMTIMER_GETCOUNTER:
 		if(copy_to_user((unsigned long __user *)arg,
 				RTC_COUNTER_ADDR, sizeof(unsigned long)))
-			return -EFAULT;
+			ret = -EFAULT;
 		break;
 	default:
-		ret = -ENOSYS;
+		ret = -ENOTTY;
 		break;
 	}
-
+	unlock_kernel();
 	return ret;
 }
 
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index 2bba250..d3d7864e 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -374,12 +374,13 @@
 	return ret;
 }
 
-static void moxa_break_ctl(struct tty_struct *tty, int state)
+static int moxa_break_ctl(struct tty_struct *tty, int state)
 {
 	struct moxa_port *port = tty->driver_data;
 
 	moxafunc(port->tableAddr, state ? FC_SendBreak : FC_StopBreak,
 			Magic_code);
+	return 0;
 }
 
 static const struct tty_operations moxa_ops = {
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 6307e30..4c756bb 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -47,7 +47,7 @@
 
 #include "mxser.h"
 
-#define	MXSER_VERSION	"2.0.3"		/* 1.11 */
+#define	MXSER_VERSION	"2.0.4"		/* 1.12 */
 #define	MXSERMAJOR	 174
 #define	MXSERCUMAJOR	 175
 
@@ -71,12 +71,13 @@
 #define UART_MCR_AFE		0x20
 #define UART_LSR_SPECIAL	0x1E
 
+#define PCI_DEVICE_ID_POS104UL	0x1044
 #define PCI_DEVICE_ID_CB108	0x1080
+#define PCI_DEVICE_ID_CP102UF	0x1023
 #define PCI_DEVICE_ID_CB114	0x1142
 #define PCI_DEVICE_ID_CP114UL	0x1143
 #define PCI_DEVICE_ID_CB134I	0x1341
 #define PCI_DEVICE_ID_CP138U	0x1380
-#define PCI_DEVICE_ID_POS104UL	0x1044
 
 
 #define C168_ASIC_ID    1
@@ -142,7 +143,8 @@
 	{ "CB-134I series",	4, },
 	{ "CP-138U series",	8, },
 	{ "POS-104UL series",	4, },
-	{ "CP-114UL series",	4, }
+	{ "CP-114UL series",	4, },
+/*30*/	{ "CP-102UF series",	2, }
 };
 
 /* driver_data correspond to the lines in the structure above
@@ -172,6 +174,7 @@
 	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP138U),	.driver_data = 27 },
 	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_POS104UL),	.driver_data = 28 },
 	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP114UL),	.driver_data = 29 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP102UF),	.driver_data = 30 },
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, mxser_pcibrds);
@@ -1414,7 +1417,6 @@
 		info->port.closing_wait = new_serial.closing_wait * HZ / 100;
 		info->port.tty->low_latency =
 				(info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-		info->port.tty->low_latency = 0;
 		if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST &&
 				(new_serial.baud_base != info->baud_base ||
 				new_serial.custom_divisor !=
@@ -1464,27 +1466,6 @@
 	return put_user(result, value);
 }
 
-/*
- * This routine sends a break character out the serial port.
- */
-static void mxser_send_break(struct mxser_port *info, int duration)
-{
-	unsigned long flags;
-
-	if (!info->ioaddr)
-		return;
-	set_current_state(TASK_INTERRUPTIBLE);
-	spin_lock_irqsave(&info->slock, flags);
-	outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC,
-		info->ioaddr + UART_LCR);
-	spin_unlock_irqrestore(&info->slock, flags);
-	schedule_timeout(duration);
-	spin_lock_irqsave(&info->slock, flags);
-	outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC,
-		info->ioaddr + UART_LCR);
-	spin_unlock_irqrestore(&info->slock, flags);
-}
-
 static int mxser_tiocmget(struct tty_struct *tty, struct file *file)
 {
 	struct mxser_port *info = tty->driver_data;
@@ -1872,21 +1853,6 @@
 		return -EIO;
 
 	switch (cmd) {
-	case TCSBRK:		/* SVID version: non-zero arg --> no break */
-		retval = tty_check_change(tty);
-		if (retval)
-			return retval;
-		tty_wait_until_sent(tty, 0);
-		if (!arg)
-			mxser_send_break(info, HZ / 4);	/* 1/4 second */
-		return 0;
-	case TCSBRKP:		/* support for POSIX tcsendbreak() */
-		retval = tty_check_change(tty);
-		if (retval)
-			return retval;
-		tty_wait_until_sent(tty, 0);
-		mxser_send_break(info, arg ? arg * (HZ / 10) : HZ / 4);
-		return 0;
 	case TIOCGSERIAL:
 		lock_kernel();
 		retval = mxser_get_serial_info(info, argp);
@@ -2219,7 +2185,7 @@
 /*
  * mxser_rs_break() --- routine which turns the break handling on or off
  */
-static void mxser_rs_break(struct tty_struct *tty, int break_state)
+static int mxser_rs_break(struct tty_struct *tty, int break_state)
 {
 	struct mxser_port *info = tty->driver_data;
 	unsigned long flags;
@@ -2232,6 +2198,7 @@
 		outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC,
 			info->ioaddr + UART_LCR);
 	spin_unlock_irqrestore(&info->slock, flags);
+	return 0;
 }
 
 static void mxser_receive_chars(struct mxser_port *port, int *status)
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index ed4e033..69ec639 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -677,6 +677,10 @@
 	/* Allocate transmit buffer */
 	/* sleep until transmit buffer available */		
 	while (!(tbuf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list))) {
+		if (file->f_flags & O_NONBLOCK) {
+			error = -EAGAIN;
+			break;
+		}
 		schedule();
 			
 		n_hdlc = tty2n_hdlc (tty);
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index a22662b..39f6357 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -107,7 +107,6 @@
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index e4a4fbd..f070ae7 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -1896,7 +1896,7 @@
 		return ret;
 	}
 
-	device_create(cmm_class, NULL, MKDEV(major, i), "cmm%d", i);
+	device_create_drvdata(cmm_class, NULL, MKDEV(major, i), NULL, "cmm%d", i);
 
 	return 0;
 }
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index 6181f8a..0b5934b 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -653,7 +653,8 @@
 		return ret;
 	}
 
-	device_create(cmx_class, NULL, MKDEV(major, i), "cmx%d", i);
+	device_create_drvdata(cmx_class, NULL, MKDEV(major, i), NULL,
+			      "cmx%d", i);
 
 	return 0;
 }
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index b694d43..d1fceab 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -2230,7 +2230,7 @@
  * Arguments:		tty		pointer to tty instance data
  *			break_state	-1=set break condition, 0=clear
  */
-static void mgslpc_break(struct tty_struct *tty, int break_state)
+static int mgslpc_break(struct tty_struct *tty, int break_state)
 {
 	MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
 	unsigned long flags;
@@ -2240,7 +2240,7 @@
 			 __FILE__,__LINE__, info->device_name, break_state);
 
 	if (mgslpc_paranoia_check(info, tty->name, "mgslpc_break"))
-		return;
+		return -EINVAL;
 
 	spin_lock_irqsave(&info->lock,flags);
  	if (break_state == -1)
@@ -2248,6 +2248,7 @@
 	else
 		clear_reg_bits(info, CHA+DAFO, BIT6);
 	spin_unlock_irqrestore(&info->lock,flags);
+	return 0;
 }
 
 /* Service an IOCTL request
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index f6e6aca..7af7a7e 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -752,8 +752,9 @@
 
 static void pp_attach(struct parport *port)
 {
-	device_create(ppdev_class, port->dev, MKDEV(PP_MAJOR, port->number),
-			"parport%d", port->number);
+	device_create_drvdata(ppdev_class, port->dev,
+			      MKDEV(PP_MAJOR, port->number),
+			      NULL, "parport%d", port->number);
 }
 
 static void pp_detach(struct parport *port)
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index 505fcbe..47b8cf2 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -131,8 +131,8 @@
 static void bind_device(struct raw_config_request *rq)
 {
 	device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
-	device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor),
-		      "raw%d", rq->raw_minor);
+	device_create_drvdata(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor),
+			      NULL, "raw%d", rq->raw_minor);
 }
 
 /*
@@ -283,7 +283,8 @@
 		ret = PTR_ERR(raw_class);
 		goto error_region;
 	}
-	device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), "rawctl");
+	device_create_drvdata(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL,
+			      "rawctl");
 
 	return 0;
 
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index 724b2b2..2c6c8f3 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -1250,11 +1250,15 @@
 	return 0;
 }
 
-static void rc_send_break(struct riscom_port *port, unsigned long length)
+static int rc_send_break(struct tty_struct *tty, int length)
 {
+	struct riscom_port *port = (struct riscom_port *)tty->driver_data;
 	struct riscom_board *bp = port_Board(port);
 	unsigned long flags;
 
+	if (length == 0 || length == -1)
+		return -EOPNOTSUPP;
+
 	spin_lock_irqsave(&riscom_lock, flags);
 
 	port->break_length = RISCOM_TPS / HZ * length;
@@ -1268,6 +1272,7 @@
 	rc_wait_CCR(bp);
 
 	spin_unlock_irqrestore(&riscom_lock, flags);
+	return 0;
 }
 
 static int rc_set_serial_info(struct riscom_port *port,
@@ -1342,27 +1347,12 @@
 {
 	struct riscom_port *port = (struct riscom_port *)tty->driver_data;
 	void __user *argp = (void __user *)arg;
-	int retval = 0;
+	int retval;
 
 	if (rc_paranoia_check(port, tty->name, "rc_ioctl"))
 		return -ENODEV;
 
 	switch (cmd) {
-	case TCSBRK:	/* SVID version: non-zero arg --> no break */
-		retval = tty_check_change(tty);
-		if (retval)
-			return retval;
-		tty_wait_until_sent(tty, 0);
-		if (!arg)
-			rc_send_break(port, HZ/4);	/* 1/4 second */
-		break;
-	case TCSBRKP:	/* support for POSIX tcsendbreak() */
-		retval = tty_check_change(tty);
-		if (retval)
-			return retval;
-		tty_wait_until_sent(tty, 0);
-		rc_send_break(port, arg ? arg*(HZ/10) : HZ/4);
-		break;
 	case TIOCGSERIAL:
 		lock_kernel();
 		retval = rc_get_serial_info(port, argp);
@@ -1517,6 +1507,7 @@
 	.hangup = rc_hangup,
 	.tiocmget = rc_tiocmget,
 	.tiocmset = rc_tiocmset,
+	.break_ctl = rc_send_break,
 };
 
 static int __init rc_init_drivers(void)
@@ -1538,7 +1529,7 @@
 		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
 	riscom_driver->init_termios.c_ispeed = 9600;
 	riscom_driver->init_termios.c_ospeed = 9600;
-	riscom_driver->flags = TTY_DRIVER_REAL_RAW;
+	riscom_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_HARDWARE_BREAK;
 	tty_set_operations(riscom_driver, &riscom_ops);
 	error = tty_register_driver(riscom_driver);
 	if (error != 0) {
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index e670eae..584d791 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -1236,13 +1236,13 @@
 	}
 }
 
-static void rp_break(struct tty_struct *tty, int break_state)
+static int rp_break(struct tty_struct *tty, int break_state)
 {
 	struct r_port *info = (struct r_port *) tty->driver_data;
 	unsigned long flags;
 
 	if (rocket_paranoia_check(info, "rp_break"))
-		return;
+		return -EINVAL;
 
 	spin_lock_irqsave(&info->slock, flags);
 	if (break_state == -1)
@@ -1250,6 +1250,7 @@
 	else
 		sClrBreak(&info->channel);
 	spin_unlock_irqrestore(&info->slock, flags);
+	return 0;
 }
 
 /*
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index 0b799ac..3ce60df 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -444,7 +444,8 @@
 				continue;
 			}
 
-			device_create(snsc_class, NULL, dev, "%s", devname);
+			device_create_drvdata(snsc_class, NULL, dev, NULL,
+					      "%s", devname);
 
 			ia64_sn_irtr_intr_enable(scd->scd_nasid,
 						 0 /*ignored */ ,
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index 037dc47..242fd46 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -77,7 +77,7 @@
 
 #include <linux/module.h>
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/ioport.h>
@@ -92,7 +92,7 @@
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/init.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "specialix_io8.h"
 #include "cd1865.h"
@@ -110,9 +110,10 @@
 
 static int sx_debug;
 static int sx_rxfifo = SPECIALIX_RXFIFO;
+static int sx_rtscts;
 
 #ifdef DEBUG
-#define dprintk(f, str...) if (sx_debug & f) printk (str)
+#define dprintk(f, str...) if (sx_debug & f) printk(str)
 #else
 #define dprintk(f, str...) /* nothing */
 #endif
@@ -131,10 +132,8 @@
 #define SX_DEBUG_FIFO    0x0800
 
 
-#define func_enter() dprintk (SX_DEBUG_FLOW, "io8: enter %s\n",__func__)
-#define func_exit()  dprintk (SX_DEBUG_FLOW, "io8: exit  %s\n", __func__)
-
-#define jiffies_from_ms(a) ((((a) * HZ)/1000)+1)
+#define func_enter() dprintk(SX_DEBUG_FLOW, "io8: enter %s\n", __func__)
+#define func_exit()  dprintk(SX_DEBUG_FLOW, "io8: exit  %s\n", __func__)
 
 
 /* Configurable options: */
@@ -142,17 +141,6 @@
 /* Am I paranoid or not ? ;-) */
 #define SPECIALIX_PARANOIA_CHECK
 
-/* Do I trust the IRQ from the card? (enabeling it doesn't seem to help)
-   When the IRQ routine leaves the chip in a state that is keeps on
-   requiring attention, the timer doesn't help either. */
-#undef SPECIALIX_TIMER
-
-#ifdef SPECIALIX_TIMER
-static int sx_poll = HZ;
-#endif
-
-
-
 /*
  * The following defines are mostly for testing purposes. But if you need
  * some nice reporting in your syslog, you can define them also.
@@ -162,16 +150,6 @@
 
 
 
-#ifdef CONFIG_SPECIALIX_RTSCTS
-#define SX_CRTSCTS(bla) 1
-#else
-#define SX_CRTSCTS(tty) C_CRTSCTS(tty)
-#endif
-
-
-/* Used to be outb (0xff, 0x80); */
-#define short_pause() udelay (1)
-
 
 #define SPECIALIX_LEGAL_FLAGS \
 	(ASYNC_HUP_NOTIFY   | ASYNC_SAK          | ASYNC_SPLIT_TERMIOS   | \
@@ -190,21 +168,14 @@
 static struct specialix_port sx_port[SX_NBOARD * SX_NPORT];
 
 
-#ifdef SPECIALIX_TIMER
-static struct timer_list missed_irq_timer;
-static irqreturn_t sx_interrupt(int irq, void * dev_id);
-#endif
-
-
-
-static inline int sx_paranoia_check(struct specialix_port const * port,
+static int sx_paranoia_check(struct specialix_port const *port,
 				    char *name, const char *routine)
 {
 #ifdef SPECIALIX_PARANOIA_CHECK
-	static const char *badmagic =
-		KERN_ERR "sx: Warning: bad specialix port magic number for device %s in %s\n";
-	static const char *badinfo =
-		KERN_ERR "sx: Warning: null specialix port for device %s in %s\n";
+	static const char *badmagic = KERN_ERR
+	  "sx: Warning: bad specialix port magic number for device %s in %s\n";
+	static const char *badinfo = KERN_ERR
+	  "sx: Warning: null specialix port for device %s in %s\n";
 
 	if (!port) {
 		printk(badinfo, name, routine);
@@ -226,66 +197,69 @@
  */
 
 /* Get board number from pointer */
-static inline int board_No (struct specialix_board * bp)
+static inline int board_No(struct specialix_board *bp)
 {
 	return bp - sx_board;
 }
 
 
 /* Get port number from pointer */
-static inline int port_No (struct specialix_port const * port)
+static inline int port_No(struct specialix_port const *port)
 {
 	return SX_PORT(port - sx_port);
 }
 
 
 /* Get pointer to board from pointer to port */
-static inline struct specialix_board * port_Board(struct specialix_port const * port)
+static inline struct specialix_board *port_Board(
+					struct specialix_port const *port)
 {
 	return &sx_board[SX_BOARD(port - sx_port)];
 }
 
 
 /* Input Byte from CL CD186x register */
-static inline unsigned char sx_in(struct specialix_board  * bp, unsigned short reg)
+static inline unsigned char sx_in(struct specialix_board *bp,
+							unsigned short reg)
 {
 	bp->reg = reg | 0x80;
-	outb (reg | 0x80, bp->base + SX_ADDR_REG);
-	return inb  (bp->base + SX_DATA_REG);
+	outb(reg | 0x80, bp->base + SX_ADDR_REG);
+	return inb(bp->base + SX_DATA_REG);
 }
 
 
 /* Output Byte to CL CD186x register */
-static inline void sx_out(struct specialix_board  * bp, unsigned short reg,
+static inline void sx_out(struct specialix_board *bp, unsigned short reg,
 			  unsigned char val)
 {
 	bp->reg = reg | 0x80;
-	outb (reg | 0x80, bp->base + SX_ADDR_REG);
-	outb (val, bp->base + SX_DATA_REG);
+	outb(reg | 0x80, bp->base + SX_ADDR_REG);
+	outb(val, bp->base + SX_DATA_REG);
 }
 
 
 /* Input Byte from CL CD186x register */
-static inline unsigned char sx_in_off(struct specialix_board  * bp, unsigned short reg)
+static inline unsigned char sx_in_off(struct specialix_board *bp,
+				unsigned short reg)
 {
 	bp->reg = reg;
-	outb (reg, bp->base + SX_ADDR_REG);
-	return inb  (bp->base + SX_DATA_REG);
+	outb(reg, bp->base + SX_ADDR_REG);
+	return inb(bp->base + SX_DATA_REG);
 }
 
 
 /* Output Byte to CL CD186x register */
-static inline void sx_out_off(struct specialix_board  * bp, unsigned short reg,
-			  unsigned char val)
+static inline void sx_out_off(struct specialix_board  *bp,
+				unsigned short reg, unsigned char val)
 {
 	bp->reg = reg;
-	outb (reg, bp->base + SX_ADDR_REG);
-	outb (val, bp->base + SX_DATA_REG);
+	outb(reg, bp->base + SX_ADDR_REG);
+	outb(val, bp->base + SX_DATA_REG);
 }
 
 
 /* Wait for Channel Command Register ready */
-static inline void sx_wait_CCR(struct specialix_board  * bp)
+static void sx_wait_CCR(struct specialix_board  *bp)
 {
 	unsigned long delay, flags;
 	unsigned char ccr;
@@ -296,7 +270,7 @@
 		spin_unlock_irqrestore(&bp->lock, flags);
 		if (!ccr)
 			return;
-		udelay (1);
+		udelay(1);
 	}
 
 	printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
@@ -304,7 +278,7 @@
 
 
 /* Wait for Channel Command Register ready */
-static inline void sx_wait_CCR_off(struct specialix_board  * bp)
+static void sx_wait_CCR_off(struct specialix_board  *bp)
 {
 	unsigned long delay;
 	unsigned char crr;
@@ -316,7 +290,7 @@
 		spin_unlock_irqrestore(&bp->lock, flags);
 		if (!crr)
 			return;
-		udelay (1);
+		udelay(1);
 	}
 
 	printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
@@ -327,7 +301,7 @@
  *  specialix IO8+ IO range functions.
  */
 
-static inline int sx_request_io_range(struct specialix_board * bp)
+static int sx_request_io_range(struct specialix_board *bp)
 {
 	return request_region(bp->base,
 		bp->flags & SX_BOARD_IS_PCI ? SX_PCI_IO_SPACE : SX_IO_SPACE,
@@ -335,15 +309,15 @@
 }
 
 
-static inline void sx_release_io_range(struct specialix_board * bp)
+static void sx_release_io_range(struct specialix_board *bp)
 {
-	release_region(bp->base,
-	               bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE);
+	release_region(bp->base, bp->flags & SX_BOARD_IS_PCI ?
+					SX_PCI_IO_SPACE : SX_IO_SPACE);
 }
 
 
 /* Set the IRQ using the RTS lines that run to the PAL on the board.... */
-static int sx_set_irq ( struct specialix_board *bp)
+static int sx_set_irq(struct specialix_board *bp)
 {
 	int virq;
 	int i;
@@ -353,15 +327,24 @@
 		return 1;
 	switch (bp->irq) {
 	/* In the same order as in the docs... */
-	case 15: virq = 0;break;
-	case 12: virq = 1;break;
-	case 11: virq = 2;break;
-	case 9:  virq = 3;break;
-	default: printk (KERN_ERR "Speclialix: cannot set irq to %d.\n", bp->irq);
-	         return 0;
+	case 15:
+		virq = 0;
+		break;
+	case 12:
+		virq = 1;
+		break;
+	case 11:
+		virq = 2;
+		break;
+	case 9:
+		virq = 3;
+		break;
+	default:printk(KERN_ERR
+			    "Speclialix: cannot set irq to %d.\n", bp->irq);
+		return 0;
 	}
 	spin_lock_irqsave(&bp->lock, flags);
-	for (i=0;i<2;i++) {
+	for (i = 0; i < 2; i++) {
 		sx_out(bp, CD186x_CAR, i);
 		sx_out(bp, CD186x_MSVRTS, ((virq >> i) & 0x1)? MSVR_RTS:0);
 	}
@@ -371,7 +354,7 @@
 
 
 /* Reset and setup CD186x chip */
-static int sx_init_CD186x(struct specialix_board  * bp)
+static int sx_init_CD186x(struct specialix_board  *bp)
 {
 	unsigned long flags;
 	int scaler;
@@ -390,7 +373,7 @@
 	sx_out_off(bp, CD186x_PILR2, SX_ACK_TINT);      /* Prio for transmitter intr */
 	sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT);      /* Prio for receiver intr    */
 	/* Set RegAckEn */
-	sx_out_off(bp, CD186x_SRCR, sx_in (bp, CD186x_SRCR) | SRCR_REGACKEN);
+	sx_out_off(bp, CD186x_SRCR, sx_in(bp, CD186x_SRCR) | SRCR_REGACKEN);
 
 	/* Setting up prescaler. We need 4 ticks per 1 ms */
 	scaler =  SX_OSCFREQ/SPECIALIX_TPS;
@@ -399,9 +382,9 @@
 	sx_out_off(bp, CD186x_PPRL, scaler & 0xff);
 	spin_unlock_irqrestore(&bp->lock, flags);
 
-	if (!sx_set_irq (bp)) {
+	if (!sx_set_irq(bp)) {
 		/* Figure out how to pass this along... */
-		printk (KERN_ERR "Cannot set irq to %d.\n", bp->irq);
+		printk(KERN_ERR "Cannot set irq to %d.\n", bp->irq);
 		rv = 0;
 	}
 
@@ -410,16 +393,16 @@
 }
 
 
-static int read_cross_byte (struct specialix_board *bp, int reg, int bit)
+static int read_cross_byte(struct specialix_board *bp, int reg, int bit)
 {
 	int i;
 	int t;
 	unsigned long flags;
 
 	spin_lock_irqsave(&bp->lock, flags);
-	for (i=0, t=0;i<8;i++) {
-		sx_out_off (bp, CD186x_CAR, i);
-		if (sx_in_off (bp, reg) & bit)
+	for (i = 0, t = 0; i < 8; i++) {
+		sx_out_off(bp, CD186x_CAR, i);
+		if (sx_in_off(bp, reg) & bit)
 			t |= 1 << i;
 	}
 	spin_unlock_irqrestore(&bp->lock, flags);
@@ -428,37 +411,10 @@
 }
 
 
-#ifdef SPECIALIX_TIMER
-void missed_irq (unsigned long data)
-{
-	unsigned char irq;
-	unsigned long flags;
-	struct specialix_board  *bp = (struct specialix_board *)data;
-
-	spin_lock_irqsave(&bp->lock, flags);
-	irq = sx_in ((struct specialix_board *)data, CD186x_SRSR) &
-	                                            (SRSR_RREQint |
-	                                             SRSR_TREQint |
-	                                             SRSR_MREQint);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	if (irq) {
-		printk (KERN_INFO "Missed interrupt... Calling int from timer. \n");
-		sx_interrupt (-1, bp);
-	}
-	mod_timer(&missed_irq_timer, jiffies + sx_poll);
-}
-#endif
-
-
-
 /* Main probing routine, also sets irq. */
 static int sx_probe(struct specialix_board *bp)
 {
 	unsigned char val1, val2;
-#if 0
-	int irqs = 0;
-	int retries;
-#endif
 	int rev;
 	int chip;
 
@@ -471,17 +427,18 @@
 
 	/* Are the I/O ports here ? */
 	sx_out_off(bp, CD186x_PPRL, 0x5a);
-	short_pause ();
+	udelay(1);
 	val1 = sx_in_off(bp, CD186x_PPRL);
 
 	sx_out_off(bp, CD186x_PPRL, 0xa5);
-	short_pause ();
+	udelay(1);
 	val2 = sx_in_off(bp, CD186x_PPRL);
 
 
-	if ((val1 != 0x5a) || (val2 != 0xa5)) {
-		printk(KERN_INFO "sx%d: specialix IO8+ Board at 0x%03x not found.\n",
-		       board_No(bp), bp->base);
+	if (val1 != 0x5a || val2 != 0xa5) {
+		printk(KERN_INFO
+			"sx%d: specialix IO8+ Board at 0x%03x not found.\n",
+						board_No(bp), bp->base);
 		sx_release_io_range(bp);
 		func_exit();
 		return 1;
@@ -489,10 +446,11 @@
 
 	/* Check the DSR lines that Specialix uses as board
 	   identification */
-	val1 = read_cross_byte (bp, CD186x_MSVR, MSVR_DSR);
-	val2 = read_cross_byte (bp, CD186x_MSVR, MSVR_RTS);
-	dprintk (SX_DEBUG_INIT, "sx%d: DSR lines are: %02x, rts lines are: %02x\n",
-	        board_No(bp),  val1, val2);
+	val1 = read_cross_byte(bp, CD186x_MSVR, MSVR_DSR);
+	val2 = read_cross_byte(bp, CD186x_MSVR, MSVR_RTS);
+	dprintk(SX_DEBUG_INIT,
+			"sx%d: DSR lines are: %02x, rts lines are: %02x\n",
+					board_No(bp), val1, val2);
 
 	/* They managed to switch the bit order between the docs and
 	   the IO8+ card. The new PCI card now conforms to old docs.
@@ -500,7 +458,8 @@
 	   old card. */
 	val2 = (bp->flags & SX_BOARD_IS_PCI)?0x4d : 0xb2;
 	if (val1 != val2) {
-		printk(KERN_INFO "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n",
+		printk(KERN_INFO
+		  "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n",
 		       board_No(bp), val2, bp->base, val1);
 		sx_release_io_range(bp);
 		func_exit();
@@ -508,47 +467,6 @@
 	}
 
 
-#if 0
-	/* It's time to find IRQ for this board */
-	for (retries = 0; retries < 5 && irqs <= 0; retries++) {
-		irqs = probe_irq_on();
-		sx_init_CD186x(bp);	       		/* Reset CD186x chip       */
-		sx_out(bp, CD186x_CAR, 2);               /* Select port 2          */
-		sx_wait_CCR(bp);
-		sx_out(bp, CD186x_CCR, CCR_TXEN);        /* Enable transmitter     */
-		sx_out(bp, CD186x_IER, IER_TXRDY);       /* Enable tx empty intr   */
-		msleep(50);
-		irqs = probe_irq_off(irqs);
-
-		dprintk (SX_DEBUG_INIT, "SRSR = %02x, ", sx_in(bp, CD186x_SRSR));
-		dprintk (SX_DEBUG_INIT, "TRAR = %02x, ", sx_in(bp, CD186x_TRAR));
-		dprintk (SX_DEBUG_INIT, "GIVR = %02x, ", sx_in(bp, CD186x_GIVR));
-		dprintk (SX_DEBUG_INIT, "GICR = %02x, ", sx_in(bp, CD186x_GICR));
-		dprintk (SX_DEBUG_INIT, "\n");
-
-		/* Reset CD186x again      */
-		if (!sx_init_CD186x(bp)) {
-			/* Hmmm. This is dead code anyway. */
-		}
-
-		dprintk (SX_DEBUG_INIT "val1 = %02x, val2 = %02x, val3 = %02x.\n",
-		        val1, val2, val3);
-
-	}
-
-#if 0
-	if (irqs <= 0) {
-		printk(KERN_ERR "sx%d: Can't find IRQ for specialix IO8+ board at 0x%03x.\n",
-		       board_No(bp), bp->base);
-		sx_release_io_range(bp);
-		func_exit();
-		return 1;
-	}
-#endif
-	printk (KERN_INFO "Started with irq=%d, but now have irq=%d.\n", bp->irq, irqs);
-	if (irqs > 0)
-		bp->irq = irqs;
-#endif
 	/* Reset CD186x again  */
 	if (!sx_init_CD186x(bp)) {
 		sx_release_io_range(bp);
@@ -560,7 +478,7 @@
 	bp->flags |= SX_BOARD_PRESENT;
 
 	/* Chip           revcode   pkgtype
-	                  GFRCR     SRCR bit 7
+			  GFRCR     SRCR bit 7
 	   CD180 rev B    0x81      0
 	   CD180 rev C    0x82      0
 	   CD1864 rev A   0x82      1
@@ -570,24 +488,32 @@
 	 */
 
 	switch (sx_in_off(bp, CD186x_GFRCR)) {
-	case 0x82:chip = 1864;rev='A';break;
-	case 0x83:chip = 1865;rev='A';break;
-	case 0x84:chip = 1865;rev='B';break;
-	case 0x85:chip = 1865;rev='C';break; /* Does not exist at this time */
-	default:chip=-1;rev='x';
+	case 0x82:
+		chip = 1864;
+		rev = 'A';
+		break;
+	case 0x83:
+		chip = 1865;
+		rev = 'A';
+		break;
+	case 0x84:
+		chip = 1865;
+		rev = 'B';
+		break;
+	case 0x85:
+		chip = 1865;
+		rev = 'C';
+		break; /* Does not exist at this time */
+	default:
+		chip = -1;
+		rev = 'x';
 	}
 
-	dprintk (SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR) );
+	dprintk(SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR));
 
-#ifdef SPECIALIX_TIMER
-	setup_timer(&missed_irq_timer, missed_irq, (unsigned long)bp);
-	mod_timer(&missed_irq_timer, jiffies + sx_poll);
-#endif
-
-	printk(KERN_INFO"sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n",
-	       board_No(bp),
-	       bp->base, bp->irq,
-	       chip, rev);
+	printk(KERN_INFO
+    "sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n",
+				board_No(bp), bp->base, bp->irq, chip, rev);
 
 	func_exit();
 	return 0;
@@ -598,20 +524,22 @@
  *  Interrupt processing routines.
  * */
 
-static inline struct specialix_port * sx_get_port(struct specialix_board * bp,
-					       unsigned char const * what)
+static struct specialix_port *sx_get_port(struct specialix_board *bp,
+					       unsigned char const *what)
 {
 	unsigned char channel;
-	struct specialix_port * port = NULL;
+	struct specialix_port *port = NULL;
 
 	channel = sx_in(bp, CD186x_GICR) >> GICR_CHAN_OFF;
-	dprintk (SX_DEBUG_CHAN, "channel: %d\n", channel);
+	dprintk(SX_DEBUG_CHAN, "channel: %d\n", channel);
 	if (channel < CD186x_NCH) {
 		port = &sx_port[board_No(bp) * SX_NPORT + channel];
-		dprintk (SX_DEBUG_CHAN, "port: %d %p flags: 0x%lx\n",board_No(bp) * SX_NPORT + channel,  port, port->port.flags & ASYNC_INITIALIZED);
+		dprintk(SX_DEBUG_CHAN, "port: %d %p flags: 0x%lx\n",
+			board_No(bp) * SX_NPORT + channel,  port,
+			port->port.flags & ASYNC_INITIALIZED);
 
 		if (port->port.flags & ASYNC_INITIALIZED) {
-			dprintk (SX_DEBUG_CHAN, "port: %d %p\n", channel, port);
+			dprintk(SX_DEBUG_CHAN, "port: %d %p\n", channel, port);
 			func_exit();
 			return port;
 		}
@@ -622,7 +550,7 @@
 }
 
 
-static inline void sx_receive_exc(struct specialix_board * bp)
+static void sx_receive_exc(struct specialix_board *bp)
 {
 	struct specialix_port *port;
 	struct tty_struct *tty;
@@ -633,7 +561,7 @@
 
 	port = sx_get_port(bp, "Receive");
 	if (!port) {
-		dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n");
+		dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n");
 		func_exit();
 		return;
 	}
@@ -641,19 +569,21 @@
 
 	status = sx_in(bp, CD186x_RCSR);
 
-	dprintk (SX_DEBUG_RX, "status: 0x%x\n", status);
+	dprintk(SX_DEBUG_RX, "status: 0x%x\n", status);
 	if (status & RCSR_OE) {
 		port->overrun++;
-		dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Overrun. Total %ld overruns.\n",
-		       board_No(bp), port_No(port), port->overrun);
+		dprintk(SX_DEBUG_FIFO,
+			"sx%d: port %d: Overrun. Total %ld overruns.\n",
+				board_No(bp), port_No(port), port->overrun);
 	}
 	status &= port->mark_mask;
 
 	/* This flip buffer check needs to be below the reading of the
 	   status register to reset the chip's IRQ.... */
 	if (tty_buffer_request_room(tty, 1) == 0) {
-		dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Working around flip buffer overflow.\n",
-		       board_No(bp), port_No(port));
+		dprintk(SX_DEBUG_FIFO,
+		    "sx%d: port %d: Working around flip buffer overflow.\n",
+					board_No(bp), port_No(port));
 		func_exit();
 		return;
 	}
@@ -664,8 +594,9 @@
 		return;
 	}
 	if (status & RCSR_TOUT) {
-		printk(KERN_INFO "sx%d: port %d: Receiver timeout. Hardware problems ?\n",
-		       board_No(bp), port_No(port));
+		printk(KERN_INFO
+		    "sx%d: port %d: Receiver timeout. Hardware problems ?\n",
+					board_No(bp), port_No(port));
 		func_exit();
 		return;
 
@@ -688,13 +619,13 @@
 	else
 		flag = TTY_NORMAL;
 
-	if(tty_insert_flip_char(tty, ch, flag))
+	if (tty_insert_flip_char(tty, ch, flag))
 		tty_flip_buffer_push(tty);
 	func_exit();
 }
 
 
-static inline void sx_receive(struct specialix_board * bp)
+static void sx_receive(struct specialix_board *bp)
 {
 	struct specialix_port *port;
 	struct tty_struct *tty;
@@ -702,15 +633,16 @@
 
 	func_enter();
 
-	if (!(port = sx_get_port(bp, "Receive"))) {
-		dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n");
+	port = sx_get_port(bp, "Receive");
+	if (port == NULL) {
+		dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n");
 		func_exit();
 		return;
 	}
 	tty = port->port.tty;
 
 	count = sx_in(bp, CD186x_RDCR);
-	dprintk (SX_DEBUG_RX, "port: %p: count: %d\n", port, count);
+	dprintk(SX_DEBUG_RX, "port: %p: count: %d\n", port, count);
 	port->hits[count > 8 ? 9 : count]++;
 
 	tty_buffer_request_room(tty, count);
@@ -722,18 +654,19 @@
 }
 
 
-static inline void sx_transmit(struct specialix_board * bp)
+static void sx_transmit(struct specialix_board *bp)
 {
 	struct specialix_port *port;
 	struct tty_struct *tty;
 	unsigned char count;
 
 	func_enter();
-	if (!(port = sx_get_port(bp, "Transmit"))) {
+	port = sx_get_port(bp, "Transmit");
+	if (port == NULL) {
 		func_exit();
 		return;
 	}
-	dprintk (SX_DEBUG_TX, "port: %p\n", port);
+	dprintk(SX_DEBUG_TX, "port: %p\n", port);
 	tty = port->port.tty;
 
 	if (port->IER & IER_TXEMPTY) {
@@ -765,7 +698,8 @@
 			sx_out(bp, CD186x_TDR, CD186x_C_ESC);
 			sx_out(bp, CD186x_TDR, CD186x_C_DELAY);
 			sx_out(bp, CD186x_TDR, count);
-			if (!(port->break_length -= count))
+			port->break_length -= count;
+			if (port->break_length == 0)
 				port->break_length--;
 		} else {
 			sx_out(bp, CD186x_TDR, CD186x_C_ESC);
@@ -794,36 +728,36 @@
 		sx_out(bp, CD186x_IER, port->IER);
 	}
 	if (port->xmit_cnt <= port->wakeup_chars)
- 		tty_wakeup(tty);
+		tty_wakeup(tty);
 
 	func_exit();
 }
 
 
-static inline void sx_check_modem(struct specialix_board * bp)
+static void sx_check_modem(struct specialix_board *bp)
 {
 	struct specialix_port *port;
 	struct tty_struct *tty;
 	unsigned char mcr;
 	int msvr_cd;
 
-	dprintk (SX_DEBUG_SIGNALS, "Modem intr. ");
-	if (!(port = sx_get_port(bp, "Modem")))
+	dprintk(SX_DEBUG_SIGNALS, "Modem intr. ");
+	port = sx_get_port(bp, "Modem");
+	if (port == NULL)
 		return;
 
 	tty = port->port.tty;
 
 	mcr = sx_in(bp, CD186x_MCR);
-	printk ("mcr = %02x.\n", mcr);
 
 	if ((mcr & MCR_CDCHG)) {
-		dprintk (SX_DEBUG_SIGNALS, "CD just changed... ");
+		dprintk(SX_DEBUG_SIGNALS, "CD just changed... ");
 		msvr_cd = sx_in(bp, CD186x_MSVR) & MSVR_CD;
 		if (msvr_cd) {
-			dprintk (SX_DEBUG_SIGNALS, "Waking up guys in open.\n");
+			dprintk(SX_DEBUG_SIGNALS, "Waking up guys in open.\n");
 			wake_up_interruptible(&port->port.open_wait);
 		} else {
-			dprintk (SX_DEBUG_SIGNALS, "Sending HUP.\n");
+			dprintk(SX_DEBUG_SIGNALS, "Sending HUP.\n");
 			tty_hangup(tty);
 		}
 	}
@@ -874,9 +808,12 @@
 
 	spin_lock_irqsave(&bp->lock, flags);
 
-	dprintk (SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __func__, port_No(sx_get_port(bp, "INT")), SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1);
+	dprintk(SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __func__,
+		port_No(sx_get_port(bp, "INT")),
+		SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1);
 	if (!(bp->flags & SX_BOARD_ACTIVE)) {
-		dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", bp->irq);
+		dprintk(SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n",
+								bp->irq);
 		spin_unlock_irqrestore(&bp->lock, flags);
 		func_exit();
 		return IRQ_NONE;
@@ -884,10 +821,11 @@
 
 	saved_reg = bp->reg;
 
-	while ((++loop < 16) && (status = (sx_in(bp, CD186x_SRSR) &
-	                                   (SRSR_RREQint |
-		                            SRSR_TREQint |
-	                                    SRSR_MREQint)))) {
+	while (++loop < 16) {
+		status = sx_in(bp, CD186x_SRSR) &
+				(SRSR_RREQint | SRSR_TREQint | SRSR_MREQint);
+		if (status == 0)
+			break;
 		if (status & SRSR_RREQint) {
 			ack = sx_in(bp, CD186x_RRAR);
 
@@ -896,8 +834,9 @@
 			else if (ack == (SX_ID | GIVR_IT_REXC))
 				sx_receive_exc(bp);
 			else
-				printk(KERN_ERR "sx%d: status: 0x%x Bad receive ack 0x%02x.\n",
-				       board_No(bp), status, ack);
+				printk(KERN_ERR
+				"sx%d: status: 0x%x Bad receive ack 0x%02x.\n",
+						board_No(bp), status, ack);
 
 		} else if (status & SRSR_TREQint) {
 			ack = sx_in(bp, CD186x_TRAR);
@@ -906,14 +845,16 @@
 				sx_transmit(bp);
 			else
 				printk(KERN_ERR "sx%d: status: 0x%x Bad transmit ack 0x%02x. port: %d\n",
-				       board_No(bp), status, ack, port_No (sx_get_port (bp, "Int")));
+					board_No(bp), status, ack,
+					port_No(sx_get_port(bp, "Int")));
 		} else if (status & SRSR_MREQint) {
 			ack = sx_in(bp, CD186x_MRAR);
 
 			if (ack == (SX_ID | GIVR_IT_MODEM))
 				sx_check_modem(bp);
 			else
-				printk(KERN_ERR "sx%d: status: 0x%x Bad modem ack 0x%02x.\n",
+				printk(KERN_ERR
+				  "sx%d: status: 0x%x Bad modem ack 0x%02x.\n",
 				       board_No(bp), status, ack);
 
 		}
@@ -921,7 +862,7 @@
 		sx_out(bp, CD186x_EOIR, 0);   /* Mark end of interrupt */
 	}
 	bp->reg = saved_reg;
-	outb (bp->reg, bp->base + SX_ADDR_REG);
+	outb(bp->reg, bp->base + SX_ADDR_REG);
 	spin_unlock_irqrestore(&bp->lock, flags);
 	func_exit();
 	return IRQ_HANDLED;
@@ -932,36 +873,26 @@
  *  Routines for open & close processing.
  */
 
-static void turn_ints_off (struct specialix_board *bp)
+static void turn_ints_off(struct specialix_board *bp)
 {
 	unsigned long flags;
 
 	func_enter();
-	if (bp->flags & SX_BOARD_IS_PCI) {
-		/* This was intended for enabeling the interrupt on the
-		 * PCI card. However it seems that it's already enabled
-		 * and as PCI interrupts can be shared, there is no real
-		 * reason to have to turn it off. */
-	}
-
 	spin_lock_irqsave(&bp->lock, flags);
-	(void) sx_in_off (bp, 0); /* Turn off interrupts. */
+	(void) sx_in_off(bp, 0); /* Turn off interrupts. */
 	spin_unlock_irqrestore(&bp->lock, flags);
 
 	func_exit();
 }
 
-static void turn_ints_on (struct specialix_board *bp)
+static void turn_ints_on(struct specialix_board *bp)
 {
 	unsigned long flags;
 
 	func_enter();
 
-	if (bp->flags & SX_BOARD_IS_PCI) {
-		/* play with the PCI chip. See comment above. */
-	}
 	spin_lock_irqsave(&bp->lock, flags);
-	(void) sx_in (bp, 0); /* Turn ON interrupts. */
+	(void) sx_in(bp, 0); /* Turn ON interrupts. */
 	spin_unlock_irqrestore(&bp->lock, flags);
 
 	func_exit();
@@ -969,7 +900,7 @@
 
 
 /* Called with disabled interrupts */
-static inline int sx_setup_board(struct specialix_board * bp)
+static int sx_setup_board(struct specialix_board *bp)
 {
 	int error;
 
@@ -977,14 +908,16 @@
 		return 0;
 
 	if (bp->flags & SX_BOARD_IS_PCI)
-		error = request_irq(bp->irq, sx_interrupt, IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp);
+		error = request_irq(bp->irq, sx_interrupt,
+			IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp);
 	else
-		error = request_irq(bp->irq, sx_interrupt, IRQF_DISABLED, "specialix IO8+", bp);
+		error = request_irq(bp->irq, sx_interrupt,
+			IRQF_DISABLED, "specialix IO8+", bp);
 
 	if (error)
 		return error;
 
-	turn_ints_on (bp);
+	turn_ints_on(bp);
 	bp->flags |= SX_BOARD_ACTIVE;
 
 	return 0;
@@ -992,7 +925,7 @@
 
 
 /* Called with disabled interrupts */
-static inline void sx_shutdown_board(struct specialix_board *bp)
+static void sx_shutdown_board(struct specialix_board *bp)
 {
 	func_enter();
 
@@ -1003,22 +936,26 @@
 
 	bp->flags &= ~SX_BOARD_ACTIVE;
 
-	dprintk (SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n",
-		 bp->irq, board_No (bp));
+	dprintk(SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n",
+		 bp->irq, board_No(bp));
 	free_irq(bp->irq, bp);
-
-	turn_ints_off (bp);
-
-
+	turn_ints_off(bp);
 	func_exit();
 }
 
+static unsigned int sx_crtscts(struct tty_struct *tty)
+{
+	if (sx_rtscts)
+		return C_CRTSCTS(tty);
+	return 1;
+}
 
 /*
  * Setting up port characteristics.
  * Must be called with disabled interrupts
  */
-static void sx_change_speed(struct specialix_board *bp, struct specialix_port *port)
+static void sx_change_speed(struct specialix_board *bp,
+						struct specialix_port *port)
 {
 	struct tty_struct *tty;
 	unsigned long baud;
@@ -1030,7 +967,8 @@
 
 	func_enter();
 
-	if (!(tty = port->port.tty) || !tty->termios) {
+	tty = port->port.tty;
+	if (!tty || !tty->termios) {
 		func_exit();
 		return;
 	}
@@ -1043,12 +981,12 @@
 
 	/* The Specialix board doens't implement the RTS lines.
 	   They are used to set the IRQ level. Don't touch them. */
-	if (SX_CRTSCTS(tty))
+	if (sx_crtscts(tty))
 		port->MSVR = MSVR_DTR | (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
 	else
 		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);
+	dprintk(SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR);
 	baud = tty_get_baud_rate(tty);
 
 	if (baud == 38400) {
@@ -1060,21 +998,19 @@
 
 	if (!baud) {
 		/* Drop DTR & exit */
-		dprintk (SX_DEBUG_TERMIOS, "Dropping DTR...  Hmm....\n");
-		if (!SX_CRTSCTS (tty)) {
-			port -> MSVR &= ~ MSVR_DTR;
+		dprintk(SX_DEBUG_TERMIOS, "Dropping DTR...  Hmm....\n");
+		if (!sx_crtscts(tty)) {
+			port->MSVR &= ~MSVR_DTR;
 			spin_lock_irqsave(&bp->lock, flags);
-			sx_out(bp, CD186x_MSVR, port->MSVR );
+			sx_out(bp, CD186x_MSVR, port->MSVR);
 			spin_unlock_irqrestore(&bp->lock, flags);
-		}
-		else
-			dprintk (SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n");
+		} else
+			dprintk(SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n");
 		return;
 	} else {
 		/* Set DTR on */
-		if (!SX_CRTSCTS (tty)) {
-			port ->MSVR |= MSVR_DTR;
-		}
+		if (!sx_crtscts(tty))
+			port->MSVR |= MSVR_DTR;
 	}
 
 	/*
@@ -1083,28 +1019,27 @@
 
 	/* Set baud rate for port */
 	tmp = port->custom_divisor ;
-	if ( tmp )
-		printk (KERN_INFO "sx%d: Using custom baud rate divisor %ld. \n"
-		                  "This is an untested option, please be carefull.\n",
-		                  port_No (port), tmp);
+	if (tmp)
+		printk(KERN_INFO
+			"sx%d: Using custom baud rate divisor %ld. \n"
+			"This is an untested option, please be careful.\n",
+							port_No(port), tmp);
 	else
-		tmp = (((SX_OSCFREQ + baud/2) / baud +
-		         CD186x_TPC/2) / CD186x_TPC);
+		tmp = (((SX_OSCFREQ + baud/2) / baud + CD186x_TPC/2) /
+								CD186x_TPC);
 
-	if ((tmp < 0x10) && time_before(again, jiffies)) {
+	if (tmp < 0x10 && time_before(again, jiffies)) {
 		again = jiffies + HZ * 60;
 		/* Page 48 of version 2.0 of the CL-CD1865 databook */
 		if (tmp >= 12) {
-			printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
-			        "Performance degradation is possible.\n"
-			        "Read specialix.txt for more info.\n",
-			        port_No (port), tmp);
+			printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
+				"Performance degradation is possible.\n"
+				"Read specialix.txt for more info.\n",
+						port_No(port), tmp);
 		} else {
-			printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
-			        "Warning: overstressing Cirrus chip. "
-			        "This might not work.\n"
-			        "Read specialix.txt for more info.\n",
-			        port_No (port), tmp);
+			printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
+		"Warning: overstressing Cirrus chip. This might not work.\n"
+		"Read specialix.txt for more info.\n", port_No(port), tmp);
 		}
 	}
 	spin_lock_irqsave(&bp->lock, flags);
@@ -1114,7 +1049,8 @@
 	sx_out(bp, CD186x_TBPRL, tmp & 0xff);
 	spin_unlock_irqrestore(&bp->lock, flags);
 	if (port->custom_divisor)
-		baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor;
+		baud = (SX_OSCFREQ + port->custom_divisor/2) /
+							port->custom_divisor;
 	baud = (baud + 5) / 10;		/* Estimated CPS */
 
 	/* Two timer ticks seems enough to wakeup something like SLIP driver */
@@ -1129,16 +1065,16 @@
 	sx_out(bp, CD186x_RTPR, tmp);
 	spin_unlock_irqrestore(&bp->lock, flags);
 	switch (C_CSIZE(tty)) {
-	 case CS5:
+	case CS5:
 		cor1 |= COR1_5BITS;
 		break;
-	 case CS6:
+	case CS6:
 		cor1 |= COR1_6BITS;
 		break;
-	 case CS7:
+	case CS7:
 		cor1 |= COR1_7BITS;
 		break;
-	 case CS8:
+	case CS8:
 		cor1 |= COR1_8BITS;
 		break;
 	}
@@ -1175,7 +1111,8 @@
 		mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD;
 		mcor2 |= MCOR2_DSROD | MCOR2_CTSOD;
 		spin_lock_irqsave(&bp->lock, flags);
-		tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & (MSVR_CTS|MSVR_DSR));
+		tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) &
+							(MSVR_CTS|MSVR_DSR));
 		spin_unlock_irqrestore(&bp->lock, flags);
 #else
 		port->COR2 |= COR2_CTSAE;
@@ -1219,7 +1156,8 @@
 	spin_lock_irqsave(&bp->lock, flags);
 	sx_out(bp, CD186x_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
 	/* Setting up modem option registers */
-	dprintk (SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n", mcor1, mcor2);
+	dprintk(SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n",
+								mcor1, mcor2);
 	sx_out(bp, CD186x_MCOR1, mcor1);
 	sx_out(bp, CD186x_MCOR2, mcor2);
 	spin_unlock_irqrestore(&bp->lock, flags);
@@ -1238,7 +1176,8 @@
 
 
 /* Must be called with interrupts enabled */
-static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port)
+static int sx_setup_port(struct specialix_board *bp,
+						struct specialix_port *port)
 {
 	unsigned long flags;
 
@@ -1253,7 +1192,8 @@
 		/* We may sleep in get_zeroed_page() */
 		unsigned long tmp;
 
-		if (!(tmp = get_zeroed_page(GFP_KERNEL))) {
+		tmp = get_zeroed_page(GFP_KERNEL);
+		if (tmp == 0L) {
 			func_exit();
 			return -ENOMEM;
 		}
@@ -1284,7 +1224,8 @@
 
 
 /* Must be called with interrupts disabled */
-static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port *port)
+static void sx_shutdown_port(struct specialix_board *bp,
+						struct specialix_port *port)
 {
 	struct tty_struct *tty;
 	int i;
@@ -1298,11 +1239,11 @@
 	}
 
 	if (sx_debug & SX_DEBUG_FIFO) {
-		dprintk(SX_DEBUG_FIFO, "sx%d: port %d: %ld overruns, FIFO hits [ ",
-			board_No(bp), port_No(port), port->overrun);
-		for (i = 0; i < 10; i++) {
+		dprintk(SX_DEBUG_FIFO,
+			"sx%d: port %d: %ld overruns, FIFO hits [ ",
+				board_No(bp), port_No(port), port->overrun);
+		for (i = 0; i < 10; i++)
 			dprintk(SX_DEBUG_FIFO, "%ld ", port->hits[i]);
-		}
 		dprintk(SX_DEBUG_FIFO, "].\n");
 	}
 
@@ -1315,7 +1256,8 @@
 	spin_lock_irqsave(&bp->lock, flags);
 	sx_out(bp, CD186x_CAR, port_No(port));
 
-	if (!(tty = port->port.tty) || C_HUPCL(tty)) {
+	tty = port->port.tty;
+	if (tty == NULL || C_HUPCL(tty)) {
 		/* Drop DTR */
 		sx_out(bp, CD186x_MSVDTR, 0);
 	}
@@ -1338,8 +1280,8 @@
 }
 
 
-static int block_til_ready(struct tty_struct *tty, struct file * filp,
-                           struct specialix_port *port)
+static int block_til_ready(struct tty_struct *tty, struct file *filp,
+						struct specialix_port *port)
 {
 	DECLARE_WAITQUEUE(wait,  current);
 	struct specialix_board *bp = port_Board(port);
@@ -1389,23 +1331,22 @@
 	retval = 0;
 	add_wait_queue(&port->port.open_wait, &wait);
 	spin_lock_irqsave(&port->lock, flags);
-	if (!tty_hung_up_p(filp)) {
+	if (!tty_hung_up_p(filp))
 		port->port.count--;
-	}
 	spin_unlock_irqrestore(&port->lock, flags);
 	port->port.blocked_open++;
 	while (1) {
 		spin_lock_irqsave(&bp->lock, flags);
 		sx_out(bp, CD186x_CAR, port_No(port));
 		CD = sx_in(bp, CD186x_MSVR) & MSVR_CD;
-		if (SX_CRTSCTS (tty)) {
+		if (sx_crtscts(tty)) {
 			/* Activate RTS */
 			port->MSVR |= MSVR_DTR;		/* WTF? */
-			sx_out (bp, CD186x_MSVR, port->MSVR);
+			sx_out(bp, CD186x_MSVR, port->MSVR);
 		} else {
 			/* Activate DTR */
 			port->MSVR |= MSVR_DTR;
-			sx_out (bp, CD186x_MSVR, port->MSVR);
+			sx_out(bp, CD186x_MSVR, port->MSVR);
 		}
 		spin_unlock_irqrestore(&bp->lock, flags);
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -1430,9 +1371,8 @@
 	set_current_state(TASK_RUNNING);
 	remove_wait_queue(&port->port.open_wait, &wait);
 	spin_lock_irqsave(&port->lock, flags);
-	if (!tty_hung_up_p(filp)) {
+	if (!tty_hung_up_p(filp))
 		port->port.count++;
-	}
 	port->port.blocked_open--;
 	spin_unlock_irqrestore(&port->lock, flags);
 	if (retval) {
@@ -1446,12 +1386,12 @@
 }
 
 
-static int sx_open(struct tty_struct * tty, struct file * filp)
+static int sx_open(struct tty_struct *tty, struct file *filp)
 {
 	int board;
 	int error;
-	struct specialix_port * port;
-	struct specialix_board * bp;
+	struct specialix_port *port;
+	struct specialix_board *bp;
 	int i;
 	unsigned long flags;
 
@@ -1468,17 +1408,19 @@
 	port = sx_port + board * SX_NPORT + SX_PORT(tty->index);
 	port->overrun = 0;
 	for (i = 0; i < 10; i++)
-		port->hits[i]=0;
+		port->hits[i] = 0;
 
-	dprintk (SX_DEBUG_OPEN, "Board = %d, bp = %p, port = %p, portno = %d.\n",
-	        board, bp, port, SX_PORT(tty->index));
+	dprintk(SX_DEBUG_OPEN,
+			"Board = %d, bp = %p, port = %p, portno = %d.\n",
+				 board, bp, port, SX_PORT(tty->index));
 
 	if (sx_paranoia_check(port, tty->name, "sx_open")) {
 		func_enter();
 		return -ENODEV;
 	}
 
-	if ((error = sx_setup_board(bp))) {
+	error = sx_setup_board(bp);
+	if (error) {
 		func_exit();
 		return error;
 	}
@@ -1490,12 +1432,14 @@
 	port->port.tty = tty;
 	spin_unlock_irqrestore(&bp->lock, flags);
 
-	if ((error = sx_setup_port(bp, port))) {
+	error = sx_setup_port(bp, port);
+	if (error) {
 		func_enter();
 		return error;
 	}
 
-	if ((error = block_til_ready(tty, filp, port))) {
+	error = block_til_ready(tty, filp, port);
+	if (error) {
 		func_enter();
 		return error;
 	}
@@ -1508,7 +1452,7 @@
 {
 	struct specialix_port *port = (struct specialix_port *)tty->driver_data;
 	unsigned long flags;
-	struct specialix_board  * bp;
+	struct specialix_board  *bp;
 
 	func_enter();
 
@@ -1526,9 +1470,9 @@
 	func_exit();
 }
 
-static void sx_close(struct tty_struct * tty, struct file * filp)
+static void sx_close(struct tty_struct *tty, struct file *filp)
 {
-	struct specialix_port *port = (struct specialix_port *) tty->driver_data;
+	struct specialix_port *port = (struct specialix_port *)tty->driver_data;
 	struct specialix_board *bp;
 	unsigned long flags;
 	unsigned long timeout;
@@ -1547,7 +1491,7 @@
 	}
 
 	bp = port_Board(port);
-	if ((tty->count == 1) && (port->port.count != 1)) {
+	if (tty->count == 1 && port->port.count != 1) {
 		printk(KERN_ERR "sx%d: sx_close: bad port count;"
 		       " tty->count is 1, port count is %d\n",
 		       board_No(bp), port->port.count);
@@ -1570,17 +1514,16 @@
 	 */
 	tty->closing = 1;
 	spin_unlock_irqrestore(&port->lock, flags);
-	dprintk (SX_DEBUG_OPEN, "Closing\n");
-	if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) {
+	dprintk(SX_DEBUG_OPEN, "Closing\n");
+	if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE)
 		tty_wait_until_sent(tty, port->port.closing_wait);
-	}
 	/*
 	 * At this point we stop accepting input.  To do this, we
 	 * disable the receive line status interrupts, and tell the
 	 * interrupt driver to stop checking the data ready bit in the
 	 * line status register.
 	 */
-	dprintk (SX_DEBUG_OPEN, "Closed\n");
+	dprintk(SX_DEBUG_OPEN, "Closed\n");
 	port->IER &= ~IER_RXD;
 	if (port->port.flags & ASYNC_INITIALIZED) {
 		port->IER &= ~IER_TXRDY;
@@ -1595,11 +1538,11 @@
 		 * important if there is a transmit FIFO!
 		 */
 		timeout = jiffies+HZ;
-		while(port->IER & IER_TXEMPTY) {
-			set_current_state (TASK_INTERRUPTIBLE);
+		while (port->IER & IER_TXEMPTY) {
+			set_current_state(TASK_INTERRUPTIBLE);
 			msleep_interruptible(jiffies_to_msecs(port->timeout));
 			if (time_after(jiffies, timeout)) {
-				printk (KERN_INFO "Timeout waiting for close\n");
+				printk(KERN_INFO "Timeout waiting for close\n");
 				break;
 			}
 		}
@@ -1607,13 +1550,15 @@
 	}
 
 	if (--bp->count < 0) {
-		printk(KERN_ERR "sx%d: sx_shutdown_port: bad board count: %d port: %d\n",
-		       board_No(bp), bp->count, tty->index);
+		printk(KERN_ERR
+		    "sx%d: sx_shutdown_port: bad board count: %d port: %d\n",
+				board_No(bp), bp->count, tty->index);
 		bp->count = 0;
 	}
 	if (--port->port.count < 0) {
-		printk(KERN_ERR "sx%d: sx_close: bad port count for tty%d: %d\n",
-		       board_No(bp), port_No(port), port->port.count);
+		printk(KERN_ERR
+			"sx%d: sx_close: bad port count for tty%d: %d\n",
+				board_No(bp), port_No(port), port->port.count);
 		port->port.count = 0;
 	}
 
@@ -1625,9 +1570,9 @@
 	port->port.tty = NULL;
 	spin_unlock_irqrestore(&port->lock, flags);
 	if (port->port.blocked_open) {
-		if (port->port.close_delay) {
-			msleep_interruptible(jiffies_to_msecs(port->port.close_delay));
-		}
+		if (port->port.close_delay)
+			msleep_interruptible(
+				jiffies_to_msecs(port->port.close_delay));
 		wake_up_interruptible(&port->port.open_wait);
 	}
 	port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
@@ -1637,8 +1582,8 @@
 }
 
 
-static int sx_write(struct tty_struct * tty,
-                    const unsigned char *buf, int count)
+static int sx_write(struct tty_struct *tty,
+					const unsigned char *buf, int count)
 {
 	struct specialix_port *port = (struct specialix_port *)tty->driver_data;
 	struct specialix_board *bp;
@@ -1690,11 +1635,11 @@
 }
 
 
-static int sx_put_char(struct tty_struct * tty, unsigned char ch)
+static int sx_put_char(struct tty_struct *tty, unsigned char ch)
 {
 	struct specialix_port *port = (struct specialix_port *)tty->driver_data;
 	unsigned long flags;
-	struct specialix_board  * bp;
+	struct specialix_board  *bp;
 
 	func_enter();
 
@@ -1702,7 +1647,7 @@
 		func_exit();
 		return 0;
 	}
-	dprintk (SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf);
+	dprintk(SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf);
 	if (!port->xmit_buf) {
 		func_exit();
 		return 0;
@@ -1710,14 +1655,15 @@
 	bp = port_Board(port);
 	spin_lock_irqsave(&port->lock, flags);
 
-	dprintk (SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n", port->xmit_cnt, port->xmit_buf);
-	if ((port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) || (!port->xmit_buf)) {
+	dprintk(SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n",
+					port->xmit_cnt, port->xmit_buf);
+	if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1 || !port->xmit_buf) {
 		spin_unlock_irqrestore(&port->lock, flags);
-		dprintk (SX_DEBUG_TX, "Exit size\n");
+		dprintk(SX_DEBUG_TX, "Exit size\n");
 		func_exit();
 		return 0;
 	}
-	dprintk (SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf);
+	dprintk(SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf);
 	port->xmit_buf[port->xmit_head++] = ch;
 	port->xmit_head &= SERIAL_XMIT_SIZE - 1;
 	port->xmit_cnt++;
@@ -1728,11 +1674,11 @@
 }
 
 
-static void sx_flush_chars(struct tty_struct * tty)
+static void sx_flush_chars(struct tty_struct *tty)
 {
 	struct specialix_port *port = (struct specialix_port *)tty->driver_data;
 	unsigned long flags;
-	struct specialix_board  * bp = port_Board(port);
+	struct specialix_board  *bp = port_Board(port);
 
 	func_enter();
 
@@ -1755,7 +1701,7 @@
 }
 
 
-static int sx_write_room(struct tty_struct * tty)
+static int sx_write_room(struct tty_struct *tty)
 {
 	struct specialix_port *port = (struct specialix_port *)tty->driver_data;
 	int	ret;
@@ -1790,12 +1736,10 @@
 	return port->xmit_cnt;
 }
 
-
-
 static int sx_tiocmget(struct tty_struct *tty, struct file *file)
 {
 	struct specialix_port *port = (struct specialix_port *)tty->driver_data;
-	struct specialix_board * bp;
+	struct specialix_board *bp;
 	unsigned char status;
 	unsigned int result;
 	unsigned long flags;
@@ -1808,25 +1752,23 @@
 	}
 
 	bp = port_Board(port);
-	spin_lock_irqsave (&bp->lock, flags);
+	spin_lock_irqsave(&bp->lock, flags);
 	sx_out(bp, CD186x_CAR, port_No(port));
 	status = sx_in(bp, CD186x_MSVR);
 	spin_unlock_irqrestore(&bp->lock, flags);
-	dprintk (SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n",
-		port_No(port), status, sx_in (bp, CD186x_CAR));
-	dprintk (SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port);
-	if (SX_CRTSCTS(port->port.tty)) {
-		result  = /*   (status & MSVR_RTS) ? */ TIOCM_DTR /* : 0) */
-		          |   ((status & MSVR_DTR) ? TIOCM_RTS : 0)
-		          |   ((status & MSVR_CD)  ? TIOCM_CAR : 0)
-		          |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
-		          |   ((status & MSVR_CTS) ? TIOCM_CTS : 0);
+	dprintk(SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n",
+			port_No(port), status, sx_in(bp, CD186x_CAR));
+	dprintk(SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port);
+	if (sx_crtscts(port->port.tty)) {
+		result  = TIOCM_DTR | TIOCM_DSR
+			  |   ((status & MSVR_DTR) ? TIOCM_RTS : 0)
+			  |   ((status & MSVR_CD)  ? TIOCM_CAR : 0)
+			  |   ((status & MSVR_CTS) ? TIOCM_CTS : 0);
 	} else {
-		result  = /*   (status & MSVR_RTS) ? */ TIOCM_RTS /* : 0) */
-		          |   ((status & MSVR_DTR) ? TIOCM_DTR : 0)
-		          |   ((status & MSVR_CD)  ? TIOCM_CAR : 0)
-		          |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
-		          |   ((status & MSVR_CTS) ? TIOCM_CTS : 0);
+		result  = TIOCM_RTS | TIOCM_DSR
+			  |   ((status & MSVR_DTR) ? TIOCM_DTR : 0)
+			  |   ((status & MSVR_CD)  ? TIOCM_CAR : 0)
+			  |   ((status & MSVR_CTS) ? TIOCM_CTS : 0);
 	}
 
 	func_exit();
@@ -1852,24 +1794,14 @@
 	bp = port_Board(port);
 
 	spin_lock_irqsave(&port->lock, flags);
-   /*	if (set & TIOCM_RTS)
-		port->MSVR |= MSVR_RTS; */
-   /*   if (set & TIOCM_DTR)
-		port->MSVR |= MSVR_DTR; */
-
-	if (SX_CRTSCTS(port->port.tty)) {
+	if (sx_crtscts(port->port.tty)) {
 		if (set & TIOCM_RTS)
 			port->MSVR |= MSVR_DTR;
 	} else {
 		if (set & TIOCM_DTR)
 			port->MSVR |= MSVR_DTR;
 	}
-
-  /*	if (clear & TIOCM_RTS)
-		port->MSVR &= ~MSVR_RTS; */
-  /*    if (clear & TIOCM_DTR)
-		port->MSVR &= ~MSVR_DTR; */
-	if (SX_CRTSCTS(port->port.tty)) {
+	if (sx_crtscts(port->port.tty)) {
 		if (clear & TIOCM_RTS)
 			port->MSVR &= ~MSVR_DTR;
 	} else {
@@ -1886,14 +1818,17 @@
 }
 
 
-static inline void sx_send_break(struct specialix_port * port, unsigned long length)
+static int sx_send_break(struct tty_struct *tty, int length)
 {
+	struct specialix_port *port = (struct specialix_port *)tty->driver_data;
 	struct specialix_board *bp = port_Board(port);
 	unsigned long flags;
 
 	func_enter();
+	if (length == 0 || length == -1)
+		return -EOPNOTSUPP;
 
-	spin_lock_irqsave (&port->lock, flags);
+	spin_lock_irqsave(&port->lock, flags);
 	port->break_length = SPECIALIX_TPS / HZ * length;
 	port->COR2 |= COR2_ETC;
 	port->IER  |= IER_TXRDY;
@@ -1902,7 +1837,7 @@
 	sx_out(bp, CD186x_COR2, port->COR2);
 	sx_out(bp, CD186x_IER, port->IER);
 	spin_unlock_irqrestore(&bp->lock, flags);
-	spin_unlock_irqrestore (&port->lock, flags);
+	spin_unlock_irqrestore(&port->lock, flags);
 	sx_wait_CCR(bp);
 	spin_lock_irqsave(&bp->lock, flags);
 	sx_out(bp, CD186x_CCR, CCR_CORCHG2);
@@ -1910,11 +1845,12 @@
 	sx_wait_CCR(bp);
 
 	func_exit();
+	return 0;
 }
 
 
-static inline int sx_set_serial_info(struct specialix_port * port,
-                                     struct serial_struct __user * newinfo)
+static int sx_set_serial_info(struct specialix_port *port,
+					struct serial_struct __user *newinfo)
 {
 	struct serial_struct tmp;
 	struct specialix_board *bp = port_Board(port);
@@ -1943,25 +1879,25 @@
 			return -EPERM;
 		}
 		port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
-		                  (tmp.flags & ASYNC_USR_MASK));
+						(tmp.flags & ASYNC_USR_MASK));
 		port->custom_divisor = tmp.custom_divisor;
 	} else {
 		port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) |
-		                  (tmp.flags & ASYNC_FLAGS));
+						(tmp.flags & ASYNC_FLAGS));
 		port->port.close_delay = tmp.close_delay;
 		port->port.closing_wait = tmp.closing_wait;
 		port->custom_divisor = tmp.custom_divisor;
 	}
-	if (change_speed) {
+	if (change_speed)
 		sx_change_speed(bp, port);
-	}
+
 	func_exit();
 	unlock_kernel();
 	return 0;
 }
 
 
-static inline int sx_get_serial_info(struct specialix_port * port,
+static int sx_get_serial_info(struct specialix_port *port,
 				     struct serial_struct __user *retinfo)
 {
 	struct serial_struct tmp;
@@ -1992,11 +1928,10 @@
 }
 
 
-static int sx_ioctl(struct tty_struct * tty, struct file * filp,
-                    unsigned int cmd, unsigned long arg)
+static int sx_ioctl(struct tty_struct *tty, struct file *filp,
+				unsigned int cmd, unsigned long arg)
 {
 	struct specialix_port *port = (struct specialix_port *)tty->driver_data;
-	int retval;
 	void __user *argp = (void __user *)arg;
 
 	func_enter();
@@ -2007,34 +1942,14 @@
 	}
 
 	switch (cmd) {
-	 case TCSBRK:	/* SVID version: non-zero arg --> no break */
-		retval = tty_check_change(tty);
-		if (retval) {
-			func_exit();
-			return retval;
-		}
-		tty_wait_until_sent(tty, 0);
-		if (!arg)
-			sx_send_break(port, HZ/4);	/* 1/4 second */
-		return 0;
-	 case TCSBRKP:	/* support for POSIX tcsendbreak() */
-		retval = tty_check_change(tty);
-		if (retval) {
-			func_exit();
-			return retval;
-		}
-		tty_wait_until_sent(tty, 0);
-		sx_send_break(port, arg ? arg*(HZ/10) : HZ/4);
+	case TIOCGSERIAL:
 		func_exit();
-		return 0;
-	 case TIOCGSERIAL:
-		 func_exit();
 		return sx_get_serial_info(port, argp);
-	 case TIOCSSERIAL:
-		 func_exit();
+	case TIOCSSERIAL:
+		func_exit();
 		return sx_set_serial_info(port, argp);
-	 default:
-		 func_exit();
+	default:
+		func_exit();
 		return -ENOIOCTLCMD;
 	}
 	func_exit();
@@ -2042,7 +1957,7 @@
 }
 
 
-static void sx_throttle(struct tty_struct * tty)
+static void sx_throttle(struct tty_struct *tty)
 {
 	struct specialix_port *port = (struct specialix_port *)tty->driver_data;
 	struct specialix_board *bp;
@@ -2058,15 +1973,16 @@
 	bp = port_Board(port);
 
 	/* Use DTR instead of RTS ! */
-	if (SX_CRTSCTS (tty))
+	if (sx_crtscts(tty))
 		port->MSVR &= ~MSVR_DTR;
 	else {
 		/* Auch!!! I think the system shouldn't call this then. */
 		/* Or maybe we're supposed (allowed?) to do our side of hw
 		   handshake anyway, even when hardware handshake is off.
 		   When you see this in your logs, please report.... */
-		printk (KERN_ERR "sx%d: Need to throttle, but can't (hardware hs is off)\n",
-	                 port_No (port));
+		printk(KERN_ERR
+		   "sx%d: Need to throttle, but can't (hardware hs is off)\n",
+							port_No(port));
 	}
 	spin_lock_irqsave(&bp->lock, flags);
 	sx_out(bp, CD186x_CAR, port_No(port));
@@ -2086,7 +2002,7 @@
 }
 
 
-static void sx_unthrottle(struct tty_struct * tty)
+static void sx_unthrottle(struct tty_struct *tty)
 {
 	struct specialix_port *port = (struct specialix_port *)tty->driver_data;
 	struct specialix_board *bp;
@@ -2103,9 +2019,9 @@
 
 	spin_lock_irqsave(&port->lock, flags);
 	/* XXXX Use DTR INSTEAD???? */
-	if (SX_CRTSCTS(tty)) {
+	if (sx_crtscts(tty))
 		port->MSVR |= MSVR_DTR;
-	} /* Else clause: see remark in "sx_throttle"... */
+	/* Else clause: see remark in "sx_throttle"... */
 	spin_lock_irqsave(&bp->lock, flags);
 	sx_out(bp, CD186x_CAR, port_No(port));
 	spin_unlock_irqrestore(&bp->lock, flags);
@@ -2127,7 +2043,7 @@
 }
 
 
-static void sx_stop(struct tty_struct * tty)
+static void sx_stop(struct tty_struct *tty)
 {
 	struct specialix_port *port = (struct specialix_port *)tty->driver_data;
 	struct specialix_board *bp;
@@ -2154,7 +2070,7 @@
 }
 
 
-static void sx_start(struct tty_struct * tty)
+static void sx_start(struct tty_struct *tty)
 {
 	struct specialix_port *port = (struct specialix_port *)tty->driver_data;
 	struct specialix_board *bp;
@@ -2182,7 +2098,7 @@
 	func_exit();
 }
 
-static void sx_hangup(struct tty_struct * tty)
+static void sx_hangup(struct tty_struct *tty)
 {
 	struct specialix_port *port = (struct specialix_port *)tty->driver_data;
 	struct specialix_board *bp;
@@ -2201,8 +2117,9 @@
 	spin_lock_irqsave(&port->lock, flags);
 	bp->count -= port->port.count;
 	if (bp->count < 0) {
-		printk(KERN_ERR "sx%d: sx_hangup: bad board count: %d port: %d\n",
-			board_No(bp), bp->count, tty->index);
+		printk(KERN_ERR
+			"sx%d: sx_hangup: bad board count: %d port: %d\n",
+					board_No(bp), bp->count, tty->index);
 		bp->count = 0;
 	}
 	port->port.count = 0;
@@ -2215,11 +2132,12 @@
 }
 
 
-static void sx_set_termios(struct tty_struct * tty, struct ktermios * old_termios)
+static void sx_set_termios(struct tty_struct *tty,
+					struct ktermios *old_termios)
 {
 	struct specialix_port *port = (struct specialix_port *)tty->driver_data;
 	unsigned long flags;
-	struct specialix_board  * bp;
+	struct specialix_board  *bp;
 
 	if (sx_paranoia_check(port, tty->name, "sx_set_termios"))
 		return;
@@ -2254,6 +2172,7 @@
 	.hangup = sx_hangup,
 	.tiocmget = sx_tiocmget,
 	.tiocmset = sx_tiocmset,
+	.break_ctl = sx_send_break,
 };
 
 static int sx_init_drivers(void)
@@ -2280,13 +2199,16 @@
 		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
 	specialix_driver->init_termios.c_ispeed = 9600;
 	specialix_driver->init_termios.c_ospeed = 9600;
-	specialix_driver->flags = TTY_DRIVER_REAL_RAW;
+	specialix_driver->flags = TTY_DRIVER_REAL_RAW |
+						TTY_DRIVER_HARDWARE_BREAK;
 	tty_set_operations(specialix_driver, &sx_ops);
 
-	if ((error = tty_register_driver(specialix_driver))) {
+	error = tty_register_driver(specialix_driver);
+	if (error) {
 		put_tty_driver(specialix_driver);
-		printk(KERN_ERR "sx: Couldn't register specialix IO8+ driver, error = %d\n",
-		       error);
+		printk(KERN_ERR
+		  "sx: Couldn't register specialix IO8+ driver, error = %d\n",
+								error);
 		func_exit();
 		return 1;
 	}
@@ -2322,11 +2244,11 @@
 
 	printk(KERN_INFO "sx: Specialix IO8+ driver v" VERSION ", (c) R.E.Wolff 1997/1998.\n");
 	printk(KERN_INFO "sx: derived from work (c) D.Gorodchanin 1994-1996.\n");
-#ifdef CONFIG_SPECIALIX_RTSCTS
-	printk (KERN_INFO "sx: DTR/RTS pin is always RTS.\n");
-#else
-	printk (KERN_INFO "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n");
-#endif
+	if (sx_rtscts)
+		printk(KERN_INFO
+			"sx: DTR/RTS pin is RTS when CRTSCTS is on.\n");
+	else
+		printk(KERN_INFO "sx: DTR/RTS pin is always RTS.\n");
 
 	for (i = 0; i < SX_NBOARD; i++)
 		spin_lock_init(&sx_board[i].lock);
@@ -2344,27 +2266,27 @@
 	{
 		struct pci_dev *pdev = NULL;
 
-		i=0;
+		i = 0;
 		while (i < SX_NBOARD) {
 			if (sx_board[i].flags & SX_BOARD_PRESENT) {
 				i++;
 				continue;
 			}
-			pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX,
-			                        PCI_DEVICE_ID_SPECIALIX_IO8,
-			                        pdev);
-			if (!pdev) break;
+			pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX,
+					PCI_DEVICE_ID_SPECIALIX_IO8, pdev);
+			if (!pdev)
+				break;
 
 			if (pci_enable_device(pdev))
 				continue;
 
 			sx_board[i].irq = pdev->irq;
 
-			sx_board[i].base = pci_resource_start (pdev, 2);
+			sx_board[i].base = pci_resource_start(pdev, 2);
 
 			sx_board[i].flags |= SX_BOARD_IS_PCI;
 			if (!sx_probe(&sx_board[i]))
-				found ++;
+				found++;
 		}
 		/* May exit pci_get sequence early with lots of boards */
 		if (pdev != NULL)
@@ -2384,16 +2306,13 @@
 }
 
 static int iobase[SX_NBOARD]  = {0,};
-
-static int irq [SX_NBOARD] = {0,};
+static int irq[SX_NBOARD] = {0,};
 
 module_param_array(iobase, int, NULL, 0);
 module_param_array(irq, int, NULL, 0);
 module_param(sx_debug, int, 0);
+module_param(sx_rtscts, int, 0);
 module_param(sx_rxfifo, int, 0);
-#ifdef SPECIALIX_TIMER
-module_param(sx_poll, int, 0);
-#endif
 
 /*
  * You can setup up to 4 boards.
@@ -2411,10 +2330,10 @@
 	func_enter();
 
 	if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) {
-		for(i = 0; i < SX_NBOARD; i++) {
+		for (i = 0; i < SX_NBOARD; i++) {
 			sx_board[i].base = iobase[i];
 			sx_board[i].irq = irq[i];
-			sx_board[i].count= 0;
+			sx_board[i].count = 0;
 		}
 	}
 
@@ -2433,10 +2352,6 @@
 	for (i = 0; i < SX_NBOARD; i++)
 		if (sx_board[i].flags & SX_BOARD_PRESENT)
 			sx_release_io_range(&sx_board[i]);
-#ifdef SPECIALIX_TIMER
-	del_timer_sync(&missed_irq_timer);
-#endif
-
 	func_exit();
 }
 
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 0243efb..b976248 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -1025,7 +1025,7 @@
 
 /*****************************************************************************/
 
-static void stl_putchar(struct tty_struct *tty, unsigned char ch)
+static int stl_putchar(struct tty_struct *tty, unsigned char ch)
 {
 	struct stlport	*portp;
 	unsigned int	len;
@@ -1034,12 +1034,12 @@
 	pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
 
 	if (tty == NULL)
-		return;
+		return -EINVAL;
 	portp = tty->driver_data;
 	if (portp == NULL)
-		return;
+		return -EINVAL;
 	if (portp->tx.buf == NULL)
-		return;
+		return -EINVAL;
 
 	head = portp->tx.head;
 	tail = portp->tx.tail;
@@ -1053,6 +1053,7 @@
 			head = portp->tx.buf;
 	}	
 	portp->tx.head = head;
+	return 0;
 }
 
 /*****************************************************************************/
@@ -1460,19 +1461,20 @@
 
 /*****************************************************************************/
 
-static void stl_breakctl(struct tty_struct *tty, int state)
+static int stl_breakctl(struct tty_struct *tty, int state)
 {
 	struct stlport	*portp;
 
 	pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
 
 	if (tty == NULL)
-		return;
+		return -EINVAL;
 	portp = tty->driver_data;
 	if (portp == NULL)
-		return;
+		return -EINVAL;
 
 	stl_sendbreak(portp, ((state == -1) ? 1 : 2));
+	return 0;
 }
 
 /*****************************************************************************/
@@ -4753,8 +4755,8 @@
 	if (IS_ERR(stallion_class))
 		printk("STALLION: failed to create class\n");
 	for (i = 0; i < 4; i++)
-		device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
-			      "staliomem%d", i);
+		device_create_drvdata(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
+				      NULL, "staliomem%d", i);
 
 	return 0;
 err_unrtty:
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index d5cffcd6..2162439b 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -1840,7 +1840,7 @@
 	return rc;
 }
 
-static void sx_break(struct tty_struct *tty, int flag)
+static int sx_break(struct tty_struct *tty, int flag)
 {
 	struct sx_port *port = tty->driver_data;
 	int rv;
@@ -1857,6 +1857,7 @@
 			read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat)));
 	unlock_kernel();
 	func_exit();
+	return 0;
 }
 
 static int sx_tiocmget(struct tty_struct *tty, struct file *file)
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index 527d220..ef6706f 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -2897,9 +2897,9 @@
  *
  * Arguments:		tty		pointer to tty instance data
  *			break_state	-1=set break condition, 0=clear
- * Return Value:	None
+ * Return Value:	error code
  */
-static void mgsl_break(struct tty_struct *tty, int break_state)
+static int mgsl_break(struct tty_struct *tty, int break_state)
 {
 	struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data;
 	unsigned long flags;
@@ -2909,7 +2909,7 @@
 			 __FILE__,__LINE__, info->device_name, break_state);
 			 
 	if (mgsl_paranoia_check(info, tty->name, "mgsl_break"))
-		return;
+		return -EINVAL;
 
 	spin_lock_irqsave(&info->irq_spinlock,flags);
  	if (break_state == -1)
@@ -2917,6 +2917,7 @@
 	else 
 		usc_OutReg(info,IOCR,(u16)(usc_InReg(info,IOCR) & ~BIT7));
 	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	return 0;
 	
 }	/* end of mgsl_break() */
 
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 2c3e43b..3e90589 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -165,7 +165,7 @@
 static int  chars_in_buffer(struct tty_struct *tty);
 static void throttle(struct tty_struct * tty);
 static void unthrottle(struct tty_struct * tty);
-static void set_break(struct tty_struct *tty, int break_state);
+static int set_break(struct tty_struct *tty, int break_state);
 
 /*
  * generic HDLC support and callbacks
@@ -214,6 +214,7 @@
 	char *buf;          /* virtual  address of data buffer */
     	unsigned int pdesc; /* physical address of this descriptor */
 	dma_addr_t buf_dma_addr;
+	unsigned short buf_count;
 };
 
 #define set_desc_buffer(a,b) (a).pbuf = cpu_to_le32((unsigned int)(b))
@@ -302,7 +303,7 @@
 	u32 idle_mode;
 	u32 max_frame_size;       /* as set by device config */
 
-	unsigned int raw_rx_size;
+	unsigned int rbuf_fill_level;
 	unsigned int if_mode;
 
 	/* device status */
@@ -466,6 +467,7 @@
 static void tx_stop(struct slgt_info *info);
 static void tx_set_idle(struct slgt_info *info);
 static unsigned int free_tbuf_count(struct slgt_info *info);
+static unsigned int tbuf_bytes(struct slgt_info *info);
 static void reset_tbufs(struct slgt_info *info);
 static void tdma_reset(struct slgt_info *info);
 static void tdma_start(struct slgt_info *info);
@@ -513,7 +515,7 @@
 static int  tiocmget(struct tty_struct *tty, struct file *file);
 static int  tiocmset(struct tty_struct *tty, struct file *file,
 		     unsigned int set, unsigned int clear);
-static void set_break(struct tty_struct *tty, int break_state);
+static int set_break(struct tty_struct *tty, int break_state);
 static int  get_interface(struct slgt_info *info, int __user *if_mode);
 static int  set_interface(struct slgt_info *info, int if_mode);
 static int  set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
@@ -849,6 +851,7 @@
 	int ret = 0;
 	struct slgt_info *info = tty->driver_data;
 	unsigned long flags;
+	unsigned int bufs_needed;
 
 	if (sanity_check(info, tty->name, "write"))
 		goto cleanup;
@@ -865,25 +868,16 @@
 	if (!count)
 		goto cleanup;
 
-	if (info->params.mode == MGSL_MODE_RAW ||
-	    info->params.mode == MGSL_MODE_MONOSYNC ||
-	    info->params.mode == MGSL_MODE_BISYNC) {
-		unsigned int bufs_needed = (count/DMABUFSIZE);
-		unsigned int bufs_free = free_tbuf_count(info);
-		if (count % DMABUFSIZE)
-			++bufs_needed;
-		if (bufs_needed > bufs_free)
-			goto cleanup;
-	} else {
-		if (info->tx_active)
-			goto cleanup;
-		if (info->tx_count) {
-			/* send accumulated data from send_char() calls */
-			/* as frame and wait before accepting more data. */
-			tx_load(info, info->tx_buf, info->tx_count);
-			goto start;
-		}
+	if (!info->tx_active && info->tx_count) {
+		/* send accumulated data from send_char() */
+		tx_load(info, info->tx_buf, info->tx_count);
+		goto start;
 	}
+	bufs_needed = (count/DMABUFSIZE);
+	if (count % DMABUFSIZE)
+		++bufs_needed;
+	if (bufs_needed > free_tbuf_count(info))
+		goto cleanup;
 
 	ret = info->tx_count = count;
 	tx_load(info, buf, count);
@@ -1396,10 +1390,12 @@
 static int chars_in_buffer(struct tty_struct *tty)
 {
 	struct slgt_info *info = tty->driver_data;
+	int count;
 	if (sanity_check(info, tty->name, "chars_in_buffer"))
 		return 0;
-	DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, info->tx_count));
-	return info->tx_count;
+	count = tbuf_bytes(info);
+	DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, count));
+	return count;
 }
 
 /*
@@ -1452,14 +1448,14 @@
  * set or clear transmit break condition
  * break_state	-1=set break condition, 0=clear
  */
-static void set_break(struct tty_struct *tty, int break_state)
+static int set_break(struct tty_struct *tty, int break_state)
 {
 	struct slgt_info *info = tty->driver_data;
 	unsigned short value;
 	unsigned long flags;
 
 	if (sanity_check(info, tty->name, "set_break"))
-		return;
+		return -EINVAL;
 	DBGINFO(("%s set_break(%d)\n", info->device_name, break_state));
 
 	spin_lock_irqsave(&info->lock,flags);
@@ -1470,6 +1466,7 @@
 		value &= ~BIT6;
 	wr_reg16(info, TCR, value);
 	spin_unlock_irqrestore(&info->lock,flags);
+	return 0;
 }
 
 #if SYNCLINK_GENERIC_HDLC
@@ -2679,8 +2676,31 @@
 static int rx_enable(struct slgt_info *info, int enable)
 {
  	unsigned long flags;
-	DBGINFO(("%s rx_enable(%d)\n", info->device_name, enable));
+	unsigned int rbuf_fill_level;
+	DBGINFO(("%s rx_enable(%08x)\n", info->device_name, enable));
 	spin_lock_irqsave(&info->lock,flags);
+	/*
+	 * enable[31..16] = receive DMA buffer fill level
+	 * 0 = noop (leave fill level unchanged)
+	 * fill level must be multiple of 4 and <= buffer size
+	 */
+	rbuf_fill_level = ((unsigned int)enable) >> 16;
+	if (rbuf_fill_level) {
+		if ((rbuf_fill_level > DMABUFSIZE) || (rbuf_fill_level % 4)) {
+			spin_unlock_irqrestore(&info->lock, flags);
+			return -EINVAL;
+		}
+		info->rbuf_fill_level = rbuf_fill_level;
+		rx_stop(info); /* restart receiver to use new fill level */
+	}
+
+	/*
+	 * enable[1..0] = receiver enable command
+	 * 0 = disable
+	 * 1 = enable
+	 * 2 = enable or force hunt mode if already enabled
+	 */
+	enable &= 3;
 	if (enable) {
 		if (!info->rx_enabled)
 			rx_start(info);
@@ -3447,7 +3467,7 @@
 		info->magic = MGSL_MAGIC;
 		INIT_WORK(&info->task, bh_handler);
 		info->max_frame_size = 4096;
-		info->raw_rx_size = DMABUFSIZE;
+		info->rbuf_fill_level = DMABUFSIZE;
 		info->port.close_delay = 5*HZ/10;
 		info->port.closing_wait = 30*HZ;
 		init_waitqueue_head(&info->status_event_wait_q);
@@ -3934,15 +3954,7 @@
 
 	/* set 1st descriptor address */
 	wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc);
-	switch(info->params.mode) {
-	case MGSL_MODE_RAW:
-	case MGSL_MODE_MONOSYNC:
-	case MGSL_MODE_BISYNC:
-		wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */
-		break;
-	default:
-		wr_reg32(info, TDCSR, BIT0); /* DMA enable */
-	}
+	wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */
 }
 
 static void tx_stop(struct slgt_info *info)
@@ -4145,7 +4157,7 @@
 	 * 01      enable
 	 * 00      auto-CTS enable
 	 */
-	val = 0;
+	val = BIT2;
 
 	switch(info->params.mode) {
 	case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break;
@@ -4418,6 +4430,8 @@
 		break;
 	}
 
+	if (info->if_mode & MGSL_INTERFACE_MSB_FIRST)
+		val |= BIT4;
 	if (info->signals & SerialSignal_DTR)
 		val |= BIT3;
 	if (info->signals & SerialSignal_RTS)
@@ -4456,16 +4470,7 @@
 	while(!done) {
 		/* reset current buffer for reuse */
 		info->rbufs[i].status = 0;
-		switch(info->params.mode) {
-		case MGSL_MODE_RAW:
-		case MGSL_MODE_MONOSYNC:
-		case MGSL_MODE_BISYNC:
-			set_desc_count(info->rbufs[i], info->raw_rx_size);
-			break;
-		default:
-			set_desc_count(info->rbufs[i], DMABUFSIZE);
-		}
-
+		set_desc_count(info->rbufs[i], info->rbuf_fill_level);
 		if (i == last)
 			done = 1;
 		if (++i == info->rbuf_count)
@@ -4572,7 +4577,7 @@
 
 	DBGBH(("%s rx frame status=%04X size=%d\n",
 		info->device_name, status, framesize));
-	DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, DMABUFSIZE), "rx");
+	DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, info->rbuf_fill_level), "rx");
 
 	if (framesize) {
 		if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) {
@@ -4592,7 +4597,7 @@
 			info->icount.rxok++;
 
 			while(copy_count) {
-				int partial_count = min(copy_count, DMABUFSIZE);
+				int partial_count = min_t(int, copy_count, info->rbuf_fill_level);
 				memcpy(p, info->rbufs[i].buf, partial_count);
 				p += partial_count;
 				copy_count -= partial_count;
@@ -4684,6 +4689,56 @@
 }
 
 /*
+ * return number of bytes in unsent transmit DMA buffers
+ * and the serial controller tx FIFO
+ */
+static unsigned int tbuf_bytes(struct slgt_info *info)
+{
+	unsigned int total_count = 0;
+	unsigned int i = info->tbuf_current;
+	unsigned int reg_value;
+	unsigned int count;
+	unsigned int active_buf_count = 0;
+
+	/*
+	 * Add descriptor counts for all tx DMA buffers.
+	 * If count is zero (cleared by DMA controller after read),
+	 * the buffer is complete or is actively being read from.
+	 *
+	 * Record buf_count of last buffer with zero count starting
+	 * from current ring position. buf_count is mirror
+	 * copy of count and is not cleared by serial controller.
+	 * If DMA controller is active, that buffer is actively
+	 * being read so add to total.
+	 */
+	do {
+		count = desc_count(info->tbufs[i]);
+		if (count)
+			total_count += count;
+		else if (!total_count)
+			active_buf_count = info->tbufs[i].buf_count;
+		if (++i == info->tbuf_count)
+			i = 0;
+	} while (i != info->tbuf_current);
+
+	/* read tx DMA status register */
+	reg_value = rd_reg32(info, TDCSR);
+
+	/* if tx DMA active, last zero count buffer is in use */
+	if (reg_value & BIT0)
+		total_count += active_buf_count;
+
+	/* add tx FIFO count = reg_value[15..8] */
+	total_count += (reg_value >> 8) & 0xff;
+
+	/* if transmitter active add one byte for shift register */
+	if (info->tx_active)
+		total_count++;
+
+	return total_count;
+}
+
+/*
  * load transmit DMA buffer(s) with data
  */
 static void tx_load(struct slgt_info *info, const char *buf, unsigned int size)
@@ -4721,6 +4776,7 @@
 			set_desc_eof(*d, 0);
 
 		set_desc_count(*d, count);
+		d->buf_count = count;
 	}
 
 	info->tbuf_current = i;
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index 5768c41..c0490cb 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -527,7 +527,7 @@
 static int  chars_in_buffer(struct tty_struct *tty);
 static void throttle(struct tty_struct * tty);
 static void unthrottle(struct tty_struct * tty);
-static void set_break(struct tty_struct *tty, int break_state);
+static int set_break(struct tty_struct *tty, int break_state);
 
 #if SYNCLINK_GENERIC_HDLC
 #define dev_to_port(D) (dev_to_hdlc(D)->priv)
@@ -552,7 +552,7 @@
 static int  tiocmget(struct tty_struct *tty, struct file *file);
 static int  tiocmset(struct tty_struct *tty, struct file *file,
 		     unsigned int set, unsigned int clear);
-static void set_break(struct tty_struct *tty, int break_state);
+static int  set_break(struct tty_struct *tty, int break_state);
 
 static void add_device(SLMP_INFO *info);
 static void device_init(int adapter_num, struct pci_dev *pdev);
@@ -1587,7 +1587,7 @@
 /* set or clear transmit break condition
  * break_state	-1=set break condition, 0=clear
  */
-static void set_break(struct tty_struct *tty, int break_state)
+static int set_break(struct tty_struct *tty, int break_state)
 {
 	unsigned char RegValue;
 	SLMP_INFO * info = (SLMP_INFO *)tty->driver_data;
@@ -1598,7 +1598,7 @@
 			 __FILE__,__LINE__, info->device_name, break_state);
 
 	if (sanity_check(info, tty->name, "set_break"))
-		return;
+		return -EINVAL;
 
 	spin_lock_irqsave(&info->lock,flags);
 	RegValue = read_reg(info, CTL);
@@ -1608,6 +1608,7 @@
 		RegValue &= ~BIT3;
 	write_reg(info, CTL, RegValue);
 	spin_unlock_irqrestore(&info->lock,flags);
+	return 0;
 }
 
 #if SYNCLINK_GENERIC_HDLC
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 82f6a8c..fa48dba 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -656,558 +656,6 @@
 
 
 /**
- *	tty_set_termios_ldisc		-	set ldisc field
- *	@tty: tty structure
- *	@num: line discipline number
- *
- *	This is probably overkill for real world processors but
- *	they are not on hot paths so a little discipline won't do
- *	any harm.
- *
- *	Locking: takes termios_mutex
- */
-
-static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
-{
-	mutex_lock(&tty->termios_mutex);
-	tty->termios->c_line = num;
-	mutex_unlock(&tty->termios_mutex);
-}
-
-/*
- *	This guards the refcounted line discipline lists. The lock
- *	must be taken with irqs off because there are hangup path
- *	callers who will do ldisc lookups and cannot sleep.
- */
-
-static DEFINE_SPINLOCK(tty_ldisc_lock);
-static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
-/* Line disc dispatch table */
-static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
-
-/**
- *	tty_register_ldisc	-	install a line discipline
- *	@disc: ldisc number
- *	@new_ldisc: pointer to the ldisc object
- *
- *	Installs a new line discipline into the kernel. The discipline
- *	is set up as unreferenced and then made available to the kernel
- *	from this point onwards.
- *
- *	Locking:
- *		takes tty_ldisc_lock to guard against ldisc races
- */
-
-int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)
-{
-	unsigned long flags;
-	int ret = 0;
-
-	if (disc < N_TTY || disc >= NR_LDISCS)
-		return -EINVAL;
-
-	spin_lock_irqsave(&tty_ldisc_lock, flags);
-	tty_ldiscs[disc] = new_ldisc;
-	new_ldisc->num = disc;
-	new_ldisc->refcount = 0;
-	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(tty_register_ldisc);
-
-/**
- *	tty_unregister_ldisc	-	unload a line discipline
- *	@disc: ldisc number
- *	@new_ldisc: pointer to the ldisc object
- *
- *	Remove a line discipline from the kernel providing it is not
- *	currently in use.
- *
- *	Locking:
- *		takes tty_ldisc_lock to guard against ldisc races
- */
-
-int tty_unregister_ldisc(int disc)
-{
-	unsigned long flags;
-	int ret = 0;
-
-	if (disc < N_TTY || disc >= NR_LDISCS)
-		return -EINVAL;
-
-	spin_lock_irqsave(&tty_ldisc_lock, flags);
-	if (tty_ldiscs[disc]->refcount)
-		ret = -EBUSY;
-	else
-		tty_ldiscs[disc] = NULL;
-	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(tty_unregister_ldisc);
-
-
-/**
- *	tty_ldisc_try_get	-	try and reference an ldisc
- *	@disc: ldisc number
- *	@ld: tty ldisc structure to complete
- *
- *	Attempt to open and lock a line discipline into place. Return
- *	the line discipline refcounted and assigned in ld. On an error
- *	report the error code back
- */
-
-static int tty_ldisc_try_get(int disc, struct tty_ldisc *ld)
-{
-	unsigned long flags;
-	struct tty_ldisc_ops *ldops;
-	int err = -EINVAL;
-	
-	spin_lock_irqsave(&tty_ldisc_lock, flags);
-	ld->ops = NULL;
-	ldops = tty_ldiscs[disc];
-	/* Check the entry is defined */
-	if (ldops) {
-		/* If the module is being unloaded we can't use it */
-		if (!try_module_get(ldops->owner))
-			err = -EAGAIN;
-		else {
-			/* lock it */
-			ldops->refcount++;
-			ld->ops = ldops;
-			err = 0;
-		}
-	}
-	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-	return err;
-}
-
-/**
- *	tty_ldisc_get		-	take a reference to an ldisc
- *	@disc: ldisc number
- *	@ld: tty line discipline structure to use
- *
- *	Takes a reference to a line discipline. Deals with refcounts and
- *	module locking counts. Returns NULL if the discipline is not available.
- *	Returns a pointer to the discipline and bumps the ref count if it is
- *	available
- *
- *	Locking:
- *		takes tty_ldisc_lock to guard against ldisc races
- */
-
-static int tty_ldisc_get(int disc, struct tty_ldisc *ld)
-{
-	int err;
-
-	if (disc < N_TTY || disc >= NR_LDISCS)
-		return -EINVAL;
-	err = tty_ldisc_try_get(disc, ld);
-	if (err == -EAGAIN) {
-		request_module("tty-ldisc-%d", disc);
-		err = tty_ldisc_try_get(disc, ld);
-	}
-	return err;
-}
-
-/**
- *	tty_ldisc_put		-	drop ldisc reference
- *	@disc: ldisc number
- *
- *	Drop a reference to a line discipline. Manage refcounts and
- *	module usage counts
- *
- *	Locking:
- *		takes tty_ldisc_lock to guard against ldisc races
- */
-
-static void tty_ldisc_put(struct tty_ldisc_ops *ld)
-{
-	unsigned long flags;
-	int disc = ld->num;
-
-	BUG_ON(disc < N_TTY || disc >= NR_LDISCS);
-
-	spin_lock_irqsave(&tty_ldisc_lock, flags);
-	ld = tty_ldiscs[disc];
-	BUG_ON(ld->refcount == 0);
-	ld->refcount--;
-	module_put(ld->owner);
-	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-}
-
-static void * tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos)
-{
-	return (*pos < NR_LDISCS) ? pos : NULL;
-}
-
-static void * tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos)
-{
-	(*pos)++;
-	return (*pos < NR_LDISCS) ? pos : NULL;
-}
-
-static void tty_ldiscs_seq_stop(struct seq_file *m, void *v)
-{
-}
-
-static int tty_ldiscs_seq_show(struct seq_file *m, void *v)
-{
-	int i = *(loff_t *)v;
-	struct tty_ldisc ld;
-	
-	if (tty_ldisc_get(i, &ld) < 0)
-		return 0;
-	seq_printf(m, "%-10s %2d\n", ld.ops->name ? ld.ops->name : "???", i);
-	tty_ldisc_put(ld.ops);
-	return 0;
-}
-
-static const struct seq_operations tty_ldiscs_seq_ops = {
-	.start	= tty_ldiscs_seq_start,
-	.next	= tty_ldiscs_seq_next,
-	.stop	= tty_ldiscs_seq_stop,
-	.show	= tty_ldiscs_seq_show,
-};
-
-static int proc_tty_ldiscs_open(struct inode *inode, struct file *file)
-{
-	return seq_open(file, &tty_ldiscs_seq_ops);
-}
-
-const struct file_operations tty_ldiscs_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= proc_tty_ldiscs_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= seq_release,
-};
-
-/**
- *	tty_ldisc_assign	-	set ldisc on a tty
- *	@tty: tty to assign
- *	@ld: line discipline
- *
- *	Install an instance of a line discipline into a tty structure. The
- *	ldisc must have a reference count above zero to ensure it remains/
- *	The tty instance refcount starts at zero.
- *
- *	Locking:
- *		Caller must hold references
- */
-
-static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
-{
-	ld->refcount = 0;
-	tty->ldisc = *ld;
-}
-
-/**
- *	tty_ldisc_try		-	internal helper
- *	@tty: the tty
- *
- *	Make a single attempt to grab and bump the refcount on
- *	the tty ldisc. Return 0 on failure or 1 on success. This is
- *	used to implement both the waiting and non waiting versions
- *	of tty_ldisc_ref
- *
- *	Locking: takes tty_ldisc_lock
- */
-
-static int tty_ldisc_try(struct tty_struct *tty)
-{
-	unsigned long flags;
-	struct tty_ldisc *ld;
-	int ret = 0;
-
-	spin_lock_irqsave(&tty_ldisc_lock, flags);
-	ld = &tty->ldisc;
-	if (test_bit(TTY_LDISC, &tty->flags)) {
-		ld->refcount++;
-		ret = 1;
-	}
-	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-	return ret;
-}
-
-/**
- *	tty_ldisc_ref_wait	-	wait for the tty ldisc
- *	@tty: tty device
- *
- *	Dereference the line discipline for the terminal and take a
- *	reference to it. If the line discipline is in flux then
- *	wait patiently until it changes.
- *
- *	Note: Must not be called from an IRQ/timer context. The caller
- *	must also be careful not to hold other locks that will deadlock
- *	against a discipline change, such as an existing ldisc reference
- *	(which we check for)
- *
- *	Locking: call functions take tty_ldisc_lock
- */
-
-struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
-{
-	/* wait_event is a macro */
-	wait_event(tty_ldisc_wait, tty_ldisc_try(tty));
-	if (tty->ldisc.refcount == 0)
-		printk(KERN_ERR "tty_ldisc_ref_wait\n");
-	return &tty->ldisc;
-}
-
-EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
-
-/**
- *	tty_ldisc_ref		-	get the tty ldisc
- *	@tty: tty device
- *
- *	Dereference the line discipline for the terminal and take a
- *	reference to it. If the line discipline is in flux then
- *	return NULL. Can be called from IRQ and timer functions.
- *
- *	Locking: called functions take tty_ldisc_lock
- */
-
-struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty)
-{
-	if (tty_ldisc_try(tty))
-		return &tty->ldisc;
-	return NULL;
-}
-
-EXPORT_SYMBOL_GPL(tty_ldisc_ref);
-
-/**
- *	tty_ldisc_deref		-	free a tty ldisc reference
- *	@ld: reference to free up
- *
- *	Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May
- *	be called in IRQ context.
- *
- *	Locking: takes tty_ldisc_lock
- */
-
-void tty_ldisc_deref(struct tty_ldisc *ld)
-{
-	unsigned long flags;
-
-	BUG_ON(ld == NULL);
-
-	spin_lock_irqsave(&tty_ldisc_lock, flags);
-	if (ld->refcount == 0)
-		printk(KERN_ERR "tty_ldisc_deref: no references.\n");
-	else
-		ld->refcount--;
-	if (ld->refcount == 0)
-		wake_up(&tty_ldisc_wait);
-	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-}
-
-EXPORT_SYMBOL_GPL(tty_ldisc_deref);
-
-/**
- *	tty_ldisc_enable	-	allow ldisc use
- *	@tty: terminal to activate ldisc on
- *
- *	Set the TTY_LDISC flag when the line discipline can be called
- *	again. Do necessary wakeups for existing sleepers.
- *
- *	Note: nobody should set this bit except via this function. Clearing
- *	directly is allowed.
- */
-
-static void tty_ldisc_enable(struct tty_struct *tty)
-{
-	set_bit(TTY_LDISC, &tty->flags);
-	wake_up(&tty_ldisc_wait);
-}
-
-/**
- *	tty_ldisc_restore	-	helper for tty ldisc change
- *	@tty: tty to recover
- *	@old: previous ldisc
- *
- *	Restore the previous line discipline or N_TTY when a line discipline
- *	change fails due to an open error
- */
-
-static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
-{
-	char buf[64];
-	struct tty_ldisc new_ldisc;
-
-	/* There is an outstanding reference here so this is safe */
-	tty_ldisc_get(old->ops->num, old);
-	tty_ldisc_assign(tty, old);
-	tty_set_termios_ldisc(tty, old->ops->num);
-	if (old->ops->open && (old->ops->open(tty) < 0)) {
-		tty_ldisc_put(old->ops);
-		/* This driver is always present */
-		if (tty_ldisc_get(N_TTY, &new_ldisc) < 0)
-			panic("n_tty: get");
-		tty_ldisc_assign(tty, &new_ldisc);
-		tty_set_termios_ldisc(tty, N_TTY);
-		if (new_ldisc.ops->open) {
-			int r = new_ldisc.ops->open(tty);
-				if (r < 0)
-				panic("Couldn't open N_TTY ldisc for "
-				      "%s --- error %d.",
-				      tty_name(tty, buf), r);
-		}
-	}
-}
-
-/**
- *	tty_set_ldisc		-	set line discipline
- *	@tty: the terminal to set
- *	@ldisc: the line discipline
- *
- *	Set the discipline of a tty line. Must be called from a process
- *	context.
- *
- *	Locking: takes tty_ldisc_lock.
- *		 called functions take termios_mutex
- */
-
-static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
-{
-	int retval;
-	struct tty_ldisc o_ldisc, new_ldisc;
-	int work;
-	unsigned long flags;
-	struct tty_struct *o_tty;
-
-restart:
-	/* This is a bit ugly for now but means we can break the 'ldisc
-	   is part of the tty struct' assumption later */
-	retval = tty_ldisc_get(ldisc, &new_ldisc);
-	if (retval)
-		return retval;
-
-	/*
-	 *	Problem: What do we do if this blocks ?
-	 */
-
-	tty_wait_until_sent(tty, 0);
-
-	if (tty->ldisc.ops->num == ldisc) {
-		tty_ldisc_put(new_ldisc.ops);
-		return 0;
-	}
-
-	/*
-	 *	No more input please, we are switching. The new ldisc
-	 *	will update this value in the ldisc open function
-	 */
-
-	tty->receive_room = 0;
-
-	o_ldisc = tty->ldisc;
-	o_tty = tty->link;
-
-	/*
-	 *	Make sure we don't change while someone holds a
-	 *	reference to the line discipline. The TTY_LDISC bit
-	 *	prevents anyone taking a reference once it is clear.
-	 *	We need the lock to avoid racing reference takers.
-	 */
-
-	spin_lock_irqsave(&tty_ldisc_lock, flags);
-	if (tty->ldisc.refcount || (o_tty && o_tty->ldisc.refcount)) {
-		if (tty->ldisc.refcount) {
-			/* Free the new ldisc we grabbed. Must drop the lock
-			   first. */
-			spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-			tty_ldisc_put(o_ldisc.ops);
-			/*
-			 * There are several reasons we may be busy, including
-			 * random momentary I/O traffic. We must therefore
-			 * retry. We could distinguish between blocking ops
-			 * and retries if we made tty_ldisc_wait() smarter.
-			 * That is up for discussion.
-			 */
-			if (wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0)
-				return -ERESTARTSYS;
-			goto restart;
-		}
-		if (o_tty && o_tty->ldisc.refcount) {
-			spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-			tty_ldisc_put(o_tty->ldisc.ops);
-			if (wait_event_interruptible(tty_ldisc_wait, o_tty->ldisc.refcount == 0) < 0)
-				return -ERESTARTSYS;
-			goto restart;
-		}
-	}
-	/*
-	 *	If the TTY_LDISC bit is set, then we are racing against
-	 *	another ldisc change
-	 */
-	if (!test_bit(TTY_LDISC, &tty->flags)) {
-		struct tty_ldisc *ld;
-		spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-		tty_ldisc_put(new_ldisc.ops);
-		ld = tty_ldisc_ref_wait(tty);
-		tty_ldisc_deref(ld);
-		goto restart;
-	}
-
-	clear_bit(TTY_LDISC, &tty->flags);
-	if (o_tty)
-		clear_bit(TTY_LDISC, &o_tty->flags);
-	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-	
-	/*
-	 *	From this point on we know nobody has an ldisc
-	 *	usage reference, nor can they obtain one until
-	 *	we say so later on.
-	 */
-
-	work = cancel_delayed_work(&tty->buf.work);
-	/*
-	 * Wait for ->hangup_work and ->buf.work handlers to terminate
-	 * MUST NOT hold locks here.
-	 */
-	flush_scheduled_work();
-	/* Shutdown the current discipline. */
-	if (o_ldisc.ops->close)
-		(o_ldisc.ops->close)(tty);
-
-	/* Now set up the new line discipline. */
-	tty_ldisc_assign(tty, &new_ldisc);
-	tty_set_termios_ldisc(tty, ldisc);
-	if (new_ldisc.ops->open)
-		retval = (new_ldisc.ops->open)(tty);
-	if (retval < 0) {
-		tty_ldisc_put(new_ldisc.ops);
-		tty_ldisc_restore(tty, &o_ldisc);
-	}
-	/* At this point we hold a reference to the new ldisc and a
-	   a reference to the old ldisc. If we ended up flipping back
-	   to the existing ldisc we have two references to it */
-
-	if (tty->ldisc.ops->num != o_ldisc.ops->num && tty->ops->set_ldisc)
-		tty->ops->set_ldisc(tty);
-
-	tty_ldisc_put(o_ldisc.ops);
-
-	/*
-	 *	Allow ldisc referencing to occur as soon as the driver
-	 *	ldisc callback completes.
-	 */
-
-	tty_ldisc_enable(tty);
-	if (o_tty)
-		tty_ldisc_enable(o_tty);
-
-	/* Restart it in case no characters kick it off. Safe if
-	   already running */
-	if (work)
-		schedule_delayed_work(&tty->buf.work, 1);
-	return retval;
-}
-
-/**
  *	get_tty_driver		-	find device of a tty
  *	@dev_t: device identifier
  *	@index: returns the index of the tty
@@ -1467,7 +915,7 @@
  *	do_tty_hangup		-	actual handler for hangup events
  *	@work: tty device
  *
-k *	This can be called by the "eventd" kernel thread.  That is process
+ *	This can be called by the "eventd" kernel thread.  That is process
  *	synchronous but doesn't hold any locks, so we need to make sure we
  *	have the appropriate locks for what we're doing.
  *
@@ -2193,7 +1641,6 @@
 	struct ktermios *tp, **tp_loc, *o_tp, **o_tp_loc;
 	struct ktermios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
 	int retval = 0;
-	struct tty_ldisc *ld;
 
 	/* check whether we're reopening an existing tty */
 	if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
@@ -2342,25 +1789,12 @@
 	 * If we fail here just call release_tty to clean up.  No need
 	 * to decrement the use counts, as release_tty doesn't care.
 	 */
-	 
-	ld = &tty->ldisc;
 
-	if (ld->ops->open) {
-		retval = (ld->ops->open)(tty);
-		if (retval)
-			goto release_mem_out;
-	}
-	if (o_tty && o_tty->ldisc.ops->open) {
-		retval = (o_tty->ldisc.ops->open)(o_tty);
-		if (retval) {
-			if (ld->ops->close)
-				(ld->ops->close)(tty);
-			goto release_mem_out;
-		}
-		tty_ldisc_enable(o_tty);
-	}
-	tty_ldisc_enable(tty);
-	goto success;
+	retval = tty_ldisc_setup(tty, o_tty);
+
+	if (retval)
+		goto release_mem_out;
+	 goto success;
 
 	/*
 	 * This fast open can be used if the tty is already open.
@@ -2498,12 +1932,10 @@
 static void release_dev(struct file *filp)
 {
 	struct tty_struct *tty, *o_tty;
-	struct tty_ldisc ld;
 	int	pty_master, tty_closing, o_tty_closing, do_sleep;
 	int	devpts;
 	int	idx;
 	char	buf[64];
-	unsigned long flags;
 
 	tty = (struct tty_struct *)filp->private_data;
 	if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode,
@@ -2705,56 +2137,9 @@
 	printk(KERN_DEBUG "freeing tty structure...");
 #endif
 	/*
-	 * Prevent flush_to_ldisc() from rescheduling the work for later.  Then
-	 * kill any delayed work. As this is the final close it does not
-	 * race with the set_ldisc code path.
+	 * Ask the line discipline code to release its structures
 	 */
-	clear_bit(TTY_LDISC, &tty->flags);
-	cancel_delayed_work(&tty->buf.work);
-
-	/*
-	 * Wait for ->hangup_work and ->buf.work handlers to terminate
-	 */
-
-	flush_scheduled_work();
-
-	/*
-	 * Wait for any short term users (we know they are just driver
-	 * side waiters as the file is closing so user count on the file
-	 * side is zero.
-	 */
-	spin_lock_irqsave(&tty_ldisc_lock, flags);
-	while (tty->ldisc.refcount) {
-		spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-		wait_event(tty_ldisc_wait, tty->ldisc.refcount == 0);
-		spin_lock_irqsave(&tty_ldisc_lock, flags);
-	}
-	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-	/*
-	 * Shutdown the current line discipline, and reset it to N_TTY.
-	 *
-	 * FIXME: this MUST get fixed for the new reflocking
-	 */
-	if (tty->ldisc.ops->close)
-		(tty->ldisc.ops->close)(tty);
-	tty_ldisc_put(tty->ldisc.ops);
-
-	/*
-	 *	Switch the line discipline back
-	 */
-	WARN_ON(tty_ldisc_get(N_TTY, &ld));
-	tty_ldisc_assign(tty, &ld);
-	tty_set_termios_ldisc(tty, N_TTY);
-	if (o_tty) {
-		/* FIXME: could o_tty be in setldisc here ? */
-		clear_bit(TTY_LDISC, &o_tty->flags);
-		if (o_tty->ldisc.ops->close)
-			(o_tty->ldisc.ops->close)(o_tty);
-		tty_ldisc_put(o_tty->ldisc.ops);
-		WARN_ON(tty_ldisc_get(N_TTY, &ld));
-		tty_ldisc_assign(o_tty, &ld);
-		tty_set_termios_ldisc(o_tty, N_TTY);
-	}
+	tty_ldisc_release(tty, o_tty);
 	/*
 	 * The release_tty function takes care of the details of clearing
 	 * the slots and preserving the termios structure.
@@ -3464,16 +2849,29 @@
 
 static int send_break(struct tty_struct *tty, unsigned int duration)
 {
-	if (tty_write_lock(tty, 0) < 0)
-		return -EINTR;
-	tty->ops->break_ctl(tty, -1);
-	if (!signal_pending(current))
-		msleep_interruptible(duration);
-	tty->ops->break_ctl(tty, 0);
-	tty_write_unlock(tty);
-	if (signal_pending(current))
-		return -EINTR;
-	return 0;
+	int retval;
+
+	if (tty->ops->break_ctl == NULL)
+		return 0;
+
+	if (tty->driver->flags & TTY_DRIVER_HARDWARE_BREAK)
+		retval = tty->ops->break_ctl(tty, duration);
+	else {
+		/* Do the work ourselves */
+		if (tty_write_lock(tty, 0) < 0)
+			return -EINTR;
+		retval = tty->ops->break_ctl(tty, -1);
+		if (retval)
+			goto out;
+		if (!signal_pending(current))
+			msleep_interruptible(duration);
+		retval = tty->ops->break_ctl(tty, 0);
+out:
+		tty_write_unlock(tty);
+		if (signal_pending(current))
+			retval = -EINTR;
+	}
+	return retval;
 }
 
 /**
@@ -3564,36 +2962,6 @@
 	    tty->driver->subtype == PTY_TYPE_MASTER)
 		real_tty = tty->link;
 
-	/*
-	 * Break handling by driver
-	 */
-
-	retval = -EINVAL;
-
-	if (!tty->ops->break_ctl) {
-		switch (cmd) {
-		case TIOCSBRK:
-		case TIOCCBRK:
-			if (tty->ops->ioctl)
-				retval = tty->ops->ioctl(tty, file, cmd, arg);
-			if (retval != -EINVAL && retval != -ENOIOCTLCMD)
-				printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name);
-			return retval;
-
-		/* These two ioctl's always return success; even if */
-		/* the driver doesn't support them. */
-		case TCSBRK:
-		case TCSBRKP:
-			if (!tty->ops->ioctl)
-				return 0;
-			retval = tty->ops->ioctl(tty, file, cmd, arg);
-			if (retval != -EINVAL && retval != -ENOIOCTLCMD)
-				printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name);
-			if (retval == -ENOIOCTLCMD)
-				retval = 0;
-			return retval;
-		}
-	}
 
 	/*
 	 * Factor out some common prep work
@@ -3615,6 +2983,9 @@
 		break;
 	}
 
+	/*
+	 *	Now do the stuff.
+	 */
 	switch (cmd) {
 	case TIOCSTI:
 		return tiocsti(tty, p);
@@ -3658,12 +3029,11 @@
 	 */
 	case TIOCSBRK:	/* Turn break on, unconditionally */
 		if (tty->ops->break_ctl)
-			tty->ops->break_ctl(tty, -1);
+			return tty->ops->break_ctl(tty, -1);
 		return 0;
-
 	case TIOCCBRK:	/* Turn break off, unconditionally */
 		if (tty->ops->break_ctl)
-			tty->ops->break_ctl(tty, 0);
+			return tty->ops->break_ctl(tty, 0);
 		return 0;
 	case TCSBRK:   /* SVID version: non-zero arg --> no break */
 		/* non-zero arg means wait for all output data
@@ -3962,12 +3332,9 @@
 
 static void initialize_tty_struct(struct tty_struct *tty)
 {
-	struct tty_ldisc ld;
 	memset(tty, 0, sizeof(struct tty_struct));
 	tty->magic = TTY_MAGIC;
-	if (tty_ldisc_get(N_TTY, &ld) < 0)
-		panic("n_tty: init_tty");
-	tty_ldisc_assign(tty, &ld);
+	tty_ldisc_init(tty);
 	tty->session = NULL;
 	tty->pgrp = NULL;
 	tty->overrun_time = jiffies;
@@ -4045,7 +3412,7 @@
 	else
 		tty_line_name(driver, index, name);
 
-	return device_create(tty_class, device, dev, name);
+	return device_create_drvdata(tty_class, device, dev, NULL, name);
 }
 
 /**
@@ -4280,7 +3647,7 @@
 	initcall_t *call;
 
 	/* Setup the default TTY line discipline. */
-	(void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
+	tty_ldisc_begin();
 
 	/*
 	 * set up the console device so that later boot sequences can
@@ -4323,20 +3690,22 @@
 	if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||
 	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
 		panic("Couldn't register /dev/tty driver\n");
-	device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), "tty");
+	device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL,
+			      "tty");
 
 	cdev_init(&console_cdev, &console_fops);
 	if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
 	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
 		panic("Couldn't register /dev/console driver\n");
-	device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), "console");
+	device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL,
+			      "console");
 
 #ifdef CONFIG_UNIX98_PTYS
 	cdev_init(&ptmx_cdev, &ptmx_fops);
 	if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
 	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
 		panic("Couldn't register /dev/ptmx driver\n");
-	device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), "ptmx");
+	device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
 #endif
 
 #ifdef CONFIG_VT
@@ -4344,7 +3713,7 @@
 	if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
 	    register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
 		panic("Couldn't register /dev/tty0 driver\n");
-	device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), "tty0");
+	device_create_drvdata(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
 
 	vty_init();
 #endif
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c
new file mode 100644
index 0000000..241cbde
--- /dev/null
+++ b/drivers/char/tty_ldisc.c
@@ -0,0 +1,714 @@
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/fcntl.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/devpts_fs.h>
+#include <linux/file.h>
+#include <linux/fdtable.h>
+#include <linux/console.h>
+#include <linux/timer.h>
+#include <linux/ctype.h>
+#include <linux/kd.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/smp_lock.h>
+#include <linux/device.h>
+#include <linux/wait.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+
+#include <linux/uaccess.h>
+#include <asm/system.h>
+
+#include <linux/kbd_kern.h>
+#include <linux/vt_kern.h>
+#include <linux/selection.h>
+
+#include <linux/kmod.h>
+#include <linux/nsproxy.h>
+
+/*
+ *	This guards the refcounted line discipline lists. The lock
+ *	must be taken with irqs off because there are hangup path
+ *	callers who will do ldisc lookups and cannot sleep.
+ */
+
+static DEFINE_SPINLOCK(tty_ldisc_lock);
+static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
+/* Line disc dispatch table */
+static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
+
+/**
+ *	tty_register_ldisc	-	install a line discipline
+ *	@disc: ldisc number
+ *	@new_ldisc: pointer to the ldisc object
+ *
+ *	Installs a new line discipline into the kernel. The discipline
+ *	is set up as unreferenced and then made available to the kernel
+ *	from this point onwards.
+ *
+ *	Locking:
+ *		takes tty_ldisc_lock to guard against ldisc races
+ */
+
+int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	if (disc < N_TTY || disc >= NR_LDISCS)
+		return -EINVAL;
+
+	spin_lock_irqsave(&tty_ldisc_lock, flags);
+	tty_ldiscs[disc] = new_ldisc;
+	new_ldisc->num = disc;
+	new_ldisc->refcount = 0;
+	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(tty_register_ldisc);
+
+/**
+ *	tty_unregister_ldisc	-	unload a line discipline
+ *	@disc: ldisc number
+ *	@new_ldisc: pointer to the ldisc object
+ *
+ *	Remove a line discipline from the kernel providing it is not
+ *	currently in use.
+ *
+ *	Locking:
+ *		takes tty_ldisc_lock to guard against ldisc races
+ */
+
+int tty_unregister_ldisc(int disc)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	if (disc < N_TTY || disc >= NR_LDISCS)
+		return -EINVAL;
+
+	spin_lock_irqsave(&tty_ldisc_lock, flags);
+	if (tty_ldiscs[disc]->refcount)
+		ret = -EBUSY;
+	else
+		tty_ldiscs[disc] = NULL;
+	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(tty_unregister_ldisc);
+
+
+/**
+ *	tty_ldisc_try_get	-	try and reference an ldisc
+ *	@disc: ldisc number
+ *	@ld: tty ldisc structure to complete
+ *
+ *	Attempt to open and lock a line discipline into place. Return
+ *	the line discipline refcounted and assigned in ld. On an error
+ *	report the error code back
+ */
+
+static int tty_ldisc_try_get(int disc, struct tty_ldisc *ld)
+{
+	unsigned long flags;
+	struct tty_ldisc_ops *ldops;
+	int err = -EINVAL;
+	
+	spin_lock_irqsave(&tty_ldisc_lock, flags);
+	ld->ops = NULL;
+	ldops = tty_ldiscs[disc];
+	/* Check the entry is defined */
+	if (ldops) {
+		/* If the module is being unloaded we can't use it */
+		if (!try_module_get(ldops->owner))
+			err = -EAGAIN;
+		else {
+			/* lock it */
+			ldops->refcount++;
+			ld->ops = ldops;
+			err = 0;
+		}
+	}
+	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+	return err;
+}
+
+/**
+ *	tty_ldisc_get		-	take a reference to an ldisc
+ *	@disc: ldisc number
+ *	@ld: tty line discipline structure to use
+ *
+ *	Takes a reference to a line discipline. Deals with refcounts and
+ *	module locking counts. Returns NULL if the discipline is not available.
+ *	Returns a pointer to the discipline and bumps the ref count if it is
+ *	available
+ *
+ *	Locking:
+ *		takes tty_ldisc_lock to guard against ldisc races
+ */
+
+static int tty_ldisc_get(int disc, struct tty_ldisc *ld)
+{
+	int err;
+
+	if (disc < N_TTY || disc >= NR_LDISCS)
+		return -EINVAL;
+	err = tty_ldisc_try_get(disc, ld);
+	if (err == -EAGAIN) {
+		request_module("tty-ldisc-%d", disc);
+		err = tty_ldisc_try_get(disc, ld);
+	}
+	return err;
+}
+
+/**
+ *	tty_ldisc_put		-	drop ldisc reference
+ *	@disc: ldisc number
+ *
+ *	Drop a reference to a line discipline. Manage refcounts and
+ *	module usage counts
+ *
+ *	Locking:
+ *		takes tty_ldisc_lock to guard against ldisc races
+ */
+
+static void tty_ldisc_put(struct tty_ldisc_ops *ld)
+{
+	unsigned long flags;
+	int disc = ld->num;
+
+	BUG_ON(disc < N_TTY || disc >= NR_LDISCS);
+
+	spin_lock_irqsave(&tty_ldisc_lock, flags);
+	ld = tty_ldiscs[disc];
+	BUG_ON(ld->refcount == 0);
+	ld->refcount--;
+	module_put(ld->owner);
+	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+}
+
+static void * tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos)
+{
+	return (*pos < NR_LDISCS) ? pos : NULL;
+}
+
+static void * tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	(*pos)++;
+	return (*pos < NR_LDISCS) ? pos : NULL;
+}
+
+static void tty_ldiscs_seq_stop(struct seq_file *m, void *v)
+{
+}
+
+static int tty_ldiscs_seq_show(struct seq_file *m, void *v)
+{
+	int i = *(loff_t *)v;
+	struct tty_ldisc ld;
+	
+	if (tty_ldisc_get(i, &ld) < 0)
+		return 0;
+	seq_printf(m, "%-10s %2d\n", ld.ops->name ? ld.ops->name : "???", i);
+	tty_ldisc_put(ld.ops);
+	return 0;
+}
+
+static const struct seq_operations tty_ldiscs_seq_ops = {
+	.start	= tty_ldiscs_seq_start,
+	.next	= tty_ldiscs_seq_next,
+	.stop	= tty_ldiscs_seq_stop,
+	.show	= tty_ldiscs_seq_show,
+};
+
+static int proc_tty_ldiscs_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &tty_ldiscs_seq_ops);
+}
+
+const struct file_operations tty_ldiscs_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= proc_tty_ldiscs_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
+/**
+ *	tty_ldisc_assign	-	set ldisc on a tty
+ *	@tty: tty to assign
+ *	@ld: line discipline
+ *
+ *	Install an instance of a line discipline into a tty structure. The
+ *	ldisc must have a reference count above zero to ensure it remains/
+ *	The tty instance refcount starts at zero.
+ *
+ *	Locking:
+ *		Caller must hold references
+ */
+
+static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
+{
+	ld->refcount = 0;
+	tty->ldisc = *ld;
+}
+
+/**
+ *	tty_ldisc_try		-	internal helper
+ *	@tty: the tty
+ *
+ *	Make a single attempt to grab and bump the refcount on
+ *	the tty ldisc. Return 0 on failure or 1 on success. This is
+ *	used to implement both the waiting and non waiting versions
+ *	of tty_ldisc_ref
+ *
+ *	Locking: takes tty_ldisc_lock
+ */
+
+static int tty_ldisc_try(struct tty_struct *tty)
+{
+	unsigned long flags;
+	struct tty_ldisc *ld;
+	int ret = 0;
+
+	spin_lock_irqsave(&tty_ldisc_lock, flags);
+	ld = &tty->ldisc;
+	if (test_bit(TTY_LDISC, &tty->flags)) {
+		ld->refcount++;
+		ret = 1;
+	}
+	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+	return ret;
+}
+
+/**
+ *	tty_ldisc_ref_wait	-	wait for the tty ldisc
+ *	@tty: tty device
+ *
+ *	Dereference the line discipline for the terminal and take a
+ *	reference to it. If the line discipline is in flux then
+ *	wait patiently until it changes.
+ *
+ *	Note: Must not be called from an IRQ/timer context. The caller
+ *	must also be careful not to hold other locks that will deadlock
+ *	against a discipline change, such as an existing ldisc reference
+ *	(which we check for)
+ *
+ *	Locking: call functions take tty_ldisc_lock
+ */
+
+struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
+{
+	/* wait_event is a macro */
+	wait_event(tty_ldisc_wait, tty_ldisc_try(tty));
+	if (tty->ldisc.refcount == 0)
+		printk(KERN_ERR "tty_ldisc_ref_wait\n");
+	return &tty->ldisc;
+}
+
+EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
+
+/**
+ *	tty_ldisc_ref		-	get the tty ldisc
+ *	@tty: tty device
+ *
+ *	Dereference the line discipline for the terminal and take a
+ *	reference to it. If the line discipline is in flux then
+ *	return NULL. Can be called from IRQ and timer functions.
+ *
+ *	Locking: called functions take tty_ldisc_lock
+ */
+
+struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty)
+{
+	if (tty_ldisc_try(tty))
+		return &tty->ldisc;
+	return NULL;
+}
+
+EXPORT_SYMBOL_GPL(tty_ldisc_ref);
+
+/**
+ *	tty_ldisc_deref		-	free a tty ldisc reference
+ *	@ld: reference to free up
+ *
+ *	Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May
+ *	be called in IRQ context.
+ *
+ *	Locking: takes tty_ldisc_lock
+ */
+
+void tty_ldisc_deref(struct tty_ldisc *ld)
+{
+	unsigned long flags;
+
+	BUG_ON(ld == NULL);
+
+	spin_lock_irqsave(&tty_ldisc_lock, flags);
+	if (ld->refcount == 0)
+		printk(KERN_ERR "tty_ldisc_deref: no references.\n");
+	else
+		ld->refcount--;
+	if (ld->refcount == 0)
+		wake_up(&tty_ldisc_wait);
+	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+}
+
+EXPORT_SYMBOL_GPL(tty_ldisc_deref);
+
+/**
+ *	tty_ldisc_enable	-	allow ldisc use
+ *	@tty: terminal to activate ldisc on
+ *
+ *	Set the TTY_LDISC flag when the line discipline can be called
+ *	again. Do necessary wakeups for existing sleepers.
+ *
+ *	Note: nobody should set this bit except via this function. Clearing
+ *	directly is allowed.
+ */
+
+void tty_ldisc_enable(struct tty_struct *tty)
+{
+	set_bit(TTY_LDISC, &tty->flags);
+	wake_up(&tty_ldisc_wait);
+}
+
+/**
+ *	tty_set_termios_ldisc		-	set ldisc field
+ *	@tty: tty structure
+ *	@num: line discipline number
+ *
+ *	This is probably overkill for real world processors but
+ *	they are not on hot paths so a little discipline won't do
+ *	any harm.
+ *
+ *	Locking: takes termios_mutex
+ */
+
+static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
+{
+	mutex_lock(&tty->termios_mutex);
+	tty->termios->c_line = num;
+	mutex_unlock(&tty->termios_mutex);
+}
+
+
+/**
+ *	tty_ldisc_restore	-	helper for tty ldisc change
+ *	@tty: tty to recover
+ *	@old: previous ldisc
+ *
+ *	Restore the previous line discipline or N_TTY when a line discipline
+ *	change fails due to an open error
+ */
+
+static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
+{
+	char buf[64];
+	struct tty_ldisc new_ldisc;
+
+	/* There is an outstanding reference here so this is safe */
+	tty_ldisc_get(old->ops->num, old);
+	tty_ldisc_assign(tty, old);
+	tty_set_termios_ldisc(tty, old->ops->num);
+	if (old->ops->open && (old->ops->open(tty) < 0)) {
+		tty_ldisc_put(old->ops);
+		/* This driver is always present */
+		if (tty_ldisc_get(N_TTY, &new_ldisc) < 0)
+			panic("n_tty: get");
+		tty_ldisc_assign(tty, &new_ldisc);
+		tty_set_termios_ldisc(tty, N_TTY);
+		if (new_ldisc.ops->open) {
+			int r = new_ldisc.ops->open(tty);
+				if (r < 0)
+				panic("Couldn't open N_TTY ldisc for "
+				      "%s --- error %d.",
+				      tty_name(tty, buf), r);
+		}
+	}
+}
+
+/**
+ *	tty_set_ldisc		-	set line discipline
+ *	@tty: the terminal to set
+ *	@ldisc: the line discipline
+ *
+ *	Set the discipline of a tty line. Must be called from a process
+ *	context.
+ *
+ *	Locking: takes tty_ldisc_lock.
+ *		 called functions take termios_mutex
+ */
+
+int tty_set_ldisc(struct tty_struct *tty, int ldisc)
+{
+	int retval;
+	struct tty_ldisc o_ldisc, new_ldisc;
+	int work;
+	unsigned long flags;
+	struct tty_struct *o_tty;
+
+restart:
+	/* This is a bit ugly for now but means we can break the 'ldisc
+	   is part of the tty struct' assumption later */
+	retval = tty_ldisc_get(ldisc, &new_ldisc);
+	if (retval)
+		return retval;
+
+	/*
+	 *	Problem: What do we do if this blocks ?
+	 */
+
+	tty_wait_until_sent(tty, 0);
+
+	if (tty->ldisc.ops->num == ldisc) {
+		tty_ldisc_put(new_ldisc.ops);
+		return 0;
+	}
+
+	/*
+	 *	No more input please, we are switching. The new ldisc
+	 *	will update this value in the ldisc open function
+	 */
+
+	tty->receive_room = 0;
+
+	o_ldisc = tty->ldisc;
+	o_tty = tty->link;
+
+	/*
+	 *	Make sure we don't change while someone holds a
+	 *	reference to the line discipline. The TTY_LDISC bit
+	 *	prevents anyone taking a reference once it is clear.
+	 *	We need the lock to avoid racing reference takers.
+	 */
+
+	spin_lock_irqsave(&tty_ldisc_lock, flags);
+	if (tty->ldisc.refcount || (o_tty && o_tty->ldisc.refcount)) {
+		if (tty->ldisc.refcount) {
+			/* Free the new ldisc we grabbed. Must drop the lock
+			   first. */
+			spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+			tty_ldisc_put(o_ldisc.ops);
+			/*
+			 * There are several reasons we may be busy, including
+			 * random momentary I/O traffic. We must therefore
+			 * retry. We could distinguish between blocking ops
+			 * and retries if we made tty_ldisc_wait() smarter.
+			 * That is up for discussion.
+			 */
+			if (wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0)
+				return -ERESTARTSYS;
+			goto restart;
+		}
+		if (o_tty && o_tty->ldisc.refcount) {
+			spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+			tty_ldisc_put(o_tty->ldisc.ops);
+			if (wait_event_interruptible(tty_ldisc_wait, o_tty->ldisc.refcount == 0) < 0)
+				return -ERESTARTSYS;
+			goto restart;
+		}
+	}
+	/*
+	 *	If the TTY_LDISC bit is set, then we are racing against
+	 *	another ldisc change
+	 */
+	if (!test_bit(TTY_LDISC, &tty->flags)) {
+		struct tty_ldisc *ld;
+		spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+		tty_ldisc_put(new_ldisc.ops);
+		ld = tty_ldisc_ref_wait(tty);
+		tty_ldisc_deref(ld);
+		goto restart;
+	}
+
+	clear_bit(TTY_LDISC, &tty->flags);
+	if (o_tty)
+		clear_bit(TTY_LDISC, &o_tty->flags);
+	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+	
+	/*
+	 *	From this point on we know nobody has an ldisc
+	 *	usage reference, nor can they obtain one until
+	 *	we say so later on.
+	 */
+
+	work = cancel_delayed_work(&tty->buf.work);
+	/*
+	 * Wait for ->hangup_work and ->buf.work handlers to terminate
+	 * MUST NOT hold locks here.
+	 */
+	flush_scheduled_work();
+	/* Shutdown the current discipline. */
+	if (o_ldisc.ops->close)
+		(o_ldisc.ops->close)(tty);
+
+	/* Now set up the new line discipline. */
+	tty_ldisc_assign(tty, &new_ldisc);
+	tty_set_termios_ldisc(tty, ldisc);
+	if (new_ldisc.ops->open)
+		retval = (new_ldisc.ops->open)(tty);
+	if (retval < 0) {
+		tty_ldisc_put(new_ldisc.ops);
+		tty_ldisc_restore(tty, &o_ldisc);
+	}
+	/* At this point we hold a reference to the new ldisc and a
+	   a reference to the old ldisc. If we ended up flipping back
+	   to the existing ldisc we have two references to it */
+
+	if (tty->ldisc.ops->num != o_ldisc.ops->num && tty->ops->set_ldisc)
+		tty->ops->set_ldisc(tty);
+
+	tty_ldisc_put(o_ldisc.ops);
+
+	/*
+	 *	Allow ldisc referencing to occur as soon as the driver
+	 *	ldisc callback completes.
+	 */
+
+	tty_ldisc_enable(tty);
+	if (o_tty)
+		tty_ldisc_enable(o_tty);
+
+	/* Restart it in case no characters kick it off. Safe if
+	   already running */
+	if (work)
+		schedule_delayed_work(&tty->buf.work, 1);
+	return retval;
+}
+
+
+/**
+ *	tty_ldisc_setup			-	open line discipline
+ *	@tty: tty being shut down
+ *	@o_tty: pair tty for pty/tty pairs
+ *
+ *	Called during the initial open of a tty/pty pair in order to set up the
+ *	line discplines and bind them to the tty.
+ */
+
+int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
+{
+	struct tty_ldisc *ld = &tty->ldisc;
+	int retval;
+
+	if (ld->ops->open) {
+		retval = (ld->ops->open)(tty);
+		if (retval)
+			return retval;
+	}
+	if (o_tty && o_tty->ldisc.ops->open) {
+		retval = (o_tty->ldisc.ops->open)(o_tty);
+		if (retval) {
+			if (ld->ops->close)
+				(ld->ops->close)(tty);
+			return retval;
+		}
+		tty_ldisc_enable(o_tty);
+	}
+	tty_ldisc_enable(tty);
+	return 0;
+}
+
+/**
+ *	tty_ldisc_release		-	release line discipline
+ *	@tty: tty being shut down
+ *	@o_tty: pair tty for pty/tty pairs
+ *
+ *	Called during the final close of a tty/pty pair in order to shut down the
+ *	line discpline layer.
+ */
+
+void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
+{
+	unsigned long flags;
+	struct tty_ldisc ld;
+	/*
+	 * Prevent flush_to_ldisc() from rescheduling the work for later.  Then
+	 * kill any delayed work. As this is the final close it does not
+	 * race with the set_ldisc code path.
+	 */
+	clear_bit(TTY_LDISC, &tty->flags);
+	cancel_delayed_work(&tty->buf.work);
+
+	/*
+	 * Wait for ->hangup_work and ->buf.work handlers to terminate
+	 */
+
+	flush_scheduled_work();
+
+	/*
+	 * Wait for any short term users (we know they are just driver
+	 * side waiters as the file is closing so user count on the file
+	 * side is zero.
+	 */
+	spin_lock_irqsave(&tty_ldisc_lock, flags);
+	while (tty->ldisc.refcount) {
+		spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+		wait_event(tty_ldisc_wait, tty->ldisc.refcount == 0);
+		spin_lock_irqsave(&tty_ldisc_lock, flags);
+	}
+	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+	/*
+	 * Shutdown the current line discipline, and reset it to N_TTY.
+	 *
+	 * FIXME: this MUST get fixed for the new reflocking
+	 */
+	if (tty->ldisc.ops->close)
+		(tty->ldisc.ops->close)(tty);
+	tty_ldisc_put(tty->ldisc.ops);
+
+	/*
+	 *	Switch the line discipline back
+	 */
+	WARN_ON(tty_ldisc_get(N_TTY, &ld));
+	tty_ldisc_assign(tty, &ld);
+	tty_set_termios_ldisc(tty, N_TTY);
+	if (o_tty) {
+		/* FIXME: could o_tty be in setldisc here ? */
+		clear_bit(TTY_LDISC, &o_tty->flags);
+		if (o_tty->ldisc.ops->close)
+			(o_tty->ldisc.ops->close)(o_tty);
+		tty_ldisc_put(o_tty->ldisc.ops);
+		WARN_ON(tty_ldisc_get(N_TTY, &ld));
+		tty_ldisc_assign(o_tty, &ld);
+		tty_set_termios_ldisc(o_tty, N_TTY);
+	}
+}
+
+/**
+ *	tty_ldisc_init		-	ldisc setup for new tty
+ *	@tty: tty being allocated
+ *
+ *	Set up the line discipline objects for a newly allocated tty. Note that
+ *	the tty structure is not completely set up when this call is made.
+ */
+
+void tty_ldisc_init(struct tty_struct *tty)
+{
+	struct tty_ldisc ld;
+	if (tty_ldisc_get(N_TTY, &ld) < 0)
+		panic("n_tty: init_tty");
+	tty_ldisc_assign(tty, &ld);
+}
+
+void tty_ldisc_begin(void)
+{
+	/* Setup the default TTY line discipline. */
+	(void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
+}
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index eebfad2..c2ae52d 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -481,10 +481,10 @@
 
 void vcs_make_sysfs(struct tty_struct *tty)
 {
-	device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
-			"vcs%u", tty->index + 1);
-	device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
-			"vcsa%u", tty->index + 1);
+	device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
+			      NULL, "vcs%u", tty->index + 1);
+	device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
+			      NULL, "vcsa%u", tty->index + 1);
 }
 
 void vcs_remove_sysfs(struct tty_struct *tty)
@@ -499,7 +499,7 @@
 		panic("unable to get major %d for vcs device", VCS_MAJOR);
 	vc_class = class_create(THIS_MODULE, "vc");
 
-	device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), "vcs");
-	device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), "vcsa");
+	device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
+	device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
 	return 0;
 }
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index e5da98d..7a70a40 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -886,10 +886,10 @@
 	state[i].cur_part = 0;
 	for (j = 0; j < MAX_PARTITIONS; ++j)
 		state[i].part_stat_rwi[j] = VIOT_IDLE;
-	device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i),
-			"iseries!vt%d", i);
-	device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80),
-			"iseries!nvt%d", i);
+	device_create_drvdata(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i),
+			      NULL, "iseries!vt%d", i);
+	device_create_drvdata(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80),
+			      NULL, "iseries!nvt%d", i);
 	printk(VIOTAPE_KERN_INFO "tape iseries/vt%d is iSeries "
 			"resource %10.10s type %4.4s, model %3.3s\n",
 			i, viotape_unitinfo[i].rsrcname,
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
index f17ac04..69c5afe 100644
--- a/drivers/char/vme_scc.c
+++ b/drivers/char/vme_scc.c
@@ -85,7 +85,7 @@
 static irqreturn_t scc_stat_int(int irq, void *data);
 static irqreturn_t scc_spcond_int(int irq, void *data);
 static void scc_setsignals(struct scc_port *port, int dtr, int rts);
-static void scc_break_ctl(struct tty_struct *tty, int break_state);
+static int scc_break_ctl(struct tty_struct *tty, int break_state);
 
 static struct tty_driver *scc_driver;
 
@@ -942,7 +942,7 @@
 }
 
 
-static void scc_break_ctl(struct tty_struct *tty, int break_state)
+static int scc_break_ctl(struct tty_struct *tty, int break_state)
 {
 	struct scc_port *port = (struct scc_port *)tty->driver_data;
 	unsigned long	flags;
@@ -952,6 +952,7 @@
 	SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK, 
 			break_state ? TCR_SEND_BREAK : 0);
 	local_irq_restore(flags);
+	return 0;
 }
 
 
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 935f1c2..e32a076 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -3425,9 +3425,10 @@
 	if (retval)
 		goto err;
 
-	con_driver->dev = device_create(vtconsole_class, NULL,
-					MKDEV(0, con_driver->node),
-					"vtcon%i", con_driver->node);
+	con_driver->dev = device_create_drvdata(vtconsole_class, NULL,
+						MKDEV(0, con_driver->node),
+						NULL, "vtcon%i",
+						con_driver->node);
 
 	if (IS_ERR(con_driver->dev)) {
 		printk(KERN_WARNING "Unable to create device for %s; "
@@ -3535,9 +3536,10 @@
 		struct con_driver *con = &registered_con_driver[i];
 
 		if (con->con && !con->dev) {
-			con->dev = device_create(vtconsole_class, NULL,
-						 MKDEV(0, con->node),
-						 "vtcon%i", con->node);
+			con->dev = device_create_drvdata(vtconsole_class, NULL,
+							 MKDEV(0, con->node),
+							 NULL, "vtcon%i",
+							 con->node);
 
 			if (IS_ERR(con->dev)) {
 				printk(KERN_WARNING "Unable to create "
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index 1e1b81e..51966cc 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -658,8 +658,9 @@
 		dev_err(dev, "cdev_add() failed\n");
 		goto failed3;
 	}
-	/*  devfs_mk_cdev(devt, S_IFCHR|S_IRUGO|S_IWUGO, DRIVER_NAME); */
-	device_create(icap_class, dev, devt, "%s%d", DRIVER_NAME, id);
+
+	device_create_drvdata(icap_class, dev, devt, NULL,
+			      "%s%d", DRIVER_NAME, id);
 	return 0;		/* success */
 
  failed3:
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index d8f8b1e..8d6a3ff 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -38,10 +38,10 @@
  * also protects the cpufreq_cpu_data array.
  */
 static struct cpufreq_driver *cpufreq_driver;
-static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS];
+static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data);
 #ifdef CONFIG_HOTPLUG_CPU
 /* This one keeps track of the previously set governor of a removed CPU */
-static struct cpufreq_governor *cpufreq_cpu_governor[NR_CPUS];
+static DEFINE_PER_CPU(struct cpufreq_governor *, cpufreq_cpu_governor);
 #endif
 static DEFINE_SPINLOCK(cpufreq_driver_lock);
 
@@ -135,7 +135,7 @@
 	struct cpufreq_policy *data;
 	unsigned long flags;
 
-	if (cpu >= NR_CPUS)
+	if (cpu >= nr_cpu_ids)
 		goto err_out;
 
 	/* get the cpufreq driver */
@@ -149,7 +149,7 @@
 
 
 	/* get the CPU */
-	data = cpufreq_cpu_data[cpu];
+	data = per_cpu(cpufreq_cpu_data, cpu);
 
 	if (!data)
 		goto err_out_put_module;
@@ -327,7 +327,7 @@
 	dprintk("notification %u of frequency transition to %u kHz\n",
 		state, freqs->new);
 
-	policy = cpufreq_cpu_data[freqs->cpu];
+	policy = per_cpu(cpufreq_cpu_data, freqs->cpu);
 	switch (state) {
 
 	case CPUFREQ_PRECHANGE:
@@ -828,8 +828,8 @@
 #ifdef CONFIG_SMP
 
 #ifdef CONFIG_HOTPLUG_CPU
-	if (cpufreq_cpu_governor[cpu]){
-		policy->governor = cpufreq_cpu_governor[cpu];
+	if (per_cpu(cpufreq_cpu_governor, cpu)) {
+		policy->governor = per_cpu(cpufreq_cpu_governor, cpu);
 		dprintk("Restoring governor %s for cpu %d\n",
 		       policy->governor->name, cpu);
 	}
@@ -854,7 +854,7 @@
 
 			spin_lock_irqsave(&cpufreq_driver_lock, flags);
 			managed_policy->cpus = policy->cpus;
-			cpufreq_cpu_data[cpu] = managed_policy;
+			per_cpu(cpufreq_cpu_data, cpu) = managed_policy;
 			spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
 			dprintk("CPU already managed, adding link\n");
@@ -899,7 +899,7 @@
 
 	spin_lock_irqsave(&cpufreq_driver_lock, flags);
 	for_each_cpu_mask_nr(j, policy->cpus) {
-		cpufreq_cpu_data[j] = policy;
+		per_cpu(cpufreq_cpu_data, j) = policy;
 		per_cpu(policy_cpu, j) = policy->cpu;
 	}
 	spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
@@ -946,7 +946,7 @@
 err_out_unregister:
 	spin_lock_irqsave(&cpufreq_driver_lock, flags);
 	for_each_cpu_mask_nr(j, policy->cpus)
-		cpufreq_cpu_data[j] = NULL;
+		per_cpu(cpufreq_cpu_data, j) = NULL;
 	spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
 	kobject_put(&policy->kobj);
@@ -989,7 +989,7 @@
 	dprintk("unregistering CPU %u\n", cpu);
 
 	spin_lock_irqsave(&cpufreq_driver_lock, flags);
-	data = cpufreq_cpu_data[cpu];
+	data = per_cpu(cpufreq_cpu_data, cpu);
 
 	if (!data) {
 		spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
@@ -997,7 +997,7 @@
 		unlock_policy_rwsem_write(cpu);
 		return -EINVAL;
 	}
-	cpufreq_cpu_data[cpu] = NULL;
+	per_cpu(cpufreq_cpu_data, cpu) = NULL;
 
 
 #ifdef CONFIG_SMP
@@ -1019,19 +1019,19 @@
 #ifdef CONFIG_SMP
 
 #ifdef CONFIG_HOTPLUG_CPU
-	cpufreq_cpu_governor[cpu] = data->governor;
+	per_cpu(cpufreq_cpu_governor, cpu) = data->governor;
 #endif
 
 	/* if we have other CPUs still registered, we need to unlink them,
 	 * or else wait_for_completion below will lock up. Clean the
-	 * cpufreq_cpu_data[] while holding the lock, and remove the sysfs
-	 * links afterwards.
+	 * per_cpu(cpufreq_cpu_data) while holding the lock, and remove
+	 * the sysfs links afterwards.
 	 */
 	if (unlikely(cpus_weight(data->cpus) > 1)) {
 		for_each_cpu_mask_nr(j, data->cpus) {
 			if (j == cpu)
 				continue;
-			cpufreq_cpu_data[j] = NULL;
+			per_cpu(cpufreq_cpu_data, j) = NULL;
 		}
 	}
 
@@ -1043,7 +1043,7 @@
 				continue;
 			dprintk("removing link for cpu %u\n", j);
 #ifdef CONFIG_HOTPLUG_CPU
-			cpufreq_cpu_governor[j] = data->governor;
+			per_cpu(cpufreq_cpu_governor, j) = data->governor;
 #endif
 			cpu_sys_dev = get_cpu_sysdev(j);
 			sysfs_remove_link(&cpu_sys_dev->kobj, "cpufreq");
@@ -1153,7 +1153,7 @@
 
 static unsigned int __cpufreq_get(unsigned int cpu)
 {
-	struct cpufreq_policy *policy = cpufreq_cpu_data[cpu];
+	struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
 	unsigned int ret_freq = 0;
 
 	if (!cpufreq_driver->get)
@@ -1822,16 +1822,19 @@
 	cpufreq_driver = driver_data;
 	spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
-	ret = sysdev_driver_register(&cpu_sysdev_class,&cpufreq_sysdev_driver);
+	ret = sysdev_driver_register(&cpu_sysdev_class,
+					&cpufreq_sysdev_driver);
 
 	if ((!ret) && !(cpufreq_driver->flags & CPUFREQ_STICKY)) {
 		int i;
 		ret = -ENODEV;
 
 		/* check for at least one working CPU */
-		for (i=0; i<NR_CPUS; i++)
-			if (cpufreq_cpu_data[i])
+		for (i = 0; i < nr_cpu_ids; i++)
+			if (cpu_possible(i) && per_cpu(cpufreq_cpu_data, i)) {
 				ret = 0;
+				break;
+			}
 
 		/* if all ->init() calls failed, unregister */
 		if (ret) {
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index ae70d63..c0ff97d 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -43,7 +43,7 @@
 #endif
 };
 
-static struct cpufreq_stats *cpufreq_stats_table[NR_CPUS];
+static DEFINE_PER_CPU(struct cpufreq_stats *, cpufreq_stats_table);
 
 struct cpufreq_stats_attribute {
 	struct attribute attr;
@@ -58,7 +58,7 @@
 
 	cur_time = get_jiffies_64();
 	spin_lock(&cpufreq_stats_lock);
-	stat = cpufreq_stats_table[cpu];
+	stat = per_cpu(cpufreq_stats_table, cpu);
 	if (stat->time_in_state)
 		stat->time_in_state[stat->last_index] =
 			cputime64_add(stat->time_in_state[stat->last_index],
@@ -71,11 +71,11 @@
 static ssize_t
 show_total_trans(struct cpufreq_policy *policy, char *buf)
 {
-	struct cpufreq_stats *stat = cpufreq_stats_table[policy->cpu];
+	struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu);
 	if (!stat)
 		return 0;
 	return sprintf(buf, "%d\n",
-			cpufreq_stats_table[stat->cpu]->total_trans);
+			per_cpu(cpufreq_stats_table, stat->cpu)->total_trans);
 }
 
 static ssize_t
@@ -83,7 +83,7 @@
 {
 	ssize_t len = 0;
 	int i;
-	struct cpufreq_stats *stat = cpufreq_stats_table[policy->cpu];
+	struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu);
 	if (!stat)
 		return 0;
 	cpufreq_stats_update(stat->cpu);
@@ -101,7 +101,7 @@
 	ssize_t len = 0;
 	int i, j;
 
-	struct cpufreq_stats *stat = cpufreq_stats_table[policy->cpu];
+	struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu);
 	if (!stat)
 		return 0;
 	cpufreq_stats_update(stat->cpu);
@@ -170,7 +170,7 @@
 
 static void cpufreq_stats_free_table(unsigned int cpu)
 {
-	struct cpufreq_stats *stat = cpufreq_stats_table[cpu];
+	struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, cpu);
 	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
 	if (policy && policy->cpu == cpu)
 		sysfs_remove_group(&policy->kobj, &stats_attr_group);
@@ -178,7 +178,7 @@
 		kfree(stat->time_in_state);
 		kfree(stat);
 	}
-	cpufreq_stats_table[cpu] = NULL;
+	per_cpu(cpufreq_stats_table, cpu) = NULL;
 	if (policy)
 		cpufreq_cpu_put(policy);
 }
@@ -192,7 +192,7 @@
 	struct cpufreq_policy *data;
 	unsigned int alloc_size;
 	unsigned int cpu = policy->cpu;
-	if (cpufreq_stats_table[cpu])
+	if (per_cpu(cpufreq_stats_table, cpu))
 		return -EBUSY;
 	if ((stat = kzalloc(sizeof(struct cpufreq_stats), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
@@ -207,7 +207,7 @@
 		goto error_out;
 
 	stat->cpu = cpu;
-	cpufreq_stats_table[cpu] = stat;
+	per_cpu(cpufreq_stats_table, cpu) = stat;
 
 	for (i=0; table[i].frequency != CPUFREQ_TABLE_END; i++) {
 		unsigned int freq = table[i].frequency;
@@ -251,7 +251,7 @@
 	cpufreq_cpu_put(data);
 error_get_fail:
 	kfree(stat);
-	cpufreq_stats_table[cpu] = NULL;
+	per_cpu(cpufreq_stats_table, cpu) = NULL;
 	return ret;
 }
 
@@ -284,7 +284,7 @@
 	if (val != CPUFREQ_POSTCHANGE)
 		return 0;
 
-	stat = cpufreq_stats_table[freq->cpu];
+	stat = per_cpu(cpufreq_stats_table, freq->cpu);
 	if (!stat)
 		return 0;
 
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index b64c6bc..9071d80 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -174,7 +174,7 @@
 }
 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);
 
-static struct cpufreq_frequency_table *show_table[NR_CPUS];
+static DEFINE_PER_CPU(struct cpufreq_frequency_table *, show_table);
 /**
  * show_available_freqs - show available frequencies for the specified CPU
  */
@@ -185,10 +185,10 @@
 	ssize_t count = 0;
 	struct cpufreq_frequency_table *table;
 
-	if (!show_table[cpu])
+	if (!per_cpu(show_table, cpu))
 		return -ENODEV;
 
-	table = show_table[cpu];
+	table = per_cpu(show_table, cpu);
 
 	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
 		if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
@@ -217,20 +217,20 @@
 				      unsigned int cpu)
 {
 	dprintk("setting show_table for cpu %u to %p\n", cpu, table);
-	show_table[cpu] = table;
+	per_cpu(show_table, cpu) = table;
 }
 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr);
 
 void cpufreq_frequency_table_put_attr(unsigned int cpu)
 {
 	dprintk("clearing show_table for cpu %u\n", cpu);
-	show_table[cpu] = NULL;
+	per_cpu(show_table, cpu) = NULL;
 }
 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr);
 
 struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu)
 {
-	return show_table[cpu];
+	return per_cpu(show_table, cpu);
 }
 EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table);
 
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
index e949618..31a0e0b 100644
--- a/drivers/cpuidle/sysfs.c
+++ b/drivers/cpuidle/sysfs.c
@@ -21,7 +21,8 @@
 }
 __setup("cpuidle_sysfs_switch", cpuidle_sysfs_setup);
 
-static ssize_t show_available_governors(struct sys_device *dev, char *buf)
+static ssize_t show_available_governors(struct sys_device *dev,
+		struct sysdev_attribute *attr, char *buf)
 {
 	ssize_t i = 0;
 	struct cpuidle_governor *tmp;
@@ -39,7 +40,8 @@
 	return i;
 }
 
-static ssize_t show_current_driver(struct sys_device *dev, char *buf)
+static ssize_t show_current_driver(struct sys_device *dev,
+		struct sysdev_attribute *attr, char *buf)
 {
 	ssize_t ret;
 
@@ -53,7 +55,8 @@
 	return ret;
 }
 
-static ssize_t show_current_governor(struct sys_device *dev, char *buf)
+static ssize_t show_current_governor(struct sys_device *dev,
+			struct sysdev_attribute *attr, char *buf)
 {
 	ssize_t ret;
 
@@ -68,6 +71,7 @@
 }
 
 static ssize_t store_current_governor(struct sys_device *dev,
+	struct sysdev_attribute *attr,
 	const char *buf, size_t count)
 {
 	char gov_name[CPUIDLE_NAME_LEN];
diff --git a/drivers/dca/dca-core.c b/drivers/dca/dca-core.c
index bf5b92f..ec249d2 100644
--- a/drivers/dca/dca-core.c
+++ b/drivers/dca/dca-core.c
@@ -28,13 +28,29 @@
 #include <linux/device.h>
 #include <linux/dca.h>
 
-MODULE_LICENSE("GPL");
+#define DCA_VERSION "1.4"
 
-/* For now we're assuming a single, global, DCA provider for the system. */
+MODULE_VERSION(DCA_VERSION);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Intel Corporation");
 
 static DEFINE_SPINLOCK(dca_lock);
 
-static struct dca_provider *global_dca = NULL;
+static LIST_HEAD(dca_providers);
+
+static struct dca_provider *dca_find_provider_by_dev(struct device *dev)
+{
+	struct dca_provider *dca, *ret = NULL;
+
+	list_for_each_entry(dca, &dca_providers, node) {
+		if ((!dev) || (dca->ops->dev_managed(dca, dev))) {
+			ret = dca;
+			break;
+		}
+	}
+
+	return ret;
+}
 
 /**
  * dca_add_requester - add a dca client to the list
@@ -42,25 +58,39 @@
  */
 int dca_add_requester(struct device *dev)
 {
-	int err, slot;
+	struct dca_provider *dca;
+	int err, slot = -ENODEV;
 
-	if (!global_dca)
-		return -ENODEV;
+	if (!dev)
+		return -EFAULT;
 
 	spin_lock(&dca_lock);
-	slot = global_dca->ops->add_requester(global_dca, dev);
-	spin_unlock(&dca_lock);
-	if (slot < 0)
-		return slot;
 
-	err = dca_sysfs_add_req(global_dca, dev, slot);
+	/* check if the requester has not been added already */
+	dca = dca_find_provider_by_dev(dev);
+	if (dca) {
+		spin_unlock(&dca_lock);
+		return -EEXIST;
+	}
+
+	list_for_each_entry(dca, &dca_providers, node) {
+		slot = dca->ops->add_requester(dca, dev);
+		if (slot >= 0)
+			break;
+	}
+	if (slot < 0) {
+		spin_unlock(&dca_lock);
+		return slot;
+	}
+
+	err = dca_sysfs_add_req(dca, dev, slot);
 	if (err) {
-		spin_lock(&dca_lock);
-		global_dca->ops->remove_requester(global_dca, dev);
+		dca->ops->remove_requester(dca, dev);
 		spin_unlock(&dca_lock);
 		return err;
 	}
 
+	spin_unlock(&dca_lock);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(dca_add_requester);
@@ -71,30 +101,78 @@
  */
 int dca_remove_requester(struct device *dev)
 {
+	struct dca_provider *dca;
 	int slot;
-	if (!global_dca)
-		return -ENODEV;
+
+	if (!dev)
+		return -EFAULT;
 
 	spin_lock(&dca_lock);
-	slot = global_dca->ops->remove_requester(global_dca, dev);
-	spin_unlock(&dca_lock);
-	if (slot < 0)
+	dca = dca_find_provider_by_dev(dev);
+	if (!dca) {
+		spin_unlock(&dca_lock);
+		return -ENODEV;
+	}
+	slot = dca->ops->remove_requester(dca, dev);
+	if (slot < 0) {
+		spin_unlock(&dca_lock);
 		return slot;
+	}
 
-	dca_sysfs_remove_req(global_dca, slot);
+	dca_sysfs_remove_req(dca, slot);
+
+	spin_unlock(&dca_lock);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(dca_remove_requester);
 
 /**
- * dca_get_tag - return the dca tag for the given cpu
+ * dca_common_get_tag - return the dca tag (serves both new and old api)
+ * @dev - the device that wants dca service
+ * @cpu - the cpuid as returned by get_cpu()
+ */
+u8 dca_common_get_tag(struct device *dev, int cpu)
+{
+	struct dca_provider *dca;
+	u8 tag;
+
+	spin_lock(&dca_lock);
+
+	dca = dca_find_provider_by_dev(dev);
+	if (!dca) {
+		spin_unlock(&dca_lock);
+		return -ENODEV;
+	}
+	tag = dca->ops->get_tag(dca, dev, cpu);
+
+	spin_unlock(&dca_lock);
+	return tag;
+}
+
+/**
+ * dca3_get_tag - return the dca tag to the requester device
+ *                for the given cpu (new api)
+ * @dev - the device that wants dca service
+ * @cpu - the cpuid as returned by get_cpu()
+ */
+u8 dca3_get_tag(struct device *dev, int cpu)
+{
+	if (!dev)
+		return -EFAULT;
+
+	return dca_common_get_tag(dev, cpu);
+}
+EXPORT_SYMBOL_GPL(dca3_get_tag);
+
+/**
+ * dca_get_tag - return the dca tag for the given cpu (old api)
  * @cpu - the cpuid as returned by get_cpu()
  */
 u8 dca_get_tag(int cpu)
 {
-	if (!global_dca)
-		return -ENODEV;
-	return global_dca->ops->get_tag(global_dca, cpu);
+	struct device *dev = NULL;
+
+	return dca_common_get_tag(dev, cpu);
 }
 EXPORT_SYMBOL_GPL(dca_get_tag);
 
@@ -140,12 +218,10 @@
 {
 	int err;
 
-	if (global_dca)
-		return -EEXIST;
 	err = dca_sysfs_add_provider(dca, dev);
 	if (err)
 		return err;
-	global_dca = dca;
+	list_add(&dca->node, &dca_providers);
 	blocking_notifier_call_chain(&dca_provider_chain,
 				     DCA_PROVIDER_ADD, NULL);
 	return 0;
@@ -158,11 +234,9 @@
  */
 void unregister_dca_provider(struct dca_provider *dca)
 {
-	if (!global_dca)
-		return;
 	blocking_notifier_call_chain(&dca_provider_chain,
 				     DCA_PROVIDER_REMOVE, NULL);
-	global_dca = NULL;
+	list_del(&dca->node);
 	dca_sysfs_remove_provider(dca);
 }
 EXPORT_SYMBOL_GPL(unregister_dca_provider);
@@ -187,6 +261,7 @@
 
 static int __init dca_init(void)
 {
+	printk(KERN_ERR "dca service started, version %s\n", DCA_VERSION);
 	return dca_sysfs_init();
 }
 
diff --git a/drivers/dca/dca-sysfs.c b/drivers/dca/dca-sysfs.c
index 011328f..7af4b40 100644
--- a/drivers/dca/dca-sysfs.c
+++ b/drivers/dca/dca-sysfs.c
@@ -13,9 +13,11 @@
 int dca_sysfs_add_req(struct dca_provider *dca, struct device *dev, int slot)
 {
 	struct device *cd;
+	static int req_count;
 
-	cd = device_create(dca_class, dca->cd, MKDEV(0, slot + 1),
-			   "requester%d", slot);
+	cd = device_create_drvdata(dca_class, dca->cd,
+				   MKDEV(0, slot + 1), NULL,
+				   "requester%d", req_count++);
 	if (IS_ERR(cd))
 		return PTR_ERR(cd);
 	return 0;
@@ -46,7 +48,8 @@
 		return err;
 	}
 
-	cd = device_create(dca_class, dev, MKDEV(0, 0), "dca%d", dca->id);
+	cd = device_create_drvdata(dca_class, dev, MKDEV(0, 0), NULL,
+				   "dca%d", dca->id);
 	if (IS_ERR(cd)) {
 		spin_lock(&dca_idr_lock);
 		idr_remove(&dca_idr, dca->id);
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 6239c3d..cd30390 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -4,13 +4,14 @@
 
 menuconfig DMADEVICES
 	bool "DMA Engine support"
-	depends on (PCI && X86) || ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX || PPC
-	depends on !HIGHMEM64G
+	depends on !HIGHMEM64G && HAS_DMA
 	help
 	  DMA engines can do asynchronous data transfers without
 	  involving the host CPU.  Currently, this framework can be
 	  used to offload memory copies in the network stack and
-	  RAID operations in the MD driver.
+	  RAID operations in the MD driver.  This menu only presents
+	  DMA Device drivers supported by the configured arch, it may
+	  be empty in some cases.
 
 if DMADEVICES
 
@@ -37,6 +38,15 @@
 	help
 	  Enable support for the Intel(R) IOP Series RAID engines.
 
+config DW_DMAC
+	tristate "Synopsys DesignWare AHB DMA support"
+	depends on AVR32
+	select DMA_ENGINE
+	default y if CPU_AT32AP7000
+	help
+	  Support the Synopsys DesignWare AHB DMA controller.  This
+	  can be integrated in chips such as the Atmel AT32ap7000.
+
 config FSL_DMA
 	bool "Freescale MPC85xx/MPC83xx DMA support"
 	depends on PPC
@@ -46,6 +56,14 @@
 	  MPC8560/40, MPC8555, MPC8548 and MPC8641 processors.
 	  The MPC8349, MPC8360 is also supported.
 
+config MV_XOR
+	bool "Marvell XOR engine support"
+	depends on PLAT_ORION
+	select ASYNC_CORE
+	select DMA_ENGINE
+	---help---
+	  Enable support for the Marvell XOR engine.
+
 config DMA_ENGINE
 	bool
 
@@ -55,10 +73,19 @@
 config NET_DMA
 	bool "Network: TCP receive copy offload"
 	depends on DMA_ENGINE && NET
+	default (INTEL_IOATDMA || FSL_DMA)
 	help
 	  This enables the use of DMA engines in the network stack to
 	  offload receive copy-to-user operations, freeing CPU cycles.
-	  Since this is the main user of the DMA engine, it should be enabled;
-	  say Y here.
+
+	  Say Y here if you enabled INTEL_IOATDMA or FSL_DMA, otherwise
+	  say N.
+
+config DMATEST
+	tristate "DMA Test client"
+	depends on DMA_ENGINE
+	help
+	  Simple DMA test client. Say N unless you're debugging a
+	  DMA Device driver.
 
 endif
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index c8036d9..14f5952 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -1,6 +1,9 @@
 obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
 obj-$(CONFIG_NET_DMA) += iovlock.o
+obj-$(CONFIG_DMATEST) += dmatest.o
 obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o
 ioatdma-objs := ioat.o ioat_dma.o ioat_dca.o
 obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
 obj-$(CONFIG_FSL_DMA) += fsldma.o
+obj-$(CONFIG_MV_XOR) += mv_xor.o
+obj-$(CONFIG_DW_DMAC) += dw_dmac.o
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 97b329e..dc003a3 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -169,12 +169,18 @@
 	enum dma_state_client ack;
 
 	/* Find a channel */
-	list_for_each_entry(device, &dma_device_list, global_node)
+	list_for_each_entry(device, &dma_device_list, global_node) {
+		/* Does the client require a specific DMA controller? */
+		if (client->slave && client->slave->dma_dev
+				&& client->slave->dma_dev != device->dev)
+			continue;
+
 		list_for_each_entry(chan, &device->channels, device_node) {
 			if (!dma_chan_satisfies_mask(chan, client->cap_mask))
 				continue;
 
-			desc = chan->device->device_alloc_chan_resources(chan);
+			desc = chan->device->device_alloc_chan_resources(
+					chan, client);
 			if (desc >= 0) {
 				ack = client->event_callback(client,
 						chan,
@@ -183,12 +189,14 @@
 				/* we are done once this client rejects
 				 * an available resource
 				 */
-				if (ack == DMA_ACK)
+				if (ack == DMA_ACK) {
 					dma_chan_get(chan);
-				else if (ack == DMA_NAK)
+					chan->client_count++;
+				} else if (ack == DMA_NAK)
 					return;
 			}
 		}
+	}
 }
 
 enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie)
@@ -272,8 +280,10 @@
 		/* client was holding resources for this channel so
 		 * free it
 		 */
-		if (ack == DMA_ACK)
+		if (ack == DMA_ACK) {
 			dma_chan_put(chan);
+			chan->client_count--;
+		}
 	}
 
 	mutex_unlock(&dma_list_mutex);
@@ -285,6 +295,10 @@
  */
 void dma_async_client_register(struct dma_client *client)
 {
+	/* validate client data */
+	BUG_ON(dma_has_cap(DMA_SLAVE, client->cap_mask) &&
+		!client->slave);
+
 	mutex_lock(&dma_list_mutex);
 	list_add_tail(&client->global_node, &dma_client_list);
 	mutex_unlock(&dma_list_mutex);
@@ -313,8 +327,10 @@
 			ack = client->event_callback(client, chan,
 				DMA_RESOURCE_REMOVED);
 
-			if (ack == DMA_ACK)
+			if (ack == DMA_ACK) {
 				dma_chan_put(chan);
+				chan->client_count--;
+			}
 		}
 
 	list_del(&client->global_node);
@@ -359,6 +375,10 @@
 		!device->device_prep_dma_memset);
 	BUG_ON(dma_has_cap(DMA_INTERRUPT, device->cap_mask) &&
 		!device->device_prep_dma_interrupt);
+	BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) &&
+		!device->device_prep_slave_sg);
+	BUG_ON(dma_has_cap(DMA_SLAVE, device->cap_mask) &&
+		!device->device_terminate_all);
 
 	BUG_ON(!device->device_alloc_chan_resources);
 	BUG_ON(!device->device_free_chan_resources);
@@ -378,7 +398,7 @@
 
 		chan->chan_id = chancnt++;
 		chan->dev.class = &dma_devclass;
-		chan->dev.parent = NULL;
+		chan->dev.parent = device->dev;
 		snprintf(chan->dev.bus_id, BUS_ID_SIZE, "dma%dchan%d",
 		         device->dev_id, chan->chan_id);
 
@@ -394,6 +414,7 @@
 		kref_get(&device->refcount);
 		kref_get(&device->refcount);
 		kref_init(&chan->refcount);
+		chan->client_count = 0;
 		chan->slow_ref = 0;
 		INIT_RCU_HEAD(&chan->rcu);
 	}
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
new file mode 100644
index 0000000..a08d197
--- /dev/null
+++ b/drivers/dma/dmatest.c
@@ -0,0 +1,444 @@
+/*
+ * DMA Engine test module
+ *
+ * Copyright (C) 2007 Atmel 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/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/init.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/random.h>
+#include <linux/wait.h>
+
+static unsigned int test_buf_size = 16384;
+module_param(test_buf_size, uint, S_IRUGO);
+MODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer");
+
+static char test_channel[BUS_ID_SIZE];
+module_param_string(channel, test_channel, sizeof(test_channel), S_IRUGO);
+MODULE_PARM_DESC(channel, "Bus ID of the channel to test (default: any)");
+
+static char test_device[BUS_ID_SIZE];
+module_param_string(device, test_device, sizeof(test_device), S_IRUGO);
+MODULE_PARM_DESC(device, "Bus ID of the DMA Engine to test (default: any)");
+
+static unsigned int threads_per_chan = 1;
+module_param(threads_per_chan, uint, S_IRUGO);
+MODULE_PARM_DESC(threads_per_chan,
+		"Number of threads to start per channel (default: 1)");
+
+static unsigned int max_channels;
+module_param(max_channels, uint, S_IRUGO);
+MODULE_PARM_DESC(nr_channels,
+		"Maximum number of channels to use (default: all)");
+
+/*
+ * Initialization patterns. All bytes in the source buffer has bit 7
+ * set, all bytes in the destination buffer has bit 7 cleared.
+ *
+ * Bit 6 is set for all bytes which are to be copied by the DMA
+ * engine. Bit 5 is set for all bytes which are to be overwritten by
+ * the DMA engine.
+ *
+ * The remaining bits are the inverse of a counter which increments by
+ * one for each byte address.
+ */
+#define PATTERN_SRC		0x80
+#define PATTERN_DST		0x00
+#define PATTERN_COPY		0x40
+#define PATTERN_OVERWRITE	0x20
+#define PATTERN_COUNT_MASK	0x1f
+
+struct dmatest_thread {
+	struct list_head	node;
+	struct task_struct	*task;
+	struct dma_chan		*chan;
+	u8			*srcbuf;
+	u8			*dstbuf;
+};
+
+struct dmatest_chan {
+	struct list_head	node;
+	struct dma_chan		*chan;
+	struct list_head	threads;
+};
+
+/*
+ * These are protected by dma_list_mutex since they're only used by
+ * the DMA client event callback
+ */
+static LIST_HEAD(dmatest_channels);
+static unsigned int nr_channels;
+
+static bool dmatest_match_channel(struct dma_chan *chan)
+{
+	if (test_channel[0] == '\0')
+		return true;
+	return strcmp(chan->dev.bus_id, test_channel) == 0;
+}
+
+static bool dmatest_match_device(struct dma_device *device)
+{
+	if (test_device[0] == '\0')
+		return true;
+	return strcmp(device->dev->bus_id, test_device) == 0;
+}
+
+static unsigned long dmatest_random(void)
+{
+	unsigned long buf;
+
+	get_random_bytes(&buf, sizeof(buf));
+	return buf;
+}
+
+static void dmatest_init_srcbuf(u8 *buf, unsigned int start, unsigned int len)
+{
+	unsigned int i;
+
+	for (i = 0; i < start; i++)
+		buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK);
+	for ( ; i < start + len; i++)
+		buf[i] = PATTERN_SRC | PATTERN_COPY
+			| (~i & PATTERN_COUNT_MASK);;
+	for ( ; i < test_buf_size; i++)
+		buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK);
+}
+
+static void dmatest_init_dstbuf(u8 *buf, unsigned int start, unsigned int len)
+{
+	unsigned int i;
+
+	for (i = 0; i < start; i++)
+		buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK);
+	for ( ; i < start + len; i++)
+		buf[i] = PATTERN_DST | PATTERN_OVERWRITE
+			| (~i & PATTERN_COUNT_MASK);
+	for ( ; i < test_buf_size; i++)
+		buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK);
+}
+
+static void dmatest_mismatch(u8 actual, u8 pattern, unsigned int index,
+		unsigned int counter, bool is_srcbuf)
+{
+	u8		diff = actual ^ pattern;
+	u8		expected = pattern | (~counter & PATTERN_COUNT_MASK);
+	const char	*thread_name = current->comm;
+
+	if (is_srcbuf)
+		pr_warning("%s: srcbuf[0x%x] overwritten!"
+				" Expected %02x, got %02x\n",
+				thread_name, index, expected, actual);
+	else if ((pattern & PATTERN_COPY)
+			&& (diff & (PATTERN_COPY | PATTERN_OVERWRITE)))
+		pr_warning("%s: dstbuf[0x%x] not copied!"
+				" Expected %02x, got %02x\n",
+				thread_name, index, expected, actual);
+	else if (diff & PATTERN_SRC)
+		pr_warning("%s: dstbuf[0x%x] was copied!"
+				" Expected %02x, got %02x\n",
+				thread_name, index, expected, actual);
+	else
+		pr_warning("%s: dstbuf[0x%x] mismatch!"
+				" Expected %02x, got %02x\n",
+				thread_name, index, expected, actual);
+}
+
+static unsigned int dmatest_verify(u8 *buf, unsigned int start,
+		unsigned int end, unsigned int counter, u8 pattern,
+		bool is_srcbuf)
+{
+	unsigned int i;
+	unsigned int error_count = 0;
+	u8 actual;
+
+	for (i = start; i < end; i++) {
+		actual = buf[i];
+		if (actual != (pattern | (~counter & PATTERN_COUNT_MASK))) {
+			if (error_count < 32)
+				dmatest_mismatch(actual, pattern, i, counter,
+						is_srcbuf);
+			error_count++;
+		}
+		counter++;
+	}
+
+	if (error_count > 32)
+		pr_warning("%s: %u errors suppressed\n",
+			current->comm, error_count - 32);
+
+	return error_count;
+}
+
+/*
+ * This function repeatedly tests DMA transfers of various lengths and
+ * offsets until it is told to exit by kthread_stop(). There may be
+ * multiple threads running this function in parallel for a single
+ * channel, and there may be multiple channels being tested in
+ * parallel.
+ *
+ * Before each test, the source and destination buffer is initialized
+ * with a known pattern. This pattern is different depending on
+ * whether it's in an area which is supposed to be copied or
+ * overwritten, and different in the source and destination buffers.
+ * So if the DMA engine doesn't copy exactly what we tell it to copy,
+ * we'll notice.
+ */
+static int dmatest_func(void *data)
+{
+	struct dmatest_thread	*thread = data;
+	struct dma_chan		*chan;
+	const char		*thread_name;
+	unsigned int		src_off, dst_off, len;
+	unsigned int		error_count;
+	unsigned int		failed_tests = 0;
+	unsigned int		total_tests = 0;
+	dma_cookie_t		cookie;
+	enum dma_status		status;
+	int			ret;
+
+	thread_name = current->comm;
+
+	ret = -ENOMEM;
+	thread->srcbuf = kmalloc(test_buf_size, GFP_KERNEL);
+	if (!thread->srcbuf)
+		goto err_srcbuf;
+	thread->dstbuf = kmalloc(test_buf_size, GFP_KERNEL);
+	if (!thread->dstbuf)
+		goto err_dstbuf;
+
+	smp_rmb();
+	chan = thread->chan;
+	dma_chan_get(chan);
+
+	while (!kthread_should_stop()) {
+		total_tests++;
+
+		len = dmatest_random() % test_buf_size + 1;
+		src_off = dmatest_random() % (test_buf_size - len + 1);
+		dst_off = dmatest_random() % (test_buf_size - len + 1);
+
+		dmatest_init_srcbuf(thread->srcbuf, src_off, len);
+		dmatest_init_dstbuf(thread->dstbuf, dst_off, len);
+
+		cookie = dma_async_memcpy_buf_to_buf(chan,
+				thread->dstbuf + dst_off,
+				thread->srcbuf + src_off,
+				len);
+		if (dma_submit_error(cookie)) {
+			pr_warning("%s: #%u: submit error %d with src_off=0x%x "
+					"dst_off=0x%x len=0x%x\n",
+					thread_name, total_tests - 1, cookie,
+					src_off, dst_off, len);
+			msleep(100);
+			failed_tests++;
+			continue;
+		}
+		dma_async_memcpy_issue_pending(chan);
+
+		do {
+			msleep(1);
+			status = dma_async_memcpy_complete(
+					chan, cookie, NULL, NULL);
+		} while (status == DMA_IN_PROGRESS);
+
+		if (status == DMA_ERROR) {
+			pr_warning("%s: #%u: error during copy\n",
+					thread_name, total_tests - 1);
+			failed_tests++;
+			continue;
+		}
+
+		error_count = 0;
+
+		pr_debug("%s: verifying source buffer...\n", thread_name);
+		error_count += dmatest_verify(thread->srcbuf, 0, src_off,
+				0, PATTERN_SRC, true);
+		error_count += dmatest_verify(thread->srcbuf, src_off,
+				src_off + len, src_off,
+				PATTERN_SRC | PATTERN_COPY, true);
+		error_count += dmatest_verify(thread->srcbuf, src_off + len,
+				test_buf_size, src_off + len,
+				PATTERN_SRC, true);
+
+		pr_debug("%s: verifying dest buffer...\n",
+				thread->task->comm);
+		error_count += dmatest_verify(thread->dstbuf, 0, dst_off,
+				0, PATTERN_DST, false);
+		error_count += dmatest_verify(thread->dstbuf, dst_off,
+				dst_off + len, src_off,
+				PATTERN_SRC | PATTERN_COPY, false);
+		error_count += dmatest_verify(thread->dstbuf, dst_off + len,
+				test_buf_size, dst_off + len,
+				PATTERN_DST, false);
+
+		if (error_count) {
+			pr_warning("%s: #%u: %u errors with "
+				"src_off=0x%x dst_off=0x%x len=0x%x\n",
+				thread_name, total_tests - 1, error_count,
+				src_off, dst_off, len);
+			failed_tests++;
+		} else {
+			pr_debug("%s: #%u: No errors with "
+				"src_off=0x%x dst_off=0x%x len=0x%x\n",
+				thread_name, total_tests - 1,
+				src_off, dst_off, len);
+		}
+	}
+
+	ret = 0;
+	dma_chan_put(chan);
+	kfree(thread->dstbuf);
+err_dstbuf:
+	kfree(thread->srcbuf);
+err_srcbuf:
+	pr_notice("%s: terminating after %u tests, %u failures (status %d)\n",
+			thread_name, total_tests, failed_tests, ret);
+	return ret;
+}
+
+static void dmatest_cleanup_channel(struct dmatest_chan *dtc)
+{
+	struct dmatest_thread	*thread;
+	struct dmatest_thread	*_thread;
+	int			ret;
+
+	list_for_each_entry_safe(thread, _thread, &dtc->threads, node) {
+		ret = kthread_stop(thread->task);
+		pr_debug("dmatest: thread %s exited with status %d\n",
+				thread->task->comm, ret);
+		list_del(&thread->node);
+		kfree(thread);
+	}
+	kfree(dtc);
+}
+
+static enum dma_state_client dmatest_add_channel(struct dma_chan *chan)
+{
+	struct dmatest_chan	*dtc;
+	struct dmatest_thread	*thread;
+	unsigned int		i;
+
+	dtc = kmalloc(sizeof(struct dmatest_chan), GFP_ATOMIC);
+	if (!dtc) {
+		pr_warning("dmatest: No memory for %s\n", chan->dev.bus_id);
+		return DMA_NAK;
+	}
+
+	dtc->chan = chan;
+	INIT_LIST_HEAD(&dtc->threads);
+
+	for (i = 0; i < threads_per_chan; i++) {
+		thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL);
+		if (!thread) {
+			pr_warning("dmatest: No memory for %s-test%u\n",
+					chan->dev.bus_id, i);
+			break;
+		}
+		thread->chan = dtc->chan;
+		smp_wmb();
+		thread->task = kthread_run(dmatest_func, thread, "%s-test%u",
+				chan->dev.bus_id, i);
+		if (IS_ERR(thread->task)) {
+			pr_warning("dmatest: Failed to run thread %s-test%u\n",
+					chan->dev.bus_id, i);
+			kfree(thread);
+			break;
+		}
+
+		/* srcbuf and dstbuf are allocated by the thread itself */
+
+		list_add_tail(&thread->node, &dtc->threads);
+	}
+
+	pr_info("dmatest: Started %u threads using %s\n", i, chan->dev.bus_id);
+
+	list_add_tail(&dtc->node, &dmatest_channels);
+	nr_channels++;
+
+	return DMA_ACK;
+}
+
+static enum dma_state_client dmatest_remove_channel(struct dma_chan *chan)
+{
+	struct dmatest_chan	*dtc, *_dtc;
+
+	list_for_each_entry_safe(dtc, _dtc, &dmatest_channels, node) {
+		if (dtc->chan == chan) {
+			list_del(&dtc->node);
+			dmatest_cleanup_channel(dtc);
+			pr_debug("dmatest: lost channel %s\n",
+					chan->dev.bus_id);
+			return DMA_ACK;
+		}
+	}
+
+	return DMA_DUP;
+}
+
+/*
+ * Start testing threads as new channels are assigned to us, and kill
+ * them when the channels go away.
+ *
+ * When we unregister the client, all channels are removed so this
+ * will also take care of cleaning things up when the module is
+ * unloaded.
+ */
+static enum dma_state_client
+dmatest_event(struct dma_client *client, struct dma_chan *chan,
+		enum dma_state state)
+{
+	enum dma_state_client	ack = DMA_NAK;
+
+	switch (state) {
+	case DMA_RESOURCE_AVAILABLE:
+		if (!dmatest_match_channel(chan)
+				|| !dmatest_match_device(chan->device))
+			ack = DMA_DUP;
+		else if (max_channels && nr_channels >= max_channels)
+			ack = DMA_NAK;
+		else
+			ack = dmatest_add_channel(chan);
+		break;
+
+	case DMA_RESOURCE_REMOVED:
+		ack = dmatest_remove_channel(chan);
+		break;
+
+	default:
+		pr_info("dmatest: Unhandled event %u (%s)\n",
+				state, chan->dev.bus_id);
+		break;
+	}
+
+	return ack;
+}
+
+static struct dma_client dmatest_client = {
+	.event_callback	= dmatest_event,
+};
+
+static int __init dmatest_init(void)
+{
+	dma_cap_set(DMA_MEMCPY, dmatest_client.cap_mask);
+	dma_async_client_register(&dmatest_client);
+	dma_async_client_chan_request(&dmatest_client);
+
+	return 0;
+}
+module_init(dmatest_init);
+
+static void __exit dmatest_exit(void)
+{
+	dma_async_client_unregister(&dmatest_client);
+}
+module_exit(dmatest_exit);
+
+MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
new file mode 100644
index 0000000..94df917
--- /dev/null
+++ b/drivers/dma/dw_dmac.c
@@ -0,0 +1,1122 @@
+/*
+ * Driver for the Synopsys DesignWare DMA Controller (aka DMACA on
+ * AVR32 systems.)
+ *
+ * Copyright (C) 2007-2008 Atmel 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/clk.h>
+#include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "dw_dmac_regs.h"
+
+/*
+ * This supports the Synopsys "DesignWare AHB Central DMA Controller",
+ * (DW_ahb_dmac) which is used with various AMBA 2.0 systems (not all
+ * of which use ARM any more).  See the "Databook" from Synopsys for
+ * information beyond what licensees probably provide.
+ *
+ * The driver has currently been tested only with the Atmel AT32AP7000,
+ * which does not support descriptor writeback.
+ */
+
+/* NOTE:  DMS+SMS is system-specific. We should get this information
+ * from the platform code somehow.
+ */
+#define DWC_DEFAULT_CTLLO	(DWC_CTLL_DST_MSIZE(0)		\
+				| DWC_CTLL_SRC_MSIZE(0)		\
+				| DWC_CTLL_DMS(0)		\
+				| DWC_CTLL_SMS(1)		\
+				| DWC_CTLL_LLP_D_EN		\
+				| DWC_CTLL_LLP_S_EN)
+
+/*
+ * This is configuration-dependent and usually a funny size like 4095.
+ * Let's round it down to the nearest power of two.
+ *
+ * Note that this is a transfer count, i.e. if we transfer 32-bit
+ * words, we can do 8192 bytes per descriptor.
+ *
+ * This parameter is also system-specific.
+ */
+#define DWC_MAX_COUNT	2048U
+
+/*
+ * Number of descriptors to allocate for each channel. This should be
+ * made configurable somehow; preferably, the clients (at least the
+ * ones using slave transfers) should be able to give us a hint.
+ */
+#define NR_DESCS_PER_CHANNEL	64
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * Because we're not relying on writeback from the controller (it may not
+ * even be configured into the core!) we don't need to use dma_pool.  These
+ * descriptors -- and associated data -- are cacheable.  We do need to make
+ * sure their dcache entries are written back before handing them off to
+ * the controller, though.
+ */
+
+static struct dw_desc *dwc_first_active(struct dw_dma_chan *dwc)
+{
+	return list_entry(dwc->active_list.next, struct dw_desc, desc_node);
+}
+
+static struct dw_desc *dwc_first_queued(struct dw_dma_chan *dwc)
+{
+	return list_entry(dwc->queue.next, struct dw_desc, desc_node);
+}
+
+static struct dw_desc *dwc_desc_get(struct dw_dma_chan *dwc)
+{
+	struct dw_desc *desc, *_desc;
+	struct dw_desc *ret = NULL;
+	unsigned int i = 0;
+
+	spin_lock_bh(&dwc->lock);
+	list_for_each_entry_safe(desc, _desc, &dwc->free_list, desc_node) {
+		if (async_tx_test_ack(&desc->txd)) {
+			list_del(&desc->desc_node);
+			ret = desc;
+			break;
+		}
+		dev_dbg(&dwc->chan.dev, "desc %p not ACKed\n", desc);
+		i++;
+	}
+	spin_unlock_bh(&dwc->lock);
+
+	dev_vdbg(&dwc->chan.dev, "scanned %u descriptors on freelist\n", i);
+
+	return ret;
+}
+
+static void dwc_sync_desc_for_cpu(struct dw_dma_chan *dwc, struct dw_desc *desc)
+{
+	struct dw_desc	*child;
+
+	list_for_each_entry(child, &desc->txd.tx_list, desc_node)
+		dma_sync_single_for_cpu(dwc->chan.dev.parent,
+				child->txd.phys, sizeof(child->lli),
+				DMA_TO_DEVICE);
+	dma_sync_single_for_cpu(dwc->chan.dev.parent,
+			desc->txd.phys, sizeof(desc->lli),
+			DMA_TO_DEVICE);
+}
+
+/*
+ * Move a descriptor, including any children, to the free list.
+ * `desc' must not be on any lists.
+ */
+static void dwc_desc_put(struct dw_dma_chan *dwc, struct dw_desc *desc)
+{
+	if (desc) {
+		struct dw_desc *child;
+
+		dwc_sync_desc_for_cpu(dwc, desc);
+
+		spin_lock_bh(&dwc->lock);
+		list_for_each_entry(child, &desc->txd.tx_list, desc_node)
+			dev_vdbg(&dwc->chan.dev,
+					"moving child desc %p to freelist\n",
+					child);
+		list_splice_init(&desc->txd.tx_list, &dwc->free_list);
+		dev_vdbg(&dwc->chan.dev, "moving desc %p to freelist\n", desc);
+		list_add(&desc->desc_node, &dwc->free_list);
+		spin_unlock_bh(&dwc->lock);
+	}
+}
+
+/* Called with dwc->lock held and bh disabled */
+static dma_cookie_t
+dwc_assign_cookie(struct dw_dma_chan *dwc, struct dw_desc *desc)
+{
+	dma_cookie_t cookie = dwc->chan.cookie;
+
+	if (++cookie < 0)
+		cookie = 1;
+
+	dwc->chan.cookie = cookie;
+	desc->txd.cookie = cookie;
+
+	return cookie;
+}
+
+/*----------------------------------------------------------------------*/
+
+/* Called with dwc->lock held and bh disabled */
+static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first)
+{
+	struct dw_dma	*dw = to_dw_dma(dwc->chan.device);
+
+	/* ASSERT:  channel is idle */
+	if (dma_readl(dw, CH_EN) & dwc->mask) {
+		dev_err(&dwc->chan.dev,
+			"BUG: Attempted to start non-idle channel\n");
+		dev_err(&dwc->chan.dev,
+			"  SAR: 0x%x DAR: 0x%x LLP: 0x%x CTL: 0x%x:%08x\n",
+			channel_readl(dwc, SAR),
+			channel_readl(dwc, DAR),
+			channel_readl(dwc, LLP),
+			channel_readl(dwc, CTL_HI),
+			channel_readl(dwc, CTL_LO));
+
+		/* The tasklet will hopefully advance the queue... */
+		return;
+	}
+
+	channel_writel(dwc, LLP, first->txd.phys);
+	channel_writel(dwc, CTL_LO,
+			DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN);
+	channel_writel(dwc, CTL_HI, 0);
+	channel_set_bit(dw, CH_EN, dwc->mask);
+}
+
+/*----------------------------------------------------------------------*/
+
+static void
+dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc)
+{
+	dma_async_tx_callback		callback;
+	void				*param;
+	struct dma_async_tx_descriptor	*txd = &desc->txd;
+
+	dev_vdbg(&dwc->chan.dev, "descriptor %u complete\n", txd->cookie);
+
+	dwc->completed = txd->cookie;
+	callback = txd->callback;
+	param = txd->callback_param;
+
+	dwc_sync_desc_for_cpu(dwc, desc);
+	list_splice_init(&txd->tx_list, &dwc->free_list);
+	list_move(&desc->desc_node, &dwc->free_list);
+
+	/*
+	 * We use dma_unmap_page() regardless of how the buffers were
+	 * mapped before they were submitted...
+	 */
+	if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP))
+		dma_unmap_page(dwc->chan.dev.parent, desc->lli.dar, desc->len,
+				DMA_FROM_DEVICE);
+	if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP))
+		dma_unmap_page(dwc->chan.dev.parent, desc->lli.sar, desc->len,
+				DMA_TO_DEVICE);
+
+	/*
+	 * The API requires that no submissions are done from a
+	 * callback, so we don't need to drop the lock here
+	 */
+	if (callback)
+		callback(param);
+}
+
+static void dwc_complete_all(struct dw_dma *dw, struct dw_dma_chan *dwc)
+{
+	struct dw_desc *desc, *_desc;
+	LIST_HEAD(list);
+
+	if (dma_readl(dw, CH_EN) & dwc->mask) {
+		dev_err(&dwc->chan.dev,
+			"BUG: XFER bit set, but channel not idle!\n");
+
+		/* Try to continue after resetting the channel... */
+		channel_clear_bit(dw, CH_EN, dwc->mask);
+		while (dma_readl(dw, CH_EN) & dwc->mask)
+			cpu_relax();
+	}
+
+	/*
+	 * Submit queued descriptors ASAP, i.e. before we go through
+	 * the completed ones.
+	 */
+	if (!list_empty(&dwc->queue))
+		dwc_dostart(dwc, dwc_first_queued(dwc));
+	list_splice_init(&dwc->active_list, &list);
+	list_splice_init(&dwc->queue, &dwc->active_list);
+
+	list_for_each_entry_safe(desc, _desc, &list, desc_node)
+		dwc_descriptor_complete(dwc, desc);
+}
+
+static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
+{
+	dma_addr_t llp;
+	struct dw_desc *desc, *_desc;
+	struct dw_desc *child;
+	u32 status_xfer;
+
+	/*
+	 * Clear block interrupt flag before scanning so that we don't
+	 * miss any, and read LLP before RAW_XFER to ensure it is
+	 * valid if we decide to scan the list.
+	 */
+	dma_writel(dw, CLEAR.BLOCK, dwc->mask);
+	llp = channel_readl(dwc, LLP);
+	status_xfer = dma_readl(dw, RAW.XFER);
+
+	if (status_xfer & dwc->mask) {
+		/* Everything we've submitted is done */
+		dma_writel(dw, CLEAR.XFER, dwc->mask);
+		dwc_complete_all(dw, dwc);
+		return;
+	}
+
+	dev_vdbg(&dwc->chan.dev, "scan_descriptors: llp=0x%x\n", llp);
+
+	list_for_each_entry_safe(desc, _desc, &dwc->active_list, desc_node) {
+		if (desc->lli.llp == llp)
+			/* This one is currently in progress */
+			return;
+
+		list_for_each_entry(child, &desc->txd.tx_list, desc_node)
+			if (child->lli.llp == llp)
+				/* Currently in progress */
+				return;
+
+		/*
+		 * No descriptors so far seem to be in progress, i.e.
+		 * this one must be done.
+		 */
+		dwc_descriptor_complete(dwc, desc);
+	}
+
+	dev_err(&dwc->chan.dev,
+		"BUG: All descriptors done, but channel not idle!\n");
+
+	/* Try to continue after resetting the channel... */
+	channel_clear_bit(dw, CH_EN, dwc->mask);
+	while (dma_readl(dw, CH_EN) & dwc->mask)
+		cpu_relax();
+
+	if (!list_empty(&dwc->queue)) {
+		dwc_dostart(dwc, dwc_first_queued(dwc));
+		list_splice_init(&dwc->queue, &dwc->active_list);
+	}
+}
+
+static void dwc_dump_lli(struct dw_dma_chan *dwc, struct dw_lli *lli)
+{
+	dev_printk(KERN_CRIT, &dwc->chan.dev,
+			"  desc: s0x%x d0x%x l0x%x c0x%x:%x\n",
+			lli->sar, lli->dar, lli->llp,
+			lli->ctlhi, lli->ctllo);
+}
+
+static void dwc_handle_error(struct dw_dma *dw, struct dw_dma_chan *dwc)
+{
+	struct dw_desc *bad_desc;
+	struct dw_desc *child;
+
+	dwc_scan_descriptors(dw, dwc);
+
+	/*
+	 * The descriptor currently at the head of the active list is
+	 * borked. Since we don't have any way to report errors, we'll
+	 * just have to scream loudly and try to carry on.
+	 */
+	bad_desc = dwc_first_active(dwc);
+	list_del_init(&bad_desc->desc_node);
+	list_splice_init(&dwc->queue, dwc->active_list.prev);
+
+	/* Clear the error flag and try to restart the controller */
+	dma_writel(dw, CLEAR.ERROR, dwc->mask);
+	if (!list_empty(&dwc->active_list))
+		dwc_dostart(dwc, dwc_first_active(dwc));
+
+	/*
+	 * KERN_CRITICAL may seem harsh, but since this only happens
+	 * when someone submits a bad physical address in a
+	 * descriptor, we should consider ourselves lucky that the
+	 * controller flagged an error instead of scribbling over
+	 * random memory locations.
+	 */
+	dev_printk(KERN_CRIT, &dwc->chan.dev,
+			"Bad descriptor submitted for DMA!\n");
+	dev_printk(KERN_CRIT, &dwc->chan.dev,
+			"  cookie: %d\n", bad_desc->txd.cookie);
+	dwc_dump_lli(dwc, &bad_desc->lli);
+	list_for_each_entry(child, &bad_desc->txd.tx_list, desc_node)
+		dwc_dump_lli(dwc, &child->lli);
+
+	/* Pretend the descriptor completed successfully */
+	dwc_descriptor_complete(dwc, bad_desc);
+}
+
+static void dw_dma_tasklet(unsigned long data)
+{
+	struct dw_dma *dw = (struct dw_dma *)data;
+	struct dw_dma_chan *dwc;
+	u32 status_block;
+	u32 status_xfer;
+	u32 status_err;
+	int i;
+
+	status_block = dma_readl(dw, RAW.BLOCK);
+	status_xfer = dma_readl(dw, RAW.BLOCK);
+	status_err = dma_readl(dw, RAW.ERROR);
+
+	dev_vdbg(dw->dma.dev, "tasklet: status_block=%x status_err=%x\n",
+			status_block, status_err);
+
+	for (i = 0; i < dw->dma.chancnt; i++) {
+		dwc = &dw->chan[i];
+		spin_lock(&dwc->lock);
+		if (status_err & (1 << i))
+			dwc_handle_error(dw, dwc);
+		else if ((status_block | status_xfer) & (1 << i))
+			dwc_scan_descriptors(dw, dwc);
+		spin_unlock(&dwc->lock);
+	}
+
+	/*
+	 * Re-enable interrupts. Block Complete interrupts are only
+	 * enabled if the INT_EN bit in the descriptor is set. This
+	 * will trigger a scan before the whole list is done.
+	 */
+	channel_set_bit(dw, MASK.XFER, dw->all_chan_mask);
+	channel_set_bit(dw, MASK.BLOCK, dw->all_chan_mask);
+	channel_set_bit(dw, MASK.ERROR, dw->all_chan_mask);
+}
+
+static irqreturn_t dw_dma_interrupt(int irq, void *dev_id)
+{
+	struct dw_dma *dw = dev_id;
+	u32 status;
+
+	dev_vdbg(dw->dma.dev, "interrupt: status=0x%x\n",
+			dma_readl(dw, STATUS_INT));
+
+	/*
+	 * Just disable the interrupts. We'll turn them back on in the
+	 * softirq handler.
+	 */
+	channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask);
+	channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask);
+	channel_clear_bit(dw, MASK.ERROR, dw->all_chan_mask);
+
+	status = dma_readl(dw, STATUS_INT);
+	if (status) {
+		dev_err(dw->dma.dev,
+			"BUG: Unexpected interrupts pending: 0x%x\n",
+			status);
+
+		/* Try to recover */
+		channel_clear_bit(dw, MASK.XFER, (1 << 8) - 1);
+		channel_clear_bit(dw, MASK.BLOCK, (1 << 8) - 1);
+		channel_clear_bit(dw, MASK.SRC_TRAN, (1 << 8) - 1);
+		channel_clear_bit(dw, MASK.DST_TRAN, (1 << 8) - 1);
+		channel_clear_bit(dw, MASK.ERROR, (1 << 8) - 1);
+	}
+
+	tasklet_schedule(&dw->tasklet);
+
+	return IRQ_HANDLED;
+}
+
+/*----------------------------------------------------------------------*/
+
+static dma_cookie_t dwc_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct dw_desc		*desc = txd_to_dw_desc(tx);
+	struct dw_dma_chan	*dwc = to_dw_dma_chan(tx->chan);
+	dma_cookie_t		cookie;
+
+	spin_lock_bh(&dwc->lock);
+	cookie = dwc_assign_cookie(dwc, desc);
+
+	/*
+	 * REVISIT: We should attempt to chain as many descriptors as
+	 * possible, perhaps even appending to those already submitted
+	 * for DMA. But this is hard to do in a race-free manner.
+	 */
+	if (list_empty(&dwc->active_list)) {
+		dev_vdbg(&tx->chan->dev, "tx_submit: started %u\n",
+				desc->txd.cookie);
+		dwc_dostart(dwc, desc);
+		list_add_tail(&desc->desc_node, &dwc->active_list);
+	} else {
+		dev_vdbg(&tx->chan->dev, "tx_submit: queued %u\n",
+				desc->txd.cookie);
+
+		list_add_tail(&desc->desc_node, &dwc->queue);
+	}
+
+	spin_unlock_bh(&dwc->lock);
+
+	return cookie;
+}
+
+static struct dma_async_tx_descriptor *
+dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+		size_t len, unsigned long flags)
+{
+	struct dw_dma_chan	*dwc = to_dw_dma_chan(chan);
+	struct dw_desc		*desc;
+	struct dw_desc		*first;
+	struct dw_desc		*prev;
+	size_t			xfer_count;
+	size_t			offset;
+	unsigned int		src_width;
+	unsigned int		dst_width;
+	u32			ctllo;
+
+	dev_vdbg(&chan->dev, "prep_dma_memcpy d0x%x s0x%x l0x%zx f0x%lx\n",
+			dest, src, len, flags);
+
+	if (unlikely(!len)) {
+		dev_dbg(&chan->dev, "prep_dma_memcpy: length is zero!\n");
+		return NULL;
+	}
+
+	/*
+	 * We can be a lot more clever here, but this should take care
+	 * of the most common optimization.
+	 */
+	if (!((src | dest  | len) & 3))
+		src_width = dst_width = 2;
+	else if (!((src | dest | len) & 1))
+		src_width = dst_width = 1;
+	else
+		src_width = dst_width = 0;
+
+	ctllo = DWC_DEFAULT_CTLLO
+			| DWC_CTLL_DST_WIDTH(dst_width)
+			| DWC_CTLL_SRC_WIDTH(src_width)
+			| DWC_CTLL_DST_INC
+			| DWC_CTLL_SRC_INC
+			| DWC_CTLL_FC_M2M;
+	prev = first = NULL;
+
+	for (offset = 0; offset < len; offset += xfer_count << src_width) {
+		xfer_count = min_t(size_t, (len - offset) >> src_width,
+				DWC_MAX_COUNT);
+
+		desc = dwc_desc_get(dwc);
+		if (!desc)
+			goto err_desc_get;
+
+		desc->lli.sar = src + offset;
+		desc->lli.dar = dest + offset;
+		desc->lli.ctllo = ctllo;
+		desc->lli.ctlhi = xfer_count;
+
+		if (!first) {
+			first = desc;
+		} else {
+			prev->lli.llp = desc->txd.phys;
+			dma_sync_single_for_device(chan->dev.parent,
+					prev->txd.phys, sizeof(prev->lli),
+					DMA_TO_DEVICE);
+			list_add_tail(&desc->desc_node,
+					&first->txd.tx_list);
+		}
+		prev = desc;
+	}
+
+
+	if (flags & DMA_PREP_INTERRUPT)
+		/* Trigger interrupt after last block */
+		prev->lli.ctllo |= DWC_CTLL_INT_EN;
+
+	prev->lli.llp = 0;
+	dma_sync_single_for_device(chan->dev.parent,
+			prev->txd.phys, sizeof(prev->lli),
+			DMA_TO_DEVICE);
+
+	first->txd.flags = flags;
+	first->len = len;
+
+	return &first->txd;
+
+err_desc_get:
+	dwc_desc_put(dwc, first);
+	return NULL;
+}
+
+static struct dma_async_tx_descriptor *
+dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+		unsigned int sg_len, enum dma_data_direction direction,
+		unsigned long flags)
+{
+	struct dw_dma_chan	*dwc = to_dw_dma_chan(chan);
+	struct dw_dma_slave	*dws = dwc->dws;
+	struct dw_desc		*prev;
+	struct dw_desc		*first;
+	u32			ctllo;
+	dma_addr_t		reg;
+	unsigned int		reg_width;
+	unsigned int		mem_width;
+	unsigned int		i;
+	struct scatterlist	*sg;
+	size_t			total_len = 0;
+
+	dev_vdbg(&chan->dev, "prep_dma_slave\n");
+
+	if (unlikely(!dws || !sg_len))
+		return NULL;
+
+	reg_width = dws->slave.reg_width;
+	prev = first = NULL;
+
+	sg_len = dma_map_sg(chan->dev.parent, sgl, sg_len, direction);
+
+	switch (direction) {
+	case DMA_TO_DEVICE:
+		ctllo = (DWC_DEFAULT_CTLLO
+				| DWC_CTLL_DST_WIDTH(reg_width)
+				| DWC_CTLL_DST_FIX
+				| DWC_CTLL_SRC_INC
+				| DWC_CTLL_FC_M2P);
+		reg = dws->slave.tx_reg;
+		for_each_sg(sgl, sg, sg_len, i) {
+			struct dw_desc	*desc;
+			u32		len;
+			u32		mem;
+
+			desc = dwc_desc_get(dwc);
+			if (!desc) {
+				dev_err(&chan->dev,
+					"not enough descriptors available\n");
+				goto err_desc_get;
+			}
+
+			mem = sg_phys(sg);
+			len = sg_dma_len(sg);
+			mem_width = 2;
+			if (unlikely(mem & 3 || len & 3))
+				mem_width = 0;
+
+			desc->lli.sar = mem;
+			desc->lli.dar = reg;
+			desc->lli.ctllo = ctllo | DWC_CTLL_SRC_WIDTH(mem_width);
+			desc->lli.ctlhi = len >> mem_width;
+
+			if (!first) {
+				first = desc;
+			} else {
+				prev->lli.llp = desc->txd.phys;
+				dma_sync_single_for_device(chan->dev.parent,
+						prev->txd.phys,
+						sizeof(prev->lli),
+						DMA_TO_DEVICE);
+				list_add_tail(&desc->desc_node,
+						&first->txd.tx_list);
+			}
+			prev = desc;
+			total_len += len;
+		}
+		break;
+	case DMA_FROM_DEVICE:
+		ctllo = (DWC_DEFAULT_CTLLO
+				| DWC_CTLL_SRC_WIDTH(reg_width)
+				| DWC_CTLL_DST_INC
+				| DWC_CTLL_SRC_FIX
+				| DWC_CTLL_FC_P2M);
+
+		reg = dws->slave.rx_reg;
+		for_each_sg(sgl, sg, sg_len, i) {
+			struct dw_desc	*desc;
+			u32		len;
+			u32		mem;
+
+			desc = dwc_desc_get(dwc);
+			if (!desc) {
+				dev_err(&chan->dev,
+					"not enough descriptors available\n");
+				goto err_desc_get;
+			}
+
+			mem = sg_phys(sg);
+			len = sg_dma_len(sg);
+			mem_width = 2;
+			if (unlikely(mem & 3 || len & 3))
+				mem_width = 0;
+
+			desc->lli.sar = reg;
+			desc->lli.dar = mem;
+			desc->lli.ctllo = ctllo | DWC_CTLL_DST_WIDTH(mem_width);
+			desc->lli.ctlhi = len >> reg_width;
+
+			if (!first) {
+				first = desc;
+			} else {
+				prev->lli.llp = desc->txd.phys;
+				dma_sync_single_for_device(chan->dev.parent,
+						prev->txd.phys,
+						sizeof(prev->lli),
+						DMA_TO_DEVICE);
+				list_add_tail(&desc->desc_node,
+						&first->txd.tx_list);
+			}
+			prev = desc;
+			total_len += len;
+		}
+		break;
+	default:
+		return NULL;
+	}
+
+	if (flags & DMA_PREP_INTERRUPT)
+		/* Trigger interrupt after last block */
+		prev->lli.ctllo |= DWC_CTLL_INT_EN;
+
+	prev->lli.llp = 0;
+	dma_sync_single_for_device(chan->dev.parent,
+			prev->txd.phys, sizeof(prev->lli),
+			DMA_TO_DEVICE);
+
+	first->len = total_len;
+
+	return &first->txd;
+
+err_desc_get:
+	dwc_desc_put(dwc, first);
+	return NULL;
+}
+
+static void dwc_terminate_all(struct dma_chan *chan)
+{
+	struct dw_dma_chan	*dwc = to_dw_dma_chan(chan);
+	struct dw_dma		*dw = to_dw_dma(chan->device);
+	struct dw_desc		*desc, *_desc;
+	LIST_HEAD(list);
+
+	/*
+	 * This is only called when something went wrong elsewhere, so
+	 * we don't really care about the data. Just disable the
+	 * channel. We still have to poll the channel enable bit due
+	 * to AHB/HSB limitations.
+	 */
+	spin_lock_bh(&dwc->lock);
+
+	channel_clear_bit(dw, CH_EN, dwc->mask);
+
+	while (dma_readl(dw, CH_EN) & dwc->mask)
+		cpu_relax();
+
+	/* active_list entries will end up before queued entries */
+	list_splice_init(&dwc->queue, &list);
+	list_splice_init(&dwc->active_list, &list);
+
+	spin_unlock_bh(&dwc->lock);
+
+	/* Flush all pending and queued descriptors */
+	list_for_each_entry_safe(desc, _desc, &list, desc_node)
+		dwc_descriptor_complete(dwc, desc);
+}
+
+static enum dma_status
+dwc_is_tx_complete(struct dma_chan *chan,
+		dma_cookie_t cookie,
+		dma_cookie_t *done, dma_cookie_t *used)
+{
+	struct dw_dma_chan	*dwc = to_dw_dma_chan(chan);
+	dma_cookie_t		last_used;
+	dma_cookie_t		last_complete;
+	int			ret;
+
+	last_complete = dwc->completed;
+	last_used = chan->cookie;
+
+	ret = dma_async_is_complete(cookie, last_complete, last_used);
+	if (ret != DMA_SUCCESS) {
+		dwc_scan_descriptors(to_dw_dma(chan->device), dwc);
+
+		last_complete = dwc->completed;
+		last_used = chan->cookie;
+
+		ret = dma_async_is_complete(cookie, last_complete, last_used);
+	}
+
+	if (done)
+		*done = last_complete;
+	if (used)
+		*used = last_used;
+
+	return ret;
+}
+
+static void dwc_issue_pending(struct dma_chan *chan)
+{
+	struct dw_dma_chan	*dwc = to_dw_dma_chan(chan);
+
+	spin_lock_bh(&dwc->lock);
+	if (!list_empty(&dwc->queue))
+		dwc_scan_descriptors(to_dw_dma(chan->device), dwc);
+	spin_unlock_bh(&dwc->lock);
+}
+
+static int dwc_alloc_chan_resources(struct dma_chan *chan,
+		struct dma_client *client)
+{
+	struct dw_dma_chan	*dwc = to_dw_dma_chan(chan);
+	struct dw_dma		*dw = to_dw_dma(chan->device);
+	struct dw_desc		*desc;
+	struct dma_slave	*slave;
+	struct dw_dma_slave	*dws;
+	int			i;
+	u32			cfghi;
+	u32			cfglo;
+
+	dev_vdbg(&chan->dev, "alloc_chan_resources\n");
+
+	/* Channels doing slave DMA can only handle one client. */
+	if (dwc->dws || client->slave) {
+		if (chan->client_count)
+			return -EBUSY;
+	}
+
+	/* ASSERT:  channel is idle */
+	if (dma_readl(dw, CH_EN) & dwc->mask) {
+		dev_dbg(&chan->dev, "DMA channel not idle?\n");
+		return -EIO;
+	}
+
+	dwc->completed = chan->cookie = 1;
+
+	cfghi = DWC_CFGH_FIFO_MODE;
+	cfglo = 0;
+
+	slave = client->slave;
+	if (slave) {
+		/*
+		 * We need controller-specific data to set up slave
+		 * transfers.
+		 */
+		BUG_ON(!slave->dma_dev || slave->dma_dev != dw->dma.dev);
+
+		dws = container_of(slave, struct dw_dma_slave, slave);
+
+		dwc->dws = dws;
+		cfghi = dws->cfg_hi;
+		cfglo = dws->cfg_lo;
+	} else {
+		dwc->dws = NULL;
+	}
+
+	channel_writel(dwc, CFG_LO, cfglo);
+	channel_writel(dwc, CFG_HI, cfghi);
+
+	/*
+	 * NOTE: some controllers may have additional features that we
+	 * need to initialize here, like "scatter-gather" (which
+	 * doesn't mean what you think it means), and status writeback.
+	 */
+
+	spin_lock_bh(&dwc->lock);
+	i = dwc->descs_allocated;
+	while (dwc->descs_allocated < NR_DESCS_PER_CHANNEL) {
+		spin_unlock_bh(&dwc->lock);
+
+		desc = kzalloc(sizeof(struct dw_desc), GFP_KERNEL);
+		if (!desc) {
+			dev_info(&chan->dev,
+				"only allocated %d descriptors\n", i);
+			spin_lock_bh(&dwc->lock);
+			break;
+		}
+
+		dma_async_tx_descriptor_init(&desc->txd, chan);
+		desc->txd.tx_submit = dwc_tx_submit;
+		desc->txd.flags = DMA_CTRL_ACK;
+		INIT_LIST_HEAD(&desc->txd.tx_list);
+		desc->txd.phys = dma_map_single(chan->dev.parent, &desc->lli,
+				sizeof(desc->lli), DMA_TO_DEVICE);
+		dwc_desc_put(dwc, desc);
+
+		spin_lock_bh(&dwc->lock);
+		i = ++dwc->descs_allocated;
+	}
+
+	/* Enable interrupts */
+	channel_set_bit(dw, MASK.XFER, dwc->mask);
+	channel_set_bit(dw, MASK.BLOCK, dwc->mask);
+	channel_set_bit(dw, MASK.ERROR, dwc->mask);
+
+	spin_unlock_bh(&dwc->lock);
+
+	dev_dbg(&chan->dev,
+		"alloc_chan_resources allocated %d descriptors\n", i);
+
+	return i;
+}
+
+static void dwc_free_chan_resources(struct dma_chan *chan)
+{
+	struct dw_dma_chan	*dwc = to_dw_dma_chan(chan);
+	struct dw_dma		*dw = to_dw_dma(chan->device);
+	struct dw_desc		*desc, *_desc;
+	LIST_HEAD(list);
+
+	dev_dbg(&chan->dev, "free_chan_resources (descs allocated=%u)\n",
+			dwc->descs_allocated);
+
+	/* ASSERT:  channel is idle */
+	BUG_ON(!list_empty(&dwc->active_list));
+	BUG_ON(!list_empty(&dwc->queue));
+	BUG_ON(dma_readl(to_dw_dma(chan->device), CH_EN) & dwc->mask);
+
+	spin_lock_bh(&dwc->lock);
+	list_splice_init(&dwc->free_list, &list);
+	dwc->descs_allocated = 0;
+	dwc->dws = NULL;
+
+	/* Disable interrupts */
+	channel_clear_bit(dw, MASK.XFER, dwc->mask);
+	channel_clear_bit(dw, MASK.BLOCK, dwc->mask);
+	channel_clear_bit(dw, MASK.ERROR, dwc->mask);
+
+	spin_unlock_bh(&dwc->lock);
+
+	list_for_each_entry_safe(desc, _desc, &list, desc_node) {
+		dev_vdbg(&chan->dev, "  freeing descriptor %p\n", desc);
+		dma_unmap_single(chan->dev.parent, desc->txd.phys,
+				sizeof(desc->lli), DMA_TO_DEVICE);
+		kfree(desc);
+	}
+
+	dev_vdbg(&chan->dev, "free_chan_resources done\n");
+}
+
+/*----------------------------------------------------------------------*/
+
+static void dw_dma_off(struct dw_dma *dw)
+{
+	dma_writel(dw, CFG, 0);
+
+	channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask);
+	channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask);
+	channel_clear_bit(dw, MASK.SRC_TRAN, dw->all_chan_mask);
+	channel_clear_bit(dw, MASK.DST_TRAN, dw->all_chan_mask);
+	channel_clear_bit(dw, MASK.ERROR, dw->all_chan_mask);
+
+	while (dma_readl(dw, CFG) & DW_CFG_DMA_EN)
+		cpu_relax();
+}
+
+static int __init dw_probe(struct platform_device *pdev)
+{
+	struct dw_dma_platform_data *pdata;
+	struct resource		*io;
+	struct dw_dma		*dw;
+	size_t			size;
+	int			irq;
+	int			err;
+	int			i;
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata || pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS)
+		return -EINVAL;
+
+	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!io)
+		return -EINVAL;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	size = sizeof(struct dw_dma);
+	size += pdata->nr_channels * sizeof(struct dw_dma_chan);
+	dw = kzalloc(size, GFP_KERNEL);
+	if (!dw)
+		return -ENOMEM;
+
+	if (!request_mem_region(io->start, DW_REGLEN, pdev->dev.driver->name)) {
+		err = -EBUSY;
+		goto err_kfree;
+	}
+
+	memset(dw, 0, sizeof *dw);
+
+	dw->regs = ioremap(io->start, DW_REGLEN);
+	if (!dw->regs) {
+		err = -ENOMEM;
+		goto err_release_r;
+	}
+
+	dw->clk = clk_get(&pdev->dev, "hclk");
+	if (IS_ERR(dw->clk)) {
+		err = PTR_ERR(dw->clk);
+		goto err_clk;
+	}
+	clk_enable(dw->clk);
+
+	/* force dma off, just in case */
+	dw_dma_off(dw);
+
+	err = request_irq(irq, dw_dma_interrupt, 0, "dw_dmac", dw);
+	if (err)
+		goto err_irq;
+
+	platform_set_drvdata(pdev, dw);
+
+	tasklet_init(&dw->tasklet, dw_dma_tasklet, (unsigned long)dw);
+
+	dw->all_chan_mask = (1 << pdata->nr_channels) - 1;
+
+	INIT_LIST_HEAD(&dw->dma.channels);
+	for (i = 0; i < pdata->nr_channels; i++, dw->dma.chancnt++) {
+		struct dw_dma_chan	*dwc = &dw->chan[i];
+
+		dwc->chan.device = &dw->dma;
+		dwc->chan.cookie = dwc->completed = 1;
+		dwc->chan.chan_id = i;
+		list_add_tail(&dwc->chan.device_node, &dw->dma.channels);
+
+		dwc->ch_regs = &__dw_regs(dw)->CHAN[i];
+		spin_lock_init(&dwc->lock);
+		dwc->mask = 1 << i;
+
+		INIT_LIST_HEAD(&dwc->active_list);
+		INIT_LIST_HEAD(&dwc->queue);
+		INIT_LIST_HEAD(&dwc->free_list);
+
+		channel_clear_bit(dw, CH_EN, dwc->mask);
+	}
+
+	/* Clear/disable all interrupts on all channels. */
+	dma_writel(dw, CLEAR.XFER, dw->all_chan_mask);
+	dma_writel(dw, CLEAR.BLOCK, dw->all_chan_mask);
+	dma_writel(dw, CLEAR.SRC_TRAN, dw->all_chan_mask);
+	dma_writel(dw, CLEAR.DST_TRAN, dw->all_chan_mask);
+	dma_writel(dw, CLEAR.ERROR, dw->all_chan_mask);
+
+	channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask);
+	channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask);
+	channel_clear_bit(dw, MASK.SRC_TRAN, dw->all_chan_mask);
+	channel_clear_bit(dw, MASK.DST_TRAN, dw->all_chan_mask);
+	channel_clear_bit(dw, MASK.ERROR, dw->all_chan_mask);
+
+	dma_cap_set(DMA_MEMCPY, dw->dma.cap_mask);
+	dma_cap_set(DMA_SLAVE, dw->dma.cap_mask);
+	dw->dma.dev = &pdev->dev;
+	dw->dma.device_alloc_chan_resources = dwc_alloc_chan_resources;
+	dw->dma.device_free_chan_resources = dwc_free_chan_resources;
+
+	dw->dma.device_prep_dma_memcpy = dwc_prep_dma_memcpy;
+
+	dw->dma.device_prep_slave_sg = dwc_prep_slave_sg;
+	dw->dma.device_terminate_all = dwc_terminate_all;
+
+	dw->dma.device_is_tx_complete = dwc_is_tx_complete;
+	dw->dma.device_issue_pending = dwc_issue_pending;
+
+	dma_writel(dw, CFG, DW_CFG_DMA_EN);
+
+	printk(KERN_INFO "%s: DesignWare DMA Controller, %d channels\n",
+			pdev->dev.bus_id, dw->dma.chancnt);
+
+	dma_async_device_register(&dw->dma);
+
+	return 0;
+
+err_irq:
+	clk_disable(dw->clk);
+	clk_put(dw->clk);
+err_clk:
+	iounmap(dw->regs);
+	dw->regs = NULL;
+err_release_r:
+	release_resource(io);
+err_kfree:
+	kfree(dw);
+	return err;
+}
+
+static int __exit dw_remove(struct platform_device *pdev)
+{
+	struct dw_dma		*dw = platform_get_drvdata(pdev);
+	struct dw_dma_chan	*dwc, *_dwc;
+	struct resource		*io;
+
+	dw_dma_off(dw);
+	dma_async_device_unregister(&dw->dma);
+
+	free_irq(platform_get_irq(pdev, 0), dw);
+	tasklet_kill(&dw->tasklet);
+
+	list_for_each_entry_safe(dwc, _dwc, &dw->dma.channels,
+			chan.device_node) {
+		list_del(&dwc->chan.device_node);
+		channel_clear_bit(dw, CH_EN, dwc->mask);
+	}
+
+	clk_disable(dw->clk);
+	clk_put(dw->clk);
+
+	iounmap(dw->regs);
+	dw->regs = NULL;
+
+	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(io->start, DW_REGLEN);
+
+	kfree(dw);
+
+	return 0;
+}
+
+static void dw_shutdown(struct platform_device *pdev)
+{
+	struct dw_dma	*dw = platform_get_drvdata(pdev);
+
+	dw_dma_off(platform_get_drvdata(pdev));
+	clk_disable(dw->clk);
+}
+
+static int dw_suspend_late(struct platform_device *pdev, pm_message_t mesg)
+{
+	struct dw_dma	*dw = platform_get_drvdata(pdev);
+
+	dw_dma_off(platform_get_drvdata(pdev));
+	clk_disable(dw->clk);
+	return 0;
+}
+
+static int dw_resume_early(struct platform_device *pdev)
+{
+	struct dw_dma	*dw = platform_get_drvdata(pdev);
+
+	clk_enable(dw->clk);
+	dma_writel(dw, CFG, DW_CFG_DMA_EN);
+	return 0;
+
+}
+
+static struct platform_driver dw_driver = {
+	.remove		= __exit_p(dw_remove),
+	.shutdown	= dw_shutdown,
+	.suspend_late	= dw_suspend_late,
+	.resume_early	= dw_resume_early,
+	.driver = {
+		.name	= "dw_dmac",
+	},
+};
+
+static int __init dw_init(void)
+{
+	return platform_driver_probe(&dw_driver, dw_probe);
+}
+module_init(dw_init);
+
+static void __exit dw_exit(void)
+{
+	platform_driver_unregister(&dw_driver);
+}
+module_exit(dw_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Synopsys DesignWare DMA Controller driver");
+MODULE_AUTHOR("Haavard Skinnemoen <haavard.skinnemoen@atmel.com>");
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
new file mode 100644
index 0000000..00fdd18
--- /dev/null
+++ b/drivers/dma/dw_dmac_regs.h
@@ -0,0 +1,225 @@
+/*
+ * Driver for the Synopsys DesignWare AHB DMA Controller
+ *
+ * Copyright (C) 2005-2007 Atmel 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/dw_dmac.h>
+
+#define DW_DMA_MAX_NR_CHANNELS	8
+
+/*
+ * Redefine this macro to handle differences between 32- and 64-bit
+ * addressing, big vs. little endian, etc.
+ */
+#define DW_REG(name)		u32 name; u32 __pad_##name
+
+/* Hardware register definitions. */
+struct dw_dma_chan_regs {
+	DW_REG(SAR);		/* Source Address Register */
+	DW_REG(DAR);		/* Destination Address Register */
+	DW_REG(LLP);		/* Linked List Pointer */
+	u32	CTL_LO;		/* Control Register Low */
+	u32	CTL_HI;		/* Control Register High */
+	DW_REG(SSTAT);
+	DW_REG(DSTAT);
+	DW_REG(SSTATAR);
+	DW_REG(DSTATAR);
+	u32	CFG_LO;		/* Configuration Register Low */
+	u32	CFG_HI;		/* Configuration Register High */
+	DW_REG(SGR);
+	DW_REG(DSR);
+};
+
+struct dw_dma_irq_regs {
+	DW_REG(XFER);
+	DW_REG(BLOCK);
+	DW_REG(SRC_TRAN);
+	DW_REG(DST_TRAN);
+	DW_REG(ERROR);
+};
+
+struct dw_dma_regs {
+	/* per-channel registers */
+	struct dw_dma_chan_regs	CHAN[DW_DMA_MAX_NR_CHANNELS];
+
+	/* irq handling */
+	struct dw_dma_irq_regs	RAW;		/* r */
+	struct dw_dma_irq_regs	STATUS;		/* r (raw & mask) */
+	struct dw_dma_irq_regs	MASK;		/* rw (set = irq enabled) */
+	struct dw_dma_irq_regs	CLEAR;		/* w (ack, affects "raw") */
+
+	DW_REG(STATUS_INT);			/* r */
+
+	/* software handshaking */
+	DW_REG(REQ_SRC);
+	DW_REG(REQ_DST);
+	DW_REG(SGL_REQ_SRC);
+	DW_REG(SGL_REQ_DST);
+	DW_REG(LAST_SRC);
+	DW_REG(LAST_DST);
+
+	/* miscellaneous */
+	DW_REG(CFG);
+	DW_REG(CH_EN);
+	DW_REG(ID);
+	DW_REG(TEST);
+
+	/* optional encoded params, 0x3c8..0x3 */
+};
+
+/* Bitfields in CTL_LO */
+#define DWC_CTLL_INT_EN		(1 << 0)	/* irqs enabled? */
+#define DWC_CTLL_DST_WIDTH(n)	((n)<<1)	/* bytes per element */
+#define DWC_CTLL_SRC_WIDTH(n)	((n)<<4)
+#define DWC_CTLL_DST_INC	(0<<7)		/* DAR update/not */
+#define DWC_CTLL_DST_DEC	(1<<7)
+#define DWC_CTLL_DST_FIX	(2<<7)
+#define DWC_CTLL_SRC_INC	(0<<7)		/* SAR update/not */
+#define DWC_CTLL_SRC_DEC	(1<<9)
+#define DWC_CTLL_SRC_FIX	(2<<9)
+#define DWC_CTLL_DST_MSIZE(n)	((n)<<11)	/* burst, #elements */
+#define DWC_CTLL_SRC_MSIZE(n)	((n)<<14)
+#define DWC_CTLL_S_GATH_EN	(1 << 17)	/* src gather, !FIX */
+#define DWC_CTLL_D_SCAT_EN	(1 << 18)	/* dst scatter, !FIX */
+#define DWC_CTLL_FC_M2M		(0 << 20)	/* mem-to-mem */
+#define DWC_CTLL_FC_M2P		(1 << 20)	/* mem-to-periph */
+#define DWC_CTLL_FC_P2M		(2 << 20)	/* periph-to-mem */
+#define DWC_CTLL_FC_P2P		(3 << 20)	/* periph-to-periph */
+/* plus 4 transfer types for peripheral-as-flow-controller */
+#define DWC_CTLL_DMS(n)		((n)<<23)	/* dst master select */
+#define DWC_CTLL_SMS(n)		((n)<<25)	/* src master select */
+#define DWC_CTLL_LLP_D_EN	(1 << 27)	/* dest block chain */
+#define DWC_CTLL_LLP_S_EN	(1 << 28)	/* src block chain */
+
+/* Bitfields in CTL_HI */
+#define DWC_CTLH_DONE		0x00001000
+#define DWC_CTLH_BLOCK_TS_MASK	0x00000fff
+
+/* Bitfields in CFG_LO. Platform-configurable bits are in <linux/dw_dmac.h> */
+#define DWC_CFGL_CH_SUSP	(1 << 8)	/* pause xfer */
+#define DWC_CFGL_FIFO_EMPTY	(1 << 9)	/* pause xfer */
+#define DWC_CFGL_HS_DST		(1 << 10)	/* handshake w/dst */
+#define DWC_CFGL_HS_SRC		(1 << 11)	/* handshake w/src */
+#define DWC_CFGL_MAX_BURST(x)	((x) << 20)
+#define DWC_CFGL_RELOAD_SAR	(1 << 30)
+#define DWC_CFGL_RELOAD_DAR	(1 << 31)
+
+/* Bitfields in CFG_HI. Platform-configurable bits are in <linux/dw_dmac.h> */
+#define DWC_CFGH_DS_UPD_EN	(1 << 5)
+#define DWC_CFGH_SS_UPD_EN	(1 << 6)
+
+/* Bitfields in SGR */
+#define DWC_SGR_SGI(x)		((x) << 0)
+#define DWC_SGR_SGC(x)		((x) << 20)
+
+/* Bitfields in DSR */
+#define DWC_DSR_DSI(x)		((x) << 0)
+#define DWC_DSR_DSC(x)		((x) << 20)
+
+/* Bitfields in CFG */
+#define DW_CFG_DMA_EN		(1 << 0)
+
+#define DW_REGLEN		0x400
+
+struct dw_dma_chan {
+	struct dma_chan		chan;
+	void __iomem		*ch_regs;
+	u8			mask;
+
+	spinlock_t		lock;
+
+	/* these other elements are all protected by lock */
+	dma_cookie_t		completed;
+	struct list_head	active_list;
+	struct list_head	queue;
+	struct list_head	free_list;
+
+	struct dw_dma_slave	*dws;
+
+	unsigned int		descs_allocated;
+};
+
+static inline struct dw_dma_chan_regs __iomem *
+__dwc_regs(struct dw_dma_chan *dwc)
+{
+	return dwc->ch_regs;
+}
+
+#define channel_readl(dwc, name) \
+	__raw_readl(&(__dwc_regs(dwc)->name))
+#define channel_writel(dwc, name, val) \
+	__raw_writel((val), &(__dwc_regs(dwc)->name))
+
+static inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan)
+{
+	return container_of(chan, struct dw_dma_chan, chan);
+}
+
+
+struct dw_dma {
+	struct dma_device	dma;
+	void __iomem		*regs;
+	struct tasklet_struct	tasklet;
+	struct clk		*clk;
+
+	u8			all_chan_mask;
+
+	struct dw_dma_chan	chan[0];
+};
+
+static inline struct dw_dma_regs __iomem *__dw_regs(struct dw_dma *dw)
+{
+	return dw->regs;
+}
+
+#define dma_readl(dw, name) \
+	__raw_readl(&(__dw_regs(dw)->name))
+#define dma_writel(dw, name, val) \
+	__raw_writel((val), &(__dw_regs(dw)->name))
+
+#define channel_set_bit(dw, reg, mask) \
+	dma_writel(dw, reg, ((mask) << 8) | (mask))
+#define channel_clear_bit(dw, reg, mask) \
+	dma_writel(dw, reg, ((mask) << 8) | 0)
+
+static inline struct dw_dma *to_dw_dma(struct dma_device *ddev)
+{
+	return container_of(ddev, struct dw_dma, dma);
+}
+
+/* LLI == Linked List Item; a.k.a. DMA block descriptor */
+struct dw_lli {
+	/* values that are not changed by hardware */
+	dma_addr_t	sar;
+	dma_addr_t	dar;
+	dma_addr_t	llp;		/* chain to next lli */
+	u32		ctllo;
+	/* values that may get written back: */
+	u32		ctlhi;
+	/* sstat and dstat can snapshot peripheral register state.
+	 * silicon config may discard either or both...
+	 */
+	u32		sstat;
+	u32		dstat;
+};
+
+struct dw_desc {
+	/* FIRST values the hardware uses */
+	struct dw_lli			lli;
+
+	/* THEN values for driver housekeeping */
+	struct list_head		desc_node;
+	struct dma_async_tx_descriptor	txd;
+	size_t				len;
+};
+
+static inline struct dw_desc *
+txd_to_dw_desc(struct dma_async_tx_descriptor *txd)
+{
+	return container_of(txd, struct dw_desc, txd);
+}
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 054eabf..c0059ca 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -366,7 +366,8 @@
  *
  * Return - The number of descriptors allocated.
  */
-static int fsl_dma_alloc_chan_resources(struct dma_chan *chan)
+static int fsl_dma_alloc_chan_resources(struct dma_chan *chan,
+					struct dma_client *client)
 {
 	struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
 	LIST_HEAD(tmp_list);
@@ -809,8 +810,7 @@
 	if (!src) {
 		dev_err(fsl_chan->dev,
 				"selftest: Cannot alloc memory for test!\n");
-		err = -ENOMEM;
-		goto out;
+		return -ENOMEM;
 	}
 
 	dest = src + test_size;
@@ -820,7 +820,7 @@
 
 	chan = &fsl_chan->common;
 
-	if (fsl_dma_alloc_chan_resources(chan) < 1) {
+	if (fsl_dma_alloc_chan_resources(chan, NULL) < 1) {
 		dev_err(fsl_chan->dev,
 				"selftest: Cannot alloc resources for DMA\n");
 		err = -ENODEV;
@@ -842,13 +842,13 @@
 	if (fsl_dma_is_complete(chan, cookie, NULL, NULL) != DMA_SUCCESS) {
 		dev_err(fsl_chan->dev, "selftest: Time out!\n");
 		err = -ENODEV;
-		goto out;
+		goto free_resources;
 	}
 
 	/* Test free and re-alloc channel resources */
 	fsl_dma_free_chan_resources(chan);
 
-	if (fsl_dma_alloc_chan_resources(chan) < 1) {
+	if (fsl_dma_alloc_chan_resources(chan, NULL) < 1) {
 		dev_err(fsl_chan->dev,
 				"selftest: Cannot alloc resources for DMA\n");
 		err = -ENODEV;
@@ -927,8 +927,7 @@
 	if (!new_fsl_chan) {
 		dev_err(&dev->dev, "No free memory for allocating "
 				"dma channels!\n");
-		err = -ENOMEM;
-		goto err;
+		return -ENOMEM;
 	}
 
 	/* get dma channel register base */
@@ -936,7 +935,7 @@
 	if (err) {
 		dev_err(&dev->dev, "Can't get %s property 'reg'\n",
 				dev->node->full_name);
-		goto err;
+		goto err_no_reg;
 	}
 
 	new_fsl_chan->feature = *(u32 *)match->data;
@@ -958,7 +957,7 @@
 		dev_err(&dev->dev, "There is no %d channel!\n",
 				new_fsl_chan->id);
 		err = -EINVAL;
-		goto err;
+		goto err_no_chan;
 	}
 	fdev->chan[new_fsl_chan->id] = new_fsl_chan;
 	tasklet_init(&new_fsl_chan->tasklet, dma_do_tasklet,
@@ -997,23 +996,26 @@
 		if (err) {
 			dev_err(&dev->dev, "DMA channel %s request_irq error "
 				"with return %d\n", dev->node->full_name, err);
-			goto err;
+			goto err_no_irq;
 		}
 	}
 
 	err = fsl_dma_self_test(new_fsl_chan);
 	if (err)
-		goto err;
+		goto err_self_test;
 
 	dev_info(&dev->dev, "#%d (%s), irq %d\n", new_fsl_chan->id,
 				match->compatible, new_fsl_chan->irq);
 
 	return 0;
-err:
-	dma_halt(new_fsl_chan);
-	iounmap(new_fsl_chan->reg_base);
+
+err_self_test:
 	free_irq(new_fsl_chan->irq, new_fsl_chan);
+err_no_irq:
 	list_del(&new_fsl_chan->common.device_node);
+err_no_chan:
+	iounmap(new_fsl_chan->reg_base);
+err_no_reg:
 	kfree(new_fsl_chan);
 	return err;
 }
@@ -1054,8 +1056,7 @@
 	fdev = kzalloc(sizeof(struct fsl_dma_device), GFP_KERNEL);
 	if (!fdev) {
 		dev_err(&dev->dev, "No enough memory for 'priv'\n");
-		err = -ENOMEM;
-		goto err;
+		return -ENOMEM;
 	}
 	fdev->dev = &dev->dev;
 	INIT_LIST_HEAD(&fdev->common.channels);
@@ -1065,7 +1066,7 @@
 	if (err) {
 		dev_err(&dev->dev, "Can't get %s property 'reg'\n",
 				dev->node->full_name);
-		goto err;
+		goto err_no_reg;
 	}
 
 	dev_info(&dev->dev, "Probe the Freescale DMA driver for %s "
@@ -1103,6 +1104,7 @@
 
 err:
 	iounmap(fdev->reg_base);
+err_no_reg:
 	kfree(fdev);
 	return err;
 }
diff --git a/drivers/dma/ioat.c b/drivers/dma/ioat.c
index 16e0fd8..9b16a3a 100644
--- a/drivers/dma/ioat.c
+++ b/drivers/dma/ioat.c
@@ -47,6 +47,16 @@
 
 	/* I/OAT v2 platforms */
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB) },
+
+	/* I/OAT v3 platforms */
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG0) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG1) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG2) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG3) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG4) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG5) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG6) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG7) },
 	{ 0, }
 };
 
@@ -83,6 +93,11 @@
 		if (device->dma && ioat_dca_enabled)
 			device->dca = ioat2_dca_init(pdev, iobase);
 		break;
+	case IOAT_VER_3_0:
+		device->dma = ioat_dma_probe(pdev, iobase);
+		if (device->dma && ioat_dca_enabled)
+			device->dca = ioat3_dca_init(pdev, iobase);
+		break;
 	default:
 		err = -ENODEV;
 		break;
diff --git a/drivers/dma/ioat_dca.c b/drivers/dma/ioat_dca.c
index 9e92276..6cf622d 100644
--- a/drivers/dma/ioat_dca.c
+++ b/drivers/dma/ioat_dca.c
@@ -37,12 +37,18 @@
 #include "ioatdma_registers.h"
 
 /*
- * Bit 16 of a tag map entry is the "valid" bit, if it is set then bits 0:15
+ * Bit 7 of a tag map entry is the "valid" bit, if it is set then bits 0:6
  * contain the bit number of the APIC ID to map into the DCA tag.  If the valid
  * bit is not set, then the value must be 0 or 1 and defines the bit in the tag.
  */
 #define DCA_TAG_MAP_VALID 0x80
 
+#define DCA3_TAG_MAP_BIT_TO_INV 0x80
+#define DCA3_TAG_MAP_BIT_TO_SEL 0x40
+#define DCA3_TAG_MAP_LITERAL_VAL 0x1
+
+#define DCA_TAG_MAP_MASK 0xDF
+
 /*
  * "Legacy" DCA systems do not implement the DCA register set in the
  * I/OAT device.  Software needs direct support for their tag mappings.
@@ -95,6 +101,7 @@
 };
 
 #define IOAT_DCA_MAX_REQ 6
+#define IOAT3_DCA_MAX_REQ 2
 
 struct ioat_dca_priv {
 	void __iomem		*iobase;
@@ -171,7 +178,9 @@
 	return -ENODEV;
 }
 
-static u8 ioat_dca_get_tag(struct dca_provider *dca, int cpu)
+static u8 ioat_dca_get_tag(struct dca_provider *dca,
+			   struct device *dev,
+			   int cpu)
 {
 	struct ioat_dca_priv *ioatdca = dca_priv(dca);
 	int i, apic_id, bit, value;
@@ -193,10 +202,26 @@
 	return tag;
 }
 
+static int ioat_dca_dev_managed(struct dca_provider *dca,
+				struct device *dev)
+{
+	struct ioat_dca_priv *ioatdca = dca_priv(dca);
+	struct pci_dev *pdev;
+	int i;
+
+	pdev = to_pci_dev(dev);
+	for (i = 0; i < ioatdca->max_requesters; i++) {
+		if (ioatdca->req_slots[i].pdev == pdev)
+			return 1;
+	}
+	return 0;
+}
+
 static struct dca_ops ioat_dca_ops = {
 	.add_requester		= ioat_dca_add_requester,
 	.remove_requester	= ioat_dca_remove_requester,
 	.get_tag		= ioat_dca_get_tag,
+	.dev_managed		= ioat_dca_dev_managed,
 };
 
 
@@ -207,6 +232,8 @@
 	u8 *tag_map = NULL;
 	int i;
 	int err;
+	u8 version;
+	u8 max_requesters;
 
 	if (!system_has_dca_enabled(pdev))
 		return NULL;
@@ -237,15 +264,20 @@
 	if (tag_map == NULL)
 		return NULL;
 
+	version = readb(iobase + IOAT_VER_OFFSET);
+	if (version == IOAT_VER_3_0)
+		max_requesters = IOAT3_DCA_MAX_REQ;
+	else
+		max_requesters = IOAT_DCA_MAX_REQ;
+
 	dca = alloc_dca_provider(&ioat_dca_ops,
 			sizeof(*ioatdca) +
-			(sizeof(struct ioat_dca_slot) * IOAT_DCA_MAX_REQ));
+			(sizeof(struct ioat_dca_slot) * max_requesters));
 	if (!dca)
 		return NULL;
 
 	ioatdca = dca_priv(dca);
-	ioatdca->max_requesters = IOAT_DCA_MAX_REQ;
-
+	ioatdca->max_requesters = max_requesters;
 	ioatdca->dca_base = iobase + 0x54;
 
 	/* copy over the APIC ID to DCA tag mapping */
@@ -323,11 +355,13 @@
 	return -ENODEV;
 }
 
-static u8 ioat2_dca_get_tag(struct dca_provider *dca, int cpu)
+static u8 ioat2_dca_get_tag(struct dca_provider *dca,
+			    struct device *dev,
+			    int cpu)
 {
 	u8 tag;
 
-	tag = ioat_dca_get_tag(dca, cpu);
+	tag = ioat_dca_get_tag(dca, dev, cpu);
 	tag = (~tag) & 0x1F;
 	return tag;
 }
@@ -336,6 +370,7 @@
 	.add_requester		= ioat2_dca_add_requester,
 	.remove_requester	= ioat2_dca_remove_requester,
 	.get_tag		= ioat2_dca_get_tag,
+	.dev_managed		= ioat_dca_dev_managed,
 };
 
 static int ioat2_dca_count_dca_slots(void __iomem *iobase, u16 dca_offset)
@@ -425,3 +460,198 @@
 
 	return dca;
 }
+
+static int ioat3_dca_add_requester(struct dca_provider *dca, struct device *dev)
+{
+	struct ioat_dca_priv *ioatdca = dca_priv(dca);
+	struct pci_dev *pdev;
+	int i;
+	u16 id;
+	u16 global_req_table;
+
+	/* This implementation only supports PCI-Express */
+	if (dev->bus != &pci_bus_type)
+		return -ENODEV;
+	pdev = to_pci_dev(dev);
+	id = dcaid_from_pcidev(pdev);
+
+	if (ioatdca->requester_count == ioatdca->max_requesters)
+		return -ENODEV;
+
+	for (i = 0; i < ioatdca->max_requesters; i++) {
+		if (ioatdca->req_slots[i].pdev == NULL) {
+			/* found an empty slot */
+			ioatdca->requester_count++;
+			ioatdca->req_slots[i].pdev = pdev;
+			ioatdca->req_slots[i].rid = id;
+			global_req_table =
+			      readw(ioatdca->dca_base + IOAT3_DCA_GREQID_OFFSET);
+			writel(id | IOAT_DCA_GREQID_VALID,
+			       ioatdca->iobase + global_req_table + (i * 4));
+			return i;
+		}
+	}
+	/* Error, ioatdma->requester_count is out of whack */
+	return -EFAULT;
+}
+
+static int ioat3_dca_remove_requester(struct dca_provider *dca,
+				      struct device *dev)
+{
+	struct ioat_dca_priv *ioatdca = dca_priv(dca);
+	struct pci_dev *pdev;
+	int i;
+	u16 global_req_table;
+
+	/* This implementation only supports PCI-Express */
+	if (dev->bus != &pci_bus_type)
+		return -ENODEV;
+	pdev = to_pci_dev(dev);
+
+	for (i = 0; i < ioatdca->max_requesters; i++) {
+		if (ioatdca->req_slots[i].pdev == pdev) {
+			global_req_table =
+			      readw(ioatdca->dca_base + IOAT3_DCA_GREQID_OFFSET);
+			writel(0, ioatdca->iobase + global_req_table + (i * 4));
+			ioatdca->req_slots[i].pdev = NULL;
+			ioatdca->req_slots[i].rid = 0;
+			ioatdca->requester_count--;
+			return i;
+		}
+	}
+	return -ENODEV;
+}
+
+static u8 ioat3_dca_get_tag(struct dca_provider *dca,
+			    struct device *dev,
+			    int cpu)
+{
+	u8 tag;
+
+	struct ioat_dca_priv *ioatdca = dca_priv(dca);
+	int i, apic_id, bit, value;
+	u8 entry;
+
+	tag = 0;
+	apic_id = cpu_physical_id(cpu);
+
+	for (i = 0; i < IOAT_TAG_MAP_LEN; i++) {
+		entry = ioatdca->tag_map[i];
+		if (entry & DCA3_TAG_MAP_BIT_TO_SEL) {
+			bit = entry &
+				~(DCA3_TAG_MAP_BIT_TO_SEL | DCA3_TAG_MAP_BIT_TO_INV);
+			value = (apic_id & (1 << bit)) ? 1 : 0;
+		} else if (entry & DCA3_TAG_MAP_BIT_TO_INV) {
+			bit = entry & ~DCA3_TAG_MAP_BIT_TO_INV;
+			value = (apic_id & (1 << bit)) ? 0 : 1;
+		} else {
+			value = (entry & DCA3_TAG_MAP_LITERAL_VAL) ? 1 : 0;
+		}
+		tag |= (value << i);
+	}
+
+	return tag;
+}
+
+static struct dca_ops ioat3_dca_ops = {
+	.add_requester		= ioat3_dca_add_requester,
+	.remove_requester	= ioat3_dca_remove_requester,
+	.get_tag		= ioat3_dca_get_tag,
+	.dev_managed		= ioat_dca_dev_managed,
+};
+
+static int ioat3_dca_count_dca_slots(void *iobase, u16 dca_offset)
+{
+	int slots = 0;
+	u32 req;
+	u16 global_req_table;
+
+	global_req_table = readw(iobase + dca_offset + IOAT3_DCA_GREQID_OFFSET);
+	if (global_req_table == 0)
+		return 0;
+
+	do {
+		req = readl(iobase + global_req_table + (slots * sizeof(u32)));
+		slots++;
+	} while ((req & IOAT_DCA_GREQID_LASTID) == 0);
+
+	return slots;
+}
+
+struct dca_provider *ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase)
+{
+	struct dca_provider *dca;
+	struct ioat_dca_priv *ioatdca;
+	int slots;
+	int i;
+	int err;
+	u16 dca_offset;
+	u16 csi_fsb_control;
+	u16 pcie_control;
+	u8 bit;
+
+	union {
+		u64 full;
+		struct {
+			u32 low;
+			u32 high;
+		};
+	} tag_map;
+
+	if (!system_has_dca_enabled(pdev))
+		return NULL;
+
+	dca_offset = readw(iobase + IOAT_DCAOFFSET_OFFSET);
+	if (dca_offset == 0)
+		return NULL;
+
+	slots = ioat3_dca_count_dca_slots(iobase, dca_offset);
+	if (slots == 0)
+		return NULL;
+
+	dca = alloc_dca_provider(&ioat3_dca_ops,
+				 sizeof(*ioatdca)
+				      + (sizeof(struct ioat_dca_slot) * slots));
+	if (!dca)
+		return NULL;
+
+	ioatdca = dca_priv(dca);
+	ioatdca->iobase = iobase;
+	ioatdca->dca_base = iobase + dca_offset;
+	ioatdca->max_requesters = slots;
+
+	/* some bios might not know to turn these on */
+	csi_fsb_control = readw(ioatdca->dca_base + IOAT3_CSI_CONTROL_OFFSET);
+	if ((csi_fsb_control & IOAT3_CSI_CONTROL_PREFETCH) == 0) {
+		csi_fsb_control |= IOAT3_CSI_CONTROL_PREFETCH;
+		writew(csi_fsb_control,
+		       ioatdca->dca_base + IOAT3_CSI_CONTROL_OFFSET);
+	}
+	pcie_control = readw(ioatdca->dca_base + IOAT3_PCI_CONTROL_OFFSET);
+	if ((pcie_control & IOAT3_PCI_CONTROL_MEMWR) == 0) {
+		pcie_control |= IOAT3_PCI_CONTROL_MEMWR;
+		writew(pcie_control,
+		       ioatdca->dca_base + IOAT3_PCI_CONTROL_OFFSET);
+	}
+
+
+	/* TODO version, compatibility and configuration checks */
+
+	/* copy out the APIC to DCA tag map */
+	tag_map.low =
+		readl(ioatdca->dca_base + IOAT3_APICID_TAG_MAP_OFFSET_LOW);
+	tag_map.high =
+		readl(ioatdca->dca_base + IOAT3_APICID_TAG_MAP_OFFSET_HIGH);
+	for (i = 0; i < 8; i++) {
+		bit = tag_map.full >> (8 * i);
+		ioatdca->tag_map[i] = bit & DCA_TAG_MAP_MASK;
+	}
+
+	err = register_dca_provider(dca, &pdev->dev);
+	if (err) {
+		free_dca_provider(dca);
+		return NULL;
+	}
+
+	return dca;
+}
diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c
index 318e8a2..a52156e 100644
--- a/drivers/dma/ioat_dma.c
+++ b/drivers/dma/ioat_dma.c
@@ -32,6 +32,7 @@
 #include <linux/dmaengine.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
+#include <linux/workqueue.h>
 #include "ioatdma.h"
 #include "ioatdma_registers.h"
 #include "ioatdma_hw.h"
@@ -41,11 +42,23 @@
 #define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node)
 #define tx_to_ioat_desc(tx) container_of(tx, struct ioat_desc_sw, async_tx)
 
+#define chan_num(ch) ((int)((ch)->reg_base - (ch)->device->reg_base) / 0x80)
 static int ioat_pending_level = 4;
 module_param(ioat_pending_level, int, 0644);
 MODULE_PARM_DESC(ioat_pending_level,
 		 "high-water mark for pushing ioat descriptors (default: 4)");
 
+#define RESET_DELAY  msecs_to_jiffies(100)
+#define WATCHDOG_DELAY  round_jiffies(msecs_to_jiffies(2000))
+static void ioat_dma_chan_reset_part2(struct work_struct *work);
+static void ioat_dma_chan_watchdog(struct work_struct *work);
+
+/*
+ * workaround for IOAT ver.3.0 null descriptor issue
+ * (channel returns error when size is 0)
+ */
+#define NULL_DESC_BUFFER_SIZE 1
+
 /* internal functions */
 static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan);
 static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan);
@@ -122,6 +135,38 @@
 	int i;
 	struct ioat_dma_chan *ioat_chan;
 
+	/*
+	 * IOAT ver.3 workarounds
+	 */
+	if (device->version == IOAT_VER_3_0) {
+		u32 chan_err_mask;
+		u16 dev_id;
+		u32 dmauncerrsts;
+
+		/*
+		 * Write CHANERRMSK_INT with 3E07h to mask out the errors
+		 * that can cause stability issues for IOAT ver.3
+		 */
+		chan_err_mask = 0x3E07;
+		pci_write_config_dword(device->pdev,
+			IOAT_PCI_CHANERRMASK_INT_OFFSET,
+			chan_err_mask);
+
+		/*
+		 * Clear DMAUNCERRSTS Cfg-Reg Parity Error status bit
+		 * (workaround for spurious config parity error after restart)
+		 */
+		pci_read_config_word(device->pdev,
+			IOAT_PCI_DEVICE_ID_OFFSET,
+			&dev_id);
+		if (dev_id == PCI_DEVICE_ID_INTEL_IOAT_TBG0) {
+			dmauncerrsts = 0x10;
+			pci_write_config_dword(device->pdev,
+				IOAT_PCI_DMAUNCERRSTS_OFFSET,
+				dmauncerrsts);
+		}
+	}
+
 	device->common.chancnt = readb(device->reg_base + IOAT_CHANCNT_OFFSET);
 	xfercap_scale = readb(device->reg_base + IOAT_XFERCAP_OFFSET);
 	xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale));
@@ -137,6 +182,7 @@
 		ioat_chan->reg_base = device->reg_base + (0x80 * (i + 1));
 		ioat_chan->xfercap = xfercap;
 		ioat_chan->desccount = 0;
+		INIT_DELAYED_WORK(&ioat_chan->work, ioat_dma_chan_reset_part2);
 		if (ioat_chan->device->version != IOAT_VER_1_2) {
 			writel(IOAT_DCACTRL_CMPL_WRITE_ENABLE
 					| IOAT_DMA_DCA_ANY_CPU,
@@ -175,7 +221,7 @@
 {
 	struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
 
-	if (ioat_chan->pending != 0) {
+	if (ioat_chan->pending > 0) {
 		spin_lock_bh(&ioat_chan->desc_lock);
 		__ioat1_dma_memcpy_issue_pending(ioat_chan);
 		spin_unlock_bh(&ioat_chan->desc_lock);
@@ -194,13 +240,228 @@
 {
 	struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
 
-	if (ioat_chan->pending != 0) {
+	if (ioat_chan->pending > 0) {
 		spin_lock_bh(&ioat_chan->desc_lock);
 		__ioat2_dma_memcpy_issue_pending(ioat_chan);
 		spin_unlock_bh(&ioat_chan->desc_lock);
 	}
 }
 
+
+/**
+ * ioat_dma_chan_reset_part2 - reinit the channel after a reset
+ */
+static void ioat_dma_chan_reset_part2(struct work_struct *work)
+{
+	struct ioat_dma_chan *ioat_chan =
+		container_of(work, struct ioat_dma_chan, work.work);
+	struct ioat_desc_sw *desc;
+
+	spin_lock_bh(&ioat_chan->cleanup_lock);
+	spin_lock_bh(&ioat_chan->desc_lock);
+
+	ioat_chan->completion_virt->low = 0;
+	ioat_chan->completion_virt->high = 0;
+	ioat_chan->pending = 0;
+
+	/*
+	 * count the descriptors waiting, and be sure to do it
+	 * right for both the CB1 line and the CB2 ring
+	 */
+	ioat_chan->dmacount = 0;
+	if (ioat_chan->used_desc.prev) {
+		desc = to_ioat_desc(ioat_chan->used_desc.prev);
+		do {
+			ioat_chan->dmacount++;
+			desc = to_ioat_desc(desc->node.next);
+		} while (&desc->node != ioat_chan->used_desc.next);
+	}
+
+	/*
+	 * write the new starting descriptor address
+	 * this puts channel engine into ARMED state
+	 */
+	desc = to_ioat_desc(ioat_chan->used_desc.prev);
+	switch (ioat_chan->device->version) {
+	case IOAT_VER_1_2:
+		writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,
+		       ioat_chan->reg_base + IOAT1_CHAINADDR_OFFSET_LOW);
+		writel(((u64) desc->async_tx.phys) >> 32,
+		       ioat_chan->reg_base + IOAT1_CHAINADDR_OFFSET_HIGH);
+
+		writeb(IOAT_CHANCMD_START, ioat_chan->reg_base
+			+ IOAT_CHANCMD_OFFSET(ioat_chan->device->version));
+		break;
+	case IOAT_VER_2_0:
+		writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,
+		       ioat_chan->reg_base + IOAT2_CHAINADDR_OFFSET_LOW);
+		writel(((u64) desc->async_tx.phys) >> 32,
+		       ioat_chan->reg_base + IOAT2_CHAINADDR_OFFSET_HIGH);
+
+		/* tell the engine to go with what's left to be done */
+		writew(ioat_chan->dmacount,
+		       ioat_chan->reg_base + IOAT_CHAN_DMACOUNT_OFFSET);
+
+		break;
+	}
+	dev_err(&ioat_chan->device->pdev->dev,
+		"chan%d reset - %d descs waiting, %d total desc\n",
+		chan_num(ioat_chan), ioat_chan->dmacount, ioat_chan->desccount);
+
+	spin_unlock_bh(&ioat_chan->desc_lock);
+	spin_unlock_bh(&ioat_chan->cleanup_lock);
+}
+
+/**
+ * ioat_dma_reset_channel - restart a channel
+ * @ioat_chan: IOAT DMA channel handle
+ */
+static void ioat_dma_reset_channel(struct ioat_dma_chan *ioat_chan)
+{
+	u32 chansts, chanerr;
+
+	if (!ioat_chan->used_desc.prev)
+		return;
+
+	chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
+	chansts = (ioat_chan->completion_virt->low
+					& IOAT_CHANSTS_DMA_TRANSFER_STATUS);
+	if (chanerr) {
+		dev_err(&ioat_chan->device->pdev->dev,
+			"chan%d, CHANSTS = 0x%08x CHANERR = 0x%04x, clearing\n",
+			chan_num(ioat_chan), chansts, chanerr);
+		writel(chanerr, ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
+	}
+
+	/*
+	 * whack it upside the head with a reset
+	 * and wait for things to settle out.
+	 * force the pending count to a really big negative
+	 * to make sure no one forces an issue_pending
+	 * while we're waiting.
+	 */
+
+	spin_lock_bh(&ioat_chan->desc_lock);
+	ioat_chan->pending = INT_MIN;
+	writeb(IOAT_CHANCMD_RESET,
+	       ioat_chan->reg_base
+	       + IOAT_CHANCMD_OFFSET(ioat_chan->device->version));
+	spin_unlock_bh(&ioat_chan->desc_lock);
+
+	/* schedule the 2nd half instead of sleeping a long time */
+	schedule_delayed_work(&ioat_chan->work, RESET_DELAY);
+}
+
+/**
+ * ioat_dma_chan_watchdog - watch for stuck channels
+ */
+static void ioat_dma_chan_watchdog(struct work_struct *work)
+{
+	struct ioatdma_device *device =
+		container_of(work, struct ioatdma_device, work.work);
+	struct ioat_dma_chan *ioat_chan;
+	int i;
+
+	union {
+		u64 full;
+		struct {
+			u32 low;
+			u32 high;
+		};
+	} completion_hw;
+	unsigned long compl_desc_addr_hw;
+
+	for (i = 0; i < device->common.chancnt; i++) {
+		ioat_chan = ioat_lookup_chan_by_index(device, i);
+
+		if (ioat_chan->device->version == IOAT_VER_1_2
+			/* have we started processing anything yet */
+		    && ioat_chan->last_completion
+			/* have we completed any since last watchdog cycle? */
+		    && (ioat_chan->last_completion ==
+				ioat_chan->watchdog_completion)
+			/* has TCP stuck on one cookie since last watchdog? */
+		    && (ioat_chan->watchdog_tcp_cookie ==
+				ioat_chan->watchdog_last_tcp_cookie)
+		    && (ioat_chan->watchdog_tcp_cookie !=
+				ioat_chan->completed_cookie)
+			/* is there something in the chain to be processed? */
+			/* CB1 chain always has at least the last one processed */
+		    && (ioat_chan->used_desc.prev != ioat_chan->used_desc.next)
+		    && ioat_chan->pending == 0) {
+
+			/*
+			 * check CHANSTS register for completed
+			 * descriptor address.
+			 * if it is different than completion writeback,
+			 * it is not zero
+			 * and it has changed since the last watchdog
+			 *     we can assume that channel
+			 *     is still working correctly
+			 *     and the problem is in completion writeback.
+			 *     update completion writeback
+			 *     with actual CHANSTS value
+			 * else
+			 *     try resetting the channel
+			 */
+
+			completion_hw.low = readl(ioat_chan->reg_base +
+				IOAT_CHANSTS_OFFSET_LOW(ioat_chan->device->version));
+			completion_hw.high = readl(ioat_chan->reg_base +
+				IOAT_CHANSTS_OFFSET_HIGH(ioat_chan->device->version));
+#if (BITS_PER_LONG == 64)
+			compl_desc_addr_hw =
+				completion_hw.full
+				& IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR;
+#else
+			compl_desc_addr_hw =
+				completion_hw.low & IOAT_LOW_COMPLETION_MASK;
+#endif
+
+			if ((compl_desc_addr_hw != 0)
+			   && (compl_desc_addr_hw != ioat_chan->watchdog_completion)
+			   && (compl_desc_addr_hw != ioat_chan->last_compl_desc_addr_hw)) {
+				ioat_chan->last_compl_desc_addr_hw = compl_desc_addr_hw;
+				ioat_chan->completion_virt->low = completion_hw.low;
+				ioat_chan->completion_virt->high = completion_hw.high;
+			} else {
+				ioat_dma_reset_channel(ioat_chan);
+				ioat_chan->watchdog_completion = 0;
+				ioat_chan->last_compl_desc_addr_hw = 0;
+			}
+
+		/*
+		 * for version 2.0 if there are descriptors yet to be processed
+		 * and the last completed hasn't changed since the last watchdog
+		 *      if they haven't hit the pending level
+		 *          issue the pending to push them through
+		 *      else
+		 *          try resetting the channel
+		 */
+		} else if (ioat_chan->device->version == IOAT_VER_2_0
+		    && ioat_chan->used_desc.prev
+		    && ioat_chan->last_completion
+		    && ioat_chan->last_completion == ioat_chan->watchdog_completion) {
+
+			if (ioat_chan->pending < ioat_pending_level)
+				ioat2_dma_memcpy_issue_pending(&ioat_chan->common);
+			else {
+				ioat_dma_reset_channel(ioat_chan);
+				ioat_chan->watchdog_completion = 0;
+			}
+		} else {
+			ioat_chan->last_compl_desc_addr_hw = 0;
+			ioat_chan->watchdog_completion
+					= ioat_chan->last_completion;
+		}
+
+		ioat_chan->watchdog_last_tcp_cookie =
+			ioat_chan->watchdog_tcp_cookie;
+	}
+
+	schedule_delayed_work(&device->work, WATCHDOG_DELAY);
+}
+
 static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx)
 {
 	struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
@@ -250,6 +511,13 @@
 		prev = new;
 	} while (len && (new = ioat1_dma_get_next_descriptor(ioat_chan)));
 
+	if (!new) {
+		dev_err(&ioat_chan->device->pdev->dev,
+			"tx submit failed\n");
+		spin_unlock_bh(&ioat_chan->desc_lock);
+		return -ENOMEM;
+	}
+
 	hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
 	if (new->async_tx.callback) {
 		hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_INT_GN;
@@ -335,7 +603,14 @@
 		desc_count++;
 	} while (len && (new = ioat2_dma_get_next_descriptor(ioat_chan)));
 
-	hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
+	if (!new) {
+		dev_err(&ioat_chan->device->pdev->dev,
+			"tx submit failed\n");
+		spin_unlock_bh(&ioat_chan->desc_lock);
+		return -ENOMEM;
+	}
+
+	hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
 	if (new->async_tx.callback) {
 		hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_INT_GN;
 		if (first != new) {
@@ -406,6 +681,7 @@
 		desc_sw->async_tx.tx_submit = ioat1_tx_submit;
 		break;
 	case IOAT_VER_2_0:
+	case IOAT_VER_3_0:
 		desc_sw->async_tx.tx_submit = ioat2_tx_submit;
 		break;
 	}
@@ -452,7 +728,8 @@
  * ioat_dma_alloc_chan_resources - returns the number of allocated descriptors
  * @chan: the channel to be filled out
  */
-static int ioat_dma_alloc_chan_resources(struct dma_chan *chan)
+static int ioat_dma_alloc_chan_resources(struct dma_chan *chan,
+					 struct dma_client *client)
 {
 	struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
 	struct ioat_desc_sw *desc;
@@ -555,6 +832,7 @@
 		}
 		break;
 	case IOAT_VER_2_0:
+	case IOAT_VER_3_0:
 		list_for_each_entry_safe(desc, _desc,
 					 ioat_chan->free_desc.next, node) {
 			list_del(&desc->node);
@@ -585,6 +863,10 @@
 	ioat_chan->last_completion = ioat_chan->completion_addr = 0;
 	ioat_chan->pending = 0;
 	ioat_chan->dmacount = 0;
+	ioat_chan->watchdog_completion = 0;
+	ioat_chan->last_compl_desc_addr_hw = 0;
+	ioat_chan->watchdog_tcp_cookie =
+		ioat_chan->watchdog_last_tcp_cookie = 0;
 }
 
 /**
@@ -640,7 +922,8 @@
 
 		/* set up the noop descriptor */
 		noop_desc = to_ioat_desc(ioat_chan->used_desc.next);
-		noop_desc->hw->size = 0;
+		/* set size to non-zero value (channel returns error when size is 0) */
+		noop_desc->hw->size = NULL_DESC_BUFFER_SIZE;
 		noop_desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL;
 		noop_desc->hw->src_addr = 0;
 		noop_desc->hw->dst_addr = 0;
@@ -690,6 +973,7 @@
 		return ioat1_dma_get_next_descriptor(ioat_chan);
 		break;
 	case IOAT_VER_2_0:
+	case IOAT_VER_3_0:
 		return ioat2_dma_get_next_descriptor(ioat_chan);
 		break;
 	}
@@ -716,8 +1000,12 @@
 		new->src = dma_src;
 		new->async_tx.flags = flags;
 		return &new->async_tx;
-	} else
+	} else {
+		dev_err(&ioat_chan->device->pdev->dev,
+			"chan%d - get_next_desc failed: %d descs waiting, %d total desc\n",
+			chan_num(ioat_chan), ioat_chan->dmacount, ioat_chan->desccount);
 		return NULL;
+	}
 }
 
 static struct dma_async_tx_descriptor *ioat2_dma_prep_memcpy(
@@ -744,8 +1032,13 @@
 		new->src = dma_src;
 		new->async_tx.flags = flags;
 		return &new->async_tx;
-	} else
+	} else {
+		spin_unlock_bh(&ioat_chan->desc_lock);
+		dev_err(&ioat_chan->device->pdev->dev,
+			"chan%d - get_next_desc failed: %d descs waiting, %d total desc\n",
+			chan_num(ioat_chan), ioat_chan->dmacount, ioat_chan->desccount);
 		return NULL;
+	}
 }
 
 static void ioat_dma_cleanup_tasklet(unsigned long data)
@@ -756,6 +1049,27 @@
 	       chan->reg_base + IOAT_CHANCTRL_OFFSET);
 }
 
+static void
+ioat_dma_unmap(struct ioat_dma_chan *ioat_chan, struct ioat_desc_sw *desc)
+{
+	/*
+	 * yes we are unmapping both _page and _single
+	 * alloc'd regions with unmap_page. Is this
+	 * *really* that bad?
+	 */
+	if (!(desc->async_tx.flags & DMA_COMPL_SKIP_DEST_UNMAP))
+		pci_unmap_page(ioat_chan->device->pdev,
+				pci_unmap_addr(desc, dst),
+				pci_unmap_len(desc, len),
+				PCI_DMA_FROMDEVICE);
+
+	if (!(desc->async_tx.flags & DMA_COMPL_SKIP_SRC_UNMAP))
+		pci_unmap_page(ioat_chan->device->pdev,
+				pci_unmap_addr(desc, src),
+				pci_unmap_len(desc, len),
+				PCI_DMA_TODEVICE);
+}
+
 /**
  * ioat_dma_memcpy_cleanup - cleanup up finished descriptors
  * @chan: ioat channel to be cleaned up
@@ -799,11 +1113,27 @@
 
 	if (phys_complete == ioat_chan->last_completion) {
 		spin_unlock_bh(&ioat_chan->cleanup_lock);
+		/*
+		 * perhaps we're stuck so hard that the watchdog can't go off?
+		 * try to catch it after 2 seconds
+		 */
+		if (ioat_chan->device->version != IOAT_VER_3_0) {
+			if (time_after(jiffies,
+				       ioat_chan->last_completion_time + HZ*WATCHDOG_DELAY)) {
+				ioat_dma_chan_watchdog(&(ioat_chan->device->work.work));
+				ioat_chan->last_completion_time = jiffies;
+			}
+		}
+		return;
+	}
+	ioat_chan->last_completion_time = jiffies;
+
+	cookie = 0;
+	if (!spin_trylock_bh(&ioat_chan->desc_lock)) {
+		spin_unlock_bh(&ioat_chan->cleanup_lock);
 		return;
 	}
 
-	cookie = 0;
-	spin_lock_bh(&ioat_chan->desc_lock);
 	switch (ioat_chan->device->version) {
 	case IOAT_VER_1_2:
 		list_for_each_entry_safe(desc, _desc,
@@ -816,21 +1146,7 @@
 			 */
 			if (desc->async_tx.cookie) {
 				cookie = desc->async_tx.cookie;
-
-				/*
-				 * yes we are unmapping both _page and _single
-				 * alloc'd regions with unmap_page. Is this
-				 * *really* that bad?
-				 */
-				pci_unmap_page(ioat_chan->device->pdev,
-						pci_unmap_addr(desc, dst),
-						pci_unmap_len(desc, len),
-						PCI_DMA_FROMDEVICE);
-				pci_unmap_page(ioat_chan->device->pdev,
-						pci_unmap_addr(desc, src),
-						pci_unmap_len(desc, len),
-						PCI_DMA_TODEVICE);
-
+				ioat_dma_unmap(ioat_chan, desc);
 				if (desc->async_tx.callback) {
 					desc->async_tx.callback(desc->async_tx.callback_param);
 					desc->async_tx.callback = NULL;
@@ -862,6 +1178,7 @@
 		}
 		break;
 	case IOAT_VER_2_0:
+	case IOAT_VER_3_0:
 		/* has some other thread has already cleaned up? */
 		if (ioat_chan->used_desc.prev == NULL)
 			break;
@@ -889,16 +1206,7 @@
 				if (desc->async_tx.cookie) {
 					cookie = desc->async_tx.cookie;
 					desc->async_tx.cookie = 0;
-
-					pci_unmap_page(ioat_chan->device->pdev,
-						      pci_unmap_addr(desc, dst),
-						      pci_unmap_len(desc, len),
-						      PCI_DMA_FROMDEVICE);
-					pci_unmap_page(ioat_chan->device->pdev,
-						      pci_unmap_addr(desc, src),
-						      pci_unmap_len(desc, len),
-						      PCI_DMA_TODEVICE);
-
+					ioat_dma_unmap(ioat_chan, desc);
 					if (desc->async_tx.callback) {
 						desc->async_tx.callback(desc->async_tx.callback_param);
 						desc->async_tx.callback = NULL;
@@ -943,6 +1251,7 @@
 
 	last_used = chan->cookie;
 	last_complete = ioat_chan->completed_cookie;
+	ioat_chan->watchdog_tcp_cookie = cookie;
 
 	if (done)
 		*done = last_complete;
@@ -973,10 +1282,19 @@
 	spin_lock_bh(&ioat_chan->desc_lock);
 
 	desc = ioat_dma_get_next_descriptor(ioat_chan);
+
+	if (!desc) {
+		dev_err(&ioat_chan->device->pdev->dev,
+			"Unable to start null desc - get next desc failed\n");
+		spin_unlock_bh(&ioat_chan->desc_lock);
+		return;
+	}
+
 	desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL
 				| IOAT_DMA_DESCRIPTOR_CTL_INT_GN
 				| IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
-	desc->hw->size = 0;
+	/* set size to non-zero value (channel returns error when size is 0) */
+	desc->hw->size = NULL_DESC_BUFFER_SIZE;
 	desc->hw->src_addr = 0;
 	desc->hw->dst_addr = 0;
 	async_tx_ack(&desc->async_tx);
@@ -994,6 +1312,7 @@
 			+ IOAT_CHANCMD_OFFSET(ioat_chan->device->version));
 		break;
 	case IOAT_VER_2_0:
+	case IOAT_VER_3_0:
 		writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,
 		       ioat_chan->reg_base + IOAT2_CHAINADDR_OFFSET_LOW);
 		writel(((u64) desc->async_tx.phys) >> 32,
@@ -1049,7 +1368,7 @@
 	dma_chan = container_of(device->common.channels.next,
 				struct dma_chan,
 				device_node);
-	if (device->common.device_alloc_chan_resources(dma_chan) < 1) {
+	if (device->common.device_alloc_chan_resources(dma_chan, NULL) < 1) {
 		dev_err(&device->pdev->dev,
 			"selftest cannot allocate chan resource\n");
 		err = -ENODEV;
@@ -1312,6 +1631,7 @@
 						ioat1_dma_memcpy_issue_pending;
 		break;
 	case IOAT_VER_2_0:
+	case IOAT_VER_3_0:
 		device->common.device_prep_dma_memcpy = ioat2_dma_prep_memcpy;
 		device->common.device_issue_pending =
 						ioat2_dma_memcpy_issue_pending;
@@ -1331,8 +1651,16 @@
 	if (err)
 		goto err_self_test;
 
+	ioat_set_tcp_copy_break(device);
+
 	dma_async_device_register(&device->common);
 
+	if (device->version != IOAT_VER_3_0) {
+		INIT_DELAYED_WORK(&device->work, ioat_dma_chan_watchdog);
+		schedule_delayed_work(&device->work,
+				      WATCHDOG_DELAY);
+	}
+
 	return device;
 
 err_self_test:
@@ -1365,6 +1693,10 @@
 	pci_release_regions(device->pdev);
 	pci_disable_device(device->pdev);
 
+	if (device->version != IOAT_VER_3_0) {
+		cancel_delayed_work(&device->work);
+	}
+
 	list_for_each_entry_safe(chan, _chan,
 				 &device->common.channels, device_node) {
 		ioat_chan = to_ioat_chan(chan);
diff --git a/drivers/dma/ioatdma.h b/drivers/dma/ioatdma.h
index f2c7fed..a3306d0 100644
--- a/drivers/dma/ioatdma.h
+++ b/drivers/dma/ioatdma.h
@@ -27,8 +27,9 @@
 #include <linux/dmapool.h>
 #include <linux/cache.h>
 #include <linux/pci_ids.h>
+#include <net/tcp.h>
 
-#define IOAT_DMA_VERSION  "2.04"
+#define IOAT_DMA_VERSION  "3.30"
 
 enum ioat_interrupt {
 	none = 0,
@@ -40,6 +41,7 @@
 
 #define IOAT_LOW_COMPLETION_MASK	0xffffffc0
 #define IOAT_DMA_DCA_ANY_CPU		~0
+#define IOAT_WATCHDOG_PERIOD		(2 * HZ)
 
 
 /**
@@ -62,6 +64,7 @@
 	struct dma_device common;
 	u8 version;
 	enum ioat_interrupt irq_mode;
+	struct delayed_work work;
 	struct msix_entry msix_entries[4];
 	struct ioat_dma_chan *idx[4];
 };
@@ -75,6 +78,7 @@
 
 	dma_cookie_t completed_cookie;
 	unsigned long last_completion;
+	unsigned long last_completion_time;
 
 	size_t xfercap;	/* XFERCAP register value expanded out */
 
@@ -82,6 +86,10 @@
 	spinlock_t desc_lock;
 	struct list_head free_desc;
 	struct list_head used_desc;
+	unsigned long watchdog_completion;
+	int watchdog_tcp_cookie;
+	u32 watchdog_last_tcp_cookie;
+	struct delayed_work work;
 
 	int pending;
 	int dmacount;
@@ -98,6 +106,7 @@
 			u32 high;
 		};
 	} *completion_virt;
+	unsigned long last_compl_desc_addr_hw;
 	struct tasklet_struct cleanup_task;
 };
 
@@ -121,17 +130,34 @@
 	struct dma_async_tx_descriptor async_tx;
 };
 
+static inline void ioat_set_tcp_copy_break(struct ioatdma_device *dev)
+{
+	#ifdef CONFIG_NET_DMA
+	switch (dev->version) {
+	case IOAT_VER_1_2:
+	case IOAT_VER_3_0:
+		sysctl_tcp_dma_copybreak = 4096;
+		break;
+	case IOAT_VER_2_0:
+		sysctl_tcp_dma_copybreak = 2048;
+		break;
+	}
+	#endif
+}
+
 #if defined(CONFIG_INTEL_IOATDMA) || defined(CONFIG_INTEL_IOATDMA_MODULE)
 struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev,
 				      void __iomem *iobase);
 void ioat_dma_remove(struct ioatdma_device *device);
 struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase);
 struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase);
+struct dca_provider *ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase);
 #else
 #define ioat_dma_probe(pdev, iobase)    NULL
 #define ioat_dma_remove(device)         do { } while (0)
 #define ioat_dca_init(pdev, iobase)	NULL
 #define ioat2_dca_init(pdev, iobase)	NULL
+#define ioat3_dca_init(pdev, iobase)	NULL
 #endif
 
 #endif /* IOATDMA_H */
diff --git a/drivers/dma/ioatdma_hw.h b/drivers/dma/ioatdma_hw.h
index dd470fa..f1ae2c7 100644
--- a/drivers/dma/ioatdma_hw.h
+++ b/drivers/dma/ioatdma_hw.h
@@ -35,6 +35,7 @@
 #define IOAT_PCI_SID            0x8086
 #define IOAT_VER_1_2            0x12    /* Version 1.2 */
 #define IOAT_VER_2_0            0x20    /* Version 2.0 */
+#define IOAT_VER_3_0            0x30    /* Version 3.0 */
 
 struct ioat_dma_descriptor {
 	uint32_t	size;
diff --git a/drivers/dma/ioatdma_registers.h b/drivers/dma/ioatdma_registers.h
index 9832d7e..827cb50 100644
--- a/drivers/dma/ioatdma_registers.h
+++ b/drivers/dma/ioatdma_registers.h
@@ -25,6 +25,10 @@
 #define IOAT_PCI_DMACTRL_DMA_EN			0x00000001
 #define IOAT_PCI_DMACTRL_MSI_EN			0x00000002
 
+#define IOAT_PCI_DEVICE_ID_OFFSET		0x02
+#define IOAT_PCI_DMAUNCERRSTS_OFFSET		0x148
+#define IOAT_PCI_CHANERRMASK_INT_OFFSET		0x184
+
 /* MMIO Device Registers */
 #define IOAT_CHANCNT_OFFSET			0x00	/*  8-bit */
 
@@ -149,7 +153,23 @@
 #define IOAT_DCA_GREQID_VALID       0x20000000
 #define IOAT_DCA_GREQID_LASTID      0x80000000
 
+#define IOAT3_CSI_CAPABILITY_OFFSET 0x08
+#define IOAT3_CSI_CAPABILITY_PREFETCH    0x1
 
+#define IOAT3_PCI_CAPABILITY_OFFSET 0x0A
+#define IOAT3_PCI_CAPABILITY_MEMWR  0x1
+
+#define IOAT3_CSI_CONTROL_OFFSET    0x0C
+#define IOAT3_CSI_CONTROL_PREFETCH  0x1
+
+#define IOAT3_PCI_CONTROL_OFFSET    0x0E
+#define IOAT3_PCI_CONTROL_MEMWR     0x1
+
+#define IOAT3_APICID_TAG_MAP_OFFSET 0x10
+#define IOAT3_APICID_TAG_MAP_OFFSET_LOW  0x10
+#define IOAT3_APICID_TAG_MAP_OFFSET_HIGH 0x14
+
+#define IOAT3_DCA_GREQID_OFFSET     0x02
 
 #define IOAT1_CHAINADDR_OFFSET		0x0C	/* 64-bit Descriptor Chain Address Register */
 #define IOAT2_CHAINADDR_OFFSET		0x10	/* 64-bit Descriptor Chain Address Register */
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index 0ec0f43..85bfeba 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -82,17 +82,24 @@
 			struct device *dev =
 				&iop_chan->device->pdev->dev;
 			u32 len = unmap->unmap_len;
-			u32 src_cnt = unmap->unmap_src_cnt;
-			dma_addr_t addr = iop_desc_get_dest_addr(unmap,
-				iop_chan);
+			enum dma_ctrl_flags flags = desc->async_tx.flags;
+			u32 src_cnt;
+			dma_addr_t addr;
 
-			dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE);
-			while (src_cnt--) {
-				addr = iop_desc_get_src_addr(unmap,
-							iop_chan,
-							src_cnt);
-				dma_unmap_page(dev, addr, len,
-					DMA_TO_DEVICE);
+			if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
+				addr = iop_desc_get_dest_addr(unmap, iop_chan);
+				dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE);
+			}
+
+			if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
+				src_cnt = unmap->unmap_src_cnt;
+				while (src_cnt--) {
+					addr = iop_desc_get_src_addr(unmap,
+								     iop_chan,
+								     src_cnt);
+					dma_unmap_page(dev, addr, len,
+						       DMA_TO_DEVICE);
+				}
 			}
 			desc->group_head = NULL;
 		}
@@ -366,8 +373,8 @@
 	if (!retry++)
 		goto retry;
 
-	/* try to free some slots if the allocation fails */
-	tasklet_schedule(&iop_chan->irq_tasklet);
+	/* perform direct reclaim if the allocation fails */
+	__iop_adma_slot_cleanup(iop_chan);
 
 	return NULL;
 }
@@ -443,8 +450,18 @@
 static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan);
 static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan);
 
-/* returns the number of allocated descriptors */
-static int iop_adma_alloc_chan_resources(struct dma_chan *chan)
+/**
+ * iop_adma_alloc_chan_resources -  returns the number of allocated descriptors
+ * @chan - allocate descriptor resources for this channel
+ * @client - current client requesting the channel be ready for requests
+ *
+ * Note: We keep the slots for 1 operation on iop_chan->chain at all times.  To
+ * avoid deadlock, via async_xor, num_descs_in_pool must at a minimum be
+ * greater than 2x the number slots needed to satisfy a device->max_xor
+ * request.
+ * */
+static int iop_adma_alloc_chan_resources(struct dma_chan *chan,
+					 struct dma_client *client)
 {
 	char *hw_desc;
 	int idx;
@@ -838,7 +855,7 @@
 	dma_chan = container_of(device->common.channels.next,
 				struct dma_chan,
 				device_node);
-	if (iop_adma_alloc_chan_resources(dma_chan) < 1) {
+	if (iop_adma_alloc_chan_resources(dma_chan, NULL) < 1) {
 		err = -ENODEV;
 		goto out;
 	}
@@ -936,7 +953,7 @@
 	dma_chan = container_of(device->common.channels.next,
 				struct dma_chan,
 				device_node);
-	if (iop_adma_alloc_chan_resources(dma_chan) < 1) {
+	if (iop_adma_alloc_chan_resources(dma_chan, NULL) < 1) {
 		err = -ENODEV;
 		goto out;
 	}
@@ -1387,6 +1404,8 @@
 	spin_unlock_bh(&iop_chan->lock);
 }
 
+MODULE_ALIAS("platform:iop-adma");
+
 static struct platform_driver iop_adma_driver = {
 	.probe		= iop_adma_probe,
 	.remove		= iop_adma_remove,
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
new file mode 100644
index 0000000..a4e4494
--- /dev/null
+++ b/drivers/dma/mv_xor.c
@@ -0,0 +1,1375 @@
+/*
+ * offload engine driver for the Marvell XOR engine
+ * Copyright (C) 2007, 2008, Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/async_tx.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/memory.h>
+#include <asm/plat-orion/mv_xor.h>
+#include "mv_xor.h"
+
+static void mv_xor_issue_pending(struct dma_chan *chan);
+
+#define to_mv_xor_chan(chan)		\
+	container_of(chan, struct mv_xor_chan, common)
+
+#define to_mv_xor_device(dev)		\
+	container_of(dev, struct mv_xor_device, common)
+
+#define to_mv_xor_slot(tx)		\
+	container_of(tx, struct mv_xor_desc_slot, async_tx)
+
+static void mv_desc_init(struct mv_xor_desc_slot *desc, unsigned long flags)
+{
+	struct mv_xor_desc *hw_desc = desc->hw_desc;
+
+	hw_desc->status = (1 << 31);
+	hw_desc->phy_next_desc = 0;
+	hw_desc->desc_command = (1 << 31);
+}
+
+static u32 mv_desc_get_dest_addr(struct mv_xor_desc_slot *desc)
+{
+	struct mv_xor_desc *hw_desc = desc->hw_desc;
+	return hw_desc->phy_dest_addr;
+}
+
+static u32 mv_desc_get_src_addr(struct mv_xor_desc_slot *desc,
+				int src_idx)
+{
+	struct mv_xor_desc *hw_desc = desc->hw_desc;
+	return hw_desc->phy_src_addr[src_idx];
+}
+
+
+static void mv_desc_set_byte_count(struct mv_xor_desc_slot *desc,
+				   u32 byte_count)
+{
+	struct mv_xor_desc *hw_desc = desc->hw_desc;
+	hw_desc->byte_count = byte_count;
+}
+
+static void mv_desc_set_next_desc(struct mv_xor_desc_slot *desc,
+				  u32 next_desc_addr)
+{
+	struct mv_xor_desc *hw_desc = desc->hw_desc;
+	BUG_ON(hw_desc->phy_next_desc);
+	hw_desc->phy_next_desc = next_desc_addr;
+}
+
+static void mv_desc_clear_next_desc(struct mv_xor_desc_slot *desc)
+{
+	struct mv_xor_desc *hw_desc = desc->hw_desc;
+	hw_desc->phy_next_desc = 0;
+}
+
+static void mv_desc_set_block_fill_val(struct mv_xor_desc_slot *desc, u32 val)
+{
+	desc->value = val;
+}
+
+static void mv_desc_set_dest_addr(struct mv_xor_desc_slot *desc,
+				  dma_addr_t addr)
+{
+	struct mv_xor_desc *hw_desc = desc->hw_desc;
+	hw_desc->phy_dest_addr = addr;
+}
+
+static int mv_chan_memset_slot_count(size_t len)
+{
+	return 1;
+}
+
+#define mv_chan_memcpy_slot_count(c) mv_chan_memset_slot_count(c)
+
+static void mv_desc_set_src_addr(struct mv_xor_desc_slot *desc,
+				 int index, dma_addr_t addr)
+{
+	struct mv_xor_desc *hw_desc = desc->hw_desc;
+	hw_desc->phy_src_addr[index] = addr;
+	if (desc->type == DMA_XOR)
+		hw_desc->desc_command |= (1 << index);
+}
+
+static u32 mv_chan_get_current_desc(struct mv_xor_chan *chan)
+{
+	return __raw_readl(XOR_CURR_DESC(chan));
+}
+
+static void mv_chan_set_next_descriptor(struct mv_xor_chan *chan,
+					u32 next_desc_addr)
+{
+	__raw_writel(next_desc_addr, XOR_NEXT_DESC(chan));
+}
+
+static void mv_chan_set_dest_pointer(struct mv_xor_chan *chan, u32 desc_addr)
+{
+	__raw_writel(desc_addr, XOR_DEST_POINTER(chan));
+}
+
+static void mv_chan_set_block_size(struct mv_xor_chan *chan, u32 block_size)
+{
+	__raw_writel(block_size, XOR_BLOCK_SIZE(chan));
+}
+
+static void mv_chan_set_value(struct mv_xor_chan *chan, u32 value)
+{
+	__raw_writel(value, XOR_INIT_VALUE_LOW(chan));
+	__raw_writel(value, XOR_INIT_VALUE_HIGH(chan));
+}
+
+static void mv_chan_unmask_interrupts(struct mv_xor_chan *chan)
+{
+	u32 val = __raw_readl(XOR_INTR_MASK(chan));
+	val |= XOR_INTR_MASK_VALUE << (chan->idx * 16);
+	__raw_writel(val, XOR_INTR_MASK(chan));
+}
+
+static u32 mv_chan_get_intr_cause(struct mv_xor_chan *chan)
+{
+	u32 intr_cause = __raw_readl(XOR_INTR_CAUSE(chan));
+	intr_cause = (intr_cause >> (chan->idx * 16)) & 0xFFFF;
+	return intr_cause;
+}
+
+static int mv_is_err_intr(u32 intr_cause)
+{
+	if (intr_cause & ((1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)))
+		return 1;
+
+	return 0;
+}
+
+static void mv_xor_device_clear_eoc_cause(struct mv_xor_chan *chan)
+{
+	u32 val = (1 << (1 + (chan->idx * 16)));
+	dev_dbg(chan->device->common.dev, "%s, val 0x%08x\n", __func__, val);
+	__raw_writel(val, XOR_INTR_CAUSE(chan));
+}
+
+static void mv_xor_device_clear_err_status(struct mv_xor_chan *chan)
+{
+	u32 val = 0xFFFF0000 >> (chan->idx * 16);
+	__raw_writel(val, XOR_INTR_CAUSE(chan));
+}
+
+static int mv_can_chain(struct mv_xor_desc_slot *desc)
+{
+	struct mv_xor_desc_slot *chain_old_tail = list_entry(
+		desc->chain_node.prev, struct mv_xor_desc_slot, chain_node);
+
+	if (chain_old_tail->type != desc->type)
+		return 0;
+	if (desc->type == DMA_MEMSET)
+		return 0;
+
+	return 1;
+}
+
+static void mv_set_mode(struct mv_xor_chan *chan,
+			       enum dma_transaction_type type)
+{
+	u32 op_mode;
+	u32 config = __raw_readl(XOR_CONFIG(chan));
+
+	switch (type) {
+	case DMA_XOR:
+		op_mode = XOR_OPERATION_MODE_XOR;
+		break;
+	case DMA_MEMCPY:
+		op_mode = XOR_OPERATION_MODE_MEMCPY;
+		break;
+	case DMA_MEMSET:
+		op_mode = XOR_OPERATION_MODE_MEMSET;
+		break;
+	default:
+		dev_printk(KERN_ERR, chan->device->common.dev,
+			   "error: unsupported operation %d.\n",
+			   type);
+		BUG();
+		return;
+	}
+
+	config &= ~0x7;
+	config |= op_mode;
+	__raw_writel(config, XOR_CONFIG(chan));
+	chan->current_type = type;
+}
+
+static void mv_chan_activate(struct mv_xor_chan *chan)
+{
+	u32 activation;
+
+	dev_dbg(chan->device->common.dev, " activate chan.\n");
+	activation = __raw_readl(XOR_ACTIVATION(chan));
+	activation |= 0x1;
+	__raw_writel(activation, XOR_ACTIVATION(chan));
+}
+
+static char mv_chan_is_busy(struct mv_xor_chan *chan)
+{
+	u32 state = __raw_readl(XOR_ACTIVATION(chan));
+
+	state = (state >> 4) & 0x3;
+
+	return (state == 1) ? 1 : 0;
+}
+
+static int mv_chan_xor_slot_count(size_t len, int src_cnt)
+{
+	return 1;
+}
+
+/**
+ * mv_xor_free_slots - flags descriptor slots for reuse
+ * @slot: Slot to free
+ * Caller must hold &mv_chan->lock while calling this function
+ */
+static void mv_xor_free_slots(struct mv_xor_chan *mv_chan,
+			      struct mv_xor_desc_slot *slot)
+{
+	dev_dbg(mv_chan->device->common.dev, "%s %d slot %p\n",
+		__func__, __LINE__, slot);
+
+	slot->slots_per_op = 0;
+
+}
+
+/*
+ * mv_xor_start_new_chain - program the engine to operate on new chain headed by
+ * sw_desc
+ * Caller must hold &mv_chan->lock while calling this function
+ */
+static void mv_xor_start_new_chain(struct mv_xor_chan *mv_chan,
+				   struct mv_xor_desc_slot *sw_desc)
+{
+	dev_dbg(mv_chan->device->common.dev, "%s %d: sw_desc %p\n",
+		__func__, __LINE__, sw_desc);
+	if (sw_desc->type != mv_chan->current_type)
+		mv_set_mode(mv_chan, sw_desc->type);
+
+	if (sw_desc->type == DMA_MEMSET) {
+		/* for memset requests we need to program the engine, no
+		 * descriptors used.
+		 */
+		struct mv_xor_desc *hw_desc = sw_desc->hw_desc;
+		mv_chan_set_dest_pointer(mv_chan, hw_desc->phy_dest_addr);
+		mv_chan_set_block_size(mv_chan, sw_desc->unmap_len);
+		mv_chan_set_value(mv_chan, sw_desc->value);
+	} else {
+		/* set the hardware chain */
+		mv_chan_set_next_descriptor(mv_chan, sw_desc->async_tx.phys);
+	}
+	mv_chan->pending += sw_desc->slot_cnt;
+	mv_xor_issue_pending(&mv_chan->common);
+}
+
+static dma_cookie_t
+mv_xor_run_tx_complete_actions(struct mv_xor_desc_slot *desc,
+	struct mv_xor_chan *mv_chan, dma_cookie_t cookie)
+{
+	BUG_ON(desc->async_tx.cookie < 0);
+
+	if (desc->async_tx.cookie > 0) {
+		cookie = desc->async_tx.cookie;
+
+		/* call the callback (must not sleep or submit new
+		 * operations to this channel)
+		 */
+		if (desc->async_tx.callback)
+			desc->async_tx.callback(
+				desc->async_tx.callback_param);
+
+		/* unmap dma addresses
+		 * (unmap_single vs unmap_page?)
+		 */
+		if (desc->group_head && desc->unmap_len) {
+			struct mv_xor_desc_slot *unmap = desc->group_head;
+			struct device *dev =
+				&mv_chan->device->pdev->dev;
+			u32 len = unmap->unmap_len;
+			enum dma_ctrl_flags flags = desc->async_tx.flags;
+			u32 src_cnt;
+			dma_addr_t addr;
+
+			if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
+				addr = mv_desc_get_dest_addr(unmap);
+				dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE);
+			}
+
+			if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
+				src_cnt = unmap->unmap_src_cnt;
+				while (src_cnt--) {
+					addr = mv_desc_get_src_addr(unmap,
+								    src_cnt);
+					dma_unmap_page(dev, addr, len,
+						       DMA_TO_DEVICE);
+				}
+			}
+			desc->group_head = NULL;
+		}
+	}
+
+	/* run dependent operations */
+	async_tx_run_dependencies(&desc->async_tx);
+
+	return cookie;
+}
+
+static int
+mv_xor_clean_completed_slots(struct mv_xor_chan *mv_chan)
+{
+	struct mv_xor_desc_slot *iter, *_iter;
+
+	dev_dbg(mv_chan->device->common.dev, "%s %d\n", __func__, __LINE__);
+	list_for_each_entry_safe(iter, _iter, &mv_chan->completed_slots,
+				 completed_node) {
+
+		if (async_tx_test_ack(&iter->async_tx)) {
+			list_del(&iter->completed_node);
+			mv_xor_free_slots(mv_chan, iter);
+		}
+	}
+	return 0;
+}
+
+static int
+mv_xor_clean_slot(struct mv_xor_desc_slot *desc,
+	struct mv_xor_chan *mv_chan)
+{
+	dev_dbg(mv_chan->device->common.dev, "%s %d: desc %p flags %d\n",
+		__func__, __LINE__, desc, desc->async_tx.flags);
+	list_del(&desc->chain_node);
+	/* the client is allowed to attach dependent operations
+	 * until 'ack' is set
+	 */
+	if (!async_tx_test_ack(&desc->async_tx)) {
+		/* move this slot to the completed_slots */
+		list_add_tail(&desc->completed_node, &mv_chan->completed_slots);
+		return 0;
+	}
+
+	mv_xor_free_slots(mv_chan, desc);
+	return 0;
+}
+
+static void __mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan)
+{
+	struct mv_xor_desc_slot *iter, *_iter;
+	dma_cookie_t cookie = 0;
+	int busy = mv_chan_is_busy(mv_chan);
+	u32 current_desc = mv_chan_get_current_desc(mv_chan);
+	int seen_current = 0;
+
+	dev_dbg(mv_chan->device->common.dev, "%s %d\n", __func__, __LINE__);
+	dev_dbg(mv_chan->device->common.dev, "current_desc %x\n", current_desc);
+	mv_xor_clean_completed_slots(mv_chan);
+
+	/* free completed slots from the chain starting with
+	 * the oldest descriptor
+	 */
+
+	list_for_each_entry_safe(iter, _iter, &mv_chan->chain,
+					chain_node) {
+		prefetch(_iter);
+		prefetch(&_iter->async_tx);
+
+		/* do not advance past the current descriptor loaded into the
+		 * hardware channel, subsequent descriptors are either in
+		 * process or have not been submitted
+		 */
+		if (seen_current)
+			break;
+
+		/* stop the search if we reach the current descriptor and the
+		 * channel is busy
+		 */
+		if (iter->async_tx.phys == current_desc) {
+			seen_current = 1;
+			if (busy)
+				break;
+		}
+
+		cookie = mv_xor_run_tx_complete_actions(iter, mv_chan, cookie);
+
+		if (mv_xor_clean_slot(iter, mv_chan))
+			break;
+	}
+
+	if ((busy == 0) && !list_empty(&mv_chan->chain)) {
+		struct mv_xor_desc_slot *chain_head;
+		chain_head = list_entry(mv_chan->chain.next,
+					struct mv_xor_desc_slot,
+					chain_node);
+
+		mv_xor_start_new_chain(mv_chan, chain_head);
+	}
+
+	if (cookie > 0)
+		mv_chan->completed_cookie = cookie;
+}
+
+static void
+mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan)
+{
+	spin_lock_bh(&mv_chan->lock);
+	__mv_xor_slot_cleanup(mv_chan);
+	spin_unlock_bh(&mv_chan->lock);
+}
+
+static void mv_xor_tasklet(unsigned long data)
+{
+	struct mv_xor_chan *chan = (struct mv_xor_chan *) data;
+	__mv_xor_slot_cleanup(chan);
+}
+
+static struct mv_xor_desc_slot *
+mv_xor_alloc_slots(struct mv_xor_chan *mv_chan, int num_slots,
+		    int slots_per_op)
+{
+	struct mv_xor_desc_slot *iter, *_iter, *alloc_start = NULL;
+	LIST_HEAD(chain);
+	int slots_found, retry = 0;
+
+	/* start search from the last allocated descrtiptor
+	 * if a contiguous allocation can not be found start searching
+	 * from the beginning of the list
+	 */
+retry:
+	slots_found = 0;
+	if (retry == 0)
+		iter = mv_chan->last_used;
+	else
+		iter = list_entry(&mv_chan->all_slots,
+			struct mv_xor_desc_slot,
+			slot_node);
+
+	list_for_each_entry_safe_continue(
+		iter, _iter, &mv_chan->all_slots, slot_node) {
+		prefetch(_iter);
+		prefetch(&_iter->async_tx);
+		if (iter->slots_per_op) {
+			/* give up after finding the first busy slot
+			 * on the second pass through the list
+			 */
+			if (retry)
+				break;
+
+			slots_found = 0;
+			continue;
+		}
+
+		/* start the allocation if the slot is correctly aligned */
+		if (!slots_found++)
+			alloc_start = iter;
+
+		if (slots_found == num_slots) {
+			struct mv_xor_desc_slot *alloc_tail = NULL;
+			struct mv_xor_desc_slot *last_used = NULL;
+			iter = alloc_start;
+			while (num_slots) {
+				int i;
+
+				/* pre-ack all but the last descriptor */
+				async_tx_ack(&iter->async_tx);
+
+				list_add_tail(&iter->chain_node, &chain);
+				alloc_tail = iter;
+				iter->async_tx.cookie = 0;
+				iter->slot_cnt = num_slots;
+				iter->xor_check_result = NULL;
+				for (i = 0; i < slots_per_op; i++) {
+					iter->slots_per_op = slots_per_op - i;
+					last_used = iter;
+					iter = list_entry(iter->slot_node.next,
+						struct mv_xor_desc_slot,
+						slot_node);
+				}
+				num_slots -= slots_per_op;
+			}
+			alloc_tail->group_head = alloc_start;
+			alloc_tail->async_tx.cookie = -EBUSY;
+			list_splice(&chain, &alloc_tail->async_tx.tx_list);
+			mv_chan->last_used = last_used;
+			mv_desc_clear_next_desc(alloc_start);
+			mv_desc_clear_next_desc(alloc_tail);
+			return alloc_tail;
+		}
+	}
+	if (!retry++)
+		goto retry;
+
+	/* try to free some slots if the allocation fails */
+	tasklet_schedule(&mv_chan->irq_tasklet);
+
+	return NULL;
+}
+
+static dma_cookie_t
+mv_desc_assign_cookie(struct mv_xor_chan *mv_chan,
+		      struct mv_xor_desc_slot *desc)
+{
+	dma_cookie_t cookie = mv_chan->common.cookie;
+
+	if (++cookie < 0)
+		cookie = 1;
+	mv_chan->common.cookie = desc->async_tx.cookie = cookie;
+	return cookie;
+}
+
+/************************ DMA engine API functions ****************************/
+static dma_cookie_t
+mv_xor_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct mv_xor_desc_slot *sw_desc = to_mv_xor_slot(tx);
+	struct mv_xor_chan *mv_chan = to_mv_xor_chan(tx->chan);
+	struct mv_xor_desc_slot *grp_start, *old_chain_tail;
+	dma_cookie_t cookie;
+	int new_hw_chain = 1;
+
+	dev_dbg(mv_chan->device->common.dev,
+		"%s sw_desc %p: async_tx %p\n",
+		__func__, sw_desc, &sw_desc->async_tx);
+
+	grp_start = sw_desc->group_head;
+
+	spin_lock_bh(&mv_chan->lock);
+	cookie = mv_desc_assign_cookie(mv_chan, sw_desc);
+
+	if (list_empty(&mv_chan->chain))
+		list_splice_init(&sw_desc->async_tx.tx_list, &mv_chan->chain);
+	else {
+		new_hw_chain = 0;
+
+		old_chain_tail = list_entry(mv_chan->chain.prev,
+					    struct mv_xor_desc_slot,
+					    chain_node);
+		list_splice_init(&grp_start->async_tx.tx_list,
+				 &old_chain_tail->chain_node);
+
+		if (!mv_can_chain(grp_start))
+			goto submit_done;
+
+		dev_dbg(mv_chan->device->common.dev, "Append to last desc %x\n",
+			old_chain_tail->async_tx.phys);
+
+		/* fix up the hardware chain */
+		mv_desc_set_next_desc(old_chain_tail, grp_start->async_tx.phys);
+
+		/* if the channel is not busy */
+		if (!mv_chan_is_busy(mv_chan)) {
+			u32 current_desc = mv_chan_get_current_desc(mv_chan);
+			/*
+			 * and the curren desc is the end of the chain before
+			 * the append, then we need to start the channel
+			 */
+			if (current_desc == old_chain_tail->async_tx.phys)
+				new_hw_chain = 1;
+		}
+	}
+
+	if (new_hw_chain)
+		mv_xor_start_new_chain(mv_chan, grp_start);
+
+submit_done:
+	spin_unlock_bh(&mv_chan->lock);
+
+	return cookie;
+}
+
+/* returns the number of allocated descriptors */
+static int mv_xor_alloc_chan_resources(struct dma_chan *chan,
+				       struct dma_client *client)
+{
+	char *hw_desc;
+	int idx;
+	struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
+	struct mv_xor_desc_slot *slot = NULL;
+	struct mv_xor_platform_data *plat_data =
+		mv_chan->device->pdev->dev.platform_data;
+	int num_descs_in_pool = plat_data->pool_size/MV_XOR_SLOT_SIZE;
+
+	/* Allocate descriptor slots */
+	idx = mv_chan->slots_allocated;
+	while (idx < num_descs_in_pool) {
+		slot = kzalloc(sizeof(*slot), GFP_KERNEL);
+		if (!slot) {
+			printk(KERN_INFO "MV XOR Channel only initialized"
+				" %d descriptor slots", idx);
+			break;
+		}
+		hw_desc = (char *) mv_chan->device->dma_desc_pool_virt;
+		slot->hw_desc = (void *) &hw_desc[idx * MV_XOR_SLOT_SIZE];
+
+		dma_async_tx_descriptor_init(&slot->async_tx, chan);
+		slot->async_tx.tx_submit = mv_xor_tx_submit;
+		INIT_LIST_HEAD(&slot->chain_node);
+		INIT_LIST_HEAD(&slot->slot_node);
+		INIT_LIST_HEAD(&slot->async_tx.tx_list);
+		hw_desc = (char *) mv_chan->device->dma_desc_pool;
+		slot->async_tx.phys =
+			(dma_addr_t) &hw_desc[idx * MV_XOR_SLOT_SIZE];
+		slot->idx = idx++;
+
+		spin_lock_bh(&mv_chan->lock);
+		mv_chan->slots_allocated = idx;
+		list_add_tail(&slot->slot_node, &mv_chan->all_slots);
+		spin_unlock_bh(&mv_chan->lock);
+	}
+
+	if (mv_chan->slots_allocated && !mv_chan->last_used)
+		mv_chan->last_used = list_entry(mv_chan->all_slots.next,
+					struct mv_xor_desc_slot,
+					slot_node);
+
+	dev_dbg(mv_chan->device->common.dev,
+		"allocated %d descriptor slots last_used: %p\n",
+		mv_chan->slots_allocated, mv_chan->last_used);
+
+	return mv_chan->slots_allocated ? : -ENOMEM;
+}
+
+static struct dma_async_tx_descriptor *
+mv_xor_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+		size_t len, unsigned long flags)
+{
+	struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
+	struct mv_xor_desc_slot *sw_desc, *grp_start;
+	int slot_cnt;
+
+	dev_dbg(mv_chan->device->common.dev,
+		"%s dest: %x src %x len: %u flags: %ld\n",
+		__func__, dest, src, len, flags);
+	if (unlikely(len < MV_XOR_MIN_BYTE_COUNT))
+		return NULL;
+
+	BUG_ON(unlikely(len > MV_XOR_MAX_BYTE_COUNT));
+
+	spin_lock_bh(&mv_chan->lock);
+	slot_cnt = mv_chan_memcpy_slot_count(len);
+	sw_desc = mv_xor_alloc_slots(mv_chan, slot_cnt, 1);
+	if (sw_desc) {
+		sw_desc->type = DMA_MEMCPY;
+		sw_desc->async_tx.flags = flags;
+		grp_start = sw_desc->group_head;
+		mv_desc_init(grp_start, flags);
+		mv_desc_set_byte_count(grp_start, len);
+		mv_desc_set_dest_addr(sw_desc->group_head, dest);
+		mv_desc_set_src_addr(grp_start, 0, src);
+		sw_desc->unmap_src_cnt = 1;
+		sw_desc->unmap_len = len;
+	}
+	spin_unlock_bh(&mv_chan->lock);
+
+	dev_dbg(mv_chan->device->common.dev,
+		"%s sw_desc %p async_tx %p\n",
+		__func__, sw_desc, sw_desc ? &sw_desc->async_tx : 0);
+
+	return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static struct dma_async_tx_descriptor *
+mv_xor_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value,
+		       size_t len, unsigned long flags)
+{
+	struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
+	struct mv_xor_desc_slot *sw_desc, *grp_start;
+	int slot_cnt;
+
+	dev_dbg(mv_chan->device->common.dev,
+		"%s dest: %x len: %u flags: %ld\n",
+		__func__, dest, len, flags);
+	if (unlikely(len < MV_XOR_MIN_BYTE_COUNT))
+		return NULL;
+
+	BUG_ON(unlikely(len > MV_XOR_MAX_BYTE_COUNT));
+
+	spin_lock_bh(&mv_chan->lock);
+	slot_cnt = mv_chan_memset_slot_count(len);
+	sw_desc = mv_xor_alloc_slots(mv_chan, slot_cnt, 1);
+	if (sw_desc) {
+		sw_desc->type = DMA_MEMSET;
+		sw_desc->async_tx.flags = flags;
+		grp_start = sw_desc->group_head;
+		mv_desc_init(grp_start, flags);
+		mv_desc_set_byte_count(grp_start, len);
+		mv_desc_set_dest_addr(sw_desc->group_head, dest);
+		mv_desc_set_block_fill_val(grp_start, value);
+		sw_desc->unmap_src_cnt = 1;
+		sw_desc->unmap_len = len;
+	}
+	spin_unlock_bh(&mv_chan->lock);
+	dev_dbg(mv_chan->device->common.dev,
+		"%s sw_desc %p async_tx %p \n",
+		__func__, sw_desc, &sw_desc->async_tx);
+	return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static struct dma_async_tx_descriptor *
+mv_xor_prep_dma_xor(struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
+		    unsigned int src_cnt, size_t len, unsigned long flags)
+{
+	struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
+	struct mv_xor_desc_slot *sw_desc, *grp_start;
+	int slot_cnt;
+
+	if (unlikely(len < MV_XOR_MIN_BYTE_COUNT))
+		return NULL;
+
+	BUG_ON(unlikely(len > MV_XOR_MAX_BYTE_COUNT));
+
+	dev_dbg(mv_chan->device->common.dev,
+		"%s src_cnt: %d len: dest %x %u flags: %ld\n",
+		__func__, src_cnt, len, dest, flags);
+
+	spin_lock_bh(&mv_chan->lock);
+	slot_cnt = mv_chan_xor_slot_count(len, src_cnt);
+	sw_desc = mv_xor_alloc_slots(mv_chan, slot_cnt, 1);
+	if (sw_desc) {
+		sw_desc->type = DMA_XOR;
+		sw_desc->async_tx.flags = flags;
+		grp_start = sw_desc->group_head;
+		mv_desc_init(grp_start, flags);
+		/* the byte count field is the same as in memcpy desc*/
+		mv_desc_set_byte_count(grp_start, len);
+		mv_desc_set_dest_addr(sw_desc->group_head, dest);
+		sw_desc->unmap_src_cnt = src_cnt;
+		sw_desc->unmap_len = len;
+		while (src_cnt--)
+			mv_desc_set_src_addr(grp_start, src_cnt, src[src_cnt]);
+	}
+	spin_unlock_bh(&mv_chan->lock);
+	dev_dbg(mv_chan->device->common.dev,
+		"%s sw_desc %p async_tx %p \n",
+		__func__, sw_desc, &sw_desc->async_tx);
+	return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static void mv_xor_free_chan_resources(struct dma_chan *chan)
+{
+	struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
+	struct mv_xor_desc_slot *iter, *_iter;
+	int in_use_descs = 0;
+
+	mv_xor_slot_cleanup(mv_chan);
+
+	spin_lock_bh(&mv_chan->lock);
+	list_for_each_entry_safe(iter, _iter, &mv_chan->chain,
+					chain_node) {
+		in_use_descs++;
+		list_del(&iter->chain_node);
+	}
+	list_for_each_entry_safe(iter, _iter, &mv_chan->completed_slots,
+				 completed_node) {
+		in_use_descs++;
+		list_del(&iter->completed_node);
+	}
+	list_for_each_entry_safe_reverse(
+		iter, _iter, &mv_chan->all_slots, slot_node) {
+		list_del(&iter->slot_node);
+		kfree(iter);
+		mv_chan->slots_allocated--;
+	}
+	mv_chan->last_used = NULL;
+
+	dev_dbg(mv_chan->device->common.dev, "%s slots_allocated %d\n",
+		__func__, mv_chan->slots_allocated);
+	spin_unlock_bh(&mv_chan->lock);
+
+	if (in_use_descs)
+		dev_err(mv_chan->device->common.dev,
+			"freeing %d in use descriptors!\n", in_use_descs);
+}
+
+/**
+ * mv_xor_is_complete - poll the status of an XOR transaction
+ * @chan: XOR channel handle
+ * @cookie: XOR transaction identifier
+ */
+static enum dma_status mv_xor_is_complete(struct dma_chan *chan,
+					  dma_cookie_t cookie,
+					  dma_cookie_t *done,
+					  dma_cookie_t *used)
+{
+	struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
+	dma_cookie_t last_used;
+	dma_cookie_t last_complete;
+	enum dma_status ret;
+
+	last_used = chan->cookie;
+	last_complete = mv_chan->completed_cookie;
+	mv_chan->is_complete_cookie = cookie;
+	if (done)
+		*done = last_complete;
+	if (used)
+		*used = last_used;
+
+	ret = dma_async_is_complete(cookie, last_complete, last_used);
+	if (ret == DMA_SUCCESS) {
+		mv_xor_clean_completed_slots(mv_chan);
+		return ret;
+	}
+	mv_xor_slot_cleanup(mv_chan);
+
+	last_used = chan->cookie;
+	last_complete = mv_chan->completed_cookie;
+
+	if (done)
+		*done = last_complete;
+	if (used)
+		*used = last_used;
+
+	return dma_async_is_complete(cookie, last_complete, last_used);
+}
+
+static void mv_dump_xor_regs(struct mv_xor_chan *chan)
+{
+	u32 val;
+
+	val = __raw_readl(XOR_CONFIG(chan));
+	dev_printk(KERN_ERR, chan->device->common.dev,
+		   "config       0x%08x.\n", val);
+
+	val = __raw_readl(XOR_ACTIVATION(chan));
+	dev_printk(KERN_ERR, chan->device->common.dev,
+		   "activation   0x%08x.\n", val);
+
+	val = __raw_readl(XOR_INTR_CAUSE(chan));
+	dev_printk(KERN_ERR, chan->device->common.dev,
+		   "intr cause   0x%08x.\n", val);
+
+	val = __raw_readl(XOR_INTR_MASK(chan));
+	dev_printk(KERN_ERR, chan->device->common.dev,
+		   "intr mask    0x%08x.\n", val);
+
+	val = __raw_readl(XOR_ERROR_CAUSE(chan));
+	dev_printk(KERN_ERR, chan->device->common.dev,
+		   "error cause  0x%08x.\n", val);
+
+	val = __raw_readl(XOR_ERROR_ADDR(chan));
+	dev_printk(KERN_ERR, chan->device->common.dev,
+		   "error addr   0x%08x.\n", val);
+}
+
+static void mv_xor_err_interrupt_handler(struct mv_xor_chan *chan,
+					 u32 intr_cause)
+{
+	if (intr_cause & (1 << 4)) {
+	     dev_dbg(chan->device->common.dev,
+		     "ignore this error\n");
+	     return;
+	}
+
+	dev_printk(KERN_ERR, chan->device->common.dev,
+		   "error on chan %d. intr cause 0x%08x.\n",
+		   chan->idx, intr_cause);
+
+	mv_dump_xor_regs(chan);
+	BUG();
+}
+
+static irqreturn_t mv_xor_interrupt_handler(int irq, void *data)
+{
+	struct mv_xor_chan *chan = data;
+	u32 intr_cause = mv_chan_get_intr_cause(chan);
+
+	dev_dbg(chan->device->common.dev, "intr cause %x\n", intr_cause);
+
+	if (mv_is_err_intr(intr_cause))
+		mv_xor_err_interrupt_handler(chan, intr_cause);
+
+	tasklet_schedule(&chan->irq_tasklet);
+
+	mv_xor_device_clear_eoc_cause(chan);
+
+	return IRQ_HANDLED;
+}
+
+static void mv_xor_issue_pending(struct dma_chan *chan)
+{
+	struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
+
+	if (mv_chan->pending >= MV_XOR_THRESHOLD) {
+		mv_chan->pending = 0;
+		mv_chan_activate(mv_chan);
+	}
+}
+
+/*
+ * Perform a transaction to verify the HW works.
+ */
+#define MV_XOR_TEST_SIZE 2000
+
+static int __devinit mv_xor_memcpy_self_test(struct mv_xor_device *device)
+{
+	int i;
+	void *src, *dest;
+	dma_addr_t src_dma, dest_dma;
+	struct dma_chan *dma_chan;
+	dma_cookie_t cookie;
+	struct dma_async_tx_descriptor *tx;
+	int err = 0;
+	struct mv_xor_chan *mv_chan;
+
+	src = kmalloc(sizeof(u8) * MV_XOR_TEST_SIZE, GFP_KERNEL);
+	if (!src)
+		return -ENOMEM;
+
+	dest = kzalloc(sizeof(u8) * MV_XOR_TEST_SIZE, GFP_KERNEL);
+	if (!dest) {
+		kfree(src);
+		return -ENOMEM;
+	}
+
+	/* Fill in src buffer */
+	for (i = 0; i < MV_XOR_TEST_SIZE; i++)
+		((u8 *) src)[i] = (u8)i;
+
+	/* Start copy, using first DMA channel */
+	dma_chan = container_of(device->common.channels.next,
+				struct dma_chan,
+				device_node);
+	if (mv_xor_alloc_chan_resources(dma_chan, NULL) < 1) {
+		err = -ENODEV;
+		goto out;
+	}
+
+	dest_dma = dma_map_single(dma_chan->device->dev, dest,
+				  MV_XOR_TEST_SIZE, DMA_FROM_DEVICE);
+
+	src_dma = dma_map_single(dma_chan->device->dev, src,
+				 MV_XOR_TEST_SIZE, DMA_TO_DEVICE);
+
+	tx = mv_xor_prep_dma_memcpy(dma_chan, dest_dma, src_dma,
+				    MV_XOR_TEST_SIZE, 0);
+	cookie = mv_xor_tx_submit(tx);
+	mv_xor_issue_pending(dma_chan);
+	async_tx_ack(tx);
+	msleep(1);
+
+	if (mv_xor_is_complete(dma_chan, cookie, NULL, NULL) !=
+	    DMA_SUCCESS) {
+		dev_printk(KERN_ERR, dma_chan->device->dev,
+			   "Self-test copy timed out, disabling\n");
+		err = -ENODEV;
+		goto free_resources;
+	}
+
+	mv_chan = to_mv_xor_chan(dma_chan);
+	dma_sync_single_for_cpu(&mv_chan->device->pdev->dev, dest_dma,
+				MV_XOR_TEST_SIZE, DMA_FROM_DEVICE);
+	if (memcmp(src, dest, MV_XOR_TEST_SIZE)) {
+		dev_printk(KERN_ERR, dma_chan->device->dev,
+			   "Self-test copy failed compare, disabling\n");
+		err = -ENODEV;
+		goto free_resources;
+	}
+
+free_resources:
+	mv_xor_free_chan_resources(dma_chan);
+out:
+	kfree(src);
+	kfree(dest);
+	return err;
+}
+
+#define MV_XOR_NUM_SRC_TEST 4 /* must be <= 15 */
+static int __devinit
+mv_xor_xor_self_test(struct mv_xor_device *device)
+{
+	int i, src_idx;
+	struct page *dest;
+	struct page *xor_srcs[MV_XOR_NUM_SRC_TEST];
+	dma_addr_t dma_srcs[MV_XOR_NUM_SRC_TEST];
+	dma_addr_t dest_dma;
+	struct dma_async_tx_descriptor *tx;
+	struct dma_chan *dma_chan;
+	dma_cookie_t cookie;
+	u8 cmp_byte = 0;
+	u32 cmp_word;
+	int err = 0;
+	struct mv_xor_chan *mv_chan;
+
+	for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) {
+		xor_srcs[src_idx] = alloc_page(GFP_KERNEL);
+		if (!xor_srcs[src_idx])
+			while (src_idx--) {
+				__free_page(xor_srcs[src_idx]);
+				return -ENOMEM;
+			}
+	}
+
+	dest = alloc_page(GFP_KERNEL);
+	if (!dest)
+		while (src_idx--) {
+			__free_page(xor_srcs[src_idx]);
+			return -ENOMEM;
+		}
+
+	/* Fill in src buffers */
+	for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) {
+		u8 *ptr = page_address(xor_srcs[src_idx]);
+		for (i = 0; i < PAGE_SIZE; i++)
+			ptr[i] = (1 << src_idx);
+	}
+
+	for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++)
+		cmp_byte ^= (u8) (1 << src_idx);
+
+	cmp_word = (cmp_byte << 24) | (cmp_byte << 16) |
+		(cmp_byte << 8) | cmp_byte;
+
+	memset(page_address(dest), 0, PAGE_SIZE);
+
+	dma_chan = container_of(device->common.channels.next,
+				struct dma_chan,
+				device_node);
+	if (mv_xor_alloc_chan_resources(dma_chan, NULL) < 1) {
+		err = -ENODEV;
+		goto out;
+	}
+
+	/* test xor */
+	dest_dma = dma_map_page(dma_chan->device->dev, dest, 0, PAGE_SIZE,
+				DMA_FROM_DEVICE);
+
+	for (i = 0; i < MV_XOR_NUM_SRC_TEST; i++)
+		dma_srcs[i] = dma_map_page(dma_chan->device->dev, xor_srcs[i],
+					   0, PAGE_SIZE, DMA_TO_DEVICE);
+
+	tx = mv_xor_prep_dma_xor(dma_chan, dest_dma, dma_srcs,
+				 MV_XOR_NUM_SRC_TEST, PAGE_SIZE, 0);
+
+	cookie = mv_xor_tx_submit(tx);
+	mv_xor_issue_pending(dma_chan);
+	async_tx_ack(tx);
+	msleep(8);
+
+	if (mv_xor_is_complete(dma_chan, cookie, NULL, NULL) !=
+	    DMA_SUCCESS) {
+		dev_printk(KERN_ERR, dma_chan->device->dev,
+			   "Self-test xor timed out, disabling\n");
+		err = -ENODEV;
+		goto free_resources;
+	}
+
+	mv_chan = to_mv_xor_chan(dma_chan);
+	dma_sync_single_for_cpu(&mv_chan->device->pdev->dev, dest_dma,
+				PAGE_SIZE, DMA_FROM_DEVICE);
+	for (i = 0; i < (PAGE_SIZE / sizeof(u32)); i++) {
+		u32 *ptr = page_address(dest);
+		if (ptr[i] != cmp_word) {
+			dev_printk(KERN_ERR, dma_chan->device->dev,
+				   "Self-test xor failed compare, disabling."
+				   " index %d, data %x, expected %x\n", i,
+				   ptr[i], cmp_word);
+			err = -ENODEV;
+			goto free_resources;
+		}
+	}
+
+free_resources:
+	mv_xor_free_chan_resources(dma_chan);
+out:
+	src_idx = MV_XOR_NUM_SRC_TEST;
+	while (src_idx--)
+		__free_page(xor_srcs[src_idx]);
+	__free_page(dest);
+	return err;
+}
+
+static int __devexit mv_xor_remove(struct platform_device *dev)
+{
+	struct mv_xor_device *device = platform_get_drvdata(dev);
+	struct dma_chan *chan, *_chan;
+	struct mv_xor_chan *mv_chan;
+	struct mv_xor_platform_data *plat_data = dev->dev.platform_data;
+
+	dma_async_device_unregister(&device->common);
+
+	dma_free_coherent(&dev->dev, plat_data->pool_size,
+			device->dma_desc_pool_virt, device->dma_desc_pool);
+
+	list_for_each_entry_safe(chan, _chan, &device->common.channels,
+				device_node) {
+		mv_chan = to_mv_xor_chan(chan);
+		list_del(&chan->device_node);
+	}
+
+	return 0;
+}
+
+static int __devinit mv_xor_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	int irq;
+	struct mv_xor_device *adev;
+	struct mv_xor_chan *mv_chan;
+	struct dma_device *dma_dev;
+	struct mv_xor_platform_data *plat_data = pdev->dev.platform_data;
+
+
+	adev = devm_kzalloc(&pdev->dev, sizeof(*adev), GFP_KERNEL);
+	if (!adev)
+		return -ENOMEM;
+
+	dma_dev = &adev->common;
+
+	/* allocate coherent memory for hardware descriptors
+	 * note: writecombine gives slightly better performance, but
+	 * requires that we explicitly flush the writes
+	 */
+	adev->dma_desc_pool_virt = dma_alloc_writecombine(&pdev->dev,
+							  plat_data->pool_size,
+							  &adev->dma_desc_pool,
+							  GFP_KERNEL);
+	if (!adev->dma_desc_pool_virt)
+		return -ENOMEM;
+
+	adev->id = plat_data->hw_id;
+
+	/* discover transaction capabilites from the platform data */
+	dma_dev->cap_mask = plat_data->cap_mask;
+	adev->pdev = pdev;
+	platform_set_drvdata(pdev, adev);
+
+	adev->shared = platform_get_drvdata(plat_data->shared);
+
+	INIT_LIST_HEAD(&dma_dev->channels);
+
+	/* set base routines */
+	dma_dev->device_alloc_chan_resources = mv_xor_alloc_chan_resources;
+	dma_dev->device_free_chan_resources = mv_xor_free_chan_resources;
+	dma_dev->device_is_tx_complete = mv_xor_is_complete;
+	dma_dev->device_issue_pending = mv_xor_issue_pending;
+	dma_dev->dev = &pdev->dev;
+
+	/* set prep routines based on capability */
+	if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask))
+		dma_dev->device_prep_dma_memcpy = mv_xor_prep_dma_memcpy;
+	if (dma_has_cap(DMA_MEMSET, dma_dev->cap_mask))
+		dma_dev->device_prep_dma_memset = mv_xor_prep_dma_memset;
+	if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
+		dma_dev->max_xor = 8;                  ;
+		dma_dev->device_prep_dma_xor = mv_xor_prep_dma_xor;
+	}
+
+	mv_chan = devm_kzalloc(&pdev->dev, sizeof(*mv_chan), GFP_KERNEL);
+	if (!mv_chan) {
+		ret = -ENOMEM;
+		goto err_free_dma;
+	}
+	mv_chan->device = adev;
+	mv_chan->idx = plat_data->hw_id;
+	mv_chan->mmr_base = adev->shared->xor_base;
+
+	if (!mv_chan->mmr_base) {
+		ret = -ENOMEM;
+		goto err_free_dma;
+	}
+	tasklet_init(&mv_chan->irq_tasklet, mv_xor_tasklet, (unsigned long)
+		     mv_chan);
+
+	/* clear errors before enabling interrupts */
+	mv_xor_device_clear_err_status(mv_chan);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		ret = irq;
+		goto err_free_dma;
+	}
+	ret = devm_request_irq(&pdev->dev, irq,
+			       mv_xor_interrupt_handler,
+			       0, dev_name(&pdev->dev), mv_chan);
+	if (ret)
+		goto err_free_dma;
+
+	mv_chan_unmask_interrupts(mv_chan);
+
+	mv_set_mode(mv_chan, DMA_MEMCPY);
+
+	spin_lock_init(&mv_chan->lock);
+	INIT_LIST_HEAD(&mv_chan->chain);
+	INIT_LIST_HEAD(&mv_chan->completed_slots);
+	INIT_LIST_HEAD(&mv_chan->all_slots);
+	INIT_RCU_HEAD(&mv_chan->common.rcu);
+	mv_chan->common.device = dma_dev;
+
+	list_add_tail(&mv_chan->common.device_node, &dma_dev->channels);
+
+	if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) {
+		ret = mv_xor_memcpy_self_test(adev);
+		dev_dbg(&pdev->dev, "memcpy self test returned %d\n", ret);
+		if (ret)
+			goto err_free_dma;
+	}
+
+	if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
+		ret = mv_xor_xor_self_test(adev);
+		dev_dbg(&pdev->dev, "xor self test returned %d\n", ret);
+		if (ret)
+			goto err_free_dma;
+	}
+
+	dev_printk(KERN_INFO, &pdev->dev, "Marvell XOR: "
+	  "( %s%s%s%s)\n",
+	  dma_has_cap(DMA_XOR, dma_dev->cap_mask) ? "xor " : "",
+	  dma_has_cap(DMA_MEMSET, dma_dev->cap_mask)  ? "fill " : "",
+	  dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask) ? "cpy " : "",
+	  dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask) ? "intr " : "");
+
+	dma_async_device_register(dma_dev);
+	goto out;
+
+ err_free_dma:
+	dma_free_coherent(&adev->pdev->dev, plat_data->pool_size,
+			adev->dma_desc_pool_virt, adev->dma_desc_pool);
+ out:
+	return ret;
+}
+
+static void
+mv_xor_conf_mbus_windows(struct mv_xor_shared_private *msp,
+			 struct mbus_dram_target_info *dram)
+{
+	void __iomem *base = msp->xor_base;
+	u32 win_enable = 0;
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		writel(0, base + WINDOW_BASE(i));
+		writel(0, base + WINDOW_SIZE(i));
+		if (i < 4)
+			writel(0, base + WINDOW_REMAP_HIGH(i));
+	}
+
+	for (i = 0; i < dram->num_cs; i++) {
+		struct mbus_dram_window *cs = dram->cs + i;
+
+		writel((cs->base & 0xffff0000) |
+		       (cs->mbus_attr << 8) |
+		       dram->mbus_dram_target_id, base + WINDOW_BASE(i));
+		writel((cs->size - 1) & 0xffff0000, base + WINDOW_SIZE(i));
+
+		win_enable |= (1 << i);
+		win_enable |= 3 << (16 + (2 * i));
+	}
+
+	writel(win_enable, base + WINDOW_BAR_ENABLE(0));
+	writel(win_enable, base + WINDOW_BAR_ENABLE(1));
+}
+
+static struct platform_driver mv_xor_driver = {
+	.probe		= mv_xor_probe,
+	.remove		= mv_xor_remove,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= MV_XOR_NAME,
+	},
+};
+
+static int mv_xor_shared_probe(struct platform_device *pdev)
+{
+	struct mv_xor_platform_shared_data *msd = pdev->dev.platform_data;
+	struct mv_xor_shared_private *msp;
+	struct resource *res;
+
+	dev_printk(KERN_NOTICE, &pdev->dev, "Marvell shared XOR driver\n");
+
+	msp = devm_kzalloc(&pdev->dev, sizeof(*msp), GFP_KERNEL);
+	if (!msp)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	msp->xor_base = devm_ioremap(&pdev->dev, res->start,
+				     res->end - res->start + 1);
+	if (!msp->xor_base)
+		return -EBUSY;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res)
+		return -ENODEV;
+
+	msp->xor_high_base = devm_ioremap(&pdev->dev, res->start,
+					  res->end - res->start + 1);
+	if (!msp->xor_high_base)
+		return -EBUSY;
+
+	platform_set_drvdata(pdev, msp);
+
+	/*
+	 * (Re-)program MBUS remapping windows if we are asked to.
+	 */
+	if (msd != NULL && msd->dram != NULL)
+		mv_xor_conf_mbus_windows(msp, msd->dram);
+
+	return 0;
+}
+
+static int mv_xor_shared_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct platform_driver mv_xor_shared_driver = {
+	.probe		= mv_xor_shared_probe,
+	.remove		= mv_xor_shared_remove,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= MV_XOR_SHARED_NAME,
+	},
+};
+
+
+static int __init mv_xor_init(void)
+{
+	int rc;
+
+	rc = platform_driver_register(&mv_xor_shared_driver);
+	if (!rc) {
+		rc = platform_driver_register(&mv_xor_driver);
+		if (rc)
+			platform_driver_unregister(&mv_xor_shared_driver);
+	}
+	return rc;
+}
+module_init(mv_xor_init);
+
+/* it's currently unsafe to unload this module */
+#if 0
+static void __exit mv_xor_exit(void)
+{
+	platform_driver_unregister(&mv_xor_driver);
+	platform_driver_unregister(&mv_xor_shared_driver);
+	return;
+}
+
+module_exit(mv_xor_exit);
+#endif
+
+MODULE_AUTHOR("Saeed Bishara <saeed@marvell.com>");
+MODULE_DESCRIPTION("DMA engine driver for Marvell's XOR engine");
+MODULE_LICENSE("GPL");
diff --git a/drivers/dma/mv_xor.h b/drivers/dma/mv_xor.h
new file mode 100644
index 0000000..06cafe1e
--- /dev/null
+++ b/drivers/dma/mv_xor.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2007, 2008, Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MV_XOR_H
+#define MV_XOR_H
+
+#include <linux/types.h>
+#include <linux/io.h>
+#include <linux/dmaengine.h>
+#include <linux/interrupt.h>
+
+#define USE_TIMER
+#define MV_XOR_SLOT_SIZE		64
+#define MV_XOR_THRESHOLD		1
+
+#define XOR_OPERATION_MODE_XOR		0
+#define XOR_OPERATION_MODE_MEMCPY	2
+#define XOR_OPERATION_MODE_MEMSET	4
+
+#define XOR_CURR_DESC(chan)	(chan->mmr_base + 0x210 + (chan->idx * 4))
+#define XOR_NEXT_DESC(chan)	(chan->mmr_base + 0x200 + (chan->idx * 4))
+#define XOR_BYTE_COUNT(chan)	(chan->mmr_base + 0x220 + (chan->idx * 4))
+#define XOR_DEST_POINTER(chan)	(chan->mmr_base + 0x2B0 + (chan->idx * 4))
+#define XOR_BLOCK_SIZE(chan)	(chan->mmr_base + 0x2C0 + (chan->idx * 4))
+#define XOR_INIT_VALUE_LOW(chan)	(chan->mmr_base + 0x2E0)
+#define XOR_INIT_VALUE_HIGH(chan)	(chan->mmr_base + 0x2E4)
+
+#define XOR_CONFIG(chan)	(chan->mmr_base + 0x10 + (chan->idx * 4))
+#define XOR_ACTIVATION(chan)	(chan->mmr_base + 0x20 + (chan->idx * 4))
+#define XOR_INTR_CAUSE(chan)	(chan->mmr_base + 0x30)
+#define XOR_INTR_MASK(chan)	(chan->mmr_base + 0x40)
+#define XOR_ERROR_CAUSE(chan)	(chan->mmr_base + 0x50)
+#define XOR_ERROR_ADDR(chan)	(chan->mmr_base + 0x60)
+#define XOR_INTR_MASK_VALUE	0x3F5
+
+#define WINDOW_BASE(w)		(0x250 + ((w) << 2))
+#define WINDOW_SIZE(w)		(0x270 + ((w) << 2))
+#define WINDOW_REMAP_HIGH(w)	(0x290 + ((w) << 2))
+#define WINDOW_BAR_ENABLE(chan)	(0x240 + ((chan) << 2))
+
+struct mv_xor_shared_private {
+	void __iomem	*xor_base;
+	void __iomem	*xor_high_base;
+};
+
+
+/**
+ * struct mv_xor_device - internal representation of a XOR device
+ * @pdev: Platform device
+ * @id: HW XOR Device selector
+ * @dma_desc_pool: base of DMA descriptor region (DMA address)
+ * @dma_desc_pool_virt: base of DMA descriptor region (CPU address)
+ * @common: embedded struct dma_device
+ */
+struct mv_xor_device {
+	struct platform_device		*pdev;
+	int				id;
+	dma_addr_t			dma_desc_pool;
+	void				*dma_desc_pool_virt;
+	struct dma_device		common;
+	struct mv_xor_shared_private	*shared;
+};
+
+/**
+ * struct mv_xor_chan - internal representation of a XOR channel
+ * @pending: allows batching of hardware operations
+ * @completed_cookie: identifier for the most recently completed operation
+ * @lock: serializes enqueue/dequeue operations to the descriptors pool
+ * @mmr_base: memory mapped register base
+ * @idx: the index of the xor channel
+ * @chain: device chain view of the descriptors
+ * @completed_slots: slots completed by HW but still need to be acked
+ * @device: parent device
+ * @common: common dmaengine channel object members
+ * @last_used: place holder for allocation to continue from where it left off
+ * @all_slots: complete domain of slots usable by the channel
+ * @slots_allocated: records the actual size of the descriptor slot pool
+ * @irq_tasklet: bottom half where mv_xor_slot_cleanup runs
+ */
+struct mv_xor_chan {
+	int			pending;
+	dma_cookie_t		completed_cookie;
+	spinlock_t		lock; /* protects the descriptor slot pool */
+	void __iomem		*mmr_base;
+	unsigned int		idx;
+	enum dma_transaction_type	current_type;
+	struct list_head	chain;
+	struct list_head	completed_slots;
+	struct mv_xor_device	*device;
+	struct dma_chan		common;
+	struct mv_xor_desc_slot	*last_used;
+	struct list_head	all_slots;
+	int			slots_allocated;
+	struct tasklet_struct	irq_tasklet;
+#ifdef USE_TIMER
+	unsigned long		cleanup_time;
+	u32			current_on_last_cleanup;
+	dma_cookie_t		is_complete_cookie;
+#endif
+};
+
+/**
+ * struct mv_xor_desc_slot - software descriptor
+ * @slot_node: node on the mv_xor_chan.all_slots list
+ * @chain_node: node on the mv_xor_chan.chain list
+ * @completed_node: node on the mv_xor_chan.completed_slots list
+ * @hw_desc: virtual address of the hardware descriptor chain
+ * @phys: hardware address of the hardware descriptor chain
+ * @group_head: first operation in a transaction
+ * @slot_cnt: total slots used in an transaction (group of operations)
+ * @slots_per_op: number of slots per operation
+ * @idx: pool index
+ * @unmap_src_cnt: number of xor sources
+ * @unmap_len: transaction bytecount
+ * @async_tx: support for the async_tx api
+ * @group_list: list of slots that make up a multi-descriptor transaction
+ *	for example transfer lengths larger than the supported hw max
+ * @xor_check_result: result of zero sum
+ * @crc32_result: result crc calculation
+ */
+struct mv_xor_desc_slot {
+	struct list_head	slot_node;
+	struct list_head	chain_node;
+	struct list_head	completed_node;
+	enum dma_transaction_type	type;
+	void			*hw_desc;
+	struct mv_xor_desc_slot	*group_head;
+	u16			slot_cnt;
+	u16			slots_per_op;
+	u16			idx;
+	u16			unmap_src_cnt;
+	u32			value;
+	size_t			unmap_len;
+	struct dma_async_tx_descriptor	async_tx;
+	union {
+		u32		*xor_check_result;
+		u32		*crc32_result;
+	};
+#ifdef USE_TIMER
+	unsigned long		arrival_time;
+	struct timer_list	timeout;
+#endif
+};
+
+/* This structure describes XOR descriptor size 64bytes	*/
+struct mv_xor_desc {
+	u32 status;		/* descriptor execution status */
+	u32 crc32_result;	/* result of CRC-32 calculation */
+	u32 desc_command;	/* type of operation to be carried out */
+	u32 phy_next_desc;	/* next descriptor address pointer */
+	u32 byte_count;		/* size of src/dst blocks in bytes */
+	u32 phy_dest_addr;	/* destination block address */
+	u32 phy_src_addr[8];	/* source block addresses */
+	u32 reserved0;
+	u32 reserved1;
+};
+
+#define to_mv_sw_desc(addr_hw_desc)		\
+	container_of(addr_hw_desc, struct mv_xor_desc_slot, hw_desc)
+
+#define mv_hw_desc_slot_idx(hw_desc, idx)	\
+	((void *)(((unsigned long)hw_desc) + ((idx) << 5)))
+
+#define MV_XOR_MIN_BYTE_COUNT	(128)
+#define XOR_MAX_BYTE_COUNT	((16 * 1024 * 1024) - 1)
+#define MV_XOR_MAX_BYTE_COUNT	XOR_MAX_BYTE_COUNT
+
+
+#endif
diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c
index b54112f..0e024fe 100644
--- a/drivers/edac/cell_edac.c
+++ b/drivers/edac/cell_edac.c
@@ -33,7 +33,7 @@
 {
 	struct cell_edac_priv		*priv = mci->pvt_info;
 	struct csrow_info		*csrow = &mci->csrows[0];
-	unsigned long			address, pfn, offset;
+	unsigned long			address, pfn, offset, syndrome;
 
 	dev_dbg(mci->dev, "ECC CE err on node %d, channel %d, ar = 0x%016lx\n",
 		priv->node, chan, ar);
@@ -44,10 +44,11 @@
 		address = (address << 1) | chan;
 	pfn = address >> PAGE_SHIFT;
 	offset = address & ~PAGE_MASK;
+	syndrome = (ar & 0x000000001fe00000ul) >> 21;
 
 	/* TODO: Decoding of the error addresss */
 	edac_mc_handle_ce(mci, csrow->first_page + pfn, offset,
-			  0, 0, chan, "");
+			  syndrome, 0, chan, "");
 }
 
 static void cell_edac_count_ue(struct mem_ctl_info *mci, int chan, u64 ar)
diff --git a/drivers/eisa/Makefile b/drivers/eisa/Makefile
index 70abf93f..5369ce9 100644
--- a/drivers/eisa/Makefile
+++ b/drivers/eisa/Makefile
@@ -9,7 +9,7 @@
 
 
 # Ugly hack to get DEVICE_NAME_SIZE value...
-DEVICE_NAME_SIZE =$(shell awk '$$1=="\#define" && $$2=="DEVICE_NAME_SIZE" {print $$3-1}' $(srctree)/include/linux/device.h)
+DEVICE_NAME_SIZE = 50
 
 $(obj)/eisa-bus.o: $(obj)/devlist.h
 
diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c
index 65dcf04..c950bf8 100644
--- a/drivers/eisa/eisa-bus.c
+++ b/drivers/eisa/eisa-bus.c
@@ -22,7 +22,7 @@
 
 struct eisa_device_info {
 	struct eisa_device_id id;
-	char name[DEVICE_NAME_SIZE];
+	char name[50];
 };
 
 #ifdef CONFIG_EISA_NAMES
@@ -63,7 +63,7 @@
 		if (!strcmp (edev->id.sig, eisa_table[i].id.sig)) {
 			strlcpy (edev->pretty_name,
 				 eisa_table[i].name,
-				 DEVICE_NAME_SIZE);
+				 sizeof(edev->pretty_name));
 			return;
 		}
 	}
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 008c38b..fced190 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -45,7 +45,7 @@
 	  will be called pca953x.
 
 config GPIO_PCF857X
-	tristate "PCF857x, PCA857x, and PCA967x I2C GPIO expanders"
+	tristate "PCF857x, PCA{85,96}7x, and MAX732[89] I2C GPIO expanders"
 	depends on I2C
 	help
 	  Say yes here to provide access to most "quasi-bidirectional" I2C
@@ -54,7 +54,8 @@
 	  some of them.  Compatible models include:
 
 	  8 bits:   pcf8574, pcf8574a, pca8574, pca8574a,
-	            pca9670, pca9672, pca9674, pca9674a
+	            pca9670, pca9672, pca9674, pca9674a,
+	  	    max7328, max7329
 
 	  16 bits:  pcf8575, pcf8575c, pca8575,
 	            pca9671, pca9673, pca9675
@@ -69,6 +70,12 @@
 
 comment "SPI GPIO expanders:"
 
+config GPIO_MAX7301
+	tristate "Maxim MAX7301 GPIO expander"
+	depends on SPI_MASTER
+	help
+	  gpio driver for Maxim MAX7301 SPI GPIO expander.
+
 config GPIO_MCP23S08
 	tristate "Microchip MCP23S08 I/O expander"
 	depends on SPI_MASTER
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index fdde992..16e796d 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_HAVE_GPIO_LIB)	+= gpiolib.o
 
+obj-$(CONFIG_GPIO_MAX7301)	+= max7301.o
 obj-$(CONFIG_GPIO_MCP23S08)	+= mcp23s08.o
 obj-$(CONFIG_GPIO_PCA953X)	+= pca953x.o
 obj-$(CONFIG_GPIO_PCF857X)	+= pcf857x.o
diff --git a/drivers/gpio/max7301.c b/drivers/gpio/max7301.c
new file mode 100644
index 0000000..39c795a
--- /dev/null
+++ b/drivers/gpio/max7301.c
@@ -0,0 +1,339 @@
+/**
+ * drivers/gpio/max7301.c
+ *
+ * Copyright (C) 2006 Juergen Beisert, Pengutronix
+ * Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix
+ *
+ * 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 Maxim's MAX7301 device is an SPI driven GPIO expander. There are
+ * 28 GPIOs. 8 of them can trigger an interrupt. See datasheet for more
+ * details
+ * Note:
+ * - DIN must be stable at the rising edge of clock.
+ * - when writing:
+ *   - always clock in 16 clocks at once
+ *   - at DIN: D15 first, D0 last
+ *   - D0..D7 = databyte, D8..D14 = commandbyte
+ *   - D15 = low -> write command
+ * - when reading
+ *   - always clock in 16 clocks at once
+ *   - at DIN: D15 first, D0 last
+ *   - D0..D7 = dummy, D8..D14 = register address
+ *   - D15 = high -> read command
+ *   - raise CS and assert it again
+ *   - always clock in 16 clocks at once
+ *   - at DOUT: D15 first, D0 last
+ *   - D0..D7 contains the data from the first cycle
+ *
+ * The driver exports a standard gpiochip interface
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/max7301.h>
+#include <linux/gpio.h>
+
+#define DRIVER_NAME "max7301"
+
+/*
+ * Pin configurations, see MAX7301 datasheet page 6
+ */
+#define PIN_CONFIG_MASK 0x03
+#define PIN_CONFIG_IN_PULLUP 0x03
+#define PIN_CONFIG_IN_WO_PULLUP 0x02
+#define PIN_CONFIG_OUT 0x01
+
+#define PIN_NUMBER 28
+
+
+/*
+ * Some registers must be read back to modify.
+ * To save time we cache them here in memory
+ */
+struct max7301 {
+	struct mutex	lock;
+	u8		port_config[8];	/* field 0 is unused */
+	u32		out_level;	/* cached output levels */
+	struct gpio_chip chip;
+	struct spi_device *spi;
+};
+
+/**
+ * max7301_write - Write a new register content
+ * @spi: The SPI device
+ * @reg: Register offset
+ * @val: Value to write
+ *
+ * A write to the MAX7301 means one message with one transfer
+ *
+ * Returns 0 if successful or a negative value on error
+ */
+static int max7301_write(struct spi_device *spi, unsigned int reg, unsigned int val)
+{
+	u16 word = ((reg & 0x7F) << 8) | (val & 0xFF);
+	return spi_write(spi, (const u8 *)&word, sizeof(word));
+}
+
+/**
+ * max7301_read - Read back register content
+ * @spi: The SPI device
+ * @reg: Register offset
+ *
+ * A read from the MAX7301 means two transfers; here, one message each
+ *
+ * Returns positive 8 bit value from device if successful or a
+ * negative value on error
+ */
+static int max7301_read(struct spi_device *spi, unsigned int reg)
+{
+	int ret;
+	u16 word;
+
+	word = 0x8000 | (reg << 8);
+	ret = spi_write(spi, (const u8 *)&word, sizeof(word));
+	if (ret)
+		return ret;
+	/*
+	 * This relies on the fact, that a transfer with NULL tx_buf shifts out
+	 * zero bytes (=NOOP for MAX7301)
+	 */
+	ret = spi_read(spi, (u8 *)&word, sizeof(word));
+	if (ret)
+		return ret;
+	return word & 0xff;
+}
+
+static int max7301_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct max7301 *ts = container_of(chip, struct max7301, chip);
+	u8 *config;
+	int ret;
+
+	/* First 4 pins are unused in the controller */
+	offset += 4;
+
+	config = &ts->port_config[offset >> 2];
+
+	mutex_lock(&ts->lock);
+
+	/* Standard GPIO API doesn't support pull-ups, has to be extended.
+	 * Hard-coding no pollup for now. */
+	*config = (*config & ~(3 << (offset & 3))) | (1 << (offset & 3));
+
+	ret = max7301_write(ts->spi, 0x08 + (offset >> 2), *config);
+
+	mutex_unlock(&ts->lock);
+
+	return ret;
+}
+
+static int __max7301_set(struct max7301 *ts, unsigned offset, int value)
+{
+	if (value) {
+		ts->out_level |= 1 << offset;
+		return max7301_write(ts->spi, 0x20 + offset, 0x01);
+	} else {
+		ts->out_level &= ~(1 << offset);
+		return max7301_write(ts->spi, 0x20 + offset, 0x00);
+	}
+}
+
+static int max7301_direction_output(struct gpio_chip *chip, unsigned offset,
+				    int value)
+{
+	struct max7301 *ts = container_of(chip, struct max7301, chip);
+	u8 *config;
+	int ret;
+
+	/* First 4 pins are unused in the controller */
+	offset += 4;
+
+	config = &ts->port_config[offset >> 2];
+
+	mutex_lock(&ts->lock);
+
+	*config = (*config & ~(3 << (offset & 3))) | (1 << (offset & 3));
+
+	ret = __max7301_set(ts, offset, value);
+
+	if (!ret)
+		ret = max7301_write(ts->spi, 0x08 + (offset >> 2), *config);
+
+	mutex_unlock(&ts->lock);
+
+	return ret;
+}
+
+static int max7301_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct max7301 *ts = container_of(chip, struct max7301, chip);
+	int config, level = -EINVAL;
+
+	/* First 4 pins are unused in the controller */
+	offset += 4;
+
+	mutex_lock(&ts->lock);
+
+	config = (ts->port_config[offset >> 2] >> ((offset & 3) * 2)) & 3;
+
+	switch (config) {
+	case 1:
+		/* Output: return cached level */
+		level =  !!(ts->out_level & (1 << offset));
+		break;
+	case 2:
+	case 3:
+		/* Input: read out */
+		level = max7301_read(ts->spi, 0x20 + offset) & 0x01;
+	}
+	mutex_unlock(&ts->lock);
+
+	return level;
+}
+
+static void max7301_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct max7301 *ts = container_of(chip, struct max7301, chip);
+
+	/* First 4 pins are unused in the controller */
+	offset += 4;
+
+	mutex_lock(&ts->lock);
+
+	__max7301_set(ts, offset, value);
+
+	mutex_unlock(&ts->lock);
+}
+
+static int __devinit max7301_probe(struct spi_device *spi)
+{
+	struct max7301 *ts;
+	struct max7301_platform_data *pdata;
+	int i, ret;
+
+	pdata = spi->dev.platform_data;
+	if (!pdata || !pdata->base)
+		return -ENODEV;
+
+	/*
+	 * bits_per_word cannot be configured in platform data
+	 */
+	spi->bits_per_word = 16;
+
+	ret = spi_setup(spi);
+	if (ret < 0)
+		return ret;
+
+	ts = kzalloc(sizeof(struct max7301), GFP_KERNEL);
+	if (!ts)
+		return -ENOMEM;
+
+	mutex_init(&ts->lock);
+
+	dev_set_drvdata(&spi->dev, ts);
+
+	/* Power up the chip and disable IRQ output */
+	max7301_write(spi, 0x04, 0x01);
+
+	ts->spi = spi;
+
+	ts->chip.label = DRIVER_NAME,
+
+	ts->chip.direction_input = max7301_direction_input;
+	ts->chip.get = max7301_get;
+	ts->chip.direction_output = max7301_direction_output;
+	ts->chip.set = max7301_set;
+
+	ts->chip.base = pdata->base;
+	ts->chip.ngpio = PIN_NUMBER;
+	ts->chip.can_sleep = 1;
+	ts->chip.dev = &spi->dev;
+	ts->chip.owner = THIS_MODULE;
+
+	ret = gpiochip_add(&ts->chip);
+	if (ret)
+		goto exit_destroy;
+
+	/*
+	 * tristate all pins in hardware and cache the
+	 * register values for later use.
+	 */
+	for (i = 1; i < 8; i++) {
+		int j;
+		/* 0xAA means input with internal pullup disabled */
+		max7301_write(spi, 0x08 + i, 0xAA);
+		ts->port_config[i] = 0xAA;
+		for (j = 0; j < 4; j++) {
+			int idx = ts->chip.base + (i - 1) * 4 + j;
+			ret = gpio_direction_input(idx);
+			if (ret)
+				goto exit_remove;
+			gpio_free(idx);
+		}
+	}
+	return ret;
+
+exit_remove:
+	gpiochip_remove(&ts->chip);
+exit_destroy:
+	dev_set_drvdata(&spi->dev, NULL);
+	mutex_destroy(&ts->lock);
+	kfree(ts);
+	return ret;
+}
+
+static int max7301_remove(struct spi_device *spi)
+{
+	struct max7301 *ts;
+	int ret;
+
+	ts = dev_get_drvdata(&spi->dev);
+	if (ts == NULL)
+		return -ENODEV;
+
+	dev_set_drvdata(&spi->dev, NULL);
+
+	/* Power down the chip and disable IRQ output */
+	max7301_write(spi, 0x04, 0x00);
+
+	ret = gpiochip_remove(&ts->chip);
+	if (!ret) {
+		mutex_destroy(&ts->lock);
+		kfree(ts);
+	} else
+		dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n",
+			ret);
+
+	return ret;
+}
+
+static struct spi_driver max7301_driver = {
+	.driver = {
+		.name		= DRIVER_NAME,
+		.owner		= THIS_MODULE,
+	},
+	.probe		= max7301_probe,
+	.remove		= __devexit_p(max7301_remove),
+};
+
+static int __init max7301_init(void)
+{
+	return spi_register_driver(&max7301_driver);
+}
+
+static void __exit max7301_exit(void)
+{
+	spi_unregister_driver(&max7301_driver);
+}
+
+module_init(max7301_init);
+module_exit(max7301_exit);
+
+MODULE_AUTHOR("Juergen Beisert");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MAX7301 SPI based GPIO-Expander");
diff --git a/drivers/gpio/pcf857x.c b/drivers/gpio/pcf857x.c
index aa6cc8b..d25d356 100644
--- a/drivers/gpio/pcf857x.c
+++ b/drivers/gpio/pcf857x.c
@@ -37,6 +37,8 @@
 	{ "pca9671", 16 },
 	{ "pca9673", 16 },
 	{ "pca9675", 16 },
+	{ "max7328", 8 },
+	{ "max7329", 8 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, pcf857x_id);
@@ -56,6 +58,7 @@
 struct pcf857x {
 	struct gpio_chip	chip;
 	struct i2c_client	*client;
+	struct mutex		lock;		/* protect 'out' */
 	unsigned		out;		/* software latch */
 };
 
@@ -66,9 +69,14 @@
 static int pcf857x_input8(struct gpio_chip *chip, unsigned offset)
 {
 	struct pcf857x	*gpio = container_of(chip, struct pcf857x, chip);
+	int		status;
 
+	mutex_lock(&gpio->lock);
 	gpio->out |= (1 << offset);
-	return i2c_smbus_write_byte(gpio->client, gpio->out);
+	status = i2c_smbus_write_byte(gpio->client, gpio->out);
+	mutex_unlock(&gpio->lock);
+
+	return status;
 }
 
 static int pcf857x_get8(struct gpio_chip *chip, unsigned offset)
@@ -84,12 +92,17 @@
 {
 	struct pcf857x	*gpio = container_of(chip, struct pcf857x, chip);
 	unsigned	bit = 1 << offset;
+	int		status;
 
+	mutex_lock(&gpio->lock);
 	if (value)
 		gpio->out |= bit;
 	else
 		gpio->out &= ~bit;
-	return i2c_smbus_write_byte(gpio->client, gpio->out);
+	status = i2c_smbus_write_byte(gpio->client, gpio->out);
+	mutex_unlock(&gpio->lock);
+
+	return status;
 }
 
 static void pcf857x_set8(struct gpio_chip *chip, unsigned offset, int value)
@@ -124,9 +137,14 @@
 static int pcf857x_input16(struct gpio_chip *chip, unsigned offset)
 {
 	struct pcf857x	*gpio = container_of(chip, struct pcf857x, chip);
+	int		status;
 
+	mutex_lock(&gpio->lock);
 	gpio->out |= (1 << offset);
-	return i2c_write_le16(gpio->client, gpio->out);
+	status = i2c_write_le16(gpio->client, gpio->out);
+	mutex_unlock(&gpio->lock);
+
+	return status;
 }
 
 static int pcf857x_get16(struct gpio_chip *chip, unsigned offset)
@@ -142,12 +160,17 @@
 {
 	struct pcf857x	*gpio = container_of(chip, struct pcf857x, chip);
 	unsigned	bit = 1 << offset;
+	int		status;
 
+	mutex_lock(&gpio->lock);
 	if (value)
 		gpio->out |= bit;
 	else
 		gpio->out &= ~bit;
-	return i2c_write_le16(gpio->client, gpio->out);
+	status = i2c_write_le16(gpio->client, gpio->out);
+	mutex_unlock(&gpio->lock);
+
+	return status;
 }
 
 static void pcf857x_set16(struct gpio_chip *chip, unsigned offset, int value)
@@ -173,6 +196,8 @@
 	if (!gpio)
 		return -ENOMEM;
 
+	mutex_init(&gpio->lock);
+
 	gpio->chip.base = pdata->gpio_base;
 	gpio->chip.can_sleep = 1;
 	gpio->chip.owner = THIS_MODULE;
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index f43d6d3..426ac5a 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -780,7 +780,7 @@
  */
 static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
 {
-	__le64 x;
+	u64 x;
 	u64 m = (1ULL << n) - 1;
 
 	if (n > 32)
@@ -796,10 +796,10 @@
 	report += offset >> 3;
 	offset &= 7;
 
-	x = get_unaligned((__le64 *)report);
-	x &= cpu_to_le64(~(m << offset));
-	x |= cpu_to_le64(((u64) value) << offset);
-	put_unaligned(x, (__le64 *) report);
+	x = get_unaligned_le64(report);
+	x &= ~(m << offset);
+	x |= ((u64)value) << offset;
+	put_unaligned_le64(x, report);
 }
 
 /*
diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c
index 4c2052c..16feea0 100644
--- a/drivers/hid/hid-input-quirks.c
+++ b/drivers/hid/hid-input-quirks.c
@@ -89,6 +89,29 @@
 	return 1;
 }
 
+static int quirk_gyration_remote(struct hid_usage *usage, struct input_dev *input,
+			      unsigned long **bit, int *max)
+{
+	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
+		return 0;
+
+	set_bit(EV_REP, input->evbit);
+	switch(usage->hid & HID_USAGE) {
+		/* Reported on Gyration MCE Remote */
+		case 0x00d: map_key_clear(KEY_HOME);		break;
+		case 0x024: map_key_clear(KEY_DVD);		break;
+		case 0x025: map_key_clear(KEY_PVR);		break;
+		case 0x046: map_key_clear(KEY_MEDIA);		break;
+		case 0x047: map_key_clear(KEY_MP3);		break;
+		case 0x049: map_key_clear(KEY_CAMERA);		break;
+		case 0x04a: map_key_clear(KEY_VIDEO);		break;
+
+		default:
+			return 0;
+	}
+	return 1;
+}
+
 static int quirk_chicony_tactical_pad(struct hid_usage *usage, struct input_dev *input,
 			      unsigned long **bit, int *max)
 {
@@ -303,6 +326,9 @@
 #define VENDOR_ID_EZKEY				0x0518
 #define DEVICE_ID_BTC_8193			0x0002
 
+#define VENDOR_ID_GYRATION			0x0c16
+#define DEVICE_ID_GYRATION_REMOTE		0x0002
+
 #define VENDOR_ID_LOGITECH			0x046d
 #define DEVICE_ID_LOGITECH_RECEIVER		0xc101
 #define DEVICE_ID_S510_RECEIVER			0xc50c
@@ -337,6 +363,8 @@
 
 	{ VENDOR_ID_EZKEY, DEVICE_ID_BTC_8193, quirk_btc_8193 },
 
+	{ VENDOR_ID_GYRATION, DEVICE_ID_GYRATION_REMOTE, quirk_gyration_remote },
+
 	{ VENDOR_ID_LOGITECH, DEVICE_ID_LOGITECH_RECEIVER, quirk_logitech_ultrax_remote },
 	{ VENDOR_ID_LOGITECH, DEVICE_ID_S510_RECEIVER, quirk_logitech_wireless },
 	{ VENDOR_ID_LOGITECH, DEVICE_ID_S510_RECEIVER_2, quirk_logitech_wireless },
@@ -438,6 +466,18 @@
 		input_event(input, usage->type, REL_WHEEL, -value);
 		return 1;
 	}
+
+	/* Gyration MCE remote "Sleep" key */
+	if (hid->vendor == VENDOR_ID_GYRATION &&
+	    hid->product == DEVICE_ID_GYRATION_REMOTE &&
+	    (usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK &&
+	    (usage->hid & 0xff) == 0x82) {
+		input_event(input, usage->type, usage->code, 1);
+		input_sync(input);
+		input_event(input, usage->type, usage->code, 0);
+		input_sync(input);
+		return 1;
+	}
 	return 0;
 }
 
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 5c52a20..1b2e8dc 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -100,6 +100,8 @@
 	{ KEY_F2,       KEY_BRIGHTNESSUP,   APPLE_FLAG_FKEY },
 	{ KEY_F3,       KEY_FN_F5,          APPLE_FLAG_FKEY }, /* Exposé */
 	{ KEY_F4,       KEY_FN_F4,          APPLE_FLAG_FKEY }, /* Dashboard */
+	{ KEY_F5,       KEY_KBDILLUMDOWN,   APPLE_FLAG_FKEY },
+	{ KEY_F6,       KEY_KBDILLUMUP,     APPLE_FLAG_FKEY },
 	{ KEY_F7,       KEY_PREVIOUSSONG,   APPLE_FLAG_FKEY },
 	{ KEY_F8,       KEY_PLAYPAUSE,      APPLE_FLAG_FKEY },
 	{ KEY_F9,       KEY_NEXTSONG,       APPLE_FLAG_FKEY },
@@ -612,6 +614,7 @@
 				case 0x0b6: map_key_clear(KEY_PREVIOUSSONG);	break;
 				case 0x0b7: map_key_clear(KEY_STOPCD);		break;
 				case 0x0b8: map_key_clear(KEY_EJECTCD);		break;
+				case 0x0bc: map_key_clear(KEY_MEDIA_REPEAT);	break;
 
 				case 0x0cd: map_key_clear(KEY_PLAYPAUSE);	break;
 			        case 0x0e0: map_abs_clear(ABS_VOLUME);		break;
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 2fde6c6..c40f040 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -105,6 +105,7 @@
 static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
 	unsigned int minor = iminor(file->f_path.dentry->d_inode);
+	/* FIXME: What stops hidraw_table going NULL */
 	struct hid_device *dev = hidraw_table[minor]->hid;
 	__u8 *buf;
 	int ret = 0;
@@ -211,38 +212,43 @@
 			kfree(list->hidraw);
 	}
 
+	kfree(list);
+
 	return 0;
 }
 
-static int hidraw_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long hidraw_ioctl(struct file *file, unsigned int cmd,
+							unsigned long arg)
 {
+	struct inode *inode = file->f_path.dentry->d_inode;
 	unsigned int minor = iminor(inode);
+	long ret = 0;
+	/* FIXME: What stops hidraw_table going NULL */
 	struct hidraw *dev = hidraw_table[minor];
 	void __user *user_arg = (void __user*) arg;
 
+	lock_kernel();
 	switch (cmd) {
 		case HIDIOCGRDESCSIZE:
 			if (put_user(dev->hid->rsize, (int __user *)arg))
-				return -EFAULT;
-			return 0;
+				ret = -EFAULT;
+			break;
 
 		case HIDIOCGRDESC:
 			{
 				__u32 len;
 
 				if (get_user(len, (int __user *)arg))
-					return -EFAULT;
-
-				if (len > HID_MAX_DESCRIPTOR_SIZE - 1)
-					return -EINVAL;
-
-				if (copy_to_user(user_arg + offsetof(
-								struct hidraw_report_descriptor,
-								value[0]),
-							dev->hid->rdesc,
-							min(dev->hid->rsize, len)))
-						return -EFAULT;
-				return 0;
+					ret = -EFAULT;
+				else if (len > HID_MAX_DESCRIPTOR_SIZE - 1)
+					ret = -EINVAL;
+				else if (copy_to_user(user_arg + offsetof(
+					struct hidraw_report_descriptor,
+					value[0]),
+					dev->hid->rdesc,
+					min(dev->hid->rsize, len)))
+					ret = -EFAULT;
+				break;
 			}
 		case HIDIOCGRAWINFO:
 			{
@@ -252,15 +258,13 @@
 				dinfo.vendor = dev->hid->vendor;
 				dinfo.product = dev->hid->product;
 				if (copy_to_user(user_arg, &dinfo, sizeof(dinfo)))
-					return -EFAULT;
-
-				return 0;
+					ret = -EFAULT;
+				break;
 			}
 		default:
-			printk(KERN_EMERG "hidraw: unsupported ioctl() %x\n",
-					cmd);
+			ret = -ENOTTY;
 	}
-	return -EINVAL;
+	return ret;
 }
 
 static const struct file_operations hidraw_ops = {
@@ -270,7 +274,7 @@
 	.poll =         hidraw_poll,
 	.open =         hidraw_open,
 	.release =      hidraw_release,
-	.ioctl =        hidraw_ioctl,
+	.unlocked_ioctl = hidraw_ioctl,
 };
 
 void hidraw_report_event(struct hid_device *hid, u8 *data, int len)
@@ -322,8 +326,9 @@
 		goto out;
 	}
 
-	dev->dev = device_create(hidraw_class, NULL, MKDEV(hidraw_major, minor),
-				"%s%d", "hidraw", minor);
+	dev->dev = device_create_drvdata(hidraw_class, NULL,
+					 MKDEV(hidraw_major, minor), NULL,
+					 "%s%d", "hidraw", minor);
 
 	if (IS_ERR(dev->dev)) {
 		spin_lock(&minors_lock);
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 01427c5..27fe4d8 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -122,7 +122,7 @@
 		dev_dbg(&usbhid->intf->dev, "resetting device\n");
 		rc = rc_lock = usb_lock_device_for_reset(hid_to_usb_dev(hid), usbhid->intf);
 		if (rc_lock >= 0) {
-			rc = usb_reset_composite_device(hid_to_usb_dev(hid), usbhid->intf);
+			rc = usb_reset_device(hid_to_usb_dev(hid));
 			if (rc_lock)
 				usb_unlock_device(hid_to_usb_dev(hid));
 		}
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 1df832a..61e78a4 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -69,12 +69,18 @@
 #define USB_DEVICE_ID_APPLE_ALU_ANSI	0x0220
 #define USB_DEVICE_ID_APPLE_ALU_ISO	0x0221
 #define USB_DEVICE_ID_APPLE_ALU_JIS	0x0222
+#define USB_DEVICE_ID_APPLE_WELLSPRING_ANSI	0x0223
+#define USB_DEVICE_ID_APPLE_WELLSPRING_ISO	0x0224
+#define USB_DEVICE_ID_APPLE_WELLSPRING_JIS	0x0225
 #define USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI    0x0229
 #define USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO     0x022a
 #define USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS     0x022b
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI  0x022c
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO   0x022d
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS   0x022e
+#define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI	0x0230
+#define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO	0x0231
+#define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS	0x0232
 #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY	0x030a
 #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY	0x030b
 #define USB_DEVICE_ID_APPLE_IRCONTROL4	0x8242
@@ -241,6 +247,8 @@
 #define USB_DEVICE_ID_LD_MACHINETEST	0x2040
 
 #define USB_VENDOR_ID_LOGITECH		0x046d
+#define USB_DEVICE_ID_LOGITECH_LX3	0xc044
+#define USB_DEVICE_ID_LOGITECH_V150	0xc047
 #define USB_DEVICE_ID_LOGITECH_RECEIVER	0xc101
 #define USB_DEVICE_ID_LOGITECH_HARMONY  0xc110
 #define USB_DEVICE_ID_LOGITECH_HARMONY_2 0xc111
@@ -314,6 +322,7 @@
 #define USB_DEVICE_ID_S510_RECEIVER_2	0xc517
 #define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500	0xc512
 #define USB_DEVICE_ID_MX3000_RECEIVER	0xc513
+#define USB_DEVICE_ID_DINOVO_DESKTOP	0xc704
 #define USB_DEVICE_ID_DINOVO_EDGE	0xc714
 #define USB_DEVICE_ID_DINOVO_MINI	0xc71f
 
@@ -443,7 +452,8 @@
 	{ USB_VENDOR_ID_NEC, USB_DEVICE_ID_NEC_USB_GAME_PAD, HID_QUIRK_BADPAD },
 	{ USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
 	{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
-	
+
+	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP, HID_QUIRK_DUPLICATE_USAGES },
 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES },
 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI, HID_QUIRK_DUPLICATE_USAGES },
 
@@ -593,6 +603,8 @@
 
 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
+	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_LX3, HID_QUIRK_INVERT_HWHEEL },
+	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_V150, HID_QUIRK_INVERT_HWHEEL },
 
 	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K, HID_QUIRK_MICROSOFT_KEYS },
 	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K, HID_QUIRK_MICROSOFT_KEYS },
@@ -642,6 +654,12 @@
 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN },
 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI, HID_QUIRK_APPLE_HAS_FN },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS, HID_QUIRK_APPLE_HAS_FN },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI, HID_QUIRK_APPLE_HAS_FN },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS, HID_QUIRK_APPLE_HAS_FN },
 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
 
@@ -1128,7 +1146,7 @@
 			 && rdesc[557] == 0x19
 			 && rdesc[559] == 0x29) {
 		printk(KERN_INFO "Fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n");
-		rdesc[284] = rdesc[304] = rdesc[558] = 0x35;
+		rdesc[284] = rdesc[304] = rdesc[557] = 0x35;
 		rdesc[352] = 0x36;
 		rdesc[286] = rdesc[355] = 0x46;
 		rdesc[306] = rdesc[559] = 0x45;
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 95cc192..842e9ed 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -406,6 +406,7 @@
 	uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL);
 	if (!uref_multi)
 		return -ENOMEM;
+	lock_kernel();
 	uref = &uref_multi->uref;
 	if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) {
 		if (copy_from_user(uref_multi, user_arg,
@@ -501,12 +502,15 @@
 		}
 
 goodreturn:
+		unlock_kernel();
 		kfree(uref_multi);
 		return 0;
 fault:
+		unlock_kernel();
 		kfree(uref_multi);
 		return -EFAULT;
 inval:
+		unlock_kernel();
 		kfree(uref_multi);
 		return -EINVAL;
 	}
@@ -540,7 +544,7 @@
 	return len;
 }
 
-static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	struct hiddev_list *list = file->private_data;
 	struct hiddev *hiddev = list->hiddev;
@@ -555,7 +559,10 @@
 	struct usbhid_device *usbhid = hid->driver_data;
 	void __user *user_arg = (void __user *)arg;
 	int i;
+	
+	/* Called without BKL by compat methods so no BKL taken */
 
+	/* FIXME: Who or what stop this racing with a disconnect ?? */
 	if (!hiddev->exist)
 		return -EIO;
 
@@ -756,8 +763,7 @@
 #ifdef CONFIG_COMPAT
 static long hiddev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-	struct inode *inode = file->f_path.dentry->d_inode;
-	return hiddev_ioctl(inode, file, cmd, (unsigned long)compat_ptr(arg));
+	return hiddev_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
 }
 #endif
 
@@ -768,7 +774,7 @@
 	.poll =		hiddev_poll,
 	.open =		hiddev_open,
 	.release =	hiddev_release,
-	.ioctl =	hiddev_ioctl,
+	.unlocked_ioctl =	hiddev_ioctl,
 	.fasync =	hiddev_fasync,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= hiddev_compat_ioctl,
diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c
index 3cd46d2..0caaafe 100644
--- a/drivers/hid/usbhid/usbkbd.c
+++ b/drivers/hid/usbhid/usbkbd.c
@@ -43,7 +43,7 @@
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE(DRIVER_LICENSE);
 
-static unsigned char usb_kbd_keycode[256] = {
+static const unsigned char usb_kbd_keycode[256] = {
 	  0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
 	 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
 	  4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
@@ -233,14 +233,6 @@
 	if (!usb_endpoint_is_int_in(endpoint))
 		return -ENODEV;
 
-#ifdef CONFIG_USB_HID
-	if (usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
-				le16_to_cpu(dev->descriptor.idProduct))
-			& HID_QUIRK_IGNORE) {
-		return -ENODEV;
-	}
-#endif
-
 	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
 	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
 
diff --git a/drivers/hid/usbhid/usbmouse.c b/drivers/hid/usbhid/usbmouse.c
index 703e9d0..35689ef 100644
--- a/drivers/hid/usbhid/usbmouse.c
+++ b/drivers/hid/usbhid/usbmouse.c
@@ -129,14 +129,6 @@
 	if (!usb_endpoint_is_int_in(endpoint))
 		return -ENODEV;
 
-#ifdef CONFIG_USB_HID
-	if (usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
-				le16_to_cpu(dev->descriptor.idProduct))
-			& (HID_QUIRK_IGNORE|HID_QUIRK_IGNORE_MOUSE)) {
-		return -ENODEV;
-	}
-#endif
-
 	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
 	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
 
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
index 50f2269..a4d92d2 100644
--- a/drivers/hwmon/hdaps.c
+++ b/drivers/hwmon/hdaps.c
@@ -581,6 +581,8 @@
 	/* initialize the input class */
 	idev = hdaps_idev->input;
 	idev->name = "hdaps";
+	idev->phys = "isa1600/input0";
+	idev->id.bustype = BUS_ISA;
 	idev->dev.parent = &pdev->dev;
 	idev->evbit[0] = BIT_MASK(EV_ABS);
 	input_set_abs_params(idev, ABS_X,
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index 3db28450..7321a88 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -55,7 +55,8 @@
 		return ERR_PTR(err);
 
 	id = id & MAX_ID_MASK;
-	hwdev = device_create(hwmon_class, dev, MKDEV(0,0), HWMON_ID_FORMAT, id);
+	hwdev = device_create_drvdata(hwmon_class, dev, MKDEV(0, 0), NULL,
+				      HWMON_ID_FORMAT, id);
 
 	if (IS_ERR(hwdev)) {
 		spin_lock(&idr_lock);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 7608df8..7bf38c4 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -722,7 +722,8 @@
 
 	INIT_LIST_HEAD(&driver->clients);
 	/* Walk the adapters that are already present */
-	class_for_each_device(&i2c_adapter_class, driver, __attach_adapter);
+	class_for_each_device(&i2c_adapter_class, NULL, driver,
+			      __attach_adapter);
 
 	mutex_unlock(&core_lock);
 	return 0;
@@ -782,7 +783,8 @@
 {
 	mutex_lock(&core_lock);
 
-	class_for_each_device(&i2c_adapter_class, driver, __detach_adapter);
+	class_for_each_device(&i2c_adapter_class, NULL, driver,
+			      __detach_adapter);
 
 	driver_unregister(&driver->driver);
 	pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 86727fa..9d55c638 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -521,9 +521,9 @@
 		return PTR_ERR(i2c_dev);
 
 	/* register this i2c device with the driver core */
-	i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,
-				     MKDEV(I2C_MAJOR, adap->nr),
-				     "i2c-%d", adap->nr);
+	i2c_dev->dev = device_create_drvdata(i2c_dev_class, &adap->dev,
+					     MKDEV(I2C_MAJOR, adap->nr),
+					     NULL, "i2c-%d", adap->nr);
 	if (IS_ERR(i2c_dev->dev)) {
 		res = PTR_ERR(i2c_dev->dev);
 		goto error;
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 15b09b8..04d9c4d 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -510,6 +510,7 @@
 
 config BLK_DEV_CY82C693
 	tristate "CY82C693 chipset support"
+	depends on ALPHA
 	select IDE_TIMINGS
 	select BLK_DEV_IDEDMA_PCI
 	help
@@ -548,6 +549,7 @@
 
 config BLK_DEV_HPT34X
 	tristate "HPT34X chipset support"
+	depends on BROKEN
 	select BLK_DEV_IDEDMA_PCI
 	help
 	  This driver adds up to 4 more EIDE devices sharing a single
diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
index 52f58c8..f575e83 100644
--- a/drivers/ide/arm/icside.c
+++ b/drivers/ide/arm/icside.c
@@ -72,7 +72,7 @@
 	void __iomem *ioc_base;
 	unsigned int sel;
 	unsigned int type;
-	ide_hwif_t *hwif[2];
+	struct ide_host *host;
 };
 
 #define ICS_TYPE_A3IN	0
@@ -375,12 +375,14 @@
 
 static void icside_dma_timeout(ide_drive_t *drive)
 {
+	ide_hwif_t *hwif = drive->hwif;
+
 	printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
 
 	if (icside_dma_test_irq(drive))
 		return;
 
-	ide_dump_status(drive, "DMA timeout", ide_read_status(drive));
+	ide_dump_status(drive, "DMA timeout", hwif->tp_ops->read_status(hwif));
 
 	icside_dma_end(drive);
 }
@@ -440,10 +442,10 @@
 static int __init
 icside_register_v5(struct icside_state *state, struct expansion_card *ec)
 {
-	ide_hwif_t *hwif;
 	void __iomem *base;
-	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
-	hw_regs_t hw;
+	struct ide_host *host;
+	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+	int ret;
 
 	base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0);
 	if (!base)
@@ -463,22 +465,23 @@
 
 	icside_setup_ports(&hw, base, &icside_cardinfo_v5, ec);
 
-	hwif = ide_find_port();
-	if (!hwif)
+	host = ide_host_alloc(NULL, hws);
+	if (host == NULL)
 		return -ENODEV;
 
-	ide_init_port_hw(hwif, &hw);
-	default_hwif_mmiops(hwif);
-
-	state->hwif[0] = hwif;
+	state->host = host;
 
 	ecard_set_drvdata(ec, state);
 
-	idx[0] = hwif->index;
-
-	ide_device_add(idx, NULL);
+	ret = ide_host_register(host, NULL, hws);
+	if (ret)
+		goto err_free;
 
 	return 0;
+err_free:
+	ide_host_free(host);
+	ecard_set_drvdata(ec, NULL);
+	return ret;
 }
 
 static const struct ide_port_info icside_v6_port_info __initdata = {
@@ -493,13 +496,12 @@
 static int __init
 icside_register_v6(struct icside_state *state, struct expansion_card *ec)
 {
-	ide_hwif_t *hwif, *mate;
 	void __iomem *ioc_base, *easi_base;
+	struct ide_host *host;
 	unsigned int sel = 0;
 	int ret;
-	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+	hw_regs_t hw[2], *hws[] = { &hw[0], NULL, NULL, NULL };
 	struct ide_port_info d = icside_v6_port_info;
-	hw_regs_t hw[2];
 
 	ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
 	if (!ioc_base) {
@@ -538,28 +540,11 @@
 	icside_setup_ports(&hw[0], easi_base, &icside_cardinfo_v6_1, ec);
 	icside_setup_ports(&hw[1], easi_base, &icside_cardinfo_v6_2, ec);
 
-	/*
-	 * Find and register the interfaces.
-	 */
-	hwif = ide_find_port();
-	if (hwif == NULL)
+	host = ide_host_alloc(&d, hws);
+	if (host == NULL)
 		return -ENODEV;
 
-	ide_init_port_hw(hwif, &hw[0]);
-	default_hwif_mmiops(hwif);
-
-	idx[0] = hwif->index;
-
-	mate = ide_find_port();
-	if (mate) {
-		ide_init_port_hw(mate, &hw[1]);
-		default_hwif_mmiops(mate);
-
-		idx[1] = mate->index;
-	}
-
-	state->hwif[0]    = hwif;
-	state->hwif[1]    = mate;
+	state->host = host;
 
 	ecard_set_drvdata(ec, state);
 
@@ -569,11 +554,17 @@
 		d.dma_ops = NULL;
 	}
 
-	ide_device_add(idx, &d);
+	ret = ide_host_register(host, NULL, hws);
+	if (ret)
+		goto err_free;
 
 	return 0;
-
- out:
+err_free:
+	ide_host_free(host);
+	if (d.dma_ops)
+		free_dma(ec->dma);
+	ecard_set_drvdata(ec, NULL);
+out:
 	return ret;
 }
 
diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c
index 2f311da..176532f 100644
--- a/drivers/ide/arm/ide_arm.c
+++ b/drivers/ide/arm/ide_arm.c
@@ -28,10 +28,8 @@
 
 static int __init ide_arm_init(void)
 {
-	ide_hwif_t *hwif;
-	hw_regs_t hw;
 	unsigned long base = IDE_ARM_IO, ctl = IDE_ARM_IO + 0x206;
-	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
 
 	if (!request_region(base, 8, DRV_NAME)) {
 		printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
@@ -51,15 +49,7 @@
 	hw.irq = IDE_ARM_IRQ;
 	hw.chipset = ide_generic;
 
-	hwif = ide_find_port();
-	if (hwif) {
-		ide_init_port_hw(hwif, &hw);
-		idx[0] = hwif->index;
-
-		ide_device_add(idx, NULL);
-	}
-
-	return 0;
+	return ide_host_add(NULL, hws, NULL);
 }
 
 module_init(ide_arm_init);
diff --git a/drivers/ide/arm/palm_bk3710.c b/drivers/ide/arm/palm_bk3710.c
index c79b85b..65bb4b8 100644
--- a/drivers/ide/arm/palm_bk3710.c
+++ b/drivers/ide/arm/palm_bk3710.c
@@ -316,15 +316,14 @@
 static int __devinit palm_bk3710_init_dma(ide_hwif_t *hwif,
 					  const struct ide_port_info *d)
 {
-	unsigned long base =
-		hwif->io_ports.data_addr - IDE_PALM_ATA_PRI_REG_OFFSET;
-
 	printk(KERN_INFO "    %s: MMIO-DMA\n", hwif->name);
 
 	if (ide_allocate_dma_engine(hwif))
 		return -1;
 
-	ide_setup_dma(hwif, base);
+	hwif->dma_base = hwif->io_ports.data_addr - IDE_PALM_ATA_PRI_REG_OFFSET;
+
+	hwif->dma_ops = &sff_dma_ops;
 
 	return 0;
 }
@@ -348,11 +347,10 @@
 {
 	struct clk *clk;
 	struct resource *mem, *irq;
-	ide_hwif_t *hwif;
+	struct ide_host *host;
 	unsigned long base, rate;
-	int i;
-	hw_regs_t hw;
-	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+	int i, rc;
+	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
 
 	clk = clk_get(NULL, "IDECLK");
 	if (IS_ERR(clk))
@@ -394,24 +392,14 @@
 	hw.irq = irq->start;
 	hw.chipset = ide_palm3710;
 
-	hwif = ide_find_port();
-	if (hwif == NULL)
+	rc = ide_host_add(&palm_bk3710_port_info, hws, NULL);
+	if (rc)
 		goto out;
 
-	i = hwif->index;
-
-	ide_init_port_hw(hwif, &hw);
-
-	default_hwif_mmiops(hwif);
-
-	idx[0] = i;
-
-	ide_device_add(idx, &palm_bk3710_port_info);
-
 	return 0;
 out:
 	printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n");
-	return -ENODEV;
+	return rc;
 }
 
 /* work with hotplug and coldplug */
diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c
index 43057e0..2bdd8b7 100644
--- a/drivers/ide/arm/rapide.c
+++ b/drivers/ide/arm/rapide.c
@@ -32,11 +32,10 @@
 static int __devinit
 rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
-	ide_hwif_t *hwif;
 	void __iomem *base;
+	struct ide_host *host;
 	int ret;
-	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
-	hw_regs_t hw;
+	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
 
 	ret = ecard_request_resources(ec);
 	if (ret)
@@ -53,20 +52,11 @@
 	hw.chipset = ide_generic;
 	hw.dev = &ec->dev;
 
-	hwif = ide_find_port();
-	if (hwif == NULL) {
-		ret = -ENOENT;
+	ret = ide_host_add(&rapide_port_info, hws, &host);
+	if (ret)
 		goto release;
-	}
 
-	ide_init_port_hw(hwif, &hw);
-	default_hwif_mmiops(hwif);
-
-	idx[0] = hwif->index;
-
-	ide_device_add(idx, &rapide_port_info);
-
-	ecard_set_drvdata(ec, hwif);
+	ecard_set_drvdata(ec, host);
 	goto out;
 
  release:
@@ -77,11 +67,11 @@
 
 static void __devexit rapide_remove(struct expansion_card *ec)
 {
-	ide_hwif_t *hwif = ecard_get_drvdata(ec);
+	struct ide_host *host = ecard_get_drvdata(ec);
 
 	ecard_set_drvdata(ec, NULL);
 
-	ide_unregister(hwif);
+	ide_host_remove(host);
 
 	ecard_release_resources(ec);
 }
diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c
index 20fad6d..bde7a58 100644
--- a/drivers/ide/h8300/ide-h8300.c
+++ b/drivers/ide/h8300/ide-h8300.c
@@ -100,6 +100,8 @@
 	/* be sure we're looking at the low order bits */
 	outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
 
+	if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+		tf->feature = inb(io_ports->feature_addr);
 	if (task->tf_flags & IDE_TFLAG_IN_NSECT)
 		tf->nsect  = inb(io_ports->nsect_addr);
 	if (task->tf_flags & IDE_TFLAG_IN_LBAL)
@@ -153,6 +155,21 @@
 	mm_outsw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
 }
 
+static const struct ide_tp_ops h8300_tp_ops = {
+	.exec_command		= ide_exec_command,
+	.read_status		= ide_read_status,
+	.read_altstatus		= ide_read_altstatus,
+	.read_sff_dma_status	= ide_read_sff_dma_status,
+
+	.set_irq		= ide_set_irq,
+
+	.tf_load		= h8300_tf_load,
+	.tf_read		= h8300_tf_read,
+
+	.input_data		= h8300_input_data,
+	.output_data		= h8300_output_data,
+};
+
 #define H8300_IDE_GAP (2)
 
 static inline void hw_setup(hw_regs_t *hw)
@@ -167,27 +184,14 @@
 	hw->chipset = ide_generic;
 }
 
-static inline void hwif_setup(ide_hwif_t *hwif)
-{
-	default_hwif_iops(hwif);
-
-	hwif->tf_load = h8300_tf_load;
-	hwif->tf_read = h8300_tf_read;
-
-	hwif->input_data  = h8300_input_data;
-	hwif->output_data = h8300_output_data;
-}
-
 static const struct ide_port_info h8300_port_info = {
+	.tp_ops			= &h8300_tp_ops,
 	.host_flags		= IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_NO_DMA,
 };
 
 static int __init h8300_ide_init(void)
 {
-	hw_regs_t hw;
-	ide_hwif_t *hwif;
-	int index;
-	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
 
 	printk(KERN_INFO DRV_NAME ": H8/300 generic IDE interface\n");
 
@@ -200,19 +204,7 @@
 
 	hw_setup(&hw);
 
-	hwif = ide_find_port_slot(&h8300_port_info);
-	if (hwif == NULL)
-		return -ENOENT;
-
-	index = hwif->index;
-	ide_init_port_hw(hwif, &hw);
-	hwif_setup(hwif);
-
-	idx[0] = index;
-
-	ide_device_add(idx, &h8300_port_info);
-
-	return 0;
+	return ide_host_add(&h8300_port_info, hws, NULL);
 
 out_busy:
 	printk(KERN_ERR "ide-h8300: IDE I/F resource already used.\n");
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index 2802031..adf04f9 100644
--- a/drivers/ide/ide-atapi.c
+++ b/drivers/ide/ide-atapi.c
@@ -22,6 +22,8 @@
 	void (*io_buffers)(ide_drive_t *, struct ide_atapi_pc *, unsigned, int))
 {
 	ide_hwif_t *hwif = drive->hwif;
+	struct request *rq = hwif->hwgroup->rq;
+	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
 	xfer_func_t *xferfunc;
 	unsigned int temp;
 	u16 bcount;
@@ -30,12 +32,12 @@
 	debug_log("Enter %s - interrupt handler\n", __func__);
 
 	if (pc->flags & PC_FLAG_TIMEDOUT) {
-		pc->callback(drive);
+		drive->pc_callback(drive);
 		return ide_stopped;
 	}
 
 	/* Clear the interrupt */
-	stat = ide_read_status(drive);
+	stat = tp_ops->read_status(hwif);
 
 	if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
 		if (hwif->dma_ops->dma_end(drive) ||
@@ -63,8 +65,9 @@
 		local_irq_enable_in_hardirq();
 
 		if (drive->media == ide_tape && !scsi &&
-		    (stat & ERR_STAT) && pc->c[0] == REQUEST_SENSE)
+		    (stat & ERR_STAT) && rq->cmd[0] == REQUEST_SENSE)
 			stat &= ~ERR_STAT;
+
 		if ((stat & ERR_STAT) || (pc->flags & PC_FLAG_DMA_ERROR)) {
 			/* Error detected */
 			debug_log("%s: I/O error\n", drive->name);
@@ -75,16 +78,17 @@
 					goto cmd_finished;
 			}
 
-			if (pc->c[0] == REQUEST_SENSE) {
+			if (rq->cmd[0] == REQUEST_SENSE) {
 				printk(KERN_ERR "%s: I/O error in request sense"
 						" command\n", drive->name);
 				return ide_do_reset(drive);
 			}
 
-			debug_log("[cmd %x]: check condition\n", pc->c[0]);
+			debug_log("[cmd %x]: check condition\n", rq->cmd[0]);
 
 			/* Retry operation */
 			retry_pc(drive);
+
 			/* queued, but not started */
 			return ide_stopped;
 		}
@@ -95,8 +99,10 @@
 			dsc_handle(drive);
 			return ide_stopped;
 		}
+
 		/* Command finished - Call the callback function */
-		pc->callback(drive);
+		drive->pc_callback(drive);
+
 		return ide_stopped;
 	}
 
@@ -107,16 +113,15 @@
 		ide_dma_off(drive);
 		return ide_do_reset(drive);
 	}
-	/* Get the number of bytes to transfer on this interrupt. */
-	bcount = (hwif->INB(hwif->io_ports.lbah_addr) << 8) |
-		  hwif->INB(hwif->io_ports.lbam_addr);
 
-	ireason = hwif->INB(hwif->io_ports.nsect_addr);
+	/* Get the number of bytes to transfer on this interrupt. */
+	ide_read_bcount_and_ireason(drive, &bcount, &ireason);
 
 	if (ireason & CD) {
 		printk(KERN_ERR "%s: CoD != 0 in %s\n", drive->name, __func__);
 		return ide_do_reset(drive);
 	}
+
 	if (((ireason & IO) == IO) == !!(pc->flags & PC_FLAG_WRITING)) {
 		/* Hopefully, we will never get here */
 		printk(KERN_ERR "%s: We wanted to %s, but the device wants us "
@@ -125,6 +130,7 @@
 				(ireason & IO) ? "Read" : "Write");
 		return ide_do_reset(drive);
 	}
+
 	if (!(pc->flags & PC_FLAG_WRITING)) {
 		/* Reading - Check that we have enough space */
 		temp = pc->xferred + bcount;
@@ -142,7 +148,7 @@
 					if (pc->sg)
 						io_buffers(drive, pc, temp, 0);
 					else
-						hwif->input_data(drive, NULL,
+						tp_ops->input_data(drive, NULL,
 							pc->cur_pos, temp);
 					printk(KERN_ERR "%s: transferred %d of "
 							"%d bytes\n",
@@ -159,9 +165,9 @@
 			debug_log("The device wants to send us more data than "
 				  "expected - allowing transfer\n");
 		}
-		xferfunc = hwif->input_data;
+		xferfunc = tp_ops->input_data;
 	} else
-		xferfunc = hwif->output_data;
+		xferfunc = tp_ops->output_data;
 
 	if ((drive->media == ide_floppy && !scsi && !pc->buf) ||
 	    (drive->media == ide_tape && !scsi && pc->bh) ||
@@ -175,7 +181,7 @@
 	pc->cur_pos += bcount;
 
 	debug_log("[cmd %x] transferred %d bytes on that intr.\n",
-		  pc->c[0], bcount);
+		  rq->cmd[0], bcount);
 
 	/* And set the interrupt handler again */
 	ide_set_handler(drive, handler, timeout, expiry);
@@ -183,16 +189,27 @@
 }
 EXPORT_SYMBOL_GPL(ide_pc_intr);
 
+static u8 ide_read_ireason(ide_drive_t *drive)
+{
+	ide_task_t task;
+
+	memset(&task, 0, sizeof(task));
+	task.tf_flags = IDE_TFLAG_IN_NSECT;
+
+	drive->hwif->tp_ops->tf_read(drive, &task);
+
+	return task.tf.nsect & 3;
+}
+
 static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason)
 {
-	ide_hwif_t *hwif = drive->hwif;
 	int retries = 100;
 
 	while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) {
 		printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
 				"a packet command, retrying\n", drive->name);
 		udelay(100);
-		ireason = hwif->INB(hwif->io_ports.nsect_addr);
+		ireason = ide_read_ireason(drive);
 		if (retries == 0) {
 			printk(KERN_ERR "%s: (IO,CoD != (0,1) while issuing "
 					"a packet command, ignoring\n",
@@ -210,6 +227,7 @@
 				ide_expiry_t *expiry)
 {
 	ide_hwif_t *hwif = drive->hwif;
+	struct request *rq = hwif->hwgroup->rq;
 	ide_startstop_t startstop;
 	u8 ireason;
 
@@ -219,7 +237,7 @@
 		return startstop;
 	}
 
-	ireason = hwif->INB(hwif->io_ports.nsect_addr);
+	ireason = ide_read_ireason(drive);
 	if (drive->media == ide_tape && !drive->scsi)
 		ireason = ide_wait_ireason(drive, ireason);
 
@@ -239,8 +257,8 @@
 	}
 
 	/* Send the actual packet */
-	if ((pc->flags & PC_FLAG_ZIP_DRIVE) == 0)
-		hwif->output_data(drive, NULL, pc->c, 12);
+	if ((drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) == 0)
+		hwif->tp_ops->output_data(drive, NULL, rq->cmd, 12);
 
 	return ide_started;
 }
@@ -284,7 +302,7 @@
 			   bcount, dma);
 
 	/* Issue the packet command */
-	if (pc->flags & PC_FLAG_DRQ_INTERRUPT) {
+	if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
 		ide_execute_command(drive, WIN_PACKETCMD, handler,
 				    timeout, NULL);
 		return ide_started;
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 6e29dd5..4e73aee 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -85,10 +85,8 @@
 /* Mark that we've seen a media change and invalidate our internal buffers. */
 static void cdrom_saw_media_change(ide_drive_t *drive)
 {
-	struct cdrom_info *cd = drive->driver_data;
-
-	cd->cd_flags |= IDE_CD_FLAG_MEDIA_CHANGED;
-	cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
+	drive->atapi_flags |= IDE_AFLAG_MEDIA_CHANGED;
+	drive->atapi_flags &= ~IDE_AFLAG_TOC_VALID;
 }
 
 static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
@@ -280,11 +278,12 @@
  */
 static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
 {
-	struct request *rq = HWGROUP(drive)->rq;
+	ide_hwif_t *hwif = drive->hwif;
+	struct request *rq = hwif->hwgroup->rq;
 	int stat, err, sense_key;
 
 	/* check for errors */
-	stat = ide_read_status(drive);
+	stat = hwif->tp_ops->read_status(hwif);
 
 	if (stat_ret)
 		*stat_ret = stat;
@@ -528,7 +527,7 @@
 	ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL,
 			   xferlen, info->dma);
 
-	if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
+	if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
 		/* waiting for CDB interrupt, not DMA yet. */
 		if (info->dma)
 			drive->waiting_for_dma = 0;
@@ -560,7 +559,7 @@
 	struct cdrom_info *info = drive->driver_data;
 	ide_startstop_t startstop;
 
-	if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
+	if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
 		/*
 		 * Here we should have been called after receiving an interrupt
 		 * from the device.  DRQ should how be set.
@@ -589,7 +588,7 @@
 		cmd_len = ATAPI_MIN_CDB_BYTES;
 
 	/* send the command to the device */
-	hwif->output_data(drive, NULL, rq->cmd, cmd_len);
+	hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len);
 
 	/* start the DMA if need be */
 	if (info->dma)
@@ -606,6 +605,8 @@
 static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
 				int len, int ireason, int rw)
 {
+	ide_hwif_t *hwif = drive->hwif;
+
 	/*
 	 * ireason == 0: the drive wants to receive data from us
 	 * ireason == 2: the drive is expecting to transfer data to us
@@ -624,7 +625,7 @@
 		 * Some drives (ASUS) seem to tell us that status info is
 		 * available.  Just get it and ignore.
 		 */
-		(void)ide_read_status(drive);
+		(void)hwif->tp_ops->read_status(hwif);
 		return 0;
 	} else {
 		/* drive wants a command packet, or invalid ireason... */
@@ -645,20 +646,18 @@
  */
 static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
 {
-	struct cdrom_info *cd = drive->driver_data;
-
 	if ((len % SECTOR_SIZE) == 0)
 		return 0;
 
 	printk(KERN_ERR "%s: %s: Bad transfer size %d\n",
 			drive->name, __func__, len);
 
-	if (cd->cd_flags & IDE_CD_FLAG_LIMIT_NFRAMES)
+	if (drive->atapi_flags & IDE_AFLAG_LIMIT_NFRAMES)
 		printk(KERN_ERR "  This drive is not supported by "
 				"this version of the driver\n");
 	else {
 		printk(KERN_ERR "  Trying to limit transfer sizes\n");
-		cd->cd_flags |= IDE_CD_FLAG_LIMIT_NFRAMES;
+		drive->atapi_flags |= IDE_AFLAG_LIMIT_NFRAMES;
 	}
 
 	return 1;
@@ -735,7 +734,7 @@
 	if (cdrom_decode_status(drive, 0, &stat))
 		return ide_stopped;
 
-	info->cd_flags |= IDE_CD_FLAG_SEEKING;
+	drive->atapi_flags |= IDE_AFLAG_SEEKING;
 
 	if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) {
 		if (--retry == 0)
@@ -892,10 +891,11 @@
 	struct request *rq = HWGROUP(drive)->rq;
 	xfer_func_t *xferfunc;
 	ide_expiry_t *expiry = NULL;
-	int dma_error = 0, dma, stat, ireason, len, thislen, uptodate = 0;
+	int dma_error = 0, dma, stat, thislen, uptodate = 0;
 	int write = (rq_data_dir(rq) == WRITE) ? 1 : 0;
 	unsigned int timeout;
-	u8 lowcyl, highcyl;
+	u16 len;
+	u8 ireason;
 
 	/* check for errors */
 	dma = info->dma;
@@ -923,12 +923,7 @@
 		goto end_request;
 	}
 
-	/* ok we fall to pio :/ */
-	ireason = hwif->INB(hwif->io_ports.nsect_addr) & 0x3;
-	lowcyl  = hwif->INB(hwif->io_ports.lbam_addr);
-	highcyl = hwif->INB(hwif->io_ports.lbah_addr);
-
-	len = lowcyl + (256 * highcyl);
+	ide_read_bcount_and_ireason(drive, &len, &ireason);
 
 	thislen = blk_fs_request(rq) ? len : rq->data_len;
 	if (thislen > len)
@@ -991,10 +986,10 @@
 
 	if (ireason == 0) {
 		write = 1;
-		xferfunc = hwif->output_data;
+		xferfunc = hwif->tp_ops->output_data;
 	} else {
 		write = 0;
-		xferfunc = hwif->input_data;
+		xferfunc = hwif->tp_ops->input_data;
 	}
 
 	/* transfer data */
@@ -1198,9 +1193,10 @@
 	int xferlen;
 
 	if (blk_fs_request(rq)) {
-		if (info->cd_flags & IDE_CD_FLAG_SEEKING) {
+		if (drive->atapi_flags & IDE_AFLAG_SEEKING) {
+			ide_hwif_t *hwif = drive->hwif;
 			unsigned long elapsed = jiffies - info->start_seek;
-			int stat = ide_read_status(drive);
+			int stat = hwif->tp_ops->read_status(hwif);
 
 			if ((stat & SEEK_STAT) != SEEK_STAT) {
 				if (elapsed < IDECD_SEEK_TIMEOUT) {
@@ -1211,7 +1207,7 @@
 				printk(KERN_ERR "%s: DSC timeout\n",
 						drive->name);
 			}
-			info->cd_flags &= ~IDE_CD_FLAG_SEEKING;
+			drive->atapi_flags &= ~IDE_AFLAG_SEEKING;
 		}
 		if (rq_data_dir(rq) == READ &&
 		    IDE_LARGE_SEEK(info->last_block, block,
@@ -1288,7 +1284,7 @@
 	 */
 	cmd[7] = cdi->sanyo_slot % 3;
 
-	return ide_cd_queue_pc(drive, cmd, 0, NULL, 0, sense, 0, REQ_QUIET);
+	return ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, sense, 0, REQ_QUIET);
 }
 
 static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
@@ -1296,8 +1292,8 @@
 			       struct request_sense *sense)
 {
 	struct {
-		__u32 lba;
-		__u32 blocklen;
+		__be32 lba;
+		__be32 blocklen;
 	} capbuf;
 
 	int stat;
@@ -1369,7 +1365,7 @@
 	 */
 	(void) cdrom_check_status(drive, sense);
 
-	if (info->cd_flags & IDE_CD_FLAG_TOC_VALID)
+	if (drive->atapi_flags & IDE_AFLAG_TOC_VALID)
 		return 0;
 
 	/* try to get the total cdrom capacity and sector size */
@@ -1391,7 +1387,7 @@
 	if (stat)
 		return stat;
 
-	if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
+	if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) {
 		toc->hdr.first_track = BCD2BIN(toc->hdr.first_track);
 		toc->hdr.last_track  = BCD2BIN(toc->hdr.last_track);
 	}
@@ -1432,7 +1428,7 @@
 		if (stat)
 			return stat;
 
-		if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
+		if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) {
 			toc->hdr.first_track = (u8)BIN2BCD(CDROM_LEADOUT);
 			toc->hdr.last_track = (u8)BIN2BCD(CDROM_LEADOUT);
 		} else {
@@ -1446,14 +1442,14 @@
 
 	toc->hdr.toc_length = be16_to_cpu(toc->hdr.toc_length);
 
-	if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
+	if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) {
 		toc->hdr.first_track = BCD2BIN(toc->hdr.first_track);
 		toc->hdr.last_track  = BCD2BIN(toc->hdr.last_track);
 	}
 
 	for (i = 0; i <= ntracks; i++) {
-		if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
-			if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD)
+		if (drive->atapi_flags & IDE_AFLAG_TOCADDR_AS_BCD) {
+			if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD)
 				toc->ent[i].track = BCD2BIN(toc->ent[i].track);
 			msf_from_bcd(&toc->ent[i].addr.msf);
 		}
@@ -1476,7 +1472,7 @@
 		toc->last_session_lba = msf_to_lba(0, 2, 0); /* 0m 2s 0f */
 	}
 
-	if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
+	if (drive->atapi_flags & IDE_AFLAG_TOCADDR_AS_BCD) {
 		/* re-read multisession information using MSF format */
 		stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp,
 					   sizeof(ms_tmp), sense);
@@ -1500,7 +1496,7 @@
 	}
 
 	/* Remember that we've read this stuff. */
-	info->cd_flags |= IDE_CD_FLAG_TOC_VALID;
+	drive->atapi_flags |= IDE_AFLAG_TOC_VALID;
 
 	return 0;
 }
@@ -1512,7 +1508,7 @@
 	struct packet_command cgc;
 	int stat, attempts = 3, size = ATAPI_CAPABILITIES_PAGE_SIZE;
 
-	if ((info->cd_flags & IDE_CD_FLAG_FULL_CAPS_PAGE) == 0)
+	if ((drive->atapi_flags & IDE_AFLAG_FULL_CAPS_PAGE) == 0)
 		size -= ATAPI_CAPABILITIES_PAGE_PAD_SIZE;
 
 	init_cdrom_command(&cgc, buf, size, CGC_DATA_UNKNOWN);
@@ -1530,15 +1526,12 @@
 	struct cdrom_info *cd = drive->driver_data;
 	u16 curspeed, maxspeed;
 
-	curspeed = *(u16 *)&buf[8 + 14];
-	maxspeed = *(u16 *)&buf[8 +  8];
-
-	if (cd->cd_flags & IDE_CD_FLAG_LE_SPEED_FIELDS) {
-		curspeed = le16_to_cpu(curspeed);
-		maxspeed = le16_to_cpu(maxspeed);
+	if (drive->atapi_flags & IDE_AFLAG_LE_SPEED_FIELDS) {
+		curspeed = le16_to_cpup((__le16 *)&buf[8 + 14]);
+		maxspeed = le16_to_cpup((__le16 *)&buf[8 + 8]);
 	} else {
-		curspeed = be16_to_cpu(curspeed);
-		maxspeed = be16_to_cpu(maxspeed);
+		curspeed = be16_to_cpup((__be16 *)&buf[8 + 14]);
+		maxspeed = be16_to_cpup((__be16 *)&buf[8 + 8]);
 	}
 
 	cd->current_speed = (curspeed + (176/2)) / 176;
@@ -1579,7 +1572,7 @@
 	devinfo->handle = drive;
 	strcpy(devinfo->name, drive->name);
 
-	if (info->cd_flags & IDE_CD_FLAG_NO_SPEED_SELECT)
+	if (drive->atapi_flags & IDE_AFLAG_NO_SPEED_SELECT)
 		devinfo->mask |= CDC_SELECT_SPEED;
 
 	devinfo->disk = info->disk;
@@ -1605,8 +1598,8 @@
 		return nslots;
 	}
 
-	if (cd->cd_flags & IDE_CD_FLAG_PRE_ATAPI12) {
-		cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT;
+	if (drive->atapi_flags & IDE_AFLAG_PRE_ATAPI12) {
+		drive->atapi_flags &= ~IDE_AFLAG_NO_EJECT;
 		cdi->mask &= ~CDC_PLAY_AUDIO;
 		return nslots;
 	}
@@ -1624,9 +1617,9 @@
 		return 0;
 
 	if ((buf[8 + 6] & 0x01) == 0)
-		cd->cd_flags |= IDE_CD_FLAG_NO_DOORLOCK;
+		drive->atapi_flags |= IDE_AFLAG_NO_DOORLOCK;
 	if (buf[8 + 6] & 0x08)
-		cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT;
+		drive->atapi_flags &= ~IDE_AFLAG_NO_EJECT;
 	if (buf[8 + 3] & 0x01)
 		cdi->mask &= ~CDC_CD_R;
 	if (buf[8 + 3] & 0x02)
@@ -1637,7 +1630,7 @@
 		cdi->mask &= ~(CDC_DVD_RAM | CDC_RAM);
 	if (buf[8 + 3] & 0x10)
 		cdi->mask &= ~CDC_DVD_R;
-	if ((buf[8 + 4] & 0x01) || (cd->cd_flags & IDE_CD_FLAG_PLAY_AUDIO_OK))
+	if ((buf[8 + 4] & 0x01) || (drive->atapi_flags & IDE_AFLAG_PLAY_AUDIO_OK))
 		cdi->mask &= ~CDC_PLAY_AUDIO;
 
 	mechtype = buf[8 + 6] >> 5;
@@ -1679,7 +1672,7 @@
 	else
 		printk(KERN_CONT " drive");
 
-	printk(KERN_CONT ", %dkB Cache\n", be16_to_cpu(*(u16 *)&buf[8 + 12]));
+	printk(KERN_CONT ", %dkB Cache\n", be16_to_cpup((__be16 *)&buf[8 + 12]));
 
 	return nslots;
 }
@@ -1802,43 +1795,43 @@
 
 static const struct cd_list_entry ide_cd_quirks_list[] = {
 	/* Limit transfer size per interrupt. */
-	{ "SAMSUNG CD-ROM SCR-2430", NULL,   IDE_CD_FLAG_LIMIT_NFRAMES	    },
-	{ "SAMSUNG CD-ROM SCR-2432", NULL,   IDE_CD_FLAG_LIMIT_NFRAMES	    },
+	{ "SAMSUNG CD-ROM SCR-2430", NULL,   IDE_AFLAG_LIMIT_NFRAMES	     },
+	{ "SAMSUNG CD-ROM SCR-2432", NULL,   IDE_AFLAG_LIMIT_NFRAMES	     },
 	/* SCR-3231 doesn't support the SET_CD_SPEED command. */
-	{ "SAMSUNG CD-ROM SCR-3231", NULL,   IDE_CD_FLAG_NO_SPEED_SELECT    },
+	{ "SAMSUNG CD-ROM SCR-3231", NULL,   IDE_AFLAG_NO_SPEED_SELECT	     },
 	/* Old NEC260 (not R) was released before ATAPI 1.2 spec. */
-	{ "NEC CD-ROM DRIVE:260",    "1.01", IDE_CD_FLAG_TOCADDR_AS_BCD |
-					     IDE_CD_FLAG_PRE_ATAPI12,	    },
+	{ "NEC CD-ROM DRIVE:260",    "1.01", IDE_AFLAG_TOCADDR_AS_BCD |
+					     IDE_AFLAG_PRE_ATAPI12,	     },
 	/* Vertos 300, some versions of this drive like to talk BCD. */
-	{ "V003S0DS",		     NULL,   IDE_CD_FLAG_VERTOS_300_SSD,    },
+	{ "V003S0DS",		     NULL,   IDE_AFLAG_VERTOS_300_SSD,	     },
 	/* Vertos 600 ESD. */
-	{ "V006E0DS",		     NULL,   IDE_CD_FLAG_VERTOS_600_ESD,    },
+	{ "V006E0DS",		     NULL,   IDE_AFLAG_VERTOS_600_ESD,	     },
 	/*
 	 * Sanyo 3 CD changer uses a non-standard command for CD changing
 	 * (by default standard ATAPI support for CD changers is used).
 	 */
-	{ "CD-ROM CDR-C3 G",	     NULL,   IDE_CD_FLAG_SANYO_3CD	    },
-	{ "CD-ROM CDR-C3G",	     NULL,   IDE_CD_FLAG_SANYO_3CD	    },
-	{ "CD-ROM CDR_C36",	     NULL,   IDE_CD_FLAG_SANYO_3CD	    },
+	{ "CD-ROM CDR-C3 G",	     NULL,   IDE_AFLAG_SANYO_3CD	     },
+	{ "CD-ROM CDR-C3G",	     NULL,   IDE_AFLAG_SANYO_3CD	     },
+	{ "CD-ROM CDR_C36",	     NULL,   IDE_AFLAG_SANYO_3CD	     },
 	/* Stingray 8X CD-ROM. */
-	{ "STINGRAY 8422 IDE 8X CD-ROM 7-27-95", NULL, IDE_CD_FLAG_PRE_ATAPI12},
+	{ "STINGRAY 8422 IDE 8X CD-ROM 7-27-95", NULL, IDE_AFLAG_PRE_ATAPI12 },
 	/*
 	 * ACER 50X CD-ROM and WPI 32X CD-ROM require the full spec length
 	 * mode sense page capabilities size, but older drives break.
 	 */
-	{ "ATAPI CD ROM DRIVE 50X MAX",	NULL,	IDE_CD_FLAG_FULL_CAPS_PAGE  },
-	{ "WPI CDS-32X",		NULL,	IDE_CD_FLAG_FULL_CAPS_PAGE  },
+	{ "ATAPI CD ROM DRIVE 50X MAX",	NULL,	IDE_AFLAG_FULL_CAPS_PAGE     },
+	{ "WPI CDS-32X",		NULL,	IDE_AFLAG_FULL_CAPS_PAGE     },
 	/* ACER/AOpen 24X CD-ROM has the speed fields byte-swapped. */
-	{ "",			     "241N", IDE_CD_FLAG_LE_SPEED_FIELDS    },
+	{ "",			     "241N", IDE_AFLAG_LE_SPEED_FIELDS       },
 	/*
 	 * Some drives used by Apple don't advertise audio play
 	 * but they do support reading TOC & audio datas.
 	 */
-	{ "MATSHITADVD-ROM SR-8187", NULL,   IDE_CD_FLAG_PLAY_AUDIO_OK	    },
-	{ "MATSHITADVD-ROM SR-8186", NULL,   IDE_CD_FLAG_PLAY_AUDIO_OK	    },
-	{ "MATSHITADVD-ROM SR-8176", NULL,   IDE_CD_FLAG_PLAY_AUDIO_OK	    },
-	{ "MATSHITADVD-ROM SR-8174", NULL,   IDE_CD_FLAG_PLAY_AUDIO_OK	    },
-	{ "Optiarc DVD RW AD-5200A", NULL,   IDE_CD_FLAG_PLAY_AUDIO_OK      },
+	{ "MATSHITADVD-ROM SR-8187", NULL,   IDE_AFLAG_PLAY_AUDIO_OK	     },
+	{ "MATSHITADVD-ROM SR-8186", NULL,   IDE_AFLAG_PLAY_AUDIO_OK	     },
+	{ "MATSHITADVD-ROM SR-8176", NULL,   IDE_AFLAG_PLAY_AUDIO_OK	     },
+	{ "MATSHITADVD-ROM SR-8174", NULL,   IDE_AFLAG_PLAY_AUDIO_OK	     },
+	{ "Optiarc DVD RW AD-5200A", NULL,   IDE_AFLAG_PLAY_AUDIO_OK	     },
 	{ NULL, NULL, 0 }
 };
 
@@ -1873,20 +1866,20 @@
 
 	drive->special.all	= 0;
 
-	cd->cd_flags = IDE_CD_FLAG_MEDIA_CHANGED | IDE_CD_FLAG_NO_EJECT |
+	drive->atapi_flags = IDE_AFLAG_MEDIA_CHANGED | IDE_AFLAG_NO_EJECT |
 		       ide_cd_flags(id);
 
 	if ((id->config & 0x0060) == 0x20)
-		cd->cd_flags |= IDE_CD_FLAG_DRQ_INTERRUPT;
+		drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;
 
-	if ((cd->cd_flags & IDE_CD_FLAG_VERTOS_300_SSD) &&
+	if ((drive->atapi_flags & IDE_AFLAG_VERTOS_300_SSD) &&
 	    id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
-		cd->cd_flags |= (IDE_CD_FLAG_TOCTRACKS_AS_BCD |
-				 IDE_CD_FLAG_TOCADDR_AS_BCD);
-	else if ((cd->cd_flags & IDE_CD_FLAG_VERTOS_600_ESD) &&
+		drive->atapi_flags |= (IDE_AFLAG_TOCTRACKS_AS_BCD |
+				     IDE_AFLAG_TOCADDR_AS_BCD);
+	else if ((drive->atapi_flags & IDE_AFLAG_VERTOS_600_ESD) &&
 		 id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
-		cd->cd_flags |= IDE_CD_FLAG_TOCTRACKS_AS_BCD;
-	else if (cd->cd_flags & IDE_CD_FLAG_SANYO_3CD)
+		drive->atapi_flags |= IDE_AFLAG_TOCTRACKS_AS_BCD;
+	else if (drive->atapi_flags & IDE_AFLAG_SANYO_3CD)
 		/* 3 => use CD in slot 0 */
 		cdi->sanyo_slot = 3;
 
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index fe0ea36..61a4599 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -27,42 +27,6 @@
 #define ATAPI_CAPABILITIES_PAGE_SIZE		(8 + 20)
 #define ATAPI_CAPABILITIES_PAGE_PAD_SIZE	4
 
-enum {
-	/* Device sends an interrupt when ready for a packet command. */
-	IDE_CD_FLAG_DRQ_INTERRUPT	= (1 << 0),
-	/* Drive cannot lock the door. */
-	IDE_CD_FLAG_NO_DOORLOCK		= (1 << 1),
-	/* Drive cannot eject the disc. */
-	IDE_CD_FLAG_NO_EJECT		= (1 << 2),
-	/* Drive is a pre ATAPI 1.2 drive. */
-	IDE_CD_FLAG_PRE_ATAPI12		= (1 << 3),
-	/* TOC addresses are in BCD. */
-	IDE_CD_FLAG_TOCADDR_AS_BCD	= (1 << 4),
-	/* TOC track numbers are in BCD. */
-	IDE_CD_FLAG_TOCTRACKS_AS_BCD	= (1 << 5),
-	/*
-	 * Drive does not provide data in multiples of SECTOR_SIZE
-	 * when more than one interrupt is needed.
-	 */
-	IDE_CD_FLAG_LIMIT_NFRAMES	= (1 << 6),
-	/* Seeking in progress. */
-	IDE_CD_FLAG_SEEKING		= (1 << 7),
-	/* Driver has noticed a media change. */
-	IDE_CD_FLAG_MEDIA_CHANGED	= (1 << 8),
-	/* Saved TOC information is current. */
-	IDE_CD_FLAG_TOC_VALID		= (1 << 9),
-	/* We think that the drive door is locked. */
-	IDE_CD_FLAG_DOOR_LOCKED		= (1 << 10),
-	/* SET_CD_SPEED command is unsupported. */
-	IDE_CD_FLAG_NO_SPEED_SELECT	= (1 << 11),
-	IDE_CD_FLAG_VERTOS_300_SSD	= (1 << 12),
-	IDE_CD_FLAG_VERTOS_600_ESD	= (1 << 13),
-	IDE_CD_FLAG_SANYO_3CD		= (1 << 14),
-	IDE_CD_FLAG_FULL_CAPS_PAGE	= (1 << 15),
-	IDE_CD_FLAG_PLAY_AUDIO_OK	= (1 << 16),
-	IDE_CD_FLAG_LE_SPEED_FIELDS	= (1 << 17),
-};
-
 /* Structure of a MSF cdrom address. */
 struct atapi_msf {
 	byte reserved;
@@ -128,8 +92,6 @@
 	unsigned long last_block;
 	unsigned long start_seek;
 
-	unsigned int cd_flags;
-
 	u8 max_speed;		/* Max speed of the drive. */
 	u8 current_speed;	/* Current speed of the drive. */
 
diff --git a/drivers/ide/ide-cd_ioctl.c b/drivers/ide/ide-cd_ioctl.c
index 24d002a..74231b4 100644
--- a/drivers/ide/ide-cd_ioctl.c
+++ b/drivers/ide/ide-cd_ioctl.c
@@ -27,10 +27,9 @@
 void ide_cdrom_release_real(struct cdrom_device_info *cdi)
 {
 	ide_drive_t *drive = cdi->handle;
-	struct cdrom_info *cd = drive->driver_data;
 
 	if (!cdi->use_count)
-		cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
+		drive->atapi_flags &= ~IDE_AFLAG_TOC_VALID;
 }
 
 /*
@@ -83,13 +82,12 @@
 				       int slot_nr)
 {
 	ide_drive_t *drive = cdi->handle;
-	struct cdrom_info *cd = drive->driver_data;
 	int retval;
 
 	if (slot_nr == CDSL_CURRENT) {
 		(void) cdrom_check_status(drive, NULL);
-		retval = (cd->cd_flags & IDE_CD_FLAG_MEDIA_CHANGED) ? 1 : 0;
-		cd->cd_flags &= ~IDE_CD_FLAG_MEDIA_CHANGED;
+		retval = (drive->atapi_flags & IDE_AFLAG_MEDIA_CHANGED) ? 1 : 0;
+		drive->atapi_flags &= ~IDE_AFLAG_MEDIA_CHANGED;
 		return retval;
 	} else {
 		return -EINVAL;
@@ -107,11 +105,11 @@
 	char loej = 0x02;
 	unsigned char cmd[BLK_MAX_CDB];
 
-	if ((cd->cd_flags & IDE_CD_FLAG_NO_EJECT) && !ejectflag)
+	if ((drive->atapi_flags & IDE_AFLAG_NO_EJECT) && !ejectflag)
 		return -EDRIVE_CANT_DO_THIS;
 
 	/* reload fails on some drives, if the tray is locked */
-	if ((cd->cd_flags & IDE_CD_FLAG_DOOR_LOCKED) && ejectflag)
+	if ((drive->atapi_flags & IDE_AFLAG_DOOR_LOCKED) && ejectflag)
 		return 0;
 
 	/* only tell drive to close tray if open, if it can do that */
@@ -123,7 +121,7 @@
 	cmd[0] = GPCMD_START_STOP_UNIT;
 	cmd[4] = loej | (ejectflag != 0);
 
-	return ide_cd_queue_pc(drive, cmd, 0, NULL, 0, sense, 0, 0);
+	return ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, sense, 0, 0);
 }
 
 /* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */
@@ -131,7 +129,6 @@
 int ide_cd_lockdoor(ide_drive_t *drive, int lockflag,
 		    struct request_sense *sense)
 {
-	struct cdrom_info *cd = drive->driver_data;
 	struct request_sense my_sense;
 	int stat;
 
@@ -139,7 +136,7 @@
 		sense = &my_sense;
 
 	/* If the drive cannot lock the door, just pretend. */
-	if (cd->cd_flags & IDE_CD_FLAG_NO_DOORLOCK) {
+	if (drive->atapi_flags & IDE_AFLAG_NO_DOORLOCK) {
 		stat = 0;
 	} else {
 		unsigned char cmd[BLK_MAX_CDB];
@@ -149,7 +146,7 @@
 		cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
 		cmd[4] = lockflag ? 1 : 0;
 
-		stat = ide_cd_queue_pc(drive, cmd, 0, NULL, 0,
+		stat = ide_cd_queue_pc(drive, cmd, 0, NULL, NULL,
 				       sense, 0, 0);
 	}
 
@@ -160,7 +157,7 @@
 	    (sense->asc == 0x24 || sense->asc == 0x20)) {
 		printk(KERN_ERR "%s: door locking not supported\n",
 			drive->name);
-		cd->cd_flags |= IDE_CD_FLAG_NO_DOORLOCK;
+		drive->atapi_flags |= IDE_AFLAG_NO_DOORLOCK;
 		stat = 0;
 	}
 
@@ -170,9 +167,9 @@
 
 	if (stat == 0) {
 		if (lockflag)
-			cd->cd_flags |= IDE_CD_FLAG_DOOR_LOCKED;
+			drive->atapi_flags |= IDE_AFLAG_DOOR_LOCKED;
 		else
-			cd->cd_flags &= ~IDE_CD_FLAG_DOOR_LOCKED;
+			drive->atapi_flags &= ~IDE_AFLAG_DOOR_LOCKED;
 	}
 
 	return stat;
@@ -231,7 +228,7 @@
 		cmd[5] = speed & 0xff;
 	}
 
-	stat = ide_cd_queue_pc(drive, cmd, 0, NULL, 0, &sense, 0, 0);
+	stat = ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, &sense, 0, 0);
 
 	if (!ide_cdrom_get_capabilities(drive, buf)) {
 		ide_cdrom_update_speed(drive, buf);
@@ -250,7 +247,7 @@
 	struct request_sense sense;
 	int ret;
 
-	if ((info->cd_flags & IDE_CD_FLAG_TOC_VALID) == 0 || !info->toc) {
+	if ((drive->atapi_flags & IDE_AFLAG_TOC_VALID) == 0 || !info->toc) {
 		ret = ide_cd_read_toc(drive, &sense);
 		if (ret)
 			return ret;
@@ -308,7 +305,7 @@
 	 * A reset will unlock the door. If it was previously locked,
 	 * lock it again.
 	 */
-	if (cd->cd_flags & IDE_CD_FLAG_DOOR_LOCKED)
+	if (drive->atapi_flags & IDE_AFLAG_DOOR_LOCKED)
 		(void)ide_cd_lockdoor(drive, 1, &sense);
 
 	return ret;
@@ -324,7 +321,7 @@
 	/*
 	 * don't serve cached data, if the toc isn't valid
 	 */
-	if ((info->cd_flags & IDE_CD_FLAG_TOC_VALID) == 0)
+	if ((drive->atapi_flags & IDE_AFLAG_TOC_VALID) == 0)
 		return -EINVAL;
 
 	/* Check validity of requested track number. */
@@ -374,7 +371,7 @@
 	lba_to_msf(lba_start,   &cmd[3], &cmd[4], &cmd[5]);
 	lba_to_msf(lba_end - 1, &cmd[6], &cmd[7], &cmd[8]);
 
-	return ide_cd_queue_pc(drive, cmd, 0, NULL, 0, &sense, 0, 0);
+	return ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, &sense, 0, 0);
 }
 
 static int ide_cd_read_tochdr(ide_drive_t *drive, void *arg)
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 3a2e802..df5fe57 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -158,7 +158,7 @@
 	write = (task->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0;
 
 	if (dma)
-		index = drive->vdma ? 4 : 8;
+		index = 8;
 	else
 		index = drive->mult_count ? 0 : 4;
 
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 7ee44f8..be99d46 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -100,10 +100,11 @@
  
 ide_startstop_t ide_dma_intr (ide_drive_t *drive)
 {
+	ide_hwif_t *hwif = drive->hwif;
 	u8 stat = 0, dma_stat = 0;
 
-	dma_stat = drive->hwif->dma_ops->dma_end(drive);
-	stat = ide_read_status(drive);
+	dma_stat = hwif->dma_ops->dma_end(drive);
+	stat = hwif->tp_ops->read_status(hwif);
 
 	if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
 		if (!dma_stat) {
@@ -334,7 +335,7 @@
 static int dma_timer_expiry (ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	u8 dma_stat		= hwif->INB(hwif->dma_status);
+	u8 dma_stat		= hwif->tp_ops->read_sff_dma_status(hwif);
 
 	printk(KERN_WARNING "%s: dma_timer_expiry: dma status == 0x%02x\n",
 		drive->name, dma_stat);
@@ -369,14 +370,18 @@
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	u8 unit			= (drive->select.b.unit & 0x01);
-	u8 dma_stat		= hwif->INB(hwif->dma_status);
+	u8 dma_stat		= hwif->tp_ops->read_sff_dma_status(hwif);
 
 	if (on)
 		dma_stat |= (1 << (5 + unit));
 	else
 		dma_stat &= ~(1 << (5 + unit));
 
-	hwif->OUTB(dma_stat, hwif->dma_status);
+	if (hwif->host_flags & IDE_HFLAG_MMIO)
+		writeb(dma_stat,
+		       (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
+	else
+		outb(dma_stat, hwif->dma_base + ATA_DMA_STATUS);
 }
 
 EXPORT_SYMBOL_GPL(ide_dma_host_set);
@@ -449,6 +454,7 @@
 	ide_hwif_t *hwif = drive->hwif;
 	struct request *rq = HWGROUP(drive)->rq;
 	unsigned int reading;
+	u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
 	u8 dma_stat;
 
 	if (rq_data_dir(rq))
@@ -470,13 +476,21 @@
 		outl(hwif->dmatable_dma, hwif->dma_base + ATA_DMA_TABLE_OFS);
 
 	/* specify r/w */
-	hwif->OUTB(reading, hwif->dma_command);
+	if (mmio)
+		writeb(reading, (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+	else
+		outb(reading, hwif->dma_base + ATA_DMA_CMD);
 
-	/* read dma_status for INTR & ERROR flags */
-	dma_stat = hwif->INB(hwif->dma_status);
+	/* read DMA status for INTR & ERROR flags */
+	dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
 
 	/* clear INTR & ERROR flags */
-	hwif->OUTB(dma_stat|6, hwif->dma_status);
+	if (mmio)
+		writeb(dma_stat | 6,
+		       (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
+	else
+		outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
+
 	drive->waiting_for_dma = 1;
 	return 0;
 }
@@ -492,16 +506,24 @@
 
 void ide_dma_start(ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-	u8 dma_cmd		= hwif->INB(hwif->dma_command);
+	ide_hwif_t *hwif = drive->hwif;
+	u8 dma_cmd;
 
 	/* Note that this is done *after* the cmd has
 	 * been issued to the drive, as per the BM-IDE spec.
 	 * The Promise Ultra33 doesn't work correctly when
 	 * we do this part before issuing the drive cmd.
 	 */
-	/* start DMA */
-	hwif->OUTB(dma_cmd|1, hwif->dma_command);
+	if (hwif->host_flags & IDE_HFLAG_MMIO) {
+		dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+		/* start DMA */
+		writeb(dma_cmd | 1,
+		       (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+	} else {
+		dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
+		outb(dma_cmd | 1, hwif->dma_base + ATA_DMA_CMD);
+	}
+
 	hwif->dma = 1;
 	wmb();
 }
@@ -511,18 +533,33 @@
 /* returns 1 on error, 0 otherwise */
 int __ide_dma_end (ide_drive_t *drive)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
+	ide_hwif_t *hwif = drive->hwif;
+	u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
 	u8 dma_stat = 0, dma_cmd = 0;
 
 	drive->waiting_for_dma = 0;
-	/* get dma_command mode */
-	dma_cmd = hwif->INB(hwif->dma_command);
-	/* stop DMA */
-	hwif->OUTB(dma_cmd&~1, hwif->dma_command);
+
+	if (mmio) {
+		/* get DMA command mode */
+		dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+		/* stop DMA */
+		writeb(dma_cmd & ~1,
+		       (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
+	} else {
+		dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
+		outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
+	}
+
 	/* get DMA status */
-	dma_stat = hwif->INB(hwif->dma_status);
-	/* clear the INTR & ERROR bits */
-	hwif->OUTB(dma_stat|6, hwif->dma_status);
+	dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+
+	if (mmio)
+		/* clear the INTR & ERROR bits */
+		writeb(dma_stat | 6,
+		       (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
+	else
+		outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
+
 	/* purge DMA mappings */
 	ide_destroy_dmatable(drive);
 	/* verify good DMA status */
@@ -537,7 +574,7 @@
 int ide_dma_test_irq(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	u8 dma_stat		= hwif->INB(hwif->dma_status);
+	u8 dma_stat		= hwif->tp_ops->read_sff_dma_status(hwif);
 
 	/* return 1 if INTR asserted */
 	if ((dma_stat & 4) == 4)
@@ -719,9 +756,8 @@
 static int ide_dma_check(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = drive->hwif;
-	int vdma = (hwif->host_flags & IDE_HFLAG_VDMA)? 1 : 0;
 
-	if (!vdma && ide_tune_dma(drive))
+	if (ide_tune_dma(drive))
 		return 0;
 
 	/* TODO: always do PIO fallback */
@@ -730,7 +766,7 @@
 
 	ide_set_max_pio(drive);
 
-	return vdma ? 0 : -1;
+	return -1;
 }
 
 int ide_id_dma_bug(ide_drive_t *drive)
@@ -842,7 +878,7 @@
 }
 EXPORT_SYMBOL_GPL(ide_allocate_dma_engine);
 
-static const struct ide_dma_ops sff_dma_ops = {
+const struct ide_dma_ops sff_dma_ops = {
 	.dma_host_set		= ide_dma_host_set,
 	.dma_setup		= ide_dma_setup,
 	.dma_exec_cmd		= ide_dma_exec_cmd,
@@ -852,18 +888,5 @@
 	.dma_timeout		= ide_dma_timeout,
 	.dma_lost_irq		= ide_dma_lost_irq,
 };
-
-void ide_setup_dma(ide_hwif_t *hwif, unsigned long base)
-{
-	hwif->dma_base = base;
-
-	if (!hwif->dma_command)
-		hwif->dma_command	= hwif->dma_base + 0;
-	if (!hwif->dma_status)
-		hwif->dma_status	= hwif->dma_base + 2;
-
-	hwif->dma_ops = &sff_dma_ops;
-}
-
-EXPORT_SYMBOL_GPL(ide_setup_dma);
+EXPORT_SYMBOL_GPL(sff_dma_ops);
 #endif /* CONFIG_BLK_DEV_IDEDMA_SFF */
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 011d720..3d8e6dd 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -125,26 +125,10 @@
 	int wp;
 	/* Supports format progress report */
 	int srfp;
-	/* Status/Action flags */
-	unsigned long flags;
 } idefloppy_floppy_t;
 
 #define IDEFLOPPY_TICKS_DELAY	HZ/20	/* default delay for ZIP 100 (50ms) */
 
-/* Floppy flag bits values. */
-enum {
-	/* DRQ interrupt device */
-	IDEFLOPPY_FLAG_DRQ_INTERRUPT		= (1 <<	0),
-	/* Media may have changed */
-	IDEFLOPPY_FLAG_MEDIA_CHANGED		= (1 << 1),
-	/* Format in progress */
-	IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS	= (1 << 2),
-	/* Avoid commands not supported in Clik drive */
-	IDEFLOPPY_FLAG_CLIK_DRIVE		= (1 << 3),
-	/* Requires BH algorithm for packets */
-	IDEFLOPPY_FLAG_ZIP_DRIVE		= (1 << 4),
-};
-
 /* Defines for the MODE SENSE command */
 #define MODE_SENSE_CURRENT		0x00
 #define MODE_SENSE_CHANGEABLE		0x01
@@ -247,9 +231,9 @@
 
 		data = bvec_kmap_irq(bvec, &flags);
 		if (direction)
-			hwif->output_data(drive, NULL, data, count);
+			hwif->tp_ops->output_data(drive, NULL, data, count);
 		else
-			hwif->input_data(drive, NULL, data, count);
+			hwif->tp_ops->input_data(drive, NULL, data, count);
 		bvec_kunmap_irq(data, &flags);
 
 		bcount -= count;
@@ -291,6 +275,7 @@
 	rq->cmd_type = REQ_TYPE_SPECIAL;
 	rq->cmd_flags |= REQ_PREEMPT;
 	rq->rq_disk = floppy->disk;
+	memcpy(rq->cmd, pc->c, 12);
 	ide_do_drive_cmd(drive, rq);
 }
 
@@ -354,7 +339,6 @@
 	memset(pc, 0, sizeof(*pc));
 	pc->buf = pc->pc_buf;
 	pc->buf_size = IDEFLOPPY_PC_BUFFER_SIZE;
-	pc->callback = ide_floppy_callback;
 }
 
 static void idefloppy_create_request_sense_cmd(struct ide_atapi_pc *pc)
@@ -402,7 +386,7 @@
 	idefloppy_floppy_t *floppy = drive->driver_data;
 
 	/* Send the actual packet */
-	drive->hwif->output_data(drive, NULL, floppy->pc->c, 12);
+	drive->hwif->tp_ops->output_data(drive, NULL, floppy->pc->c, 12);
 
 	/* Timeout for the packet command */
 	return IDEFLOPPY_WAIT_CMD;
@@ -429,7 +413,7 @@
 	 * 40 and 50msec work well. idefloppy_pc_intr will not be actually
 	 * used until after the packet is moved in about 50 msec.
 	 */
-	if (pc->flags & PC_FLAG_ZIP_DRIVE) {
+	if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) {
 		timeout = floppy->ticks;
 		expiry = &idefloppy_transfer_pc;
 	} else {
@@ -474,7 +458,7 @@
 		pc->error = IDEFLOPPY_ERROR_GENERAL;
 
 		floppy->failed_pc = NULL;
-		pc->callback(drive);
+		drive->pc_callback(drive);
 		return ide_stopped;
 	}
 
@@ -574,6 +558,8 @@
 	put_unaligned(cpu_to_be16(blocks), (unsigned short *)&pc->c[7]);
 	put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[2]);
 
+	memcpy(rq->cmd, pc->c, 12);
+
 	pc->rq = rq;
 	pc->b_count = cmd == READ ? 0 : rq->bio->bi_size;
 	if (rq->cmd_flags & REQ_RW)
@@ -647,12 +633,6 @@
 		return ide_stopped;
 	}
 
-	if (floppy->flags & IDEFLOPPY_FLAG_DRQ_INTERRUPT)
-		pc->flags |= PC_FLAG_DRQ_INTERRUPT;
-
-	if (floppy->flags & IDEFLOPPY_FLAG_ZIP_DRIVE)
-		pc->flags |= PC_FLAG_ZIP_DRIVE;
-
 	pc->rq = rq;
 
 	return idefloppy_issue_pc(drive, pc);
@@ -671,6 +651,7 @@
 	rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
 	rq->buffer = (char *) pc;
 	rq->cmd_type = REQ_TYPE_SPECIAL;
+	memcpy(rq->cmd, pc->c, 12);
 	error = blk_execute_rq(drive->queue, floppy->disk, rq, 0);
 	blk_put_request(rq);
 
@@ -795,7 +776,7 @@
 		switch (pc.buf[desc_start + 4] & 0x03) {
 		/* Clik! drive returns this instead of CAPACITY_CURRENT */
 		case CAPACITY_UNFORMATTED:
-			if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE))
+			if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE))
 				/*
 				 * If it is not a clik drive, break out
 				 * (maintains previous driver behaviour)
@@ -841,7 +822,7 @@
 	}
 
 	/* Clik! disk does not support get_flexible_disk_page */
-	if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE))
+	if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE))
 		(void) ide_floppy_get_flexible_disk_page(drive);
 
 	set_capacity(floppy->disk, floppy->blocks * floppy->bs_factor);
@@ -949,11 +930,12 @@
 
 		/* Else assume format_unit has finished, and we're at 0x10000 */
 	} else {
+		ide_hwif_t *hwif = drive->hwif;
 		unsigned long flags;
 		u8 stat;
 
 		local_irq_save(flags);
-		stat = ide_read_status(drive);
+		stat = hwif->tp_ops->read_status(hwif);
 		local_irq_restore(flags);
 
 		progress_indication = ((stat & SEEK_STAT) == 0) ? 0 : 0x10000;
@@ -1039,9 +1021,10 @@
 
 	*((u16 *) &gcw) = drive->id->config;
 	floppy->pc = floppy->pc_stack;
+	drive->pc_callback = ide_floppy_callback;
 
 	if (((gcw[0] & 0x60) >> 5) == 1)
-		floppy->flags |= IDEFLOPPY_FLAG_DRQ_INTERRUPT;
+		drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;
 	/*
 	 * We used to check revisions here. At this point however I'm giving up.
 	 * Just assume they are all broken, its easier.
@@ -1052,7 +1035,7 @@
 	 * we'll leave the limitation below for the 2.2.x tree.
 	 */
 	if (!strncmp(drive->id->model, "IOMEGA ZIP 100 ATAPI", 20)) {
-		floppy->flags |= IDEFLOPPY_FLAG_ZIP_DRIVE;
+		drive->atapi_flags |= IDE_AFLAG_ZIP_DRIVE;
 		/* This value will be visible in the /proc/ide/hdx/settings */
 		floppy->ticks = IDEFLOPPY_TICKS_DELAY;
 		blk_queue_max_sectors(drive->queue, 64);
@@ -1064,7 +1047,7 @@
 	 */
 	if (strncmp(drive->id->model, "IOMEGA Clik!", 11) == 0) {
 		blk_queue_max_sectors(drive->queue, 64);
-		floppy->flags |= IDEFLOPPY_FLAG_CLIK_DRIVE;
+		drive->atapi_flags |= IDE_AFLAG_CLIK_DRIVE;
 	}
 
 	(void) ide_floppy_get_capacity(drive);
@@ -1153,7 +1136,7 @@
 	floppy->openers++;
 
 	if (floppy->openers == 1) {
-		floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
+		drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
 		/* Just in case */
 
 		idefloppy_init_pc(&pc);
@@ -1180,14 +1163,14 @@
 			ret = -EROFS;
 			goto out_put_floppy;
 		}
-		floppy->flags |= IDEFLOPPY_FLAG_MEDIA_CHANGED;
+		drive->atapi_flags |= IDE_AFLAG_MEDIA_CHANGED;
 		/* IOMEGA Clik! drives do not support lock/unlock commands */
-		if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) {
+		if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) {
 			idefloppy_create_prevent_cmd(&pc, 1);
 			(void) idefloppy_queue_pc_tail(drive, &pc);
 		}
 		check_disk_change(inode->i_bdev);
-	} else if (floppy->flags & IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS) {
+	} else if (drive->atapi_flags & IDE_AFLAG_FORMAT_IN_PROGRESS) {
 		ret = -EBUSY;
 		goto out_put_floppy;
 	}
@@ -1210,12 +1193,12 @@
 
 	if (floppy->openers == 1) {
 		/* IOMEGA Clik! drives do not support lock/unlock commands */
-		if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) {
+		if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) {
 			idefloppy_create_prevent_cmd(&pc, 0);
 			(void) idefloppy_queue_pc_tail(drive, &pc);
 		}
 
-		floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
+		drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
 	}
 
 	floppy->openers--;
@@ -1236,15 +1219,17 @@
 	return 0;
 }
 
-static int ide_floppy_lockdoor(idefloppy_floppy_t *floppy,
-		struct ide_atapi_pc *pc, unsigned long arg, unsigned int cmd)
+static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc,
+			       unsigned long arg, unsigned int cmd)
 {
+	idefloppy_floppy_t *floppy = drive->driver_data;
+
 	if (floppy->openers > 1)
 		return -EBUSY;
 
 	/* The IOMEGA Clik! Drive doesn't support this command -
 	 * no room for an eject mechanism */
-	if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) {
+	if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) {
 		int prevent = arg ? 1 : 0;
 
 		if (cmd == CDROMEJECT)
@@ -1265,16 +1250,17 @@
 static int ide_floppy_format_unit(idefloppy_floppy_t *floppy,
 				  int __user *arg)
 {
-	int blocks, length, flags, err = 0;
 	struct ide_atapi_pc pc;
+	ide_drive_t *drive = floppy->drive;
+	int blocks, length, flags, err = 0;
 
 	if (floppy->openers > 1) {
 		/* Don't format if someone is using the disk */
-		floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
+		drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
 		return -EBUSY;
 	}
 
-	floppy->flags |= IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
+	drive->atapi_flags |= IDE_AFLAG_FORMAT_IN_PROGRESS;
 
 	/*
 	 * Send ATAPI_FORMAT_UNIT to the drive.
@@ -1298,15 +1284,15 @@
 		goto out;
 	}
 
-	(void) idefloppy_get_sfrp_bit(floppy->drive);
+	(void) idefloppy_get_sfrp_bit(drive);
 	idefloppy_create_format_unit_cmd(&pc, blocks, length, flags);
 
-	if (idefloppy_queue_pc_tail(floppy->drive, &pc))
+	if (idefloppy_queue_pc_tail(drive, &pc))
 		err = -EIO;
 
 out:
 	if (err)
-		floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
+		drive->atapi_flags &= ~IDE_AFLAG_FORMAT_IN_PROGRESS;
 	return err;
 }
 
@@ -1325,7 +1311,7 @@
 	case CDROMEJECT:
 		/* fall through */
 	case CDROM_LOCKDOOR:
-		return ide_floppy_lockdoor(floppy, &pc, arg, cmd);
+		return ide_floppy_lockdoor(drive, &pc, arg, cmd);
 	case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED:
 		return 0;
 	case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY:
@@ -1366,8 +1352,8 @@
 		drive->attach = 0;
 		return 0;
 	}
-	ret = !!(floppy->flags & IDEFLOPPY_FLAG_MEDIA_CHANGED);
-	floppy->flags &= ~IDEFLOPPY_FLAG_MEDIA_CHANGED;
+	ret = !!(drive->atapi_flags & IDE_AFLAG_MEDIA_CHANGED);
+	drive->atapi_flags &= ~IDE_AFLAG_MEDIA_CHANGED;
 	return ret;
 }
 
diff --git a/drivers/ide/ide-generic.c b/drivers/ide/ide-generic.c
index 2d92214..31d98fe 100644
--- a/drivers/ide/ide-generic.c
+++ b/drivers/ide/ide-generic.c
@@ -28,29 +28,21 @@
 
 static ssize_t store_add(struct class *cls, const char *buf, size_t n)
 {
-	ide_hwif_t *hwif;
 	unsigned int base, ctl;
-	int irq;
-	hw_regs_t hw;
-	u8 idx[] = { 0xff, 0xff, 0xff, 0xff };
+	int irq, rc;
+	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
 
 	if (sscanf(buf, "%x:%x:%d", &base, &ctl, &irq) != 3)
 		return -EINVAL;
 
-	hwif = ide_find_port();
-	if (hwif == NULL)
-		return -ENOENT;
-
 	memset(&hw, 0, sizeof(hw));
 	ide_std_init_ports(&hw, base, ctl);
 	hw.irq = irq;
 	hw.chipset = ide_generic;
 
-	ide_init_port_hw(hwif, &hw);
-
-	idx[0] = hwif->index;
-
-	ide_device_add(idx, NULL);
+	rc = ide_host_add(NULL, hws, NULL);
+	if (rc)
+		return rc;
 
 	return n;
 };
@@ -90,18 +82,18 @@
 
 static int __init ide_generic_init(void)
 {
-	u8 idx[MAX_HWIFS];
-	int i;
+	hw_regs_t hw[MAX_HWIFS], *hws[MAX_HWIFS];
+	struct ide_host *host;
+	unsigned long io_addr;
+	int i, rc;
 
 	printk(KERN_INFO DRV_NAME ": please use \"probe_mask=0x3f\" module "
 			 "parameter for probing all legacy ISA IDE ports\n");
 
 	for (i = 0; i < MAX_HWIFS; i++) {
-		ide_hwif_t *hwif;
-		unsigned long io_addr = ide_default_io_base(i);
-		hw_regs_t hw;
+		io_addr = ide_default_io_base(i);
 
-		idx[i] = 0xff;
+		hws[i] = NULL;
 
 		if ((probe_mask & (1 << i)) && io_addr) {
 			if (!request_region(io_addr, 8, DRV_NAME)) {
@@ -119,33 +111,42 @@
 				continue;
 			}
 
-			/*
-			 * Skip probing if the corresponding
-			 * slot is already occupied.
-			 */
-			hwif = ide_find_port();
-			if (hwif == NULL || hwif->index != i) {
-				idx[i] = 0xff;
-				continue;
-			}
+			memset(&hw[i], 0, sizeof(hw[i]));
+			ide_std_init_ports(&hw[i], io_addr, io_addr + 0x206);
+			hw[i].irq = ide_default_irq(io_addr);
+			hw[i].chipset = ide_generic;
 
-			memset(&hw, 0, sizeof(hw));
-			ide_std_init_ports(&hw, io_addr, io_addr + 0x206);
-			hw.irq = ide_default_irq(io_addr);
-			hw.chipset = ide_generic;
-			ide_init_port_hw(hwif, &hw);
-
-			idx[i] = i;
+			hws[i] = &hw[i];
 		}
 	}
 
-	ide_device_add_all(idx, NULL);
+	host = ide_host_alloc_all(NULL, hws);
+	if (host == NULL) {
+		rc = -ENOMEM;
+		goto err;
+	}
+
+	rc = ide_host_register(host, NULL, hws);
+	if (rc)
+		goto err_free;
 
 	if (ide_generic_sysfs_init())
 		printk(KERN_ERR DRV_NAME ": failed to create ide_generic "
 					 "class\n");
 
 	return 0;
+err_free:
+	ide_host_free(host);
+err:
+	for (i = 0; i < MAX_HWIFS; i++) {
+		if (hws[i] == NULL)
+			continue;
+
+		io_addr = hws[i]->io_ports.data_addr;
+		release_region(io_addr + 0x206, 1);
+		release_region(io_addr, 8);
+	}
+	return rc;
 }
 
 module_init(ide_generic_init);
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 661b75a..a896a28 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -330,7 +330,7 @@
 			tf->error = err;
 			tf->status = stat;
 
-			drive->hwif->tf_read(drive, task);
+			drive->hwif->tp_ops->tf_read(drive, task);
 
 			if (task->tf_flags & IDE_TFLAG_DYN)
 				kfree(task);
@@ -381,8 +381,7 @@
 		if (err == ABRT_ERR) {
 			if (drive->select.b.lba &&
 			    /* some newer drives don't support WIN_SPECIFY */
-			    hwif->INB(hwif->io_ports.command_addr) ==
-				WIN_SPECIFY)
+			    hwif->tp_ops->read_status(hwif) == WIN_SPECIFY)
 				return ide_stopped;
 		} else if ((err & BAD_CRC) == BAD_CRC) {
 			/* UDMA crc error, just retry the operation */
@@ -408,7 +407,7 @@
 		return ide_stopped;
 	}
 
-	if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
+	if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT))
 		rq->errors |= ERROR_RESET;
 
 	if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
@@ -435,10 +434,9 @@
 		/* add decoding error stuff */
 	}
 
-	if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
+	if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT))
 		/* force an abort */
-		hwif->OUTBSYNC(hwif, WIN_IDLEIMMEDIATE,
-			       hwif->io_ports.command_addr);
+		hwif->tp_ops->exec_command(hwif, WIN_IDLEIMMEDIATE);
 
 	if (rq->errors >= ERROR_MAX) {
 		ide_kill_rq(drive, rq);
@@ -712,7 +710,8 @@
 #ifdef DEBUG
  	printk("%s: DRIVE_CMD (null)\n", drive->name);
 #endif
-	ide_end_drive_cmd(drive, ide_read_status(drive), ide_read_error(drive));
+	ide_end_drive_cmd(drive, hwif->tp_ops->read_status(hwif),
+			  ide_read_error(drive));
 
  	return ide_stopped;
 }
@@ -747,16 +746,17 @@
 		 * the bus may be broken enough to walk on our toes at this
 		 * point.
 		 */
+		ide_hwif_t *hwif = drive->hwif;
 		int rc;
 #ifdef DEBUG_PM
 		printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name);
 #endif
-		rc = ide_wait_not_busy(HWIF(drive), 35000);
+		rc = ide_wait_not_busy(hwif, 35000);
 		if (rc)
 			printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name);
 		SELECT_DRIVE(drive);
-		ide_set_irq(drive, 1);
-		rc = ide_wait_not_busy(HWIF(drive), 100000);
+		hwif->tp_ops->set_irq(hwif, 1);
+		rc = ide_wait_not_busy(hwif, 100000);
 		if (rc)
 			printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name);
 	}
@@ -1042,7 +1042,7 @@
 			 * quirk_list may not like intr setups/cleanups
 			 */
 			if (drive->quirk_list != 1)
-				ide_set_irq(drive, 0);
+				hwif->tp_ops->set_irq(hwif, 0);
 		}
 		hwgroup->hwif = hwif;
 		hwgroup->drive = drive;
@@ -1142,7 +1142,7 @@
 		printk(KERN_WARNING "%s: DMA timeout error\n", drive->name);
 		(void)hwif->dma_ops->dma_end(drive);
 		ret = ide_error(drive, "dma timeout error",
-				ide_read_status(drive));
+				hwif->tp_ops->read_status(hwif));
 	} else {
 		printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
 		hwif->dma_ops->dma_timeout(drive);
@@ -1267,7 +1267,7 @@
 				} else
 					startstop =
 					ide_error(drive, "irq timeout",
-						  ide_read_status(drive));
+						  hwif->tp_ops->read_status(hwif));
 			}
 			drive->service_time = jiffies - drive->service_start;
 			spin_lock_irq(&ide_lock);
@@ -1323,7 +1323,8 @@
 	 */
 	do {
 		if (hwif->irq == irq) {
-			stat = hwif->INB(hwif->io_ports.status_addr);
+			stat = hwif->tp_ops->read_status(hwif);
+
 			if (!OK_STAT(stat, READY_STAT, BAD_STAT)) {
 				/* Try to not flood the console with msgs */
 				static unsigned long last_msgtime, count;
@@ -1413,7 +1414,7 @@
 			 * Whack the status register, just in case
 			 * we have a leftover pending IRQ.
 			 */
-			(void) hwif->INB(hwif->io_ports.status_addr);
+			(void)hwif->tp_ops->read_status(hwif);
 #endif /* CONFIG_BLK_DEV_IDEPCI */
 		}
 		spin_unlock_irqrestore(&ide_lock, flags);
@@ -1519,6 +1520,7 @@
 
 void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma)
 {
+	ide_hwif_t *hwif = drive->hwif;
 	ide_task_t task;
 
 	memset(&task, 0, sizeof(task));
@@ -1529,9 +1531,9 @@
 	task.tf.lbah    = (bcount >> 8) & 0xff;
 
 	ide_tf_dump(drive->name, &task.tf);
-	ide_set_irq(drive, 1);
+	hwif->tp_ops->set_irq(hwif, 1);
 	SELECT_MASK(drive, 0);
-	drive->hwif->tf_load(drive, &task);
+	hwif->tp_ops->tf_load(drive, &task);
 }
 
 EXPORT_SYMBOL_GPL(ide_pktcmd_tf_load);
@@ -1543,9 +1545,9 @@
 
 	while (len > 0) {
 		if (write)
-			hwif->output_data(drive, NULL, buf, min(4, len));
+			hwif->tp_ops->output_data(drive, NULL, buf, min(4, len));
 		else
-			hwif->input_data(drive, NULL, buf, min(4, len));
+			hwif->tp_ops->input_data(drive, NULL, buf, min(4, len));
 		len -= 4;
 	}
 }
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index 44aaec2..07da5fb 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -42,18 +42,6 @@
 	outb(val, port);
 }
 
-static void ide_outbsync(ide_hwif_t *hwif, u8 addr, unsigned long port)
-{
-	outb(addr, port);
-}
-
-void default_hwif_iops (ide_hwif_t *hwif)
-{
-	hwif->OUTB	= ide_outb;
-	hwif->OUTBSYNC	= ide_outbsync;
-	hwif->INB	= ide_inb;
-}
-
 /*
  *	MMIO operations, typically used for SATA controllers
  */
@@ -68,31 +56,19 @@
 	writeb(value, (void __iomem *) port);
 }
 
-static void ide_mm_outbsync(ide_hwif_t *hwif, u8 value, unsigned long port)
-{
-	writeb(value, (void __iomem *) port);
-}
-
-void default_hwif_mmiops (ide_hwif_t *hwif)
-{
-	hwif->OUTB	= ide_mm_outb;
-	/* Most systems will need to override OUTBSYNC, alas however
-	   this one is controller specific! */
-	hwif->OUTBSYNC	= ide_mm_outbsync;
-	hwif->INB	= ide_mm_inb;
-}
-
-EXPORT_SYMBOL(default_hwif_mmiops);
-
 void SELECT_DRIVE (ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	const struct ide_port_ops *port_ops = hwif->port_ops;
+	ide_task_t task;
 
 	if (port_ops && port_ops->selectproc)
 		port_ops->selectproc(drive);
 
-	hwif->OUTB(drive->select.all, hwif->io_ports.device_addr);
+	memset(&task, 0, sizeof(task));
+	task.tf_flags = IDE_TFLAG_OUT_DEVICE;
+
+	drive->hwif->tp_ops->tf_load(drive, &task);
 }
 
 void SELECT_MASK(ide_drive_t *drive, int mask)
@@ -103,7 +79,61 @@
 		port_ops->maskproc(drive, mask);
 }
 
-static void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
+void ide_exec_command(ide_hwif_t *hwif, u8 cmd)
+{
+	if (hwif->host_flags & IDE_HFLAG_MMIO)
+		writeb(cmd, (void __iomem *)hwif->io_ports.command_addr);
+	else
+		outb(cmd, hwif->io_ports.command_addr);
+}
+EXPORT_SYMBOL_GPL(ide_exec_command);
+
+u8 ide_read_status(ide_hwif_t *hwif)
+{
+	if (hwif->host_flags & IDE_HFLAG_MMIO)
+		return readb((void __iomem *)hwif->io_ports.status_addr);
+	else
+		return inb(hwif->io_ports.status_addr);
+}
+EXPORT_SYMBOL_GPL(ide_read_status);
+
+u8 ide_read_altstatus(ide_hwif_t *hwif)
+{
+	if (hwif->host_flags & IDE_HFLAG_MMIO)
+		return readb((void __iomem *)hwif->io_ports.ctl_addr);
+	else
+		return inb(hwif->io_ports.ctl_addr);
+}
+EXPORT_SYMBOL_GPL(ide_read_altstatus);
+
+u8 ide_read_sff_dma_status(ide_hwif_t *hwif)
+{
+	if (hwif->host_flags & IDE_HFLAG_MMIO)
+		return readb((void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
+	else
+		return inb(hwif->dma_base + ATA_DMA_STATUS);
+}
+EXPORT_SYMBOL_GPL(ide_read_sff_dma_status);
+
+void ide_set_irq(ide_hwif_t *hwif, int on)
+{
+	u8 ctl = ATA_DEVCTL_OBS;
+
+	if (on == 4) { /* hack for SRST */
+		ctl |= 4;
+		on &= ~4;
+	}
+
+	ctl |= on ? 0 : 2;
+
+	if (hwif->host_flags & IDE_HFLAG_MMIO)
+		writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr);
+	else
+		outb(ctl, hwif->io_ports.ctl_addr);
+}
+EXPORT_SYMBOL_GPL(ide_set_irq);
+
+void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct ide_io_ports *io_ports = &hwif->io_ports;
@@ -155,8 +185,9 @@
 		tf_outb((tf->device & HIHI) | drive->select.all,
 			 io_ports->device_addr);
 }
+EXPORT_SYMBOL_GPL(ide_tf_load);
 
-static void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
+void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct ide_io_ports *io_ports = &hwif->io_ports;
@@ -188,6 +219,8 @@
 	/* be sure we're looking at the low order bits */
 	tf_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
 
+	if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+		tf->feature = tf_inb(io_ports->feature_addr);
 	if (task->tf_flags & IDE_TFLAG_IN_NSECT)
 		tf->nsect  = tf_inb(io_ports->nsect_addr);
 	if (task->tf_flags & IDE_TFLAG_IN_LBAL)
@@ -214,6 +247,7 @@
 			tf->hob_lbah    = tf_inb(io_ports->lbah_addr);
 	}
 }
+EXPORT_SYMBOL_GPL(ide_tf_read);
 
 /*
  * Some localbus EIDE interfaces require a special access sequence
@@ -236,8 +270,8 @@
  * so if an odd len is specified, be sure that there's at least one
  * extra byte allocated for the buffer.
  */
-static void ata_input_data(ide_drive_t *drive, struct request *rq,
-			   void *buf, unsigned int len)
+void ide_input_data(ide_drive_t *drive, struct request *rq, void *buf,
+		    unsigned int len)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct ide_io_ports *io_ports = &hwif->io_ports;
@@ -277,12 +311,13 @@
 			insw(data_addr, buf, len / 2);
 	}
 }
+EXPORT_SYMBOL_GPL(ide_input_data);
 
 /*
  * This is used for most PIO data transfers *to* the IDE interface
  */
-static void ata_output_data(ide_drive_t *drive, struct request *rq,
-			    void *buf, unsigned int len)
+void ide_output_data(ide_drive_t *drive, struct request *rq, void *buf,
+		     unsigned int len)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct ide_io_ports *io_ports = &hwif->io_ports;
@@ -320,15 +355,50 @@
 			outsw(data_addr, buf, len / 2);
 	}
 }
+EXPORT_SYMBOL_GPL(ide_output_data);
 
-void default_hwif_transport(ide_hwif_t *hwif)
+u8 ide_read_error(ide_drive_t *drive)
 {
-	hwif->tf_load	  = ide_tf_load;
-	hwif->tf_read	  = ide_tf_read;
+	ide_task_t task;
 
-	hwif->input_data  = ata_input_data;
-	hwif->output_data = ata_output_data;
+	memset(&task, 0, sizeof(task));
+	task.tf_flags = IDE_TFLAG_IN_FEATURE;
+
+	drive->hwif->tp_ops->tf_read(drive, &task);
+
+	return task.tf.error;
 }
+EXPORT_SYMBOL_GPL(ide_read_error);
+
+void ide_read_bcount_and_ireason(ide_drive_t *drive, u16 *bcount, u8 *ireason)
+{
+	ide_task_t task;
+
+	memset(&task, 0, sizeof(task));
+	task.tf_flags = IDE_TFLAG_IN_LBAH | IDE_TFLAG_IN_LBAM |
+			IDE_TFLAG_IN_NSECT;
+
+	drive->hwif->tp_ops->tf_read(drive, &task);
+
+	*bcount = (task.tf.lbah << 8) | task.tf.lbam;
+	*ireason = task.tf.nsect & 3;
+}
+EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason);
+
+const struct ide_tp_ops default_tp_ops = {
+	.exec_command		= ide_exec_command,
+	.read_status		= ide_read_status,
+	.read_altstatus		= ide_read_altstatus,
+	.read_sff_dma_status	= ide_read_sff_dma_status,
+
+	.set_irq		= ide_set_irq,
+
+	.tf_load		= ide_tf_load,
+	.tf_read		= ide_tf_read,
+
+	.input_data		= ide_input_data,
+	.output_data		= ide_output_data,
+};
 
 void ide_fix_driveid (struct hd_driveid *id)
 {
@@ -483,10 +553,10 @@
 	 * about possible isa-pnp and pci-pnp issues yet.
 	 */
 	if (hwif->io_ports.ctl_addr)
-		stat = ide_read_altstatus(drive);
+		stat = hwif->tp_ops->read_altstatus(hwif);
 	else
 		/* Note: this may clear a pending IRQ!! */
-		stat = ide_read_status(drive);
+		stat = hwif->tp_ops->read_status(hwif);
 
 	if (stat & BUSY_STAT)
 		/* drive busy:  definitely not interrupting */
@@ -511,24 +581,26 @@
  */
 static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout, u8 *rstat)
 {
+	ide_hwif_t *hwif = drive->hwif;
+	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
 	unsigned long flags;
 	int i;
 	u8 stat;
 
 	udelay(1);	/* spec allows drive 400ns to assert "BUSY" */
-	stat = ide_read_status(drive);
+	stat = tp_ops->read_status(hwif);
 
 	if (stat & BUSY_STAT) {
 		local_irq_set(flags);
 		timeout += jiffies;
-		while ((stat = ide_read_status(drive)) & BUSY_STAT) {
+		while ((stat = tp_ops->read_status(hwif)) & BUSY_STAT) {
 			if (time_after(jiffies, timeout)) {
 				/*
 				 * One last read after the timeout in case
 				 * heavy interrupt load made us not make any
 				 * progress during the timeout..
 				 */
-				stat = ide_read_status(drive);
+				stat = tp_ops->read_status(hwif);
 				if (!(stat & BUSY_STAT))
 					break;
 
@@ -548,7 +620,7 @@
 	 */
 	for (i = 0; i < 10; i++) {
 		udelay(1);
-		stat = ide_read_status(drive);
+		stat = tp_ops->read_status(hwif);
 
 		if (OK_STAT(stat, good, bad)) {
 			*rstat = stat;
@@ -674,6 +746,7 @@
 int ide_driveid_update(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = drive->hwif;
+	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
 	struct hd_driveid *id;
 	unsigned long timeout, flags;
 	u8 stat;
@@ -684,9 +757,9 @@
 	 */
 
 	SELECT_MASK(drive, 1);
-	ide_set_irq(drive, 0);
+	tp_ops->set_irq(hwif, 0);
 	msleep(50);
-	hwif->OUTBSYNC(hwif, WIN_IDENTIFY, hwif->io_ports.command_addr);
+	tp_ops->exec_command(hwif, WIN_IDENTIFY);
 	timeout = jiffies + WAIT_WORSTCASE;
 	do {
 		if (time_after(jiffies, timeout)) {
@@ -695,11 +768,11 @@
 		}
 
 		msleep(50);	/* give drive a breather */
-		stat = ide_read_altstatus(drive);
+		stat = tp_ops->read_altstatus(hwif);
 	} while (stat & BUSY_STAT);
 
 	msleep(50);	/* wait for IRQ and DRQ_STAT */
-	stat = ide_read_status(drive);
+	stat = tp_ops->read_status(hwif);
 
 	if (!OK_STAT(stat, DRQ_STAT, BAD_R_STAT)) {
 		SELECT_MASK(drive, 0);
@@ -713,8 +786,8 @@
 		local_irq_restore(flags);
 		return 0;
 	}
-	hwif->input_data(drive, NULL, id, SECTOR_SIZE);
-	(void)ide_read_status(drive);	/* clear drive IRQ */
+	tp_ops->input_data(drive, NULL, id, SECTOR_SIZE);
+	(void)tp_ops->read_status(hwif);	/* clear drive IRQ */
 	local_irq_enable();
 	local_irq_restore(flags);
 	ide_fix_driveid(id);
@@ -735,9 +808,10 @@
 int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
 {
 	ide_hwif_t *hwif = drive->hwif;
-	struct ide_io_ports *io_ports = &hwif->io_ports;
+	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
 	int error = 0;
 	u8 stat;
+	ide_task_t task;
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (hwif->dma_ops)	/* check if host supports DMA */
@@ -770,12 +844,19 @@
 	SELECT_DRIVE(drive);
 	SELECT_MASK(drive, 0);
 	udelay(1);
-	ide_set_irq(drive, 0);
-	hwif->OUTB(speed, io_ports->nsect_addr);
-	hwif->OUTB(SETFEATURES_XFER, io_ports->feature_addr);
-	hwif->OUTBSYNC(hwif, WIN_SETFEATURES, io_ports->command_addr);
+	tp_ops->set_irq(hwif, 0);
+
+	memset(&task, 0, sizeof(task));
+	task.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT;
+	task.tf.feature = SETFEATURES_XFER;
+	task.tf.nsect   = speed;
+
+	tp_ops->tf_load(drive, &task);
+
+	tp_ops->exec_command(hwif, WIN_SETFEATURES);
+
 	if (drive->quirk_list == 2)
-		ide_set_irq(drive, 1);
+		tp_ops->set_irq(hwif, 1);
 
 	error = __ide_wait_stat(drive, drive->ready_stat,
 				BUSY_STAT|DRQ_STAT|ERR_STAT,
@@ -796,8 +877,7 @@
 
  skip:
 #ifdef CONFIG_BLK_DEV_IDEDMA
-	if ((speed >= XFER_SW_DMA_0 || (hwif->host_flags & IDE_HFLAG_VDMA)) &&
-	    drive->using_dma)
+	if (speed >= XFER_SW_DMA_0 && drive->using_dma)
 		hwif->dma_ops->dma_host_set(drive, 1);
 	else if (hwif->dma_ops)	/* check if host supports DMA */
 		ide_dma_off_quietly(drive);
@@ -881,7 +961,7 @@
 
 	spin_lock_irqsave(&ide_lock, flags);
 	__ide_set_handler(drive, handler, timeout, expiry);
-	hwif->OUTBSYNC(hwif, cmd, hwif->io_ports.command_addr);
+	hwif->tp_ops->exec_command(hwif, cmd);
 	/*
 	 * Drive takes 400nS to respond, we must avoid the IRQ being
 	 * serviced before that.
@@ -899,7 +979,7 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&ide_lock, flags);
-	hwif->OUTBSYNC(hwif, WIN_PACKETCMD, hwif->io_ports.command_addr);
+	hwif->tp_ops->exec_command(hwif, WIN_PACKETCMD);
 	ndelay(400);
 	spin_unlock_irqrestore(&ide_lock, flags);
 }
@@ -924,12 +1004,13 @@
  */
 static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
 {
-	ide_hwgroup_t *hwgroup	= HWGROUP(drive);
+	ide_hwif_t *hwif = drive->hwif;
+	ide_hwgroup_t *hwgroup = hwif->hwgroup;
 	u8 stat;
 
 	SELECT_DRIVE(drive);
 	udelay (10);
-	stat = ide_read_status(drive);
+	stat = hwif->tp_ops->read_status(hwif);
 
 	if (OK_STAT(stat, 0, BUSY_STAT))
 		printk("%s: ATAPI reset complete\n", drive->name);
@@ -975,7 +1056,7 @@
 		}
 	}
 
-	tmp = ide_read_status(drive);
+	tmp = hwif->tp_ops->read_status(hwif);
 
 	if (!OK_STAT(tmp, 0, BUSY_STAT)) {
 		if (time_before(jiffies, hwgroup->poll_timeout)) {
@@ -1089,8 +1170,8 @@
 	ide_hwif_t *hwif;
 	ide_hwgroup_t *hwgroup;
 	struct ide_io_ports *io_ports;
+	const struct ide_tp_ops *tp_ops;
 	const struct ide_port_ops *port_ops;
-	u8 ctl;
 
 	spin_lock_irqsave(&ide_lock, flags);
 	hwif = HWIF(drive);
@@ -1098,6 +1179,8 @@
 
 	io_ports = &hwif->io_ports;
 
+	tp_ops = hwif->tp_ops;
+
 	/* We must not reset with running handlers */
 	BUG_ON(hwgroup->handler != NULL);
 
@@ -1106,7 +1189,7 @@
 		pre_reset(drive);
 		SELECT_DRIVE(drive);
 		udelay (20);
-		hwif->OUTBSYNC(hwif, WIN_SRST, io_ports->command_addr);
+		tp_ops->exec_command(hwif, WIN_SRST);
 		ndelay(400);
 		hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
 		hwgroup->polling = 1;
@@ -1135,16 +1218,15 @@
 	 * immediate interrupt due to the edge transition it produces.
 	 * This single interrupt gives us a "fast poll" for drives that
 	 * recover from reset very quickly, saving us the first 50ms wait time.
+	 *
+	 * TODO: add ->softreset method and stop abusing ->set_irq
 	 */
 	/* set SRST and nIEN */
-	hwif->OUTBSYNC(hwif, ATA_DEVCTL_OBS | 6, io_ports->ctl_addr);
+	tp_ops->set_irq(hwif, 4);
 	/* more than enough time */
 	udelay(10);
-	if (drive->quirk_list == 2)
-		ctl = ATA_DEVCTL_OBS;		/* clear SRST and nIEN */
-	else
-		ctl = ATA_DEVCTL_OBS | 2;	/* clear SRST, leave nIEN */
-	hwif->OUTBSYNC(hwif, ctl, io_ports->ctl_addr);
+	/* clear SRST, leave nIEN (unless device is on the quirk list) */
+	tp_ops->set_irq(hwif, drive->quirk_list == 2);
 	/* more than enough time */
 	udelay(10);
 	hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
@@ -1189,7 +1271,7 @@
 		 * about locking issues (2.5 work ?).
 		 */
 		mdelay(1);
-		stat = hwif->INB(hwif->io_ports.status_addr);
+		stat = hwif->tp_ops->read_status(hwif);
 		if ((stat & BUSY_STAT) == 0)
 			return 0;
 		/*
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index 13af72f..97fefab 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -266,22 +266,11 @@
 
 	rate = ide_rate_filter(drive, rate);
 
+	BUG_ON(rate < XFER_PIO_0);
+
 	if (rate >= XFER_PIO_0 && rate <= XFER_PIO_5)
 		return ide_set_pio_mode(drive, rate);
 
-	/*
-	 * TODO: transfer modes 0x00-0x07 passed from the user-space are
-	 * currently handled here which needs fixing (please note that such
-	 * case could happen iff the transfer mode has already been set on
-	 * the device by ide-proc.c::set_xfer_rate()).
-	 */
-	if (rate < XFER_PIO_0) {
-		if (hwif->host_flags & IDE_HFLAG_ABUSE_SET_DMA_MODE)
-			return ide_set_dma_mode(drive, rate);
-		else
-			return ide_config_drive_speed(drive, rate);
-	}
-
 	return ide_set_dma_mode(drive, rate);
 }
 
@@ -336,7 +325,7 @@
 	else
 		task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_DEVICE;
 
-	drive->hwif->tf_read(drive, &task);
+	drive->hwif->tp_ops->tf_read(drive, &task);
 
 	if (lba48 || (tf->device & ATA_LBA))
 		printk(", LBAsect=%llu",
diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c
index 03f2ef5..bac9b39 100644
--- a/drivers/ide/ide-pnp.c
+++ b/drivers/ide/ide-pnp.c
@@ -29,9 +29,10 @@
 
 static int idepnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
 {
-	hw_regs_t hw;
-	ide_hwif_t *hwif;
+	struct ide_host *host;
 	unsigned long base, ctl;
+	int rc;
+	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
 
 	printk(KERN_INFO DRV_NAME ": generic PnP IDE interface\n");
 
@@ -59,31 +60,25 @@
 	hw.irq = pnp_irq(dev, 0);
 	hw.chipset = ide_generic;
 
-	hwif = ide_find_port();
-	if (hwif) {
-		u8 index = hwif->index;
-		u8 idx[4] = { index, 0xff, 0xff, 0xff };
+	rc = ide_host_add(NULL, hws, &host);
+	if (rc)
+		goto out;
 
-		ide_init_port_hw(hwif, &hw);
+	pnp_set_drvdata(dev, host);
 
-		pnp_set_drvdata(dev, hwif);
-
-		ide_device_add(idx, NULL);
-
-		return 0;
-	}
-
+	return 0;
+out:
 	release_region(ctl, 1);
 	release_region(base, 8);
 
-	return -1;
+	return rc;
 }
 
 static void idepnp_remove(struct pnp_dev *dev)
 {
-	ide_hwif_t *hwif = pnp_get_drvdata(dev);
+	struct ide_host *host = pnp_get_drvdata(dev);
 
-	ide_unregister(hwif);
+	ide_host_remove(host);
 
 	release_region(pnp_port_start(dev, 1), 1);
 	release_region(pnp_port_start(dev, 0), 8);
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 235ebdb..4aa76c45 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -39,8 +39,6 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-static ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */
-
 /**
  *	generic_id		-	add a generic drive id
  *	@drive:	drive to make an ID block for
@@ -126,7 +124,7 @@
 
 	id = drive->id;
 	/* read 512 bytes of id info */
-	hwif->input_data(drive, NULL, id, SECTOR_SIZE);
+	hwif->tp_ops->input_data(drive, NULL, id, SECTOR_SIZE);
 
 	drive->id_read = 1;
 	local_irq_enable();
@@ -267,6 +265,7 @@
 {
 	ide_hwif_t *hwif = HWIF(drive);
 	struct ide_io_ports *io_ports = &hwif->io_ports;
+	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
 	int use_altstatus = 0, rc;
 	unsigned long timeout;
 	u8 s = 0, a = 0;
@@ -275,8 +274,8 @@
 	msleep(50);
 
 	if (io_ports->ctl_addr) {
-		a = ide_read_altstatus(drive);
-		s = ide_read_status(drive);
+		a = tp_ops->read_altstatus(hwif);
+		s = tp_ops->read_status(hwif);
 		if ((a ^ s) & ~INDEX_STAT)
 			/* ancient Seagate drives, broken interfaces */
 			printk(KERN_INFO "%s: probing with STATUS(0x%02x) "
@@ -290,12 +289,18 @@
 	/* set features register for atapi
 	 * identify command to be sure of reply
 	 */
-	if ((cmd == WIN_PIDENTIFY))
-		/* disable dma & overlap */
-		hwif->OUTB(0, io_ports->feature_addr);
+	if (cmd == WIN_PIDENTIFY) {
+		ide_task_t task;
+
+		memset(&task, 0, sizeof(task));
+		/* disable DMA & overlap */
+		task.tf_flags = IDE_TFLAG_OUT_FEATURE;
+
+		tp_ops->tf_load(drive, &task);
+	}
 
 	/* ask drive for ID */
-	hwif->OUTBSYNC(hwif, cmd, hwif->io_ports.command_addr);
+	tp_ops->exec_command(hwif, cmd);
 
 	timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
 	timeout += jiffies;
@@ -306,13 +311,13 @@
 		}
 		/* give drive a breather */
 		msleep(50);
-		s = use_altstatus ? ide_read_altstatus(drive)
-				  : ide_read_status(drive);
+		s = use_altstatus ? tp_ops->read_altstatus(hwif)
+				  : tp_ops->read_status(hwif);
 	} while (s & BUSY_STAT);
 
 	/* wait for IRQ and DRQ_STAT */
 	msleep(50);
-	s = ide_read_status(drive);
+	s = tp_ops->read_status(hwif);
 
 	if (OK_STAT(s, DRQ_STAT, BAD_R_STAT)) {
 		unsigned long flags;
@@ -324,7 +329,7 @@
 		/* drive responded with ID */
 		rc = 0;
 		/* clear drive IRQ */
-		(void)ide_read_status(drive);
+		(void)tp_ops->read_status(hwif);
 		local_irq_restore(flags);
 	} else {
 		/* drive refused ID */
@@ -346,6 +351,7 @@
 static int try_to_identify (ide_drive_t *drive, u8 cmd)
 {
 	ide_hwif_t *hwif = HWIF(drive);
+	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
 	int retval;
 	int autoprobe = 0;
 	unsigned long cookie = 0;
@@ -361,7 +367,7 @@
 			autoprobe = 1;
 			cookie = probe_irq_on();
 		}
-		ide_set_irq(drive, autoprobe);
+		tp_ops->set_irq(hwif, autoprobe);
 	}
 
 	retval = actual_try_to_identify(drive, cmd);
@@ -369,9 +375,9 @@
 	if (autoprobe) {
 		int irq;
 
-		ide_set_irq(drive, 0);
+		tp_ops->set_irq(hwif, 0);
 		/* clear drive IRQ */
-		(void)ide_read_status(drive);
+		(void)tp_ops->read_status(hwif);
 		udelay(5);
 		irq = probe_irq_off(cookie);
 		if (!hwif->irq) {
@@ -396,7 +402,7 @@
 
 	do {
 		msleep(50);
-		stat = hwif->INB(hwif->io_ports.status_addr);
+		stat = hwif->tp_ops->read_status(hwif);
 		if ((stat & BUSY_STAT) == 0)
 			return 0;
 	} while (time_before(jiffies, timeout));
@@ -404,6 +410,18 @@
 	return 1;
 }
 
+static u8 ide_read_device(ide_drive_t *drive)
+{
+	ide_task_t task;
+
+	memset(&task, 0, sizeof(task));
+	task.tf_flags = IDE_TFLAG_IN_DEVICE;
+
+	drive->hwif->tp_ops->tf_read(drive, &task);
+
+	return task.tf.device;
+}
+
 /**
  *	do_probe		-	probe an IDE device
  *	@drive: drive to probe
@@ -428,7 +446,7 @@
 static int do_probe (ide_drive_t *drive, u8 cmd)
 {
 	ide_hwif_t *hwif = HWIF(drive);
-	struct ide_io_ports *io_ports = &hwif->io_ports;
+	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
 	int rc;
 	u8 stat;
 
@@ -449,8 +467,8 @@
 	msleep(50);
 	SELECT_DRIVE(drive);
 	msleep(50);
-	if (hwif->INB(io_ports->device_addr) != drive->select.all &&
-	    !drive->present) {
+
+	if (ide_read_device(drive) != drive->select.all && !drive->present) {
 		if (drive->select.b.unit != 0) {
 			/* exit with drive0 selected */
 			SELECT_DRIVE(&hwif->drives[0]);
@@ -461,7 +479,7 @@
 		return 3;
 	}
 
-	stat = ide_read_status(drive);
+	stat = tp_ops->read_status(hwif);
 
 	if (OK_STAT(stat, READY_STAT, BUSY_STAT) ||
 	    drive->present || cmd == WIN_PIDENTIFY) {
@@ -471,7 +489,7 @@
 			rc = try_to_identify(drive,cmd);
 		}
 
-		stat = ide_read_status(drive);
+		stat = tp_ops->read_status(hwif);
 
 		if (stat == (BUSY_STAT | READY_STAT))
 			return 4;
@@ -482,13 +500,13 @@
 			msleep(50);
 			SELECT_DRIVE(drive);
 			msleep(50);
-			hwif->OUTBSYNC(hwif, WIN_SRST, io_ports->command_addr);
+			tp_ops->exec_command(hwif, WIN_SRST);
 			(void)ide_busy_sleep(hwif);
 			rc = try_to_identify(drive, cmd);
 		}
 
 		/* ensure drive IRQ is clear */
-		stat = ide_read_status(drive);
+		stat = tp_ops->read_status(hwif);
 
 		if (rc == 1)
 			printk(KERN_ERR "%s: no response (status = 0x%02x)\n",
@@ -502,7 +520,7 @@
 		SELECT_DRIVE(&hwif->drives[0]);
 		msleep(50);
 		/* ensure drive irq is clear */
-		(void)ide_read_status(drive);
+		(void)tp_ops->read_status(hwif);
 	}
 	return rc;
 }
@@ -513,12 +531,13 @@
 static void enable_nest (ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = HWIF(drive);
+	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
 	u8 stat;
 
 	printk("%s: enabling %s -- ", hwif->name, drive->id->model);
 	SELECT_DRIVE(drive);
 	msleep(50);
-	hwif->OUTBSYNC(hwif, EXABYTE_ENABLE_NEST, hwif->io_ports.command_addr);
+	tp_ops->exec_command(hwif, EXABYTE_ENABLE_NEST);
 
 	if (ide_busy_sleep(hwif)) {
 		printk(KERN_CONT "failed (timeout)\n");
@@ -527,7 +546,7 @@
 
 	msleep(50);
 
-	stat = ide_read_status(drive);
+	stat = tp_ops->read_status(hwif);
 
 	if (!OK_STAT(stat, 0, BAD_STAT))
 		printk(KERN_CONT "failed (status = 0x%02x)\n", stat);
@@ -619,7 +638,7 @@
 	return drive->present;
 }
 
-static void hwif_release_dev (struct device *dev)
+static void hwif_release_dev(struct device *dev)
 {
 	ide_hwif_t *hwif = container_of(dev, ide_hwif_t, gendev);
 
@@ -709,7 +728,7 @@
 		/* Ignore disks that we will not probe for later. */
 		if (!drive->noprobe || drive->present) {
 			SELECT_DRIVE(drive);
-			ide_set_irq(drive, 1);
+			hwif->tp_ops->set_irq(hwif, 1);
 			mdelay(2);
 			rc = ide_wait_not_busy(hwif, 35000);
 			if (rc)
@@ -971,6 +990,45 @@
 	mutex_unlock(&ide_cfg_mtx);
 }
 
+static ide_hwif_t *ide_ports[MAX_HWIFS];
+
+void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
+{
+	ide_hwgroup_t *hwgroup = hwif->hwgroup;
+
+	ide_ports[hwif->index] = NULL;
+
+	spin_lock_irq(&ide_lock);
+	/*
+	 * Remove us from the hwgroup, and free
+	 * the hwgroup if we were the only member
+	 */
+	if (hwif->next == hwif) {
+		BUG_ON(hwgroup->hwif != hwif);
+		kfree(hwgroup);
+	} else {
+		/* There is another interface in hwgroup.
+		 * Unlink us, and set hwgroup->drive and ->hwif to
+		 * something sane.
+		 */
+		ide_hwif_t *g = hwgroup->hwif;
+
+		while (g->next != hwif)
+			g = g->next;
+		g->next = hwif->next;
+		if (hwgroup->hwif == hwif) {
+			/* Chose a random hwif for hwgroup->hwif.
+			 * It's guaranteed that there are no drives
+			 * left in the hwgroup.
+			 */
+			BUG_ON(hwgroup->drive != NULL);
+			hwgroup->hwif = g;
+		}
+		BUG_ON(hwgroup->hwif == hwif);
+	}
+	spin_unlock_irq(&ide_lock);
+}
+
 /*
  * This routine sets up the irq for an ide interface, and creates a new
  * hwgroup for the irq/hwif if none was previously assigned.
@@ -998,8 +1056,9 @@
 	 * Group up with any other hwifs that share our irq(s).
 	 */
 	for (index = 0; index < MAX_HWIFS; index++) {
-		ide_hwif_t *h = &ide_hwifs[index];
-		if (h->hwgroup) {  /* scan only initialized hwif's */
+		ide_hwif_t *h = ide_ports[index];
+
+		if (h && h->hwgroup) {  /* scan only initialized ports */
 			if (hwif->irq == h->irq) {
 				hwif->sharing_irq = h->sharing_irq = 1;
 				if (hwif->chipset != ide_pci ||
@@ -1053,6 +1112,8 @@
 		hwgroup->timer.data = (unsigned long) hwgroup;
 	}
 
+	ide_ports[hwif->index] = hwif;
+
 	/*
 	 * Allocate the irq, if not already obtained for another hwif
 	 */
@@ -1066,8 +1127,7 @@
 			sa = IRQF_SHARED;
 
 		if (io_ports->ctl_addr)
-			/* clear nIEN */
-			hwif->OUTBSYNC(hwif, ATA_DEVCTL_OBS, io_ports->ctl_addr);
+			hwif->tp_ops->set_irq(hwif, 1);
 
 		if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup))
 	       		goto out_unlink;
@@ -1345,6 +1405,9 @@
 	hwif->host_flags |= d->host_flags;
 	hwif->pio_mask = d->pio_mask;
 
+	if (d->tp_ops)
+		hwif->tp_ops = d->tp_ops;
+
 	/* ->set_pio_mode for DTC2278 is currently limited to port 0 */
 	if (hwif->chipset != ide_dtc2278 || hwif->channel == 0)
 		hwif->port_ops = d->port_ops;
@@ -1363,6 +1426,7 @@
 
 		if (rc < 0) {
 			printk(KERN_INFO "%s: DMA disabled\n", hwif->name);
+			hwif->dma_base = 0;
 			hwif->swdma_mask = 0;
 			hwif->mwdma_mask = 0;
 			hwif->ultra_mask = 0;
@@ -1446,18 +1510,20 @@
 	return rc;
 }
 
+static unsigned int ide_indexes;
+
 /**
- *	ide_find_port_slot	-	find free ide_hwifs[] slot
+ *	ide_find_port_slot	-	find free port slot
  *	@d: IDE port info
  *
- *	Return the new hwif.  If we are out of free slots return NULL.
+ *	Return the new port slot index or -ENOENT if we are out of free slots.
  */
 
-ide_hwif_t *ide_find_port_slot(const struct ide_port_info *d)
+static int ide_find_port_slot(const struct ide_port_info *d)
 {
-	ide_hwif_t *hwif;
-	int i;
+	int idx = -ENOENT;
 	u8 bootable = (d && (d->host_flags & IDE_HFLAG_NON_BOOTABLE)) ? 0 : 1;
+	u8 i = (d && (d->host_flags & IDE_HFLAG_QD_2ND_PORT)) ? 1 : 0;;
 
 	/*
 	 * Claim an unassigned slot.
@@ -1469,51 +1535,106 @@
 	 * Unless there is a bootable card that does not use the standard
 	 * ports 0x1f0/0x170 (the ide0/ide1 defaults).
 	 */
-	if (bootable) {
-		i = (d && (d->host_flags & IDE_HFLAG_QD_2ND_PORT)) ? 1 : 0;
-
-		for (; i < MAX_HWIFS; i++) {
-			hwif = &ide_hwifs[i];
-			if (hwif->chipset == ide_unknown)
-				goto out_found;
-		}
+	mutex_lock(&ide_cfg_mtx);
+	if (MAX_HWIFS == 1) {
+		if (ide_indexes == 0 && i == 0)
+			idx = 1;
 	} else {
-		for (i = 2; i < MAX_HWIFS; i++) {
-			hwif = &ide_hwifs[i];
-			if (hwif->chipset == ide_unknown)
-				goto out_found;
-		}
-		for (i = 0; i < 2 && i < MAX_HWIFS; i++) {
-			hwif = &ide_hwifs[i];
-			if (hwif->chipset == ide_unknown)
-				goto out_found;
+		if (bootable) {
+			if ((ide_indexes | i) != (1 << MAX_HWIFS) - 1)
+				idx = ffz(ide_indexes | i);
+		} else {
+			if ((ide_indexes | 3) != (1 << MAX_HWIFS) - 1)
+				idx = ffz(ide_indexes | 3);
+			else if ((ide_indexes & 3) != 3)
+				idx = ffz(ide_indexes);
 		}
 	}
+	if (idx >= 0)
+		ide_indexes |= (1 << idx);
+	mutex_unlock(&ide_cfg_mtx);
 
-	printk(KERN_ERR "%s: no free slot for interface\n",
-			d ? d->name : "ide");
-
-	return NULL;
-
-out_found:
-	ide_init_port_data(hwif, i);
-	return hwif;
+	return idx;
 }
-EXPORT_SYMBOL_GPL(ide_find_port_slot);
 
-int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
+static void ide_free_port_slot(int idx)
 {
-	ide_hwif_t *hwif, *mate = NULL;
-	int i, rc = 0;
+	mutex_lock(&ide_cfg_mtx);
+	ide_indexes &= ~(1 << idx);
+	mutex_unlock(&ide_cfg_mtx);
+}
+
+struct ide_host *ide_host_alloc_all(const struct ide_port_info *d,
+				    hw_regs_t **hws)
+{
+	struct ide_host *host;
+	int i;
+
+	host = kzalloc(sizeof(*host), GFP_KERNEL);
+	if (host == NULL)
+		return NULL;
 
 	for (i = 0; i < MAX_HWIFS; i++) {
-		if (idx[i] == 0xff) {
+		ide_hwif_t *hwif;
+		int idx;
+
+		if (hws[i] == NULL)
+			continue;
+
+		hwif = kzalloc(sizeof(*hwif), GFP_KERNEL);
+		if (hwif == NULL)
+			continue;
+
+		idx = ide_find_port_slot(d);
+		if (idx < 0) {
+			printk(KERN_ERR "%s: no free slot for interface\n",
+					d ? d->name : "ide");
+			kfree(hwif);
+			continue;
+		}
+
+		ide_init_port_data(hwif, idx);
+
+		host->ports[i] = hwif;
+		host->n_ports++;
+	}
+
+	if (host->n_ports == 0) {
+		kfree(host);
+		return NULL;
+	}
+
+	return host;
+}
+EXPORT_SYMBOL_GPL(ide_host_alloc_all);
+
+struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws)
+{
+	hw_regs_t *hws_all[MAX_HWIFS];
+	int i;
+
+	for (i = 0; i < MAX_HWIFS; i++)
+		hws_all[i] = (i < 4) ? hws[i] : NULL;
+
+	return ide_host_alloc_all(d, hws_all);
+}
+EXPORT_SYMBOL_GPL(ide_host_alloc);
+
+int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
+		      hw_regs_t **hws)
+{
+	ide_hwif_t *hwif, *mate = NULL;
+	int i, j = 0;
+
+	for (i = 0; i < MAX_HWIFS; i++) {
+		hwif = host->ports[i];
+
+		if (hwif == NULL) {
 			mate = NULL;
 			continue;
 		}
 
-		hwif = &ide_hwifs[idx[i]];
-
+		ide_init_port_hw(hwif, hws[i]);
 		ide_port_apply_params(hwif);
 
 		if (d == NULL) {
@@ -1534,10 +1655,10 @@
 	}
 
 	for (i = 0; i < MAX_HWIFS; i++) {
-		if (idx[i] == 0xff)
-			continue;
+		hwif = host->ports[i];
 
-		hwif = &ide_hwifs[idx[i]];
+		if (hwif == NULL)
+			continue;
 
 		if (ide_probe_port(hwif) == 0)
 			hwif->present = 1;
@@ -1551,19 +1672,20 @@
 	}
 
 	for (i = 0; i < MAX_HWIFS; i++) {
-		if (idx[i] == 0xff)
-			continue;
+		hwif = host->ports[i];
 
-		hwif = &ide_hwifs[idx[i]];
+		if (hwif == NULL)
+			continue;
 
 		if (hwif_init(hwif) == 0) {
 			printk(KERN_INFO "%s: failed to initialize IDE "
 					 "interface\n", hwif->name);
 			hwif->present = 0;
-			rc = -1;
 			continue;
 		}
 
+		j++;
+
 		if (hwif->present)
 			ide_port_setup_devices(hwif);
 
@@ -1574,10 +1696,10 @@
 	}
 
 	for (i = 0; i < MAX_HWIFS; i++) {
-		if (idx[i] == 0xff)
-			continue;
+		hwif = host->ports[i];
 
-		hwif = &ide_hwifs[idx[i]];
+		if (hwif == NULL)
+			continue;
 
 		if (hwif->chipset == ide_unknown)
 			hwif->chipset = ide_generic;
@@ -1587,10 +1709,10 @@
 	}
 
 	for (i = 0; i < MAX_HWIFS; i++) {
-		if (idx[i] == 0xff)
-			continue;
+		hwif = host->ports[i];
 
-		hwif = &ide_hwifs[idx[i]];
+		if (hwif == NULL)
+			continue;
 
 		ide_sysfs_register_port(hwif);
 		ide_proc_register_port(hwif);
@@ -1599,21 +1721,64 @@
 			ide_proc_port_register_devices(hwif);
 	}
 
-	return rc;
+	return j ? 0 : -1;
 }
-EXPORT_SYMBOL_GPL(ide_device_add_all);
+EXPORT_SYMBOL_GPL(ide_host_register);
 
-int ide_device_add(u8 idx[4], const struct ide_port_info *d)
+int ide_host_add(const struct ide_port_info *d, hw_regs_t **hws,
+		 struct ide_host **hostp)
 {
-	u8 idx_all[MAX_HWIFS];
+	struct ide_host *host;
+	int rc;
+
+	host = ide_host_alloc(d, hws);
+	if (host == NULL)
+		return -ENOMEM;
+
+	rc = ide_host_register(host, d, hws);
+	if (rc) {
+		ide_host_free(host);
+		return rc;
+	}
+
+	if (hostp)
+		*hostp = host;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ide_host_add);
+
+void ide_host_free(struct ide_host *host)
+{
+	ide_hwif_t *hwif;
 	int i;
 
-	for (i = 0; i < MAX_HWIFS; i++)
-		idx_all[i] = (i < 4) ? idx[i] : 0xff;
+	for (i = 0; i < MAX_HWIFS; i++) {
+		hwif = host->ports[i];
 
-	return ide_device_add_all(idx_all, d);
+		if (hwif == NULL)
+			continue;
+
+		ide_free_port_slot(hwif->index);
+		kfree(hwif);
+	}
+
+	kfree(host);
 }
-EXPORT_SYMBOL_GPL(ide_device_add);
+EXPORT_SYMBOL_GPL(ide_host_free);
+
+void ide_host_remove(struct ide_host *host)
+{
+	int i;
+
+	for (i = 0; i < MAX_HWIFS; i++) {
+		if (host->ports[i])
+			ide_unregister(host->ports[i]);
+	}
+
+	ide_host_free(host);
+}
+EXPORT_SYMBOL_GPL(ide_host_remove);
 
 void ide_port_scan(ide_hwif_t *hwif)
 {
@@ -1634,11 +1799,10 @@
 }
 EXPORT_SYMBOL_GPL(ide_port_scan);
 
-static void ide_legacy_init_one(u8 *idx, hw_regs_t *hw, u8 port_no,
-				const struct ide_port_info *d,
+static void ide_legacy_init_one(hw_regs_t **hws, hw_regs_t *hw,
+				u8 port_no, const struct ide_port_info *d,
 				unsigned long config)
 {
-	ide_hwif_t *hwif;
 	unsigned long base, ctl;
 	int irq;
 
@@ -1668,33 +1832,25 @@
 	ide_std_init_ports(hw, base, ctl);
 	hw->irq = irq;
 	hw->chipset = d->chipset;
+	hw->config = config;
 
-	hwif = ide_find_port_slot(d);
-	if (hwif) {
-		ide_init_port_hw(hwif, hw);
-		if (config)
-			hwif->config_data = config;
-		idx[port_no] = hwif->index;
-	}
+	hws[port_no] = hw;
 }
 
 int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config)
 {
-	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
-	hw_regs_t hw[2];
+	hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL };
 
 	memset(&hw, 0, sizeof(hw));
 
 	if ((d->host_flags & IDE_HFLAG_QD_2ND_PORT) == 0)
-		ide_legacy_init_one(idx, &hw[0], 0, d, config);
-	ide_legacy_init_one(idx, &hw[1], 1, d, config);
+		ide_legacy_init_one(hws, &hw[0], 0, d, config);
+	ide_legacy_init_one(hws, &hw[1], 1, d, config);
 
-	if (idx[0] == 0xff && idx[1] == 0xff &&
+	if (hws[0] == NULL && hws[1] == NULL &&
 	    (d->host_flags & IDE_HFLAG_SINGLE))
 		return -ENOENT;
 
-	ide_device_add(idx, d);
-
-	return 0;
+	return ide_host_add(d, hws, NULL);
 }
 EXPORT_SYMBOL_GPL(ide_legacy_device_add);
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index 8af88bf0..151c91e 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -345,7 +345,7 @@
 	ide_task_t task;
 	int err;
 
-	if (arg < 0 || arg > 70)
+	if (arg < XFER_PIO_0 || arg > XFER_UDMA_6)
 		return -EINVAL;
 
 	memset(&task, 0, sizeof(task));
@@ -357,7 +357,7 @@
 
 	err = ide_no_data_taskfile(drive, &task);
 
-	if (!err && arg) {
+	if (!err) {
 		ide_set_xfer_rate(drive, (u8) arg);
 		ide_driveid_update(drive);
 	}
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index b711ab9..6962ca4 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -195,23 +195,6 @@
 #define IDETAPE_BLOCK_DESCRIPTOR	0
 #define IDETAPE_CAPABILITIES_PAGE	0x2a
 
-/* Tape flag bits values. */
-enum {
-	IDETAPE_FLAG_IGNORE_DSC		= (1 << 0),
-	/* 0 When the tape position is unknown */
-	IDETAPE_FLAG_ADDRESS_VALID	= (1 <<	1),
-	/* Device already opened */
-	IDETAPE_FLAG_BUSY		= (1 << 2),
-	/* Attempt to auto-detect the current user block size */
-	IDETAPE_FLAG_DETECT_BS		= (1 << 3),
-	/* Currently on a filemark */
-	IDETAPE_FLAG_FILEMARK		= (1 << 4),
-	/* DRQ interrupt device */
-	IDETAPE_FLAG_DRQ_INTERRUPT	= (1 << 5),
-	/* 0 = no tape is loaded, so we don't rewind after ejecting */
-	IDETAPE_FLAG_MEDIUM_PRESENT	= (1 << 6),
-};
-
 /*
  * Most of our global data which we need to save even as we leave the driver due
  * to an interrupt or a timer event is stored in the struct defined below.
@@ -312,8 +295,6 @@
 	/* Wasted space in each stage */
 	int excess_bh_size;
 
-	/* Status/Action flags: long for set_bit */
-	unsigned long flags;
 	/* protects the ide-tape queue */
 	spinlock_t lock;
 
@@ -398,7 +379,7 @@
 		count = min(
 			(unsigned int)(bh->b_size - atomic_read(&bh->b_count)),
 			bcount);
-		drive->hwif->input_data(drive, NULL, bh->b_data +
+		drive->hwif->tp_ops->input_data(drive, NULL, bh->b_data +
 					atomic_read(&bh->b_count), count);
 		bcount -= count;
 		atomic_add(count, &bh->b_count);
@@ -424,7 +405,7 @@
 			return;
 		}
 		count = min((unsigned int)pc->b_count, (unsigned int)bcount);
-		drive->hwif->output_data(drive, NULL, pc->b_data, count);
+		drive->hwif->tp_ops->output_data(drive, NULL, pc->b_data, count);
 		bcount -= count;
 		pc->b_data += count;
 		pc->b_count -= count;
@@ -585,7 +566,6 @@
 		bh = bh->b_reqnext;
 		kfree(prev_bh);
 	}
-	kfree(tape->merge_bh);
 }
 
 static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
@@ -665,7 +645,7 @@
 		if (readpos[0] & 0x4) {
 			printk(KERN_INFO "ide-tape: Block location is unknown"
 					 "to the tape\n");
-			clear_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags);
+			clear_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags);
 			uptodate = 0;
 		} else {
 			debug_log(DBG_SENSE, "Block Location - %u\n",
@@ -673,7 +653,7 @@
 
 			tape->partition = readpos[1];
 			tape->first_frame = be32_to_cpu(*(u32 *)&readpos[4]);
-			set_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags);
+			set_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags);
 		}
 	}
 
@@ -690,7 +670,6 @@
 	pc->buf_size = IDETAPE_PC_BUFFER_SIZE;
 	pc->bh = NULL;
 	pc->b_data = NULL;
-	pc->callback = ide_tape_callback;
 }
 
 static void idetape_create_request_sense_cmd(struct ide_atapi_pc *pc)
@@ -705,7 +684,7 @@
 {
 	blk_rq_init(NULL, rq);
 	rq->cmd_type = REQ_TYPE_SPECIAL;
-	rq->cmd[0] = cmd;
+	rq->cmd[13] = cmd;
 }
 
 /*
@@ -732,6 +711,7 @@
 	rq->cmd_flags |= REQ_PREEMPT;
 	rq->buffer = (char *) pc;
 	rq->rq_disk = tape->disk;
+	memcpy(rq->cmd, pc->c, 12);
 	ide_do_drive_cmd(drive, rq);
 }
 
@@ -742,7 +722,6 @@
  */
 static void idetape_retry_pc(ide_drive_t *drive)
 {
-	idetape_tape_t *tape = drive->driver_data;
 	struct ide_atapi_pc *pc;
 	struct request *rq;
 
@@ -750,7 +729,7 @@
 	pc = idetape_next_pc_storage(drive);
 	rq = idetape_next_rq_storage(drive);
 	idetape_create_request_sense_cmd(pc);
-	set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags);
+	set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
 	idetape_queue_pc_head(drive, pc, rq);
 }
 
@@ -887,7 +866,7 @@
 			pc->error = IDETAPE_ERROR_GENERAL;
 		}
 		tape->failed_pc = NULL;
-		pc->callback(drive);
+		drive->pc_callback(drive);
 		return ide_stopped;
 	}
 	debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]);
@@ -927,11 +906,12 @@
 
 static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
 {
+	ide_hwif_t *hwif = drive->hwif;
 	idetape_tape_t *tape = drive->driver_data;
 	struct ide_atapi_pc *pc = tape->pc;
 	u8 stat;
 
-	stat = ide_read_status(drive);
+	stat = hwif->tp_ops->read_status(hwif);
 
 	if (stat & SEEK_STAT) {
 		if (stat & ERR_STAT) {
@@ -948,14 +928,17 @@
 		pc->error = IDETAPE_ERROR_GENERAL;
 		tape->failed_pc = NULL;
 	}
-	pc->callback(drive);
+	drive->pc_callback(drive);
 	return ide_stopped;
 }
 
 static void ide_tape_create_rw_cmd(idetape_tape_t *tape,
-		struct ide_atapi_pc *pc, unsigned int length,
-		struct idetape_bh *bh, u8 opcode)
+				   struct ide_atapi_pc *pc, struct request *rq,
+				   u8 opcode)
 {
+	struct idetape_bh *bh = (struct idetape_bh *)rq->special;
+	unsigned int length = rq->current_nr_sectors;
+
 	idetape_init_pc(pc);
 	put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
 	pc->c[1] = 1;
@@ -975,11 +958,14 @@
 		pc->b_data = bh->b_data;
 		pc->b_count = atomic_read(&bh->b_count);
 	}
+
+	memcpy(rq->cmd, pc->c, 12);
 }
 
 static ide_startstop_t idetape_do_request(ide_drive_t *drive,
 					  struct request *rq, sector_t block)
 {
+	ide_hwif_t *hwif = drive->hwif;
 	idetape_tape_t *tape = drive->driver_data;
 	struct ide_atapi_pc *pc = NULL;
 	struct request *postponed_rq = tape->postponed_rq;
@@ -1017,17 +1003,17 @@
 	 * If the tape is still busy, postpone our request and service
 	 * the other device meanwhile.
 	 */
-	stat = ide_read_status(drive);
+	stat = hwif->tp_ops->read_status(hwif);
 
-	if (!drive->dsc_overlap && !(rq->cmd[0] & REQ_IDETAPE_PC2))
-		set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags);
+	if (!drive->dsc_overlap && !(rq->cmd[13] & REQ_IDETAPE_PC2))
+		set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
 
 	if (drive->post_reset == 1) {
-		set_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags);
+		set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
 		drive->post_reset = 0;
 	}
 
-	if (!test_and_clear_bit(IDETAPE_FLAG_IGNORE_DSC, &tape->flags) &&
+	if (!test_and_clear_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags) &&
 	    (stat & SEEK_STAT) == 0) {
 		if (postponed_rq == NULL) {
 			tape->dsc_polling_start = jiffies;
@@ -1036,7 +1022,7 @@
 		} else if (time_after(jiffies, tape->dsc_timeout)) {
 			printk(KERN_ERR "ide-tape: %s: DSC timeout\n",
 				tape->name);
-			if (rq->cmd[0] & REQ_IDETAPE_PC2) {
+			if (rq->cmd[13] & REQ_IDETAPE_PC2) {
 				idetape_media_access_finished(drive);
 				return ide_stopped;
 			} else {
@@ -1049,35 +1035,29 @@
 		idetape_postpone_request(drive);
 		return ide_stopped;
 	}
-	if (rq->cmd[0] & REQ_IDETAPE_READ) {
+	if (rq->cmd[13] & REQ_IDETAPE_READ) {
 		pc = idetape_next_pc_storage(drive);
-		ide_tape_create_rw_cmd(tape, pc, rq->current_nr_sectors,
-					(struct idetape_bh *)rq->special,
-					READ_6);
+		ide_tape_create_rw_cmd(tape, pc, rq, READ_6);
 		goto out;
 	}
-	if (rq->cmd[0] & REQ_IDETAPE_WRITE) {
+	if (rq->cmd[13] & REQ_IDETAPE_WRITE) {
 		pc = idetape_next_pc_storage(drive);
-		ide_tape_create_rw_cmd(tape, pc, rq->current_nr_sectors,
-					 (struct idetape_bh *)rq->special,
-					 WRITE_6);
+		ide_tape_create_rw_cmd(tape, pc, rq, WRITE_6);
 		goto out;
 	}
-	if (rq->cmd[0] & REQ_IDETAPE_PC1) {
+	if (rq->cmd[13] & REQ_IDETAPE_PC1) {
 		pc = (struct ide_atapi_pc *) rq->buffer;
-		rq->cmd[0] &= ~(REQ_IDETAPE_PC1);
-		rq->cmd[0] |= REQ_IDETAPE_PC2;
+		rq->cmd[13] &= ~(REQ_IDETAPE_PC1);
+		rq->cmd[13] |= REQ_IDETAPE_PC2;
 		goto out;
 	}
-	if (rq->cmd[0] & REQ_IDETAPE_PC2) {
+	if (rq->cmd[13] & REQ_IDETAPE_PC2) {
 		idetape_media_access_finished(drive);
 		return ide_stopped;
 	}
 	BUG();
-out:
-	if (test_bit(IDETAPE_FLAG_DRQ_INTERRUPT, &tape->flags))
-		pc->flags |= PC_FLAG_DRQ_INTERRUPT;
 
+out:
 	return idetape_issue_pc(drive, pc);
 }
 
@@ -1281,8 +1261,9 @@
 
 	rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
 	rq->cmd_type = REQ_TYPE_SPECIAL;
-	rq->cmd[0] = REQ_IDETAPE_PC1;
+	rq->cmd[13] = REQ_IDETAPE_PC1;
 	rq->buffer = (char *)pc;
+	memcpy(rq->cmd, pc->c, 12);
 	error = blk_execute_rq(drive->queue, tape->disk, rq, 0);
 	blk_put_request(rq);
 	return error;
@@ -1304,7 +1285,7 @@
 	int load_attempted = 0;
 
 	/* Wait for the tape to become ready */
-	set_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags);
+	set_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags);
 	timeout += jiffies;
 	while (time_before(jiffies, timeout)) {
 		idetape_create_test_unit_ready_cmd(&pc);
@@ -1397,7 +1378,7 @@
 	if (tape->chrdev_dir != IDETAPE_DIR_READ)
 		return;
 
-	clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags);
+	clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags);
 	tape->merge_bh_size = 0;
 	if (tape->merge_bh != NULL) {
 		ide_tape_kfree_buffer(tape);
@@ -1465,7 +1446,7 @@
 
 	rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
 	rq->cmd_type = REQ_TYPE_SPECIAL;
-	rq->cmd[0] = cmd;
+	rq->cmd[13] = cmd;
 	rq->rq_disk = tape->disk;
 	rq->special = (void *)bh;
 	rq->sector = tape->first_frame;
@@ -1636,7 +1617,7 @@
 	debug_log(DBG_PROCS, "Enter %s, %d blocks\n", __func__, blocks);
 
 	/* If we are at a filemark, return a read length of 0 */
-	if (test_bit(IDETAPE_FLAG_FILEMARK, &tape->flags))
+	if (test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags))
 		return 0;
 
 	idetape_init_read(drive);
@@ -1746,7 +1727,7 @@
 
 	if (tape->chrdev_dir == IDETAPE_DIR_READ) {
 		tape->merge_bh_size = 0;
-		if (test_and_clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags))
+		if (test_and_clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags))
 			++count;
 		ide_tape_discard_merge_buffer(drive, 0);
 	}
@@ -1801,7 +1782,7 @@
 	debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count);
 
 	if (tape->chrdev_dir != IDETAPE_DIR_READ) {
-		if (test_bit(IDETAPE_FLAG_DETECT_BS, &tape->flags))
+		if (test_bit(IDE_AFLAG_DETECT_BS, &drive->atapi_flags))
 			if (count > tape->blk_size &&
 			    (count % tape->blk_size) == 0)
 				tape->user_bs_factor = count / tape->blk_size;
@@ -1841,7 +1822,7 @@
 		tape->merge_bh_size = bytes_read-temp;
 	}
 finish:
-	if (!actually_read && test_bit(IDETAPE_FLAG_FILEMARK, &tape->flags)) {
+	if (!actually_read && test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) {
 		debug_log(DBG_SENSE, "%s: spacing over filemark\n", tape->name);
 
 		idetape_space_over_filemarks(drive, MTFSF, 1);
@@ -2027,7 +2008,7 @@
 					      !IDETAPE_LU_LOAD_MASK);
 		retval = idetape_queue_pc_tail(drive, &pc);
 		if (!retval)
-			clear_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags);
+			clear_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags);
 		return retval;
 	case MTNOP:
 		ide_tape_discard_merge_buffer(drive, 0);
@@ -2050,9 +2031,9 @@
 			    mt_count % tape->blk_size)
 				return -EIO;
 			tape->user_bs_factor = mt_count / tape->blk_size;
-			clear_bit(IDETAPE_FLAG_DETECT_BS, &tape->flags);
+			clear_bit(IDE_AFLAG_DETECT_BS, &drive->atapi_flags);
 		} else
-			set_bit(IDETAPE_FLAG_DETECT_BS, &tape->flags);
+			set_bit(IDE_AFLAG_DETECT_BS, &drive->atapi_flags);
 		return 0;
 	case MTSEEK:
 		ide_tape_discard_merge_buffer(drive, 0);
@@ -2202,20 +2183,20 @@
 
 	filp->private_data = tape;
 
-	if (test_and_set_bit(IDETAPE_FLAG_BUSY, &tape->flags)) {
+	if (test_and_set_bit(IDE_AFLAG_BUSY, &drive->atapi_flags)) {
 		retval = -EBUSY;
 		goto out_put_tape;
 	}
 
 	retval = idetape_wait_ready(drive, 60 * HZ);
 	if (retval) {
-		clear_bit(IDETAPE_FLAG_BUSY, &tape->flags);
+		clear_bit(IDE_AFLAG_BUSY, &drive->atapi_flags);
 		printk(KERN_ERR "ide-tape: %s: drive not ready\n", tape->name);
 		goto out_put_tape;
 	}
 
 	idetape_read_position(drive);
-	if (!test_bit(IDETAPE_FLAG_ADDRESS_VALID, &tape->flags))
+	if (!test_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags))
 		(void)idetape_rewind_tape(drive);
 
 	/* Read block size and write protect status from drive. */
@@ -2231,7 +2212,7 @@
 	if (tape->write_prot) {
 		if ((filp->f_flags & O_ACCMODE) == O_WRONLY ||
 		    (filp->f_flags & O_ACCMODE) == O_RDWR) {
-			clear_bit(IDETAPE_FLAG_BUSY, &tape->flags);
+			clear_bit(IDE_AFLAG_BUSY, &drive->atapi_flags);
 			retval = -EROFS;
 			goto out_put_tape;
 		}
@@ -2291,7 +2272,7 @@
 			ide_tape_discard_merge_buffer(drive, 1);
 	}
 
-	if (minor < 128 && test_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags))
+	if (minor < 128 && test_bit(IDE_AFLAG_MEDIUM_PRESENT, &drive->atapi_flags))
 		(void) idetape_rewind_tape(drive);
 	if (tape->chrdev_dir == IDETAPE_DIR_NONE) {
 		if (tape->door_locked == DOOR_LOCKED) {
@@ -2301,7 +2282,7 @@
 			}
 		}
 	}
-	clear_bit(IDETAPE_FLAG_BUSY, &tape->flags);
+	clear_bit(IDE_AFLAG_BUSY, &drive->atapi_flags);
 	ide_tape_put(tape);
 	unlock_kernel();
 	return 0;
@@ -2464,6 +2445,8 @@
 	u8 gcw[2];
 	u16 *ctl = (u16 *)&tape->caps[12];
 
+	drive->pc_callback = ide_tape_callback;
+
 	spin_lock_init(&tape->lock);
 	drive->dsc_overlap = 1;
 	if (drive->hwif->host_flags & IDE_HFLAG_NO_DSC) {
@@ -2484,7 +2467,7 @@
 
 	/* Command packet DRQ type */
 	if (((gcw[0] & 0x60) >> 5) == 1)
-		set_bit(IDETAPE_FLAG_DRQ_INTERRUPT, &tape->flags);
+		set_bit(IDE_AFLAG_DRQ_INTERRUPT, &drive->atapi_flags);
 
 	idetape_get_inquiry_results(drive);
 	idetape_get_mode_sense_results(drive);
@@ -2697,10 +2680,12 @@
 
 	idetape_setup(drive, tape, minor);
 
-	device_create(idetape_sysfs_class, &drive->gendev,
-		      MKDEV(IDETAPE_MAJOR, minor), "%s", tape->name);
-	device_create(idetape_sysfs_class, &drive->gendev,
-			MKDEV(IDETAPE_MAJOR, minor + 128), "n%s", tape->name);
+	device_create_drvdata(idetape_sysfs_class, &drive->gendev,
+			      MKDEV(IDETAPE_MAJOR, minor), NULL,
+			      "%s", tape->name);
+	device_create_drvdata(idetape_sysfs_class, &drive->gendev,
+			      MKDEV(IDETAPE_MAJOR, minor + 128), NULL,
+			      "n%s", tape->name);
 
 	g->fops = &idetape_block_ops;
 	ide_register_region(g);
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 1fbdb74..aeddbbd 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -64,6 +64,7 @@
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct ide_taskfile *tf = &task->tf;
 	ide_handler_t *handler = NULL;
+	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
 	const struct ide_dma_ops *dma_ops = hwif->dma_ops;
 
 	if (task->data_phase == TASKFILE_MULTI_IN ||
@@ -80,15 +81,15 @@
 
 	if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) {
 		ide_tf_dump(drive->name, tf);
-		ide_set_irq(drive, 1);
+		tp_ops->set_irq(hwif, 1);
 		SELECT_MASK(drive, 0);
-		hwif->tf_load(drive, task);
+		tp_ops->tf_load(drive, task);
 	}
 
 	switch (task->data_phase) {
 	case TASKFILE_MULTI_OUT:
 	case TASKFILE_OUT:
-		hwif->OUTBSYNC(hwif, tf->command, hwif->io_ports.command_addr);
+		tp_ops->exec_command(hwif, tf->command);
 		ndelay(400);	/* FIXME */
 		return pre_task_out_intr(drive, task->rq);
 	case TASKFILE_MULTI_IN:
@@ -124,7 +125,8 @@
  */
 static ide_startstop_t set_multmode_intr(ide_drive_t *drive)
 {
-	u8 stat = ide_read_status(drive);
+	ide_hwif_t *hwif = drive->hwif;
+	u8 stat = hwif->tp_ops->read_status(hwif);
 
 	if (OK_STAT(stat, READY_STAT, BAD_STAT))
 		drive->mult_count = drive->mult_req;
@@ -141,11 +143,16 @@
  */
 static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
 {
+	ide_hwif_t *hwif = drive->hwif;
 	int retries = 5;
 	u8 stat;
 
-	while (((stat = ide_read_status(drive)) & BUSY_STAT) && retries--)
+	while (1) {
+		stat = hwif->tp_ops->read_status(hwif);
+		if ((stat & BUSY_STAT) == 0 || retries-- == 0)
+			break;
 		udelay(10);
+	};
 
 	if (OK_STAT(stat, READY_STAT, BAD_STAT))
 		return ide_stopped;
@@ -162,7 +169,8 @@
  */
 static ide_startstop_t recal_intr(ide_drive_t *drive)
 {
-	u8 stat = ide_read_status(drive);
+	ide_hwif_t *hwif = drive->hwif;
+	u8 stat = hwif->tp_ops->read_status(hwif);
 
 	if (!OK_STAT(stat, READY_STAT, BAD_STAT))
 		return ide_error(drive, "recal_intr", stat);
@@ -174,11 +182,12 @@
  */
 static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
 {
-	ide_task_t *args	= HWGROUP(drive)->rq->special;
+	ide_hwif_t *hwif = drive->hwif;
+	ide_task_t *args = hwif->hwgroup->rq->special;
 	u8 stat;
 
 	local_irq_enable_in_hardirq();
-	stat = ide_read_status(drive);
+	stat = hwif->tp_ops->read_status(hwif);
 
 	if (!OK_STAT(stat, READY_STAT, BAD_STAT))
 		return ide_error(drive, "task_no_data_intr", stat);
@@ -192,6 +201,7 @@
 
 static u8 wait_drive_not_busy(ide_drive_t *drive)
 {
+	ide_hwif_t *hwif = drive->hwif;
 	int retries;
 	u8 stat;
 
@@ -200,7 +210,7 @@
 	 * take up to 6 ms on some ATAPI devices, so we will wait max 10 ms.
 	 */
 	for (retries = 0; retries < 1000; retries++) {
-		stat = ide_read_status(drive);
+		stat = hwif->tp_ops->read_status(hwif);
 
 		if (stat & BUSY_STAT)
 			udelay(10);
@@ -255,9 +265,9 @@
 
 	/* do the actual data transfer */
 	if (write)
-		hwif->output_data(drive, rq, buf, SECTOR_SIZE);
+		hwif->tp_ops->output_data(drive, rq, buf, SECTOR_SIZE);
 	else
-		hwif->input_data(drive, rq, buf, SECTOR_SIZE);
+		hwif->tp_ops->input_data(drive, rq, buf, SECTOR_SIZE);
 
 	kunmap_atomic(buf, KM_BIO_SRC_IRQ);
 #ifdef CONFIG_HIGHMEM
@@ -383,8 +393,8 @@
 static ide_startstop_t task_in_intr(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = drive->hwif;
-	struct request *rq = HWGROUP(drive)->rq;
-	u8 stat = ide_read_status(drive);
+	struct request *rq = hwif->hwgroup->rq;
+	u8 stat = hwif->tp_ops->read_status(hwif);
 
 	/* Error? */
 	if (stat & ERR_STAT)
@@ -418,7 +428,7 @@
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct request *rq = HWGROUP(drive)->rq;
-	u8 stat = ide_read_status(drive);
+	u8 stat = hwif->tp_ops->read_status(hwif);
 
 	if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
 		return task_error(drive, rq, __func__, stat);
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index d4a6b10..60f0ca6 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1994-1998	    Linus Torvalds & authors (see below)
- *  Copyrifht (C) 2003-2005, 2007   Bartlomiej Zolnierkiewicz
+ *  Copyright (C) 2003-2005, 2007   Bartlomiej Zolnierkiewicz
  */
 
 /*
@@ -101,8 +101,7 @@
 
 	init_completion(&hwif->gendev_rel_comp);
 
-	default_hwif_iops(hwif);
-	default_hwif_transport(hwif);
+	hwif->tp_ops = &default_tp_ops;
 
 	ide_port_init_devices_data(hwif);
 }
@@ -134,41 +133,6 @@
 	}
 }
 
-void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
-{
-	ide_hwgroup_t *hwgroup = hwif->hwgroup;
-
-	spin_lock_irq(&ide_lock);
-	/*
-	 * Remove us from the hwgroup, and free
-	 * the hwgroup if we were the only member
-	 */
-	if (hwif->next == hwif) {
-		BUG_ON(hwgroup->hwif != hwif);
-		kfree(hwgroup);
-	} else {
-		/* There is another interface in hwgroup.
-		 * Unlink us, and set hwgroup->drive and ->hwif to
-		 * something sane.
-		 */
-		ide_hwif_t *g = hwgroup->hwif;
-
-		while (g->next != hwif)
-			g = g->next;
-		g->next = hwif->next;
-		if (hwgroup->hwif == hwif) {
-			/* Chose a random hwif for hwgroup->hwif.
-			 * It's guaranteed that there are no drives
-			 * left in the hwgroup.
-			 */
-			BUG_ON(hwgroup->drive != NULL);
-			hwgroup->hwif = g;
-		}
-		BUG_ON(hwgroup->hwif == hwif);
-	}
-	spin_unlock_irq(&ide_lock);
-}
-
 /* Called with ide_lock held. */
 static void __ide_port_unregister_devices(ide_hwif_t *hwif)
 {
@@ -269,16 +233,9 @@
 	if (hwif->dma_base)
 		ide_release_dma_engine(hwif);
 
-	spin_lock_irq(&ide_lock);
-	/* restore hwif data to pristine status */
-	ide_init_port_data(hwif, hwif->index);
-	spin_unlock_irq(&ide_lock);
-
 	mutex_unlock(&ide_cfg_mtx);
 }
 
-EXPORT_SYMBOL(ide_unregister);
-
 void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw)
 {
 	memcpy(&hwif->io_ports, &hw->io_ports, sizeof(hwif->io_ports));
@@ -287,8 +244,8 @@
 	hwif->dev = hw->dev;
 	hwif->gendev.parent = hw->parent ? hw->parent : hw->dev;
 	hwif->ack_intr = hw->ack_intr;
+	hwif->config_data = hw->config;
 }
-EXPORT_SYMBOL_GPL(ide_init_port_hw);
 
 /*
  *	Locks for IDE setting functionality
diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c
index 0497e7f..7c2afa9 100644
--- a/drivers/ide/legacy/buddha.c
+++ b/drivers/ide/legacy/buddha.c
@@ -37,6 +37,8 @@
 #define CATWEASEL_NUM_HWIFS	3
 #define XSURF_NUM_HWIFS         2
 
+#define MAX_NUM_HWIFS		3
+
     /*
      *  Bases of the IDE interfaces (relative to the board address)
      */
@@ -148,18 +150,14 @@
 
 static int __init buddha_init(void)
 {
-	hw_regs_t hw;
-	ide_hwif_t *hwif;
-	int i;
-
 	struct zorro_dev *z = NULL;
 	u_long buddha_board = 0;
 	BuddhaType type;
-	int buddha_num_hwifs;
+	int buddha_num_hwifs, i;
 
 	while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
 		unsigned long board;
-		u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+		hw_regs_t hw[MAX_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
 
 		if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) {
 			buddha_num_hwifs = BUDDHA_NUM_HWIFS;
@@ -221,19 +219,13 @@
 				ack_intr = xsurf_ack_intr;
 			}
 
-			buddha_setup_ports(&hw, base, ctl, irq_port, ack_intr);
+			buddha_setup_ports(&hw[i], base, ctl, irq_port,
+					   ack_intr);
 
-			hwif = ide_find_port();
-			if (hwif) {
-				u8 index = hwif->index;
-
-				ide_init_port_hw(hwif, &hw);
-
-				idx[i] = index;
-			}
+			hws[i] = &hw[i];
 		}
 
-		ide_device_add(idx, NULL);
+		ide_host_add(NULL, hws, NULL);
 	}
 
 	return 0;
diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c
index 129a812..724f950 100644
--- a/drivers/ide/legacy/falconide.c
+++ b/drivers/ide/legacy/falconide.c
@@ -66,6 +66,27 @@
 	outsw_swapw(data_addr, buf, (len + 1) / 2);
 }
 
+/* Atari has a byte-swapped IDE interface */
+static const struct ide_tp_ops falconide_tp_ops = {
+	.exec_command		= ide_exec_command,
+	.read_status		= ide_read_status,
+	.read_altstatus		= ide_read_altstatus,
+	.read_sff_dma_status	= ide_read_sff_dma_status,
+
+	.set_irq		= ide_set_irq,
+
+	.tf_load		= ide_tf_load,
+	.tf_read		= ide_tf_read,
+
+	.input_data		= falconide_input_data,
+	.output_data		= falconide_output_data,
+};
+
+static const struct ide_port_info falconide_port_info = {
+	.tp_ops			= &falconide_tp_ops,
+	.host_flags		= IDE_HFLAG_NO_DMA,
+};
+
 static void __init falconide_setup_ports(hw_regs_t *hw)
 {
 	int i;
@@ -91,11 +112,12 @@
 
 static int __init falconide_init(void)
 {
-	hw_regs_t hw;
-	ide_hwif_t *hwif;
+	struct ide_host *host;
+	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+	int rc;
 
 	if (!MACH_IS_ATARI || !ATARIHW_PRESENT(IDE))
-		return 0;
+		return -ENODEV;
 
 	printk(KERN_INFO "ide: Falcon IDE controller\n");
 
@@ -106,23 +128,25 @@
 
 	falconide_setup_ports(&hw);
 
-	hwif = ide_find_port();
-	if (hwif) {
-		u8 index = hwif->index;
-		u8 idx[4] = { index, 0xff, 0xff, 0xff };
-
-		ide_init_port_hw(hwif, &hw);
-
-		/* Atari has a byte-swapped IDE interface */
-		hwif->input_data  = falconide_input_data;
-		hwif->output_data = falconide_output_data;
-
-		ide_get_lock(NULL, NULL);
-		ide_device_add(idx, NULL);
-		ide_release_lock();
+	host = ide_host_alloc(&falconide_port_info, hws);
+	if (host == NULL) {
+		rc = -ENOMEM;
+		goto err;
 	}
 
+	ide_get_lock(NULL, NULL);
+	rc = ide_host_register(host, &falconide_port_info, hws);
+	ide_release_lock();
+
+	if (rc)
+		goto err_free;
+
 	return 0;
+err_free:
+	ide_host_free(host);
+err:
+	release_mem_region(ATA_HD_BASE, 0x40);
+	return rc;
 }
 
 module_init(falconide_init);
diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c
index 7e74b20..dd5c467 100644
--- a/drivers/ide/legacy/gayle.c
+++ b/drivers/ide/legacy/gayle.c
@@ -31,6 +31,8 @@
 #define GAYLE_BASE_4000	0xdd2020	/* A4000/A4000T */
 #define GAYLE_BASE_1200	0xda0000	/* A1200/A600 and E-Matrix 530 */
 
+#define GAYLE_IDEREG_SIZE	0x2000
+
     /*
      *  Offsets from one of the above bases
      */
@@ -56,13 +58,11 @@
 #define GAYLE_NUM_HWIFS		1
 #define GAYLE_NUM_PROBE_HWIFS	GAYLE_NUM_HWIFS
 #define GAYLE_HAS_CONTROL_REG	1
-#define GAYLE_IDEREG_SIZE	0x2000
 #else /* CONFIG_BLK_DEV_IDEDOUBLER */
 #define GAYLE_NUM_HWIFS		2
 #define GAYLE_NUM_PROBE_HWIFS	(ide_doubler ? GAYLE_NUM_HWIFS : \
 					       GAYLE_NUM_HWIFS-1)
 #define GAYLE_HAS_CONTROL_REG	(!ide_doubler)
-#define GAYLE_IDEREG_SIZE	(ide_doubler ? 0x1000 : 0x2000)
 
 static int ide_doubler;
 module_param_named(doubler, ide_doubler, bool, 0);
@@ -124,8 +124,11 @@
 
 static int __init gayle_init(void)
 {
+    unsigned long phys_base, res_start, res_n;
+    unsigned long base, ctrlport, irqport;
+    ide_ack_intr_t *ack_intr;
     int a4000, i;
-    u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+    hw_regs_t hw[GAYLE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
 
     if (!MACH_IS_AMIGA)
 	return -ENODEV;
@@ -148,13 +151,6 @@
 #endif
 			 "");
 
-    for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
-	unsigned long base, ctrlport, irqport;
-	ide_ack_intr_t *ack_intr;
-	hw_regs_t hw;
-	ide_hwif_t *hwif;
-	unsigned long phys_base, res_start, res_n;
-
 	if (a4000) {
 	    phys_base = GAYLE_BASE_4000;
 	    irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_4000);
@@ -168,33 +164,22 @@
  * FIXME: we now have selectable modes between mmio v/s iomio
  */
 
-	phys_base += i*GAYLE_NEXT_PORT;
-
 	res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1);
 	res_n = GAYLE_IDEREG_SIZE;
 
 	if (!request_mem_region(res_start, res_n, "IDE"))
-	    continue;
+		return -EBUSY;
 
-	base = (unsigned long)ZTWO_VADDR(phys_base);
+    for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
+	base = (unsigned long)ZTWO_VADDR(phys_base + i * GAYLE_NEXT_PORT);
 	ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0;
 
-	gayle_setup_ports(&hw, base, ctrlport, irqport, ack_intr);
+	gayle_setup_ports(&hw[i], base, ctrlport, irqport, ack_intr);
 
-	hwif = ide_find_port();
-	if (hwif) {
-	    u8 index = hwif->index;
-
-	    ide_init_port_hw(hwif, &hw);
-
-	    idx[i] = index;
-	} else
-	    release_mem_region(res_start, res_n);
+	hws[i] = &hw[i];
     }
 
-    ide_device_add(idx, NULL);
-
-    return 0;
+    return ide_host_add(NULL, hws, NULL);
 }
 
 module_init(gayle_init);
diff --git a/drivers/ide/legacy/ide-4drives.c b/drivers/ide/legacy/ide-4drives.c
index 89c8ff0..c76d55d 100644
--- a/drivers/ide/legacy/ide-4drives.c
+++ b/drivers/ide/legacy/ide-4drives.c
@@ -28,10 +28,8 @@
 
 static int __init ide_4drives_init(void)
 {
-	ide_hwif_t *hwif, *mate;
 	unsigned long base = 0x1f0, ctl = 0x3f6;
-	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
-	hw_regs_t hw;
+	hw_regs_t hw, *hws[] = { &hw, &hw, NULL, NULL };
 
 	if (probe_4drives == 0)
 		return -ENODEV;
@@ -55,21 +53,7 @@
 	hw.irq = 14;
 	hw.chipset = ide_4drives;
 
-	hwif = ide_find_port();
-	if (hwif) {
-		ide_init_port_hw(hwif, &hw);
-		idx[0] = hwif->index;
-	}
-
-	mate = ide_find_port();
-	if (mate) {
-		ide_init_port_hw(mate, &hw);
-		idx[1] = mate->index;
-	}
-
-	ide_device_add(idx, &ide_4drives_port_info);
-
-	return 0;
+	return ide_host_add(&ide_4drives_port_info, hws, NULL);
 }
 
 module_init(ide_4drives_init);
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index 27b1e0b..21bfac1 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -74,7 +74,7 @@
 
 typedef struct ide_info_t {
 	struct pcmcia_device	*p_dev;
-	ide_hwif_t		*hwif;
+	struct ide_host		*host;
     int		ndev;
     dev_node_t	node;
 } ide_info_t;
@@ -132,7 +132,7 @@
 static void ide_detach(struct pcmcia_device *link)
 {
     ide_info_t *info = link->priv;
-    ide_hwif_t *hwif = info->hwif;
+    ide_hwif_t *hwif = info->host->ports[0];
     unsigned long data_addr, ctl_addr;
 
     DEBUG(0, "ide_detach(0x%p)\n", link);
@@ -157,13 +157,13 @@
 	.host_flags		= IDE_HFLAG_NO_DMA,
 };
 
-static ide_hwif_t *idecs_register(unsigned long io, unsigned long ctl,
+static struct ide_host *idecs_register(unsigned long io, unsigned long ctl,
 				unsigned long irq, struct pcmcia_device *handle)
 {
+    struct ide_host *host;
     ide_hwif_t *hwif;
-    hw_regs_t hw;
-    int i;
-    u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+    int i, rc;
+    hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
 
     if (!request_region(io, 8, DRV_NAME)) {
 	printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
@@ -184,30 +184,24 @@
     hw.chipset = ide_pci;
     hw.dev = &handle->dev;
 
-    hwif = ide_find_port();
-    if (hwif == NULL)
+    rc = ide_host_add(&idecs_port_info, hws, &host);
+    if (rc)
 	goto out_release;
 
-    i = hwif->index;
-
-    ide_init_port_hw(hwif, &hw);
-
-    idx[0] = i;
-
-    ide_device_add(idx, &idecs_port_info);
+    hwif = host->ports[0];
 
     if (hwif->present)
-	return hwif;
+	return host;
 
     /* retry registration in case device is still spinning up */
     for (i = 0; i < 10; i++) {
 	msleep(100);
 	ide_port_scan(hwif);
 	if (hwif->present)
-	    return hwif;
+	    return host;
     }
 
-    return hwif;
+    return host;
 
 out_release:
     release_region(ctl, 1);
@@ -239,7 +233,7 @@
     cistpl_cftable_entry_t *cfg;
     int pass, last_ret = 0, last_fn = 0, is_kme = 0;
     unsigned long io_base, ctl_base;
-    ide_hwif_t *hwif;
+    struct ide_host *host;
 
     DEBUG(0, "ide_config(0x%p)\n", link);
 
@@ -334,21 +328,21 @@
     if (is_kme)
 	outb(0x81, ctl_base+1);
 
-     hwif = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
-     if (hwif == NULL && link->io.NumPorts1 == 0x20) {
+     host = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link);
+     if (host == NULL && link->io.NumPorts1 == 0x20) {
 	    outb(0x02, ctl_base + 0x10);
-	    hwif = idecs_register(io_base + 0x10, ctl_base + 0x10,
+	    host = idecs_register(io_base + 0x10, ctl_base + 0x10,
 				  link->irq.AssignedIRQ, link);
     }
 
-    if (hwif == NULL)
+    if (host == NULL)
 	goto failed;
 
     info->ndev = 1;
-    sprintf(info->node.dev_name, "hd%c", 'a' + hwif->index * 2);
-    info->node.major = hwif->major;
+    sprintf(info->node.dev_name, "hd%c", 'a' + host->ports[0]->index * 2);
+    info->node.major = host->ports[0]->major;
     info->node.minor = 0;
-    info->hwif = hwif;
+    info->host = host;
     link->dev_node = &info->node;
     printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n",
 	   info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10);
@@ -379,15 +373,15 @@
 static void ide_release(struct pcmcia_device *link)
 {
     ide_info_t *info = link->priv;
-    ide_hwif_t *hwif = info->hwif;
+    struct ide_host *host = info->host;
 
     DEBUG(0, "ide_release(0x%p)\n", link);
 
-    if (info->ndev) {
+    if (info->ndev)
 	/* FIXME: if this fails we need to queue the cleanup somehow
 	   -- need to investigate the required PCMCIA magic */
-	ide_unregister(hwif);
-    }
+	ide_host_remove(host);
+
     info->ndev = 0;
 
     pcmcia_disable_device(link);
diff --git a/drivers/ide/legacy/ide_platform.c b/drivers/ide/legacy/ide_platform.c
index a249562..051b4ab 100644
--- a/drivers/ide/legacy/ide_platform.c
+++ b/drivers/ide/legacy/ide_platform.c
@@ -52,12 +52,10 @@
 {
 	struct resource *res_base, *res_alt, *res_irq;
 	void __iomem *base, *alt_base;
-	ide_hwif_t *hwif;
 	struct pata_platform_info *pdata;
-	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
-	int ret = 0;
-	int mmio = 0;
-	hw_regs_t hw;
+	struct ide_host *host;
+	int ret = 0, mmio = 0;
+	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
 	struct ide_port_info d = platform_ide_port_info;
 
 	pdata = pdev->dev.platform_data;
@@ -94,28 +92,18 @@
 			res_alt->start, res_alt->end - res_alt->start + 1);
 	}
 
-	hwif = ide_find_port();
-	if (!hwif) {
-		ret = -ENODEV;
-		goto out;
-	}
-
 	memset(&hw, 0, sizeof(hw));
 	plat_ide_setup_ports(&hw, base, alt_base, pdata, res_irq->start);
 	hw.dev = &pdev->dev;
 
-	ide_init_port_hw(hwif, &hw);
-
-	if (mmio) {
+	if (mmio)
 		d.host_flags |= IDE_HFLAG_MMIO;
-		default_hwif_mmiops(hwif);
-	}
 
-	idx[0] = hwif->index;
+	ret = ide_host_add(&d, hws, &host);
+	if (ret)
+		goto out;
 
-	ide_device_add(idx, &d);
-
-	platform_set_drvdata(pdev, hwif);
+	platform_set_drvdata(pdev, host);
 
 	return 0;
 
@@ -125,9 +113,9 @@
 
 static int __devexit plat_ide_remove(struct platform_device *pdev)
 {
-	ide_hwif_t *hwif = pdev->dev.driver_data;
+	struct ide_host *host = pdev->dev.driver_data;
 
-	ide_unregister(hwif);
+	ide_host_remove(host);
 
 	return 0;
 }
diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c
index 0a6195b..a0bb167 100644
--- a/drivers/ide/legacy/macide.c
+++ b/drivers/ide/legacy/macide.c
@@ -91,11 +91,10 @@
 
 static int __init macide_init(void)
 {
-	ide_hwif_t *hwif;
 	ide_ack_intr_t *ack_intr;
 	unsigned long base;
 	int irq;
-	hw_regs_t hw;
+	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
 
 	if (!MACH_IS_MAC)
 		return -ENODEV;
@@ -125,17 +124,7 @@
 
 	macide_setup_ports(&hw, base, irq, ack_intr);
 
-	hwif = ide_find_port();
-	if (hwif) {
-		u8 index = hwif->index;
-		u8 idx[4] = { index, 0xff, 0xff, 0xff };
-
-		ide_init_port_hw(hwif, &hw);
-
-		ide_device_add(idx, NULL);
-	}
-
-	return 0;
+	return ide_host_add(NULL, hws, NULL);
 }
 
 module_init(macide_init);
diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c
index 9c2b9d0..4abd8fc 100644
--- a/drivers/ide/legacy/q40ide.c
+++ b/drivers/ide/legacy/q40ide.c
@@ -96,6 +96,27 @@
 	outsw_swapw(data_addr, buf, (len + 1) / 2);
 }
 
+/* Q40 has a byte-swapped IDE interface */
+static const struct ide_tp_ops q40ide_tp_ops = {
+	.exec_command		= ide_exec_command,
+	.read_status		= ide_read_status,
+	.read_altstatus		= ide_read_altstatus,
+	.read_sff_dma_status	= ide_read_sff_dma_status,
+
+	.set_irq		= ide_set_irq,
+
+	.tf_load		= ide_tf_load,
+	.tf_read		= ide_tf_read,
+
+	.input_data		= q40ide_input_data,
+	.output_data		= q40ide_output_data,
+};
+
+static const struct ide_port_info q40ide_port_info = {
+	.tp_ops			= &q40ide_tp_ops,
+	.host_flags		= IDE_HFLAG_NO_DMA,
+};
+
 /* 
  * the static array is needed to have the name reported in /proc/ioports,
  * hwif->name unfortunately isn't available yet
@@ -111,9 +132,7 @@
 static int __init q40ide_init(void)
 {
     int i;
-    ide_hwif_t *hwif;
-    const char *name;
-    u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+    hw_regs_t hw[Q40IDE_NUM_HWIFS], *hws[] = { NULL, NULL, NULL, NULL };
 
     if (!MACH_IS_Q40)
       return -ENODEV;
@@ -121,9 +140,8 @@
     printk(KERN_INFO "ide: Q40 IDE controller\n");
 
     for (i = 0; i < Q40IDE_NUM_HWIFS; i++) {
-	hw_regs_t hw;
+	const char *name = q40_ide_names[i];
 
-	name = q40_ide_names[i];
 	if (!request_region(pcide_bases[i], 8, name)) {
 		printk("could not reserve ports %lx-%lx for %s\n",
 		       pcide_bases[i],pcide_bases[i]+8,name);
@@ -135,26 +153,13 @@
 		release_region(pcide_bases[i], 8);
 		continue;
 	}
-	q40_ide_setup_ports(&hw, pcide_bases[i],
-			NULL,
-//			m68kide_iops,
+	q40_ide_setup_ports(&hw[i], pcide_bases[i], NULL,
 			q40ide_default_irq(pcide_bases[i]));
 
-	hwif = ide_find_port();
-	if (hwif) {
-		ide_init_port_hw(hwif, &hw);
-
-		/* Q40 has a byte-swapped IDE interface */
-		hwif->input_data  = q40ide_input_data;
-		hwif->output_data = q40ide_output_data;
-
-		idx[i] = hwif->index;
-	}
+	hws[i] = &hw[i];
     }
 
-    ide_device_add(idx, NULL);
-
-    return 0;
+    return ide_host_add(&q40ide_port_info, hws, NULL);
 }
 
 module_init(q40ide_init);
diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
index 48d57ca..11b7f61 100644
--- a/drivers/ide/mips/au1xxx-ide.c
+++ b/drivers/ide/mips/au1xxx-ide.c
@@ -519,6 +519,23 @@
 	*ata_regs = ahwif->regbase + (14 << IDE_REG_SHIFT);
 }
 
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
+static const struct ide_tp_ops au1xxx_tp_ops = {
+	.exec_command		= ide_exec_command,
+	.read_status		= ide_read_status,
+	.read_altstatus		= ide_read_altstatus,
+	.read_sff_dma_status	= ide_read_sff_dma_status,
+
+	.set_irq		= ide_set_irq,
+
+	.tf_load		= ide_tf_load,
+	.tf_read		= ide_tf_read,
+
+	.input_data		= au1xxx_input_data,
+	.output_data		= au1xxx_output_data,
+};
+#endif
+
 static const struct ide_port_ops au1xxx_port_ops = {
 	.set_pio_mode		= au1xxx_set_pio_mode,
 	.set_dma_mode		= auide_set_dma_mode,
@@ -526,6 +543,9 @@
 
 static const struct ide_port_info au1xxx_port_info = {
 	.init_dma		= auide_ddma_init,
+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
+	.tp_ops			= &au1xxx_tp_ops,
+#endif
 	.port_ops		= &au1xxx_port_ops,
 #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
 	.dma_ops		= &au1xxx_dma_ops,
@@ -543,11 +563,10 @@
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	_auide_hwif *ahwif = &auide_hwif;
-	ide_hwif_t *hwif;
 	struct resource *res;
+	struct ide_host *host;
 	int ret = 0;
-	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
-	hw_regs_t hw;
+	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
 
 #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
 	char *mode = "MWDMA2";
@@ -584,36 +603,19 @@
 		goto out;
 	}
 
-	hwif = ide_find_port();
-	if (hwif == NULL) {
-		ret = -ENOENT;
-		goto out;
-	}
-
 	memset(&hw, 0, sizeof(hw));
 	auide_setup_ports(&hw, ahwif);
 	hw.irq = ahwif->irq;
 	hw.dev = dev;
 	hw.chipset = ide_au1xxx;
 
-	ide_init_port_hw(hwif, &hw);
+	ret = ide_host_add(&au1xxx_port_info, hws, &host);
+	if (ret)
+		goto out;
 
-	/* If the user has selected DDMA assisted copies,
-	   then set up a few local I/O function entry points 
-	*/
+	auide_hwif.hwif = host->ports[0];
 
-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA	
-	hwif->input_data  = au1xxx_input_data;
-	hwif->output_data = au1xxx_output_data;
-#endif
-
-	auide_hwif.hwif                 = hwif;
-
-	idx[0] = hwif->index;
-
-	ide_device_add(idx, &au1xxx_port_info);
-
-	dev_set_drvdata(dev, hwif);
+	dev_set_drvdata(dev, host);
 
 	printk(KERN_INFO "Au1xxx IDE(builtin) configured for %s\n", mode );
 
@@ -625,10 +627,10 @@
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct resource *res;
-	ide_hwif_t *hwif = dev_get_drvdata(dev);
+	struct ide_host *host = dev_get_drvdata(dev);
 	_auide_hwif *ahwif = &auide_hwif;
 
-	ide_unregister(hwif);
+	ide_host_remove(host);
 
 	iounmap((void *)ahwif->regbase);
 
diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c
index 9f1212c..badf79f 100644
--- a/drivers/ide/mips/swarm.c
+++ b/drivers/ide/mips/swarm.c
@@ -72,12 +72,11 @@
  */
 static int __devinit swarm_ide_probe(struct device *dev)
 {
-	ide_hwif_t *hwif;
 	u8 __iomem *base;
+	struct ide_host *host;
 	phys_t offset, size;
-	hw_regs_t hw;
-	int i;
-	u8 idx[] = { 0xff, 0xff, 0xff, 0xff };
+	int i, rc;
+	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
 
 	if (!SIBYTE_HAVE_IDE)
 		return -ENODEV;
@@ -116,26 +115,17 @@
 	hw.irq = K_INT_GB_IDE;
 	hw.chipset = ide_generic;
 
-	hwif = ide_find_port_slot(&swarm_port_info);
-	if (hwif == NULL)
+	rc = ide_host_add(&swarm_port_info, hws, &host);
+	if (rc)
 		goto err;
 
-	ide_init_port_hw(hwif, &hw);
-
-	/* Setup MMIO ops. */
-	default_hwif_mmiops(hwif);
-
-	idx[0] = hwif->index;
-
-	ide_device_add(idx, &swarm_port_info);
-
-	dev_set_drvdata(dev, hwif);
+	dev_set_drvdata(dev, host);
 
 	return 0;
 err:
 	release_resource(&swarm_ide_resource);
 	iounmap(base);
-	return -ENOMEM;
+	return rc;
 }
 
 static struct device_driver swarm_ide_driver = {
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index ae7a432..fbc43e1 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -195,7 +195,6 @@
 		.host_flags	= IDE_HFLAG_SERIALIZE |
 				  IDE_HFLAG_NO_ATAPI_DMA |
 				  IDE_HFLAG_NO_DSC |
-				  IDE_HFLAG_ABUSE_SET_DMA_MODE |
 				  IDE_HFLAG_OFF_BOARD,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
@@ -205,7 +204,6 @@
 		.init_chipset	= init_chipset_aec62xx,
 		.port_ops	= &atp86x_port_ops,
 		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_NO_AUTODMA |
-				  IDE_HFLAG_ABUSE_SET_DMA_MODE |
 				  IDE_HFLAG_OFF_BOARD,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
@@ -216,7 +214,6 @@
 		.enablebits	= {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
 		.port_ops	= &atp86x_port_ops,
 		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA |
-				  IDE_HFLAG_ABUSE_SET_DMA_MODE |
 				  IDE_HFLAG_NON_BOOTABLE,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
@@ -226,7 +223,6 @@
 		.init_chipset	= init_chipset_aec62xx,
 		.port_ops	= &atp86x_port_ops,
 		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA |
-				  IDE_HFLAG_ABUSE_SET_DMA_MODE |
 				  IDE_HFLAG_OFF_BOARD,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
@@ -237,7 +233,6 @@
 		.enablebits	= {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
 		.port_ops	= &atp86x_port_ops,
 		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA |
-				  IDE_HFLAG_ABUSE_SET_DMA_MODE |
 				  IDE_HFLAG_OFF_BOARD,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index 80d19c0..5ef7817 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -471,7 +471,15 @@
 	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	unsigned long base = ide_pci_dma_base(hwif, d);
 
-	if (base == 0 || ide_pci_set_master(dev, d->name) < 0)
+	if (base == 0)
+		return -1;
+
+	hwif->dma_base = base;
+
+	if (ide_pci_check_simplex(hwif, d) < 0)
+		return -1;
+
+	if (ide_pci_set_master(dev, d->name) < 0)
 		return -1;
 
 	if (!hwif->channel)
@@ -483,7 +491,7 @@
 	if (ide_allocate_dma_engine(hwif))
 		return -1;
 
-	ide_setup_dma(hwif, base);
+	hwif->dma_ops = &sff_dma_ops;
 
 	return 0;
 }
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index 0bfcdd0..ef7d971 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -218,7 +218,6 @@
 
 #define IDE_HFLAGS_AMD \
 	(IDE_HFLAG_PIO_NO_BLACKLIST | \
-	 IDE_HFLAG_ABUSE_SET_DMA_MODE | \
 	 IDE_HFLAG_POST_SET_MODE | \
 	 IDE_HFLAG_IO_32BIT | \
 	 IDE_HFLAG_UNMASK_IRQS)
diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c
index 1ad1e23..e6c6200 100644
--- a/drivers/ide/pci/cmd640.c
+++ b/drivers/ide/pci/cmd640.c
@@ -181,11 +181,6 @@
 static DEFINE_SPINLOCK(cmd640_lock);
 
 /*
- * These are initialized to point at the devices we control
- */
-static ide_hwif_t  *cmd_hwif0, *cmd_hwif1;
-
-/*
  * Interface to access cmd640x registers
  */
 static unsigned int cmd640_key;
@@ -717,8 +712,7 @@
 	int second_port_cmd640 = 0, rc;
 	const char *bus_type, *port2;
 	u8 b, cfr;
-	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
-	hw_regs_t hw[2];
+	hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL };
 
 	if (cmd640_vlb && probe_for_cmd640_vlb()) {
 		bus_type = "VLB";
@@ -781,15 +775,10 @@
 	printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x"
 			 "\n", 'a' + cmd640_chip_version - 1, bus_type, cfr);
 
-	cmd_hwif0 = ide_find_port();
-
 	/*
 	 * Initialize data for primary port
 	 */
-	if (cmd_hwif0) {
-		ide_init_port_hw(cmd_hwif0, &hw[0]);
-		idx[0] = cmd_hwif0->index;
-	}
+	hws[0] = &hw[0];
 
 	/*
 	 * Ensure compatibility by always using the slowest timings
@@ -829,13 +818,9 @@
 	/*
 	 * Initialize data for secondary cmd640 port, if enabled
 	 */
-	if (second_port_cmd640) {
-		cmd_hwif1 = ide_find_port();
-		if (cmd_hwif1) {
-			ide_init_port_hw(cmd_hwif1, &hw[1]);
-			idx[1] = cmd_hwif1->index;
-		}
-	}
+	if (second_port_cmd640)
+		hws[1] = &hw[1];
+
 	printk(KERN_INFO "cmd640: %sserialized, secondary interface %s\n",
 			 second_port_cmd640 ? "" : "not ", port2);
 
@@ -843,9 +828,7 @@
 	cmd640_dump_regs();
 #endif
 
-	ide_device_add(idx, &cmd640_port_info);
-
-	return 1;
+	return ide_host_add(&cmd640_port_info, hws, NULL);
 }
 
 module_param_named(probe_vlb, cmd640_vlb, bool, 0);
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index cfa784b..ce58bfc 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -262,7 +262,7 @@
 	unsigned long base	= hwif->dma_base - (hwif->channel * 8);
 	u8 irq_mask		= hwif->channel ? MRDMODE_INTR_CH1 :
 						  MRDMODE_INTR_CH0;
-	u8 dma_stat		= inb(hwif->dma_status);
+	u8 dma_stat		= inb(hwif->dma_base + ATA_DMA_STATUS);
 	u8 mrdmode		= inb(base + 1);
 
 #ifdef DEBUG
@@ -286,7 +286,7 @@
 	int irq_reg		= hwif->channel ? ARTTIM23 : CFR;
 	u8  irq_mask		= hwif->channel ? ARTTIM23_INTR_CH1 :
 						  CFR_INTR_CH0;
-	u8  dma_stat		= inb(hwif->dma_status);
+	u8  dma_stat		= inb(hwif->dma_base + ATA_DMA_STATUS);
 	u8  irq_stat		= 0;
 
 	(void) pci_read_config_byte(dev, irq_reg, &irq_stat);
@@ -317,13 +317,13 @@
 
 	drive->waiting_for_dma = 0;
 	/* get DMA status */
-	dma_stat = inb(hwif->dma_status);
+	dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
 	/* read DMA command state */
-	dma_cmd = inb(hwif->dma_command);
+	dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
 	/* stop DMA */
-	outb(dma_cmd & ~1, hwif->dma_command);
+	outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
 	/* clear the INTR & ERROR bits */
-	outb(dma_stat | 6, hwif->dma_status);
+	outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
 	/* and free any DMA resources */
 	ide_destroy_dmatable(drive);
 	/* verify good DMA status */
diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
index 992b1cf..b03d8ae 100644
--- a/drivers/ide/pci/cs5520.c
+++ b/drivers/ide/pci/cs5520.c
@@ -62,8 +62,6 @@
 	struct pci_dev *pdev = to_pci_dev(hwif->dev);
 	int controller = drive->dn > 1 ? 1 : 0;
 
-	/* FIXME: if DMA = 1 do we need to set the DMA bit here ? */
-
 	/* 8bit CAT/CRT - 8bit command timing for channel */
 	pci_write_config_byte(pdev, 0x62 + controller, 
 		(cs5520_pio_clocks[pio].recovery << 4) |
@@ -89,46 +87,17 @@
 	cs5520_set_pio_mode(drive, 0);
 }
 
-/*
- *	We wrap the DMA activate to set the vdma flag. This is needed
- *	so that the IDE DMA layer issues PIO not DMA commands over the
- *	DMA channel
- *
- *	ATAPI is harder so disable it for now using IDE_HFLAG_NO_ATAPI_DMA
- */
-
-static void cs5520_dma_host_set(ide_drive_t *drive, int on)
-{
-	drive->vdma = on;
-	ide_dma_host_set(drive, on);
-}
-
 static const struct ide_port_ops cs5520_port_ops = {
 	.set_pio_mode		= cs5520_set_pio_mode,
 	.set_dma_mode		= cs5520_set_dma_mode,
 };
 
-static const struct ide_dma_ops cs5520_dma_ops = {
-	.dma_host_set		= cs5520_dma_host_set,
-	.dma_setup		= ide_dma_setup,
-	.dma_exec_cmd		= ide_dma_exec_cmd,
-	.dma_start		= ide_dma_start,
-	.dma_end		= __ide_dma_end,
-	.dma_test_irq		= ide_dma_test_irq,
-	.dma_lost_irq		= ide_dma_lost_irq,
-	.dma_timeout		= ide_dma_timeout,
-};
-
-/* FIXME: VDMA is disabled because it caused system hangs */
 #define DECLARE_CS_DEV(name_str)				\
 	{							\
 		.name		= name_str,			\
 		.port_ops	= &cs5520_port_ops,		\
-		.dma_ops	= &cs5520_dma_ops,		\
 		.host_flags	= IDE_HFLAG_ISA_PORTS |		\
-				  IDE_HFLAG_CS5520 |		\
-				  IDE_HFLAG_NO_ATAPI_DMA |	\
-				  IDE_HFLAG_ABUSE_SET_DMA_MODE, \
+				  IDE_HFLAG_CS5520,		\
 		.pio_mask	= ATA_PIO4,			\
 	}
 
@@ -146,7 +115,7 @@
 static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
 	const struct ide_port_info *d = &cyrix_chipsets[id->driver_data];
-	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+	hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL };
 
 	ide_setup_pci_noise(dev, d);
 
@@ -168,11 +137,9 @@
 	 *	do all the device setup for us
 	 */
 
-	ide_pci_setup_ports(dev, d, 14, &idx[0]);
+	ide_pci_setup_ports(dev, d, 14, &hw[0], &hws[0]);
 
-	ide_device_add(idx, d);
-
-	return 0;
+	return ide_host_add(d, hws, NULL);
 }
 
 static const struct pci_device_id cs5520_pci_tbl[] = {
diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c
index dc97c48..5404fe4 100644
--- a/drivers/ide/pci/cs5535.c
+++ b/drivers/ide/pci/cs5535.c
@@ -171,8 +171,7 @@
 static const struct ide_port_info cs5535_chipset __devinitdata = {
 	.name		= "CS5535",
 	.port_ops	= &cs5535_port_ops,
-	.host_flags	= IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE |
-			  IDE_HFLAG_ABUSE_SET_DMA_MODE,
+	.host_flags	= IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE,
 	.pio_mask	= ATA_PIO4,
 	.mwdma_mask	= ATA_MWDMA2,
 	.udma_mask	= ATA_UDMA4,
diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/pci/delkin_cb.c
index 0106e2a..f84bfb4 100644
--- a/drivers/ide/pci/delkin_cb.c
+++ b/drivers/ide/pci/delkin_cb.c
@@ -56,11 +56,10 @@
 static int __devinit
 delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
 {
+	struct ide_host *host;
 	unsigned long base;
-	hw_regs_t hw;
-	ide_hwif_t *hwif = NULL;
 	int i, rc;
-	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
 
 	rc = pci_enable_device(dev);
 	if (rc) {
@@ -87,34 +86,26 @@
 	hw.dev = &dev->dev;
 	hw.chipset = ide_pci;		/* this enables IRQ sharing */
 
-	hwif = ide_find_port();
-	if (hwif == NULL)
+	rc = ide_host_add(&delkin_cb_port_info, hws, &host);
+	if (rc)
 		goto out_disable;
 
-	i = hwif->index;
-
-	ide_init_port_hw(hwif, &hw);
-
-	idx[0] = i;
-
-	ide_device_add(idx, &delkin_cb_port_info);
-
-	pci_set_drvdata(dev, hwif);
+	pci_set_drvdata(dev, host);
 
 	return 0;
 
 out_disable:
 	pci_release_regions(dev);
 	pci_disable_device(dev);
-	return -ENODEV;
+	return rc;
 }
 
 static void
 delkin_cb_remove (struct pci_dev *dev)
 {
-	ide_hwif_t *hwif = pci_get_drvdata(dev);
+	struct ide_host *host = pci_get_drvdata(dev);
 
-	ide_unregister(hwif);
+	ide_host_remove(host);
 
 	pci_release_regions(dev);
 	pci_disable_device(dev);
diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
index 84c36c1..9e1d1c4 100644
--- a/drivers/ide/pci/hpt34x.c
+++ b/drivers/ide/pci/hpt34x.c
@@ -123,7 +123,6 @@
 #define IDE_HFLAGS_HPT34X \
 	(IDE_HFLAG_NO_ATAPI_DMA | \
 	 IDE_HFLAG_NO_DSC | \
-	 IDE_HFLAG_ABUSE_SET_DMA_MODE | \
 	 IDE_HFLAG_NO_AUTODMA)
 
 static const struct ide_port_info hpt34x_chipsets[] __devinitdata = {
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index 397c6cb..1f1135c 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -801,9 +801,9 @@
 	printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo & 0x1ff);
 
 	/* get DMA command mode */
-	dma_cmd = inb(hwif->dma_command);
+	dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
 	/* stop DMA */
-	outb(dma_cmd & ~0x1, hwif->dma_command);
+	outb(dma_cmd & ~0x1, hwif->dma_base + ATA_DMA_CMD);
 	hpt370_clear_engine(drive);
 }
 
@@ -818,12 +818,12 @@
 static int hpt370_dma_end(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-	u8  dma_stat		= inb(hwif->dma_status);
+	u8  dma_stat		= inb(hwif->dma_base + ATA_DMA_STATUS);
 
 	if (dma_stat & 0x01) {
 		/* wait a little */
 		udelay(20);
-		dma_stat = inb(hwif->dma_status);
+		dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
 		if (dma_stat & 0x01)
 			hpt370_irq_timeout(drive);
 	}
@@ -850,7 +850,7 @@
 		return 0;
 	}
 
-	dma_stat = inb(hwif->dma_status);
+	dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
 	/* return 1 if INTR asserted */
 	if (dma_stat & 4)
 		return 1;
@@ -1320,7 +1320,15 @@
 	unsigned long flags, base = ide_pci_dma_base(hwif, d);
 	u8 dma_old, dma_new, masterdma = 0, slavedma = 0;
 
-	if (base == 0 || ide_pci_set_master(dev, d->name) < 0)
+	if (base == 0)
+		return -1;
+
+	hwif->dma_base = base;
+
+	if (ide_pci_check_simplex(hwif, d) < 0)
+		return -1;
+
+	if (ide_pci_set_master(dev, d->name) < 0)
 		return -1;
 
 	dma_old = inb(base + 2);
@@ -1346,7 +1354,7 @@
 	if (ide_allocate_dma_engine(hwif))
 		return -1;
 
-	ide_setup_dma(hwif, base);
+	hwif->dma_ops = &sff_dma_ops;
 
 	return 0;
 }
@@ -1401,7 +1409,6 @@
 
 #define IDE_HFLAGS_HPT3XX \
 	(IDE_HFLAG_NO_ATAPI_DMA | \
-	 IDE_HFLAG_ABUSE_SET_DMA_MODE | \
 	 IDE_HFLAG_OFF_BOARD)
 
 static const struct ide_port_ops hpt3xx_port_ops = {
diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c
index 45ba71a..5cd2b32 100644
--- a/drivers/ide/pci/ns87415.c
+++ b/drivers/ide/pci/ns87415.c
@@ -28,10 +28,6 @@
  */
 #include <asm/superio.h>
 
-static unsigned long superio_ide_status[2];
-static unsigned long superio_ide_select[2];
-static unsigned long superio_ide_dma_status[2];
-
 #define SUPERIO_IDE_MAX_RETRIES 25
 
 /* Because of a defect in Super I/O, all reads of the PCI DMA status 
@@ -40,27 +36,28 @@
  */
 static u8 superio_ide_inb (unsigned long port)
 {
-	if (port == superio_ide_status[0] ||
-	    port == superio_ide_status[1] ||
-	    port == superio_ide_select[0] ||
-	    port == superio_ide_select[1] ||
-	    port == superio_ide_dma_status[0] ||
-	    port == superio_ide_dma_status[1]) {
-		u8 tmp;
-		int retries = SUPERIO_IDE_MAX_RETRIES;
+	u8 tmp;
+	int retries = SUPERIO_IDE_MAX_RETRIES;
 
-		/* printk(" [ reading port 0x%x with retry ] ", port); */
+	/* printk(" [ reading port 0x%x with retry ] ", port); */
 
-		do {
-			tmp = inb(port);
-			if (tmp == 0)
-				udelay(50);
-		} while (tmp == 0 && retries-- > 0);
+	do {
+		tmp = inb(port);
+		if (tmp == 0)
+			udelay(50);
+	} while (tmp == 0 && retries-- > 0);
 
-		return tmp;
-	}
+	return tmp;
+}
 
-	return inb(port);
+static u8 superio_read_status(ide_hwif_t *hwif)
+{
+	return superio_ide_inb(hwif->io_ports.status_addr);
+}
+
+static u8 superio_read_sff_dma_status(ide_hwif_t *hwif)
+{
+	return superio_ide_inb(hwif->dma_base + ATA_DMA_STATUS);
 }
 
 static void superio_tf_read(ide_drive_t *drive, ide_task_t *task)
@@ -78,6 +75,8 @@
 	/* be sure we're looking at the low order bits */
 	outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
 
+	if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+		tf->feature = inb(io_ports->feature_addr);
 	if (task->tf_flags & IDE_TFLAG_IN_NSECT)
 		tf->nsect  = inb(io_ports->nsect_addr);
 	if (task->tf_flags & IDE_TFLAG_IN_LBAL)
@@ -105,36 +104,32 @@
 	}
 }
 
-static void __devinit superio_ide_init_iops (struct hwif_s *hwif)
+static const struct ide_tp_ops superio_tp_ops = {
+	.exec_command		= ide_exec_command,
+	.read_status		= superio_read_status,
+	.read_altstatus		= ide_read_altstatus,
+	.read_sff_dma_status	= superio_read_sff_dma_status,
+
+	.set_irq		= ide_set_irq,
+
+	.tf_load		= ide_tf_load,
+	.tf_read		= superio_tf_read,
+
+	.input_data		= ide_input_data,
+	.output_data		= ide_output_data,
+};
+
+static void __devinit superio_init_iops(struct hwif_s *hwif)
 {
 	struct pci_dev *pdev = to_pci_dev(hwif->dev);
-	u32 base, dmabase;
+	u32 dma_stat;
 	u8 port = hwif->channel, tmp;
 
-	base = pci_resource_start(pdev, port * 2) & ~3;
-	dmabase = pci_resource_start(pdev, 4) & ~3;
-
-	superio_ide_status[port] = base + 7;
-	superio_ide_select[port] = base + 6;
-	superio_ide_dma_status[port] = dmabase + (!port ? 2 : 0xa);
+	dma_stat = (pci_resource_start(pdev, 4) & ~3) + (!port ? 2 : 0xa);
 
 	/* Clear error/interrupt, enable dma */
-	tmp = superio_ide_inb(superio_ide_dma_status[port]);
-	outb(tmp | 0x66, superio_ide_dma_status[port]);
-
-	hwif->tf_read = superio_tf_read;
-
-	/* We need to override inb to workaround a SuperIO errata */
-	hwif->INB = superio_ide_inb;
-}
-
-static void __devinit init_iops_ns87415(ide_hwif_t *hwif)
-{
-	struct pci_dev *dev = to_pci_dev(hwif->dev);
-
-	if (PCI_SLOT(dev->devfn) == 0xE)
-		/* Built-in - assume it's under superio. */
-		superio_ide_init_iops(hwif);
+	tmp = superio_ide_inb(dma_stat);
+	outb(tmp | 0x66, dma_stat);
 }
 #endif
 
@@ -200,14 +195,14 @@
 	u8 dma_stat = 0, dma_cmd = 0;
 
 	drive->waiting_for_dma = 0;
-	dma_stat = hwif->INB(hwif->dma_status);
-	/* get dma command mode */
-	dma_cmd = hwif->INB(hwif->dma_command);
+	dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+	/* get DMA command mode */
+	dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
 	/* stop DMA */
-	outb(dma_cmd & ~1, hwif->dma_command);
+	outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
 	/* from ERRATA: clear the INTR & ERROR bits */
-	dma_cmd = hwif->INB(hwif->dma_command);
-	outb(dma_cmd | 6, hwif->dma_command);
+	dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
+	outb(dma_cmd | 6, hwif->dma_base + ATA_DMA_CMD);
 	/* and free any DMA resources */
 	ide_destroy_dmatable(drive);
 	/* verify good DMA status */
@@ -276,7 +271,7 @@
 		outb(8, hwif->io_ports.ctl_addr);
 		do {
 			udelay(50);
-			stat = hwif->INB(hwif->io_ports.status_addr);
+			stat = hwif->tp_ops->read_status(hwif);
                 	if (stat == 0xff)
                         	break;
         	} while ((stat & BUSY_STAT) && --timeout);
@@ -291,7 +286,7 @@
 	if (!hwif->dma_base)
 		return;
 
-	outb(0x60, hwif->dma_status);
+	outb(0x60, hwif->dma_base + ATA_DMA_STATUS);
 }
 
 static const struct ide_port_ops ns87415_port_ops = {
@@ -311,9 +306,6 @@
 
 static const struct ide_port_info ns87415_chipset __devinitdata = {
 	.name		= "NS87415",
-#ifdef CONFIG_SUPERIO
-	.init_iops	= init_iops_ns87415,
-#endif
 	.init_hwif	= init_hwif_ns87415,
 	.port_ops	= &ns87415_port_ops,
 	.dma_ops	= &ns87415_dma_ops,
@@ -323,7 +315,16 @@
 
 static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-	return ide_setup_pci_device(dev, &ns87415_chipset);
+	struct ide_port_info d = ns87415_chipset;
+
+#ifdef CONFIG_SUPERIO
+	if (PCI_SLOT(dev->devfn) == 0xE) {
+		/* Built-in - assume it's under superio. */
+		d.init_iops = superio_init_iops;
+		d.tp_ops = &superio_tp_ops;
+	}
+#endif
+	return ide_setup_pci_device(dev, &d);
 }
 
 static const struct pci_device_id ns87415_pci_tbl[] = {
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index fca89ed..e54dc65 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -206,7 +206,7 @@
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	unsigned long high_16	= hwif->extra_base - 16;
-	u8 dma_stat		= inb(hwif->dma_status);
+	u8 dma_stat		= inb(hwif->dma_base + ATA_DMA_STATUS);
 	u8 sc1d			= inb(high_16 + 0x001d);
 
 	if (hwif->channel) {
@@ -312,7 +312,6 @@
 
 #define IDE_HFLAGS_PDC202XX \
 	(IDE_HFLAG_ERROR_STOPS_FIFO | \
-	 IDE_HFLAG_ABUSE_SET_DMA_MODE | \
 	 IDE_HFLAG_OFF_BOARD)
 
 static const struct ide_port_ops pdc20246_port_ops = {
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index f04738d..0ce41b4 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -227,9 +227,9 @@
 	u8 dma_stat;
 
 	/* clear the INTR & ERROR bits */
-	dma_stat = inb(hwif->dma_status);
+	dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
 	/* Should we force the bit as well ? */
-	outb(dma_stat, hwif->dma_status);
+	outb(dma_stat, hwif->dma_base + ATA_DMA_STATUS);
 }
 
 struct ich_laptop {
diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c
index 789c66d..94a7ab86 100644
--- a/drivers/ide/pci/scc_pata.c
+++ b/drivers/ide/pci/scc_pata.c
@@ -65,7 +65,7 @@
 
 static struct scc_ports {
 	unsigned long ctl, dma;
-	ide_hwif_t *hwif;  /* for removing port from system */
+	struct ide_host *host;	/* for removing port from system */
 } scc_ports[MAX_HWIFS];
 
 /* PIO transfer mode  table */
@@ -126,6 +126,46 @@
 	return (u8)data;
 }
 
+static void scc_exec_command(ide_hwif_t *hwif, u8 cmd)
+{
+	out_be32((void *)hwif->io_ports.command_addr, cmd);
+	eieio();
+	in_be32((void *)(hwif->dma_base + 0x01c));
+	eieio();
+}
+
+static u8 scc_read_status(ide_hwif_t *hwif)
+{
+	return (u8)in_be32((void *)hwif->io_ports.status_addr);
+}
+
+static u8 scc_read_altstatus(ide_hwif_t *hwif)
+{
+	return (u8)in_be32((void *)hwif->io_ports.ctl_addr);
+}
+
+static u8 scc_read_sff_dma_status(ide_hwif_t *hwif)
+{
+	return (u8)in_be32((void *)(hwif->dma_base + 4));
+}
+
+static void scc_set_irq(ide_hwif_t *hwif, int on)
+{
+	u8 ctl = ATA_DEVCTL_OBS;
+
+	if (on == 4) { /* hack for SRST */
+		ctl |= 4;
+		on &= ~4;
+	}
+
+	ctl |= on ? 0 : 2;
+
+	out_be32((void *)hwif->io_ports.ctl_addr, ctl);
+	eieio();
+	in_be32((void *)(hwif->dma_base + 0x01c));
+	eieio();
+}
+
 static void scc_ide_insw(unsigned long port, void *addr, u32 count)
 {
 	u16 *ptr = (u16 *)addr;
@@ -148,14 +188,6 @@
 	out_be32((void*)port, addr);
 }
 
-static void scc_ide_outbsync(ide_hwif_t *hwif, u8 addr, unsigned long port)
-{
-	out_be32((void*)port, addr);
-	eieio();
-	in_be32((void*)(hwif->dma_base + 0x01c));
-	eieio();
-}
-
 static void
 scc_ide_outsw(unsigned long port, void *addr, u32 count)
 {
@@ -261,14 +293,14 @@
 {
 	ide_hwif_t *hwif = drive->hwif;
 	u8 unit = (drive->select.b.unit & 0x01);
-	u8 dma_stat = scc_ide_inb(hwif->dma_status);
+	u8 dma_stat = scc_ide_inb(hwif->dma_base + 4);
 
 	if (on)
 		dma_stat |= (1 << (5 + unit));
 	else
 		dma_stat &= ~(1 << (5 + unit));
 
-	scc_ide_outb(dma_stat, hwif->dma_status);
+	scc_ide_outb(dma_stat, hwif->dma_base + 4);
 }
 
 /**
@@ -304,13 +336,13 @@
 	out_be32((void __iomem *)(hwif->dma_base + 8), hwif->dmatable_dma);
 
 	/* specify r/w */
-	out_be32((void __iomem *)hwif->dma_command, reading);
+	out_be32((void __iomem *)hwif->dma_base, reading);
 
-	/* read dma_status for INTR & ERROR flags */
-	dma_stat = in_be32((void __iomem *)hwif->dma_status);
+	/* read DMA status for INTR & ERROR flags */
+	dma_stat = in_be32((void __iomem *)(hwif->dma_base + 4));
 
 	/* clear INTR & ERROR flags */
-	out_be32((void __iomem *)hwif->dma_status, dma_stat|6);
+	out_be32((void __iomem *)(hwif->dma_base + 4), dma_stat | 6);
 	drive->waiting_for_dma = 1;
 	return 0;
 }
@@ -318,10 +350,10 @@
 static void scc_dma_start(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = drive->hwif;
-	u8 dma_cmd = scc_ide_inb(hwif->dma_command);
+	u8 dma_cmd = scc_ide_inb(hwif->dma_base);
 
 	/* start DMA */
-	scc_ide_outb(dma_cmd | 1, hwif->dma_command);
+	scc_ide_outb(dma_cmd | 1, hwif->dma_base);
 	hwif->dma = 1;
 	wmb();
 }
@@ -333,13 +365,13 @@
 
 	drive->waiting_for_dma = 0;
 	/* get DMA command mode */
-	dma_cmd = scc_ide_inb(hwif->dma_command);
+	dma_cmd = scc_ide_inb(hwif->dma_base);
 	/* stop DMA */
-	scc_ide_outb(dma_cmd & ~1, hwif->dma_command);
+	scc_ide_outb(dma_cmd & ~1, hwif->dma_base);
 	/* get DMA status */
-	dma_stat = scc_ide_inb(hwif->dma_status);
+	dma_stat = scc_ide_inb(hwif->dma_base + 4);
 	/* clear the INTR & ERROR bits */
-	scc_ide_outb(dma_stat | 6, hwif->dma_status);
+	scc_ide_outb(dma_stat | 6, hwif->dma_base + 4);
 	/* purge DMA mappings */
 	ide_destroy_dmatable(drive);
 	/* verify good DMA status */
@@ -359,6 +391,7 @@
 static int scc_dma_end(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = HWIF(drive);
+	void __iomem *dma_base = (void __iomem *)hwif->dma_base;
 	unsigned long intsts_port = hwif->dma_base + 0x014;
 	u32 reg;
 	int dma_stat, data_loss = 0;
@@ -397,7 +430,7 @@
 			printk(KERN_WARNING "%s: SERROR\n", SCC_PATA_NAME);
 			out_be32((void __iomem *)intsts_port, INTSTS_SERROR|INTSTS_BMSINT);
 
-			out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+			out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
 			continue;
 		}
 
@@ -412,7 +445,7 @@
 
 			out_be32((void __iomem *)intsts_port, INTSTS_PRERR|INTSTS_BMSINT);
 
-			out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+			out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
 			continue;
 		}
 
@@ -420,12 +453,12 @@
 			printk(KERN_WARNING "%s: Response Error\n", SCC_PATA_NAME);
 			out_be32((void __iomem *)intsts_port, INTSTS_RERR|INTSTS_BMSINT);
 
-			out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+			out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
 			continue;
 		}
 
 		if (reg & INTSTS_ICERR) {
-			out_be32((void __iomem *)hwif->dma_command, in_be32((void __iomem *)hwif->dma_command) & ~QCHCD_IOS_SS);
+			out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
 
 			printk(KERN_WARNING "%s: Illegal Configuration\n", SCC_PATA_NAME);
 			out_be32((void __iomem *)intsts_port, INTSTS_ICERR|INTSTS_BMSINT);
@@ -553,14 +586,9 @@
 				    const struct ide_port_info *d)
 {
 	struct scc_ports *ports = pci_get_drvdata(dev);
-	ide_hwif_t *hwif = NULL;
-	hw_regs_t hw;
-	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
-	int i;
-
-	hwif = ide_find_port_slot(d);
-	if (hwif == NULL)
-		return -ENOMEM;
+	struct ide_host *host;
+	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
+	int i, rc;
 
 	memset(&hw, 0, sizeof(hw));
 	for (i = 0; i <= 8; i++)
@@ -568,11 +596,12 @@
 	hw.irq = dev->irq;
 	hw.dev = &dev->dev;
 	hw.chipset = ide_pci;
-	ide_init_port_hw(hwif, &hw);
 
-	idx[0] = hwif->index;
+	rc = ide_host_add(d, hws, &host);
+	if (rc)
+		return rc;
 
-	ide_device_add(idx, d);
+	ports->host = host;
 
 	return 0;
 }
@@ -701,6 +730,8 @@
 	/* be sure we're looking at the low order bits */
 	scc_ide_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
 
+	if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+		tf->feature = scc_ide_inb(io_ports->feature_addr);
 	if (task->tf_flags & IDE_TFLAG_IN_NSECT)
 		tf->nsect  = scc_ide_inb(io_ports->nsect_addr);
 	if (task->tf_flags & IDE_TFLAG_IN_LBAL)
@@ -774,16 +805,6 @@
 
 	ide_set_hwifdata(hwif, ports);
 
-	hwif->tf_load = scc_tf_load;
-	hwif->tf_read = scc_tf_read;
-
-	hwif->input_data  = scc_input_data;
-	hwif->output_data = scc_output_data;
-
-	hwif->INB = scc_ide_inb;
-	hwif->OUTB = scc_ide_outb;
-	hwif->OUTBSYNC = scc_ide_outbsync;
-
 	hwif->dma_base = dma_base;
 	hwif->config_data = ports->ctl;
 }
@@ -824,11 +845,6 @@
 {
 	struct scc_ports *ports = ide_get_hwifdata(hwif);
 
-	ports->hwif = hwif;
-
-	hwif->dma_command = hwif->dma_base;
-	hwif->dma_status = hwif->dma_base + 0x04;
-
 	/* PTERADD */
 	out_be32((void __iomem *)(hwif->dma_base + 0x018), hwif->dmatable_dma);
 
@@ -838,6 +854,21 @@
 		hwif->ultra_mask = ATA_UDMA5; /* 100MHz */
 }
 
+static const struct ide_tp_ops scc_tp_ops = {
+	.exec_command		= scc_exec_command,
+	.read_status		= scc_read_status,
+	.read_altstatus		= scc_read_altstatus,
+	.read_sff_dma_status	= scc_read_sff_dma_status,
+
+	.set_irq		= scc_set_irq,
+
+	.tf_load		= scc_tf_load,
+	.tf_read		= scc_tf_read,
+
+	.input_data		= scc_input_data,
+	.output_data		= scc_output_data,
+};
+
 static const struct ide_port_ops scc_port_ops = {
 	.set_pio_mode		= scc_set_pio_mode,
 	.set_dma_mode		= scc_set_dma_mode,
@@ -861,6 +892,7 @@
       .name		= name_str,			\
       .init_iops	= init_iops_scc,		\
       .init_hwif	= init_hwif_scc,		\
+      .tp_ops		= &scc_tp_ops,		\
       .port_ops		= &scc_port_ops,		\
       .dma_ops		= &scc_dma_ops,			\
       .host_flags	= IDE_HFLAG_SINGLE,		\
@@ -895,7 +927,8 @@
 static void __devexit scc_remove(struct pci_dev *dev)
 {
 	struct scc_ports *ports = pci_get_drvdata(dev);
-	ide_hwif_t *hwif = ports->hwif;
+	struct ide_host *host = ports->host;
+	ide_hwif_t *hwif = host->ports[0];
 
 	if (hwif->dmatable_cpu) {
 		pci_free_consistent(dev, PRD_ENTRIES * PRD_BYTES,
@@ -903,7 +936,7 @@
 		hwif->dmatable_cpu = NULL;
 	}
 
-	ide_unregister(hwif);
+	ide_host_remove(host);
 
 	iounmap((void*)ports->dma);
 	iounmap((void*)ports->ctl);
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index a1fb208..127ccb4 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -349,9 +349,7 @@
 	.cable_detect		= svwks_cable_detect,
 };
 
-#define IDE_HFLAGS_SVWKS \
-	(IDE_HFLAG_LEGACY_IRQS | \
-	 IDE_HFLAG_ABUSE_SET_DMA_MODE)
+#define IDE_HFLAGS_SVWKS IDE_HFLAG_LEGACY_IRQS
 
 static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
 	{	/* 0 */
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index c79ff5b..42eef19 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -127,7 +127,7 @@
 	return 0;
 }
 
-static u8 sgiioc4_INB(unsigned long);
+static u8 sgiioc4_read_status(ide_hwif_t *);
 
 static int
 sgiioc4_clearirq(ide_drive_t * drive)
@@ -141,18 +141,19 @@
 	intr_reg = readl((void __iomem *)other_ir);
 	if (intr_reg & 0x03) { /* Valid IOC4-IDE interrupt */
 		/*
-		 * Using sgiioc4_INB to read the Status register has a side
-		 * effect of clearing the interrupt.  The first read should
+		 * Using sgiioc4_read_status to read the Status register has a
+		 * side effect of clearing the interrupt.  The first read should
 		 * clear it if it is set.  The second read should return
 		 * a "clear" status if it got cleared.  If not, then spin
 		 * for a bit trying to clear it.
 		 */
-		u8 stat = sgiioc4_INB(io_ports->status_addr);
+		u8 stat = sgiioc4_read_status(hwif);
 		int count = 0;
-		stat = sgiioc4_INB(io_ports->status_addr);
+
+		stat = sgiioc4_read_status(hwif);
 		while ((stat & 0x80) && (count++ < 100)) {
 			udelay(1);
-			stat = sgiioc4_INB(io_ports->status_addr);
+			stat = sgiioc4_read_status(hwif);
 		}
 
 		if (intr_reg & 0x02) {
@@ -304,9 +305,9 @@
 	ide_dma_lost_irq(drive);
 }
 
-static u8
-sgiioc4_INB(unsigned long port)
+static u8 sgiioc4_read_status(ide_hwif_t *hwif)
 {
+	unsigned long port = hwif->io_ports.status_addr;
 	u8 reg = (u8) readb((void __iomem *) port);
 
 	if ((port & 0xFFF) == 0x11C) {	/* Status register of IOC4 */
@@ -549,6 +550,21 @@
 	return 0;
 }
 
+static const struct ide_tp_ops sgiioc4_tp_ops = {
+	.exec_command		= ide_exec_command,
+	.read_status		= sgiioc4_read_status,
+	.read_altstatus		= ide_read_altstatus,
+	.read_sff_dma_status	= ide_read_sff_dma_status,
+
+	.set_irq		= ide_set_irq,
+
+	.tf_load		= ide_tf_load,
+	.tf_read		= ide_tf_read,
+
+	.input_data		= ide_input_data,
+	.output_data		= ide_output_data,
+};
+
 static const struct ide_port_ops sgiioc4_port_ops = {
 	.set_dma_mode		= sgiioc4_set_dma_mode,
 	/* reset DMA engine, clear IRQs */
@@ -571,6 +587,7 @@
 	.name			= DRV_NAME,
 	.chipset		= ide_pci,
 	.init_dma		= ide_dma_sgiioc4,
+	.tp_ops			= &sgiioc4_tp_ops,
 	.port_ops		= &sgiioc4_port_ops,
 	.dma_ops		= &sgiioc4_dma_ops,
 	.host_flags		= IDE_HFLAG_MMIO,
@@ -583,10 +600,10 @@
 	unsigned long cmd_base, irqport;
 	unsigned long bar0, cmd_phys_base, ctl;
 	void __iomem *virt_base;
-	ide_hwif_t *hwif;
-	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
-	hw_regs_t hw;
+	struct ide_host *host;
+	hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
 	struct ide_port_info d = sgiioc4_port_info;
+	int rc;
 
 	/*  Get the CmdBlk and CtrlBlk Base Registers */
 	bar0 = pci_resource_start(dev, 0);
@@ -618,30 +635,26 @@
 	hw.chipset = ide_pci;
 	hw.dev = &dev->dev;
 
-	hwif = ide_find_port_slot(&d);
-	if (hwif == NULL)
-		goto err;
-
-	ide_init_port_hw(hwif, &hw);
-
-	/* The IOC4 uses MMIO rather than Port IO. */
-	default_hwif_mmiops(hwif);
-
 	/* Initializing chipset IRQ Registers */
 	writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4));
 
-	hwif->INB = &sgiioc4_INB;
+	host = ide_host_alloc(&d, hws);
+	if (host == NULL) {
+		rc = -ENOMEM;
+		goto err;
+	}
 
-	idx[0] = hwif->index;
-
-	if (ide_device_add(idx, &d))
-		return -EIO;
+	rc = ide_host_register(host, &d, hws);
+	if (rc)
+		goto err_free;
 
 	return 0;
+err_free:
+	ide_host_free(host);
 err:
 	release_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE);
 	iounmap(virt_base);
-	return -ENOMEM;
+	return rc;
 }
 
 static unsigned int __devinit
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index 6e9d765..5965a35 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -334,7 +334,7 @@
 	unsigned long addr	= siimage_selreg(hwif, 1);
 
 	/* return 1 if INTR asserted */
-	if (hwif->INB(hwif->dma_status) & 4)
+	if (inb(hwif->dma_base + ATA_DMA_STATUS) & 4)
 		return 1;
 
 	/* return 1 if Device INTR asserted */
@@ -382,7 +382,7 @@
 	}
 
 	/* return 1 if INTR asserted */
-	if (readb((void __iomem *)hwif->dma_status) & 0x04)
+	if (readb((void __iomem *)(hwif->dma_base + ATA_DMA_STATUS)) & 4)
 		return 1;
 
 	/* return 1 if Device INTR asserted */
@@ -601,7 +601,7 @@
 	 *	Fill in the basic hwif bits
 	 */
 	hwif->host_flags |= IDE_HFLAG_MMIO;
-	default_hwif_mmiops(hwif);
+
 	hwif->hwif_data	= addr;
 
 	/*
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
index 6efbde29..f82a650 100644
--- a/drivers/ide/pci/sl82c105.c
+++ b/drivers/ide/pci/sl82c105.c
@@ -157,9 +157,9 @@
 	 * Was DMA enabled?  If so, disable it - we're resetting the
 	 * host.  The IDE layer will be handling the drive for us.
 	 */
-	dma_cmd = inb(hwif->dma_command);
+	dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
 	if (dma_cmd & 1) {
-		outb(dma_cmd & ~1, hwif->dma_command);
+		outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
 		printk("sl82c105: DMA was enabled\n");
 	}
 
diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c
index 9b4b27a..477e197 100644
--- a/drivers/ide/pci/tc86c001.c
+++ b/drivers/ide/pci/tc86c001.c
@@ -63,7 +63,7 @@
 	ide_hwif_t *hwif	= HWIF(drive);
 	ide_expiry_t *expiry	= ide_get_hwifdata(hwif);
 	ide_hwgroup_t *hwgroup	= HWGROUP(drive);
-	u8 dma_stat		= inb(hwif->dma_status);
+	u8 dma_stat		= inb(hwif->dma_base + ATA_DMA_STATUS);
 
 	/* Restore a higher level driver's expiry handler first. */
 	hwgroup->expiry	= expiry;
@@ -71,21 +71,24 @@
 	if ((dma_stat & 5) == 1) {	/* DMA active and no interrupt */
 		unsigned long sc_base	= hwif->config_data;
 		unsigned long twcr_port	= sc_base + (drive->dn ? 0x06 : 0x04);
-		u8 dma_cmd		= inb(hwif->dma_command);
+		u8 dma_cmd		= inb(hwif->dma_base + ATA_DMA_CMD);
 
 		printk(KERN_WARNING "%s: DMA interrupt possibly stuck, "
 		       "attempting recovery...\n", drive->name);
 
 		/* Stop DMA */
-		outb(dma_cmd & ~0x01, hwif->dma_command);
+		outb(dma_cmd & ~0x01, hwif->dma_base + ATA_DMA_CMD);
 
 		/* Setup the dummy DMA transfer */
 		outw(0, sc_base + 0x0a);	/* Sector Count */
 		outw(0, twcr_port);	/* Transfer Word Count 1 or 2 */
 
 		/* Start the dummy DMA transfer */
-		outb(0x00, hwif->dma_command); /* clear R_OR_WCTR for write */
-		outb(0x01, hwif->dma_command); /* set START_STOPBM */
+
+		/* clear R_OR_WCTR for write */
+		outb(0x00, hwif->dma_base + ATA_DMA_CMD);
+		/* set START_STOPBM */
+		outb(0x01, hwif->dma_base + ATA_DMA_CMD);
 
 		/*
 		 * If an interrupt was pending, it should come thru shortly.
@@ -203,8 +206,7 @@
 	.init_hwif	= init_hwif_tc86c001,
 	.port_ops	= &tc86c001_port_ops,
 	.dma_ops	= &tc86c001_dma_ops,
-	.host_flags	= IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD |
-			  IDE_HFLAG_ABUSE_SET_DMA_MODE,
+	.host_flags	= IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD,
 	.pio_mask	= ATA_PIO4,
 	.mwdma_mask	= ATA_MWDMA2,
 	.udma_mask	= ATA_UDMA4,
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index e47384c..09dc480 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -425,7 +425,6 @@
 	.enablebits	= { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } },
 	.port_ops	= &via_port_ops,
 	.host_flags	= IDE_HFLAG_PIO_NO_BLACKLIST |
-			  IDE_HFLAG_ABUSE_SET_DMA_MODE |
 			  IDE_HFLAG_POST_SET_MODE |
 			  IDE_HFLAG_IO_32BIT,
 	.pio_mask	= ATA_PIO5,
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index 93fb906..c521bf6 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -48,6 +48,8 @@
 #include <asm/mediabay.h>
 #endif
 
+#define DRV_NAME "ide-pmac"
+
 #undef IDE_PMAC_DEBUG
 
 #define DMA_WAIT_TIMEOUT	50
@@ -424,7 +426,9 @@
 static void
 pmac_ide_selectproc(ide_drive_t *drive)
 {
-	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+	ide_hwif_t *hwif = drive->hwif;
+	pmac_ide_hwif_t *pmif =
+		(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
 
 	if (pmif == NULL)
 		return;
@@ -444,7 +448,9 @@
 static void
 pmac_ide_kauai_selectproc(ide_drive_t *drive)
 {
-	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+	ide_hwif_t *hwif = drive->hwif;
+	pmac_ide_hwif_t *pmif =
+		(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
 
 	if (pmif == NULL)
 		return;
@@ -465,7 +471,9 @@
 static void
 pmac_ide_do_update_timings(ide_drive_t *drive)
 {
-	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+	ide_hwif_t *hwif = drive->hwif;
+	pmac_ide_hwif_t *pmif =
+		(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
 
 	if (pmif == NULL)
 		return;
@@ -478,12 +486,26 @@
 		pmac_ide_selectproc(drive);
 }
 
-static void pmac_outbsync(ide_hwif_t *hwif, u8 value, unsigned long port)
+static void pmac_exec_command(ide_hwif_t *hwif, u8 cmd)
 {
-	u32 tmp;
-	
-	writeb(value, (void __iomem *) port);
-	tmp = readl((void __iomem *)(hwif->io_ports.data_addr
+	writeb(cmd, (void __iomem *)hwif->io_ports.command_addr);
+	(void)readl((void __iomem *)(hwif->io_ports.data_addr
+				     + IDE_TIMING_CONFIG));
+}
+
+static void pmac_set_irq(ide_hwif_t *hwif, int on)
+{
+	u8 ctl = ATA_DEVCTL_OBS;
+
+	if (on == 4) { /* hack for SRST */
+		ctl |= 4;
+		on &= ~4;
+	}
+
+	ctl |= on ? 0 : 2;
+
+	writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr);
+	(void)readl((void __iomem *)(hwif->io_ports.data_addr
 				     + IDE_TIMING_CONFIG));
 }
 
@@ -493,11 +515,13 @@
 static void
 pmac_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
+	ide_hwif_t *hwif = drive->hwif;
+	pmac_ide_hwif_t *pmif =
+		(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
 	struct ide_timing *tim = ide_timing_find_mode(XFER_PIO_0 + pio);
 	u32 *timings, t;
 	unsigned accessTicks, recTicks;
 	unsigned accessTime, recTime;
-	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
 	unsigned int cycle_time;
 
 	if (pmif == NULL)
@@ -778,9 +802,11 @@
 
 static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
+	ide_hwif_t *hwif = drive->hwif;
+	pmac_ide_hwif_t *pmif =
+		(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
 	int unit = (drive->select.b.unit & 0x01);
 	int ret = 0;
-	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
 	u32 *timings, *timings2, tl[2];
 
 	timings = &pmif->timings[unit];
@@ -852,11 +878,8 @@
 /* Suspend call back, should be called after the child devices
  * have actually been suspended
  */
-static int
-pmac_ide_do_suspend(ide_hwif_t *hwif)
+static int pmac_ide_do_suspend(pmac_ide_hwif_t *pmif)
 {
-	pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
-	
 	/* We clear the timings */
 	pmif->timings[0] = 0;
 	pmif->timings[1] = 0;
@@ -884,11 +907,8 @@
 /* Resume call back, should be called before the child devices
  * are resumed
  */
-static int
-pmac_ide_do_resume(ide_hwif_t *hwif)
+static int pmac_ide_do_resume(pmac_ide_hwif_t *pmif)
 {
-	pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
-	
 	/* Hard reset & re-enable controller (do we really need to reset ? -BenH) */
 	if (!pmif->mediabay) {
 		ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 1);
@@ -916,7 +936,8 @@
 
 static u8 pmac_ide_cable_detect(ide_hwif_t *hwif)
 {
-	pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)ide_get_hwifdata(hwif);
+	pmac_ide_hwif_t *pmif =
+		(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
 	struct device_node *np = pmif->node;
 	const char *cable = of_get_property(np, "cable-type", NULL);
 
@@ -936,7 +957,40 @@
 	return ATA_CBL_PATA40;
 }
 
+static void pmac_ide_init_dev(ide_drive_t *drive)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	pmac_ide_hwif_t *pmif =
+		(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
+
+	if (pmif->mediabay) {
+#ifdef CONFIG_PMAC_MEDIABAY
+		if (check_media_bay_by_base(pmif->regbase, MB_CD) == 0) {
+			drive->noprobe = 0;
+			return;
+		}
+#endif
+		drive->noprobe = 1;
+	}
+}
+
+static const struct ide_tp_ops pmac_tp_ops = {
+	.exec_command		= pmac_exec_command,
+	.read_status		= ide_read_status,
+	.read_altstatus		= ide_read_altstatus,
+	.read_sff_dma_status	= ide_read_sff_dma_status,
+
+	.set_irq		= pmac_set_irq,
+
+	.tf_load		= ide_tf_load,
+	.tf_read		= ide_tf_read,
+
+	.input_data		= ide_input_data,
+	.output_data		= ide_output_data,
+};
+
 static const struct ide_port_ops pmac_ide_ata6_port_ops = {
+	.init_dev		= pmac_ide_init_dev,
 	.set_pio_mode		= pmac_ide_set_pio_mode,
 	.set_dma_mode		= pmac_ide_set_dma_mode,
 	.selectproc		= pmac_ide_kauai_selectproc,
@@ -944,6 +998,7 @@
 };
 
 static const struct ide_port_ops pmac_ide_ata4_port_ops = {
+	.init_dev		= pmac_ide_init_dev,
 	.set_pio_mode		= pmac_ide_set_pio_mode,
 	.set_dma_mode		= pmac_ide_set_dma_mode,
 	.selectproc		= pmac_ide_selectproc,
@@ -951,6 +1006,7 @@
 };
 
 static const struct ide_port_ops pmac_ide_port_ops = {
+	.init_dev		= pmac_ide_init_dev,
 	.set_pio_mode		= pmac_ide_set_pio_mode,
 	.set_dma_mode		= pmac_ide_set_dma_mode,
 	.selectproc		= pmac_ide_selectproc,
@@ -959,12 +1015,14 @@
 static const struct ide_dma_ops pmac_dma_ops;
 
 static const struct ide_port_info pmac_port_info = {
+	.name			= DRV_NAME,
 	.init_dma		= pmac_ide_init_dma,
 	.chipset		= ide_pmac,
+	.tp_ops			= &pmac_tp_ops,
+	.port_ops		= &pmac_ide_port_ops,
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
 	.dma_ops		= &pmac_dma_ops,
 #endif
-	.port_ops		= &pmac_ide_port_ops,
 	.host_flags		= IDE_HFLAG_SET_PIO_MODE_KEEP_DMA |
 				  IDE_HFLAG_POST_SET_MODE |
 				  IDE_HFLAG_MMIO |
@@ -977,13 +1035,15 @@
  * Setup, register & probe an IDE channel driven by this driver, this is
  * called by one of the 2 probe functions (macio or PCI).
  */
-static int __devinit
-pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw)
+static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, hw_regs_t *hw)
 {
 	struct device_node *np = pmif->node;
 	const int *bidp;
-	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+	struct ide_host *host;
+	ide_hwif_t *hwif;
+	hw_regs_t *hws[] = { hw, NULL, NULL, NULL };
 	struct ide_port_info d = pmac_port_info;
+	int rc;
 
 	pmif->broken_dma = pmif->broken_dma_warn = 0;
 	if (of_device_is_compatible(np, "shasta-ata")) {
@@ -1054,31 +1114,16 @@
 		msleep(jiffies_to_msecs(IDE_WAKEUP_DELAY));
 	}
 
-	/* Setup MMIO ops */
-	default_hwif_mmiops(hwif);
-       	hwif->OUTBSYNC = pmac_outbsync;
+	printk(KERN_INFO DRV_NAME ": Found Apple %s controller (%s), "
+			 "bus ID %d%s, irq %d\n", model_name[pmif->kind],
+			 pmif->mdev ? "macio" : "PCI", pmif->aapl_bus_id,
+			 pmif->mediabay ? " (mediabay)" : "", hw->irq);
 
-	hwif->hwif_data = pmif;
-	ide_init_port_hw(hwif, hw);
+	rc = ide_host_add(&d, hws, &host);
+	if (rc)
+		return rc;
 
-	printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s, irq %d\n",
-	       hwif->index, model_name[pmif->kind], pmif->aapl_bus_id,
-	       pmif->mediabay ? " (mediabay)" : "", hwif->irq);
-
-	if (pmif->mediabay) {
-#ifdef CONFIG_PMAC_MEDIABAY
-		if (check_media_bay_by_base(pmif->regbase, MB_CD)) {
-#else
-		if (1) {
-#endif
-			hwif->drives[0].noprobe = 1;
-			hwif->drives[1].noprobe = 1;
-		}
-	}
-
-	idx[0] = hwif->index;
-
-	ide_device_add(idx, &d);
+	hwif = host->ports[0];
 
 	return 0;
 }
@@ -1101,7 +1146,6 @@
 {
 	void __iomem *base;
 	unsigned long regbase;
-	ide_hwif_t *hwif;
 	pmac_ide_hwif_t *pmif;
 	int irq, rc;
 	hw_regs_t hw;
@@ -1110,14 +1154,6 @@
 	if (pmif == NULL)
 		return -ENOMEM;
 
-	hwif = ide_find_port();
-	if (hwif == NULL) {
-		printk(KERN_ERR "ide-pmac: MacIO interface attach with no slot\n");
-		printk(KERN_ERR "          %s\n", mdev->ofdev.node->full_name);
-		rc = -ENODEV;
-		goto out_free_pmif;
-	}
-
 	if (macio_resource_count(mdev) == 0) {
 		printk(KERN_WARNING "ide-pmac: no address for %s\n",
 				    mdev->ofdev.node->full_name);
@@ -1164,7 +1200,7 @@
 	} else
 		pmif->dma_regs = NULL;
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
-	dev_set_drvdata(&mdev->ofdev.dev, hwif);
+	dev_set_drvdata(&mdev->ofdev.dev, pmif);
 
 	memset(&hw, 0, sizeof(hw));
 	pmac_ide_init_ports(&hw, pmif->regbase);
@@ -1172,7 +1208,7 @@
 	hw.dev = &mdev->bus->pdev->dev;
 	hw.parent = &mdev->ofdev.dev;
 
-	rc = pmac_ide_setup_device(pmif, hwif, &hw);
+	rc = pmac_ide_setup_device(pmif, &hw);
 	if (rc != 0) {
 		/* The inteface is released to the common IDE layer */
 		dev_set_drvdata(&mdev->ofdev.dev, NULL);
@@ -1195,12 +1231,13 @@
 static int
 pmac_ide_macio_suspend(struct macio_dev *mdev, pm_message_t mesg)
 {
-	ide_hwif_t	*hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
-	int		rc = 0;
+	pmac_ide_hwif_t *pmif =
+		(pmac_ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
+	int rc = 0;
 
 	if (mesg.event != mdev->ofdev.dev.power.power_state.event
 			&& (mesg.event & PM_EVENT_SLEEP)) {
-		rc = pmac_ide_do_suspend(hwif);
+		rc = pmac_ide_do_suspend(pmif);
 		if (rc == 0)
 			mdev->ofdev.dev.power.power_state = mesg;
 	}
@@ -1211,11 +1248,12 @@
 static int
 pmac_ide_macio_resume(struct macio_dev *mdev)
 {
-	ide_hwif_t	*hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
-	int		rc = 0;
-	
+	pmac_ide_hwif_t *pmif =
+		(pmac_ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
+	int rc = 0;
+
 	if (mdev->ofdev.dev.power.power_state.event != PM_EVENT_ON) {
-		rc = pmac_ide_do_resume(hwif);
+		rc = pmac_ide_do_resume(pmif);
 		if (rc == 0)
 			mdev->ofdev.dev.power.power_state = PMSG_ON;
 	}
@@ -1229,7 +1267,6 @@
 static int __devinit
 pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
 {
-	ide_hwif_t *hwif;
 	struct device_node *np;
 	pmac_ide_hwif_t *pmif;
 	void __iomem *base;
@@ -1247,14 +1284,6 @@
 	if (pmif == NULL)
 		return -ENOMEM;
 
-	hwif = ide_find_port();
-	if (hwif == NULL) {
-		printk(KERN_ERR "ide-pmac: PCI interface attach with no slot\n");
-		printk(KERN_ERR "          %s\n", np->full_name);
-		rc = -ENODEV;
-		goto out_free_pmif;
-	}
-
 	if (pci_enable_device(pdev)) {
 		printk(KERN_WARNING "ide-pmac: Can't enable PCI device for "
 				    "%s\n", np->full_name);
@@ -1284,14 +1313,14 @@
 	pmif->kauai_fcr = base;
 	pmif->irq = pdev->irq;
 
-	pci_set_drvdata(pdev, hwif);
+	pci_set_drvdata(pdev, pmif);
 
 	memset(&hw, 0, sizeof(hw));
 	pmac_ide_init_ports(&hw, pmif->regbase);
 	hw.irq = pdev->irq;
 	hw.dev = &pdev->dev;
 
-	rc = pmac_ide_setup_device(pmif, hwif, &hw);
+	rc = pmac_ide_setup_device(pmif, &hw);
 	if (rc != 0) {
 		/* The inteface is released to the common IDE layer */
 		pci_set_drvdata(pdev, NULL);
@@ -1310,12 +1339,12 @@
 static int
 pmac_ide_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
 {
-	ide_hwif_t	*hwif = (ide_hwif_t *)pci_get_drvdata(pdev);
-	int		rc = 0;
-	
+	pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)pci_get_drvdata(pdev);
+	int rc = 0;
+
 	if (mesg.event != pdev->dev.power.power_state.event
 			&& (mesg.event & PM_EVENT_SLEEP)) {
-		rc = pmac_ide_do_suspend(hwif);
+		rc = pmac_ide_do_suspend(pmif);
 		if (rc == 0)
 			pdev->dev.power.power_state = mesg;
 	}
@@ -1326,11 +1355,11 @@
 static int
 pmac_ide_pci_resume(struct pci_dev *pdev)
 {
-	ide_hwif_t	*hwif = (ide_hwif_t *)pci_get_drvdata(pdev);
-	int		rc = 0;
-	
+	pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)pci_get_drvdata(pdev);
+	int rc = 0;
+
 	if (pdev->dev.power.power_state.event != PM_EVENT_ON) {
-		rc = pmac_ide_do_resume(hwif);
+		rc = pmac_ide_do_resume(pmif);
 		if (rc == 0)
 			pdev->dev.power.power_state = PMSG_ON;
 	}
@@ -1421,10 +1450,11 @@
 static int
 pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq)
 {
+	ide_hwif_t *hwif = drive->hwif;
+	pmac_ide_hwif_t *pmif =
+		(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
 	struct dbdma_cmd *table;
 	int i, count = 0;
-	ide_hwif_t *hwif = HWIF(drive);
-	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
 	volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
 	struct scatterlist *sg;
 	int wr = (rq_data_dir(rq) == WRITE);
@@ -1520,7 +1550,8 @@
 pmac_ide_dma_setup(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = HWIF(drive);
-	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
+	pmac_ide_hwif_t *pmif =
+		(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
 	struct request *rq = HWGROUP(drive)->rq;
 	u8 unit = (drive->select.b.unit & 0x01);
 	u8 ata4;
@@ -1560,7 +1591,9 @@
 static void
 pmac_ide_dma_start(ide_drive_t *drive)
 {
-	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+	ide_hwif_t *hwif = drive->hwif;
+	pmac_ide_hwif_t *pmif =
+		(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
 	volatile struct dbdma_regs __iomem *dma;
 
 	dma = pmif->dma_regs;
@@ -1576,7 +1609,9 @@
 static int
 pmac_ide_dma_end (ide_drive_t *drive)
 {
-	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+	ide_hwif_t *hwif = drive->hwif;
+	pmac_ide_hwif_t *pmif =
+		(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
 	volatile struct dbdma_regs __iomem *dma;
 	u32 dstat;
 	
@@ -1604,7 +1639,9 @@
 static int
 pmac_ide_dma_test_irq (ide_drive_t *drive)
 {
-	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+	ide_hwif_t *hwif = drive->hwif;
+	pmac_ide_hwif_t *pmif =
+		(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
 	volatile struct dbdma_regs __iomem *dma;
 	unsigned long status, timeout;
 
@@ -1664,7 +1701,9 @@
 static void
 pmac_ide_dma_lost_irq (ide_drive_t *drive)
 {
-	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
+	ide_hwif_t *hwif = drive->hwif;
+	pmac_ide_hwif_t *pmif =
+		(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
 	volatile struct dbdma_regs __iomem *dma;
 	unsigned long status;
 
@@ -1694,7 +1733,8 @@
 static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif,
 				       const struct ide_port_info *d)
 {
-	pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
+	pmac_ide_hwif_t *pmif =
+		(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
 	struct pci_dev *dev = to_pci_dev(hwif->dev);
 
 	/* We won't need pci_dev if we switch to generic consistent
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index 65fc08b..b15cad5 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -73,15 +73,12 @@
  *	@d: IDE port info
  *
  *	Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space.
- *	Where a device has a partner that is already in DMA mode we check
- *	and enforce IDE simplex rules.
  */
 
 unsigned long ide_pci_dma_base(ide_hwif_t *hwif, const struct ide_port_info *d)
 {
 	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	unsigned long dma_base = 0;
-	u8 dma_stat = 0;
 
 	if (hwif->host_flags & IDE_HFLAG_MMIO)
 		return hwif->dma_base;
@@ -102,11 +99,19 @@
 	if (hwif->channel)
 		dma_base += 8;
 
-	if (d->host_flags & IDE_HFLAG_CS5520)
+	return dma_base;
+}
+EXPORT_SYMBOL_GPL(ide_pci_dma_base);
+
+int ide_pci_check_simplex(ide_hwif_t *hwif, const struct ide_port_info *d)
+{
+	u8 dma_stat;
+
+	if (d->host_flags & (IDE_HFLAG_MMIO | IDE_HFLAG_CS5520))
 		goto out;
 
 	if (d->host_flags & IDE_HFLAG_CLEAR_SIMPLEX) {
-		ide_pci_clear_simplex(dma_base, d->name);
+		ide_pci_clear_simplex(hwif->dma_base, d->name);
 		goto out;
 	}
 
@@ -120,15 +125,15 @@
 	 * we tune the drive then try to grab DMA ownership if we want to be
 	 * the DMA end.  This has to be become dynamic to handle hot-plug.
 	 */
-	dma_stat = hwif->INB(dma_base + 2);
+	dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
 	if ((dma_stat & 0x80) && hwif->mate && hwif->mate->dma_base) {
 		printk(KERN_INFO "%s: simplex device: DMA disabled\n", d->name);
-		dma_base = 0;
+		return -1;
 	}
 out:
-	return dma_base;
+	return 0;
 }
-EXPORT_SYMBOL_GPL(ide_pci_dma_base);
+EXPORT_SYMBOL_GPL(ide_pci_check_simplex);
 
 /*
  * Set up BM-DMA capability (PnP BIOS should have done this)
@@ -284,33 +289,31 @@
 }
 
 /**
- *	ide_hwif_configure	-	configure an IDE interface
+ *	ide_hw_configure	-	configure a hw_regs_t instance
  *	@dev: PCI device holding interface
  *	@d: IDE port info
  *	@port: port number
  *	@irq: PCI IRQ
+ *	@hw: hw_regs_t instance corresponding to this port
  *
  *	Perform the initial set up for the hardware interface structure. This
  *	is done per interface port rather than per PCI device. There may be
  *	more than one port per device.
  *
- *	Returns the new hardware interface structure, or NULL on a failure
+ *	Returns zero on success or an error code.
  */
 
-static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev,
-				      const struct ide_port_info *d,
-				      unsigned int port, int irq)
+static int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d,
+			    unsigned int port, int irq, hw_regs_t *hw)
 {
 	unsigned long ctl = 0, base = 0;
-	ide_hwif_t *hwif;
-	struct hw_regs_s hw;
 
 	if ((d->host_flags & IDE_HFLAG_ISA_PORTS) == 0) {
 		if (ide_pci_check_iomem(dev, d, 2 * port) ||
 		    ide_pci_check_iomem(dev, d, 2 * port + 1)) {
 			printk(KERN_ERR "%s: I/O baseregs (BIOS) are reported "
 					"as MEM for port %d!\n", d->name, port);
-			return NULL;
+			return -EINVAL;
 		}
 
 		ctl  = pci_resource_start(dev, 2*port+1);
@@ -324,22 +327,16 @@
 	if (!base || !ctl) {
 		printk(KERN_ERR "%s: bad PCI BARs for port %d, skipping\n",
 				d->name, port);
-		return NULL;
+		return -EINVAL;
 	}
 
-	hwif = ide_find_port_slot(d);
-	if (hwif == NULL)
-		return NULL;
+	memset(hw, 0, sizeof(*hw));
+	hw->irq = irq;
+	hw->dev = &dev->dev;
+	hw->chipset = d->chipset ? d->chipset : ide_pci;
+	ide_std_init_ports(hw, base, ctl | 2);
 
-	memset(&hw, 0, sizeof(hw));
-	hw.irq = irq;
-	hw.dev = &dev->dev;
-	hw.chipset = d->chipset ? d->chipset : ide_pci;
-	ide_std_init_ports(&hw, base, ctl | 2);
-
-	ide_init_port_hw(hwif, &hw);
-
-	return hwif;
+	return 0;
 }
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
@@ -362,7 +359,15 @@
 	     (dev->class & 0x80))) {
 		unsigned long base = ide_pci_dma_base(hwif, d);
 
-		if (base == 0 || ide_pci_set_master(dev, d->name) < 0)
+		if (base == 0)
+			return -1;
+
+		hwif->dma_base = base;
+
+		if (ide_pci_check_simplex(hwif, d) < 0)
+			return -1;
+
+		if (ide_pci_set_master(dev, d->name) < 0)
 			return -1;
 
 		if (hwif->host_flags & IDE_HFLAG_MMIO)
@@ -376,7 +381,7 @@
 		if (ide_allocate_dma_engine(hwif))
 			return -1;
 
-		ide_setup_dma(hwif, base);
+		hwif->dma_ops = &sff_dma_ops;
 	}
 
 	return 0;
@@ -429,7 +434,8 @@
  *	@dev: PCI device
  *	@d: IDE port info
  *	@pciirq: IRQ line
- *	@idx: ATA index table to update
+ *	@hw: hw_regs_t instances corresponding to this PCI IDE device
+ *	@hws: hw_regs_t pointers table to update
  *
  *	Scan the interfaces attached to this device and do any
  *	necessary per port setup. Attach the devices and ask the
@@ -440,10 +446,10 @@
  *	where the chipset setup is not the default PCI IDE one.
  */
 
-void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int pciirq, u8 *idx)
+void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d,
+			 int pciirq, hw_regs_t *hw, hw_regs_t **hws)
 {
 	int channels = (d->host_flags & IDE_HFLAG_SINGLE) ? 1 : 2, port;
-	ide_hwif_t *hwif;
 	u8 tmp;
 
 	/*
@@ -459,11 +465,10 @@
 			continue;	/* port not enabled */
 		}
 
-		hwif = ide_hwif_configure(dev, d, port, pciirq);
-		if (hwif == NULL)
+		if (ide_hw_configure(dev, d, port, pciirq, hw + port))
 			continue;
 
-		*(idx + port) = hwif->index;
+		*(hws + port) = hw + port;
 	}
 }
 EXPORT_SYMBOL_GPL(ide_pci_setup_ports);
@@ -480,7 +485,7 @@
  */
 static int do_ide_setup_pci_device(struct pci_dev *dev,
 				   const struct ide_port_info *d,
-				   u8 *idx, u8 noisy)
+				   u8 noisy)
 {
 	int tried_config = 0;
 	int pciirq, ret;
@@ -529,22 +534,24 @@
 				d->name, pciirq);
 	}
 
-	/* FIXME: silent failure can happen */
-
-	ide_pci_setup_ports(dev, d, pciirq, idx);
+	ret = pciirq;
 out:
 	return ret;
 }
 
 int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d)
 {
-	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+	hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL };
 	int ret;
 
-	ret = do_ide_setup_pci_device(dev, d, &idx[0], 1);
+	ret = do_ide_setup_pci_device(dev, d, 1);
 
-	if (ret >= 0)
-		ide_device_add(idx, d);
+	if (ret >= 0) {
+		/* FIXME: silent failure can happen */
+		ide_pci_setup_ports(dev, d, ret, &hw[0], &hws[0]);
+
+		ret = ide_host_add(d, hws, NULL);
+	}
 
 	return ret;
 }
@@ -555,19 +562,23 @@
 {
 	struct pci_dev *pdev[] = { dev1, dev2 };
 	int ret, i;
-	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+	hw_regs_t hw[4], *hws[] = { NULL, NULL, NULL, NULL };
 
 	for (i = 0; i < 2; i++) {
-		ret = do_ide_setup_pci_device(pdev[i], d, &idx[i*2], !i);
+		ret = do_ide_setup_pci_device(pdev[i], d, !i);
+
 		/*
 		 * FIXME: Mom, mom, they stole me the helper function to undo
 		 * do_ide_setup_pci_device() on the first device!
 		 */
 		if (ret < 0)
 			goto out;
+
+		/* FIXME: silent failure can happen */
+		ide_pci_setup_ports(pdev[i], d, ret, &hw[i*2], &hws[i*2]);
 	}
 
-	ide_device_add(idx, d);
+	ret = ide_host_add(d, hws, NULL);
 out:
 	return ret;
 }
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index 9d19aec..b6eb2cf 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -2296,9 +2296,10 @@
 
 	ohci = (struct ti_ohci *)host->hostdata;
 
-	device_create(hpsb_protocol_class, NULL, MKDEV(
-		IEEE1394_MAJOR,	IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
-		"dv1394-%d", id);
+	device_create_drvdata(hpsb_protocol_class, NULL,
+			      MKDEV(IEEE1394_MAJOR,
+				    IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)), NULL,
+			      "dv1394-%d", id);
 
 	dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
 	dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 05710c7..994a21e 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -754,7 +754,8 @@
 	 */
 	mutex_lock(&nodemgr_serialize_remove_uds);
 	for (;;) {
-		dev = class_find_device(&nodemgr_ud_class, ne, __match_ne);
+		dev = class_find_device(&nodemgr_ud_class, NULL, ne,
+					__match_ne);
 		if (!dev)
 			break;
 		ud = container_of(dev, struct unit_directory, unit_dev);
@@ -901,7 +902,8 @@
 	struct device *dev;
 	struct node_entry *ne;
 
-	dev = class_find_device(&nodemgr_ne_class, &guid, __match_ne_guid);
+	dev = class_find_device(&nodemgr_ne_class, NULL, &guid,
+				__match_ne_guid);
 	if (!dev)
 		return NULL;
 	ne = container_of(dev, struct node_entry, node_dev);
@@ -940,7 +942,8 @@
 	param.host = host;
 	param.nodeid = nodeid;
 
-	dev = class_find_device(&nodemgr_ne_class, &param, __match_ne_nodeid);
+	dev = class_find_device(&nodemgr_ne_class, NULL, &param,
+				__match_ne_nodeid);
 	if (!dev)
 		return NULL;
 	ne = container_of(dev, struct node_entry, node_dev);
@@ -1453,7 +1456,8 @@
 	ne->in_limbo = 1;
 	WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo));
 
-	class_for_each_device(&nodemgr_ud_class, ne, __nodemgr_driver_suspend);
+	class_for_each_device(&nodemgr_ud_class, NULL, ne,
+			      __nodemgr_driver_suspend);
 }
 
 
@@ -1462,7 +1466,8 @@
 	ne->in_limbo = 0;
 	device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
 
-	class_for_each_device(&nodemgr_ud_class, ne, __nodemgr_driver_resume);
+	class_for_each_device(&nodemgr_ud_class, NULL, ne,
+			      __nodemgr_driver_resume);
 	HPSB_DEBUG("Node resumed: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
 		   NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
 }
@@ -1498,7 +1503,8 @@
 
 static void nodemgr_update_pdrv(struct node_entry *ne)
 {
-	class_for_each_device(&nodemgr_ud_class, ne, __nodemgr_update_pdrv);
+	class_for_each_device(&nodemgr_ud_class, NULL, ne,
+			      __nodemgr_update_pdrv);
 }
 
 
@@ -1591,7 +1597,8 @@
 	 * while probes are time-consuming. (Well, those probes need some
 	 * improvement...) */
 
-	class_for_each_device(&nodemgr_ne_class, &param, __nodemgr_node_probe);
+	class_for_each_device(&nodemgr_ne_class, NULL, &param,
+			      __nodemgr_node_probe);
 
 	/* If we had a bus reset while we were scanning the bus, it is
 	 * possible that we did not probe all nodes.  In that case, we
@@ -1826,7 +1833,7 @@
 
 	hip.cb = cb;
 	hip.data = data;
-	error = class_for_each_device(&hpsb_host_class, &hip,
+	error = class_for_each_device(&hpsb_host_class, NULL, &hip,
 				      __nodemgr_for_each_host);
 
 	return error;
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index 96f2847..6fa9e4a 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -3010,10 +3010,10 @@
 	hpsb_register_highlevel(&raw1394_highlevel);
 
 	if (IS_ERR
-	    (device_create(
+	    (device_create_drvdata(
 	      hpsb_protocol_class, NULL,
 	      MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
-	      RAW1394_DEVICE_NAME))) {
+	      NULL, RAW1394_DEVICE_NAME))) {
 		ret = -EFAULT;
 		goto out_unreg;
 	}
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 069b9f6..25db6e6 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -1341,9 +1341,9 @@
 	hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
 
 	minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
-	device_create(hpsb_protocol_class, NULL,
-		      MKDEV(IEEE1394_MAJOR, minor),
-		      "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
+	device_create_drvdata(hpsb_protocol_class, NULL,
+			      MKDEV(IEEE1394_MAJOR, minor), NULL,
+			      "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
 }
 
 
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 55738ee..922d35f 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -44,6 +44,7 @@
 #include <linux/spinlock.h>
 #include <linux/sysfs.h>
 #include <linux/workqueue.h>
+#include <linux/kdev_t.h>
 
 #include <rdma/ib_cache.h>
 #include <rdma/ib_cm.h>
@@ -162,8 +163,8 @@
 
 struct cm_device {
 	struct list_head list;
-	struct ib_device *device;
-	struct kobject dev_obj;
+	struct ib_device *ib_device;
+	struct device *device;
 	u8 ack_delay;
 	struct cm_port *port[0];
 };
@@ -339,7 +340,7 @@
 {
 	av->port = port;
 	av->pkey_index = wc->pkey_index;
-	ib_init_ah_from_wc(port->cm_dev->device, port->port_num, wc,
+	ib_init_ah_from_wc(port->cm_dev->ib_device, port->port_num, wc,
 			   grh, &av->ah_attr);
 }
 
@@ -353,7 +354,7 @@
 
 	read_lock_irqsave(&cm.device_lock, flags);
 	list_for_each_entry(cm_dev, &cm.device_list, list) {
-		if (!ib_find_cached_gid(cm_dev->device, &path->sgid,
+		if (!ib_find_cached_gid(cm_dev->ib_device, &path->sgid,
 					&p, NULL)) {
 			port = cm_dev->port[p-1];
 			break;
@@ -364,13 +365,13 @@
 	if (!port)
 		return -EINVAL;
 
-	ret = ib_find_cached_pkey(cm_dev->device, port->port_num,
+	ret = ib_find_cached_pkey(cm_dev->ib_device, port->port_num,
 				  be16_to_cpu(path->pkey), &av->pkey_index);
 	if (ret)
 		return ret;
 
 	av->port = port;
-	ib_init_ah_from_path(cm_dev->device, port->port_num, path,
+	ib_init_ah_from_path(cm_dev->ib_device, port->port_num, path,
 			     &av->ah_attr);
 	av->timeout = path->packet_life_time + 1;
 	return 0;
@@ -1515,7 +1516,7 @@
 
 	req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
 
-	cm_id = ib_create_cm_id(work->port->cm_dev->device, NULL, NULL);
+	cm_id = ib_create_cm_id(work->port->cm_dev->ib_device, NULL, NULL);
 	if (IS_ERR(cm_id))
 		return PTR_ERR(cm_id);
 
@@ -1550,7 +1551,7 @@
 	cm_format_paths_from_req(req_msg, &work->path[0], &work->path[1]);
 	ret = cm_init_av_by_path(&work->path[0], &cm_id_priv->av);
 	if (ret) {
-		ib_get_cached_gid(work->port->cm_dev->device,
+		ib_get_cached_gid(work->port->cm_dev->ib_device,
 				  work->port->port_num, 0, &work->path[0].sgid);
 		ib_send_cm_rej(cm_id, IB_CM_REJ_INVALID_GID,
 			       &work->path[0].sgid, sizeof work->path[0].sgid,
@@ -2950,7 +2951,7 @@
 	struct cm_sidr_req_msg *sidr_req_msg;
 	struct ib_wc *wc;
 
-	cm_id = ib_create_cm_id(work->port->cm_dev->device, NULL, NULL);
+	cm_id = ib_create_cm_id(work->port->cm_dev->ib_device, NULL, NULL);
 	if (IS_ERR(cm_id))
 		return PTR_ERR(cm_id);
 	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
@@ -3578,7 +3579,7 @@
 {
 	struct ib_device_attr attr;
 
-	if (ib_query_device(cm_dev->device, &attr))
+	if (ib_query_device(cm_dev->ib_device, &attr))
 		cm_dev->ack_delay = 0; /* acks will rely on packet life time */
 	else
 		cm_dev->ack_delay = attr.local_ca_ack_delay;
@@ -3618,18 +3619,6 @@
 	.release = cm_release_port_obj
 };
 
-static void cm_release_dev_obj(struct kobject *obj)
-{
-	struct cm_device *cm_dev;
-
-	cm_dev = container_of(obj, struct cm_device, dev_obj);
-	kfree(cm_dev);
-}
-
-static struct kobj_type cm_dev_obj_type = {
-	.release = cm_release_dev_obj
-};
-
 struct class cm_class = {
 	.name    = "infiniband_cm",
 };
@@ -3640,7 +3629,7 @@
 	int i, ret;
 
 	ret = kobject_init_and_add(&port->port_obj, &cm_port_obj_type,
-				   &port->cm_dev->dev_obj,
+				   &port->cm_dev->device->kobj,
 				   "%d", port->port_num);
 	if (ret) {
 		kfree(port);
@@ -3676,7 +3665,7 @@
 	kobject_put(&port->port_obj);
 }
 
-static void cm_add_one(struct ib_device *device)
+static void cm_add_one(struct ib_device *ib_device)
 {
 	struct cm_device *cm_dev;
 	struct cm_port *port;
@@ -3691,26 +3680,27 @@
 	int ret;
 	u8 i;
 
-	if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
+	if (rdma_node_get_transport(ib_device->node_type) != RDMA_TRANSPORT_IB)
 		return;
 
 	cm_dev = kzalloc(sizeof(*cm_dev) + sizeof(*port) *
-			 device->phys_port_cnt, GFP_KERNEL);
+			 ib_device->phys_port_cnt, GFP_KERNEL);
 	if (!cm_dev)
 		return;
 
-	cm_dev->device = device;
+	cm_dev->ib_device = ib_device;
 	cm_get_ack_delay(cm_dev);
 
-	ret = kobject_init_and_add(&cm_dev->dev_obj, &cm_dev_obj_type,
-				   &cm_class.subsys.kobj, "%s", device->name);
-	if (ret) {
+	cm_dev->device = device_create_drvdata(&cm_class, &ib_device->dev,
+					       MKDEV(0, 0), NULL,
+					       "%s", ib_device->name);
+	if (!cm_dev->device) {
 		kfree(cm_dev);
 		return;
 	}
 
 	set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask);
-	for (i = 1; i <= device->phys_port_cnt; i++) {
+	for (i = 1; i <= ib_device->phys_port_cnt; i++) {
 		port = kzalloc(sizeof *port, GFP_KERNEL);
 		if (!port)
 			goto error1;
@@ -3723,7 +3713,7 @@
 		if (ret)
 			goto error1;
 
-		port->mad_agent = ib_register_mad_agent(device, i,
+		port->mad_agent = ib_register_mad_agent(ib_device, i,
 							IB_QPT_GSI,
 							&reg_req,
 							0,
@@ -3733,11 +3723,11 @@
 		if (IS_ERR(port->mad_agent))
 			goto error2;
 
-		ret = ib_modify_port(device, i, 0, &port_modify);
+		ret = ib_modify_port(ib_device, i, 0, &port_modify);
 		if (ret)
 			goto error3;
 	}
-	ib_set_client_data(device, &cm_client, cm_dev);
+	ib_set_client_data(ib_device, &cm_client, cm_dev);
 
 	write_lock_irqsave(&cm.device_lock, flags);
 	list_add_tail(&cm_dev->list, &cm.device_list);
@@ -3753,14 +3743,14 @@
 	port_modify.clr_port_cap_mask = IB_PORT_CM_SUP;
 	while (--i) {
 		port = cm_dev->port[i-1];
-		ib_modify_port(device, port->port_num, 0, &port_modify);
+		ib_modify_port(ib_device, port->port_num, 0, &port_modify);
 		ib_unregister_mad_agent(port->mad_agent);
 		cm_remove_port_fs(port);
 	}
-	kobject_put(&cm_dev->dev_obj);
+	device_unregister(cm_dev->device);
 }
 
-static void cm_remove_one(struct ib_device *device)
+static void cm_remove_one(struct ib_device *ib_device)
 {
 	struct cm_device *cm_dev;
 	struct cm_port *port;
@@ -3770,7 +3760,7 @@
 	unsigned long flags;
 	int i;
 
-	cm_dev = ib_get_client_data(device, &cm_client);
+	cm_dev = ib_get_client_data(ib_device, &cm_client);
 	if (!cm_dev)
 		return;
 
@@ -3778,14 +3768,14 @@
 	list_del(&cm_dev->list);
 	write_unlock_irqrestore(&cm.device_lock, flags);
 
-	for (i = 1; i <= device->phys_port_cnt; i++) {
+	for (i = 1; i <= ib_device->phys_port_cnt; i++) {
 		port = cm_dev->port[i-1];
-		ib_modify_port(device, port->port_num, 0, &port_modify);
+		ib_modify_port(ib_device, port->port_num, 0, &port_modify);
 		ib_unregister_mad_agent(port->mad_agent);
 		flush_workqueue(cm.wq);
 		cm_remove_port_fs(port);
 	}
-	kobject_put(&cm_dev->dev_obj);
+	device_unregister(cm_dev->device);
 }
 
 static int __init ib_cm_init(void)
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
index 35f301c..56c0eda 100644
--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -2455,7 +2455,7 @@
 		goto err_cdev;
 	}
 
-	device = device_create(ipath_class, NULL, dev, name);
+	device = device_create_drvdata(ipath_class, NULL, dev, NULL, name);
 
 	if (IS_ERR(device)) {
 		ret = PTR_ERR(device);
diff --git a/drivers/input/evbug.c b/drivers/input/evbug.c
index c21f2f1..0353601 100644
--- a/drivers/input/evbug.c
+++ b/drivers/input/evbug.c
@@ -1,6 +1,4 @@
 /*
- * $Id: evbug.c,v 1.10 2001/09/25 10:12:07 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  */
 
@@ -41,7 +39,7 @@
 static void evbug_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
 {
 	printk(KERN_DEBUG "evbug.c: Event. Dev: %s, Type: %d, Code: %d, Value: %d\n",
-		handle->dev->phys, type, code, value);
+		handle->dev->dev.bus_id, type, code, value);
 }
 
 static int evbug_connect(struct input_handler *handler, struct input_dev *dev,
@@ -66,7 +64,10 @@
 	if (error)
 		goto err_unregister_handle;
 
-	printk(KERN_DEBUG "evbug.c: Connected device: \"%s\", %s\n", dev->name, dev->phys);
+	printk(KERN_DEBUG "evbug.c: Connected device: %s (%s at %s)\n",
+		dev->dev.bus_id,
+		dev->name ?: "unknown",
+		dev->phys ?: "unknown");
 
 	return 0;
 
@@ -79,7 +80,8 @@
 
 static void evbug_disconnect(struct input_handle *handle)
 {
-	printk(KERN_DEBUG "evbug.c: Disconnected device: %s\n", handle->dev->phys);
+	printk(KERN_DEBUG "evbug.c: Disconnected device: %s\n",
+		handle->dev->dev.bus_id);
 
 	input_close_device(handle);
 	input_unregister_handle(handle);
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index b32984b..2d65411 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -300,6 +300,35 @@
 	__s32 value;
 };
 
+struct ff_periodic_effect_compat {
+	__u16 waveform;
+	__u16 period;
+	__s16 magnitude;
+	__s16 offset;
+	__u16 phase;
+
+	struct ff_envelope envelope;
+
+	__u32 custom_len;
+	compat_uptr_t custom_data;
+};
+
+struct ff_effect_compat {
+	__u16 type;
+	__s16 id;
+	__u16 direction;
+	struct ff_trigger trigger;
+	struct ff_replay replay;
+
+	union {
+		struct ff_constant_effect constant;
+		struct ff_ramp_effect ramp;
+		struct ff_periodic_effect_compat periodic;
+		struct ff_condition_effect condition[2]; /* One for each axis */
+		struct ff_rumble_effect rumble;
+	} u;
+};
+
 /* Note to the author of this code: did it ever occur to
    you why the ifdefs are needed? Think about it again. -AK */
 #ifdef CONFIG_X86_64
@@ -368,6 +397,42 @@
 	return 0;
 }
 
+static int evdev_ff_effect_from_user(const char __user *buffer, size_t size,
+				     struct ff_effect *effect)
+{
+	if (COMPAT_TEST) {
+		struct ff_effect_compat *compat_effect;
+
+		if (size != sizeof(struct ff_effect_compat))
+			return -EINVAL;
+
+		/*
+		 * It so happens that the pointer which needs to be changed
+		 * is the last field in the structure, so we can copy the
+		 * whole thing and replace just the pointer.
+		 */
+
+		compat_effect = (struct ff_effect_compat *)effect;
+
+		if (copy_from_user(compat_effect, buffer,
+				   sizeof(struct ff_effect_compat)))
+			return -EFAULT;
+
+		if (compat_effect->type == FF_PERIODIC &&
+		    compat_effect->u.periodic.waveform == FF_CUSTOM)
+			effect->u.periodic.custom_data =
+				compat_ptr(compat_effect->u.periodic.custom_data);
+	} else {
+		if (size != sizeof(struct ff_effect))
+			return -EINVAL;
+
+		if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
 #else
 
 static inline size_t evdev_event_size(void)
@@ -393,6 +458,18 @@
 	return 0;
 }
 
+static int evdev_ff_effect_from_user(const char __user *buffer, size_t size,
+				     struct ff_effect *effect)
+{
+	if (size != sizeof(struct ff_effect))
+		return -EINVAL;
+
+	if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
+		return -EFAULT;
+
+	return 0;
+}
+
 #endif /* CONFIG_COMPAT */
 
 static ssize_t evdev_write(struct file *file, const char __user *buffer,
@@ -633,17 +710,6 @@
 
 		return input_set_keycode(dev, t, v);
 
-	case EVIOCSFF:
-		if (copy_from_user(&effect, p, sizeof(effect)))
-			return -EFAULT;
-
-		error = input_ff_upload(dev, &effect, file);
-
-		if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
-			return -EFAULT;
-
-		return error;
-
 	case EVIOCRMFF:
 		return input_ff_erase(dev, (int)(unsigned long) p, file);
 
@@ -733,6 +799,19 @@
 
 		if (_IOC_DIR(cmd) == _IOC_WRITE) {
 
+			if (_IOC_NR(cmd) == _IOC_NR(EVIOCSFF)) {
+
+				if (evdev_ff_effect_from_user(p, _IOC_SIZE(cmd), &effect))
+					return -EFAULT;
+
+				error = input_ff_upload(dev, &effect, file);
+
+				if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
+					return -EFAULT;
+
+				return error;
+			}
+
 			if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
 
 				t = _IOC_NR(cmd) & ABS_MAX;
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c
index d226d93..6790e97 100644
--- a/drivers/input/ff-memless.c
+++ b/drivers/input/ff-memless.c
@@ -247,9 +247,9 @@
 		 * in s8, this should be changed to something more generic
 		 */
 		effect->u.ramp.start_level =
-			max(min(effect->u.ramp.start_level + x, 0x7f), -0x80);
+			clamp_val(effect->u.ramp.start_level + x, -0x80, 0x7f);
 		effect->u.ramp.end_level =
-			max(min(effect->u.ramp.end_level + y, 0x7f), -0x80);
+			clamp_val(effect->u.ramp.end_level + y, -0x80, 0x7f);
 		break;
 
 	case FF_RUMBLE:
diff --git a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c
index 9793ac3..b04930f 100644
--- a/drivers/input/gameport/emu10k1-gp.c
+++ b/drivers/input/gameport/emu10k1-gp.c
@@ -1,6 +1,4 @@
 /*
- * $Id: emu10k1-gp.c,v 1.8 2002/01/22 20:40:46 vojtech Exp $
- *
  *  Copyright (c) 2001 Vojtech Pavlik
  */
 
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index c5600ac..078e4ee 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -36,7 +36,6 @@
 EXPORT_SYMBOL(gameport_unregister_driver);
 EXPORT_SYMBOL(gameport_open);
 EXPORT_SYMBOL(gameport_close);
-EXPORT_SYMBOL(gameport_rescan);
 EXPORT_SYMBOL(gameport_set_phys);
 EXPORT_SYMBOL(gameport_start_polling);
 EXPORT_SYMBOL(gameport_stop_polling);
@@ -230,8 +229,6 @@
  */
 
 enum gameport_event_type {
-	GAMEPORT_RESCAN,
-	GAMEPORT_RECONNECT,
 	GAMEPORT_REGISTER_PORT,
 	GAMEPORT_REGISTER_DRIVER,
 };
@@ -365,15 +362,6 @@
 				gameport_add_port(event->object);
 				break;
 
-			case GAMEPORT_RECONNECT:
-				gameport_reconnect_port(event->object);
-				break;
-
-			case GAMEPORT_RESCAN:
-				gameport_disconnect_port(event->object);
-				gameport_find_driver(event->object);
-				break;
-
 			case GAMEPORT_REGISTER_DRIVER:
 				gameport_add_driver(event->object);
 				break;
@@ -651,16 +639,6 @@
 	device_release_driver(&gameport->dev);
 }
 
-void gameport_rescan(struct gameport *gameport)
-{
-	gameport_queue_event(gameport, NULL, GAMEPORT_RESCAN);
-}
-
-void gameport_reconnect(struct gameport *gameport)
-{
-	gameport_queue_event(gameport, NULL, GAMEPORT_RECONNECT);
-}
-
 /*
  * Submits register request to kgameportd for subsequent execution.
  * Note that port registration is always asynchronous.
diff --git a/drivers/input/gameport/lightning.c b/drivers/input/gameport/lightning.c
index 6b4d456..06ad36e 100644
--- a/drivers/input/gameport/lightning.c
+++ b/drivers/input/gameport/lightning.c
@@ -1,6 +1,4 @@
 /*
- * $Id: lightning.c,v 1.20 2002/01/22 20:41:31 vojtech Exp $
- *
  *  Copyright (c) 1998-2001 Vojtech Pavlik
  */
 
diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c
index 7b7a546..2b282cd 100644
--- a/drivers/input/gameport/ns558.c
+++ b/drivers/input/gameport/ns558.c
@@ -1,6 +1,4 @@
 /*
- * $Id: ns558.c,v 1.43 2002/01/24 19:23:21 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  *  Copyright (c) 1999 Brian Gerst
  */
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 408df0b..c13ced3 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -242,7 +242,7 @@
 		break;
 	}
 
-	if (type != EV_SYN)
+	if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
 		dev->sync = 0;
 
 	if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c
index 52ba16f..92498d4 100644
--- a/drivers/input/joystick/a3d.c
+++ b/drivers/input/joystick/a3d.c
@@ -1,6 +1,4 @@
 /*
- * $Id: a3d.c,v 1.21 2002/01/22 20:11:50 vojtech Exp $
- *
  *  Copyright (c) 1998-2001 Vojtech Pavlik
  */
 
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c
index deb9f82..05022f0 100644
--- a/drivers/input/joystick/amijoy.c
+++ b/drivers/input/joystick/amijoy.c
@@ -1,6 +1,4 @@
 /*
- * $Id: amijoy.c,v 1.13 2002/01/22 20:26:32 vojtech Exp $
- *
  *  Copyright (c) 1998-2001 Vojtech Pavlik
  */
 
diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c
index 55646a6..639b975 100644
--- a/drivers/input/joystick/cobra.c
+++ b/drivers/input/joystick/cobra.c
@@ -1,6 +1,4 @@
 /*
- * $Id: cobra.c,v 1.19 2002/01/22 20:26:52 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  */
 
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
index 960e501..5239594 100644
--- a/drivers/input/joystick/db9.c
+++ b/drivers/input/joystick/db9.c
@@ -1,6 +1,4 @@
 /*
- * $Id: db9.c,v 1.13 2002/04/07 20:13:37 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  *
  *  Based on the work of:
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c
index 1f6302c..cb6eef1 100644
--- a/drivers/input/joystick/gf2k.c
+++ b/drivers/input/joystick/gf2k.c
@@ -1,6 +1,4 @@
 /*
- * $Id: gf2k.c,v 1.19 2002/01/22 20:27:43 vojtech Exp $
- *
  *  Copyright (c) 1998-2001 Vojtech Pavlik
  */
 
diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c
index fd3853a..684e07c 100644
--- a/drivers/input/joystick/grip.c
+++ b/drivers/input/joystick/grip.c
@@ -1,6 +1,4 @@
 /*
- * $Id: grip.c,v 1.21 2002/01/22 20:27:57 vojtech Exp $
- *
  *  Copyright (c) 1998-2001 Vojtech Pavlik
  */
 
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
index c57e21d..8279481 100644
--- a/drivers/input/joystick/grip_mp.c
+++ b/drivers/input/joystick/grip_mp.c
@@ -1,6 +1,4 @@
 /*
- * $Id: grip_mp.c,v 1.9 2002/07/20 19:28:45 bonnland Exp $
- *
  *  Driver for the Gravis Grip Multiport, a gamepad "hub" that
  *  connects up to four 9-pin digital gamepads/joysticks.
  *  Driver tested on SMP and UP kernel versions 2.4.18-4 and 2.4.18-5.
diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c
index aa6bfb3..25ec3fa 100644
--- a/drivers/input/joystick/guillemot.c
+++ b/drivers/input/joystick/guillemot.c
@@ -1,6 +1,4 @@
 /*
- * $Id: guillemot.c,v 1.10 2002/01/22 20:28:12 vojtech Exp $
- *
  *  Copyright (c) 2001 Vojtech Pavlik
  */
 
diff --git a/drivers/input/joystick/iforce/iforce-ff.c b/drivers/input/joystick/iforce/iforce-ff.c
index f2a4381..7839b7b 100644
--- a/drivers/input/joystick/iforce/iforce-ff.c
+++ b/drivers/input/joystick/iforce/iforce-ff.c
@@ -1,6 +1,4 @@
 /*
- * $Id: iforce-ff.c,v 1.9 2002/02/02 19:28:35 jdeneux Exp $
- *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
  *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index a2517fa..61ee6e3 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -1,6 +1,4 @@
 /*
- * $Id: iforce-main.c,v 1.19 2002/07/07 10:22:50 jdeneux Exp $
- *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
  *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c
index 45c4939..015b50a 100644
--- a/drivers/input/joystick/iforce/iforce-packets.c
+++ b/drivers/input/joystick/iforce/iforce-packets.c
@@ -1,6 +1,4 @@
 /*
- * $Id: iforce-packets.c,v 1.16 2002/07/07 10:22:50 jdeneux Exp $
- *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
  *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c
index 7b4bc19..46d5041 100644
--- a/drivers/input/joystick/iforce/iforce-serio.c
+++ b/drivers/input/joystick/iforce/iforce-serio.c
@@ -1,6 +1,4 @@
 /*
- * $Id: iforce-serio.c,v 1.4 2002/01/28 22:45:00 jdeneux Exp $
- *
  *  Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz>
  *  Copyright (c) 2001, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index 7fb3cf8..851cc408 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -1,6 +1,4 @@
  /*
- * $Id: iforce-usb.c,v 1.16 2002/06/09 11:08:04 jdeneux Exp $
- *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
  *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
@@ -89,10 +87,10 @@
 	case -ESHUTDOWN:
 		/* this urb is terminated, clean up */
 		dbg("%s - urb shutting down with status: %d",
-		    __FUNCTION__, urb->status);
+		    __func__, urb->status);
 		return;
 	default:
-		dbg("%s - urb has status of: %d", __FUNCTION__, urb->status);
+		dbg("%s - urb has status of: %d", __func__, urb->status);
 		goto exit;
 	}
 
@@ -103,7 +101,7 @@
 	status = usb_submit_urb (urb, GFP_ATOMIC);
 	if (status)
 		err ("%s - usb_submit_urb failed with result %d",
-		     __FUNCTION__, status);
+		     __func__, status);
 }
 
 static void iforce_usb_out(struct urb *urb)
diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h
index a964a7c..f2d91f40 100644
--- a/drivers/input/joystick/iforce/iforce.h
+++ b/drivers/input/joystick/iforce/iforce.h
@@ -1,6 +1,4 @@
 /*
- * $Id: iforce.h,v 1.13 2002/07/07 10:22:50 jdeneux Exp $
- *
  *  Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
  *  Copyright (c) 2001-2002, 2007 Johann Deneux <johann.deneux@gmail.com>
  *
diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c
index bc8ea95..8c3290b 100644
--- a/drivers/input/joystick/interact.c
+++ b/drivers/input/joystick/interact.c
@@ -1,6 +1,4 @@
 /*
- * $Id: interact.c,v 1.16 2002/01/22 20:28:25 vojtech Exp $
- *
  *  Copyright (c) 2001 Vojtech Pavlik
  *
  *  Based on the work of:
diff --git a/drivers/input/joystick/joydump.c b/drivers/input/joystick/joydump.c
index 88ec5a91..2a1b82c 100644
--- a/drivers/input/joystick/joydump.c
+++ b/drivers/input/joystick/joydump.c
@@ -1,6 +1,4 @@
 /*
- * $Id: joydump.c,v 1.1 2002/01/23 06:56:16 jsimmons Exp $
- *
  *  Copyright (c) 1996-2001 Vojtech Pavlik
  */
 
diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c
index 54e6769..40e4078 100644
--- a/drivers/input/joystick/magellan.c
+++ b/drivers/input/joystick/magellan.c
@@ -1,6 +1,4 @@
 /*
- * $Id: magellan.c,v 1.16 2002/01/22 20:28:39 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  */
 
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
index d4087fd..0cd9b29 100644
--- a/drivers/input/joystick/spaceball.c
+++ b/drivers/input/joystick/spaceball.c
@@ -1,6 +1,4 @@
 /*
- * $Id: spaceball.c,v 1.17 2002/01/22 20:29:03 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  *
  *  Based on the work of:
diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c
index f7ce400..a694bf8 100644
--- a/drivers/input/joystick/spaceorb.c
+++ b/drivers/input/joystick/spaceorb.c
@@ -1,6 +1,4 @@
 /*
- * $Id: spaceorb.c,v 1.15 2002/01/22 20:29:19 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  *
  *  Based on the work of:
diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c
index baa10b2..e0db9f5 100644
--- a/drivers/input/joystick/stinger.c
+++ b/drivers/input/joystick/stinger.c
@@ -1,6 +1,4 @@
 /*
- * $Id: stinger.c,v 1.10 2002/01/22 20:29:31 vojtech Exp $
- *
  *  Copyright (c) 2000-2001 Vojtech Pavlik
  *  Copyright (c) 2000 Mark Fletcher
  */
diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c
index 0feeb8a..60c37bcb 100644
--- a/drivers/input/joystick/tmdc.c
+++ b/drivers/input/joystick/tmdc.c
@@ -1,6 +1,4 @@
 /*
- * $Id: tmdc.c,v 1.31 2002/01/22 20:29:52 vojtech Exp $
- *
  *  Copyright (c) 1998-2001 Vojtech Pavlik
  *
  *   Based on the work of:
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
index 989483f..b6f8598 100644
--- a/drivers/input/joystick/turbografx.c
+++ b/drivers/input/joystick/turbografx.c
@@ -1,6 +1,4 @@
 /*
- * $Id: turbografx.c,v 1.14 2002/01/22 20:30:39 vojtech Exp $
- *
  *  Copyright (c) 1998-2001 Vojtech Pavlik
  *
  *  Based on the work of:
diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c
index 1085c84..3f4ec73 100644
--- a/drivers/input/joystick/twidjoy.c
+++ b/drivers/input/joystick/twidjoy.c
@@ -1,8 +1,4 @@
 /*
- * $Id: twidjoy.c,v 1.5 2002/01/22 20:31:53 vojtech Exp $
- *
- *  derived from CVS-ID "stinger.c,v 1.5 2001/05/29 12:57:18 vojtech Exp"
- *
  *  Copyright (c) 2001 Arndt Schoenewald
  *  Copyright (c) 2000-2001 Vojtech Pavlik
  *  Copyright (c) 2000 Mark Fletcher
diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c
index e928b6e..f72c83e 100644
--- a/drivers/input/joystick/warrior.c
+++ b/drivers/input/joystick/warrior.c
@@ -1,6 +1,4 @@
 /*
- * $Id: warrior.c,v 1.14 2002/01/22 20:32:10 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  */
 
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index b29e3af..87d3e7e 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -418,11 +418,11 @@
 	case -ESHUTDOWN:
 		/* this urb is terminated, clean up */
 		dbg("%s - urb shutting down with status: %d",
-			__FUNCTION__, status);
+			__func__, status);
 		return;
 	default:
 		dbg("%s - nonzero urb status received: %d",
-			__FUNCTION__, status);
+			__func__, status);
 		goto exit;
 	}
 
@@ -441,7 +441,7 @@
 	retval = usb_submit_urb (urb, GFP_ATOMIC);
 	if (retval)
 		err ("%s - usb_submit_urb failed with result %d",
-		     __FUNCTION__, retval);
+		     __func__, retval);
 }
 
 static void xpad_bulk_out(struct urb *urb)
@@ -477,11 +477,11 @@
 		case -ESHUTDOWN:
 			/* this urb is terminated, clean up */
 			dbg("%s - urb shutting down with status: %d",
-				__FUNCTION__, status);
+				__func__, status);
 			return;
 		default:
 			dbg("%s - nonzero urb status received: %d",
-				__FUNCTION__, status);
+				__func__, status);
 			goto exit;
 	}
 
@@ -489,7 +489,7 @@
 	retval = usb_submit_urb(urb, GFP_ATOMIC);
 	if (retval)
 		err("%s - usb_submit_urb failed with result %d",
-		    __FUNCTION__, retval);
+		    __func__, retval);
 }
 
 static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c
index 81bf756..35149ec 100644
--- a/drivers/input/keyboard/amikbd.c
+++ b/drivers/input/keyboard/amikbd.c
@@ -1,6 +1,4 @@
 /*
- * $Id: amikbd.c,v 1.13 2002/02/01 16:02:24 vojtech Exp $
- *
  *  Copyright (c) 2000-2001 Vojtech Pavlik
  *
  *  Based on the work of:
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index af58a6f..b1ce10f 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -68,7 +68,7 @@
  * are loadable via an userland utility.
  */
 
-static unsigned char atkbd_set2_keycode[512] = {
+static const unsigned short atkbd_set2_keycode[512] = {
 
 #ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES
 
@@ -99,7 +99,7 @@
 #endif
 };
 
-static unsigned char atkbd_set3_keycode[512] = {
+static const unsigned short atkbd_set3_keycode[512] = {
 
 	  0,  0,  0,  0,  0,  0,  0, 59,  1,138,128,129,130, 15, 41, 60,
 	131, 29, 42, 86, 58, 16,  2, 61,133, 56, 44, 31, 30, 17,  3, 62,
@@ -115,7 +115,7 @@
 	148,149,147,140
 };
 
-static unsigned char atkbd_unxlate_table[128] = {
+static const unsigned short atkbd_unxlate_table[128] = {
           0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
          21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
          35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
@@ -161,7 +161,7 @@
 #define ATKBD_SCR_LEFT		249
 #define ATKBD_SCR_RIGHT		248
 
-#define ATKBD_SPECIAL		248
+#define ATKBD_SPECIAL		ATKBD_SCR_RIGHT
 
 #define ATKBD_LED_EVENT_BIT	0
 #define ATKBD_REP_EVENT_BIT	1
@@ -173,7 +173,7 @@
 #define ATKBD_XL_HANGEUL	0x10
 #define ATKBD_XL_HANJA		0x20
 
-static struct {
+static const struct {
 	unsigned char keycode;
 	unsigned char set2;
 } atkbd_scroll_keys[] = {
@@ -200,7 +200,7 @@
 	char phys[32];
 
 	unsigned short id;
-	unsigned char keycode[512];
+	unsigned short keycode[512];
 	DECLARE_BITMAP(force_release_mask, 512);
 	unsigned char set;
 	unsigned char translated;
@@ -357,7 +357,7 @@
 	unsigned int code = data;
 	int scroll = 0, hscroll = 0, click = -1;
 	int value;
-	unsigned char keycode;
+	unsigned short keycode;
 
 #ifdef ATKBD_DEBUG
 	printk(KERN_DEBUG "atkbd.c: Received %02x flags %02x\n", data, flags);
@@ -851,6 +851,23 @@
 }
 
 /*
+ * Perform fixup for HP system that doesn't generate release
+ * for its video switch
+ */
+static void atkbd_hp_keymap_fixup(struct atkbd *atkbd)
+{
+	const unsigned int forced_release_keys[] = {
+		0x94,
+	};
+	int i;
+
+	if (atkbd->set == 2)
+		for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++)
+			__set_bit(forced_release_keys[i],
+					atkbd->force_release_mask);
+}
+
+/*
  * atkbd_set_keycode_table() initializes keyboard's keycode table
  * according to the selected scancode set
  */
@@ -961,16 +978,16 @@
 		input_dev->evbit[0] |= BIT_MASK(EV_REL);
 		input_dev->relbit[0] = BIT_MASK(REL_WHEEL) |
 			BIT_MASK(REL_HWHEEL);
-		set_bit(BTN_MIDDLE, input_dev->keybit);
+		__set_bit(BTN_MIDDLE, input_dev->keybit);
 	}
 
 	input_dev->keycode = atkbd->keycode;
-	input_dev->keycodesize = sizeof(unsigned char);
+	input_dev->keycodesize = sizeof(unsigned short);
 	input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode);
 
 	for (i = 0; i < 512; i++)
 		if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL)
-			set_bit(atkbd->keycode[i], input_dev->keybit);
+			__set_bit(atkbd->keycode[i], input_dev->keybit);
 }
 
 /*
@@ -1452,6 +1469,15 @@
 		.callback = atkbd_setup_fixup,
 		.driver_data = atkbd_latitude_keymap_fixup,
 	},
+	{
+		.ident = "HP 2133",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP 2133"),
+		},
+		.callback = atkbd_setup_fixup,
+		.driver_data = atkbd_hp_keymap_fixup,
+	},
 	{ }
 };
 
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index bbd00c3..be58730 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -26,23 +26,54 @@
 
 #include <asm/gpio.h>
 
+struct gpio_button_data {
+	struct gpio_keys_button *button;
+	struct input_dev *input;
+	struct timer_list timer;
+};
+
+struct gpio_keys_drvdata {
+	struct input_dev *input;
+	struct gpio_button_data data[0];
+};
+
+static void gpio_keys_report_event(struct gpio_keys_button *button,
+				   struct input_dev *input)
+{
+	unsigned int type = button->type ?: EV_KEY;
+	int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low;
+
+	input_event(input, type, button->code, !!state);
+	input_sync(input);
+}
+
+static void gpio_check_button(unsigned long _data)
+{
+	struct gpio_button_data *data = (struct gpio_button_data *)_data;
+
+	gpio_keys_report_event(data->button, data->input);
+}
+
 static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
 {
-	int i;
 	struct platform_device *pdev = dev_id;
 	struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
-	struct input_dev *input = platform_get_drvdata(pdev);
+	struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
+	int i;
 
 	for (i = 0; i < pdata->nbuttons; i++) {
 		struct gpio_keys_button *button = &pdata->buttons[i];
-		int gpio = button->gpio;
 
-		if (irq == gpio_to_irq(gpio)) {
-			unsigned int type = button->type ?: EV_KEY;
-			int state = (gpio_get_value(gpio) ? 1 : 0) ^ button->active_low;
+		if (irq == gpio_to_irq(button->gpio)) {
+			struct gpio_button_data *bdata = &ddata->data[i];
 
-			input_event(input, type, button->code, !!state);
-			input_sync(input);
+			if (button->debounce_interval)
+				mod_timer(&bdata->timer,
+					  jiffies +
+					  msecs_to_jiffies(button->debounce_interval));
+			else
+				gpio_keys_report_event(button, bdata->input);
+
 			return IRQ_HANDLED;
 		}
 	}
@@ -53,17 +84,21 @@
 static int __devinit gpio_keys_probe(struct platform_device *pdev)
 {
 	struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
+	struct gpio_keys_drvdata *ddata;
 	struct input_dev *input;
 	int i, error;
 	int wakeup = 0;
 
+	ddata = kzalloc(sizeof(struct gpio_keys_drvdata) +
+			pdata->nbuttons * sizeof(struct gpio_button_data),
+			GFP_KERNEL);
 	input = input_allocate_device();
-	if (!input)
-		return -ENOMEM;
+	if (!ddata || !input) {
+		error = -ENOMEM;
+		goto fail1;
+	}
 
-	platform_set_drvdata(pdev, input);
-
-	input->evbit[0] = BIT_MASK(EV_KEY);
+	platform_set_drvdata(pdev, ddata);
 
 	input->name = pdev->name;
 	input->phys = "gpio-keys/input0";
@@ -74,16 +109,23 @@
 	input->id.product = 0x0001;
 	input->id.version = 0x0100;
 
+	ddata->input = input;
+
 	for (i = 0; i < pdata->nbuttons; i++) {
 		struct gpio_keys_button *button = &pdata->buttons[i];
+		struct gpio_button_data *bdata = &ddata->data[i];
 		int irq;
 		unsigned int type = button->type ?: EV_KEY;
 
+		bdata->input = input;
+		setup_timer(&bdata->timer,
+			    gpio_check_button, (unsigned long)bdata);
+
 		error = gpio_request(button->gpio, button->desc ?: "gpio_keys");
 		if (error < 0) {
 			pr_err("gpio-keys: failed to request GPIO %d,"
 				" error %d\n", button->gpio, error);
-			goto fail;
+			goto fail2;
 		}
 
 		error = gpio_direction_input(button->gpio);
@@ -92,7 +134,7 @@
 				" direction for GPIO %d, error %d\n",
 				button->gpio, error);
 			gpio_free(button->gpio);
-			goto fail;
+			goto fail2;
 		}
 
 		irq = gpio_to_irq(button->gpio);
@@ -102,7 +144,7 @@
 				" for GPIO %d, error %d\n",
 				button->gpio, error);
 			gpio_free(button->gpio);
-			goto fail;
+			goto fail2;
 		}
 
 		error = request_irq(irq, gpio_keys_isr,
@@ -114,7 +156,7 @@
 			pr_err("gpio-keys: Unable to claim irq %d; error %d\n",
 				irq, error);
 			gpio_free(button->gpio);
-			goto fail;
+			goto fail2;
 		}
 
 		if (button->wakeup)
@@ -127,21 +169,25 @@
 	if (error) {
 		pr_err("gpio-keys: Unable to register input device, "
 			"error: %d\n", error);
-		goto fail;
+		goto fail2;
 	}
 
 	device_init_wakeup(&pdev->dev, wakeup);
 
 	return 0;
 
- fail:
+ fail2:
 	while (--i >= 0) {
 		free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev);
+		if (pdata->buttons[i].debounce_interval)
+			del_timer_sync(&ddata->data[i].timer);
 		gpio_free(pdata->buttons[i].gpio);
 	}
 
 	platform_set_drvdata(pdev, NULL);
+ fail1:
 	input_free_device(input);
+	kfree(ddata);
 
 	return error;
 }
@@ -149,7 +195,8 @@
 static int __devexit gpio_keys_remove(struct platform_device *pdev)
 {
 	struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
-	struct input_dev *input = platform_get_drvdata(pdev);
+	struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
+	struct input_dev *input = ddata->input;
 	int i;
 
 	device_init_wakeup(&pdev->dev, 0);
@@ -157,6 +204,8 @@
 	for (i = 0; i < pdata->nbuttons; i++) {
 		int irq = gpio_to_irq(pdata->buttons[i].gpio);
 		free_irq(irq, pdev);
+		if (pdata->buttons[i].debounce_interval)
+			del_timer_sync(&ddata->data[i].timer);
 		gpio_free(pdata->buttons[i].gpio);
 	}
 
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c
index 32e2c26..4730ef3 100644
--- a/drivers/input/keyboard/lkkbd.c
+++ b/drivers/input/keyboard/lkkbd.c
@@ -538,11 +538,11 @@
 			switch (code) {
 				case SND_CLICK:
 					if (value == 0) {
-						DBG ("%s: Deactivating key clicks\n", __FUNCTION__);
+						DBG ("%s: Deactivating key clicks\n", __func__);
 						lk->serio->write (lk->serio, LK_CMD_DISABLE_KEYCLICK);
 						lk->serio->write (lk->serio, LK_CMD_DISABLE_CTRCLICK);
 					} else {
-						DBG ("%s: Activating key clicks\n", __FUNCTION__);
+						DBG ("%s: Activating key clicks\n", __func__);
 						lk->serio->write (lk->serio, LK_CMD_ENABLE_KEYCLICK);
 						lk->serio->write (lk->serio, volume_to_hw (lk->keyclick_volume));
 						lk->serio->write (lk->serio, LK_CMD_ENABLE_CTRCLICK);
@@ -560,7 +560,7 @@
 
 		default:
 			printk (KERN_ERR "%s (): Got unknown type %d, code %d, value %d\n",
-					__FUNCTION__, type, code, value);
+					__func__, type, code, value);
 	}
 
 	return -1;
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index 45767e7..6f1516f 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -105,6 +105,8 @@
 	struct input_dev *input_dev;
 	void __iomem *mmio_base;
 
+	int irq;
+
 	/* matrix key code map */
 	unsigned int matrix_keycodes[MAX_MATRIX_KEY_NUM];
 
@@ -392,6 +394,10 @@
 	struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
 
 	clk_disable(keypad->clk);
+
+	if (device_may_wakeup(&pdev->dev))
+		enable_irq_wake(keypad->irq);
+
 	return 0;
 }
 
@@ -400,6 +406,9 @@
 	struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
 	struct input_dev *input_dev = keypad->input_dev;
 
+	if (device_may_wakeup(&pdev->dev))
+		disable_irq_wake(keypad->irq);
+
 	mutex_lock(&input_dev->mutex);
 
 	if (input_dev->users) {
@@ -509,6 +518,8 @@
 		goto failed_free_dev;
 	}
 
+	keypad->irq = irq;
+
 	/* Register the input device */
 	error = input_register_device(input_dev);
 	if (error) {
@@ -516,6 +527,8 @@
 		goto failed_free_irq;
 	}
 
+	device_init_wakeup(&pdev->dev, 1);
+
 	return 0;
 
 failed_free_irq:
@@ -539,7 +552,7 @@
 	struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
 	struct resource *res;
 
-	free_irq(platform_get_irq(pdev, 0), pdev);
+	free_irq(keypad->irq, pdev);
 
 	clk_disable(keypad->clk);
 	clk_put(keypad->clk);
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
index be0f5d1..9fce6d1 100644
--- a/drivers/input/keyboard/sunkbd.c
+++ b/drivers/input/keyboard/sunkbd.c
@@ -1,6 +1,4 @@
 /*
- * $Id: sunkbd.c,v 1.14 2001/09/25 10:12:07 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  */
 
diff --git a/drivers/input/keyboard/tosakbd.c b/drivers/input/keyboard/tosakbd.c
index 94e444b..b12b7ee 100644
--- a/drivers/input/keyboard/tosakbd.c
+++ b/drivers/input/keyboard/tosakbd.c
@@ -215,8 +215,6 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&tosakbd->lock, flags);
-	PGSR1 = (PGSR1 & ~TOSA_GPIO_LOW_STROBE_BIT);
-	PGSR2 = (PGSR2 & ~TOSA_GPIO_HIGH_STROBE_BIT);
 	tosakbd->suspended = 1;
 	spin_unlock_irqrestore(&tosakbd->lock, flags);
 
diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c
index 152a2c0..37b01d7 100644
--- a/drivers/input/keyboard/xtkbd.c
+++ b/drivers/input/keyboard/xtkbd.c
@@ -1,6 +1,4 @@
 /*
- * $Id: xtkbd.c,v 1.11 2001/09/25 10:12:07 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  */
 
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 432699d..e99b788 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -189,6 +189,16 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called uinput.
 
+config INPUT_SGI_BTNS
+	tristate "SGI Indy/O2 volume button interface"
+	depends on SGI_IP22 || SGI_IP32
+	select INPUT_POLLDEV
+	help
+	  Say Y here if you want to support SGI Indy/O2 volume button interface.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called sgi_btns.
+
 config HP_SDC_RTC
 	tristate "HP SDC Real Time Clock"
 	depends on GSC || HP300
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index ebd39f2..f48009b 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -19,3 +19,4 @@
 obj-$(CONFIG_HP_SDC_RTC)		+= hp_sdc_rtc.o
 obj-$(CONFIG_INPUT_UINPUT)		+= uinput.o
 obj-$(CONFIG_INPUT_APANEL)		+= apanel.o
+obj-$(CONFIG_INPUT_SGI_BTNS)		+= sgi_btns.o
diff --git a/drivers/input/misc/ati_remote.c b/drivers/input/misc/ati_remote.c
index f3b86c2..debfc1a 100644
--- a/drivers/input/misc/ati_remote.c
+++ b/drivers/input/misc/ati_remote.c
@@ -330,7 +330,7 @@
 	ati_remote->irq_urb->dev = ati_remote->udev;
 	if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) {
 		dev_err(&ati_remote->interface->dev,
-			"%s: usb_submit_urb failed!\n", __FUNCTION__);
+			"%s: usb_submit_urb failed!\n", __func__);
 		return -EIO;
 	}
 
@@ -356,7 +356,7 @@
 
 	if (urb->status) {
 		dev_dbg(&ati_remote->interface->dev, "%s: status %d\n",
-			__FUNCTION__, urb->status);
+			__func__, urb->status);
 		return;
 	}
 
@@ -601,17 +601,17 @@
 	case -ENOENT:
 	case -ESHUTDOWN:
 		dev_dbg(&ati_remote->interface->dev, "%s: urb error status, unlink? \n",
-			__FUNCTION__);
+			__func__);
 		return;
 	default:		/* error */
 		dev_dbg(&ati_remote->interface->dev, "%s: Nonzero urb status %d\n",
-			__FUNCTION__, urb->status);
+			__func__, urb->status);
 	}
 
 	retval = usb_submit_urb(urb, GFP_ATOMIC);
 	if (retval)
 		dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n",
-			__FUNCTION__, retval);
+			__func__, retval);
 }
 
 /*
@@ -734,7 +734,7 @@
 	int err = -ENOMEM;
 
 	if (iface_host->desc.bNumEndpoints != 2) {
-		err("%s: Unexpected desc.bNumEndpoints\n", __FUNCTION__);
+		err("%s: Unexpected desc.bNumEndpoints\n", __func__);
 		return -ENODEV;
 	}
 
@@ -742,11 +742,11 @@
 	endpoint_out = &iface_host->endpoint[1].desc;
 
 	if (!usb_endpoint_is_int_in(endpoint_in)) {
-		err("%s: Unexpected endpoint_in\n", __FUNCTION__);
+		err("%s: Unexpected endpoint_in\n", __func__);
 		return -ENODEV;
 	}
 	if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) {
-		err("%s: endpoint_in message size==0? \n", __FUNCTION__);
+		err("%s: endpoint_in message size==0? \n", __func__);
 		return -ENODEV;
 	}
 
@@ -814,7 +814,7 @@
 	ati_remote = usb_get_intfdata(interface);
 	usb_set_intfdata(interface, NULL);
 	if (!ati_remote) {
-		warn("%s - null device?\n", __FUNCTION__);
+		warn("%s - null device?\n", __func__);
 		return;
 	}
 
diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c
index f2709b8..a7fabaf 100644
--- a/drivers/input/misc/ati_remote2.c
+++ b/drivers/input/misc/ati_remote2.c
@@ -137,14 +137,14 @@
 	r = usb_submit_urb(ar2->urb[0], GFP_KERNEL);
 	if (r) {
 		dev_err(&ar2->intf[0]->dev,
-			"%s: usb_submit_urb() = %d\n", __FUNCTION__, r);
+			"%s: usb_submit_urb() = %d\n", __func__, r);
 		return r;
 	}
 	r = usb_submit_urb(ar2->urb[1], GFP_KERNEL);
 	if (r) {
 		usb_kill_urb(ar2->urb[0]);
 		dev_err(&ar2->intf[1]->dev,
-			"%s: usb_submit_urb() = %d\n", __FUNCTION__, r);
+			"%s: usb_submit_urb() = %d\n", __func__, r);
 		return r;
 	}
 
@@ -294,17 +294,17 @@
 	case -ECONNRESET:
 	case -ESHUTDOWN:
 		dev_dbg(&ar2->intf[0]->dev,
-			"%s(): urb status = %d\n", __FUNCTION__, urb->status);
+			"%s(): urb status = %d\n", __func__, urb->status);
 		return;
 	default:
 		dev_err(&ar2->intf[0]->dev,
-			"%s(): urb status = %d\n", __FUNCTION__, urb->status);
+			"%s(): urb status = %d\n", __func__, urb->status);
 	}
 
 	r = usb_submit_urb(urb, GFP_ATOMIC);
 	if (r)
 		dev_err(&ar2->intf[0]->dev,
-			"%s(): usb_submit_urb() = %d\n", __FUNCTION__, r);
+			"%s(): usb_submit_urb() = %d\n", __func__, r);
 }
 
 static void ati_remote2_complete_key(struct urb *urb)
@@ -321,17 +321,17 @@
 	case -ECONNRESET:
 	case -ESHUTDOWN:
 		dev_dbg(&ar2->intf[1]->dev,
-			"%s(): urb status = %d\n", __FUNCTION__, urb->status);
+			"%s(): urb status = %d\n", __func__, urb->status);
 		return;
 	default:
 		dev_err(&ar2->intf[1]->dev,
-			"%s(): urb status = %d\n", __FUNCTION__, urb->status);
+			"%s(): urb status = %d\n", __func__, urb->status);
 	}
 
 	r = usb_submit_urb(urb, GFP_ATOMIC);
 	if (r)
 		dev_err(&ar2->intf[1]->dev,
-			"%s(): usb_submit_urb() = %d\n", __FUNCTION__, r);
+			"%s(): usb_submit_urb() = %d\n", __func__, r);
 }
 
 static int ati_remote2_input_init(struct ati_remote2 *ar2)
@@ -438,7 +438,7 @@
 			    channel, 0x0, NULL, 0, USB_CTRL_SET_TIMEOUT);
 	if (r) {
 		dev_err(&ar2->udev->dev, "%s - failed to set channel due to error: %d\n",
-			__FUNCTION__, r);
+			__func__, r);
 		return r;
 	}
 
diff --git a/drivers/input/misc/keyspan_remote.c b/drivers/input/misc/keyspan_remote.c
index 952938a..86afdd1 100644
--- a/drivers/input/misc/keyspan_remote.c
+++ b/drivers/input/misc/keyspan_remote.c
@@ -159,7 +159,7 @@
 	if (dev->data.pos >= dev->data.len) {
 		dev_dbg(&dev->udev->dev,
 			"%s - Error ran out of data. pos: %d, len: %d\n",
-			__FUNCTION__, dev->data.pos, dev->data.len);
+			__func__, dev->data.pos, dev->data.len);
 		return -1;
 	}
 
@@ -267,7 +267,7 @@
 				remote->data.tester = remote->data.tester >> 6;
 				remote->data.bits_left -= 6;
 			} else {
-				err("%s - Unknown sequence found in system data.\n", __FUNCTION__);
+				err("%s - Unknown sequence found in system data.\n", __func__);
 				remote->stage = 0;
 				return;
 			}
@@ -286,7 +286,7 @@
 				remote->data.tester = remote->data.tester >> 6;
 				remote->data.bits_left -= 6;
 			} else {
-				err("%s - Unknown sequence found in button data.\n", __FUNCTION__);
+				err("%s - Unknown sequence found in button data.\n", __func__);
 				remote->stage = 0;
 				return;
 			}
@@ -302,7 +302,7 @@
 			remote->data.tester = remote->data.tester >> 6;
 			remote->data.bits_left -= 6;
 		} else {
-			err("%s - Error in message, invalid toggle.\n", __FUNCTION__);
+			err("%s - Error in message, invalid toggle.\n", __func__);
 			remote->stage = 0;
 			return;
 		}
@@ -317,7 +317,7 @@
 
 		dev_dbg(&remote->udev->dev,
 			"%s found valid message: system: %d, button: %d, toggle: %d\n",
-			__FUNCTION__, message.system, message.button, message.toggle);
+			__func__, message.system, message.button, message.toggle);
 
 		if (message.toggle != remote->toggle) {
 			keyspan_report_button(remote, message.button, 1);
@@ -341,7 +341,7 @@
 				 0x11, 0x40, 0x5601, 0x0, NULL, 0, 0);
 	if (retval) {
 		dev_dbg(&dev->dev, "%s - failed to set bit rate due to error: %d\n",
-			__FUNCTION__, retval);
+			__func__, retval);
 		return(retval);
 	}
 
@@ -349,7 +349,7 @@
 				 0x44, 0x40, 0x0, 0x0, NULL, 0, 0);
 	if (retval) {
 		dev_dbg(&dev->dev, "%s - failed to set resume sensitivity due to error: %d\n",
-			__FUNCTION__, retval);
+			__func__, retval);
 		return(retval);
 	}
 
@@ -357,11 +357,11 @@
 				 0x22, 0x40, 0x0, 0x0, NULL, 0, 0);
 	if (retval) {
 		dev_dbg(&dev->dev, "%s - failed to turn receive on due to error: %d\n",
-			__FUNCTION__, retval);
+			__func__, retval);
 		return(retval);
 	}
 
-	dev_dbg(&dev->dev, "%s - Setup complete.\n", __FUNCTION__);
+	dev_dbg(&dev->dev, "%s - Setup complete.\n", __func__);
 	return(retval);
 }
 
@@ -397,7 +397,7 @@
 resubmit:
 	retval = usb_submit_urb(urb, GFP_ATOMIC);
 	if (retval)
-		err ("%s - usb_submit_urb failed with result: %d", __FUNCTION__, retval);
+		err ("%s - usb_submit_urb failed with result: %d", __func__, retval);
 }
 
 static int keyspan_open(struct input_dev *dev)
diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c
index 7a7b8c7..a53c488 100644
--- a/drivers/input/misc/powermate.c
+++ b/drivers/input/misc/powermate.c
@@ -96,10 +96,10 @@
 	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", __func__, urb->status);
 		return;
 	default:
-		dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+		dbg("%s - nonzero urb status received: %d", __func__, urb->status);
 		goto exit;
 	}
 
@@ -112,7 +112,7 @@
 	retval = usb_submit_urb (urb, GFP_ATOMIC);
 	if (retval)
 		err ("%s - usb_submit_urb failed with result %d",
-		     __FUNCTION__, retval);
+		     __func__, retval);
 }
 
 /* Decide if we need to issue a control message and do so. Must be called with pm->lock taken */
diff --git a/drivers/input/misc/sgi_btns.c b/drivers/input/misc/sgi_btns.c
new file mode 100644
index 0000000..ce238f5
--- /dev/null
+++ b/drivers/input/misc/sgi_btns.c
@@ -0,0 +1,178 @@
+/*
+ *  SGI Volume Button interface driver
+ *
+ *  Copyright (C) 2008  Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/init.h>
+#include <linux/input-polldev.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#ifdef CONFIG_SGI_IP22
+#include <asm/sgi/ioc.h>
+
+static inline u8 button_status(void)
+{
+	u8 status;
+
+	status = readb(&sgioc->panel) ^ 0xa0;
+	return ((status & 0x80) >> 6) | ((status & 0x20) >> 5);
+}
+#endif
+
+#ifdef CONFIG_SGI_IP32
+#include <asm/ip32/mace.h>
+
+static inline u8 button_status(void)
+{
+	u64 status;
+
+	status = readq(&mace->perif.audio.control);
+	writeq(status & ~(3U << 23), &mace->perif.audio.control);
+
+	return (status >> 23) & 3;
+}
+#endif
+
+#define BUTTONS_POLL_INTERVAL	30	/* msec */
+#define BUTTONS_COUNT_THRESHOLD	3
+
+static const unsigned short sgi_map[] = {
+	KEY_VOLUMEDOWN,
+	KEY_VOLUMEUP
+};
+
+struct buttons_dev {
+	struct input_polled_dev *poll_dev;
+	unsigned short keymap[ARRAY_SIZE(sgi_map)];
+	int count[ARRAY_SIZE(sgi_map)];
+};
+
+static void handle_buttons(struct input_polled_dev *dev)
+{
+	struct buttons_dev *bdev = dev->private;
+	struct input_dev *input = dev->input;
+	u8 status;
+	int i;
+
+	status = button_status();
+
+	for (i = 0; i < ARRAY_SIZE(bdev->keymap); i++) {
+		if (status & (1U << i)) {
+			if (++bdev->count[i] == BUTTONS_COUNT_THRESHOLD) {
+				input_event(input, EV_MSC, MSC_SCAN, i);
+				input_report_key(input, bdev->keymap[i], 1);
+				input_sync(input);
+			}
+		} else {
+			if (bdev->count[i] >= BUTTONS_COUNT_THRESHOLD) {
+				input_event(input, EV_MSC, MSC_SCAN, i);
+				input_report_key(input, bdev->keymap[i], 0);
+				input_sync(input);
+			}
+			bdev->count[i] = 0;
+		}
+	}
+}
+
+static int __devinit sgi_buttons_probe(struct platform_device *pdev)
+{
+	struct buttons_dev *bdev;
+	struct input_polled_dev *poll_dev;
+	struct input_dev *input;
+	int error, i;
+
+	bdev = kzalloc(sizeof(struct buttons_dev), GFP_KERNEL);
+	poll_dev = input_allocate_polled_device();
+	if (!bdev || !poll_dev) {
+		error = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	memcpy(bdev->keymap, sgi_map, sizeof(bdev->keymap));
+
+	poll_dev->private = bdev;
+	poll_dev->poll = handle_buttons;
+	poll_dev->poll_interval = BUTTONS_POLL_INTERVAL;
+
+	input = poll_dev->input;
+	input->name = "SGI buttons";
+	input->phys = "sgi/input0";
+	input->id.bustype = BUS_HOST;
+	input->dev.parent = &pdev->dev;
+
+	input->keycode = bdev->keymap;
+	input->keycodemax = ARRAY_SIZE(bdev->keymap);
+	input->keycodesize = sizeof(unsigned short);
+
+	input_set_capability(input, EV_MSC, MSC_SCAN);
+	__set_bit(EV_KEY, input->evbit);
+	for (i = 0; i < ARRAY_SIZE(sgi_map); i++)
+		__set_bit(bdev->keymap[i], input->keybit);
+	__clear_bit(KEY_RESERVED, input->keybit);
+
+	bdev->poll_dev = poll_dev;
+	dev_set_drvdata(&pdev->dev, bdev);
+
+	error = input_register_polled_device(poll_dev);
+	if (error)
+		goto err_free_mem;
+
+	return 0;
+
+ err_free_mem:
+	input_free_polled_device(poll_dev);
+	kfree(bdev);
+	dev_set_drvdata(&pdev->dev, NULL);
+	return error;
+}
+
+static int __devexit sgi_buttons_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct buttons_dev *bdev = dev_get_drvdata(dev);
+
+	input_unregister_polled_device(bdev->poll_dev);
+	input_free_polled_device(bdev->poll_dev);
+	kfree(bdev);
+	dev_set_drvdata(dev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver sgi_buttons_driver = {
+	.probe	= sgi_buttons_probe,
+	.remove	= __devexit_p(sgi_buttons_remove),
+	.driver	= {
+		.name	= "sgibtns",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init sgi_buttons_init(void)
+{
+	return platform_driver_register(&sgi_buttons_driver);
+}
+
+static void __exit sgi_buttons_exit(void)
+{
+	platform_driver_unregister(&sgi_buttons_driver);
+}
+
+module_init(sgi_buttons_init);
+module_exit(sgi_buttons_exit);
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index 72176f3d..fe268be 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -1186,7 +1186,7 @@
 
 static int __devinit setup_input_dev(void)
 {
-	const struct key_entry *key;
+	struct key_entry *key;
 	struct input_dev *input_dev;
 	int error;
 
@@ -1219,6 +1219,23 @@
 				set_bit(key->sw.code, input_dev->swbit);
 				break;
 
+			/* if wifi or bluetooth are not available, create normal keys */
+			case KE_WIFI:
+				if (!have_wifi) {
+					key->type = KE_KEY;
+					key->keycode = KEY_WLAN;
+					key--;
+				}
+				break;
+
+			case KE_BLUETOOTH:
+				if (!have_bluetooth) {
+					key->type = KE_KEY;
+					key->keycode = KEY_BLUETOOTH;
+					key--;
+				}
+				break;
+
 			default:
 				break;
 		}
diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c
index 46279ef..facefd3 100644
--- a/drivers/input/misc/yealink.c
+++ b/drivers/input/misc/yealink.c
@@ -119,6 +119,8 @@
 	u8 lcdMap[ARRAY_SIZE(lcdMap)];	/* state of LCD, LED ... */
 	int key_code;			/* last reported key	 */
 
+	unsigned int shutdown:1;
+
 	int	stat_ix;
 	union {
 		struct yld_status s;
@@ -424,10 +426,10 @@
 static void urb_irq_callback(struct urb *urb)
 {
 	struct yealink_dev *yld = urb->context;
-	int ret;
+	int ret, status = urb->status;
 
-	if (urb->status)
-		err("%s - urb status %d", __FUNCTION__, urb->status);
+	if (status)
+		err("%s - urb status %d", __func__, status);
 
 	switch (yld->irq_data->cmd) {
 	case CMD_KEYPRESS:
@@ -447,33 +449,38 @@
 
 	yealink_do_idle_tasks(yld);
 
-	ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
-	if (ret)
-		err("%s - usb_submit_urb failed %d", __FUNCTION__, ret);
+	if (!yld->shutdown) {
+		ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
+		if (ret && ret != -EPERM)
+			err("%s - usb_submit_urb failed %d", __func__, ret);
+	}
 }
 
 static void urb_ctl_callback(struct urb *urb)
 {
 	struct yealink_dev *yld = urb->context;
-	int ret;
+	int ret = 0, status = urb->status;
 
-	if (urb->status)
-		err("%s - urb status %d", __FUNCTION__, urb->status);
+	if (status)
+		err("%s - urb status %d", __func__, status);
 
 	switch (yld->ctl_data->cmd) {
 	case CMD_KEYPRESS:
 	case CMD_SCANCODE:
 		/* ask for a response */
-		ret = usb_submit_urb(yld->urb_irq, GFP_ATOMIC);
+		if (!yld->shutdown)
+			ret = usb_submit_urb(yld->urb_irq, GFP_ATOMIC);
 		break;
 	default:
 		/* send new command */
 		yealink_do_idle_tasks(yld);
-		ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
+		if (!yld->shutdown)
+			ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
+		break;
 	}
 
-	if (ret)
-		err("%s - usb_submit_urb failed %d", __FUNCTION__, ret);
+	if (ret && ret != -EPERM)
+		err("%s - usb_submit_urb failed %d", __func__, ret);
 }
 
 /*******************************************************************************
@@ -505,7 +512,7 @@
 	struct yealink_dev *yld = input_get_drvdata(dev);
 	int i, ret;
 
-	dbg("%s", __FUNCTION__);
+	dbg("%s", __func__);
 
 	/* force updates to device */
 	for (i = 0; i<sizeof(yld->master); i++)
@@ -521,7 +528,7 @@
 	yld->ctl_data->sum	= 0x100-CMD_INIT-10;
 	if ((ret = usb_submit_urb(yld->urb_ctl, GFP_KERNEL)) != 0) {
 		dbg("%s - usb_submit_urb failed with result %d",
-		     __FUNCTION__, ret);
+		     __func__, ret);
 		return ret;
 	}
 	return 0;
@@ -531,8 +538,18 @@
 {
 	struct yealink_dev *yld = input_get_drvdata(dev);
 
+	yld->shutdown = 1;
+	/*
+	 * Make sure the flag is seen by other CPUs before we start
+	 * killing URBs so new URBs won't be submitted
+	 */
+	smp_wmb();
+
 	usb_kill_urb(yld->urb_ctl);
 	usb_kill_urb(yld->urb_irq);
+
+	yld->shutdown = 0;
+	smp_wmb();
 }
 
 /*******************************************************************************
@@ -809,9 +826,6 @@
 	if (yld == NULL)
 		return err;
 
-	usb_kill_urb(yld->urb_irq);	/* parameter validation in core/urb */
-	usb_kill_urb(yld->urb_ctl);	/* parameter validation in core/urb */
-
         if (yld->idev) {
 		if (err)
 			input_free_device(yld->idev);
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c
index ce6fdec..1f41ae9 100644
--- a/drivers/input/mouse/appletouch.c
+++ b/drivers/input/mouse/appletouch.c
@@ -2,12 +2,13 @@
  * Apple USB Touchpad (for post-February 2005 PowerBooks and MacBooks) driver
  *
  * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2005      Johannes Berg (johannes@sipsolutions.net)
+ * Copyright (C) 2005-2008 Johannes Berg (johannes@sipsolutions.net)
  * Copyright (C) 2005      Stelian Pop (stelian@popies.net)
  * Copyright (C) 2005      Frank Arnold (frank@scirocco-5v-turbo.de)
  * Copyright (C) 2005      Peter Osterlund (petero2@telia.com)
  * Copyright (C) 2005      Michael Hanselmann (linux-kernel@hansmi.ch)
  * Copyright (C) 2006      Nicolas Boichat (nicolas@boichat.ch)
+ * Copyright (C) 2007-2008 Sven Anders (anders@anduras.de)
  *
  * Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
  *
@@ -34,77 +35,64 @@
 #include <linux/module.h>
 #include <linux/usb/input.h>
 
-/* Apple has powerbooks which have the keyboard with different Product IDs */
-#define APPLE_VENDOR_ID		0x05AC
+/* Type of touchpad */
+enum atp_touchpad_type {
+	ATP_FOUNTAIN,
+	ATP_GEYSER1,
+	ATP_GEYSER2,
+	ATP_GEYSER3,
+	ATP_GEYSER4
+};
 
-/* These names come from Info.plist in AppleUSBTrackpad.kext */
-#define FOUNTAIN_ANSI_PRODUCT_ID	0x020E
-#define FOUNTAIN_ISO_PRODUCT_ID		0x020F
-
-#define FOUNTAIN_TP_ONLY_PRODUCT_ID	0x030A
-
-#define GEYSER1_TP_ONLY_PRODUCT_ID	0x030B
-
-#define GEYSER_ANSI_PRODUCT_ID		0x0214
-#define GEYSER_ISO_PRODUCT_ID		0x0215
-#define GEYSER_JIS_PRODUCT_ID		0x0216
-
-/* MacBook devices */
-#define GEYSER3_ANSI_PRODUCT_ID		0x0217
-#define GEYSER3_ISO_PRODUCT_ID		0x0218
-#define GEYSER3_JIS_PRODUCT_ID		0x0219
-
-/*
- * Geyser IV: same as Geyser III according to Info.plist in AppleUSBTrackpad.kext
- * -> same IOClass (AppleUSBGrIIITrackpad), same acceleration tables
- */
-#define GEYSER4_ANSI_PRODUCT_ID	0x021A
-#define GEYSER4_ISO_PRODUCT_ID	0x021B
-#define GEYSER4_JIS_PRODUCT_ID	0x021C
-
-#define GEYSER4_HF_ANSI_PRODUCT_ID	0x0229
-#define GEYSER4_HF_ISO_PRODUCT_ID	0x022A
-#define GEYSER4_HF_JIS_PRODUCT_ID	0x022B
-
-#define ATP_DEVICE(prod)					\
+#define ATP_DEVICE(prod, type)					\
+{								\
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |		\
 		       USB_DEVICE_ID_MATCH_INT_CLASS |		\
 		       USB_DEVICE_ID_MATCH_INT_PROTOCOL,	\
-	.idVendor = APPLE_VENDOR_ID,				\
+	.idVendor = 0x05ac, /* Apple */				\
 	.idProduct = (prod),					\
 	.bInterfaceClass = 0x03,				\
-	.bInterfaceProtocol = 0x02
+	.bInterfaceProtocol = 0x02,				\
+	.driver_info = ATP_ ## type,				\
+}
 
-/* table of devices that work with this driver */
+/*
+ * Table of devices (Product IDs) that work with this driver.
+ * (The names come from Info.plist in AppleUSBTrackpad.kext,
+ *  According to Info.plist Geyser IV is the same as Geyser III.)
+ */
+
 static struct usb_device_id atp_table [] = {
-	{ ATP_DEVICE(FOUNTAIN_ANSI_PRODUCT_ID) },
-	{ ATP_DEVICE(FOUNTAIN_ISO_PRODUCT_ID) },
-	{ ATP_DEVICE(FOUNTAIN_TP_ONLY_PRODUCT_ID) },
-	{ ATP_DEVICE(GEYSER1_TP_ONLY_PRODUCT_ID) },
+	/* PowerBooks Feb 2005, iBooks G4 */
+	ATP_DEVICE(0x020e, FOUNTAIN),	/* FOUNTAIN ANSI */
+	ATP_DEVICE(0x020f, FOUNTAIN),	/* FOUNTAIN ISO */
+	ATP_DEVICE(0x030a, FOUNTAIN),	/* FOUNTAIN TP ONLY */
+	ATP_DEVICE(0x030b, GEYSER1),	/* GEYSER 1 TP ONLY */
 
 	/* PowerBooks Oct 2005 */
-	{ ATP_DEVICE(GEYSER_ANSI_PRODUCT_ID) },
-	{ ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) },
-	{ ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) },
+	ATP_DEVICE(0x0214, GEYSER2),	/* GEYSER 2 ANSI */
+	ATP_DEVICE(0x0215, GEYSER2),	/* GEYSER 2 ISO */
+	ATP_DEVICE(0x0216, GEYSER2),	/* GEYSER 2 JIS */
 
 	/* Core Duo MacBook & MacBook Pro */
-	{ ATP_DEVICE(GEYSER3_ANSI_PRODUCT_ID) },
-	{ ATP_DEVICE(GEYSER3_ISO_PRODUCT_ID) },
-	{ ATP_DEVICE(GEYSER3_JIS_PRODUCT_ID) },
+	ATP_DEVICE(0x0217, GEYSER3),	/* GEYSER 3 ANSI */
+	ATP_DEVICE(0x0218, GEYSER3),	/* GEYSER 3 ISO */
+	ATP_DEVICE(0x0219, GEYSER3),	/* GEYSER 3 JIS */
 
 	/* Core2 Duo MacBook & MacBook Pro */
-	{ ATP_DEVICE(GEYSER4_ANSI_PRODUCT_ID) },
-	{ ATP_DEVICE(GEYSER4_ISO_PRODUCT_ID) },
-	{ ATP_DEVICE(GEYSER4_JIS_PRODUCT_ID) },
+	ATP_DEVICE(0x021a, GEYSER4),	/* GEYSER 4 ANSI */
+	ATP_DEVICE(0x021b, GEYSER4),	/* GEYSER 4 ISO */
+	ATP_DEVICE(0x021c, GEYSER4),	/* GEYSER 4 JIS */
 
-	{ ATP_DEVICE(GEYSER4_HF_ANSI_PRODUCT_ID) },
-	{ ATP_DEVICE(GEYSER4_HF_ISO_PRODUCT_ID) },
-	{ ATP_DEVICE(GEYSER4_HF_JIS_PRODUCT_ID) },
+	/* Core2 Duo MacBook3,1 */
+	ATP_DEVICE(0x0229, GEYSER4),	/* GEYSER 4 HF ANSI */
+	ATP_DEVICE(0x022a, GEYSER4),	/* GEYSER 4 HF ISO */
+	ATP_DEVICE(0x022b, GEYSER4),	/* GEYSER 4 HF JIS */
 
 	/* Terminating entry */
 	{ }
 };
-MODULE_DEVICE_TABLE (usb, atp_table);
+MODULE_DEVICE_TABLE(usb, atp_table);
 
 /*
  * number of sensors. Note that only 16 instead of 26 X (horizontal)
@@ -124,9 +112,13 @@
  * We try to keep the touchpad aspect ratio while still doing only simple
  * arithmetics.
  * The factors below give coordinates like:
- *	0 <= x <  960 on 12" and 15" Powerbooks
- *	0 <= x < 1600 on 17" Powerbooks
- *	0 <= y <  646
+ *
+ *      0 <= x <  960 on 12" and 15" Powerbooks
+ *      0 <= x < 1600 on 17" Powerbooks and 17" MacBook Pro
+ *      0 <= x < 1216 on MacBooks and 15" MacBook Pro
+ *
+ *      0 <= y <  646 on all Powerbooks
+ *      0 <= y <  774 on all MacBooks
  */
 #define ATP_XFACT	64
 #define ATP_YFACT	43
@@ -147,43 +139,46 @@
 /* Structure to hold all of our device specific stuff */
 struct atp {
 	char			phys[64];
-	struct usb_device *	udev;		/* usb device */
-	struct urb *		urb;		/* usb request block */
-	signed char *		data;		/* transferred data */
-	struct input_dev *	input;		/* input dev */
-	unsigned char		open;		/* non-zero if opened */
-	unsigned char		valid;		/* are the sensors valid ? */
-	unsigned char		size_detect_done;
-	unsigned char		overflowwarn;	/* overflow warning printed? */
+	struct usb_device	*udev;		/* usb device */
+	struct urb		*urb;		/* usb request block */
+	signed char		*data;		/* transferred data */
+	struct input_dev	*input;		/* input dev */
+	enum atp_touchpad_type	type;		/* type of touchpad */
+	bool			open;
+	bool			valid;		/* are the samples valid? */
+	bool			size_detect_done;
+	bool			overflow_warned;
 	int			x_old;		/* last reported x/y, */
 	int			y_old;		/* used for smoothing */
-						/* current value of the sensors */
 	signed char		xy_cur[ATP_XSENSORS + ATP_YSENSORS];
-						/* last value of the sensors */
 	signed char		xy_old[ATP_XSENSORS + ATP_YSENSORS];
-						/* accumulated sensors */
 	int			xy_acc[ATP_XSENSORS + ATP_YSENSORS];
-	int			datalen;	/* size of an USB urb transfer */
-	int			idlecount;      /* number of empty packets */
-	struct work_struct      work;
+	int			datalen;	/* size of USB transfer */
+	int			idlecount;	/* number of empty packets */
+	struct work_struct	work;
 };
 
 #define dbg_dump(msg, tab) \
 	if (debug > 1) {						\
-		int i;							\
-		printk("appletouch: %s %lld", msg, (long long)jiffies); \
-		for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++)	\
-			printk(" %02x", tab[i]);			\
+		int __i;						\
+		printk(KERN_DEBUG "appletouch: %s", msg);		\
+		for (__i = 0; __i < ATP_XSENSORS + ATP_YSENSORS; __i++)	\
+			printk(" %02x", tab[__i]);			\
 		printk("\n");						\
 	}
 
 #define dprintk(format, a...)						\
 	do {								\
-		if (debug) printk(KERN_DEBUG format, ##a);		\
+		if (debug)						\
+			printk(KERN_DEBUG format, ##a);			\
 	} while (0)
 
-MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann");
-MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");
+MODULE_AUTHOR("Johannes Berg");
+MODULE_AUTHOR("Stelian Pop");
+MODULE_AUTHOR("Frank Arnold");
+MODULE_AUTHOR("Michael Hanselmann");
+MODULE_AUTHOR("Sven Anders");
+MODULE_DESCRIPTION("Apple PowerBook and MacBook USB touchpad driver");
 MODULE_LICENSE("GPL");
 
 /*
@@ -191,46 +186,14 @@
  */
 static int threshold = ATP_THRESHOLD;
 module_param(threshold, int, 0644);
-MODULE_PARM_DESC(threshold, "Discards any change in data from a sensor (trackpad has hundreds of these sensors) less than this value");
+MODULE_PARM_DESC(threshold, "Discard any change in data from a sensor"
+			    " (the trackpad has many of these sensors)"
+			    " less than this value.");
 
-static int debug = 1;
+static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Activate debugging output");
 
-static inline int atp_is_fountain(struct atp *dev)
-{
-	u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct);
-
-	return productId == FOUNTAIN_ANSI_PRODUCT_ID ||
-	       productId == FOUNTAIN_ISO_PRODUCT_ID ||
-	       productId == FOUNTAIN_TP_ONLY_PRODUCT_ID;
-}
-
-/* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */
-static inline int atp_is_geyser_2(struct atp *dev)
-{
-	u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct);
-
-	return (productId == GEYSER_ANSI_PRODUCT_ID) ||
-		(productId == GEYSER_ISO_PRODUCT_ID) ||
-		(productId == GEYSER_JIS_PRODUCT_ID);
-}
-
-static inline int atp_is_geyser_3(struct atp *dev)
-{
-	u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct);
-
-	return (productId == GEYSER3_ANSI_PRODUCT_ID) ||
-		(productId == GEYSER3_ISO_PRODUCT_ID) ||
-		(productId == GEYSER3_JIS_PRODUCT_ID) ||
-		(productId == GEYSER4_ANSI_PRODUCT_ID) ||
-		(productId == GEYSER4_ISO_PRODUCT_ID) ||
-		(productId == GEYSER4_JIS_PRODUCT_ID) ||
-		(productId == GEYSER4_HF_ANSI_PRODUCT_ID) ||
-		(productId == GEYSER4_HF_ISO_PRODUCT_ID) ||
-		(productId == GEYSER4_HF_JIS_PRODUCT_ID);
-}
-
 /*
  * By default newer Geyser devices send standard USB HID mouse
  * packets (Report ID 2). This code changes device mode, so it
@@ -240,6 +203,7 @@
 {
 	char data[8];
 	int size;
+	int i;
 
 	size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
 			ATP_GEYSER_MODE_READ_REQUEST_ID,
@@ -248,8 +212,11 @@
 			ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000);
 
 	if (size != 8) {
-		err("Could not do mode read request from device"
-		    " (Geyser Raw mode)");
+		dprintk("atp_geyser_init: read error\n");
+		for (i = 0; i < 8; i++)
+			dprintk("appletouch[%d]: %d\n", i, data[i]);
+
+		err("Failed to read mode from device.");
 		return -EIO;
 	}
 
@@ -263,8 +230,11 @@
 			ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000);
 
 	if (size != 8) {
-		err("Could not do mode write request to device"
-		    " (Geyser Raw mode)");
+		dprintk("atp_geyser_init: write error\n");
+		for (i = 0; i < 8; i++)
+			dprintk("appletouch[%d]: %d\n", i, data[i]);
+
+		err("Failed to request geyser raw mode");
 		return -EIO;
 	}
 	return 0;
@@ -280,15 +250,15 @@
 	struct usb_device *udev = dev->udev;
 	int retval;
 
+	dprintk("appletouch: putting appletouch to sleep (reinit)\n");
 	dev->idlecount = 0;
 
 	atp_geyser_init(udev);
 
 	retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
-	if (retval) {
-		err("%s - usb_submit_urb failed with result %d",
-		    __FUNCTION__, retval);
-	}
+	if (retval)
+		err("atp_reinit: usb_submit_urb failed with error %d",
+		    retval);
 }
 
 static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
@@ -323,7 +293,8 @@
 		 *
 		 * - Jason Parekh <jasonparekh@gmail.com>
 		 */
-		if (i < 1 || (!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) {
+		if (i < 1 ||
+		    (!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) {
 			(*fingers)++;
 			is_increasing = 1;
 		} else if (i > 0 && xy_sensors[i - 1] >= xy_sensors[i]) {
@@ -331,11 +302,11 @@
 		}
 
 		/*
-		 * Subtracts threshold so a high sensor that just passes the threshold
-		 * won't skew the calculated absolute coordinate.  Fixes an issue
-		 * where slowly moving the mouse would occassionaly jump a number of
-		 * pixels (let me restate--slowly moving the mouse makes this issue
-		 * most apparent).
+		 * Subtracts threshold so a high sensor that just passes the
+		 * threshold won't skew the calculated absolute coordinate.
+		 * Fixes an issue where slowly moving the mouse would
+		 * occasionally jump a number of pixels (slowly moving the
+		 * finger makes this issue most apparent.)
 		 */
 		pcum += (xy_sensors[i] - threshold) * i;
 		psum += (xy_sensors[i] - threshold);
@@ -356,7 +327,7 @@
 	input_report_key(input, BTN_TOOL_TRIPLETAP, fingers > 2);
 }
 
-static void atp_complete(struct urb* urb)
+static void atp_complete(struct urb *urb)
 {
 	int x, y, x_z, y_z, x_f, y_f;
 	int retval, i, j;
@@ -368,22 +339,22 @@
 		/* success */
 		break;
 	case -EOVERFLOW:
-		if(!dev->overflowwarn) {
+		if (!dev->overflow_warned) {
 			printk(KERN_WARNING "appletouch: OVERFLOW with data "
 				"length %d, actual length is %d\n",
 				dev->datalen, dev->urb->actual_length);
-			dev->overflowwarn = 1;
+			dev->overflow_warned = true;
 		}
 	case -ECONNRESET:
 	case -ENOENT:
 	case -ESHUTDOWN:
 		/* This urb is terminated, clean up */
-		dbg("%s - urb shutting down with status: %d",
-		    __FUNCTION__, urb->status);
+		dbg("atp_complete: urb shutting down with status: %d",
+		    urb->status);
 		return;
 	default:
-		dbg("%s - nonzero urb status received: %d",
-		    __FUNCTION__, urb->status);
+		dbg("atp_complete: nonzero urb status received: %d",
+		    urb->status);
 		goto exit;
 	}
 
@@ -396,7 +367,7 @@
 	}
 
 	/* reorder the sensors values */
-	if (atp_is_geyser_3(dev)) {
+	if (dev->type == ATP_GEYSER3 || dev->type == ATP_GEYSER4) {
 		memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
 
 		/*
@@ -415,7 +386,7 @@
 			dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1];
 			dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2];
 		}
-	} else if (atp_is_geyser_2(dev)) {
+	} else if (dev->type == ATP_GEYSER2) {
 		memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
 
 		/*
@@ -438,7 +409,7 @@
 	} else {
 		for (i = 0; i < 8; i++) {
 			/* X values */
-			dev->xy_cur[i     ] = dev->data[5 * i +  2];
+			dev->xy_cur[i +  0] = dev->data[5 * i +  2];
 			dev->xy_cur[i +  8] = dev->data[5 * i +  4];
 			dev->xy_cur[i + 16] = dev->data[5 * i + 42];
 			if (i < 2)
@@ -454,21 +425,22 @@
 
 	if (!dev->valid) {
 		/* first sample */
-		dev->valid = 1;
+		dev->valid = true;
 		dev->x_old = dev->y_old = -1;
 		memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
 
 		if (dev->size_detect_done ||
-		    atp_is_geyser_3(dev)) /* No 17" Macbooks (yet) */
+		    dev->type == ATP_GEYSER3) /* No 17" Macbooks (yet) */
 			goto exit;
 
 		/* 17" Powerbooks have extra X sensors */
-		for (i = (atp_is_geyser_2(dev) ? 15 : 16); i < ATP_XSENSORS; i++) {
+		for (i = (dev->type == ATP_GEYSER2 ? 15 : 16);
+		     i < ATP_XSENSORS; i++) {
 			if (!dev->xy_cur[i])
 				continue;
 
 			printk(KERN_INFO "appletouch: 17\" model detected.\n");
-			if (atp_is_geyser_2(dev))
+			if (dev->type == ATP_GEYSER2)
 				input_set_abs_params(dev->input, ABS_X, 0,
 						     (20 - 1) *
 						     ATP_XFACT - 1,
@@ -548,11 +520,15 @@
 	 * several hundred times a second. Re-initialization does not
 	 * work on Fountain touchpads.
 	 */
-	if (!atp_is_fountain(dev)) {
+	if (dev->type != ATP_FOUNTAIN) {
+		/*
+		 * Button must not be pressed when entering suspend,
+		 * otherwise we will never release the button.
+		 */
 		if (!x && !y && !key) {
 			dev->idlecount++;
 			if (dev->idlecount == 10) {
-				dev->valid = 0;
+				dev->valid = false;
 				schedule_work(&dev->work);
 				/* Don't resubmit urb here, wait for reinit */
 				return;
@@ -561,12 +537,11 @@
 			dev->idlecount = 0;
 	}
 
-exit:
+ exit:
 	retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
-	if (retval) {
-		err("%s - usb_submit_urb failed with result %d",
-		    __FUNCTION__, retval);
-	}
+	if (retval)
+		err("atp_complete: usb_submit_urb failed with result %d",
+		    retval);
 }
 
 static int atp_open(struct input_dev *input)
@@ -593,7 +568,7 @@
 {
 	struct usb_device *udev = dev->udev;
 
-	if (!atp_is_fountain(dev)) {
+	if (dev->type != ATP_FOUNTAIN) {
 		/* switch to raw sensor mode */
 		if (atp_geyser_init(udev))
 			return -EIO;
@@ -604,7 +579,8 @@
 	return 0;
 }
 
-static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id)
+static int atp_probe(struct usb_interface *iface,
+		     const struct usb_device_id *id)
 {
 	struct atp *dev;
 	struct input_dev *input_dev;
@@ -640,13 +616,12 @@
 
 	dev->udev = udev;
 	dev->input = input_dev;
-	dev->overflowwarn = 0;
-	if (atp_is_geyser_3(dev))
-		dev->datalen = 64;
-	else if (atp_is_geyser_2(dev))
-		dev->datalen = 64;
-	else
+	dev->type = id->driver_info;
+	dev->overflow_warned = false;
+	if (dev->type == ATP_FOUNTAIN || dev->type == ATP_GEYSER1)
 		dev->datalen = 81;
+	else
+		dev->datalen = 64;
 
 	dev->urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!dev->urb)
@@ -680,7 +655,7 @@
 
 	set_bit(EV_ABS, input_dev->evbit);
 
-	if (atp_is_geyser_3(dev)) {
+	if (dev->type == ATP_GEYSER3 || dev->type == ATP_GEYSER4) {
 		/*
 		 * MacBook have 20 X sensors, 10 Y sensors
 		 */
@@ -688,7 +663,7 @@
 				     ((20 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0);
 		input_set_abs_params(input_dev, ABS_Y, 0,
 				     ((10 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0);
-	} else if (atp_is_geyser_2(dev)) {
+	} else if (dev->type == ATP_GEYSER2) {
 		/*
 		 * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected
 		 * later.
@@ -703,9 +678,11 @@
 		 * 17" models are detected later.
 		 */
 		input_set_abs_params(input_dev, ABS_X, 0,
-				     (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
+				     (16 - 1) * ATP_XFACT - 1,
+				     ATP_FUZZ, 0);
 		input_set_abs_params(input_dev, ABS_Y, 0,
-				     (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
+				     (ATP_YSENSORS - 1) * ATP_YFACT - 1,
+				     ATP_FUZZ, 0);
 	}
 	input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
 
@@ -774,7 +751,7 @@
 	struct atp *dev = usb_get_intfdata(iface);
 
 	usb_kill_urb(dev->urb);
-	dev->valid = 0;
+	dev->valid = false;
 
 	return 0;
 }
diff --git a/drivers/input/mouse/atarimouse.c b/drivers/input/mouse/atarimouse.c
index 98a3561..adf45b3 100644
--- a/drivers/input/mouse/atarimouse.c
+++ b/drivers/input/mouse/atarimouse.c
@@ -57,15 +57,12 @@
 MODULE_DESCRIPTION("Atari mouse driver");
 MODULE_LICENSE("GPL");
 
-static int mouse_threshold[2] = {2,2};
+static int mouse_threshold[2] = {2, 2};
+module_param_array(mouse_threshold, int, NULL, 0);
 
-#ifdef __MODULE__
-MODULE_PARM(mouse_threshold, "2i");
-#endif
 #ifdef FIXED_ATARI_JOYSTICK
 extern int atari_mouse_buttons;
 #endif
-static int atamouse_used = 0;
 
 static struct input_dev *atamouse_dev;
 
@@ -97,9 +94,6 @@
 
 static int atamouse_open(struct input_dev *dev)
 {
-	if (atamouse_used++)
-		return 0;
-
 #ifdef FIXED_ATARI_JOYSTICK
 	atari_mouse_buttons = 0;
 #endif
@@ -107,23 +101,24 @@
 	ikbd_mouse_thresh(mouse_threshold[0], mouse_threshold[1]);
 	ikbd_mouse_rel_pos();
 	atari_input_mouse_interrupt_hook = atamouse_interrupt;
+
 	return 0;
 }
 
 static void atamouse_close(struct input_dev *dev)
 {
-	if (!--atamouse_used) {
-		ikbd_mouse_disable();
-		atari_mouse_interrupt_hook = NULL;
-	}
+	ikbd_mouse_disable();
+	atari_mouse_interrupt_hook = NULL;
 }
 
 static int __init atamouse_init(void)
 {
+	int error;
+
 	if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ST_MFP))
 		return -ENODEV;
 
-	if (!(atari_keyb_init()))
+	if (!atari_keyb_init())
 		return -ENODEV;
 
 	atamouse_dev = input_allocate_device();
@@ -141,12 +136,14 @@
 	atamouse_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
 	atamouse_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) |
 		BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
+
 	atamouse_dev->open = atamouse_open;
 	atamouse_dev->close = atamouse_close;
 
-	if (input_register_device(atamouse_dev)) {
+	error = input_register_device(atamouse_dev);
+	if (error) {
 		input_free_device(atamouse_dev);
-		return -ENOMEM;
+		return error;
 	}
 
 	return 0;
diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c
index 27f88fb..e532c48 100644
--- a/drivers/input/mouse/hil_ptr.c
+++ b/drivers/input/mouse/hil_ptr.c
@@ -247,19 +247,24 @@
 
 static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
 {
-	struct hil_ptr	 *ptr;
-	const char	 *txt;
-	unsigned int	 i, naxsets, btntype;
-	uint8_t		 did, *idd;
+	struct hil_ptr	*ptr;
+	const char	*txt;
+	unsigned int	i, naxsets, btntype;
+	uint8_t		did, *idd;
+	int		error;
 
-	if (!(ptr = kzalloc(sizeof(struct hil_ptr), GFP_KERNEL)))
+	ptr = kzalloc(sizeof(struct hil_ptr), GFP_KERNEL);
+	if (!ptr)
 		return -ENOMEM;
 
 	ptr->dev = input_allocate_device();
-	if (!ptr->dev)
+	if (!ptr->dev) {
+		error = -ENOMEM;
 		goto bail0;
+	}
 
-	if (serio_open(serio, driver))
+	error = serio_open(serio, driver);
+	if (error)
 		goto bail1;
 
 	serio_set_drvdata(serio, ptr);
@@ -297,6 +302,7 @@
 	did = ptr->idd[0];
 	idd = ptr->idd + 1;
 	txt = "unknown";
+
 	if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) {
 		ptr->dev->evbit[0] = BIT_MASK(EV_REL);
 		txt = "relative";
@@ -306,8 +312,11 @@
 		ptr->dev->evbit[0] = BIT_MASK(EV_ABS);
 		txt = "absolute";
 	}
-	if (!ptr->dev->evbit[0])
+
+	if (!ptr->dev->evbit[0]) {
+		error = -ENODEV;
 		goto bail2;
+	}
 
 	ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd);
 	if (ptr->nbtn)
@@ -380,13 +389,19 @@
 	ptr->dev->id.version	= 0x0100; /* TODO: get from ptr->rsc */
 	ptr->dev->dev.parent	= &serio->dev;
 
-	input_register_device(ptr->dev);
+	error = input_register_device(ptr->dev);
+	if (error) {
+		printk(KERN_INFO PREFIX "Unable to register input device\n");
+		goto bail2;
+	}
+
 	printk(KERN_INFO "input: %s (%s), ID: %d\n",
 		ptr->dev->name,
 		(btntype == BTN_MOUSE) ? "HIL mouse":"HIL tablet or touchpad",
 		did);
 
 	return 0;
+
  bail2:
 	serio_close(serio);
  bail1:
@@ -394,7 +409,7 @@
  bail0:
 	kfree(ptr);
 	serio_set_drvdata(serio, NULL);
-	return -ENODEV;
+	return error;
 }
 
 static struct serio_device_id hil_ptr_ids[] = {
diff --git a/drivers/input/mouse/inport.c b/drivers/input/mouse/inport.c
index 06c35fc..3827a22 100644
--- a/drivers/input/mouse/inport.c
+++ b/drivers/input/mouse/inport.c
@@ -1,6 +1,4 @@
 /*
- * $Id: inport.c,v 1.11 2001/09/25 10:12:07 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  *
  *  Based on the work of:
diff --git a/drivers/input/mouse/logibm.c b/drivers/input/mouse/logibm.c
index 9ea8955..e241311 100644
--- a/drivers/input/mouse/logibm.c
+++ b/drivers/input/mouse/logibm.c
@@ -1,6 +1,4 @@
 /*
- * $Id: logibm.c,v 1.11 2001/09/25 10:12:07 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  *
  *  Based on the work of:
diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c
index 61cff83..fd09c8d 100644
--- a/drivers/input/mouse/pc110pad.c
+++ b/drivers/input/mouse/pc110pad.c
@@ -1,6 +1,4 @@
 /*
- * $Id: pc110pad.c,v 1.12 2001/09/25 10:12:07 vojtech Exp $
- *
  *  Copyright (c) 2000-2001 Vojtech Pavlik
  *
  *  Based on the work of:
diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c
index ed917bf..17ff137b 100644
--- a/drivers/input/mouse/sermouse.c
+++ b/drivers/input/mouse/sermouse.c
@@ -1,6 +1,4 @@
 /*
- * $Id: sermouse.c,v 1.17 2002/03/13 10:03:43 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  */
 
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index ec4b661..27d70d32 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -190,4 +190,14 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called serio_raw.
 
+config SERIO_XILINX_XPS_PS2
+	tristate "Xilinx XPS PS/2 Controller Support"
+	depends on PPC
+	help
+	  This driver supports XPS PS/2 IP from the Xilinx EDK on
+	  PowerPC platform.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called xilinx_ps2.
+
 endif
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
index 38b8868..9b6c813 100644
--- a/drivers/input/serio/Makefile
+++ b/drivers/input/serio/Makefile
@@ -21,3 +21,4 @@
 obj-$(CONFIG_SERIO_MACEPS2)	+= maceps2.o
 obj-$(CONFIG_SERIO_LIBPS2)	+= libps2.o
 obj-$(CONFIG_SERIO_RAW)		+= serio_raw.o
+obj-$(CONFIG_SERIO_XILINX_XPS_PS2)	+= xilinx_ps2.o
diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c
index 0d35018..d1380fc 100644
--- a/drivers/input/serio/ct82c710.c
+++ b/drivers/input/serio/ct82c710.c
@@ -1,6 +1,4 @@
 /*
- * $Id: ct82c710.c,v 1.11 2001/09/25 10:12:07 vojtech Exp $
- *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  */
 
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index 93a1a6b..37586a6 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -76,7 +76,7 @@
 static int			hil_mlcs_probe;
 
 static void hil_mlcs_process(unsigned long unused);
-DECLARE_TASKLET_DISABLED(hil_mlcs_tasklet, hil_mlcs_process, 0);
+static DECLARE_TASKLET_DISABLED(hil_mlcs_tasklet, hil_mlcs_process, 0);
 
 
 /* #define HIL_MLC_DEBUG */
@@ -459,7 +459,7 @@
 #define OUT_LAST(pack) \
 { HILSE_OUT_LAST,	{ .packet = pack }, 0, 0, 0, 0 },
 
-const struct hilse_node hil_mlc_se[HILSEN_END] = {
+static const struct hilse_node hil_mlc_se[HILSEN_END] = {
 
 	/* 0  HILSEN_START */
 	FUNC(hilse_init_lcv, 0,	HILSEN_NEXT,	HILSEN_SLEEP,	0)
@@ -784,7 +784,7 @@
 
 /************************* Keepalive timer task *********************/
 
-void hil_mlcs_timer(unsigned long data)
+static void hil_mlcs_timer(unsigned long data)
 {
 	hil_mlcs_probe = 1;
 	tasklet_schedule(&hil_mlcs_tasklet);
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index edfedd9..7b233a4 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -105,6 +105,10 @@
 EXPORT_SYMBOL(hp_sdc_enqueue_transaction);
 EXPORT_SYMBOL(hp_sdc_dequeue_transaction);
 
+static unsigned int hp_sdc_disabled;
+module_param_named(no_hpsdc, hp_sdc_disabled, bool, 0);
+MODULE_PARM_DESC(no_hpsdc, "Do not enable HP SDC driver.");
+
 static hp_i8042_sdc	hp_sdc;	/* All driver state is kept in here. */
 
 /*************** primitives for use in any context *********************/
@@ -980,6 +984,11 @@
 	unsigned char i;
 #endif
 
+	if (hp_sdc_disabled) {
+		printk(KERN_WARNING PREFIX "HP SDC driver disabled by no_hpsdc=1.\n");
+		return -ENODEV;
+	}
+
 	hp_sdc.dev = NULL;
 	hp_sdc.dev_err = 0;
 #if defined(__hppa__)
diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c
index 587398f..b587e2d 100644
--- a/drivers/input/serio/hp_sdc_mlc.c
+++ b/drivers/input/serio/hp_sdc_mlc.c
@@ -50,7 +50,7 @@
 MODULE_DESCRIPTION("Glue for onboard HIL MLC in HP-PARISC machines");
 MODULE_LICENSE("Dual BSD/GPL");
 
-struct hp_sdc_mlc_priv_s {
+static struct hp_sdc_mlc_priv_s {
 	int emtestmode;
 	hp_sdc_transaction trans;
 	u8 tseq[16];
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 78eb784..fe732a5 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -63,13 +63,22 @@
 	outb(val, I8042_COMMAND_REG);
 }
 
-#if defined(__i386__) || defined(__x86_64__)
+#ifdef CONFIG_X86
 
 #include <linux/dmi.h>
 
 static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = {
 	{
 		/* AUX LOOP command does not raise AUX IRQ */
+		.ident = "Arima-Rioworks HDAMB",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "RIOWORKS"),
+			DMI_MATCH(DMI_BOARD_NAME, "HDAMB"),
+			DMI_MATCH(DMI_BOARD_VERSION, "Rev E"),
+		},
+	},
+	{
+		/* AUX LOOP command does not raise AUX IRQ */
 		.ident = "ASUS P65UP5",
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
@@ -118,6 +127,14 @@
 			DMI_MATCH(DMI_PRODUCT_VERSION, "VS2005R2"),
 		},
 	},
+	{
+		.ident = "Medion MAM 2070",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "MAM 2070"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "5a"),
+		},
+	},
 	{ }
 };
 
@@ -291,17 +308,36 @@
 			DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"),
 		},
 	},
+	{
+		.ident = "Acer Aspire 1360",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1360"),
+		},
+	},
+	{
+		.ident = "Gericom Bellagio",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Gericom"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "N34AS6"),
+		},
+	},
 	{ }
 };
 
-
-
+#ifdef CONFIG_PNP
+static struct dmi_system_id __initdata i8042_dmi_nopnp_table[] = {
+	{
+		.ident = "Intel MBO Desktop D845PESV",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_NAME, "D845PESV"),
+			DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
+		},
+	},
+	{ }
+};
 #endif
 
-#ifdef CONFIG_X86
-
-#include <linux/dmi.h>
-
 /*
  * Some Wistron based laptops need us to explicitly enable the 'Dritek
  * keyboard extension' to make their extra keys start generating scancodes.
@@ -331,6 +367,13 @@
 		},
 	},
 	{
+		.ident = "Acer Aspire 5720",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5720"),
+		},
+	},
+	{
 		.ident = "Acer Aspire 9110",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
@@ -356,7 +399,6 @@
 
 #endif /* CONFIG_X86 */
 
-
 #ifdef CONFIG_PNP
 #include <linux/pnp.h>
 
@@ -466,6 +508,11 @@
 	int pnp_data_busted = 0;
 	int err;
 
+#ifdef CONFIG_X86
+	if (dmi_check_system(i8042_dmi_nopnp_table))
+		i8042_nopnp = 1;
+#endif
+
 	if (i8042_nopnp) {
 		printk(KERN_INFO "i8042: PNP detection disabled\n");
 		return 0;
@@ -591,15 +638,13 @@
         i8042_reset = 1;
 #endif
 
-#if defined(__i386__) || defined(__x86_64__)
+#ifdef CONFIG_X86
 	if (dmi_check_system(i8042_dmi_noloop_table))
 		i8042_noloop = 1;
 
 	if (dmi_check_system(i8042_dmi_nomux_table))
 		i8042_nomux = 1;
-#endif
 
-#ifdef CONFIG_X86
 	if (dmi_check_system(i8042_dmi_dritek_table))
 		i8042_dritek = 1;
 #endif /* CONFIG_X86 */
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index b819239..2b304c2 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -26,15 +26,6 @@
 MODULE_DESCRIPTION("PS/2 driver library");
 MODULE_LICENSE("GPL");
 
-/* Work structure to schedule execution of a command */
-struct ps2work {
-	struct work_struct work;
-	struct ps2dev *ps2dev;
-	int command;
-	unsigned char param[0];
-};
-
-
 /*
  * ps2_sendbyte() sends a byte to the device and waits for acknowledge.
  * It doesn't handle retransmission, though it could - because if there
@@ -246,49 +237,6 @@
 EXPORT_SYMBOL(ps2_command);
 
 /*
- * ps2_execute_scheduled_command() sends a command, previously scheduled by
- * ps2_schedule_command(), to a PS/2 device (keyboard, mouse, etc.)
- */
-
-static void ps2_execute_scheduled_command(struct work_struct *work)
-{
-	struct ps2work *ps2work = container_of(work, struct ps2work, work);
-
-	ps2_command(ps2work->ps2dev, ps2work->param, ps2work->command);
-	kfree(ps2work);
-}
-
-/*
- * ps2_schedule_command() allows to schedule delayed execution of a PS/2
- * command and can be used to issue a command from an interrupt or softirq
- * context.
- */
-
-int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int command)
-{
-	struct ps2work *ps2work;
-	int send = (command >> 12) & 0xf;
-	int receive = (command >> 8) & 0xf;
-
-	if (!(ps2work = kmalloc(sizeof(struct ps2work) + max(send, receive), GFP_ATOMIC)))
-		return -1;
-
-	memset(ps2work, 0, sizeof(struct ps2work));
-	ps2work->ps2dev = ps2dev;
-	ps2work->command = command;
-	memcpy(ps2work->param, param, send);
-	INIT_WORK(&ps2work->work, ps2_execute_scheduled_command);
-
-	if (!schedule_work(&ps2work->work)) {
-		kfree(ps2work);
-		return -1;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(ps2_schedule_command);
-
-/*
  * ps2_init() initializes ps2dev structure
  */
 
diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c
index d962a8d..e36a090 100644
--- a/drivers/input/serio/q40kbd.c
+++ b/drivers/input/serio/q40kbd.c
@@ -1,6 +1,4 @@
 /*
- * $Id: q40kbd.c,v 1.12 2002/02/02 22:26:44 vojtech Exp $
- *
  *  Copyright (c) 2000-2001 Vojtech Pavlik
  *
  *  Based on the work of:
@@ -49,7 +47,7 @@
 MODULE_DESCRIPTION("Q40 PS/2 keyboard controller driver");
 MODULE_LICENSE("GPL");
 
-DEFINE_SPINLOCK(q40kbd_lock);
+static DEFINE_SPINLOCK(q40kbd_lock);
 static struct serio *q40kbd_port;
 static struct platform_device *q40kbd_device;
 
diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c
index 34c59d9..1567b77 100644
--- a/drivers/input/serio/rpckbd.c
+++ b/drivers/input/serio/rpckbd.c
@@ -1,6 +1,4 @@
 /*
- * $Id: rpckbd.c,v 1.7 2001/09/25 10:12:07 vojtech Exp $
- *
  *  Copyright (c) 2000-2001 Vojtech Pavlik
  *  Copyright (c) 2002 Russell King
  */
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 7f52938..78f2abb 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -331,9 +331,10 @@
 }
 
 /*
- * Remove all events that have been submitted for a given serio port.
+ * Remove all events that have been submitted for a given
+ * object, be it serio port or driver.
  */
-static void serio_remove_pending_events(struct serio *serio)
+static void serio_remove_pending_events(void *object)
 {
 	struct list_head *node, *next;
 	struct serio_event *event;
@@ -343,7 +344,7 @@
 
 	list_for_each_safe(node, next, &serio_event_list) {
 		event = list_entry(node, struct serio_event, node);
-		if (event->object == serio) {
+		if (event->object == object) {
 			list_del_init(node);
 			serio_free_event(event);
 		}
@@ -837,7 +838,9 @@
 	struct serio *serio;
 
 	mutex_lock(&serio_mutex);
+
 	drv->manual_bind = 1;	/* so serio_find_driver ignores it */
+	serio_remove_pending_events(drv);
 
 start_over:
 	list_for_each_entry(serio, &serio_list, node) {
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c
new file mode 100644
index 0000000..0ed044d
--- /dev/null
+++ b/drivers/input/serio/xilinx_ps2.c
@@ -0,0 +1,380 @@
+/*
+ * Xilinx XPS PS/2 device driver
+ *
+ * (c) 2005 MontaVista Software, Inc.
+ * (c) 2008 Xilinx, 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.
+ *
+ * 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/serio.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/io.h>
+
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+
+#define DRIVER_NAME		"xilinx_ps2"
+
+/* Register offsets for the xps2 device */
+#define XPS2_SRST_OFFSET	0x00000000 /* Software Reset register */
+#define XPS2_STATUS_OFFSET	0x00000004 /* Status register */
+#define XPS2_RX_DATA_OFFSET	0x00000008 /* Receive Data register */
+#define XPS2_TX_DATA_OFFSET	0x0000000C /* Transmit Data register */
+#define XPS2_GIER_OFFSET	0x0000002C /* Global Interrupt Enable reg */
+#define XPS2_IPISR_OFFSET	0x00000030 /* Interrupt Status register */
+#define XPS2_IPIER_OFFSET	0x00000038 /* Interrupt Enable register */
+
+/* Reset Register Bit Definitions */
+#define XPS2_SRST_RESET		0x0000000A /* Software Reset  */
+
+/* Status Register Bit Positions */
+#define XPS2_STATUS_RX_FULL	0x00000001 /* Receive Full  */
+#define XPS2_STATUS_TX_FULL	0x00000002 /* Transmit Full  */
+
+/* Bit definitions for ISR/IER registers. Both the registers have the same bit
+ * definitions and are only defined once. */
+#define XPS2_IPIXR_WDT_TOUT	0x00000001 /* Watchdog Timeout Interrupt */
+#define XPS2_IPIXR_TX_NOACK	0x00000002 /* Transmit No ACK Interrupt */
+#define XPS2_IPIXR_TX_ACK	0x00000004 /* Transmit ACK (Data) Interrupt */
+#define XPS2_IPIXR_RX_OVF	0x00000008 /* Receive Overflow Interrupt */
+#define XPS2_IPIXR_RX_ERR	0x00000010 /* Receive Error Interrupt */
+#define XPS2_IPIXR_RX_FULL	0x00000020 /* Receive Data Interrupt */
+
+/* Mask for all the Transmit Interrupts */
+#define XPS2_IPIXR_TX_ALL	(XPS2_IPIXR_TX_NOACK | XPS2_IPIXR_TX_ACK)
+
+/* Mask for all the Receive Interrupts */
+#define XPS2_IPIXR_RX_ALL	(XPS2_IPIXR_RX_OVF | XPS2_IPIXR_RX_ERR |  \
+					XPS2_IPIXR_RX_FULL)
+
+/* Mask for all the Interrupts */
+#define XPS2_IPIXR_ALL		(XPS2_IPIXR_TX_ALL | XPS2_IPIXR_RX_ALL |  \
+					XPS2_IPIXR_WDT_TOUT)
+
+/* Global Interrupt Enable mask */
+#define XPS2_GIER_GIE_MASK	0x80000000
+
+struct xps2data {
+	int irq;
+	u32 phys_addr;
+	u32 remap_size;
+	spinlock_t lock;
+	u8 rxb;				/* Rx buffer */
+	void __iomem *base_address;	/* virt. address of control registers */
+	unsigned int dfl;
+	struct serio serio;		/* serio */
+};
+
+/************************************/
+/* XPS PS/2 data transmission calls */
+/************************************/
+
+/*
+ * xps2_recv() will attempt to receive a byte of data from the PS/2 port.
+ */
+static int xps2_recv(struct xps2data *drvdata, u8 *byte)
+{
+	u32 sr;
+	int status = -1;
+
+	/* If there is data available in the PS/2 receiver, read it */
+	sr = in_be32(drvdata->base_address + XPS2_STATUS_OFFSET);
+	if (sr & XPS2_STATUS_RX_FULL) {
+		*byte = in_be32(drvdata->base_address + XPS2_RX_DATA_OFFSET);
+		status = 0;
+	}
+
+	return status;
+}
+
+/*********************/
+/* Interrupt handler */
+/*********************/
+static irqreturn_t xps2_interrupt(int irq, void *dev_id)
+{
+	struct xps2data *drvdata = dev_id;
+	u32 intr_sr;
+	u8 c;
+	int status;
+
+	/* Get the PS/2 interrupts and clear them */
+	intr_sr = in_be32(drvdata->base_address + XPS2_IPISR_OFFSET);
+	out_be32(drvdata->base_address + XPS2_IPISR_OFFSET, intr_sr);
+
+	/* Check which interrupt is active */
+	if (intr_sr & XPS2_IPIXR_RX_OVF)
+		printk(KERN_WARNING "%s: receive overrun error\n",
+			drvdata->serio.name);
+
+	if (intr_sr & XPS2_IPIXR_RX_ERR)
+		drvdata->dfl |= SERIO_PARITY;
+
+	if (intr_sr & (XPS2_IPIXR_TX_NOACK | XPS2_IPIXR_WDT_TOUT))
+		drvdata->dfl |= SERIO_TIMEOUT;
+
+	if (intr_sr & XPS2_IPIXR_RX_FULL) {
+		status = xps2_recv(drvdata, &drvdata->rxb);
+
+		/* Error, if a byte is not received */
+		if (status) {
+			printk(KERN_ERR
+				"%s: wrong rcvd byte count (%d)\n",
+				drvdata->serio.name, status);
+		} else {
+			c = drvdata->rxb;
+			serio_interrupt(&drvdata->serio, c, drvdata->dfl);
+			drvdata->dfl = 0;
+		}
+	}
+
+	if (intr_sr & XPS2_IPIXR_TX_ACK)
+		drvdata->dfl = 0;
+
+	return IRQ_HANDLED;
+}
+
+/*******************/
+/* serio callbacks */
+/*******************/
+
+/*
+ * sxps2_write() sends a byte out through the PS/2 interface.
+ */
+static int sxps2_write(struct serio *pserio, unsigned char c)
+{
+	struct xps2data *drvdata = pserio->port_data;
+	unsigned long flags;
+	u32 sr;
+	int status = -1;
+
+	spin_lock_irqsave(&drvdata->lock, flags);
+
+	/* If the PS/2 transmitter is empty send a byte of data */
+	sr = in_be32(drvdata->base_address + XPS2_STATUS_OFFSET);
+	if (!(sr & XPS2_STATUS_TX_FULL)) {
+		out_be32(drvdata->base_address + XPS2_TX_DATA_OFFSET, c);
+		status = 0;
+	}
+
+	spin_unlock_irqrestore(&drvdata->lock, flags);
+
+	return status;
+}
+
+/*
+ * sxps2_open() is called when a port is open by the higher layer.
+ */
+static int sxps2_open(struct serio *pserio)
+{
+	struct xps2data *drvdata = pserio->port_data;
+	int retval;
+
+	retval = request_irq(drvdata->irq, &xps2_interrupt, 0,
+				DRIVER_NAME, drvdata);
+	if (retval) {
+		printk(KERN_ERR
+			"%s: Couldn't allocate interrupt %d\n",
+			drvdata->serio.name, drvdata->irq);
+		return retval;
+	}
+
+	/* start reception by enabling the interrupts */
+	out_be32(drvdata->base_address + XPS2_GIER_OFFSET, XPS2_GIER_GIE_MASK);
+	out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, XPS2_IPIXR_RX_ALL);
+	(void)xps2_recv(drvdata, &drvdata->rxb);
+
+	return 0;		/* success */
+}
+
+/*
+ * sxps2_close() frees the interrupt.
+ */
+static void sxps2_close(struct serio *pserio)
+{
+	struct xps2data *drvdata = pserio->port_data;
+
+	/* Disable the PS2 interrupts */
+	out_be32(drvdata->base_address + XPS2_GIER_OFFSET, 0x00);
+	out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, 0x00);
+	free_irq(drvdata->irq, drvdata);
+}
+
+/*********************/
+/* Device setup code */
+/*********************/
+
+static int xps2_setup(struct device *dev, struct resource *regs_res,
+		      struct resource *irq_res)
+{
+	struct xps2data *drvdata;
+	struct serio *serio;
+	unsigned long remap_size;
+	int retval;
+
+	if (!dev)
+		return -EINVAL;
+
+	if (!regs_res || !irq_res) {
+		dev_err(dev, "IO resource(s) not found\n");
+		return -EINVAL;
+	}
+
+	drvdata = kzalloc(sizeof(struct xps2data), GFP_KERNEL);
+	if (!drvdata) {
+		dev_err(dev, "Couldn't allocate device private record\n");
+		return -ENOMEM;
+	}
+
+	dev_set_drvdata(dev, drvdata);
+
+	spin_lock_init(&drvdata->lock);
+	drvdata->irq = irq_res->start;
+
+	remap_size = regs_res->end - regs_res->start + 1;
+	if (!request_mem_region(regs_res->start, remap_size, DRIVER_NAME)) {
+		dev_err(dev, "Couldn't lock memory region at 0x%08X\n",
+			(unsigned int)regs_res->start);
+		retval = -EBUSY;
+		goto failed1;
+	}
+
+	/* Fill in configuration data and add them to the list */
+	drvdata->phys_addr = regs_res->start;
+	drvdata->remap_size = remap_size;
+	drvdata->base_address = ioremap(regs_res->start, remap_size);
+	if (drvdata->base_address == NULL) {
+		dev_err(dev, "Couldn't ioremap memory at 0x%08X\n",
+			(unsigned int)regs_res->start);
+		retval = -EFAULT;
+		goto failed2;
+	}
+
+	/* Disable all the interrupts, just in case */
+	out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, 0);
+
+	/* Reset the PS2 device and abort any current transaction, to make sure
+	 * we have the PS2 in a good state */
+	out_be32(drvdata->base_address + XPS2_SRST_OFFSET, XPS2_SRST_RESET);
+
+	dev_info(dev, "Xilinx PS2 at 0x%08X mapped to 0x%08X, irq=%d\n",
+		drvdata->phys_addr, (u32)drvdata->base_address, drvdata->irq);
+
+	serio = &drvdata->serio;
+	serio->id.type = SERIO_8042;
+	serio->write = sxps2_write;
+	serio->open = sxps2_open;
+	serio->close = sxps2_close;
+	serio->port_data = drvdata;
+	serio->dev.parent = dev;
+	snprintf(serio->name, sizeof(serio->name),
+		 "Xilinx XPS PS/2 at %08X", drvdata->phys_addr);
+	snprintf(serio->phys, sizeof(serio->phys),
+		 "xilinxps2/serio at %08X", drvdata->phys_addr);
+	serio_register_port(serio);
+
+	return 0;		/* success */
+
+failed2:
+	release_mem_region(regs_res->start, remap_size);
+failed1:
+	kfree(drvdata);
+	dev_set_drvdata(dev, NULL);
+
+	return retval;
+}
+
+/***************************/
+/* OF Platform Bus Support */
+/***************************/
+
+static int __devinit xps2_of_probe(struct of_device *ofdev, const struct
+				   of_device_id * match)
+{
+	struct resource r_irq; /* Interrupt resources */
+	struct resource r_mem; /* IO mem resources */
+	int rc = 0;
+
+	printk(KERN_INFO "Device Tree Probing \'%s\'\n",
+			ofdev->node->name);
+
+	/* Get iospace for the device */
+	rc = of_address_to_resource(ofdev->node, 0, &r_mem);
+	if (rc) {
+		dev_err(&ofdev->dev, "invalid address\n");
+		return rc;
+	}
+
+	/* Get IRQ for the device */
+	rc = of_irq_to_resource(ofdev->node, 0, &r_irq);
+	if (rc == NO_IRQ) {
+		dev_err(&ofdev->dev, "no IRQ found\n");
+		return rc;
+	}
+
+	return xps2_setup(&ofdev->dev, &r_mem, &r_irq);
+}
+
+static int __devexit xps2_of_remove(struct of_device *of_dev)
+{
+	struct device *dev = &of_dev->dev;
+	struct xps2data *drvdata;
+
+	if (!dev)
+		return -EINVAL;
+
+	drvdata = dev_get_drvdata(dev);
+
+	serio_unregister_port(&drvdata->serio);
+	iounmap(drvdata->base_address);
+	release_mem_region(drvdata->phys_addr, drvdata->remap_size);
+	kfree(drvdata);
+
+	dev_set_drvdata(dev, NULL);
+
+	return 0;		/* success */
+}
+
+/* Match table for of_platform binding */
+static struct of_device_id xps2_of_match[] __devinitdata = {
+	{ .compatible = "xlnx,xps-ps2-1.00.a", },
+	{ /* end of list */ },
+};
+MODULE_DEVICE_TABLE(of, xps2_of_match);
+
+static struct of_platform_driver xps2_of_driver = {
+	.name		= DRIVER_NAME,
+	.match_table	= xps2_of_match,
+	.probe		= xps2_of_probe,
+	.remove		= __devexit_p(xps2_of_remove),
+};
+
+static int __init xps2_init(void)
+{
+	return of_register_platform_driver(&xps2_of_driver);
+}
+
+static void __exit xps2_cleanup(void)
+{
+	of_unregister_platform_driver(&xps2_of_driver);
+}
+
+module_init(xps2_init);
+module_exit(xps2_cleanup);
+
+MODULE_AUTHOR("Xilinx, Inc.");
+MODULE_DESCRIPTION("Xilinx XPS PS/2 driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/input/tablet/acecad.c b/drivers/input/tablet/acecad.c
index b973d0e..570e0e8 100644
--- a/drivers/input/tablet/acecad.c
+++ b/drivers/input/tablet/acecad.c
@@ -73,10 +73,10 @@
 		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", __func__, urb->status);
 			return;
 		default:
-			dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+			dbg("%s - nonzero urb status received: %d", __func__, urb->status);
 			goto resubmit;
 	}
 
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c
index 55c1134..8f037a1 100644
--- a/drivers/input/tablet/aiptek.c
+++ b/drivers/input/tablet/aiptek.c
@@ -449,12 +449,12 @@
 	case -ESHUTDOWN:
 		/* This urb is terminated, clean up */
 		dbg("%s - urb shutting down with status: %d",
-		    __FUNCTION__, urb->status);
+		    __func__, urb->status);
 		return;
 
 	default:
 		dbg("%s - nonzero urb status received: %d",
-		    __FUNCTION__, urb->status);
+		    __func__, urb->status);
 		goto exit;
 	}
 
@@ -813,7 +813,7 @@
 	retval = usb_submit_urb(urb, GFP_ATOMIC);
 	if (retval != 0) {
 		err("%s - usb_submit_urb failed with result %d",
-		    __FUNCTION__, retval);
+		    __func__, retval);
 	}
 }
 
diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c
index 1e748e4..b9b7a98 100644
--- a/drivers/input/tablet/gtco.c
+++ b/drivers/input/tablet/gtco.c
@@ -863,7 +863,7 @@
 	gtco->urbinfo = usb_alloc_urb(0, GFP_KERNEL);
 	if (!gtco->urbinfo) {
 		err("Failed to allocate URB");
-		return -ENOMEM;
+		error = -ENOMEM;
 		goto err_free_buf;
 	}
 
diff --git a/drivers/input/tablet/kbtab.c b/drivers/input/tablet/kbtab.c
index f23f5a9..d89112f 100644
--- a/drivers/input/tablet/kbtab.c
+++ b/drivers/input/tablet/kbtab.c
@@ -56,10 +56,10 @@
 	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", __func__, urb->status);
 		return;
 	default:
-		dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+		dbg("%s - nonzero urb status received: %d", __func__, urb->status);
 		goto exit;
 	}
 
@@ -88,7 +88,7 @@
 	retval = usb_submit_urb (urb, GFP_ATOMIC);
 	if (retval)
 		err ("%s - usb_submit_urb failed with result %d",
-		     __FUNCTION__, retval);
+		     __func__, retval);
 }
 
 static struct usb_device_id kbtab_ids[] = {
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index 706619d..ca62ec6 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -105,7 +105,7 @@
 	struct urb *irq;
 	struct wacom_wac * wacom_wac;
 	struct mutex lock;
-	int open:1;
+	unsigned int open:1;
 	char phys[32];
 };
 
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 71cc0c1..5fbc463 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -56,10 +56,10 @@
 	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", __func__, urb->status);
 		return;
 	default:
-		dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+		dbg("%s - nonzero urb status received: %d", __func__, urb->status);
 		goto exit;
 	}
 
@@ -74,7 +74,7 @@
 	retval = usb_submit_urb (urb, GFP_ATOMIC);
 	if (retval)
 		err ("%s - usb_submit_urb failed with result %d",
-		     __FUNCTION__, retval);
+		     __func__, retval);
 }
 
 void wacom_report_key(void *wcombo, unsigned int key_type, int key_data)
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 192513e..bf3d9a8 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -56,7 +56,7 @@
 static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo)
 {
 	unsigned char *data = wacom->data;
-	int prox, id, pressure;
+	int prox, pressure;
 
 	if (data[0] != 2) {
 		dbg("wacom_pl_irq: received unknown report #%d", data[0]);
@@ -65,7 +65,7 @@
 
 	prox = data[1] & 0x40;
 
-	id = ERASER_DEVICE_ID;
+	wacom->id[0] = ERASER_DEVICE_ID;
 	if (prox) {
 
 		pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
@@ -99,10 +99,10 @@
 		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->id[0] = 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_MISC, wacom->id[0]); /* 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);
@@ -127,7 +127,6 @@
 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]);
@@ -137,13 +136,13 @@
 	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;
+		wacom->id[0] = 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->id[0] = STYLUS_DEVICE_ID;
 	}
-	wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */
+	wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* 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]));
@@ -155,27 +154,26 @@
 static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
 {
 	unsigned char *data = wacom->data;
-	int x, y, id, rw;
+	int x, y, rw;
 
 	if (data[0] != 2) {
 		dbg("wacom_graphire_irq: received unknown report #%d", data[0]);
 		return 0;
 	}
 
-	id = STYLUS_DEVICE_ID;
-	if ((data[1] & 0x80) && ((data[1] & 0x07) || data[2] || data[3] || data[4]
-			|| data[5] || data[6] || (data[7] & 0x07))) {
+	if (data[1] & 0x80) {
 		/* in prox and not a pad data */
 
 		switch ((data[1] >> 5) & 3) {
 
 			case 0:	/* Pen */
 				wacom->tool[0] = BTN_TOOL_PEN;
+				wacom->id[0] = STYLUS_DEVICE_ID;
 				break;
 
 			case 1: /* Rubber */
 				wacom->tool[0] = BTN_TOOL_RUBBER;
-				id = ERASER_DEVICE_ID;
+				wacom->id[0] = ERASER_DEVICE_ID;
 				break;
 
 			case 2: /* Mouse with wheel */
@@ -190,7 +188,7 @@
 
 			case 3: /* Mouse without wheel */
 				wacom->tool[0] = BTN_TOOL_MOUSE;
-				id = CURSOR_DEVICE_ID;
+				wacom->id[0] = 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 ||
@@ -210,9 +208,9 @@
 			wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);
 			wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04);
 		}
-		wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */
+		wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */
 		wacom_report_key(wcombo, wacom->tool[0], 1);
-	} else if (!(data[1] & 0x90)) {
+	} else if (wacom->id[0]) {
 		wacom_report_abs(wcombo, ABS_X, 0);
 		wacom_report_abs(wcombo, ABS_Y, 0);
 		if (wacom->tool[0] == BTN_TOOL_MOUSE) {
@@ -225,6 +223,7 @@
 			wacom_report_key(wcombo, BTN_STYLUS, 0);
 			wacom_report_key(wcombo, BTN_STYLUS2, 0);
 		}
+		wacom->id[0] = 0;
 		wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
 		wacom_report_key(wcombo, wacom->tool[0], 0);
 	}
@@ -234,13 +233,13 @@
 	    case WACOM_G4:
 		if (data[7] & 0xf8) {
 			wacom_input_sync(wcombo); /* sync last event */
-			wacom->id[1] = 1;
+			wacom->id[1] = PAD_DEVICE_ID;
 			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_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
+			wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]);
 			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
 		} else if (wacom->id[1]) {
 			wacom_input_sync(wcombo); /* sync last event */
@@ -255,14 +254,14 @@
 	    case WACOM_MO:
 		if ((data[7] & 0xf8) || (data[8] & 0xff)) {
 			wacom_input_sync(wcombo); /* sync last event */
-			wacom->id[1] = 1;
+			wacom->id[1] = PAD_DEVICE_ID;
 			wacom_report_key(wcombo, BTN_0, (data[7] & 0x08));
 			wacom_report_key(wcombo, BTN_1, (data[7] & 0x20));
 			wacom_report_key(wcombo, BTN_4, (data[7] & 0x10));
 			wacom_report_key(wcombo, BTN_5, (data[7] & 0x40));
 			wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f));
 			wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0);
-			wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
+			wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]);
 			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
 		} else if (wacom->id[1]) {
 			wacom_input_sync(wcombo); /* sync last event */
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 565ec71..e573665 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -103,6 +103,18 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called mtouch.
 
+config TOUCHSCREEN_INEXIO
+	tristate "iNexio serial touchscreens"
+	select SERIO
+	help
+	  Say Y here if you have an iNexio serial touchscreen connected to
+	  your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called inexio.
+
 config TOUCHSCREEN_MK712
 	tristate "ICS MicroClock MK712 touchscreen"
 	help
@@ -134,6 +146,18 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called jornada720_ts.
 
+config TOUCHSCREEN_HTCPEN
+	tristate "HTC Shift X9500 touchscreen"
+	depends on ISA
+	help
+	  Say Y here if you have an HTC Shift UMPC also known as HTC X9500
+	  Clio / Shangrila and want to support the built-in touchscreen.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called htcpen.
+
 config TOUCHSCREEN_PENMOUNT
 	tristate "Penmount serial touchscreen"
 	select SERIO
@@ -146,6 +170,17 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called penmount.
 
+config TOUCHSCREEN_MIGOR
+	tristate "Renesas MIGO-R touchscreen"
+	depends on SH_MIGOR && I2C
+	help
+	  Say Y here to enable MIGO-R touchscreen support.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called migor_ts.
+
 config TOUCHSCREEN_TOUCHRIGHT
 	tristate "Touchright serial touchscreen"
 	select SERIO
@@ -316,4 +351,15 @@
 	bool "GoTop Super_Q2/GogoPen/PenPower tablet device support" if EMBEDDED
 	depends on TOUCHSCREEN_USB_COMPOSITE
 
+config TOUCHSCREEN_TOUCHIT213
+	tristate "Sahara TouchIT-213 touchscreen"
+	select SERIO
+	help
+	  Say Y here if you have a Sahara TouchIT-213 Tablet PC.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called touchit213.
+
 endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 3c096d7..39a804c 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -12,12 +12,16 @@
 obj-$(CONFIG_TOUCHSCREEN_GUNZE)		+= gunze.o
 obj-$(CONFIG_TOUCHSCREEN_ELO)		+= elo.o
 obj-$(CONFIG_TOUCHSCREEN_FUJITSU)	+= fujitsu_ts.o
+obj-$(CONFIG_TOUCHSCREEN_INEXIO)	+= inexio.o
+obj-$(CONFIG_TOUCHSCREEN_MIGOR)		+= migor_ts.o
 obj-$(CONFIG_TOUCHSCREEN_MTOUCH)	+= mtouch.o
 obj-$(CONFIG_TOUCHSCREEN_MK712)		+= mk712.o
 obj-$(CONFIG_TOUCHSCREEN_HP600)		+= hp680_ts_input.o
 obj-$(CONFIG_TOUCHSCREEN_HP7XX)		+= jornada720_ts.o
+obj-$(CONFIG_TOUCHSCREEN_HTCPEN)	+= htcpen.o
 obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE)	+= usbtouchscreen.o
 obj-$(CONFIG_TOUCHSCREEN_PENMOUNT)	+= penmount.o
+obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213)	+= touchit213.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)	+= touchright.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)	+= touchwin.o
 obj-$(CONFIG_TOUCHSCREEN_UCB1400)	+= ucb1400_ts.o
diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c
index a48a158..a54f90e0 100644
--- a/drivers/input/touchscreen/gunze.c
+++ b/drivers/input/touchscreen/gunze.c
@@ -1,6 +1,4 @@
 /*
- * $Id: gunze.c,v 1.12 2001/09/25 10:12:07 vojtech Exp $
- *
  *  Copyright (c) 2000-2001 Vojtech Pavlik
  */
 
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c
index 28ae15e..4f86081 100644
--- a/drivers/input/touchscreen/h3600_ts_input.c
+++ b/drivers/input/touchscreen/h3600_ts_input.c
@@ -1,6 +1,4 @@
 /*
- * $Id: h3600_ts_input.c,v 1.4 2002/01/23 06:39:37 jsimmons Exp $
- *
  *  Copyright (c) 2001 "Crazy" James Simmons jsimmons@transvirtual.com
  *
  *  Sponsored by Transvirtual Technology.
diff --git a/drivers/input/touchscreen/htcpen.c b/drivers/input/touchscreen/htcpen.c
new file mode 100644
index 0000000..62811de
--- /dev/null
+++ b/drivers/input/touchscreen/htcpen.c
@@ -0,0 +1,255 @@
+/*
+ * HTC Shift touchscreen driver
+ *
+ * Copyright (C) 2008 Pau Oliva Fora <pof@eslack.org>
+ *
+ * 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/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/isa.h>
+#include <linux/ioport.h>
+#include <linux/dmi.h>
+
+MODULE_AUTHOR("Pau Oliva Fora <pau@eslack.org>");
+MODULE_DESCRIPTION("HTC Shift touchscreen driver");
+MODULE_LICENSE("GPL");
+
+#define HTCPEN_PORT_IRQ_CLEAR	0x068
+#define HTCPEN_PORT_INIT	0x06c
+#define HTCPEN_PORT_INDEX	0x0250
+#define HTCPEN_PORT_DATA	0x0251
+#define HTCPEN_IRQ		3
+
+#define DEVICE_ENABLE		0xa2
+#define DEVICE_DISABLE		0xa3
+
+#define X_INDEX			3
+#define Y_INDEX			5
+#define TOUCH_INDEX		0xb
+#define LSB_XY_INDEX		0xc
+#define X_AXIS_MAX		2040
+#define Y_AXIS_MAX		2040
+
+static int invert_x;
+module_param(invert_x, bool, 0644);
+MODULE_PARM_DESC(invert_x, "If set, X axis is inverted");
+static int invert_y;
+module_param(invert_y, bool, 0644);
+MODULE_PARM_DESC(invert_y, "If set, Y axis is inverted");
+
+static struct pnp_device_id pnp_ids[] = {
+	{ .id = "PNP0cc0" },
+	{ .id = "" }
+};
+MODULE_DEVICE_TABLE(pnp, pnp_ids);
+
+static irqreturn_t htcpen_interrupt(int irq, void *handle)
+{
+	struct input_dev *htcpen_dev = handle;
+	unsigned short x, y, xy;
+
+	/* 0 = press; 1 = release */
+	outb_p(TOUCH_INDEX, HTCPEN_PORT_INDEX);
+
+	if (inb_p(HTCPEN_PORT_DATA)) {
+		input_report_key(htcpen_dev, BTN_TOUCH, 0);
+	} else {
+		outb_p(X_INDEX, HTCPEN_PORT_INDEX);
+		x = inb_p(HTCPEN_PORT_DATA);
+
+		outb_p(Y_INDEX, HTCPEN_PORT_INDEX);
+		y = inb_p(HTCPEN_PORT_DATA);
+
+		outb_p(LSB_XY_INDEX, HTCPEN_PORT_INDEX);
+		xy = inb_p(HTCPEN_PORT_DATA);
+
+		/* get high resolution value of X and Y using LSB */
+		x = X_AXIS_MAX - ((x * 8) + ((xy >> 4) & 0xf));
+		y = (y * 8) + (xy & 0xf);
+		if (invert_x)
+			x = X_AXIS_MAX - x;
+		if (invert_y)
+			y = Y_AXIS_MAX - y;
+
+		if (x != X_AXIS_MAX && x != 0) {
+			input_report_key(htcpen_dev, BTN_TOUCH, 1);
+			input_report_abs(htcpen_dev, ABS_X, x);
+			input_report_abs(htcpen_dev, ABS_Y, y);
+		}
+	}
+
+	input_sync(htcpen_dev);
+
+	inb_p(HTCPEN_PORT_IRQ_CLEAR);
+
+	return IRQ_HANDLED;
+}
+
+static int htcpen_open(struct input_dev *dev)
+{
+	outb_p(DEVICE_ENABLE, HTCPEN_PORT_INIT);
+
+	return 0;
+}
+
+static void htcpen_close(struct input_dev *dev)
+{
+	outb_p(DEVICE_DISABLE, HTCPEN_PORT_INIT);
+	synchronize_irq(HTCPEN_IRQ);
+}
+
+static int __devinit htcpen_isa_probe(struct device *dev, unsigned int id)
+{
+	struct input_dev *htcpen_dev;
+	int err = -EBUSY;
+
+	if (!request_region(HTCPEN_PORT_IRQ_CLEAR, 1, "htcpen")) {
+		printk(KERN_ERR "htcpen: unable to get IO region 0x%x\n",
+			HTCPEN_PORT_IRQ_CLEAR);
+		goto request_region1_failed;
+	}
+
+	if (!request_region(HTCPEN_PORT_INIT, 1, "htcpen")) {
+		printk(KERN_ERR "htcpen: unable to get IO region 0x%x\n",
+			HTCPEN_PORT_INIT);
+		goto request_region2_failed;
+	}
+
+	if (!request_region(HTCPEN_PORT_INDEX, 2, "htcpen")) {
+		printk(KERN_ERR "htcpen: unable to get IO region 0x%x\n",
+			HTCPEN_PORT_INDEX);
+		goto request_region3_failed;
+	}
+
+	htcpen_dev = input_allocate_device();
+	if (!htcpen_dev) {
+		printk(KERN_ERR "htcpen: can't allocate device\n");
+		err = -ENOMEM;
+		goto input_alloc_failed;
+	}
+
+	htcpen_dev->name = "HTC Shift EC TouchScreen";
+	htcpen_dev->id.bustype = BUS_ISA;
+
+	htcpen_dev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
+	htcpen_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+	input_set_abs_params(htcpen_dev, ABS_X, 0, X_AXIS_MAX, 0, 0);
+	input_set_abs_params(htcpen_dev, ABS_Y, 0, Y_AXIS_MAX, 0, 0);
+
+	htcpen_dev->open = htcpen_open;
+	htcpen_dev->close = htcpen_close;
+
+	err = request_irq(HTCPEN_IRQ, htcpen_interrupt, 0, "htcpen",
+			htcpen_dev);
+	if (err) {
+		printk(KERN_ERR "htcpen: irq busy\n");
+		goto request_irq_failed;
+	}
+
+	inb_p(HTCPEN_PORT_IRQ_CLEAR);
+
+	err = input_register_device(htcpen_dev);
+	if (err)
+		goto input_register_failed;
+
+	dev_set_drvdata(dev, htcpen_dev);
+
+	return 0;
+
+ input_register_failed:
+	free_irq(HTCPEN_IRQ, htcpen_dev);
+ request_irq_failed:
+	input_free_device(htcpen_dev);
+ input_alloc_failed:
+	release_region(HTCPEN_PORT_INDEX, 2);
+ request_region3_failed:
+	release_region(HTCPEN_PORT_INIT, 1);
+ request_region2_failed:
+	release_region(HTCPEN_PORT_IRQ_CLEAR, 1);
+ request_region1_failed:
+	return err;
+}
+
+static int __devexit htcpen_isa_remove(struct device *dev, unsigned int id)
+{
+	struct input_dev *htcpen_dev = dev_get_drvdata(dev);
+
+	input_unregister_device(htcpen_dev);
+
+	free_irq(HTCPEN_IRQ, htcpen_dev);
+
+	release_region(HTCPEN_PORT_INDEX, 2);
+	release_region(HTCPEN_PORT_INIT, 1);
+	release_region(HTCPEN_PORT_IRQ_CLEAR, 1);
+
+	dev_set_drvdata(dev, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int htcpen_isa_suspend(struct device *dev, unsigned int n,
+				pm_message_t state)
+{
+	outb_p(DEVICE_DISABLE, HTCPEN_PORT_INIT);
+
+	return 0;
+}
+
+static int htcpen_isa_resume(struct device *dev, unsigned int n)
+{
+	outb_p(DEVICE_ENABLE, HTCPEN_PORT_INIT);
+
+	return 0;
+}
+#endif
+
+static struct isa_driver htcpen_isa_driver = {
+	.probe		= htcpen_isa_probe,
+	.remove		= __devexit_p(htcpen_isa_remove),
+#ifdef CONFIG_PM
+	.suspend	= htcpen_isa_suspend,
+	.resume		= htcpen_isa_resume,
+#endif
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "htcpen",
+	}
+};
+
+static struct dmi_system_id __initdata htcshift_dmi_table[] = {
+	{
+		.ident = "Shift",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "High Tech Computer Corp"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Shift"),
+		},
+	},
+	{ }
+};
+
+static int __init htcpen_isa_init(void)
+{
+	if (!dmi_check_system(htcshift_dmi_table))
+		return -ENODEV;
+
+	return isa_register_driver(&htcpen_isa_driver, 1);
+}
+
+static void __exit htcpen_isa_exit(void)
+{
+	isa_unregister_driver(&htcpen_isa_driver);
+}
+
+module_init(htcpen_isa_init);
+module_exit(htcpen_isa_exit);
diff --git a/drivers/input/touchscreen/inexio.c b/drivers/input/touchscreen/inexio.c
new file mode 100644
index 0000000..192ade0
--- /dev/null
+++ b/drivers/input/touchscreen/inexio.c
@@ -0,0 +1,207 @@
+/*
+ * iNexio serial touchscreen driver
+ *
+ * Copyright (c) 2008 Richard Lemon
+ * Based on the mtouch driver (c) Vojtech Pavlik and Dan Streetman
+ *
+ */
+
+/*
+ * 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.
+ */
+
+/*
+ * 2008/06/19 Richard Lemon <richard@codelemon.com>
+ *   Copied mtouch.c and edited for iNexio protocol
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+
+#define DRIVER_DESC	"iNexio serial touchscreen driver"
+
+MODULE_AUTHOR("Richard Lemon <richard@codelemon.com>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+/*
+ * Definitions & global arrays.
+ */
+
+#define INEXIO_FORMAT_TOUCH_BIT 0x01
+#define INEXIO_FORMAT_LENGTH 5
+#define INEXIO_RESPONSE_BEGIN_BYTE 0x80
+
+/* todo: check specs for max length of all responses */
+#define INEXIO_MAX_LENGTH 16
+
+#define INEXIO_MIN_XC 0
+#define INEXIO_MAX_XC 0x3fff
+#define INEXIO_MIN_YC 0
+#define INEXIO_MAX_YC 0x3fff
+
+#define INEXIO_GET_XC(data) (((data[1])<<7) | data[2])
+#define INEXIO_GET_YC(data) (((data[3])<<7) | data[4])
+#define INEXIO_GET_TOUCHED(data) (INEXIO_FORMAT_TOUCH_BIT & data[0])
+
+/*
+ * Per-touchscreen data.
+ */
+
+struct inexio {
+	struct input_dev *dev;
+	struct serio *serio;
+	int idx;
+	unsigned char data[INEXIO_MAX_LENGTH];
+	char phys[32];
+};
+
+static void inexio_process_data(struct inexio *pinexio)
+{
+	struct input_dev *dev = pinexio->dev;
+
+	if (INEXIO_FORMAT_LENGTH == ++pinexio->idx) {
+		input_report_abs(dev, ABS_X, INEXIO_GET_XC(pinexio->data));
+		input_report_abs(dev, ABS_Y, INEXIO_GET_YC(pinexio->data));
+		input_report_key(dev, BTN_TOUCH, INEXIO_GET_TOUCHED(pinexio->data));
+		input_sync(dev);
+
+		pinexio->idx = 0;
+	}
+}
+
+static irqreturn_t inexio_interrupt(struct serio *serio,
+		unsigned char data, unsigned int flags)
+{
+	struct inexio* pinexio = serio_get_drvdata(serio);
+
+	pinexio->data[pinexio->idx] = data;
+
+	if (INEXIO_RESPONSE_BEGIN_BYTE&pinexio->data[0])
+		inexio_process_data(pinexio);
+	else
+		printk(KERN_DEBUG "inexio.c: unknown/unsynchronized data from device, byte %x\n",pinexio->data[0]);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * inexio_disconnect() is the opposite of inexio_connect()
+ */
+
+static void inexio_disconnect(struct serio *serio)
+{
+	struct inexio* pinexio = serio_get_drvdata(serio);
+
+	input_get_device(pinexio->dev);
+	input_unregister_device(pinexio->dev);
+	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
+	input_put_device(pinexio->dev);
+	kfree(pinexio);
+}
+
+/*
+ * inexio_connect() is the routine that is called when someone adds a
+ * new serio device that supports iNexio protocol and registers it as
+ * an input device. This is usually accomplished using inputattach.
+ */
+
+static int inexio_connect(struct serio *serio, struct serio_driver *drv)
+{
+	struct inexio *pinexio;
+	struct input_dev *input_dev;
+	int err;
+
+	pinexio = kzalloc(sizeof(struct inexio), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!pinexio || !input_dev) {
+		err = -ENOMEM;
+		goto fail1;
+	}
+
+	pinexio->serio = serio;
+	pinexio->dev = input_dev;
+	snprintf(pinexio->phys, sizeof(pinexio->phys), "%s/input0", serio->phys);
+
+	input_dev->name = "iNexio Serial TouchScreen";
+	input_dev->phys = pinexio->phys;
+	input_dev->id.bustype = BUS_RS232;
+	input_dev->id.vendor = SERIO_INEXIO;
+	input_dev->id.product = 0;
+	input_dev->id.version = 0x0001;
+	input_dev->dev.parent = &serio->dev;
+	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+	input_set_abs_params(pinexio->dev, ABS_X, INEXIO_MIN_XC, INEXIO_MAX_XC, 0, 0);
+	input_set_abs_params(pinexio->dev, ABS_Y, INEXIO_MIN_YC, INEXIO_MAX_YC, 0, 0);
+
+	serio_set_drvdata(serio, pinexio);
+
+	err = serio_open(serio, drv);
+	if (err)
+		goto fail2;
+
+	err = input_register_device(pinexio->dev);
+	if (err)
+		goto fail3;
+
+	return 0;
+
+ fail3:	serio_close(serio);
+ fail2:	serio_set_drvdata(serio, NULL);
+ fail1:	input_free_device(input_dev);
+	kfree(pinexio);
+	return err;
+}
+
+/*
+ * The serio driver structure.
+ */
+
+static struct serio_device_id inexio_serio_ids[] = {
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_INEXIO,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, inexio_serio_ids);
+
+static struct serio_driver inexio_drv = {
+	.driver		= {
+		.name	= "inexio",
+	},
+	.description	= DRIVER_DESC,
+	.id_table	= inexio_serio_ids,
+	.interrupt	= inexio_interrupt,
+	.connect	= inexio_connect,
+	.disconnect	= inexio_disconnect,
+};
+
+/*
+ * The functions for inserting/removing us as a module.
+ */
+
+static int __init inexio_init(void)
+{
+	return serio_register_driver(&inexio_drv);
+}
+
+static void __exit inexio_exit(void)
+{
+	serio_unregister_driver(&inexio_drv);
+}
+
+module_init(inexio_init);
+module_exit(inexio_exit);
diff --git a/drivers/input/touchscreen/migor_ts.c b/drivers/input/touchscreen/migor_ts.c
new file mode 100644
index 0000000..c1cd99d
--- /dev/null
+++ b/drivers/input/touchscreen/migor_ts.c
@@ -0,0 +1,250 @@
+/*
+ * Touch Screen driver for Renesas MIGO-R Platform
+ *
+ * Copyright (c) 2008 Magnus Damm
+ * Copyright (c) 2007 Ujjwal Pande <ujjwal@kenati.com>,
+ *  Kenati Technologies Pvt Ltd.
+ *
+ * This file 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 file 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 library; 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/kernel.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+#include <linux/i2c.h>
+#include <linux/timer.h>
+
+#define EVENT_PENDOWN 1
+#define EVENT_REPEAT  2
+#define EVENT_PENUP   3
+
+struct migor_ts_priv {
+	struct i2c_client *client;
+	struct input_dev *input;
+	struct delayed_work work;
+	int irq;
+};
+
+static const u_int8_t migor_ts_ena_seq[17] = { 0x33, 0x22, 0x11,
+					       0x01, 0x06, 0x07, };
+static const u_int8_t migor_ts_dis_seq[17] = { };
+
+static void migor_ts_poscheck(struct work_struct *work)
+{
+	struct migor_ts_priv *priv = container_of(work,
+						  struct migor_ts_priv,
+						  work.work);
+	unsigned short xpos, ypos;
+	unsigned char event;
+	u_int8_t buf[16];
+
+	memset(buf, 0, sizeof(buf));
+
+	/* Set Index 0 */
+	buf[0] = 0;
+	if (i2c_master_send(priv->client, buf, 1) != 1) {
+		dev_err(&priv->client->dev, "Unable to write i2c index\n");
+		goto out;
+	}
+
+	/* Now do Page Read */
+	if (i2c_master_recv(priv->client, buf, sizeof(buf)) != sizeof(buf)) {
+		dev_err(&priv->client->dev, "Unable to read i2c page\n");
+		goto out;
+	}
+
+	ypos = ((buf[9] & 0x03) << 8 | buf[8]);
+	xpos = ((buf[11] & 0x03) << 8 | buf[10]);
+	event = buf[12];
+
+	if (event == EVENT_PENDOWN || event == EVENT_REPEAT) {
+		input_report_key(priv->input, BTN_TOUCH, 1);
+		input_report_abs(priv->input, ABS_X, ypos); /*X-Y swap*/
+		input_report_abs(priv->input, ABS_Y, xpos);
+		input_sync(priv->input);
+	} else if (event == EVENT_PENUP) {
+		input_report_key(priv->input, BTN_TOUCH, 0);
+		input_sync(priv->input);
+	}
+ out:
+	enable_irq(priv->irq);
+}
+
+static irqreturn_t migor_ts_isr(int irq, void *dev_id)
+{
+	struct migor_ts_priv *priv = dev_id;
+
+	/* the touch screen controller chip is hooked up to the cpu
+	 * using i2c and a single interrupt line. the interrupt line
+	 * is pulled low whenever someone taps the screen. to deassert
+	 * the interrupt line we need to acknowledge the interrupt by
+	 * communicating with the controller over the slow i2c bus.
+	 *
+	 * we can't acknowledge from interrupt context since the i2c
+	 * bus controller may sleep, so we just disable the interrupt
+	 * here and handle the acknowledge using delayed work.
+	 */
+
+	disable_irq_nosync(irq);
+	schedule_delayed_work(&priv->work, HZ / 20);
+
+	return IRQ_HANDLED;
+}
+
+
+static int migor_ts_open(struct input_dev *dev)
+{
+	struct migor_ts_priv *priv = input_get_drvdata(dev);
+	struct i2c_client *client = priv->client;
+	int count;
+
+	/* enable controller */
+	count = i2c_master_send(client, migor_ts_ena_seq,
+				sizeof(migor_ts_ena_seq));
+	if (count != sizeof(migor_ts_ena_seq)) {
+		dev_err(&client->dev, "Unable to enable touchscreen.\n");
+		return -ENXIO;
+	}
+
+	return 0;
+}
+
+static void migor_ts_close(struct input_dev *dev)
+{
+	struct migor_ts_priv *priv = input_get_drvdata(dev);
+	struct i2c_client *client = priv->client;
+
+	disable_irq(priv->irq);
+
+	/* cancel pending work and wait for migor_ts_poscheck() to finish */
+	if (cancel_delayed_work_sync(&priv->work)) {
+		/*
+		 * if migor_ts_poscheck was canceled we need to enable IRQ
+		 * here to balance disable done in migor_ts_isr.
+		 */
+		enable_irq(priv->irq);
+	}
+
+	/* disable controller */
+	i2c_master_send(client, migor_ts_dis_seq, sizeof(migor_ts_dis_seq));
+
+	enable_irq(priv->irq);
+}
+
+static int migor_ts_probe(struct i2c_client *client,
+			  const struct i2c_device_id *idp)
+{
+	struct migor_ts_priv *priv;
+	struct input_dev *input;
+	int error;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(&client->dev, "failed to allocate driver data\n");
+		error = -ENOMEM;
+		goto err0;
+	}
+
+	dev_set_drvdata(&client->dev, priv);
+
+	input = input_allocate_device();
+	if (!input) {
+		dev_err(&client->dev, "Failed to allocate input device.\n");
+		error = -ENOMEM;
+		goto err1;
+	}
+
+	input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+	input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+	input_set_abs_params(input, ABS_X, 95, 955, 0, 0);
+	input_set_abs_params(input, ABS_Y, 85, 935, 0, 0);
+
+	input->name = client->driver_name;
+	input->id.bustype = BUS_I2C;
+	input->dev.parent = &client->dev;
+
+	input->open = migor_ts_open;
+	input->close = migor_ts_close;
+
+	input_set_drvdata(input, priv);
+
+	priv->client = client;
+	priv->input = input;
+	INIT_DELAYED_WORK(&priv->work, migor_ts_poscheck);
+	priv->irq = client->irq;
+
+	error = input_register_device(input);
+	if (error)
+		goto err1;
+
+	error = request_irq(priv->irq, migor_ts_isr, IRQF_TRIGGER_LOW,
+			    client->driver_name, priv);
+	if (error) {
+		dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
+		goto err2;
+	}
+
+	return 0;
+
+ err2:
+	input_unregister_device(input);
+	input = NULL; /* so we dont try to free it below */
+ err1:
+	input_free_device(input);
+	kfree(priv);
+ err0:
+	dev_set_drvdata(&client->dev, NULL);
+	return error;
+}
+
+static int migor_ts_remove(struct i2c_client *client)
+{
+	struct migor_ts_priv *priv = dev_get_drvdata(&client->dev);
+
+	free_irq(priv->irq, priv);
+	input_unregister_device(priv->input);
+	kfree(priv);
+
+	dev_set_drvdata(&client->dev, NULL);
+
+	return 0;
+}
+
+static struct i2c_driver migor_ts_driver = {
+	.driver = {
+		.name = "migor_ts",
+	},
+	.probe = migor_ts_probe,
+	.remove = migor_ts_remove,
+};
+
+static int __init migor_ts_init(void)
+{
+	return i2c_add_driver(&migor_ts_driver);
+}
+
+static void __exit migor_ts_exit(void)
+{
+	i2c_del_driver(&migor_ts_driver);
+}
+
+MODULE_DESCRIPTION("MigoR Touchscreen driver");
+MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
+MODULE_LICENSE("GPL");
+
+module_init(migor_ts_init);
+module_exit(migor_ts_exit);
diff --git a/drivers/input/touchscreen/touchit213.c b/drivers/input/touchscreen/touchit213.c
new file mode 100644
index 0000000..d1297ba
--- /dev/null
+++ b/drivers/input/touchscreen/touchit213.c
@@ -0,0 +1,234 @@
+/*
+ * Sahara TouchIT-213 serial touchscreen driver
+ *
+ * Copyright (c) 2007-2008 Claudio Nieder <private@claudio.ch>
+ *
+ * Based on Touchright driver (drivers/input/touchscreen/touchright.c)
+ * Copyright (c) 2006 Rick Koch <n1gp@hotmail.com>
+ * Copyright (c) 2004 Vojtech Pavlik
+ * and Dan Streetman <ddstreet@ieee.org>
+ */
+
+/*
+ * 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/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+
+#define DRIVER_DESC	"Sahara TouchIT-213 serial touchscreen driver"
+
+MODULE_AUTHOR("Claudio Nieder <private@claudio.ch>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+/*
+ * Definitions & global arrays.
+ */
+
+/*
+ * Data is received through COM1 at 9600bit/s,8bit,no parity in packets
+ * of 5 byte each.
+ *
+ *   +--------+   +--------+   +--------+   +--------+   +--------+
+ *   |1000000p|   |0xxxxxxx|   |0xxxxxxx|   |0yyyyyyy|   |0yyyyyyy|
+ *   +--------+   +--------+   +--------+   +--------+   +--------+
+ *                    MSB          LSB          MSB          LSB
+ *
+ * The value of p is 1 as long as the screen is touched and 0 when
+ * reporting the location where touching stopped, e.g. where the pen was
+ * lifted from the screen.
+ *
+ * When holding the screen in landscape mode as the BIOS text output is
+ * presented, x is the horizontal axis with values growing from left to
+ * right and y is the vertical axis with values growing from top to
+ * bottom.
+ *
+ * When holding the screen in portrait mode with the Sahara logo in its
+ * correct position, x ist the vertical axis with values growing from
+ * top to bottom and y is the horizontal axis with values growing from
+ * right to left.
+ */
+
+#define T213_FORMAT_TOUCH_BIT	0x01
+#define T213_FORMAT_STATUS_BYTE	0x80
+#define T213_FORMAT_STATUS_MASK	~T213_FORMAT_TOUCH_BIT
+
+/*
+ * On my Sahara Touch-IT 213 I have observed x values from 0 to 0x7f0
+ * and y values from 0x1d to 0x7e9, so the actual measurement is
+ * probably done with an 11 bit precision.
+ */
+#define T213_MIN_XC 0
+#define T213_MAX_XC 0x07ff
+#define T213_MIN_YC 0
+#define T213_MAX_YC 0x07ff
+
+/*
+ * Per-touchscreen data.
+ */
+
+struct touchit213 {
+	struct input_dev *dev;
+	struct serio *serio;
+	int idx;
+	unsigned char csum;
+	unsigned char data[5];
+	char phys[32];
+};
+
+static irqreturn_t touchit213_interrupt(struct serio *serio,
+		unsigned char data, unsigned int flags)
+{
+	struct touchit213 *touchit213 = serio_get_drvdata(serio);
+	struct input_dev *dev = touchit213->dev;
+
+	touchit213->data[touchit213->idx] = data;
+
+	switch (touchit213->idx++) {
+	case 0:
+		if ((touchit213->data[0] & T213_FORMAT_STATUS_MASK) !=
+				T213_FORMAT_STATUS_BYTE) {
+			pr_debug("unsynchronized data: 0x%02x\n", data);
+			touchit213->idx = 0;
+		}
+		break;
+
+	case 4:
+		touchit213->idx = 0;
+		input_report_abs(dev, ABS_X,
+			(touchit213->data[1] << 7) | touchit213->data[2]);
+		input_report_abs(dev, ABS_Y,
+			(touchit213->data[3] << 7) | touchit213->data[4]);
+		input_report_key(dev, BTN_TOUCH,
+			touchit213->data[0] & T213_FORMAT_TOUCH_BIT);
+		input_sync(dev);
+		break;
+	}
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * touchit213_disconnect() is the opposite of touchit213_connect()
+ */
+
+static void touchit213_disconnect(struct serio *serio)
+{
+	struct touchit213 *touchit213 = serio_get_drvdata(serio);
+
+	input_get_device(touchit213->dev);
+	input_unregister_device(touchit213->dev);
+	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
+	input_put_device(touchit213->dev);
+	kfree(touchit213);
+}
+
+/*
+ * touchit213_connect() is the routine that is called when someone adds a
+ * new serio device that supports the Touchright protocol and registers it as
+ * an input device.
+ */
+
+static int touchit213_connect(struct serio *serio, struct serio_driver *drv)
+{
+	struct touchit213 *touchit213;
+	struct input_dev *input_dev;
+	int err;
+
+	touchit213 = kzalloc(sizeof(struct touchit213), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!touchit213 || !input_dev) {
+		err = -ENOMEM;
+		goto fail1;
+	}
+
+	touchit213->serio = serio;
+	touchit213->dev = input_dev;
+	snprintf(touchit213->phys, sizeof(touchit213->phys),
+		 "%s/input0", serio->phys);
+
+	input_dev->name = "Sahara Touch-iT213 Serial TouchScreen";
+	input_dev->phys = touchit213->phys;
+	input_dev->id.bustype = BUS_RS232;
+	input_dev->id.vendor = SERIO_TOUCHIT213;
+	input_dev->id.product = 0;
+	input_dev->id.version = 0x0100;
+	input_dev->dev.parent = &serio->dev;
+	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+	input_set_abs_params(touchit213->dev, ABS_X,
+			     T213_MIN_XC, T213_MAX_XC, 0, 0);
+	input_set_abs_params(touchit213->dev, ABS_Y,
+			     T213_MIN_YC, T213_MAX_YC, 0, 0);
+
+	serio_set_drvdata(serio, touchit213);
+
+	err = serio_open(serio, drv);
+	if (err)
+		goto fail2;
+
+	err = input_register_device(touchit213->dev);
+	if (err)
+		goto fail3;
+
+	return 0;
+
+ fail3:	serio_close(serio);
+ fail2:	serio_set_drvdata(serio, NULL);
+ fail1:	input_free_device(input_dev);
+	kfree(touchit213);
+	return err;
+}
+
+/*
+ * The serio driver structure.
+ */
+
+static struct serio_device_id touchit213_serio_ids[] = {
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_TOUCHIT213,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, touchit213_serio_ids);
+
+static struct serio_driver touchit213_drv = {
+	.driver		= {
+		.name	= "touchit213",
+	},
+	.description	= DRIVER_DESC,
+	.id_table	= touchit213_serio_ids,
+	.interrupt	= touchit213_interrupt,
+	.connect	= touchit213_connect,
+	.disconnect	= touchit213_disconnect,
+};
+
+/*
+ * The functions for inserting/removing us as a module.
+ */
+
+static int __init touchit213_init(void)
+{
+	return serio_register_driver(&touchit213_drv);
+}
+
+static void __exit touchit213_exit(void)
+{
+	serio_unregister_driver(&touchit213_drv);
+}
+
+module_init(touchit213_init);
+module_exit(touchit213_exit);
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
index 3a0a8ca..fdd645c 100644
--- a/drivers/input/touchscreen/usbtouchscreen.c
+++ b/drivers/input/touchscreen/usbtouchscreen.c
@@ -49,6 +49,7 @@
 #include <linux/init.h>
 #include <linux/usb.h>
 #include <linux/usb/input.h>
+#include <linux/hid.h>
 
 
 #define DRIVER_VERSION		"v0.6"
@@ -101,7 +102,7 @@
 
 /* device types */
 enum {
-	DEVTPYE_DUMMY = -1,
+	DEVTYPE_IGNORE = -1,
 	DEVTYPE_EGALAX,
 	DEVTYPE_PANJIT,
 	DEVTYPE_3M,
@@ -115,8 +116,21 @@
 	DEVTYPE_GOTOP,
 };
 
+#define USB_DEVICE_HID_CLASS(vend, prod) \
+	.match_flags = USB_DEVICE_ID_MATCH_INT_CLASS \
+		| USB_DEVICE_ID_MATCH_DEVICE, \
+	.idVendor = (vend), \
+	.idProduct = (prod), \
+	.bInterfaceClass = USB_INTERFACE_CLASS_HID, \
+	.bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE
+
 static struct usb_device_id usbtouch_devices[] = {
 #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX
+	/* ignore the HID capable devices, handled by usbhid */
+	{USB_DEVICE_HID_CLASS(0x0eef, 0x0001), .driver_info = DEVTYPE_IGNORE},
+	{USB_DEVICE_HID_CLASS(0x0eef, 0x0002), .driver_info = DEVTYPE_IGNORE},
+
+	/* normal device IDs */
 	{USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX},
 	{USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX},
 	{USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX},
@@ -262,7 +276,7 @@
 	                      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 	                      1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
 	dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d",
-	    __FUNCTION__, ret);
+	    __func__, ret);
 	if (ret < 0)
 		return ret;
 	msleep(150);
@@ -273,7 +287,7 @@
 				      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);
+		    __func__, ret);
 		if (ret >= 0)
 			break;
 		if (ret != -EPIPE)
@@ -793,18 +807,18 @@
 	case -ETIME:
 		/* this urb is timing out */
 		dbg("%s - urb timed out - was the device unplugged?",
-		    __FUNCTION__);
+		    __func__);
 		return;
 	case -ECONNRESET:
 	case -ENOENT:
 	case -ESHUTDOWN:
 		/* this urb is terminated, clean up */
 		dbg("%s - urb shutting down with status: %d",
-		    __FUNCTION__, urb->status);
+		    __func__, urb->status);
 		return;
 	default:
 		dbg("%s - nonzero urb status received: %d",
-		    __FUNCTION__, urb->status);
+		    __func__, urb->status);
 		goto exit;
 	}
 
@@ -814,7 +828,7 @@
 	retval = usb_submit_urb(urb, GFP_ATOMIC);
 	if (retval)
 		err("%s - usb_submit_urb failed with result: %d",
-		    __FUNCTION__, retval);
+		    __func__, retval);
 }
 
 static int usbtouch_open(struct input_dev *input)
@@ -857,6 +871,10 @@
 	struct usbtouch_device_info *type;
 	int err = -ENOMEM;
 
+	/* some devices are ignored */
+	if (id->driver_info == DEVTYPE_IGNORE)
+		return -ENODEV;
+
 	interface = intf->cur_altsetting;
 	endpoint = &interface->endpoint[0].desc;
 
@@ -883,7 +901,7 @@
 
 	usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL);
 	if (!usbtouch->irq) {
-		dbg("%s - usb_alloc_urb failed: usbtouch->irq", __FUNCTION__);
+		dbg("%s - usb_alloc_urb failed: usbtouch->irq", __func__);
 		goto out_free_buffers;
 	}
 
@@ -939,14 +957,14 @@
 	if (type->init) {
 		err = type->init(usbtouch);
 		if (err) {
-			dbg("%s - type->init() failed, err: %d", __FUNCTION__, err);
+			dbg("%s - type->init() failed, err: %d", __func__, err);
 			goto out_free_buffers;
 		}
 	}
 
 	err = input_register_device(usbtouch->input);
 	if (err) {
-		dbg("%s - input_register_device failed, err: %d", __FUNCTION__, err);
+		dbg("%s - input_register_device failed, err: %d", __func__, err);
 		goto out_free_buffers;
 	}
 
@@ -966,12 +984,12 @@
 {
 	struct usbtouch_usb *usbtouch = usb_get_intfdata(intf);
 
-	dbg("%s - called", __FUNCTION__);
+	dbg("%s - called", __func__);
 
 	if (!usbtouch)
 		return;
 
-	dbg("%s - usbtouch is initialized, cleaning up", __FUNCTION__);
+	dbg("%s - usbtouch is initialized, cleaning up", __func__);
 	usb_set_intfdata(intf, NULL);
 	usb_kill_urb(usbtouch->irq);
 	input_unregister_device(usbtouch->input);
diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c
index 0b6e4cf..4c5d85a 100644
--- a/drivers/input/touchscreen/wm9712.c
+++ b/drivers/input/touchscreen/wm9712.c
@@ -168,6 +168,18 @@
 			64000 / rpu);
 	}
 
+	/* WM9712 five wire */
+	if (five_wire) {
+		dig2 |= WM9712_45W;
+		dev_dbg(wm->dev, "setting 5-wire touchscreen mode.");
+
+		if (pil) {
+			dev_warn(wm->dev, "pressure measurement is not "
+				 "supported in 5-wire mode\n");
+			pil = 0;
+		}
+	}
+
 	/* touchpanel pressure current*/
 	if (pil == 2) {
 		dig2 |= WM9712_PIL;
@@ -179,12 +191,6 @@
 	if (!pil)
 		pressure = 0;
 
-	/* WM9712 five wire */
-	if (five_wire) {
-		dig2 |= WM9712_45W;
-		dev_dbg(wm->dev, "setting 5-wire touchscreen mode.");
-	}
-
 	/* polling mode sample settling delay */
 	if (delay < 0 || delay > 15) {
 		dev_dbg(wm->dev, "supplied delay out of range.");
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 8a35029c..871b0cbc 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -1302,11 +1302,12 @@
 #endif
 }
 
-static void capinc_tty_break_ctl(struct tty_struct *tty, int state)
+static int capinc_tty_break_ctl(struct tty_struct *tty, int state)
 {
 #ifdef _DEBUG_TTYFUNCS
 	printk(KERN_DEBUG "capinc_tty_break_ctl(%d)\n", state);
 #endif
+	return 0;
 }
 
 static void capinc_tty_flush_buffer(struct tty_struct *tty)
@@ -1552,7 +1553,8 @@
 		return PTR_ERR(capi_class);
 	}
 
-	device_create(capi_class, NULL, MKDEV(capi_major, 0), "capi");
+	device_create_drvdata(capi_class, NULL, MKDEV(capi_major, 0), NULL,
+			      "capi");
 
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 	if (capinc_tty_init() < 0) {
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index e5d4468..cae5248 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -862,7 +862,8 @@
 	adb_dev_class = class_create(THIS_MODULE, "adb");
 	if (IS_ERR(adb_dev_class))
 		return;
-	device_create(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), "adb");
+	device_create_drvdata(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), NULL,
+			      "adb");
 
 	platform_device_register(&adb_pfdev);
 	platform_driver_probe(&adb_pfdrv, adb_dummy_probe);
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index 59ea520..5396c67 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -219,11 +219,13 @@
 	int flags;
 };
 
-#define FLAG_FN_KEY_PRESSED	0x00000001
-#define FLAG_POWER_FROM_FN	0x00000002
-#define FLAG_EMU_FWDEL_DOWN	0x00000004
-#define FLAG_CAPSLOCK_TRANSLATE	0x00000008
-#define FLAG_CAPSLOCK_DOWN	0x00000010
+#define FLAG_FN_KEY_PRESSED		0x00000001
+#define FLAG_POWER_FROM_FN		0x00000002
+#define FLAG_EMU_FWDEL_DOWN		0x00000004
+#define FLAG_CAPSLOCK_TRANSLATE		0x00000008
+#define FLAG_CAPSLOCK_DOWN		0x00000010
+#define FLAG_CAPSLOCK_IGNORE_NEXT	0x00000020
+#define FLAG_POWER_KEY_PRESSED		0x00000040
 
 static struct adbhid *adbhid[16];
 
@@ -291,11 +293,20 @@
 		if (keycode == ADB_KEY_CAPSLOCK && !up_flag) {
 			/* Key pressed, turning on the CapsLock LED.
 			 * The next 0xff will be interpreted as a release. */
-			ahid->flags |= FLAG_CAPSLOCK_TRANSLATE
+			if (ahid->flags & FLAG_CAPSLOCK_IGNORE_NEXT) {
+				/* Throw away this key event if it happens
+				 * just after resume. */
+				ahid->flags &= ~FLAG_CAPSLOCK_IGNORE_NEXT;
+				return;
+			} else {
+				ahid->flags |= FLAG_CAPSLOCK_TRANSLATE
 					| FLAG_CAPSLOCK_DOWN;
-		} else if (scancode == 0xff) {
+			}
+		} else if (scancode == 0xff &&
+			   !(ahid->flags & FLAG_POWER_KEY_PRESSED)) {
 			/* Scancode 0xff usually signifies that the capslock
-			 * key was either pressed or released. */
+			 * key was either pressed or released, or that the
+			 * power button was released. */
 			if (ahid->flags & FLAG_CAPSLOCK_TRANSLATE) {
 				keycode = ADB_KEY_CAPSLOCK;
 				if (ahid->flags & FLAG_CAPSLOCK_DOWN) {
@@ -309,7 +320,7 @@
 				}
 			} else {
 				printk(KERN_INFO "Spurious caps lock event "
-						"(scancode 0xff).");
+						 "(scancode 0xff).\n");
 			}
 		}
 	}
@@ -336,6 +347,12 @@
 		}
 		break;
 	case ADB_KEY_POWER:
+		/* Keep track of the power key state */
+		if (up_flag)
+			ahid->flags &= ~FLAG_POWER_KEY_PRESSED;
+		else
+			ahid->flags |= FLAG_POWER_KEY_PRESSED;
+
 		/* Fn + Command will produce a bogus "power" keycode */
 		if (ahid->flags & FLAG_FN_KEY_PRESSED) {
 			keycode = ADB_KEY_CMD;
@@ -681,6 +698,21 @@
 	return -1;
 }
 
+static void
+adbhid_kbd_capslock_remember(void)
+{
+	struct adbhid *ahid;
+	int i;
+
+	for (i = 1; i < 16; i++) {
+		ahid = adbhid[i];
+
+		if (ahid && ahid->id == ADB_KEYBOARD)
+			if (ahid->flags & FLAG_CAPSLOCK_TRANSLATE)
+				ahid->flags |= FLAG_CAPSLOCK_IGNORE_NEXT;
+	}
+}
+
 static int
 adb_message_handler(struct notifier_block *this, unsigned long code, void *x)
 {
@@ -697,8 +729,17 @@
 		}
 
 		/* Stop pending led requests */
-		while(leds_req_pending)
+		while (leds_req_pending)
 			adb_poll();
+
+		/* After resume, and if the capslock LED is on, the PMU will
+		 * send a "capslock down" key event. This confuses the
+		 * restore_capslock_events logic. Remember if the capslock
+		 * LED was on before suspend so the unwanted key event can
+		 * be ignored after resume. */
+		if (restore_capslock_events)
+			adbhid_kbd_capslock_remember();
+
 		break;
 
 	case ADB_MSG_POST_RESET:
diff --git a/drivers/mca/mca-bus.c b/drivers/mca/mca-bus.c
index 67b8e94..ef2dbfe 100644
--- a/drivers/mca/mca-bus.c
+++ b/drivers/mca/mca-bus.c
@@ -40,7 +40,7 @@
 
 struct mca_device_info {
 	short pos_id;		/* the 2 byte pos id for this card */
-	char name[DEVICE_NAME_SIZE];
+	char name[50];
 };
 
 static int mca_bus_match (struct device *dev, struct device_driver *drv)
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index b26927c..621a272 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -225,7 +225,7 @@
 		    || test_bit(Faulty, &rdev->flags))
 			continue;
 
-		target = (rdev->sb_offset << 1) + offset + index * (PAGE_SIZE/512);
+		target = rdev->sb_start + offset + index * (PAGE_SIZE/512);
 
 		if (sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ)) {
 			page->index = index;
@@ -241,10 +241,10 @@
 static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
 {
 	mdk_rdev_t *rdev;
-	struct list_head *tmp;
 	mddev_t *mddev = bitmap->mddev;
 
-	rdev_for_each(rdev, tmp, mddev)
+	rcu_read_lock();
+	rdev_for_each_rcu(rdev, mddev)
 		if (test_bit(In_sync, &rdev->flags)
 		    && !test_bit(Faulty, &rdev->flags)) {
 			int size = PAGE_SIZE;
@@ -260,32 +260,37 @@
 				    + (long)(page->index * (PAGE_SIZE/512))
 				    + size/512 > 0)
 					/* bitmap runs in to metadata */
-					return -EINVAL;
+					goto bad_alignment;
 				if (rdev->data_offset + mddev->size*2
-				    > rdev->sb_offset*2 + bitmap->offset)
+				    > rdev->sb_start + bitmap->offset)
 					/* data runs in to bitmap */
-					return -EINVAL;
-			} else if (rdev->sb_offset*2 < rdev->data_offset) {
+					goto bad_alignment;
+			} else if (rdev->sb_start < rdev->data_offset) {
 				/* METADATA BITMAP DATA */
-				if (rdev->sb_offset*2
+				if (rdev->sb_start
 				    + bitmap->offset
 				    + page->index*(PAGE_SIZE/512) + size/512
 				    > rdev->data_offset)
 					/* bitmap runs in to data */
-					return -EINVAL;
+					goto bad_alignment;
 			} else {
 				/* DATA METADATA BITMAP - no problems */
 			}
 			md_super_write(mddev, rdev,
-				       (rdev->sb_offset<<1) + bitmap->offset
+				       rdev->sb_start + bitmap->offset
 				       + page->index * (PAGE_SIZE/512),
 				       size,
 				       page);
 		}
+	rcu_read_unlock();
 
 	if (wait)
 		md_super_wait(mddev);
 	return 0;
+
+ bad_alignment:
+	rcu_read_unlock();
+	return -EINVAL;
 }
 
 static void bitmap_file_kick(struct bitmap *bitmap);
@@ -454,8 +459,11 @@
 	spin_unlock_irqrestore(&bitmap->lock, flags);
 	sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
 	sb->events = cpu_to_le64(bitmap->mddev->events);
-	if (!bitmap->mddev->degraded)
-		sb->events_cleared = cpu_to_le64(bitmap->mddev->events);
+	if (bitmap->mddev->events < bitmap->events_cleared) {
+		/* rocking back to read-only */
+		bitmap->events_cleared = bitmap->mddev->events;
+		sb->events_cleared = cpu_to_le64(bitmap->events_cleared);
+	}
 	kunmap_atomic(sb, KM_USER0);
 	write_page(bitmap, bitmap->sb_page, 1);
 }
@@ -1085,9 +1093,19 @@
 			} else
 				spin_unlock_irqrestore(&bitmap->lock, flags);
 			lastpage = page;
-/*
-			printk("bitmap clean at page %lu\n", j);
-*/
+
+			/* We are possibly going to clear some bits, so make
+			 * sure that events_cleared is up-to-date.
+			 */
+			if (bitmap->need_sync) {
+				bitmap_super_t *sb;
+				bitmap->need_sync = 0;
+				sb = kmap_atomic(bitmap->sb_page, KM_USER0);
+				sb->events_cleared =
+					cpu_to_le64(bitmap->events_cleared);
+				kunmap_atomic(sb, KM_USER0);
+				write_page(bitmap, bitmap->sb_page, 1);
+			}
 			spin_lock_irqsave(&bitmap->lock, flags);
 			clear_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
 		}
@@ -1257,6 +1275,12 @@
 			return;
 		}
 
+		if (success &&
+		    bitmap->events_cleared < bitmap->mddev->events) {
+			bitmap->events_cleared = bitmap->mddev->events;
+			bitmap->need_sync = 1;
+		}
+
 		if (!success && ! (*bmc & NEEDED_MASK))
 			*bmc |= NEEDED_MASK;
 
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index ab6a61d..1395643 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -1216,9 +1216,24 @@
 	return -EINVAL;
 }
 
+static int crypt_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
+		       struct bio_vec *biovec, int max_size)
+{
+	struct crypt_config *cc = ti->private;
+	struct request_queue *q = bdev_get_queue(cc->dev->bdev);
+
+	if (!q->merge_bvec_fn)
+		return max_size;
+
+	bvm->bi_bdev = cc->dev->bdev;
+	bvm->bi_sector = cc->start + bvm->bi_sector - ti->begin;
+
+	return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
+}
+
 static struct target_type crypt_target = {
 	.name   = "crypt",
-	.version= {1, 5, 0},
+	.version= {1, 6, 0},
 	.module = THIS_MODULE,
 	.ctr    = crypt_ctr,
 	.dtr    = crypt_dtr,
@@ -1228,6 +1243,7 @@
 	.preresume = crypt_preresume,
 	.resume = crypt_resume,
 	.message = crypt_message,
+	.merge  = crypt_merge,
 };
 
 static int __init dm_crypt_init(void)
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 17753d8..6449bcd 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -69,13 +69,25 @@
 	kfree(lc);
 }
 
+static sector_t linear_map_sector(struct dm_target *ti, sector_t bi_sector)
+{
+	struct linear_c *lc = ti->private;
+
+	return lc->start + (bi_sector - ti->begin);
+}
+
+static void linear_map_bio(struct dm_target *ti, struct bio *bio)
+{
+	struct linear_c *lc = ti->private;
+
+	bio->bi_bdev = lc->dev->bdev;
+	bio->bi_sector = linear_map_sector(ti, bio->bi_sector);
+}
+
 static int linear_map(struct dm_target *ti, struct bio *bio,
 		      union map_info *map_context)
 {
-	struct linear_c *lc = (struct linear_c *) ti->private;
-
-	bio->bi_bdev = lc->dev->bdev;
-	bio->bi_sector = lc->start + (bio->bi_sector - ti->begin);
+	linear_map_bio(ti, bio);
 
 	return DM_MAPIO_REMAPPED;
 }
@@ -114,15 +126,31 @@
 	return blkdev_driver_ioctl(bdev->bd_inode, &fake_file, bdev->bd_disk, cmd, arg);
 }
 
+static int linear_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
+			struct bio_vec *biovec, int max_size)
+{
+	struct linear_c *lc = ti->private;
+	struct request_queue *q = bdev_get_queue(lc->dev->bdev);
+
+	if (!q->merge_bvec_fn)
+		return max_size;
+
+	bvm->bi_bdev = lc->dev->bdev;
+	bvm->bi_sector = linear_map_sector(ti, bvm->bi_sector);
+
+	return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
+}
+
 static struct target_type linear_target = {
 	.name   = "linear",
-	.version= {1, 0, 2},
+	.version= {1, 0, 3},
 	.module = THIS_MODULE,
 	.ctr    = linear_ctr,
 	.dtr    = linear_dtr,
 	.map    = linear_map,
 	.status = linear_status,
 	.ioctl  = linear_ioctl,
+	.merge  = linear_merge,
 };
 
 int __init dm_linear_init(void)
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index 67a6f31..5b48478 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -831,7 +831,7 @@
 	.status = disk_status,
 };
 
-int __init dm_dirty_log_init(void)
+static int __init dm_dirty_log_init(void)
 {
 	int r;
 
@@ -848,7 +848,7 @@
 	return r;
 }
 
-void __exit dm_dirty_log_exit(void)
+static void __exit dm_dirty_log_exit(void)
 {
 	dm_dirty_log_type_unregister(&_disk_type);
 	dm_dirty_log_type_unregister(&_core_type);
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 9f7302d..fea966d 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -525,8 +525,10 @@
 	}
 
 	r = read_param(_params, shift(as), &ps_argc, &ti->error);
-	if (r)
+	if (r) {
+		dm_put_path_selector(pst);
 		return -EINVAL;
+	}
 
 	r = pst->create(&pg->ps, ps_argc, as->argv);
 	if (r) {
@@ -623,8 +625,10 @@
 		struct pgpath *pgpath;
 		struct arg_set path_args;
 
-		if (as->argc < nr_params)
+		if (as->argc < nr_params) {
+			ti->error = "not enough path parameters";
 			goto bad;
+		}
 
 		path_args.argc = nr_params;
 		path_args.argv = as->argv;
@@ -867,7 +871,7 @@
 	if (pgpath->path.is_active)
 		goto out;
 
-	if (!pgpath->pg->ps.type) {
+	if (!pgpath->pg->ps.type->reinstate_path) {
 		DMWARN("Reinstate path not supported by path selector %s",
 		       pgpath->pg->ps.type->name);
 		r = -EINVAL;
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 1ba8a47d..6e5528a 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -40,6 +40,11 @@
  */
 #define SNAPSHOT_PAGES (((1UL << 20) >> PAGE_SHIFT) ? : 1)
 
+/*
+ * The size of the mempool used to track chunks in use.
+ */
+#define MIN_IOS 256
+
 static struct workqueue_struct *ksnapd;
 static void flush_queued_bios(struct work_struct *work);
 
@@ -91,7 +96,63 @@
  */
 static struct kmem_cache *exception_cache;
 static struct kmem_cache *pending_cache;
-static mempool_t *pending_pool;
+
+struct dm_snap_tracked_chunk {
+	struct hlist_node node;
+	chunk_t chunk;
+};
+
+static struct kmem_cache *tracked_chunk_cache;
+
+static struct dm_snap_tracked_chunk *track_chunk(struct dm_snapshot *s,
+						 chunk_t chunk)
+{
+	struct dm_snap_tracked_chunk *c = mempool_alloc(s->tracked_chunk_pool,
+							GFP_NOIO);
+	unsigned long flags;
+
+	c->chunk = chunk;
+
+	spin_lock_irqsave(&s->tracked_chunk_lock, flags);
+	hlist_add_head(&c->node,
+		       &s->tracked_chunk_hash[DM_TRACKED_CHUNK_HASH(chunk)]);
+	spin_unlock_irqrestore(&s->tracked_chunk_lock, flags);
+
+	return c;
+}
+
+static void stop_tracking_chunk(struct dm_snapshot *s,
+				struct dm_snap_tracked_chunk *c)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&s->tracked_chunk_lock, flags);
+	hlist_del(&c->node);
+	spin_unlock_irqrestore(&s->tracked_chunk_lock, flags);
+
+	mempool_free(c, s->tracked_chunk_pool);
+}
+
+static int __chunk_is_tracked(struct dm_snapshot *s, chunk_t chunk)
+{
+	struct dm_snap_tracked_chunk *c;
+	struct hlist_node *hn;
+	int found = 0;
+
+	spin_lock_irq(&s->tracked_chunk_lock);
+
+	hlist_for_each_entry(c, hn,
+	    &s->tracked_chunk_hash[DM_TRACKED_CHUNK_HASH(chunk)], node) {
+		if (c->chunk == chunk) {
+			found = 1;
+			break;
+		}
+	}
+
+	spin_unlock_irq(&s->tracked_chunk_lock);
+
+	return found;
+}
 
 /*
  * One of these per registered origin, held in the snapshot_origins hash
@@ -302,14 +363,19 @@
 	kmem_cache_free(exception_cache, e);
 }
 
-static struct dm_snap_pending_exception *alloc_pending_exception(void)
+static struct dm_snap_pending_exception *alloc_pending_exception(struct dm_snapshot *s)
 {
-	return mempool_alloc(pending_pool, GFP_NOIO);
+	struct dm_snap_pending_exception *pe = mempool_alloc(s->pending_pool,
+							     GFP_NOIO);
+
+	pe->snap = s;
+
+	return pe;
 }
 
 static void free_pending_exception(struct dm_snap_pending_exception *pe)
 {
-	mempool_free(pe, pending_pool);
+	mempool_free(pe, pe->snap->pending_pool);
 }
 
 static void insert_completed_exception(struct dm_snapshot *s,
@@ -482,6 +548,7 @@
 static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 {
 	struct dm_snapshot *s;
+	int i;
 	int r = -EINVAL;
 	char persistent;
 	char *origin_path;
@@ -564,11 +631,30 @@
 		goto bad5;
 	}
 
+	s->pending_pool = mempool_create_slab_pool(MIN_IOS, pending_cache);
+	if (!s->pending_pool) {
+		ti->error = "Could not allocate mempool for pending exceptions";
+		goto bad6;
+	}
+
+	s->tracked_chunk_pool = mempool_create_slab_pool(MIN_IOS,
+							 tracked_chunk_cache);
+	if (!s->tracked_chunk_pool) {
+		ti->error = "Could not allocate tracked_chunk mempool for "
+			    "tracking reads";
+		goto bad_tracked_chunk_pool;
+	}
+
+	for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++)
+		INIT_HLIST_HEAD(&s->tracked_chunk_hash[i]);
+
+	spin_lock_init(&s->tracked_chunk_lock);
+
 	/* Metadata must only be loaded into one table at once */
 	r = s->store.read_metadata(&s->store);
 	if (r < 0) {
 		ti->error = "Failed to read snapshot metadata";
-		goto bad6;
+		goto bad_load_and_register;
 	} else if (r > 0) {
 		s->valid = 0;
 		DMWARN("Snapshot is marked invalid.");
@@ -582,7 +668,7 @@
 	if (register_snapshot(s)) {
 		r = -EINVAL;
 		ti->error = "Cannot register snapshot origin";
-		goto bad6;
+		goto bad_load_and_register;
 	}
 
 	ti->private = s;
@@ -590,6 +676,12 @@
 
 	return 0;
 
+ bad_load_and_register:
+	mempool_destroy(s->tracked_chunk_pool);
+
+ bad_tracked_chunk_pool:
+	mempool_destroy(s->pending_pool);
+
  bad6:
 	dm_kcopyd_client_destroy(s->kcopyd_client);
 
@@ -624,6 +716,9 @@
 
 static void snapshot_dtr(struct dm_target *ti)
 {
+#ifdef CONFIG_DM_DEBUG
+	int i;
+#endif
 	struct dm_snapshot *s = ti->private;
 
 	flush_workqueue(ksnapd);
@@ -632,8 +727,17 @@
 	/* After this returns there can be no new kcopyd jobs. */
 	unregister_snapshot(s);
 
+#ifdef CONFIG_DM_DEBUG
+	for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++)
+		BUG_ON(!hlist_empty(&s->tracked_chunk_hash[i]));
+#endif
+
+	mempool_destroy(s->tracked_chunk_pool);
+
 	__free_exceptions(s);
 
+	mempool_destroy(s->pending_pool);
+
 	dm_put_device(ti, s->origin);
 	dm_put_device(ti, s->cow);
 
@@ -772,6 +876,13 @@
 	}
 
 	/*
+	 * Check for conflicting reads. This is extremely improbable,
+	 * so yield() is sufficient and there is no need for a wait queue.
+	 */
+	while (__chunk_is_tracked(s, pe->e.old_chunk))
+		yield();
+
+	/*
 	 * Add a proper exception, and remove the
 	 * in-flight exception from the list.
 	 */
@@ -873,7 +984,7 @@
 	 * to hold the lock while we do this.
 	 */
 	up_write(&s->lock);
-	pe = alloc_pending_exception();
+	pe = alloc_pending_exception(s);
 	down_write(&s->lock);
 
 	if (!s->valid) {
@@ -893,7 +1004,6 @@
 	bio_list_init(&pe->snapshot_bios);
 	pe->primary_pe = NULL;
 	atomic_set(&pe->ref_count, 0);
-	pe->snap = s;
 	pe->started = 0;
 
 	if (s->store.prepare_exception(&s->store, &pe->e)) {
@@ -974,14 +1084,10 @@
 			start_copy(pe);
 			goto out;
 		}
-	} else
-		/*
-		 * FIXME: this read path scares me because we
-		 * always use the origin when we have a pending
-		 * exception.  However I can't think of a
-		 * situation where this is wrong - ejt.
-		 */
+	} else {
 		bio->bi_bdev = s->origin->bdev;
+		map_context->ptr = track_chunk(s, chunk);
+	}
 
  out_unlock:
 	up_write(&s->lock);
@@ -989,6 +1095,18 @@
 	return r;
 }
 
+static int snapshot_end_io(struct dm_target *ti, struct bio *bio,
+			   int error, union map_info *map_context)
+{
+	struct dm_snapshot *s = ti->private;
+	struct dm_snap_tracked_chunk *c = map_context->ptr;
+
+	if (c)
+		stop_tracking_chunk(s, c);
+
+	return 0;
+}
+
 static void snapshot_resume(struct dm_target *ti)
 {
 	struct dm_snapshot *s = ti->private;
@@ -1266,6 +1384,7 @@
 	.ctr     = snapshot_ctr,
 	.dtr     = snapshot_dtr,
 	.map     = snapshot_map,
+	.end_io  = snapshot_end_io,
 	.resume  = snapshot_resume,
 	.status  = snapshot_status,
 };
@@ -1306,9 +1425,9 @@
 		goto bad4;
 	}
 
-	pending_pool = mempool_create_slab_pool(128, pending_cache);
-	if (!pending_pool) {
-		DMERR("Couldn't create pending pool.");
+	tracked_chunk_cache = KMEM_CACHE(dm_snap_tracked_chunk, 0);
+	if (!tracked_chunk_cache) {
+		DMERR("Couldn't create cache to track chunks in use.");
 		r = -ENOMEM;
 		goto bad5;
 	}
@@ -1317,13 +1436,13 @@
 	if (!ksnapd) {
 		DMERR("Failed to create ksnapd workqueue.");
 		r = -ENOMEM;
-		goto bad6;
+		goto bad_pending_pool;
 	}
 
 	return 0;
 
-      bad6:
-	mempool_destroy(pending_pool);
+      bad_pending_pool:
+	kmem_cache_destroy(tracked_chunk_cache);
       bad5:
 	kmem_cache_destroy(pending_cache);
       bad4:
@@ -1352,9 +1471,9 @@
 		DMERR("origin unregister failed %d", r);
 
 	exit_origin_hash();
-	mempool_destroy(pending_pool);
 	kmem_cache_destroy(pending_cache);
 	kmem_cache_destroy(exception_cache);
+	kmem_cache_destroy(tracked_chunk_cache);
 }
 
 /* Module hooks */
diff --git a/drivers/md/dm-snap.h b/drivers/md/dm-snap.h
index 24f9fb7..292c156 100644
--- a/drivers/md/dm-snap.h
+++ b/drivers/md/dm-snap.h
@@ -130,6 +130,10 @@
 	void *context;
 };
 
+#define DM_TRACKED_CHUNK_HASH_SIZE	16
+#define DM_TRACKED_CHUNK_HASH(x)	((unsigned long)(x) & \
+					 (DM_TRACKED_CHUNK_HASH_SIZE - 1))
+
 struct dm_snapshot {
 	struct rw_semaphore lock;
 	struct dm_target *ti;
@@ -157,6 +161,8 @@
 	/* The last percentage we notified */
 	int last_percent;
 
+	mempool_t *pending_pool;
+
 	struct exception_table pending;
 	struct exception_table complete;
 
@@ -174,6 +180,11 @@
 	/* Queue of snapshot writes for ksnapd to flush */
 	struct bio_list queued_bios;
 	struct work_struct queued_bios_work;
+
+	/* Chunks with outstanding reads */
+	mempool_t *tracked_chunk_pool;
+	spinlock_t tracked_chunk_lock;
+	struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE];
 };
 
 /*
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 94116ea..798e468 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -506,14 +506,13 @@
 	rs->max_sectors =
 		min_not_zero(rs->max_sectors, q->max_sectors);
 
-	/* FIXME: Device-Mapper on top of RAID-0 breaks because DM
-	 *        currently doesn't honor MD's merge_bvec_fn routine.
-	 *        In this case, we'll force DM to use PAGE_SIZE or
-	 *        smaller I/O, just to be safe. A better fix is in the
-	 *        works, but add this for the time being so it will at
-	 *        least operate correctly.
+	/*
+	 * Check if merge fn is supported.
+	 * If not we'll force DM to use PAGE_SIZE or
+	 * smaller I/O, just to be safe.
 	 */
-	if (q->merge_bvec_fn)
+
+	if (q->merge_bvec_fn && !ti->type->merge)
 		rs->max_sectors =
 			min_not_zero(rs->max_sectors,
 				     (unsigned int) (PAGE_SIZE >> 9));
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 372369b..bca448e 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -37,8 +37,8 @@
 struct dm_io {
 	struct mapped_device *md;
 	int error;
-	struct bio *bio;
 	atomic_t io_count;
+	struct bio *bio;
 	unsigned long start_time;
 };
 
@@ -829,6 +829,49 @@
  * CRUD END
  *---------------------------------------------------------------*/
 
+static int dm_merge_bvec(struct request_queue *q,
+			 struct bvec_merge_data *bvm,
+			 struct bio_vec *biovec)
+{
+	struct mapped_device *md = q->queuedata;
+	struct dm_table *map = dm_get_table(md);
+	struct dm_target *ti;
+	sector_t max_sectors;
+	int max_size;
+
+	if (unlikely(!map))
+		return 0;
+
+	ti = dm_table_find_target(map, bvm->bi_sector);
+
+	/*
+	 * Find maximum amount of I/O that won't need splitting
+	 */
+	max_sectors = min(max_io_len(md, bvm->bi_sector, ti),
+			  (sector_t) BIO_MAX_SECTORS);
+	max_size = (max_sectors << SECTOR_SHIFT) - bvm->bi_size;
+	if (max_size < 0)
+		max_size = 0;
+
+	/*
+	 * merge_bvec_fn() returns number of bytes
+	 * it can accept at this offset
+	 * max is precomputed maximal io size
+	 */
+	if (max_size && ti->type->merge)
+		max_size = ti->type->merge(ti, bvm, biovec, max_size);
+
+	/*
+	 * Always allow an entire first page
+	 */
+	if (max_size <= biovec->bv_len && !(bvm->bi_size >> SECTOR_SHIFT))
+		max_size = biovec->bv_len;
+
+	dm_table_put(map);
+
+	return max_size;
+}
+
 /*
  * The request function that just remaps the bio built up by
  * dm_merge_bvec.
@@ -1032,6 +1075,7 @@
 	blk_queue_make_request(md->queue, dm_request);
 	blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY);
 	md->queue->unplug_fn = dm_unplug_all;
+	blk_queue_merge_bvec(md->queue, dm_merge_bvec);
 
 	md->io_pool = mempool_create_slab_pool(MIN_IOS, _io_cache);
 	if (!md->io_pool)
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 8c03b63..1e59a0b 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -100,12 +100,6 @@
 
 void dm_kobject_uevent(struct mapped_device *md);
 
-/*
- * Dirty log
- */
-int dm_dirty_log_init(void);
-void dm_dirty_log_exit(void);
-
 int dm_kcopyd_init(void);
 void dm_kcopyd_exit(void);
 
diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c
index d107ddc..268547d 100644
--- a/drivers/md/faulty.c
+++ b/drivers/md/faulty.c
@@ -297,7 +297,7 @@
 	rdev_for_each(rdev, tmp, mddev)
 		conf->rdev = rdev;
 
-	mddev->array_size = mddev->size;
+	mddev->array_sectors = mddev->size * 2;
 	mddev->private = conf;
 
 	reconfig(mddev, mddev->layout, -1);
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 6a866d7..b1eebf8 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -122,13 +122,13 @@
 		return NULL;
 
 	cnt = 0;
-	conf->array_size = 0;
+	conf->array_sectors = 0;
 
 	rdev_for_each(rdev, tmp, mddev) {
 		int j = rdev->raid_disk;
 		dev_info_t *disk = conf->disks + j;
 
-		if (j < 0 || j > raid_disks || disk->rdev) {
+		if (j < 0 || j >= raid_disks || disk->rdev) {
 			printk("linear: disk numbering problem. Aborting!\n");
 			goto out;
 		}
@@ -146,7 +146,7 @@
 			blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
 		disk->size = rdev->size;
-		conf->array_size += rdev->size;
+		conf->array_sectors += rdev->size * 2;
 
 		cnt++;
 	}
@@ -155,7 +155,7 @@
 		goto out;
 	}
 
-	min_spacing = conf->array_size;
+	min_spacing = conf->array_sectors / 2;
 	sector_div(min_spacing, PAGE_SIZE/sizeof(struct dev_info *));
 
 	/* min_spacing is the minimum spacing that will fit the hash
@@ -164,7 +164,7 @@
 	 * that is larger than min_spacing as use the size of that as
 	 * the actual spacing
 	 */
-	conf->hash_spacing = conf->array_size;
+	conf->hash_spacing = conf->array_sectors / 2;
 	for (i=0; i < cnt-1 ; i++) {
 		sector_t sz = 0;
 		int j;
@@ -194,7 +194,7 @@
 		unsigned round;
 		unsigned long base;
 
-		sz = conf->array_size >> conf->preshift;
+		sz = conf->array_sectors >> (conf->preshift + 1);
 		sz += 1; /* force round-up */
 		base = conf->hash_spacing >> conf->preshift;
 		round = sector_div(sz, base);
@@ -221,7 +221,7 @@
 	curr_offset = 0;
 	i = 0;
 	for (curr_offset = 0;
-	     curr_offset < conf->array_size;
+	     curr_offset < conf->array_sectors / 2;
 	     curr_offset += conf->hash_spacing) {
 
 		while (i < raid_disks-1 &&
@@ -258,7 +258,7 @@
 	if (!conf)
 		return 1;
 	mddev->private = conf;
-	mddev->array_size = conf->array_size;
+	mddev->array_sectors = conf->array_sectors;
 
 	blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec);
 	mddev->queue->unplug_fn = linear_unplug;
@@ -292,8 +292,8 @@
 	newconf->prev = mddev_to_conf(mddev);
 	mddev->private = newconf;
 	mddev->raid_disks++;
-	mddev->array_size = newconf->array_size;
-	set_capacity(mddev->gendisk, mddev->array_size << 1);
+	mddev->array_sectors = newconf->array_sectors;
+	set_capacity(mddev->gendisk, mddev->array_sectors);
 	return 0;
 }
 
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 2580ac1..c2ff77c 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -169,7 +169,6 @@
 {
 	atomic_inc(&md_event_count);
 	wake_up(&md_event_waiters);
-	sysfs_notify(&mddev->kobj, NULL, "sync_action");
 }
 EXPORT_SYMBOL_GPL(md_new_event);
 
@@ -274,10 +273,12 @@
 	INIT_LIST_HEAD(&new->all_mddevs);
 	init_timer(&new->safemode_timer);
 	atomic_set(&new->active, 1);
+	atomic_set(&new->openers, 0);
 	spin_lock_init(&new->write_lock);
 	init_waitqueue_head(&new->sb_wait);
 	init_waitqueue_head(&new->recovery_wait);
 	new->reshape_position = MaxSector;
+	new->resync_min = 0;
 	new->resync_max = MaxSector;
 	new->level = LEVEL_NONE;
 
@@ -347,21 +348,20 @@
 	return NULL;
 }
 
+/* return the offset of the super block in 512byte sectors */
 static inline sector_t calc_dev_sboffset(struct block_device *bdev)
 {
-	sector_t size = bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
-	return MD_NEW_SIZE_BLOCKS(size);
+	sector_t num_sectors = bdev->bd_inode->i_size / 512;
+	return MD_NEW_SIZE_SECTORS(num_sectors);
 }
 
-static sector_t calc_dev_size(mdk_rdev_t *rdev, unsigned chunk_size)
+static sector_t calc_num_sectors(mdk_rdev_t *rdev, unsigned chunk_size)
 {
-	sector_t size;
-
-	size = rdev->sb_offset;
+	sector_t num_sectors = rdev->sb_start;
 
 	if (chunk_size)
-		size &= ~((sector_t)chunk_size/1024 - 1);
-	return size;
+		num_sectors &= ~((sector_t)chunk_size/512 - 1);
+	return num_sectors;
 }
 
 static int alloc_disk_sb(mdk_rdev_t * rdev)
@@ -372,7 +372,7 @@
 	rdev->sb_page = alloc_page(GFP_KERNEL);
 	if (!rdev->sb_page) {
 		printk(KERN_ALERT "md: out of memory.\n");
-		return -EINVAL;
+		return -ENOMEM;
 	}
 
 	return 0;
@@ -384,7 +384,7 @@
 		put_page(rdev->sb_page);
 		rdev->sb_loaded = 0;
 		rdev->sb_page = NULL;
-		rdev->sb_offset = 0;
+		rdev->sb_start = 0;
 		rdev->size = 0;
 	}
 }
@@ -530,7 +530,7 @@
 		return 0;
 
 
-	if (!sync_page_io(rdev->bdev, rdev->sb_offset<<1, size, rdev->sb_page, READ))
+	if (!sync_page_io(rdev->bdev, rdev->sb_start, size, rdev->sb_page, READ))
 		goto fail;
 	rdev->sb_loaded = 1;
 	return 0;
@@ -543,17 +543,12 @@
 
 static int uuid_equal(mdp_super_t *sb1, mdp_super_t *sb2)
 {
-	if (	(sb1->set_uuid0 == sb2->set_uuid0) &&
-		(sb1->set_uuid1 == sb2->set_uuid1) &&
-		(sb1->set_uuid2 == sb2->set_uuid2) &&
-		(sb1->set_uuid3 == sb2->set_uuid3))
-
-		return 1;
-
-	return 0;
+	return 	sb1->set_uuid0 == sb2->set_uuid0 &&
+		sb1->set_uuid1 == sb2->set_uuid1 &&
+		sb1->set_uuid2 == sb2->set_uuid2 &&
+		sb1->set_uuid3 == sb2->set_uuid3;
 }
 
-
 static int sb_equal(mdp_super_t *sb1, mdp_super_t *sb2)
 {
 	int ret;
@@ -564,7 +559,7 @@
 
 	if (!tmp1 || !tmp2) {
 		ret = 0;
-		printk(KERN_INFO "md.c: sb1 is not equal to sb2!\n");
+		printk(KERN_INFO "md.c sb_equal(): failed to allocate memory!\n");
 		goto abort;
 	}
 
@@ -577,11 +572,7 @@
 	tmp1->nr_disks = 0;
 	tmp2->nr_disks = 0;
 
-	if (memcmp(tmp1, tmp2, MD_SB_GENERIC_CONSTANT_WORDS * 4))
-		ret = 0;
-	else
-		ret = 1;
-
+	ret = (memcmp(tmp1, tmp2, MD_SB_GENERIC_CONSTANT_WORDS * 4) == 0);
 abort:
 	kfree(tmp1);
 	kfree(tmp2);
@@ -658,11 +649,14 @@
  */
 
 struct super_type  {
-	char 		*name;
-	struct module	*owner;
-	int		(*load_super)(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version);
-	int		(*validate_super)(mddev_t *mddev, mdk_rdev_t *rdev);
-	void		(*sync_super)(mddev_t *mddev, mdk_rdev_t *rdev);
+	char		    *name;
+	struct module	    *owner;
+	int		    (*load_super)(mdk_rdev_t *rdev, mdk_rdev_t *refdev,
+					  int minor_version);
+	int		    (*validate_super)(mddev_t *mddev, mdk_rdev_t *rdev);
+	void		    (*sync_super)(mddev_t *mddev, mdk_rdev_t *rdev);
+	unsigned long long  (*rdev_size_change)(mdk_rdev_t *rdev,
+						sector_t num_sectors);
 };
 
 /*
@@ -673,16 +667,14 @@
 	char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
 	mdp_super_t *sb;
 	int ret;
-	sector_t sb_offset;
 
 	/*
-	 * Calculate the position of the superblock,
+	 * Calculate the position of the superblock (512byte sectors),
 	 * it's at the end of the disk.
 	 *
 	 * It also happens to be a multiple of 4Kb.
 	 */
-	sb_offset = calc_dev_sboffset(rdev->bdev);
-	rdev->sb_offset = sb_offset;
+	rdev->sb_start = calc_dev_sboffset(rdev->bdev);
 
 	ret = read_disk_sb(rdev, MD_SB_BYTES);
 	if (ret) return ret;
@@ -759,7 +751,7 @@
 		else 
 			ret = 0;
 	}
-	rdev->size = calc_dev_size(rdev, sb->chunk_size);
+	rdev->size = calc_num_sectors(rdev, sb->chunk_size) / 2;
 
 	if (rdev->size < sb->size && sb->level > 1)
 		/* "this cannot possibly happen" ... */
@@ -1004,6 +996,26 @@
 }
 
 /*
+ * rdev_size_change for 0.90.0
+ */
+static unsigned long long
+super_90_rdev_size_change(mdk_rdev_t *rdev, sector_t num_sectors)
+{
+	if (num_sectors && num_sectors < rdev->mddev->size * 2)
+		return 0; /* component must fit device */
+	if (rdev->mddev->bitmap_offset)
+		return 0; /* can't move bitmap */
+	rdev->sb_start = calc_dev_sboffset(rdev->bdev);
+	if (!num_sectors || num_sectors > rdev->sb_start)
+		num_sectors = rdev->sb_start;
+	md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size,
+		       rdev->sb_page);
+	md_super_wait(rdev->mddev);
+	return num_sectors / 2; /* kB for sysfs */
+}
+
+
+/*
  * version 1 superblock
  */
 
@@ -1034,12 +1046,12 @@
 {
 	struct mdp_superblock_1 *sb;
 	int ret;
-	sector_t sb_offset;
+	sector_t sb_start;
 	char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
 	int bmask;
 
 	/*
-	 * Calculate the position of the superblock.
+	 * Calculate the position of the superblock in 512byte sectors.
 	 * It is always aligned to a 4K boundary and
 	 * depeding on minor_version, it can be:
 	 * 0: At least 8K, but less than 12K, from end of device
@@ -1048,22 +1060,20 @@
 	 */
 	switch(minor_version) {
 	case 0:
-		sb_offset = rdev->bdev->bd_inode->i_size >> 9;
-		sb_offset -= 8*2;
-		sb_offset &= ~(sector_t)(4*2-1);
-		/* convert from sectors to K */
-		sb_offset /= 2;
+		sb_start = rdev->bdev->bd_inode->i_size >> 9;
+		sb_start -= 8*2;
+		sb_start &= ~(sector_t)(4*2-1);
 		break;
 	case 1:
-		sb_offset = 0;
+		sb_start = 0;
 		break;
 	case 2:
-		sb_offset = 4;
+		sb_start = 8;
 		break;
 	default:
 		return -EINVAL;
 	}
-	rdev->sb_offset = sb_offset;
+	rdev->sb_start = sb_start;
 
 	/* superblock is rarely larger than 1K, but it can be larger,
 	 * and it is safe to read 4k, so we do that
@@ -1077,7 +1087,7 @@
 	if (sb->magic != cpu_to_le32(MD_SB_MAGIC) ||
 	    sb->major_version != cpu_to_le32(1) ||
 	    le32_to_cpu(sb->max_dev) > (4096-256)/2 ||
-	    le64_to_cpu(sb->super_offset) != (rdev->sb_offset<<1) ||
+	    le64_to_cpu(sb->super_offset) != rdev->sb_start ||
 	    (le32_to_cpu(sb->feature_map) & ~MD_FEATURE_ALL) != 0)
 		return -EINVAL;
 
@@ -1113,7 +1123,7 @@
 		rdev->sb_size = (rdev->sb_size | bmask) + 1;
 
 	if (minor_version
-	    && rdev->data_offset < sb_offset + (rdev->sb_size/512))
+	    && rdev->data_offset < sb_start + (rdev->sb_size/512))
 		return -EINVAL;
 
 	if (sb->level == cpu_to_le32(LEVEL_MULTIPATH))
@@ -1149,7 +1159,7 @@
 	if (minor_version)
 		rdev->size = ((rdev->bdev->bd_inode->i_size>>9) - le64_to_cpu(sb->data_offset)) / 2;
 	else
-		rdev->size = rdev->sb_offset;
+		rdev->size = rdev->sb_start / 2;
 	if (rdev->size < le64_to_cpu(sb->data_size)/2)
 		return -EINVAL;
 	rdev->size = le64_to_cpu(sb->data_size)/2;
@@ -1328,35 +1338,74 @@
 	sb->sb_csum = calc_sb_1_csum(sb);
 }
 
+static unsigned long long
+super_1_rdev_size_change(mdk_rdev_t *rdev, sector_t num_sectors)
+{
+	struct mdp_superblock_1 *sb;
+	sector_t max_sectors;
+	if (num_sectors && num_sectors < rdev->mddev->size * 2)
+		return 0; /* component must fit device */
+	if (rdev->sb_start < rdev->data_offset) {
+		/* minor versions 1 and 2; superblock before data */
+		max_sectors = rdev->bdev->bd_inode->i_size >> 9;
+		max_sectors -= rdev->data_offset;
+		if (!num_sectors || num_sectors > max_sectors)
+			num_sectors = max_sectors;
+	} else if (rdev->mddev->bitmap_offset) {
+		/* minor version 0 with bitmap we can't move */
+		return 0;
+	} else {
+		/* minor version 0; superblock after data */
+		sector_t sb_start;
+		sb_start = (rdev->bdev->bd_inode->i_size >> 9) - 8*2;
+		sb_start &= ~(sector_t)(4*2 - 1);
+		max_sectors = rdev->size * 2 + sb_start - rdev->sb_start;
+		if (!num_sectors || num_sectors > max_sectors)
+			num_sectors = max_sectors;
+		rdev->sb_start = sb_start;
+	}
+	sb = (struct mdp_superblock_1 *) page_address(rdev->sb_page);
+	sb->data_size = cpu_to_le64(num_sectors);
+	sb->super_offset = rdev->sb_start;
+	sb->sb_csum = calc_sb_1_csum(sb);
+	md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size,
+		       rdev->sb_page);
+	md_super_wait(rdev->mddev);
+	return num_sectors / 2; /* kB for sysfs */
+}
 
 static struct super_type super_types[] = {
 	[0] = {
 		.name	= "0.90.0",
 		.owner	= THIS_MODULE,
-		.load_super	= super_90_load,
-		.validate_super	= super_90_validate,
-		.sync_super	= super_90_sync,
+		.load_super	    = super_90_load,
+		.validate_super	    = super_90_validate,
+		.sync_super	    = super_90_sync,
+		.rdev_size_change   = super_90_rdev_size_change,
 	},
 	[1] = {
 		.name	= "md-1",
 		.owner	= THIS_MODULE,
-		.load_super	= super_1_load,
-		.validate_super	= super_1_validate,
-		.sync_super	= super_1_sync,
+		.load_super	    = super_1_load,
+		.validate_super	    = super_1_validate,
+		.sync_super	    = super_1_sync,
+		.rdev_size_change   = super_1_rdev_size_change,
 	},
 };
 
 static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2)
 {
-	struct list_head *tmp, *tmp2;
 	mdk_rdev_t *rdev, *rdev2;
 
-	rdev_for_each(rdev, tmp, mddev1)
-		rdev_for_each(rdev2, tmp2, mddev2)
+	rcu_read_lock();
+	rdev_for_each_rcu(rdev, mddev1)
+		rdev_for_each_rcu(rdev2, mddev2)
 			if (rdev->bdev->bd_contains ==
-			    rdev2->bdev->bd_contains)
+			    rdev2->bdev->bd_contains) {
+				rcu_read_unlock();
 				return 1;
-
+			}
+	rcu_read_unlock();
 	return 0;
 }
 
@@ -1423,7 +1472,7 @@
 		kobject_del(&rdev->kobj);
 		goto fail;
 	}
-	list_add(&rdev->same_set, &mddev->disks);
+	list_add_rcu(&rdev->same_set, &mddev->disks);
 	bd_claim_by_disk(rdev->bdev, rdev->bdev->bd_holder, mddev->gendisk);
 	return 0;
 
@@ -1448,14 +1497,16 @@
 		return;
 	}
 	bd_release_from_disk(rdev->bdev, rdev->mddev->gendisk);
-	list_del_init(&rdev->same_set);
+	list_del_rcu(&rdev->same_set);
 	printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b));
 	rdev->mddev = NULL;
 	sysfs_remove_link(&rdev->kobj, "block");
 
 	/* We need to delay this, otherwise we can deadlock when
-	 * writing to 'remove' to "dev/state"
+	 * writing to 'remove' to "dev/state".  We also need
+	 * to delay it due to rcu usage.
 	 */
+	synchronize_rcu();
 	INIT_WORK(&rdev->del_work, md_delayed_delete);
 	kobject_get(&rdev->kobj);
 	schedule_work(&rdev->del_work);
@@ -1511,7 +1562,6 @@
 	if (rdev->mddev)
 		MD_BUG();
 	free_disk_sb(rdev);
-	list_del_init(&rdev->same_set);
 #ifndef MODULE
 	if (test_bit(AutoDetected, &rdev->flags))
 		md_autodetect_dev(rdev->bdev->bd_dev);
@@ -1758,11 +1808,11 @@
 		dprintk("%s ", bdevname(rdev->bdev,b));
 		if (!test_bit(Faulty, &rdev->flags)) {
 			md_super_write(mddev,rdev,
-				       rdev->sb_offset<<1, rdev->sb_size,
+				       rdev->sb_start, rdev->sb_size,
 				       rdev->sb_page);
 			dprintk(KERN_INFO "(write) %s's sb offset: %llu\n",
 				bdevname(rdev->bdev,b),
-				(unsigned long long)rdev->sb_offset);
+				(unsigned long long)rdev->sb_start);
 			rdev->sb_events = mddev->events;
 
 		} else
@@ -1787,7 +1837,7 @@
 
 }
 
-/* words written to sysfs files may, or my not, be \n terminated.
+/* words written to sysfs files may, or may not, be \n terminated.
  * We want to accept with case. For this we use cmd_match.
  */
 static int cmd_match(const char *cmd, const char *str)
@@ -1886,6 +1936,8 @@
 
 		err = 0;
 	}
+	if (!err)
+		sysfs_notify(&rdev->kobj, NULL, "state");
 	return err ? err : len;
 }
 static struct rdev_sysfs_entry rdev_state =
@@ -1931,7 +1983,7 @@
 		slot = -1;
 	else if (e==buf || (*e && *e!= '\n'))
 		return -EINVAL;
-	if (rdev->mddev->pers) {
+	if (rdev->mddev->pers && slot == -1) {
 		/* Setting 'slot' on an active array requires also
 		 * updating the 'rd%d' link, and communicating
 		 * with the personality with ->hot_*_disk.
@@ -1939,8 +1991,6 @@
 		 * failed/spare devices.  This normally happens automatically,
 		 * but not when the metadata is externally managed.
 		 */
-		if (slot != -1)
-			return -EBUSY;
 		if (rdev->raid_disk == -1)
 			return -EEXIST;
 		/* personality does all needed checks */
@@ -1954,6 +2004,43 @@
 		sysfs_remove_link(&rdev->mddev->kobj, nm);
 		set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery);
 		md_wakeup_thread(rdev->mddev->thread);
+	} else if (rdev->mddev->pers) {
+		mdk_rdev_t *rdev2;
+		struct list_head *tmp;
+		/* Activating a spare .. or possibly reactivating
+		 * if we every get bitmaps working here.
+		 */
+
+		if (rdev->raid_disk != -1)
+			return -EBUSY;
+
+		if (rdev->mddev->pers->hot_add_disk == NULL)
+			return -EINVAL;
+
+		rdev_for_each(rdev2, tmp, rdev->mddev)
+			if (rdev2->raid_disk == slot)
+				return -EEXIST;
+
+		rdev->raid_disk = slot;
+		if (test_bit(In_sync, &rdev->flags))
+			rdev->saved_raid_disk = slot;
+		else
+			rdev->saved_raid_disk = -1;
+		err = rdev->mddev->pers->
+			hot_add_disk(rdev->mddev, rdev);
+		if (err) {
+			rdev->raid_disk = -1;
+			return err;
+		} else
+			sysfs_notify(&rdev->kobj, NULL, "state");
+		sprintf(nm, "rd%d", rdev->raid_disk);
+		if (sysfs_create_link(&rdev->mddev->kobj, &rdev->kobj, nm))
+			printk(KERN_WARNING
+			       "md: cannot register "
+			       "%s for %s\n",
+			       nm, mdname(rdev->mddev));
+
+		/* don't wakeup anyone, leave that to userspace. */
 	} else {
 		if (slot >= rdev->mddev->raid_disks)
 			return -ENOSPC;
@@ -1962,6 +2049,7 @@
 		clear_bit(Faulty, &rdev->flags);
 		clear_bit(WriteMostly, &rdev->flags);
 		set_bit(In_sync, &rdev->flags);
+		sysfs_notify(&rdev->kobj, NULL, "state");
 	}
 	return len;
 }
@@ -1983,7 +2071,7 @@
 	unsigned long long offset = simple_strtoull(buf, &e, 10);
 	if (e==buf || (*e && *e != '\n'))
 		return -EINVAL;
-	if (rdev->mddev->pers)
+	if (rdev->mddev->pers && rdev->raid_disk >= 0)
 		return -EBUSY;
 	if (rdev->size && rdev->mddev->external)
 		/* Must set offset before size, so overlap checks
@@ -2015,17 +2103,30 @@
 static ssize_t
 rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len)
 {
-	char *e;
-	unsigned long long size = simple_strtoull(buf, &e, 10);
+	unsigned long long size;
 	unsigned long long oldsize = rdev->size;
 	mddev_t *my_mddev = rdev->mddev;
 
-	if (e==buf || (*e && *e != '\n'))
+	if (strict_strtoull(buf, 10, &size) < 0)
 		return -EINVAL;
-	if (my_mddev->pers)
-		return -EBUSY;
+	if (size < my_mddev->size)
+		return -EINVAL;
+	if (my_mddev->pers && rdev->raid_disk >= 0) {
+		if (my_mddev->persistent) {
+			size = super_types[my_mddev->major_version].
+				rdev_size_change(rdev, size * 2);
+			if (!size)
+				return -EBUSY;
+		} else if (!size) {
+			size = (rdev->bdev->bd_inode->i_size >> 10);
+			size -= rdev->data_offset/2;
+		}
+		if (size < my_mddev->size)
+			return -EINVAL; /* component must fit device */
+	}
+
 	rdev->size = size;
-	if (size > oldsize && rdev->mddev->external) {
+	if (size > oldsize && my_mddev->external) {
 		/* need to check that all other rdevs with the same ->bdev
 		 * do not overlap.  We need to unlock the mddev to avoid
 		 * a deadlock.  We have already changed rdev->size, and if
@@ -2044,8 +2145,9 @@
 				if (test_bit(AllReserved, &rdev2->flags) ||
 				    (rdev->bdev == rdev2->bdev &&
 				     rdev != rdev2 &&
-				     overlaps(rdev->data_offset, rdev->size,
-					    rdev2->data_offset, rdev2->size))) {
+				     overlaps(rdev->data_offset, rdev->size * 2,
+					      rdev2->data_offset,
+					      rdev2->size * 2))) {
 					overlap = 1;
 					break;
 				}
@@ -2067,8 +2169,6 @@
 			return -EBUSY;
 		}
 	}
-	if (size < my_mddev->size || my_mddev->size == 0)
-		my_mddev->size = size;
 	return len;
 }
 
@@ -2512,7 +2612,7 @@
  *     When written, doesn't tear down array, but just stops it
  * suspended (not supported yet)
  *     All IO requests will block. The array can be reconfigured.
- *     Writing this, if accepted, will block until array is quiessent
+ *     Writing this, if accepted, will block until array is quiescent
  * readonly
  *     no resync can happen.  no superblocks get written.
  *     write requests fail
@@ -2585,7 +2685,7 @@
 	return sprintf(page, "%s\n", array_states[st]);
 }
 
-static int do_md_stop(mddev_t * mddev, int ro);
+static int do_md_stop(mddev_t * mddev, int ro, int is_open);
 static int do_md_run(mddev_t * mddev);
 static int restart_array(mddev_t *mddev);
 
@@ -2599,16 +2699,16 @@
 		break;
 	case clear:
 		/* stopping an active array */
-		if (atomic_read(&mddev->active) > 1)
+		if (atomic_read(&mddev->openers) > 0)
 			return -EBUSY;
-		err = do_md_stop(mddev, 0);
+		err = do_md_stop(mddev, 0, 0);
 		break;
 	case inactive:
 		/* stopping an active array */
 		if (mddev->pers) {
-			if (atomic_read(&mddev->active) > 1)
+			if (atomic_read(&mddev->openers) > 0)
 				return -EBUSY;
-			err = do_md_stop(mddev, 2);
+			err = do_md_stop(mddev, 2, 0);
 		} else
 			err = 0; /* already inactive */
 		break;
@@ -2616,7 +2716,7 @@
 		break; /* not supported yet */
 	case readonly:
 		if (mddev->pers)
-			err = do_md_stop(mddev, 1);
+			err = do_md_stop(mddev, 1, 0);
 		else {
 			mddev->ro = 1;
 			set_disk_ro(mddev->gendisk, 1);
@@ -2626,7 +2726,7 @@
 	case read_auto:
 		if (mddev->pers) {
 			if (mddev->ro != 1)
-				err = do_md_stop(mddev, 1);
+				err = do_md_stop(mddev, 1, 0);
 			else
 				err = restart_array(mddev);
 			if (err == 0) {
@@ -2681,8 +2781,10 @@
 	}
 	if (err)
 		return err;
-	else
+	else {
+		sysfs_notify(&mddev->kobj, NULL, "array_state");
 		return len;
+	}
 }
 static struct md_sysfs_entry md_array_state =
 __ATTR(array_state, S_IRUGO|S_IWUSR, array_state_show, array_state_store);
@@ -2785,7 +2887,7 @@
 	return sprintf(page, "%llu\n", (unsigned long long)mddev->size);
 }
 
-static int update_size(mddev_t *mddev, unsigned long size);
+static int update_size(mddev_t *mddev, sector_t num_sectors);
 
 static ssize_t
 size_store(mddev_t *mddev, const char *buf, size_t len)
@@ -2802,7 +2904,7 @@
 		return -EINVAL;
 
 	if (mddev->pers) {
-		err = update_size(mddev, size);
+		err = update_size(mddev, size * 2);
 		md_update_sb(mddev, 1);
 	} else {
 		if (mddev->size == 0 ||
@@ -2899,7 +3001,7 @@
 				type = "check";
 			else
 				type = "repair";
-		} else
+		} else if (test_bit(MD_RECOVERY_RECOVER, &mddev->recovery))
 			type = "recover";
 	}
 	return sprintf(page, "%s\n", type);
@@ -2921,15 +3023,19 @@
 	} else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
 		   test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
 		return -EBUSY;
-	else if (cmd_match(page, "resync") || cmd_match(page, "recover"))
+	else if (cmd_match(page, "resync"))
 		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
-	else if (cmd_match(page, "reshape")) {
+	else if (cmd_match(page, "recover")) {
+		set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
+		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+	} else if (cmd_match(page, "reshape")) {
 		int err;
 		if (mddev->pers->start_reshape == NULL)
 			return -EINVAL;
 		err = mddev->pers->start_reshape(mddev);
 		if (err)
 			return err;
+		sysfs_notify(&mddev->kobj, NULL, "degraded");
 	} else {
 		if (cmd_match(page, "check"))
 			set_bit(MD_RECOVERY_CHECK, &mddev->recovery);
@@ -2940,6 +3046,7 @@
 	}
 	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 	md_wakeup_thread(mddev->thread);
+	sysfs_notify(&mddev->kobj, NULL, "sync_action");
 	return len;
 }
 
@@ -3049,11 +3156,11 @@
 sync_speed_show(mddev_t *mddev, char *page)
 {
 	unsigned long resync, dt, db;
-	resync = (mddev->curr_mark_cnt - atomic_read(&mddev->recovery_active));
-	dt = ((jiffies - mddev->resync_mark) / HZ);
+	resync = mddev->curr_mark_cnt - atomic_read(&mddev->recovery_active);
+	dt = (jiffies - mddev->resync_mark) / HZ;
 	if (!dt) dt++;
-	db = resync - (mddev->resync_mark_cnt);
-	return sprintf(page, "%ld\n", db/dt/2); /* K/sec */
+	db = resync - mddev->resync_mark_cnt;
+	return sprintf(page, "%lu\n", db/dt/2); /* K/sec */
 }
 
 static struct md_sysfs_entry md_sync_speed = __ATTR_RO(sync_speed);
@@ -3075,6 +3182,36 @@
 static struct md_sysfs_entry md_sync_completed = __ATTR_RO(sync_completed);
 
 static ssize_t
+min_sync_show(mddev_t *mddev, char *page)
+{
+	return sprintf(page, "%llu\n",
+		       (unsigned long long)mddev->resync_min);
+}
+static ssize_t
+min_sync_store(mddev_t *mddev, const char *buf, size_t len)
+{
+	unsigned long long min;
+	if (strict_strtoull(buf, 10, &min))
+		return -EINVAL;
+	if (min > mddev->resync_max)
+		return -EINVAL;
+	if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
+		return -EBUSY;
+
+	/* Must be a multiple of chunk_size */
+	if (mddev->chunk_size) {
+		if (min & (sector_t)((mddev->chunk_size>>9)-1))
+			return -EINVAL;
+	}
+	mddev->resync_min = min;
+
+	return len;
+}
+
+static struct md_sysfs_entry md_min_sync =
+__ATTR(sync_min, S_IRUGO|S_IWUSR, min_sync_show, min_sync_store);
+
+static ssize_t
 max_sync_show(mddev_t *mddev, char *page)
 {
 	if (mddev->resync_max == MaxSector)
@@ -3089,9 +3226,10 @@
 	if (strncmp(buf, "max", 3) == 0)
 		mddev->resync_max = MaxSector;
 	else {
-		char *ep;
-		unsigned long long max = simple_strtoull(buf, &ep, 10);
-		if (ep == buf || (*ep != 0 && *ep != '\n'))
+		unsigned long long max;
+		if (strict_strtoull(buf, 10, &max))
+			return -EINVAL;
+		if (max < mddev->resync_min)
 			return -EINVAL;
 		if (max < mddev->resync_max &&
 		    test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
@@ -3222,6 +3360,7 @@
 	&md_sync_speed.attr,
 	&md_sync_force_parallel.attr,
 	&md_sync_completed.attr,
+	&md_min_sync.attr,
 	&md_max_sync.attr,
 	&md_suspend_lo.attr,
 	&md_suspend_hi.attr,
@@ -3326,9 +3465,9 @@
 	disk->queue = mddev->queue;
 	add_disk(disk);
 	mddev->gendisk = disk;
-	mutex_unlock(&disks_mutex);
 	error = kobject_init_and_add(&mddev->kobj, &md_ktype, &disk->dev.kobj,
 				     "%s", "md");
+	mutex_unlock(&disks_mutex);
 	if (error)
 		printk(KERN_WARNING "md: cannot register %s/md - name in use\n",
 		       disk->disk_name);
@@ -3341,7 +3480,11 @@
 {
 	mddev_t *mddev = (mddev_t *) data;
 
-	mddev->safemode = 1;
+	if (!atomic_read(&mddev->writes_pending)) {
+		mddev->safemode = 1;
+		if (mddev->external)
+			sysfs_notify(&mddev->kobj, NULL, "array_state");
+	}
 	md_wakeup_thread(mddev->thread);
 }
 
@@ -3432,22 +3575,23 @@
 		 * We don't want the data to overlap the metadata,
 		 * Internal Bitmap issues has handled elsewhere.
 		 */
-		if (rdev->data_offset < rdev->sb_offset) {
+		if (rdev->data_offset < rdev->sb_start) {
 			if (mddev->size &&
 			    rdev->data_offset + mddev->size*2
-			    > rdev->sb_offset*2) {
+			    > rdev->sb_start) {
 				printk("md: %s: data overlaps metadata\n",
 				       mdname(mddev));
 				return -EINVAL;
 			}
 		} else {
-			if (rdev->sb_offset*2 + rdev->sb_size/512
+			if (rdev->sb_start + rdev->sb_size/512
 			    > rdev->data_offset) {
 				printk("md: %s: metadata overlaps data\n",
 				       mdname(mddev));
 				return -EINVAL;
 			}
 		}
+		sysfs_notify(&rdev->kobj, NULL, "state");
 	}
 
 	md_probe(mddev->unit, NULL, NULL);
@@ -3519,7 +3663,9 @@
 		mddev->ro = 2; /* read-only, but switch on first write */
 
 	err = mddev->pers->run(mddev);
-	if (!err && mddev->pers->sync_request) {
+	if (err)
+		printk(KERN_ERR "md: pers->run() failed ...\n");
+	else if (mddev->pers->sync_request) {
 		err = bitmap_create(mddev);
 		if (err) {
 			printk(KERN_ERR "%s: failed to create bitmap (%d)\n",
@@ -3528,7 +3674,6 @@
 		}
 	}
 	if (err) {
-		printk(KERN_ERR "md: pers->run() failed ...\n");
 		module_put(mddev->pers->owner);
 		mddev->pers = NULL;
 		bitmap_destroy(mddev);
@@ -3563,7 +3708,7 @@
 	if (mddev->flags)
 		md_update_sb(mddev, 0);
 
-	set_capacity(disk, mddev->array_size<<1);
+	set_capacity(disk, mddev->array_sectors);
 
 	/* If we call blk_queue_make_request here, it will
 	 * re-initialise max_sectors etc which may have been
@@ -3608,6 +3753,9 @@
 
 	mddev->changed = 1;
 	md_new_event(mddev);
+	sysfs_notify(&mddev->kobj, NULL, "array_state");
+	sysfs_notify(&mddev->kobj, NULL, "sync_action");
+	sysfs_notify(&mddev->kobj, NULL, "degraded");
 	kobject_uevent(&mddev->gendisk->dev.kobj, KOBJ_CHANGE);
 	return 0;
 }
@@ -3615,38 +3763,25 @@
 static int restart_array(mddev_t *mddev)
 {
 	struct gendisk *disk = mddev->gendisk;
-	int err;
 
-	/*
-	 * Complain if it has no devices
-	 */
-	err = -ENXIO;
+	/* Complain if it has no devices */
 	if (list_empty(&mddev->disks))
-		goto out;
-
-	if (mddev->pers) {
-		err = -EBUSY;
-		if (!mddev->ro)
-			goto out;
-
-		mddev->safemode = 0;
-		mddev->ro = 0;
-		set_disk_ro(disk, 0);
-
-		printk(KERN_INFO "md: %s switched to read-write mode.\n",
-			mdname(mddev));
-		/*
-		 * Kick recovery or resync if necessary
-		 */
-		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
-		md_wakeup_thread(mddev->thread);
-		md_wakeup_thread(mddev->sync_thread);
-		err = 0;
-	} else
-		err = -EINVAL;
-
-out:
-	return err;
+		return -ENXIO;
+	if (!mddev->pers)
+		return -EINVAL;
+	if (!mddev->ro)
+		return -EBUSY;
+	mddev->safemode = 0;
+	mddev->ro = 0;
+	set_disk_ro(disk, 0);
+	printk(KERN_INFO "md: %s switched to read-write mode.\n",
+		mdname(mddev));
+	/* Kick recovery or resync if necessary */
+	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+	md_wakeup_thread(mddev->thread);
+	md_wakeup_thread(mddev->sync_thread);
+	sysfs_notify(&mddev->kobj, NULL, "array_state");
+	return 0;
 }
 
 /* similar to deny_write_access, but accounts for our holding a reference
@@ -3680,16 +3815,17 @@
  *   1 - switch to readonly
  *   2 - stop but do not disassemble array
  */
-static int do_md_stop(mddev_t * mddev, int mode)
+static int do_md_stop(mddev_t * mddev, int mode, int is_open)
 {
 	int err = 0;
 	struct gendisk *disk = mddev->gendisk;
 
+	if (atomic_read(&mddev->openers) > is_open) {
+		printk("md: %s still in use.\n",mdname(mddev));
+		return -EBUSY;
+	}
+
 	if (mddev->pers) {
-		if (atomic_read(&mddev->active)>2) {
-			printk("md: %s still in use.\n",mdname(mddev));
-			return -EBUSY;
-		}
 
 		if (mddev->sync_thread) {
 			set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
@@ -3773,10 +3909,11 @@
 
 		export_array(mddev);
 
-		mddev->array_size = 0;
+		mddev->array_sectors = 0;
 		mddev->size = 0;
 		mddev->raid_disks = 0;
 		mddev->recovery_cp = 0;
+		mddev->resync_min = 0;
 		mddev->resync_max = MaxSector;
 		mddev->reshape_position = MaxSector;
 		mddev->external = 0;
@@ -3811,6 +3948,7 @@
 			mdname(mddev));
 	err = 0;
 	md_new_event(mddev);
+	sysfs_notify(&mddev->kobj, NULL, "array_state");
 out:
 	return err;
 }
@@ -3836,7 +3974,7 @@
 	err = do_md_run (mddev);
 	if (err) {
 		printk(KERN_WARNING "md: do_md_run() returned %d\n", err);
-		do_md_stop (mddev, 0);
+		do_md_stop (mddev, 0, 0);
 	}
 }
 
@@ -3927,8 +4065,10 @@
 		/* on success, candidates will be empty, on error
 		 * it won't...
 		 */
-		rdev_for_each_list(rdev, tmp, candidates)
+		rdev_for_each_list(rdev, tmp, candidates) {
+			list_del_init(&rdev->same_set);
 			export_rdev(rdev);
+		}
 		mddev_put(mddev);
 	}
 	printk(KERN_INFO "md: ... autorun DONE.\n");
@@ -4009,9 +4149,11 @@
 	char *ptr, *buf = NULL;
 	int err = -ENOMEM;
 
-	md_allow_write(mddev);
+	if (md_allow_write(mddev))
+		file = kmalloc(sizeof(*file), GFP_NOIO);
+	else
+		file = kmalloc(sizeof(*file), GFP_KERNEL);
 
-	file = kmalloc(sizeof(*file), GFP_KERNEL);
 	if (!file)
 		goto out;
 
@@ -4044,15 +4186,12 @@
 static int get_disk_info(mddev_t * mddev, void __user * arg)
 {
 	mdu_disk_info_t info;
-	unsigned int nr;
 	mdk_rdev_t *rdev;
 
 	if (copy_from_user(&info, arg, sizeof(info)))
 		return -EFAULT;
 
-	nr = info.number;
-
-	rdev = find_rdev_nr(mddev, nr);
+	rdev = find_rdev_nr(mddev, info.number);
 	if (rdev) {
 		info.major = MAJOR(rdev->bdev->bd_dev);
 		info.minor = MINOR(rdev->bdev->bd_dev);
@@ -4172,8 +4311,12 @@
 		}
 		if (err)
 			export_rdev(rdev);
+		else
+			sysfs_notify(&rdev->kobj, NULL, "state");
 
 		md_update_sb(mddev, 1);
+		if (mddev->degraded)
+			set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
 		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 		md_wakeup_thread(mddev->thread);
 		return err;
@@ -4212,10 +4355,10 @@
 
 		if (!mddev->persistent) {
 			printk(KERN_INFO "md: nonpersistent superblock ...\n");
-			rdev->sb_offset = rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
+			rdev->sb_start = rdev->bdev->bd_inode->i_size / 512;
 		} else 
-			rdev->sb_offset = calc_dev_sboffset(rdev->bdev);
-		rdev->size = calc_dev_size(rdev, mddev->chunk_size);
+			rdev->sb_start = calc_dev_sboffset(rdev->bdev);
+		rdev->size = calc_num_sectors(rdev, mddev->chunk_size) / 2;
 
 		err = bind_rdev_to_array(rdev, mddev);
 		if (err) {
@@ -4232,9 +4375,6 @@
 	char b[BDEVNAME_SIZE];
 	mdk_rdev_t *rdev;
 
-	if (!mddev->pers)
-		return -ENODEV;
-
 	rdev = find_rdev(mddev, dev);
 	if (!rdev)
 		return -ENXIO;
@@ -4257,7 +4397,6 @@
 {
 	char b[BDEVNAME_SIZE];
 	int err;
-	unsigned int size;
 	mdk_rdev_t *rdev;
 
 	if (!mddev->pers)
@@ -4285,13 +4424,11 @@
 	}
 
 	if (mddev->persistent)
-		rdev->sb_offset = calc_dev_sboffset(rdev->bdev);
+		rdev->sb_start = calc_dev_sboffset(rdev->bdev);
 	else
-		rdev->sb_offset =
-			rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
+		rdev->sb_start = rdev->bdev->bd_inode->i_size / 512;
 
-	size = calc_dev_size(rdev, mddev->chunk_size);
-	rdev->size = size;
+	rdev->size = calc_num_sectors(rdev, mddev->chunk_size) / 2;
 
 	if (test_bit(Faulty, &rdev->flags)) {
 		printk(KERN_WARNING 
@@ -4476,24 +4613,24 @@
 	return 0;
 }
 
-static int update_size(mddev_t *mddev, unsigned long size)
+static int update_size(mddev_t *mddev, sector_t num_sectors)
 {
 	mdk_rdev_t * rdev;
 	int rv;
 	struct list_head *tmp;
-	int fit = (size == 0);
+	int fit = (num_sectors == 0);
 
 	if (mddev->pers->resize == NULL)
 		return -EINVAL;
-	/* The "size" is the amount of each device that is used.
-	 * This can only make sense for arrays with redundancy.
-	 * linear and raid0 always use whatever space is available
-	 * We can only consider changing the size if no resync
-	 * or reconstruction is happening, and if the new size
-	 * is acceptable. It must fit before the sb_offset or,
-	 * if that is <data_offset, it must fit before the
-	 * size of each device.
-	 * If size is zero, we find the largest size that fits.
+	/* The "num_sectors" is the number of sectors of each device that
+	 * is used.  This can only make sense for arrays with redundancy.
+	 * linear and raid0 always use whatever space is available. We can only
+	 * consider changing this number if no resync or reconstruction is
+	 * happening, and if the new size is acceptable. It must fit before the
+	 * sb_start or, if that is <data_offset, it must fit before the size
+	 * of each device.  If num_sectors is zero, we find the largest size
+	 * that fits.
+
 	 */
 	if (mddev->sync_thread)
 		return -EBUSY;
@@ -4501,19 +4638,20 @@
 		sector_t avail;
 		avail = rdev->size * 2;
 
-		if (fit && (size == 0 || size > avail/2))
-			size = avail/2;
-		if (avail < ((sector_t)size << 1))
+		if (fit && (num_sectors == 0 || num_sectors > avail))
+			num_sectors = avail;
+		if (avail < num_sectors)
 			return -ENOSPC;
 	}
-	rv = mddev->pers->resize(mddev, (sector_t)size *2);
+	rv = mddev->pers->resize(mddev, num_sectors);
 	if (!rv) {
 		struct block_device *bdev;
 
 		bdev = bdget_disk(mddev->gendisk, 0);
 		if (bdev) {
 			mutex_lock(&bdev->bd_inode->i_mutex);
-			i_size_write(bdev->bd_inode, (loff_t)mddev->array_size << 10);
+			i_size_write(bdev->bd_inode,
+				     (loff_t)mddev->array_sectors << 9);
 			mutex_unlock(&bdev->bd_inode->i_mutex);
 			bdput(bdev);
 		}
@@ -4588,7 +4726,7 @@
 			return mddev->pers->reconfig(mddev, info->layout, -1);
 	}
 	if (info->size >= 0 && mddev->size != info->size)
-		rv = update_size(mddev, info->size);
+		rv = update_size(mddev, (sector_t)info->size * 2);
 
 	if (mddev->raid_disks    != info->raid_disks)
 		rv = update_raid_disks(mddev, info->raid_disks);
@@ -4641,6 +4779,12 @@
 	return 0;
 }
 
+/*
+ * We have a problem here : there is no easy way to give a CHS
+ * virtual geometry. We currently pretend that we have a 2 heads
+ * 4 sectors (with a BIG number of cylinders...). This drives
+ * dosfs just mad... ;-)
+ */
 static int md_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 {
 	mddev_t *mddev = bdev->bd_disk->private_data;
@@ -4785,19 +4929,13 @@
 			goto done_unlock;
 
 		case STOP_ARRAY:
-			err = do_md_stop (mddev, 0);
+			err = do_md_stop (mddev, 0, 1);
 			goto done_unlock;
 
 		case STOP_ARRAY_RO:
-			err = do_md_stop (mddev, 1);
+			err = do_md_stop (mddev, 1, 1);
 			goto done_unlock;
 
-	/*
-	 * We have a problem here : there is no easy way to give a CHS
-	 * virtual geometry. We currently pretend that we have a 2 heads
-	 * 4 sectors (with a BIG number of cylinders...). This drives
-	 * dosfs just mad... ;-)
-	 */
 	}
 
 	/*
@@ -4807,13 +4945,12 @@
 	 * here and hit the 'default' below, so only disallow
 	 * 'md' ioctls, and switch to rw mode if started auto-readonly.
 	 */
-	if (_IOC_TYPE(cmd) == MD_MAJOR &&
-	    mddev->ro && mddev->pers) {
+	if (_IOC_TYPE(cmd) == MD_MAJOR && mddev->ro && mddev->pers) {
 		if (mddev->ro == 2) {
 			mddev->ro = 0;
-		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
-		md_wakeup_thread(mddev->thread);
-
+			sysfs_notify(&mddev->kobj, NULL, "array_state");
+			set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+			md_wakeup_thread(mddev->thread);
 		} else {
 			err = -EROFS;
 			goto abort_unlock;
@@ -4883,6 +5020,7 @@
 
 	err = 0;
 	mddev_get(mddev);
+	atomic_inc(&mddev->openers);
 	mddev_unlock(mddev);
 
 	check_disk_change(inode->i_bdev);
@@ -4895,6 +5033,7 @@
  	mddev_t *mddev = inode->i_bdev->bd_disk->private_data;
 
 	BUG_ON(!mddev);
+	atomic_dec(&mddev->openers);
 	mddev_put(mddev);
 
 	return 0;
@@ -5029,6 +5168,9 @@
 	if (!mddev->pers->error_handler)
 		return;
 	mddev->pers->error_handler(mddev,rdev);
+	if (mddev->degraded)
+		set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
+	set_bit(StateChanged, &rdev->flags);
 	set_bit(MD_RECOVERY_INTR, &mddev->recovery);
 	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 	md_wakeup_thread(mddev->thread);
@@ -5258,10 +5400,11 @@
 		if (!list_empty(&mddev->disks)) {
 			if (mddev->pers)
 				seq_printf(seq, "\n      %llu blocks",
-					(unsigned long long)mddev->array_size);
+					   (unsigned long long)
+					   mddev->array_sectors / 2);
 			else
 				seq_printf(seq, "\n      %llu blocks",
-					(unsigned long long)size);
+					   (unsigned long long)size);
 		}
 		if (mddev->persistent) {
 			if (mddev->major_version != 0 ||
@@ -5391,12 +5534,12 @@
 static int is_mddev_idle(mddev_t *mddev)
 {
 	mdk_rdev_t * rdev;
-	struct list_head *tmp;
 	int idle;
 	long curr_events;
 
 	idle = 1;
-	rdev_for_each(rdev, tmp, mddev) {
+	rcu_read_lock();
+	rdev_for_each_rcu(rdev, mddev) {
 		struct gendisk *disk = rdev->bdev->bd_contains->bd_disk;
 		curr_events = disk_stat_read(disk, sectors[0]) + 
 				disk_stat_read(disk, sectors[1]) - 
@@ -5428,6 +5571,7 @@
 			idle = 0;
 		}
 	}
+	rcu_read_unlock();
 	return idle;
 }
 
@@ -5451,6 +5595,7 @@
  */
 void md_write_start(mddev_t *mddev, struct bio *bi)
 {
+	int did_change = 0;
 	if (bio_data_dir(bi) != WRITE)
 		return;
 
@@ -5461,6 +5606,7 @@
 		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 		md_wakeup_thread(mddev->thread);
 		md_wakeup_thread(mddev->sync_thread);
+		did_change = 1;
 	}
 	atomic_inc(&mddev->writes_pending);
 	if (mddev->safemode == 1)
@@ -5471,10 +5617,12 @@
 			mddev->in_sync = 0;
 			set_bit(MD_CHANGE_CLEAN, &mddev->flags);
 			md_wakeup_thread(mddev->thread);
+			did_change = 1;
 		}
 		spin_unlock_irq(&mddev->write_lock);
-		sysfs_notify(&mddev->kobj, NULL, "array_state");
 	}
+	if (did_change)
+		sysfs_notify(&mddev->kobj, NULL, "array_state");
 	wait_event(mddev->sb_wait,
 		   !test_bit(MD_CHANGE_CLEAN, &mddev->flags) &&
 		   !test_bit(MD_CHANGE_PENDING, &mddev->flags));
@@ -5495,13 +5643,18 @@
  * may proceed without blocking.  It is important to call this before
  * attempting a GFP_KERNEL allocation while holding the mddev lock.
  * Must be called with mddev_lock held.
+ *
+ * In the ->external case MD_CHANGE_CLEAN can not be cleared until mddev->lock
+ * is dropped, so return -EAGAIN after notifying userspace.
  */
-void md_allow_write(mddev_t *mddev)
+int md_allow_write(mddev_t *mddev)
 {
 	if (!mddev->pers)
-		return;
+		return 0;
 	if (mddev->ro)
-		return;
+		return 0;
+	if (!mddev->pers->sync_request)
+		return 0;
 
 	spin_lock_irq(&mddev->write_lock);
 	if (mddev->in_sync) {
@@ -5512,14 +5665,14 @@
 			mddev->safemode = 1;
 		spin_unlock_irq(&mddev->write_lock);
 		md_update_sb(mddev, 0);
-
 		sysfs_notify(&mddev->kobj, NULL, "array_state");
-		/* wait for the dirty state to be recorded in the metadata */
-		wait_event(mddev->sb_wait,
-			   !test_bit(MD_CHANGE_CLEAN, &mddev->flags) &&
-			   !test_bit(MD_CHANGE_PENDING, &mddev->flags));
 	} else
 		spin_unlock_irq(&mddev->write_lock);
+
+	if (test_bit(MD_CHANGE_CLEAN, &mddev->flags))
+		return -EAGAIN;
+	else
+		return 0;
 }
 EXPORT_SYMBOL_GPL(md_allow_write);
 
@@ -5625,9 +5778,11 @@
 		max_sectors = mddev->resync_max_sectors;
 		mddev->resync_mismatches = 0;
 		/* we don't use the checkpoint if there's a bitmap */
-		if (!mddev->bitmap &&
-		    !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
+		if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
+			j = mddev->resync_min;
+		else if (!mddev->bitmap)
 			j = mddev->recovery_cp;
+
 	} else if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
 		max_sectors = mddev->size << 1;
 	else {
@@ -5796,6 +5951,7 @@
 
  skip:
 	mddev->curr_resync = 0;
+	mddev->resync_min = 0;
 	mddev->resync_max = MaxSector;
 	sysfs_notify(&mddev->kobj, NULL, "sync_completed");
 	wake_up(&resync_wait);
@@ -5845,7 +6001,8 @@
 			if (rdev->raid_disk < 0
 			    && !test_bit(Faulty, &rdev->flags)) {
 				rdev->recovery_offset = 0;
-				if (mddev->pers->hot_add_disk(mddev,rdev)) {
+				if (mddev->pers->
+				    hot_add_disk(mddev, rdev) == 0) {
 					char nm[20];
 					sprintf(nm, "rd%d", rdev->raid_disk);
 					if (sysfs_create_link(&mddev->kobj,
@@ -5920,23 +6077,31 @@
 		int spares = 0;
 
 		if (!mddev->external) {
+			int did_change = 0;
 			spin_lock_irq(&mddev->write_lock);
 			if (mddev->safemode &&
 			    !atomic_read(&mddev->writes_pending) &&
 			    !mddev->in_sync &&
 			    mddev->recovery_cp == MaxSector) {
 				mddev->in_sync = 1;
+				did_change = 1;
 				if (mddev->persistent)
 					set_bit(MD_CHANGE_CLEAN, &mddev->flags);
 			}
 			if (mddev->safemode == 1)
 				mddev->safemode = 0;
 			spin_unlock_irq(&mddev->write_lock);
+			if (did_change)
+				sysfs_notify(&mddev->kobj, NULL, "array_state");
 		}
 
 		if (mddev->flags)
 			md_update_sb(mddev, 0);
 
+		rdev_for_each(rdev, rtmp, mddev)
+			if (test_and_clear_bit(StateChanged, &rdev->flags))
+				sysfs_notify(&rdev->kobj, NULL, "state");
+
 
 		if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) &&
 		    !test_bit(MD_RECOVERY_DONE, &mddev->recovery)) {
@@ -5951,7 +6116,9 @@
 			if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
 				/* success...*/
 				/* activate any spares */
-				mddev->pers->spare_active(mddev);
+				if (mddev->pers->spare_active(mddev))
+					sysfs_notify(&mddev->kobj, NULL,
+						     "degraded");
 			}
 			md_update_sb(mddev, 1);
 
@@ -5965,13 +6132,18 @@
 			mddev->recovery = 0;
 			/* flag recovery needed just to double check */
 			set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+			sysfs_notify(&mddev->kobj, NULL, "sync_action");
 			md_new_event(mddev);
 			goto unlock;
 		}
+		/* Set RUNNING before clearing NEEDED to avoid
+		 * any transients in the value of "sync_action".
+		 */
+		set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
+		clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 		/* Clear some bits that don't mean anything, but
 		 * might be left set
 		 */
-		clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 		clear_bit(MD_RECOVERY_INTR, &mddev->recovery);
 		clear_bit(MD_RECOVERY_DONE, &mddev->recovery);
 
@@ -5989,17 +6161,19 @@
 				/* Cannot proceed */
 				goto unlock;
 			set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
+			clear_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
 		} else if ((spares = remove_and_add_spares(mddev))) {
 			clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
 			clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
+			set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
 		} else if (mddev->recovery_cp < MaxSector) {
 			set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
+			clear_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
 		} else if (!test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
 			/* nothing to be done ... */
 			goto unlock;
 
 		if (mddev->pers->sync_request) {
-			set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
 			if (spares && mddev->bitmap && ! mddev->bitmap->file) {
 				/* We are adding a device or devices to an array
 				 * which has the bitmap stored on all devices.
@@ -6018,9 +6192,16 @@
 				mddev->recovery = 0;
 			} else
 				md_wakeup_thread(mddev->sync_thread);
+			sysfs_notify(&mddev->kobj, NULL, "sync_action");
 			md_new_event(mddev);
 		}
 	unlock:
+		if (!mddev->sync_thread) {
+			clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
+			if (test_and_clear_bit(MD_RECOVERY_RECOVER,
+					       &mddev->recovery))
+				sysfs_notify(&mddev->kobj, NULL, "sync_action");
+		}
 		mddev_unlock(mddev);
 	}
 }
@@ -6047,7 +6228,7 @@
 
 		for_each_mddev(mddev, tmp)
 			if (mddev_trylock(mddev)) {
-				do_md_stop (mddev, 1);
+				do_md_stop (mddev, 1, 0);
 				mddev_unlock(mddev);
 			}
 		/*
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index e968116..c4779cc 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -281,13 +281,18 @@
 {
 	multipath_conf_t *conf = mddev->private;
 	struct request_queue *q;
-	int found = 0;
+	int err = -EEXIST;
 	int path;
 	struct multipath_info *p;
+	int first = 0;
+	int last = mddev->raid_disks - 1;
+
+	if (rdev->raid_disk >= 0)
+		first = last = rdev->raid_disk;
 
 	print_multipath_conf(conf);
 
-	for (path=0; path<mddev->raid_disks; path++) 
+	for (path = first; path <= last; path++)
 		if ((p=conf->multipaths+path)->rdev == NULL) {
 			q = rdev->bdev->bd_disk->queue;
 			blk_queue_stack_limits(mddev->queue, q);
@@ -307,11 +312,13 @@
 			rdev->raid_disk = path;
 			set_bit(In_sync, &rdev->flags);
 			rcu_assign_pointer(p->rdev, rdev);
-			found = 1;
+			err = 0;
+			break;
 		}
 
 	print_multipath_conf(conf);
-	return found;
+
+	return err;
 }
 
 static int multipath_remove_disk(mddev_t *mddev, int number)
@@ -497,7 +504,7 @@
 	/*
 	 * Ok, everything is just fine now
 	 */
-	mddev->array_size = mddev->size;
+	mddev->array_sectors = mddev->size * 2;
 
 	mddev->queue->unplug_fn = multipath_unplug;
 	mddev->queue->backing_dev_info.congested_fn = multipath_congested;
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index bcbb825..1836106 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -295,16 +295,16 @@
 		goto out_free_conf;
 
 	/* calculate array device size */
-	mddev->array_size = 0;
+	mddev->array_sectors = 0;
 	rdev_for_each(rdev, tmp, mddev)
-		mddev->array_size += rdev->size;
+		mddev->array_sectors += rdev->size * 2;
 
 	printk("raid0 : md_size is %llu blocks.\n", 
-		(unsigned long long)mddev->array_size);
+		(unsigned long long)mddev->array_sectors / 2);
 	printk("raid0 : conf->hash_spacing is %llu blocks.\n",
 		(unsigned long long)conf->hash_spacing);
 	{
-		sector_t s = mddev->array_size;
+		sector_t s = mddev->array_sectors / 2;
 		sector_t space = conf->hash_spacing;
 		int round;
 		conf->preshift = 0;
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index c610b947..03a5ab7 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1100,11 +1100,16 @@
 static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
 {
 	conf_t *conf = mddev->private;
-	int found = 0;
+	int err = -EEXIST;
 	int mirror = 0;
 	mirror_info_t *p;
+	int first = 0;
+	int last = mddev->raid_disks - 1;
 
-	for (mirror=0; mirror < mddev->raid_disks; mirror++)
+	if (rdev->raid_disk >= 0)
+		first = last = rdev->raid_disk;
+
+	for (mirror = first; mirror <= last; mirror++)
 		if ( !(p=conf->mirrors+mirror)->rdev) {
 
 			blk_queue_stack_limits(mddev->queue,
@@ -1119,7 +1124,7 @@
 
 			p->head_position = 0;
 			rdev->raid_disk = mirror;
-			found = 1;
+			err = 0;
 			/* As all devices are equivalent, we don't need a full recovery
 			 * if this was recently any drive of the array
 			 */
@@ -1130,7 +1135,7 @@
 		}
 
 	print_conf(conf);
-	return found;
+	return err;
 }
 
 static int raid1_remove_disk(mddev_t *mddev, int number)
@@ -2038,7 +2043,7 @@
 	/*
 	 * Ok, everything is just fine now
 	 */
-	mddev->array_size = mddev->size;
+	mddev->array_sectors = mddev->size * 2;
 
 	mddev->queue->unplug_fn = raid1_unplug;
 	mddev->queue->backing_dev_info.congested_fn = raid1_congested;
@@ -2100,14 +2105,15 @@
 	 * any io in the removed space completes, but it hardly seems
 	 * worth it.
 	 */
-	mddev->array_size = sectors>>1;
-	set_capacity(mddev->gendisk, mddev->array_size << 1);
+	mddev->array_sectors = sectors;
+	set_capacity(mddev->gendisk, mddev->array_sectors);
 	mddev->changed = 1;
-	if (mddev->array_size > mddev->size && mddev->recovery_cp == MaxSector) {
+	if (mddev->array_sectors / 2 > mddev->size &&
+	    mddev->recovery_cp == MaxSector) {
 		mddev->recovery_cp = mddev->size << 1;
 		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 	}
-	mddev->size = mddev->array_size;
+	mddev->size = mddev->array_sectors / 2;
 	mddev->resync_max_sectors = sectors;
 	return 0;
 }
@@ -2131,7 +2137,7 @@
 	conf_t *conf = mddev_to_conf(mddev);
 	int cnt, raid_disks;
 	unsigned long flags;
-	int d, d2;
+	int d, d2, err;
 
 	/* Cannot change chunk_size, layout, or level */
 	if (mddev->chunk_size != mddev->new_chunk ||
@@ -2143,7 +2149,9 @@
 		return -EINVAL;
 	}
 
-	md_allow_write(mddev);
+	err = md_allow_write(mddev);
+	if (err)
+		return err;
 
 	raid_disks = mddev->raid_disks + mddev->delta_disks;
 
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 22bb2b1..159535d 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1114,24 +1114,30 @@
 static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
 {
 	conf_t *conf = mddev->private;
-	int found = 0;
+	int err = -EEXIST;
 	int mirror;
 	mirror_info_t *p;
+	int first = 0;
+	int last = mddev->raid_disks - 1;
 
 	if (mddev->recovery_cp < MaxSector)
 		/* only hot-add to in-sync arrays, as recovery is
 		 * very different from resync
 		 */
-		return 0;
+		return -EBUSY;
 	if (!enough(conf))
-		return 0;
+		return -EINVAL;
+
+	if (rdev->raid_disk)
+		first = last = rdev->raid_disk;
 
 	if (rdev->saved_raid_disk >= 0 &&
+	    rdev->saved_raid_disk >= first &&
 	    conf->mirrors[rdev->saved_raid_disk].rdev == NULL)
 		mirror = rdev->saved_raid_disk;
 	else
-		mirror = 0;
-	for ( ; mirror < mddev->raid_disks; mirror++)
+		mirror = first;
+	for ( ; mirror <= last ; mirror++)
 		if ( !(p=conf->mirrors+mirror)->rdev) {
 
 			blk_queue_stack_limits(mddev->queue,
@@ -1146,7 +1152,7 @@
 
 			p->head_position = 0;
 			rdev->raid_disk = mirror;
-			found = 1;
+			err = 0;
 			if (rdev->saved_raid_disk != mirror)
 				conf->fullsync = 1;
 			rcu_assign_pointer(p->rdev, rdev);
@@ -1154,7 +1160,7 @@
 		}
 
 	print_conf(conf);
-	return found;
+	return err;
 }
 
 static int raid10_remove_disk(mddev_t *mddev, int number)
@@ -2159,7 +2165,7 @@
 	/*
 	 * Ok, everything is just fine now
 	 */
-	mddev->array_size = size << (conf->chunk_shift-1);
+	mddev->array_sectors = size << conf->chunk_shift;
 	mddev->resync_max_sectors = size << conf->chunk_shift;
 
 	mddev->queue->unplug_fn = raid10_unplug;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 9ce7154..55e7c56 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -115,15 +115,20 @@
 		return_bi = bi->bi_next;
 		bi->bi_next = NULL;
 		bi->bi_size = 0;
-		bi->bi_end_io(bi,
-			      test_bit(BIO_UPTODATE, &bi->bi_flags)
-			        ? 0 : -EIO);
+		bio_endio(bi, 0);
 		bi = return_bi;
 	}
 }
 
 static void print_raid5_conf (raid5_conf_t *conf);
 
+static int stripe_operations_active(struct stripe_head *sh)
+{
+	return sh->check_state || sh->reconstruct_state ||
+	       test_bit(STRIPE_BIOFILL_RUN, &sh->state) ||
+	       test_bit(STRIPE_COMPUTE_RUN, &sh->state);
+}
+
 static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
 {
 	if (atomic_dec_and_test(&sh->count)) {
@@ -143,7 +148,7 @@
 			}
 			md_wakeup_thread(conf->mddev->thread);
 		} else {
-			BUG_ON(sh->ops.pending);
+			BUG_ON(stripe_operations_active(sh));
 			if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
 				atomic_dec(&conf->preread_active_stripes);
 				if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
@@ -245,7 +250,7 @@
 
 	BUG_ON(atomic_read(&sh->count) != 0);
 	BUG_ON(test_bit(STRIPE_HANDLE, &sh->state));
-	BUG_ON(sh->ops.pending || sh->ops.ack || sh->ops.complete);
+	BUG_ON(stripe_operations_active(sh));
 
 	CHECK_DEVLOCK();
 	pr_debug("init_stripe called, stripe %llu\n",
@@ -346,62 +351,18 @@
 	return sh;
 }
 
-/* test_and_ack_op() ensures that we only dequeue an operation once */
-#define test_and_ack_op(op, pend) \
-do {							\
-	if (test_bit(op, &sh->ops.pending) &&		\
-		!test_bit(op, &sh->ops.complete)) {	\
-		if (test_and_set_bit(op, &sh->ops.ack)) \
-			clear_bit(op, &pend);		\
-		else					\
-			ack++;				\
-	} else						\
-		clear_bit(op, &pend);			\
-} while (0)
-
-/* find new work to run, do not resubmit work that is already
- * in flight
- */
-static unsigned long get_stripe_work(struct stripe_head *sh)
-{
-	unsigned long pending;
-	int ack = 0;
-
-	pending = sh->ops.pending;
-
-	test_and_ack_op(STRIPE_OP_BIOFILL, pending);
-	test_and_ack_op(STRIPE_OP_COMPUTE_BLK, pending);
-	test_and_ack_op(STRIPE_OP_PREXOR, pending);
-	test_and_ack_op(STRIPE_OP_BIODRAIN, pending);
-	test_and_ack_op(STRIPE_OP_POSTXOR, pending);
-	test_and_ack_op(STRIPE_OP_CHECK, pending);
-	if (test_and_clear_bit(STRIPE_OP_IO, &sh->ops.pending))
-		ack++;
-
-	sh->ops.count -= ack;
-	if (unlikely(sh->ops.count < 0)) {
-		printk(KERN_ERR "pending: %#lx ops.pending: %#lx ops.ack: %#lx "
-			"ops.complete: %#lx\n", pending, sh->ops.pending,
-			sh->ops.ack, sh->ops.complete);
-		BUG();
-	}
-
-	return pending;
-}
-
 static void
 raid5_end_read_request(struct bio *bi, int error);
 static void
 raid5_end_write_request(struct bio *bi, int error);
 
-static void ops_run_io(struct stripe_head *sh)
+static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
 {
 	raid5_conf_t *conf = sh->raid_conf;
 	int i, disks = sh->disks;
 
 	might_sleep();
 
-	set_bit(STRIPE_IO_STARTED, &sh->state);
 	for (i = disks; i--; ) {
 		int rw;
 		struct bio *bi;
@@ -430,11 +391,11 @@
 		rcu_read_unlock();
 
 		if (rdev) {
-			if (test_bit(STRIPE_SYNCING, &sh->state) ||
-				test_bit(STRIPE_EXPAND_SOURCE, &sh->state) ||
-				test_bit(STRIPE_EXPAND_READY, &sh->state))
+			if (s->syncing || s->expanding || s->expanded)
 				md_sync_acct(rdev->bdev, STRIPE_SECTORS);
 
+			set_bit(STRIPE_IO_STARTED, &sh->state);
+
 			bi->bi_bdev = rdev->bdev;
 			pr_debug("%s: for %llu schedule op %ld on disc %d\n",
 				__func__, (unsigned long long)sh->sector,
@@ -528,38 +489,34 @@
 		(unsigned long long)sh->sector);
 
 	/* clear completed biofills */
+	spin_lock_irq(&conf->device_lock);
 	for (i = sh->disks; i--; ) {
 		struct r5dev *dev = &sh->dev[i];
 
 		/* acknowledge completion of a biofill operation */
 		/* and check if we need to reply to a read request,
 		 * new R5_Wantfill requests are held off until
-		 * !test_bit(STRIPE_OP_BIOFILL, &sh->ops.pending)
+		 * !STRIPE_BIOFILL_RUN
 		 */
 		if (test_and_clear_bit(R5_Wantfill, &dev->flags)) {
 			struct bio *rbi, *rbi2;
 
-			/* The access to dev->read is outside of the
-			 * spin_lock_irq(&conf->device_lock), but is protected
-			 * by the STRIPE_OP_BIOFILL pending bit
-			 */
 			BUG_ON(!dev->read);
 			rbi = dev->read;
 			dev->read = NULL;
 			while (rbi && rbi->bi_sector <
 				dev->sector + STRIPE_SECTORS) {
 				rbi2 = r5_next_bio(rbi, dev->sector);
-				spin_lock_irq(&conf->device_lock);
 				if (--rbi->bi_phys_segments == 0) {
 					rbi->bi_next = return_bi;
 					return_bi = rbi;
 				}
-				spin_unlock_irq(&conf->device_lock);
 				rbi = rbi2;
 			}
 		}
 	}
-	set_bit(STRIPE_OP_BIOFILL, &sh->ops.complete);
+	spin_unlock_irq(&conf->device_lock);
+	clear_bit(STRIPE_BIOFILL_RUN, &sh->state);
 
 	return_io(return_bi);
 
@@ -610,13 +567,14 @@
 	set_bit(R5_UPTODATE, &tgt->flags);
 	BUG_ON(!test_bit(R5_Wantcompute, &tgt->flags));
 	clear_bit(R5_Wantcompute, &tgt->flags);
-	set_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete);
+	clear_bit(STRIPE_COMPUTE_RUN, &sh->state);
+	if (sh->check_state == check_state_compute_run)
+		sh->check_state = check_state_compute_result;
 	set_bit(STRIPE_HANDLE, &sh->state);
 	release_stripe(sh);
 }
 
-static struct dma_async_tx_descriptor *
-ops_run_compute5(struct stripe_head *sh, unsigned long pending)
+static struct dma_async_tx_descriptor *ops_run_compute5(struct stripe_head *sh)
 {
 	/* kernel stack size limits the total number of disks */
 	int disks = sh->disks;
@@ -646,10 +604,6 @@
 			ASYNC_TX_XOR_ZERO_DST, NULL,
 			ops_complete_compute5, sh);
 
-	/* ack now if postxor is not set to be run */
-	if (tx && !test_bit(STRIPE_OP_POSTXOR, &pending))
-		async_tx_ack(tx);
-
 	return tx;
 }
 
@@ -659,8 +613,6 @@
 
 	pr_debug("%s: stripe %llu\n", __func__,
 		(unsigned long long)sh->sector);
-
-	set_bit(STRIPE_OP_PREXOR, &sh->ops.complete);
 }
 
 static struct dma_async_tx_descriptor *
@@ -680,7 +632,7 @@
 	for (i = disks; i--; ) {
 		struct r5dev *dev = &sh->dev[i];
 		/* Only process blocks that are known to be uptodate */
-		if (dev->towrite && test_bit(R5_Wantprexor, &dev->flags))
+		if (test_bit(R5_Wantdrain, &dev->flags))
 			xor_srcs[count++] = dev->page;
 	}
 
@@ -692,16 +644,10 @@
 }
 
 static struct dma_async_tx_descriptor *
-ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx,
-		 unsigned long pending)
+ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
 {
 	int disks = sh->disks;
-	int pd_idx = sh->pd_idx, i;
-
-	/* check if prexor is active which means only process blocks
-	 * that are part of a read-modify-write (Wantprexor)
-	 */
-	int prexor = test_bit(STRIPE_OP_PREXOR, &pending);
+	int i;
 
 	pr_debug("%s: stripe %llu\n", __func__,
 		(unsigned long long)sh->sector);
@@ -709,20 +655,8 @@
 	for (i = disks; i--; ) {
 		struct r5dev *dev = &sh->dev[i];
 		struct bio *chosen;
-		int towrite;
 
-		towrite = 0;
-		if (prexor) { /* rmw */
-			if (dev->towrite &&
-			    test_bit(R5_Wantprexor, &dev->flags))
-				towrite = 1;
-		} else { /* rcw */
-			if (i != pd_idx && dev->towrite &&
-				test_bit(R5_LOCKED, &dev->flags))
-				towrite = 1;
-		}
-
-		if (towrite) {
+		if (test_and_clear_bit(R5_Wantdrain, &dev->flags)) {
 			struct bio *wbi;
 
 			spin_lock(&sh->lock);
@@ -747,18 +681,6 @@
 static void ops_complete_postxor(void *stripe_head_ref)
 {
 	struct stripe_head *sh = stripe_head_ref;
-
-	pr_debug("%s: stripe %llu\n", __func__,
-		(unsigned long long)sh->sector);
-
-	set_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
-	set_bit(STRIPE_HANDLE, &sh->state);
-	release_stripe(sh);
-}
-
-static void ops_complete_write(void *stripe_head_ref)
-{
-	struct stripe_head *sh = stripe_head_ref;
 	int disks = sh->disks, i, pd_idx = sh->pd_idx;
 
 	pr_debug("%s: stripe %llu\n", __func__,
@@ -770,16 +692,21 @@
 			set_bit(R5_UPTODATE, &dev->flags);
 	}
 
-	set_bit(STRIPE_OP_BIODRAIN, &sh->ops.complete);
-	set_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
+	if (sh->reconstruct_state == reconstruct_state_drain_run)
+		sh->reconstruct_state = reconstruct_state_drain_result;
+	else if (sh->reconstruct_state == reconstruct_state_prexor_drain_run)
+		sh->reconstruct_state = reconstruct_state_prexor_drain_result;
+	else {
+		BUG_ON(sh->reconstruct_state != reconstruct_state_run);
+		sh->reconstruct_state = reconstruct_state_result;
+	}
 
 	set_bit(STRIPE_HANDLE, &sh->state);
 	release_stripe(sh);
 }
 
 static void
-ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx,
-		unsigned long pending)
+ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
 {
 	/* kernel stack size limits the total number of disks */
 	int disks = sh->disks;
@@ -787,9 +714,8 @@
 
 	int count = 0, pd_idx = sh->pd_idx, i;
 	struct page *xor_dest;
-	int prexor = test_bit(STRIPE_OP_PREXOR, &pending);
+	int prexor = 0;
 	unsigned long flags;
-	dma_async_tx_callback callback;
 
 	pr_debug("%s: stripe %llu\n", __func__,
 		(unsigned long long)sh->sector);
@@ -797,7 +723,8 @@
 	/* check if prexor is active which means only process blocks
 	 * that are part of a read-modify-write (written)
 	 */
-	if (prexor) {
+	if (sh->reconstruct_state == reconstruct_state_prexor_drain_run) {
+		prexor = 1;
 		xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;
 		for (i = disks; i--; ) {
 			struct r5dev *dev = &sh->dev[i];
@@ -813,10 +740,6 @@
 		}
 	}
 
-	/* check whether this postxor is part of a write */
-	callback = test_bit(STRIPE_OP_BIODRAIN, &pending) ?
-		ops_complete_write : ops_complete_postxor;
-
 	/* 1/ if we prexor'd then the dest is reused as a source
 	 * 2/ if we did not prexor then we are redoing the parity
 	 * set ASYNC_TX_XOR_DROP_DST and ASYNC_TX_XOR_ZERO_DST
@@ -830,25 +753,20 @@
 	if (unlikely(count == 1)) {
 		flags &= ~(ASYNC_TX_XOR_DROP_DST | ASYNC_TX_XOR_ZERO_DST);
 		tx = async_memcpy(xor_dest, xor_srcs[0], 0, 0, STRIPE_SIZE,
-			flags, tx, callback, sh);
+			flags, tx, ops_complete_postxor, sh);
 	} else
 		tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
-			flags, tx, callback, sh);
+			flags, tx, ops_complete_postxor, sh);
 }
 
 static void ops_complete_check(void *stripe_head_ref)
 {
 	struct stripe_head *sh = stripe_head_ref;
-	int pd_idx = sh->pd_idx;
 
 	pr_debug("%s: stripe %llu\n", __func__,
 		(unsigned long long)sh->sector);
 
-	if (test_and_clear_bit(STRIPE_OP_MOD_DMA_CHECK, &sh->ops.pending) &&
-		sh->ops.zero_sum_result == 0)
-		set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
-
-	set_bit(STRIPE_OP_CHECK, &sh->ops.complete);
+	sh->check_state = check_state_check_result;
 	set_bit(STRIPE_HANDLE, &sh->state);
 	release_stripe(sh);
 }
@@ -875,46 +793,42 @@
 	tx = async_xor_zero_sum(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
 		&sh->ops.zero_sum_result, 0, NULL, NULL, NULL);
 
-	if (tx)
-		set_bit(STRIPE_OP_MOD_DMA_CHECK, &sh->ops.pending);
-	else
-		clear_bit(STRIPE_OP_MOD_DMA_CHECK, &sh->ops.pending);
-
 	atomic_inc(&sh->count);
 	tx = async_trigger_callback(ASYNC_TX_DEP_ACK | ASYNC_TX_ACK, tx,
 		ops_complete_check, sh);
 }
 
-static void raid5_run_ops(struct stripe_head *sh, unsigned long pending)
+static void raid5_run_ops(struct stripe_head *sh, unsigned long ops_request)
 {
 	int overlap_clear = 0, i, disks = sh->disks;
 	struct dma_async_tx_descriptor *tx = NULL;
 
-	if (test_bit(STRIPE_OP_BIOFILL, &pending)) {
+	if (test_bit(STRIPE_OP_BIOFILL, &ops_request)) {
 		ops_run_biofill(sh);
 		overlap_clear++;
 	}
 
-	if (test_bit(STRIPE_OP_COMPUTE_BLK, &pending))
-		tx = ops_run_compute5(sh, pending);
+	if (test_bit(STRIPE_OP_COMPUTE_BLK, &ops_request)) {
+		tx = ops_run_compute5(sh);
+		/* terminate the chain if postxor is not set to be run */
+		if (tx && !test_bit(STRIPE_OP_POSTXOR, &ops_request))
+			async_tx_ack(tx);
+	}
 
-	if (test_bit(STRIPE_OP_PREXOR, &pending))
+	if (test_bit(STRIPE_OP_PREXOR, &ops_request))
 		tx = ops_run_prexor(sh, tx);
 
-	if (test_bit(STRIPE_OP_BIODRAIN, &pending)) {
-		tx = ops_run_biodrain(sh, tx, pending);
+	if (test_bit(STRIPE_OP_BIODRAIN, &ops_request)) {
+		tx = ops_run_biodrain(sh, tx);
 		overlap_clear++;
 	}
 
-	if (test_bit(STRIPE_OP_POSTXOR, &pending))
-		ops_run_postxor(sh, tx, pending);
+	if (test_bit(STRIPE_OP_POSTXOR, &ops_request))
+		ops_run_postxor(sh, tx);
 
-	if (test_bit(STRIPE_OP_CHECK, &pending))
+	if (test_bit(STRIPE_OP_CHECK, &ops_request))
 		ops_run_check(sh);
 
-	if (test_bit(STRIPE_OP_IO, &pending))
-		ops_run_io(sh);
-
 	if (overlap_clear)
 		for (i = disks; i--; ) {
 			struct r5dev *dev = &sh->dev[i];
@@ -997,14 +911,16 @@
 	struct stripe_head *osh, *nsh;
 	LIST_HEAD(newstripes);
 	struct disk_info *ndisks;
-	int err = 0;
+	int err;
 	struct kmem_cache *sc;
 	int i;
 
 	if (newsize <= conf->pool_size)
 		return 0; /* never bother to shrink */
 
-	md_allow_write(conf->mddev);
+	err = md_allow_write(conf->mddev);
+	if (err)
+		return err;
 
 	/* Step 1 */
 	sc = kmem_cache_create(conf->cache_name[1-conf->active_name],
@@ -1703,11 +1619,11 @@
 	}
 }
 
-static int
-handle_write_operations5(struct stripe_head *sh, int rcw, int expand)
+static void
+schedule_reconstruction5(struct stripe_head *sh, struct stripe_head_state *s,
+			 int rcw, int expand)
 {
 	int i, pd_idx = sh->pd_idx, disks = sh->disks;
-	int locked = 0;
 
 	if (rcw) {
 		/* if we are not expanding this is a proper write request, and
@@ -1715,53 +1631,48 @@
 		 * stripe cache
 		 */
 		if (!expand) {
-			set_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending);
-			sh->ops.count++;
-		}
+			sh->reconstruct_state = reconstruct_state_drain_run;
+			set_bit(STRIPE_OP_BIODRAIN, &s->ops_request);
+		} else
+			sh->reconstruct_state = reconstruct_state_run;
 
-		set_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
-		sh->ops.count++;
+		set_bit(STRIPE_OP_POSTXOR, &s->ops_request);
 
 		for (i = disks; i--; ) {
 			struct r5dev *dev = &sh->dev[i];
 
 			if (dev->towrite) {
 				set_bit(R5_LOCKED, &dev->flags);
+				set_bit(R5_Wantdrain, &dev->flags);
 				if (!expand)
 					clear_bit(R5_UPTODATE, &dev->flags);
-				locked++;
+				s->locked++;
 			}
 		}
-		if (locked + 1 == disks)
+		if (s->locked + 1 == disks)
 			if (!test_and_set_bit(STRIPE_FULL_WRITE, &sh->state))
 				atomic_inc(&sh->raid_conf->pending_full_writes);
 	} else {
 		BUG_ON(!(test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags) ||
 			test_bit(R5_Wantcompute, &sh->dev[pd_idx].flags)));
 
-		set_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
-		set_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending);
-		set_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
-
-		sh->ops.count += 3;
+		sh->reconstruct_state = reconstruct_state_prexor_drain_run;
+		set_bit(STRIPE_OP_PREXOR, &s->ops_request);
+		set_bit(STRIPE_OP_BIODRAIN, &s->ops_request);
+		set_bit(STRIPE_OP_POSTXOR, &s->ops_request);
 
 		for (i = disks; i--; ) {
 			struct r5dev *dev = &sh->dev[i];
 			if (i == pd_idx)
 				continue;
 
-			/* For a read-modify write there may be blocks that are
-			 * locked for reading while others are ready to be
-			 * written so we distinguish these blocks by the
-			 * R5_Wantprexor bit
-			 */
 			if (dev->towrite &&
 			    (test_bit(R5_UPTODATE, &dev->flags) ||
-			    test_bit(R5_Wantcompute, &dev->flags))) {
-				set_bit(R5_Wantprexor, &dev->flags);
+			     test_bit(R5_Wantcompute, &dev->flags))) {
+				set_bit(R5_Wantdrain, &dev->flags);
 				set_bit(R5_LOCKED, &dev->flags);
 				clear_bit(R5_UPTODATE, &dev->flags);
-				locked++;
+				s->locked++;
 			}
 		}
 	}
@@ -1771,13 +1682,11 @@
 	 */
 	set_bit(R5_LOCKED, &sh->dev[pd_idx].flags);
 	clear_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
-	locked++;
+	s->locked++;
 
-	pr_debug("%s: stripe %llu locked: %d pending: %lx\n",
+	pr_debug("%s: stripe %llu locked: %d ops_request: %lx\n",
 		__func__, (unsigned long long)sh->sector,
-		locked, sh->ops.pending);
-
-	return locked;
+		s->locked, s->ops_request);
 }
 
 /*
@@ -1876,7 +1785,7 @@
 }
 
 static void
-handle_requests_to_failed_array(raid5_conf_t *conf, struct stripe_head *sh,
+handle_failed_stripe(raid5_conf_t *conf, struct stripe_head *sh,
 				struct stripe_head_state *s, int disks,
 				struct bio **return_bi)
 {
@@ -1967,48 +1876,38 @@
 			md_wakeup_thread(conf->mddev->thread);
 }
 
-/* __handle_issuing_new_read_requests5 - returns 0 if there are no more disks
- * to process
+/* fetch_block5 - checks the given member device to see if its data needs
+ * to be read or computed to satisfy a request.
+ *
+ * Returns 1 when no more member devices need to be checked, otherwise returns
+ * 0 to tell the loop in handle_stripe_fill5 to continue
  */
-static int __handle_issuing_new_read_requests5(struct stripe_head *sh,
-			struct stripe_head_state *s, int disk_idx, int disks)
+static int fetch_block5(struct stripe_head *sh, struct stripe_head_state *s,
+			int disk_idx, int disks)
 {
 	struct r5dev *dev = &sh->dev[disk_idx];
 	struct r5dev *failed_dev = &sh->dev[s->failed_num];
 
-	/* don't schedule compute operations or reads on the parity block while
-	 * a check is in flight
-	 */
-	if ((disk_idx == sh->pd_idx) &&
-	     test_bit(STRIPE_OP_CHECK, &sh->ops.pending))
-		return ~0;
-
 	/* is the data in this block needed, and can we get it? */
 	if (!test_bit(R5_LOCKED, &dev->flags) &&
-	    !test_bit(R5_UPTODATE, &dev->flags) && (dev->toread ||
-	    (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
-	     s->syncing || s->expanding || (s->failed &&
-	     (failed_dev->toread || (failed_dev->towrite &&
-	     !test_bit(R5_OVERWRITE, &failed_dev->flags)
-	     ))))) {
-		/* 1/ We would like to get this block, possibly by computing it,
-		 * but we might not be able to.
-		 *
-		 * 2/ Since parity check operations potentially make the parity
-		 * block !uptodate it will need to be refreshed before any
-		 * compute operations on data disks are scheduled.
-		 *
-		 * 3/ We hold off parity block re-reads until check operations
-		 * have quiesced.
+	    !test_bit(R5_UPTODATE, &dev->flags) &&
+	    (dev->toread ||
+	     (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
+	     s->syncing || s->expanding ||
+	     (s->failed &&
+	      (failed_dev->toread ||
+	       (failed_dev->towrite &&
+		!test_bit(R5_OVERWRITE, &failed_dev->flags)))))) {
+		/* We would like to get this block, possibly by computing it,
+		 * otherwise read it if the backing disk is insync
 		 */
 		if ((s->uptodate == disks - 1) &&
-		    (s->failed && disk_idx == s->failed_num) &&
-		    !test_bit(STRIPE_OP_CHECK, &sh->ops.pending)) {
-			set_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending);
+		    (s->failed && disk_idx == s->failed_num)) {
+			set_bit(STRIPE_COMPUTE_RUN, &sh->state);
+			set_bit(STRIPE_OP_COMPUTE_BLK, &s->ops_request);
 			set_bit(R5_Wantcompute, &dev->flags);
 			sh->ops.target = disk_idx;
 			s->req_compute = 1;
-			sh->ops.count++;
 			/* Careful: from this point on 'uptodate' is in the eye
 			 * of raid5_run_ops which services 'compute' operations
 			 * before writes. R5_Wantcompute flags a block that will
@@ -2016,53 +1915,40 @@
 			 * subsequent operation.
 			 */
 			s->uptodate++;
-			return 0; /* uptodate + compute == disks */
+			return 1; /* uptodate + compute == disks */
 		} else if (test_bit(R5_Insync, &dev->flags)) {
 			set_bit(R5_LOCKED, &dev->flags);
 			set_bit(R5_Wantread, &dev->flags);
-			if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
-				sh->ops.count++;
 			s->locked++;
 			pr_debug("Reading block %d (sync=%d)\n", disk_idx,
 				s->syncing);
 		}
 	}
 
-	return ~0;
+	return 0;
 }
 
-static void handle_issuing_new_read_requests5(struct stripe_head *sh,
+/**
+ * handle_stripe_fill5 - read or compute data to satisfy pending requests.
+ */
+static void handle_stripe_fill5(struct stripe_head *sh,
 			struct stripe_head_state *s, int disks)
 {
 	int i;
 
-	/* Clear completed compute operations.  Parity recovery
-	 * (STRIPE_OP_MOD_REPAIR_PD) implies a write-back which is handled
-	 * later on in this routine
-	 */
-	if (test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete) &&
-		!test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) {
-		clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete);
-		clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.ack);
-		clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending);
-	}
-
 	/* look for blocks to read/compute, skip this if a compute
 	 * is already in flight, or if the stripe contents are in the
 	 * midst of changing due to a write
 	 */
-	if (!test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending) &&
-		!test_bit(STRIPE_OP_PREXOR, &sh->ops.pending) &&
-		!test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) {
+	if (!test_bit(STRIPE_COMPUTE_RUN, &sh->state) && !sh->check_state &&
+	    !sh->reconstruct_state)
 		for (i = disks; i--; )
-			if (__handle_issuing_new_read_requests5(
-				sh, s, i, disks) == 0)
+			if (fetch_block5(sh, s, i, disks))
 				break;
-	}
 	set_bit(STRIPE_HANDLE, &sh->state);
 }
 
-static void handle_issuing_new_read_requests6(struct stripe_head *sh,
+static void handle_stripe_fill6(struct stripe_head *sh,
 			struct stripe_head_state *s, struct r6_state *r6s,
 			int disks)
 {
@@ -2121,12 +2007,12 @@
 }
 
 
-/* handle_completed_write_requests
+/* handle_stripe_clean_event
  * any written block on an uptodate or failed drive can be returned.
  * Note that if we 'wrote' to a failed drive, it will be UPTODATE, but
  * never LOCKED, so we don't need to test 'failed' directly.
  */
-static void handle_completed_write_requests(raid5_conf_t *conf,
+static void handle_stripe_clean_event(raid5_conf_t *conf,
 	struct stripe_head *sh, int disks, struct bio **return_bi)
 {
 	int i;
@@ -2171,7 +2057,7 @@
 			md_wakeup_thread(conf->mddev->thread);
 }
 
-static void handle_issuing_new_write_requests5(raid5_conf_t *conf,
+static void handle_stripe_dirtying5(raid5_conf_t *conf,
 		struct stripe_head *sh,	struct stripe_head_state *s, int disks)
 {
 	int rmw = 0, rcw = 0, i;
@@ -2215,9 +2101,6 @@
 						"%d for r-m-w\n", i);
 					set_bit(R5_LOCKED, &dev->flags);
 					set_bit(R5_Wantread, &dev->flags);
-					if (!test_and_set_bit(
-						STRIPE_OP_IO, &sh->ops.pending))
-						sh->ops.count++;
 					s->locked++;
 				} else {
 					set_bit(STRIPE_DELAYED, &sh->state);
@@ -2241,9 +2124,6 @@
 						"%d for Reconstruct\n", i);
 					set_bit(R5_LOCKED, &dev->flags);
 					set_bit(R5_Wantread, &dev->flags);
-					if (!test_and_set_bit(
-						STRIPE_OP_IO, &sh->ops.pending))
-						sh->ops.count++;
 					s->locked++;
 				} else {
 					set_bit(STRIPE_DELAYED, &sh->state);
@@ -2261,14 +2141,13 @@
 	 * simultaneously.  If this is not the case then new writes need to be
 	 * held off until the compute completes.
 	 */
-	if ((s->req_compute ||
-	    !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending)) &&
-		(s->locked == 0 && (rcw == 0 || rmw == 0) &&
-		!test_bit(STRIPE_BIT_DELAY, &sh->state)))
-		s->locked += handle_write_operations5(sh, rcw == 0, 0);
+	if ((s->req_compute || !test_bit(STRIPE_COMPUTE_RUN, &sh->state)) &&
+	    (s->locked == 0 && (rcw == 0 || rmw == 0) &&
+	    !test_bit(STRIPE_BIT_DELAY, &sh->state)))
+		schedule_reconstruction5(sh, s, rcw == 0, 0);
 }
 
-static void handle_issuing_new_write_requests6(raid5_conf_t *conf,
+static void handle_stripe_dirtying6(raid5_conf_t *conf,
 		struct stripe_head *sh,	struct stripe_head_state *s,
 		struct r6_state *r6s, int disks)
 {
@@ -2371,92 +2250,86 @@
 static void handle_parity_checks5(raid5_conf_t *conf, struct stripe_head *sh,
 				struct stripe_head_state *s, int disks)
 {
-	int canceled_check = 0;
+	struct r5dev *dev = NULL;
 
 	set_bit(STRIPE_HANDLE, &sh->state);
 
-	/* complete a check operation */
-	if (test_and_clear_bit(STRIPE_OP_CHECK, &sh->ops.complete)) {
-		clear_bit(STRIPE_OP_CHECK, &sh->ops.ack);
-		clear_bit(STRIPE_OP_CHECK, &sh->ops.pending);
+	switch (sh->check_state) {
+	case check_state_idle:
+		/* start a new check operation if there are no failures */
 		if (s->failed == 0) {
-			if (sh->ops.zero_sum_result == 0)
-				/* parity is correct (on disc,
-				 * not in buffer any more)
-				 */
-				set_bit(STRIPE_INSYNC, &sh->state);
-			else {
-				conf->mddev->resync_mismatches +=
-					STRIPE_SECTORS;
-				if (test_bit(
-				     MD_RECOVERY_CHECK, &conf->mddev->recovery))
-					/* don't try to repair!! */
-					set_bit(STRIPE_INSYNC, &sh->state);
-				else {
-					set_bit(STRIPE_OP_COMPUTE_BLK,
-						&sh->ops.pending);
-					set_bit(STRIPE_OP_MOD_REPAIR_PD,
-						&sh->ops.pending);
-					set_bit(R5_Wantcompute,
-						&sh->dev[sh->pd_idx].flags);
-					sh->ops.target = sh->pd_idx;
-					sh->ops.count++;
-					s->uptodate++;
-				}
-			}
-		} else
-			canceled_check = 1; /* STRIPE_INSYNC is not set */
-	}
-
-	/* start a new check operation if there are no failures, the stripe is
-	 * not insync, and a repair is not in flight
-	 */
-	if (s->failed == 0 &&
-	    !test_bit(STRIPE_INSYNC, &sh->state) &&
-	    !test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) {
-		if (!test_and_set_bit(STRIPE_OP_CHECK, &sh->ops.pending)) {
 			BUG_ON(s->uptodate != disks);
+			sh->check_state = check_state_run;
+			set_bit(STRIPE_OP_CHECK, &s->ops_request);
 			clear_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags);
-			sh->ops.count++;
 			s->uptodate--;
+			break;
 		}
-	}
-
-	/* check if we can clear a parity disk reconstruct */
-	if (test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete) &&
-	    test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) {
-
-		clear_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending);
-		clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete);
-		clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.ack);
-		clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending);
-	}
-
-
-	/* Wait for check parity and compute block operations to complete
-	 * before write-back.  If a failure occurred while the check operation
-	 * was in flight we need to cycle this stripe through handle_stripe
-	 * since the parity block may not be uptodate
-	 */
-	if (!canceled_check && !test_bit(STRIPE_INSYNC, &sh->state) &&
-	    !test_bit(STRIPE_OP_CHECK, &sh->ops.pending) &&
-	    !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending)) {
-		struct r5dev *dev;
-		/* either failed parity check, or recovery is happening */
-		if (s->failed == 0)
-			s->failed_num = sh->pd_idx;
 		dev = &sh->dev[s->failed_num];
+		/* fall through */
+	case check_state_compute_result:
+		sh->check_state = check_state_idle;
+		if (!dev)
+			dev = &sh->dev[sh->pd_idx];
+
+		/* check that a write has not made the stripe insync */
+		if (test_bit(STRIPE_INSYNC, &sh->state))
+			break;
+
+		/* either failed parity check, or recovery is happening */
 		BUG_ON(!test_bit(R5_UPTODATE, &dev->flags));
 		BUG_ON(s->uptodate != disks);
 
 		set_bit(R5_LOCKED, &dev->flags);
+		s->locked++;
 		set_bit(R5_Wantwrite, &dev->flags);
-		if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
-			sh->ops.count++;
 
 		clear_bit(STRIPE_DEGRADED, &sh->state);
-		s->locked++;
 		set_bit(STRIPE_INSYNC, &sh->state);
+		break;
+	case check_state_run:
+		break; /* we will be called again upon completion */
+	case check_state_check_result:
+		sh->check_state = check_state_idle;
+
+		/* if a failure occurred during the check operation, leave
+		 * STRIPE_INSYNC not set and let the stripe be handled again
+		 */
+		if (s->failed)
+			break;
+
+		/* handle a successful check operation, if parity is correct
+		 * we are done.  Otherwise update the mismatch count and repair
+		 * parity if !MD_RECOVERY_CHECK
+		 */
+		if (sh->ops.zero_sum_result == 0)
+			/* parity is correct (on disc,
+			 * not in buffer any more)
+			 */
+			set_bit(STRIPE_INSYNC, &sh->state);
+		else {
+			conf->mddev->resync_mismatches += STRIPE_SECTORS;
+			if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
+				/* don't try to repair!! */
+				set_bit(STRIPE_INSYNC, &sh->state);
+			else {
+				sh->check_state = check_state_compute_run;
+				set_bit(STRIPE_COMPUTE_RUN, &sh->state);
+				set_bit(STRIPE_OP_COMPUTE_BLK, &s->ops_request);
+				set_bit(R5_Wantcompute,
+					&sh->dev[sh->pd_idx].flags);
+				sh->ops.target = sh->pd_idx;
+				s->uptodate++;
+			}
+		}
+		break;
+	case check_state_compute_run:
+		break;
+	default:
+		printk(KERN_ERR "%s: unknown check_state: %d sector: %llu\n",
+		       __func__, sh->check_state,
+		       (unsigned long long) sh->sector);
+		BUG();
 	}
 }
 
@@ -2641,15 +2514,14 @@
 	struct bio *return_bi = NULL;
 	struct stripe_head_state s;
 	struct r5dev *dev;
-	unsigned long pending = 0;
 	mdk_rdev_t *blocked_rdev = NULL;
 	int prexor;
 
 	memset(&s, 0, sizeof(s));
-	pr_debug("handling stripe %llu, state=%#lx cnt=%d, pd_idx=%d "
-		"ops=%lx:%lx:%lx\n", (unsigned long long)sh->sector, sh->state,
-		atomic_read(&sh->count), sh->pd_idx,
-		sh->ops.pending, sh->ops.ack, sh->ops.complete);
+	pr_debug("handling stripe %llu, state=%#lx cnt=%d, pd_idx=%d check:%d "
+		 "reconstruct:%d\n", (unsigned long long)sh->sector, sh->state,
+		 atomic_read(&sh->count), sh->pd_idx, sh->check_state,
+		 sh->reconstruct_state);
 
 	spin_lock(&sh->lock);
 	clear_bit(STRIPE_HANDLE, &sh->state);
@@ -2658,15 +2530,8 @@
 	s.syncing = test_bit(STRIPE_SYNCING, &sh->state);
 	s.expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
 	s.expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
+
 	/* Now to look around and see what can be done */
-
-	/* clean-up completed biofill operations */
-	if (test_bit(STRIPE_OP_BIOFILL, &sh->ops.complete)) {
-		clear_bit(STRIPE_OP_BIOFILL, &sh->ops.pending);
-		clear_bit(STRIPE_OP_BIOFILL, &sh->ops.ack);
-		clear_bit(STRIPE_OP_BIOFILL, &sh->ops.complete);
-	}
-
 	rcu_read_lock();
 	for (i=disks; i--; ) {
 		mdk_rdev_t *rdev;
@@ -2680,10 +2545,10 @@
 		/* maybe we can request a biofill operation
 		 *
 		 * new wantfill requests are only permitted while
-		 * STRIPE_OP_BIOFILL is clear
+		 * ops_complete_biofill is guaranteed to be inactive
 		 */
 		if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread &&
-			!test_bit(STRIPE_OP_BIOFILL, &sh->ops.pending))
+		    !test_bit(STRIPE_BIOFILL_RUN, &sh->state))
 			set_bit(R5_Wantfill, &dev->flags);
 
 		/* now count some things */
@@ -2727,8 +2592,10 @@
 		goto unlock;
 	}
 
-	if (s.to_fill && !test_and_set_bit(STRIPE_OP_BIOFILL, &sh->ops.pending))
-		sh->ops.count++;
+	if (s.to_fill && !test_bit(STRIPE_BIOFILL_RUN, &sh->state)) {
+		set_bit(STRIPE_OP_BIOFILL, &s.ops_request);
+		set_bit(STRIPE_BIOFILL_RUN, &sh->state);
+	}
 
 	pr_debug("locked=%d uptodate=%d to_read=%d"
 		" to_write=%d failed=%d failed_num=%d\n",
@@ -2738,8 +2605,7 @@
 	 * need to be failed
 	 */
 	if (s.failed > 1 && s.to_read+s.to_write+s.written)
-		handle_requests_to_failed_array(conf, sh, &s, disks,
-						&return_bi);
+		handle_failed_stripe(conf, sh, &s, disks, &return_bi);
 	if (s.failed > 1 && s.syncing) {
 		md_done_sync(conf->mddev, STRIPE_SECTORS,0);
 		clear_bit(STRIPE_SYNCING, &sh->state);
@@ -2755,48 +2621,25 @@
 	       !test_bit(R5_LOCKED, &dev->flags) &&
 	       test_bit(R5_UPTODATE, &dev->flags)) ||
 	       (s.failed == 1 && s.failed_num == sh->pd_idx)))
-		handle_completed_write_requests(conf, sh, disks, &return_bi);
+		handle_stripe_clean_event(conf, sh, disks, &return_bi);
 
 	/* Now we might consider reading some blocks, either to check/generate
 	 * parity, or to satisfy requests
 	 * or to load a block that is being partially written.
 	 */
 	if (s.to_read || s.non_overwrite ||
-	    (s.syncing && (s.uptodate + s.compute < disks)) || s.expanding ||
-	    test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending))
-		handle_issuing_new_read_requests5(sh, &s, disks);
+	    (s.syncing && (s.uptodate + s.compute < disks)) || s.expanding)
+		handle_stripe_fill5(sh, &s, disks);
 
 	/* Now we check to see if any write operations have recently
 	 * completed
 	 */
-
-	/* leave prexor set until postxor is done, allows us to distinguish
-	 * a rmw from a rcw during biodrain
-	 */
 	prexor = 0;
-	if (test_bit(STRIPE_OP_PREXOR, &sh->ops.complete) &&
-		test_bit(STRIPE_OP_POSTXOR, &sh->ops.complete)) {
-
+	if (sh->reconstruct_state == reconstruct_state_prexor_drain_result)
 		prexor = 1;
-		clear_bit(STRIPE_OP_PREXOR, &sh->ops.complete);
-		clear_bit(STRIPE_OP_PREXOR, &sh->ops.ack);
-		clear_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
-
-		for (i = disks; i--; )
-			clear_bit(R5_Wantprexor, &sh->dev[i].flags);
-	}
-
-	/* if only POSTXOR is set then this is an 'expand' postxor */
-	if (test_bit(STRIPE_OP_BIODRAIN, &sh->ops.complete) &&
-		test_bit(STRIPE_OP_POSTXOR, &sh->ops.complete)) {
-
-		clear_bit(STRIPE_OP_BIODRAIN, &sh->ops.complete);
-		clear_bit(STRIPE_OP_BIODRAIN, &sh->ops.ack);
-		clear_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending);
-
-		clear_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
-		clear_bit(STRIPE_OP_POSTXOR, &sh->ops.ack);
-		clear_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
+	if (sh->reconstruct_state == reconstruct_state_drain_result ||
+	    sh->reconstruct_state == reconstruct_state_prexor_drain_result) {
+		sh->reconstruct_state = reconstruct_state_idle;
 
 		/* All the 'written' buffers and the parity block are ready to
 		 * be written back to disk
@@ -2808,9 +2651,6 @@
 				(i == sh->pd_idx || dev->written)) {
 				pr_debug("Writing block %d\n", i);
 				set_bit(R5_Wantwrite, &dev->flags);
-				if (!test_and_set_bit(
-				    STRIPE_OP_IO, &sh->ops.pending))
-					sh->ops.count++;
 				if (prexor)
 					continue;
 				if (!test_bit(R5_Insync, &dev->flags) ||
@@ -2832,20 +2672,18 @@
 	 * 2/ A 'check' operation is in flight, as it may clobber the parity
 	 *    block.
 	 */
-	if (s.to_write && !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending) &&
-			  !test_bit(STRIPE_OP_CHECK, &sh->ops.pending))
-		handle_issuing_new_write_requests5(conf, sh, &s, disks);
+	if (s.to_write && !sh->reconstruct_state && !sh->check_state)
+		handle_stripe_dirtying5(conf, sh, &s, disks);
 
 	/* maybe we need to check and possibly fix the parity for this stripe
 	 * Any reads will already have been scheduled, so we just see if enough
 	 * data is available.  The parity check is held off while parity
 	 * dependent operations are in flight.
 	 */
-	if ((s.syncing && s.locked == 0 &&
-	     !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending) &&
-	     !test_bit(STRIPE_INSYNC, &sh->state)) ||
-	      test_bit(STRIPE_OP_CHECK, &sh->ops.pending) ||
-	      test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending))
+	if (sh->check_state ||
+	    (s.syncing && s.locked == 0 &&
+	     !test_bit(STRIPE_COMPUTE_RUN, &sh->state) &&
+	     !test_bit(STRIPE_INSYNC, &sh->state)))
 		handle_parity_checks5(conf, sh, &s, disks);
 
 	if (s.syncing && s.locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
@@ -2864,52 +2702,35 @@
 		dev = &sh->dev[s.failed_num];
 		if (!test_bit(R5_ReWrite, &dev->flags)) {
 			set_bit(R5_Wantwrite, &dev->flags);
-			if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
-				sh->ops.count++;
 			set_bit(R5_ReWrite, &dev->flags);
 			set_bit(R5_LOCKED, &dev->flags);
 			s.locked++;
 		} else {
 			/* let's read it back */
 			set_bit(R5_Wantread, &dev->flags);
-			if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
-				sh->ops.count++;
 			set_bit(R5_LOCKED, &dev->flags);
 			s.locked++;
 		}
 	}
 
-	/* Finish postxor operations initiated by the expansion
-	 * process
-	 */
-	if (test_bit(STRIPE_OP_POSTXOR, &sh->ops.complete) &&
-		!test_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending)) {
-
+	/* Finish reconstruct operations initiated by the expansion process */
+	if (sh->reconstruct_state == reconstruct_state_result) {
+		sh->reconstruct_state = reconstruct_state_idle;
 		clear_bit(STRIPE_EXPANDING, &sh->state);
-
-		clear_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
-		clear_bit(STRIPE_OP_POSTXOR, &sh->ops.ack);
-		clear_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
-
-		for (i = conf->raid_disks; i--; ) {
+		for (i = conf->raid_disks; i--; )
 			set_bit(R5_Wantwrite, &sh->dev[i].flags);
 			set_bit(R5_LOCKED, &dev->flags);
 			s.locked++;
-			if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
-				sh->ops.count++;
-		}
 	}
 
 	if (s.expanded && test_bit(STRIPE_EXPANDING, &sh->state) &&
-		!test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) {
+	    !sh->reconstruct_state) {
 		/* Need to write out all blocks after computing parity */
 		sh->disks = conf->raid_disks;
 		sh->pd_idx = stripe_to_pdidx(sh->sector, conf,
 			conf->raid_disks);
-		s.locked += handle_write_operations5(sh, 1, 1);
-	} else if (s.expanded &&
-		   s.locked == 0 &&
-		!test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) {
+		schedule_reconstruction5(sh, &s, 1, 1);
+	} else if (s.expanded && !sh->reconstruct_state && s.locked == 0) {
 		clear_bit(STRIPE_EXPAND_READY, &sh->state);
 		atomic_dec(&conf->reshape_stripes);
 		wake_up(&conf->wait_for_overlap);
@@ -2917,12 +2738,9 @@
 	}
 
 	if (s.expanding && s.locked == 0 &&
-	    !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending))
+	    !test_bit(STRIPE_COMPUTE_RUN, &sh->state))
 		handle_stripe_expansion(conf, sh, NULL);
 
-	if (sh->ops.count)
-		pending = get_stripe_work(sh);
-
  unlock:
 	spin_unlock(&sh->lock);
 
@@ -2930,11 +2748,12 @@
 	if (unlikely(blocked_rdev))
 		md_wait_for_blocked_rdev(blocked_rdev, conf->mddev);
 
-	if (pending)
-		raid5_run_ops(sh, pending);
+	if (s.ops_request)
+		raid5_run_ops(sh, s.ops_request);
+
+	ops_run_io(sh, &s);
 
 	return_io(return_bi);
-
 }
 
 static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
@@ -3042,8 +2861,7 @@
 	 * might need to be failed
 	 */
 	if (s.failed > 2 && s.to_read+s.to_write+s.written)
-		handle_requests_to_failed_array(conf, sh, &s, disks,
-						&return_bi);
+		handle_failed_stripe(conf, sh, &s, disks, &return_bi);
 	if (s.failed > 2 && s.syncing) {
 		md_done_sync(conf->mddev, STRIPE_SECTORS,0);
 		clear_bit(STRIPE_SYNCING, &sh->state);
@@ -3068,7 +2886,7 @@
 	     ( r6s.q_failed || ((test_bit(R5_Insync, &qdev->flags)
 			     && !test_bit(R5_LOCKED, &qdev->flags)
 			     && test_bit(R5_UPTODATE, &qdev->flags)))))
-		handle_completed_write_requests(conf, sh, disks, &return_bi);
+		handle_stripe_clean_event(conf, sh, disks, &return_bi);
 
 	/* Now we might consider reading some blocks, either to check/generate
 	 * parity, or to satisfy requests
@@ -3076,11 +2894,11 @@
 	 */
 	if (s.to_read || s.non_overwrite || (s.to_write && s.failed) ||
 	    (s.syncing && (s.uptodate < disks)) || s.expanding)
-		handle_issuing_new_read_requests6(sh, &s, &r6s, disks);
+		handle_stripe_fill6(sh, &s, &r6s, disks);
 
 	/* now to consider writing and what else, if anything should be read */
 	if (s.to_write)
-		handle_issuing_new_write_requests6(conf, sh, &s, &r6s, disks);
+		handle_stripe_dirtying6(conf, sh, &s, &r6s, disks);
 
 	/* maybe we need to check and possibly fix the parity for this stripe
 	 * Any reads will already have been scheduled, so we just see if enough
@@ -3136,7 +2954,7 @@
 	}
 
 	if (s.expanding && s.locked == 0 &&
-	    !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending))
+	    !test_bit(STRIPE_COMPUTE_RUN, &sh->state))
 		handle_stripe_expansion(conf, sh, &r6s);
 
  unlock:
@@ -3146,68 +2964,9 @@
 	if (unlikely(blocked_rdev))
 		md_wait_for_blocked_rdev(blocked_rdev, conf->mddev);
 
+	ops_run_io(sh, &s);
+
 	return_io(return_bi);
-
-	for (i=disks; i-- ;) {
-		int rw;
-		struct bio *bi;
-		mdk_rdev_t *rdev;
-		if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags))
-			rw = WRITE;
-		else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
-			rw = READ;
-		else
-			continue;
-
-		set_bit(STRIPE_IO_STARTED, &sh->state);
-
-		bi = &sh->dev[i].req;
-
-		bi->bi_rw = rw;
-		if (rw == WRITE)
-			bi->bi_end_io = raid5_end_write_request;
-		else
-			bi->bi_end_io = raid5_end_read_request;
-
-		rcu_read_lock();
-		rdev = rcu_dereference(conf->disks[i].rdev);
-		if (rdev && test_bit(Faulty, &rdev->flags))
-			rdev = NULL;
-		if (rdev)
-			atomic_inc(&rdev->nr_pending);
-		rcu_read_unlock();
-
-		if (rdev) {
-			if (s.syncing || s.expanding || s.expanded)
-				md_sync_acct(rdev->bdev, STRIPE_SECTORS);
-
-			bi->bi_bdev = rdev->bdev;
-			pr_debug("for %llu schedule op %ld on disc %d\n",
-				(unsigned long long)sh->sector, bi->bi_rw, i);
-			atomic_inc(&sh->count);
-			bi->bi_sector = sh->sector + rdev->data_offset;
-			bi->bi_flags = 1 << BIO_UPTODATE;
-			bi->bi_vcnt = 1;
-			bi->bi_max_vecs = 1;
-			bi->bi_idx = 0;
-			bi->bi_io_vec = &sh->dev[i].vec;
-			bi->bi_io_vec[0].bv_len = STRIPE_SIZE;
-			bi->bi_io_vec[0].bv_offset = 0;
-			bi->bi_size = STRIPE_SIZE;
-			bi->bi_next = NULL;
-			if (rw == WRITE &&
-			    test_bit(R5_ReWrite, &sh->dev[i].flags))
-				atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
-			generic_make_request(bi);
-		} else {
-			if (rw == WRITE)
-				set_bit(STRIPE_DEGRADED, &sh->state);
-			pr_debug("skip op %ld on disc %d for sector %llu\n",
-				bi->bi_rw, i, (unsigned long long)sh->sector);
-			clear_bit(R5_LOCKED, &sh->dev[i].flags);
-			set_bit(STRIPE_HANDLE, &sh->state);
-		}
-	}
 }
 
 static void handle_stripe(struct stripe_head *sh, struct page *tmp_page)
@@ -3697,9 +3456,7 @@
 		if ( rw == WRITE )
 			md_write_end(mddev);
 
-		bi->bi_end_io(bi,
-			      test_bit(BIO_UPTODATE, &bi->bi_flags)
-			        ? 0 : -EIO);
+		bio_endio(bi, 0);
 	}
 	return 0;
 }
@@ -3785,7 +3542,7 @@
 			    j == raid6_next_disk(sh->pd_idx, sh->disks))
 				continue;
 			s = compute_blocknr(sh, j);
-			if (s < (mddev->array_size<<1)) {
+			if (s < mddev->array_sectors) {
 				skipped = 1;
 				continue;
 			}
@@ -4002,12 +3759,8 @@
 	spin_lock_irq(&conf->device_lock);
 	remaining = --raid_bio->bi_phys_segments;
 	spin_unlock_irq(&conf->device_lock);
-	if (remaining == 0) {
-
-		raid_bio->bi_end_io(raid_bio,
-			      test_bit(BIO_UPTODATE, &raid_bio->bi_flags)
-			        ? 0 : -EIO);
-	}
+	if (remaining == 0)
+		bio_endio(raid_bio, 0);
 	if (atomic_dec_and_test(&conf->active_aligned_reads))
 		wake_up(&conf->wait_for_stripe);
 	return handled;
@@ -4094,6 +3847,8 @@
 {
 	raid5_conf_t *conf = mddev_to_conf(mddev);
 	unsigned long new;
+	int err;
+
 	if (len >= PAGE_SIZE)
 		return -EINVAL;
 	if (!conf)
@@ -4109,7 +3864,9 @@
 		else
 			break;
 	}
-	md_allow_write(mddev);
+	err = md_allow_write(mddev);
+	if (err)
+		return err;
 	while (new > conf->max_nr_stripes) {
 		if (grow_one_stripe(conf))
 			conf->max_nr_stripes++;
@@ -4434,7 +4191,7 @@
 	mddev->queue->backing_dev_info.congested_data = mddev;
 	mddev->queue->backing_dev_info.congested_fn = raid5_congested;
 
-	mddev->array_size =  mddev->size * (conf->previous_raid_disks -
+	mddev->array_sectors = 2 * mddev->size * (conf->previous_raid_disks -
 					    conf->max_degraded);
 
 	blk_queue_merge_bvec(mddev->queue, raid5_mergeable_bvec);
@@ -4609,35 +4366,41 @@
 static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
 {
 	raid5_conf_t *conf = mddev->private;
-	int found = 0;
+	int err = -EEXIST;
 	int disk;
 	struct disk_info *p;
+	int first = 0;
+	int last = conf->raid_disks - 1;
 
 	if (mddev->degraded > conf->max_degraded)
 		/* no point adding a device */
-		return 0;
+		return -EINVAL;
+
+	if (rdev->raid_disk >= 0)
+		first = last = rdev->raid_disk;
 
 	/*
 	 * find the disk ... but prefer rdev->saved_raid_disk
 	 * if possible.
 	 */
 	if (rdev->saved_raid_disk >= 0 &&
+	    rdev->saved_raid_disk >= first &&
 	    conf->disks[rdev->saved_raid_disk].rdev == NULL)
 		disk = rdev->saved_raid_disk;
 	else
-		disk = 0;
-	for ( ; disk < conf->raid_disks; disk++)
+		disk = first;
+	for ( ; disk <= last ; disk++)
 		if ((p=conf->disks + disk)->rdev == NULL) {
 			clear_bit(In_sync, &rdev->flags);
 			rdev->raid_disk = disk;
-			found = 1;
+			err = 0;
 			if (rdev->saved_raid_disk != disk)
 				conf->fullsync = 1;
 			rcu_assign_pointer(p->rdev, rdev);
 			break;
 		}
 	print_raid5_conf(conf);
-	return found;
+	return err;
 }
 
 static int raid5_resize(mddev_t *mddev, sector_t sectors)
@@ -4652,8 +4415,9 @@
 	raid5_conf_t *conf = mddev_to_conf(mddev);
 
 	sectors &= ~((sector_t)mddev->chunk_size/512 - 1);
-	mddev->array_size = (sectors * (mddev->raid_disks-conf->max_degraded))>>1;
-	set_capacity(mddev->gendisk, mddev->array_size << 1);
+	mddev->array_sectors = sectors * (mddev->raid_disks
+					  - conf->max_degraded);
+	set_capacity(mddev->gendisk, mddev->array_sectors);
 	mddev->changed = 1;
 	if (sectors/2  > mddev->size && mddev->recovery_cp == MaxSector) {
 		mddev->recovery_cp = mddev->size << 1;
@@ -4738,7 +4502,7 @@
 	rdev_for_each(rdev, rtmp, mddev)
 		if (rdev->raid_disk < 0 &&
 		    !test_bit(Faulty, &rdev->flags)) {
-			if (raid5_add_disk(mddev, rdev)) {
+			if (raid5_add_disk(mddev, rdev) == 0) {
 				char nm[20];
 				set_bit(In_sync, &rdev->flags);
 				added_devices++;
@@ -4786,15 +4550,16 @@
 	struct block_device *bdev;
 
 	if (!test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) {
-		conf->mddev->array_size = conf->mddev->size *
+		conf->mddev->array_sectors = 2 * conf->mddev->size *
 			(conf->raid_disks - conf->max_degraded);
-		set_capacity(conf->mddev->gendisk, conf->mddev->array_size << 1);
+		set_capacity(conf->mddev->gendisk, conf->mddev->array_sectors);
 		conf->mddev->changed = 1;
 
 		bdev = bdget_disk(conf->mddev->gendisk, 0);
 		if (bdev) {
 			mutex_lock(&bdev->bd_inode->i_mutex);
-			i_size_write(bdev->bd_inode, (loff_t)conf->mddev->array_size << 10);
+			i_size_write(bdev->bd_inode,
+				     (loff_t)conf->mddev->array_sectors << 9);
 			mutex_unlock(&bdev->bd_inode->i_mutex);
 			bdput(bdev);
 		}
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index e208a60..e713277 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -233,9 +233,9 @@
 
 	mutex_unlock(&dvbdev_register_lock);
 
-	clsdev = device_create(dvb_class, adap->device,
+	clsdev = device_create_drvdata(dvb_class, adap->device,
 			       MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
-			       "dvb%d.%s%d", adap->num, dnames[type], id);
+			       NULL, "dvb%d.%s%d", adap->num, dnames[type], id);
 	if (IS_ERR(clsdev)) {
 		printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n",
 		       __func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c
index a054668..4e3bfbc 100644
--- a/drivers/memstick/host/jmb38x_ms.c
+++ b/drivers/memstick/host/jmb38x_ms.c
@@ -51,7 +51,7 @@
 	void __iomem            *addr;
 	spinlock_t              lock;
 	int                     id;
-	char                    host_id[DEVICE_ID_SIZE];
+	char                    host_id[32];
 	int                     irq;
 	unsigned int            block_pos;
 	unsigned long           timeout_jiffies;
@@ -781,7 +781,7 @@
 
 	spin_lock_init(&host->lock);
 	host->id = cnt;
-	snprintf(host->host_id, DEVICE_ID_SIZE, DRIVER_NAME ":slot%d",
+	snprintf(host->host_id, sizeof(host->host_id), DRIVER_NAME ":slot%d",
 		 host->id);
 	host->irq = jm->pdev->irq;
 	host->timeout_jiffies = msecs_to_jiffies(1000);
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 75e599b..34402c4 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -1670,7 +1670,8 @@
 	INIT_DELAYED_WORK(&ioc->fault_reset_work, mpt_fault_reset_work);
 	spin_lock_init(&ioc->fault_reset_work_lock);
 
-	snprintf(ioc->reset_work_q_name, KOBJ_NAME_LEN, "mpt_poll_%d", ioc->id);
+	snprintf(ioc->reset_work_q_name, sizeof(ioc->reset_work_q_name),
+		 "mpt_poll_%d", ioc->id);
 	ioc->reset_work_q =
 		create_singlethread_workqueue(ioc->reset_work_q_name);
 	if (!ioc->reset_work_q) {
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 6adab64..dff048c 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -707,12 +707,12 @@
 	u8			 fc_link_speed[2];
 	spinlock_t		 fc_rescan_work_lock;
 	struct work_struct	 fc_rescan_work;
-	char			 fc_rescan_work_q_name[KOBJ_NAME_LEN];
+	char			 fc_rescan_work_q_name[20];
 	struct workqueue_struct *fc_rescan_work_q;
 	struct scsi_cmnd	**ScsiLookup;
 	spinlock_t		  scsi_lookup_lock;
 
-	char			 reset_work_q_name[KOBJ_NAME_LEN];
+	char			 reset_work_q_name[20];
 	struct workqueue_struct *reset_work_q;
 	struct delayed_work	 fault_reset_work;
 	spinlock_t		 fault_reset_work_lock;
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index fc31ca6..b36cae9 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -1326,8 +1326,8 @@
 
 	/* initialize workqueue */
 
-	snprintf(ioc->fc_rescan_work_q_name, KOBJ_NAME_LEN, "mptfc_wq_%d",
-		sh->host_no);
+	snprintf(ioc->fc_rescan_work_q_name, sizeof(ioc->fc_rescan_work_q_name),
+		 "mptfc_wq_%d", sh->host_no);
 	ioc->fc_rescan_work_q =
 		create_singlethread_workqueue(ioc->fc_rescan_work_q_name);
 	if (!ioc->fc_rescan_work_q)
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 260bade..9f93c29 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -5,6 +5,10 @@
 menu "Multifunction device drivers"
 	depends on HAS_IOMEM
 
+config MFD_CORE
+	tristate
+	default n
+
 config MFD_SM501
 	tristate "Support for Silicon Motion SM501"
 	 ---help---
@@ -38,6 +42,13 @@
 	  HTC Magician devices, respectively. Actual functionality is
 	  handled by the leds-pasic3 and ds1wm drivers.
 
+config MFD_TC6393XB
+	bool "Support Toshiba TC6393XB"
+	depends on HAVE_GPIO_LIB
+	select MFD_CORE
+	help
+	  Support for Toshiba Mobile IO Controller TC6393XB
+
 endmenu
 
 menu "Multimedia Capabilities Port drivers"
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index eef4e26..33daa2f 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -8,6 +8,10 @@
 obj-$(CONFIG_HTC_EGPIO)		+= htc-egpio.o
 obj-$(CONFIG_HTC_PASIC3)	+= htc-pasic3.o
 
+obj-$(CONFIG_MFD_TC6393XB)	+= tc6393xb.o
+
+obj-$(CONFIG_MFD_CORE)		+= mfd-core.o
+
 obj-$(CONFIG_MCP)		+= mcp-core.o
 obj-$(CONFIG_MCP_SA11X0)	+= mcp-sa11x0.o
 obj-$(CONFIG_MCP_UCB1200)	+= ucb1x00-core.o
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
new file mode 100644
index 0000000..d7d88ce
--- /dev/null
+++ b/drivers/mfd/mfd-core.c
@@ -0,0 +1,114 @@
+/*
+ * drivers/mfd/mfd-core.c
+ *
+ * core MFD support
+ * Copyright (c) 2006 Ian Molton
+ * Copyright (c) 2007,2008 Dmitry Baryshkov
+ *
+ * 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/platform_device.h>
+#include <linux/mfd/core.h>
+
+static int mfd_add_device(struct platform_device *parent,
+		const struct mfd_cell *cell,
+		struct resource *mem_base,
+		int irq_base)
+{
+	struct resource res[cell->num_resources];
+	struct platform_device *pdev;
+	int ret = -ENOMEM;
+	int r;
+
+	pdev = platform_device_alloc(cell->name, parent->id);
+	if (!pdev)
+		goto fail_alloc;
+
+	pdev->dev.parent = &parent->dev;
+
+	ret = platform_device_add_data(pdev,
+			cell, sizeof(struct mfd_cell));
+	if (ret)
+		goto fail_device;
+
+	memzero(res, sizeof(res));
+	for (r = 0; r < cell->num_resources; r++) {
+		res[r].name = cell->resources[r].name;
+		res[r].flags = cell->resources[r].flags;
+
+		/* Find out base to use */
+		if (cell->resources[r].flags & IORESOURCE_MEM) {
+			res[r].parent = mem_base;
+			res[r].start = mem_base->start +
+				cell->resources[r].start;
+			res[r].end = mem_base->start +
+				cell->resources[r].end;
+		} else if (cell->resources[r].flags & IORESOURCE_IRQ) {
+			res[r].start = irq_base +
+				cell->resources[r].start;
+			res[r].end   = irq_base +
+				cell->resources[r].end;
+		} else {
+			res[r].parent = cell->resources[r].parent;
+			res[r].start = cell->resources[r].start;
+			res[r].end   = cell->resources[r].end;
+		}
+	}
+
+	platform_device_add_resources(pdev, res, cell->num_resources);
+
+	ret = platform_device_add(pdev);
+	if (ret)
+		goto fail_device;
+
+	return 0;
+
+/*	platform_device_del(pdev); */
+fail_device:
+	platform_device_put(pdev);
+fail_alloc:
+	return ret;
+}
+
+int mfd_add_devices(
+		struct platform_device *parent,
+		const struct mfd_cell *cells, int n_devs,
+		struct resource *mem_base,
+		int irq_base)
+{
+	int i;
+	int ret = 0;
+
+	for (i = 0; i < n_devs; i++) {
+		ret = mfd_add_device(parent, cells + i, mem_base, irq_base);
+		if (ret)
+			break;
+	}
+
+	if (ret)
+		mfd_remove_devices(parent);
+
+	return ret;
+}
+EXPORT_SYMBOL(mfd_add_devices);
+
+static int mfd_remove_devices_fn(struct device *dev, void *unused)
+{
+	platform_device_unregister(
+			container_of(dev, struct platform_device, dev));
+	return 0;
+}
+
+void mfd_remove_devices(struct platform_device *parent)
+{
+	device_for_each_child(&parent->dev, NULL, mfd_remove_devices_fn);
+}
+EXPORT_SYMBOL(mfd_remove_devices);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov");
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
new file mode 100644
index 0000000..2d87501
--- /dev/null
+++ b/drivers/mfd/tc6393xb.c
@@ -0,0 +1,600 @@
+/*
+ * Toshiba TC6393XB SoC support
+ *
+ * Copyright(c) 2005-2006 Chris Humbert
+ * Copyright(c) 2005 Dirk Opfer
+ * Copyright(c) 2005 Ian Molton <spyro@f2s.com>
+ * Copyright(c) 2007 Dmitry Baryshkov
+ *
+ * Based on code written by Sharp/Lineo for 2.4 kernels
+ * Based on locomo.c
+ *
+ * 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/module.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/clk.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/tmio.h>
+#include <linux/mfd/tc6393xb.h>
+#include <linux/gpio.h>
+
+#define SCR_REVID	0x08		/* b Revision ID	*/
+#define SCR_ISR		0x50		/* b Interrupt Status	*/
+#define SCR_IMR		0x52		/* b Interrupt Mask	*/
+#define SCR_IRR		0x54		/* b Interrupt Routing	*/
+#define SCR_GPER	0x60		/* w GP Enable		*/
+#define SCR_GPI_SR(i)	(0x64 + (i))	/* b3 GPI Status	*/
+#define SCR_GPI_IMR(i)	(0x68 + (i))	/* b3 GPI INT Mask	*/
+#define SCR_GPI_EDER(i)	(0x6c + (i))	/* b3 GPI Edge Detect Enable */
+#define SCR_GPI_LIR(i)	(0x70 + (i))	/* b3 GPI Level Invert	*/
+#define SCR_GPO_DSR(i)	(0x78 + (i))	/* b3 GPO Data Set	*/
+#define SCR_GPO_DOECR(i) (0x7c + (i))	/* b3 GPO Data OE Control */
+#define SCR_GP_IARCR(i)	(0x80 + (i))	/* b3 GP Internal Active Register Control */
+#define SCR_GP_IARLCR(i) (0x84 + (i))	/* b3 GP INTERNAL Active Register Level Control */
+#define SCR_GPI_BCR(i)	(0x88 + (i))	/* b3 GPI Buffer Control */
+#define SCR_GPA_IARCR	0x8c		/* w GPa Internal Active Register Control */
+#define SCR_GPA_IARLCR	0x90		/* w GPa Internal Active Register Level Control */
+#define SCR_GPA_BCR	0x94		/* w GPa Buffer Control */
+#define SCR_CCR		0x98		/* w Clock Control	*/
+#define SCR_PLL2CR	0x9a		/* w PLL2 Control	*/
+#define SCR_PLL1CR	0x9c		/* l PLL1 Control	*/
+#define SCR_DIARCR	0xa0		/* b Device Internal Active Register Control */
+#define SCR_DBOCR	0xa1		/* b Device Buffer Off Control */
+#define SCR_FER		0xe0		/* b Function Enable	*/
+#define SCR_MCR		0xe4		/* w Mode Control	*/
+#define SCR_CONFIG	0xfc		/* b Configuration Control */
+#define SCR_DEBUG	0xff		/* b Debug		*/
+
+#define SCR_CCR_CK32K	BIT(0)
+#define SCR_CCR_USBCK	BIT(1)
+#define SCR_CCR_UNK1	BIT(4)
+#define SCR_CCR_MCLK_MASK	(7 << 8)
+#define SCR_CCR_MCLK_OFF	(0 << 8)
+#define SCR_CCR_MCLK_12	(1 << 8)
+#define SCR_CCR_MCLK_24	(2 << 8)
+#define SCR_CCR_MCLK_48	(3 << 8)
+#define SCR_CCR_HCLK_MASK	(3 << 12)
+#define SCR_CCR_HCLK_24	(0 << 12)
+#define SCR_CCR_HCLK_48	(1 << 12)
+
+#define SCR_FER_USBEN		BIT(0)	/* USB host enable */
+#define SCR_FER_LCDCVEN		BIT(1)	/* polysilicon TFT enable */
+#define SCR_FER_SLCDEN		BIT(2)	/* SLCD enable */
+
+#define SCR_MCR_RDY_MASK		(3 << 0)
+#define SCR_MCR_RDY_OPENDRAIN	(0 << 0)
+#define SCR_MCR_RDY_TRISTATE	(1 << 0)
+#define SCR_MCR_RDY_PUSHPULL	(2 << 0)
+#define SCR_MCR_RDY_UNK		BIT(2)
+#define SCR_MCR_RDY_EN		BIT(3)
+#define SCR_MCR_INT_MASK		(3 << 4)
+#define SCR_MCR_INT_OPENDRAIN	(0 << 4)
+#define SCR_MCR_INT_TRISTATE	(1 << 4)
+#define SCR_MCR_INT_PUSHPULL	(2 << 4)
+#define SCR_MCR_INT_UNK		BIT(6)
+#define SCR_MCR_INT_EN		BIT(7)
+/* bits 8 - 16 are unknown */
+
+#define TC_GPIO_BIT(i)		(1 << (i & 0x7))
+
+/*--------------------------------------------------------------------------*/
+
+struct tc6393xb {
+	void __iomem		*scr;
+
+	struct gpio_chip	gpio;
+
+	struct clk		*clk; /* 3,6 Mhz */
+
+	spinlock_t		lock; /* protects RMW cycles */
+
+	struct {
+		u8		fer;
+		u16		ccr;
+		u8		gpi_bcr[3];
+		u8		gpo_dsr[3];
+		u8		gpo_doecr[3];
+	} suspend_state;
+
+	struct resource		rscr;
+	struct resource		*iomem;
+	int			irq;
+	int			irq_base;
+};
+
+enum {
+	TC6393XB_CELL_NAND,
+};
+
+/*--------------------------------------------------------------------------*/
+
+static int tc6393xb_nand_enable(struct platform_device *nand)
+{
+	struct platform_device *dev = to_platform_device(nand->dev.parent);
+	struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&tc6393xb->lock, flags);
+
+	/* SMD buffer on */
+	dev_dbg(&dev->dev, "SMD buffer on\n");
+	iowrite8(0xff, tc6393xb->scr + SCR_GPI_BCR(1));
+
+	spin_unlock_irqrestore(&tc6393xb->lock, flags);
+
+	return 0;
+}
+
+static struct resource __devinitdata tc6393xb_nand_resources[] = {
+	{
+		.name	= TMIO_NAND_CONFIG,
+		.start	= 0x0100,
+		.end	= 0x01ff,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= TMIO_NAND_CONTROL,
+		.start	= 0x1000,
+		.end	= 0x1007,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= TMIO_NAND_IRQ,
+		.start	= IRQ_TC6393_NAND,
+		.end	= IRQ_TC6393_NAND,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct mfd_cell __devinitdata tc6393xb_cells[] = {
+	[TC6393XB_CELL_NAND] = {
+		.name = "tmio-nand",
+		.enable = tc6393xb_nand_enable,
+		.num_resources = ARRAY_SIZE(tc6393xb_nand_resources),
+		.resources = tc6393xb_nand_resources,
+	},
+};
+
+/*--------------------------------------------------------------------------*/
+
+static int tc6393xb_gpio_get(struct gpio_chip *chip,
+		unsigned offset)
+{
+	struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
+
+	/* XXX: does dsr also represent inputs? */
+	return ioread8(tc6393xb->scr + SCR_GPO_DSR(offset / 8))
+		& TC_GPIO_BIT(offset);
+}
+
+static void __tc6393xb_gpio_set(struct gpio_chip *chip,
+		unsigned offset, int value)
+{
+	struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
+	u8  dsr;
+
+	dsr = ioread8(tc6393xb->scr + SCR_GPO_DSR(offset / 8));
+	if (value)
+		dsr |= TC_GPIO_BIT(offset);
+	else
+		dsr &= ~TC_GPIO_BIT(offset);
+
+	iowrite8(dsr, tc6393xb->scr + SCR_GPO_DSR(offset / 8));
+}
+
+static void tc6393xb_gpio_set(struct gpio_chip *chip,
+		unsigned offset, int value)
+{
+	struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
+	unsigned long flags;
+
+	spin_lock_irqsave(&tc6393xb->lock, flags);
+
+	__tc6393xb_gpio_set(chip, offset, value);
+
+	spin_unlock_irqrestore(&tc6393xb->lock, flags);
+}
+
+static int tc6393xb_gpio_direction_input(struct gpio_chip *chip,
+			unsigned offset)
+{
+	struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
+	unsigned long flags;
+	u8 doecr;
+
+	spin_lock_irqsave(&tc6393xb->lock, flags);
+
+	doecr = ioread8(tc6393xb->scr + SCR_GPO_DOECR(offset / 8));
+	doecr &= ~TC_GPIO_BIT(offset);
+	iowrite8(doecr, tc6393xb->scr + SCR_GPO_DOECR(offset / 8));
+
+	spin_unlock_irqrestore(&tc6393xb->lock, flags);
+
+	return 0;
+}
+
+static int tc6393xb_gpio_direction_output(struct gpio_chip *chip,
+			unsigned offset, int value)
+{
+	struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
+	unsigned long flags;
+	u8 doecr;
+
+	spin_lock_irqsave(&tc6393xb->lock, flags);
+
+	__tc6393xb_gpio_set(chip, offset, value);
+
+	doecr = ioread8(tc6393xb->scr + SCR_GPO_DOECR(offset / 8));
+	doecr |= TC_GPIO_BIT(offset);
+	iowrite8(doecr, tc6393xb->scr + SCR_GPO_DOECR(offset / 8));
+
+	spin_unlock_irqrestore(&tc6393xb->lock, flags);
+
+	return 0;
+}
+
+static int tc6393xb_register_gpio(struct tc6393xb *tc6393xb, int gpio_base)
+{
+	tc6393xb->gpio.label = "tc6393xb";
+	tc6393xb->gpio.base = gpio_base;
+	tc6393xb->gpio.ngpio = 16;
+	tc6393xb->gpio.set = tc6393xb_gpio_set;
+	tc6393xb->gpio.get = tc6393xb_gpio_get;
+	tc6393xb->gpio.direction_input = tc6393xb_gpio_direction_input;
+	tc6393xb->gpio.direction_output = tc6393xb_gpio_direction_output;
+
+	return gpiochip_add(&tc6393xb->gpio);
+}
+
+/*--------------------------------------------------------------------------*/
+
+static void
+tc6393xb_irq(unsigned int irq, struct irq_desc *desc)
+{
+	struct tc6393xb *tc6393xb = get_irq_data(irq);
+	unsigned int isr;
+	unsigned int i, irq_base;
+
+	irq_base = tc6393xb->irq_base;
+
+	while ((isr = ioread8(tc6393xb->scr + SCR_ISR) &
+				~ioread8(tc6393xb->scr + SCR_IMR)))
+		for (i = 0; i < TC6393XB_NR_IRQS; i++) {
+			if (isr & (1 << i))
+				generic_handle_irq(irq_base + i);
+		}
+}
+
+static void tc6393xb_irq_ack(unsigned int irq)
+{
+}
+
+static void tc6393xb_irq_mask(unsigned int irq)
+{
+	struct tc6393xb *tc6393xb = get_irq_chip_data(irq);
+	unsigned long flags;
+	u8 imr;
+
+	spin_lock_irqsave(&tc6393xb->lock, flags);
+	imr = ioread8(tc6393xb->scr + SCR_IMR);
+	imr |= 1 << (irq - tc6393xb->irq_base);
+	iowrite8(imr, tc6393xb->scr + SCR_IMR);
+	spin_unlock_irqrestore(&tc6393xb->lock, flags);
+}
+
+static void tc6393xb_irq_unmask(unsigned int irq)
+{
+	struct tc6393xb *tc6393xb = get_irq_chip_data(irq);
+	unsigned long flags;
+	u8 imr;
+
+	spin_lock_irqsave(&tc6393xb->lock, flags);
+	imr = ioread8(tc6393xb->scr + SCR_IMR);
+	imr &= ~(1 << (irq - tc6393xb->irq_base));
+	iowrite8(imr, tc6393xb->scr + SCR_IMR);
+	spin_unlock_irqrestore(&tc6393xb->lock, flags);
+}
+
+static struct irq_chip tc6393xb_chip = {
+	.name	= "tc6393xb",
+	.ack	= tc6393xb_irq_ack,
+	.mask	= tc6393xb_irq_mask,
+	.unmask	= tc6393xb_irq_unmask,
+};
+
+static void tc6393xb_attach_irq(struct platform_device *dev)
+{
+	struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+	unsigned int irq, irq_base;
+
+	irq_base = tc6393xb->irq_base;
+
+	for (irq = irq_base; irq < irq_base + TC6393XB_NR_IRQS; irq++) {
+		set_irq_chip(irq, &tc6393xb_chip);
+		set_irq_chip_data(irq, tc6393xb);
+		set_irq_handler(irq, handle_edge_irq);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	}
+
+	set_irq_type(tc6393xb->irq, IRQT_FALLING);
+	set_irq_data(tc6393xb->irq, tc6393xb);
+	set_irq_chained_handler(tc6393xb->irq, tc6393xb_irq);
+}
+
+static void tc6393xb_detach_irq(struct platform_device *dev)
+{
+	struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+	unsigned int irq, irq_base;
+
+	set_irq_chained_handler(tc6393xb->irq, NULL);
+	set_irq_data(tc6393xb->irq, NULL);
+
+	irq_base = tc6393xb->irq_base;
+
+	for (irq = irq_base; irq < irq_base + TC6393XB_NR_IRQS; irq++) {
+		set_irq_flags(irq, 0);
+		set_irq_chip(irq, NULL);
+		set_irq_chip_data(irq, NULL);
+	}
+}
+
+/*--------------------------------------------------------------------------*/
+
+static int tc6393xb_hw_init(struct platform_device *dev)
+{
+	struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
+	struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+	int i;
+
+	iowrite8(tc6393xb->suspend_state.fer,	tc6393xb->scr + SCR_FER);
+	iowrite16(tcpd->scr_pll2cr,		tc6393xb->scr + SCR_PLL2CR);
+	iowrite16(tc6393xb->suspend_state.ccr,	tc6393xb->scr + SCR_CCR);
+	iowrite16(SCR_MCR_RDY_OPENDRAIN | SCR_MCR_RDY_UNK | SCR_MCR_RDY_EN |
+		  SCR_MCR_INT_OPENDRAIN | SCR_MCR_INT_UNK | SCR_MCR_INT_EN |
+		  BIT(15),			tc6393xb->scr + SCR_MCR);
+	iowrite16(tcpd->scr_gper,		tc6393xb->scr + SCR_GPER);
+	iowrite8(0,				tc6393xb->scr + SCR_IRR);
+	iowrite8(0xbf,				tc6393xb->scr + SCR_IMR);
+
+	for (i = 0; i < 3; i++) {
+		iowrite8(tc6393xb->suspend_state.gpo_dsr[i],
+					tc6393xb->scr + SCR_GPO_DSR(i));
+		iowrite8(tc6393xb->suspend_state.gpo_doecr[i],
+					tc6393xb->scr + SCR_GPO_DOECR(i));
+		iowrite8(tc6393xb->suspend_state.gpi_bcr[i],
+					tc6393xb->scr + SCR_GPI_BCR(i));
+	}
+
+	return 0;
+}
+
+static int __devinit tc6393xb_probe(struct platform_device *dev)
+{
+	struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
+	struct tc6393xb *tc6393xb;
+	struct resource *iomem;
+	struct resource *rscr;
+	int retval, temp;
+	int i;
+
+	iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!iomem)
+		return -EINVAL;
+
+	tc6393xb = kzalloc(sizeof *tc6393xb, GFP_KERNEL);
+	if (!tc6393xb) {
+		retval = -ENOMEM;
+		goto err_kzalloc;
+	}
+
+	spin_lock_init(&tc6393xb->lock);
+
+	platform_set_drvdata(dev, tc6393xb);
+	tc6393xb->iomem = iomem;
+	tc6393xb->irq = platform_get_irq(dev, 0);
+	tc6393xb->irq_base = tcpd->irq_base;
+
+	tc6393xb->clk = clk_get(&dev->dev, "GPIO27_CLK" /* "CK3P6MI" */);
+	if (IS_ERR(tc6393xb->clk)) {
+		retval = PTR_ERR(tc6393xb->clk);
+		goto err_clk_get;
+	}
+
+	rscr = &tc6393xb->rscr;
+	rscr->name = "tc6393xb-core";
+	rscr->start = iomem->start;
+	rscr->end = iomem->start + 0xff;
+	rscr->flags = IORESOURCE_MEM;
+
+	retval = request_resource(iomem, rscr);
+	if (retval)
+		goto err_request_scr;
+
+	tc6393xb->scr = ioremap(rscr->start, rscr->end - rscr->start + 1);
+	if (!tc6393xb->scr) {
+		retval = -ENOMEM;
+		goto err_ioremap;
+	}
+
+	retval = clk_enable(tc6393xb->clk);
+	if (retval)
+		goto err_clk_enable;
+
+	retval = tcpd->enable(dev);
+	if (retval)
+		goto err_enable;
+
+	tc6393xb->suspend_state.fer = 0;
+	for (i = 0; i < 3; i++) {
+		tc6393xb->suspend_state.gpo_dsr[i] =
+			(tcpd->scr_gpo_dsr >> (8 * i)) & 0xff;
+		tc6393xb->suspend_state.gpo_doecr[i] =
+			(tcpd->scr_gpo_doecr >> (8 * i)) & 0xff;
+	}
+	/*
+	 * It may be necessary to change this back to
+	 * platform-dependant code
+	 */
+	tc6393xb->suspend_state.ccr = SCR_CCR_UNK1 |
+					SCR_CCR_HCLK_48;
+
+	retval = tc6393xb_hw_init(dev);
+	if (retval)
+		goto err_hw_init;
+
+	printk(KERN_INFO "Toshiba tc6393xb revision %d at 0x%08lx, irq %d\n",
+			ioread8(tc6393xb->scr + SCR_REVID),
+			(unsigned long) iomem->start, tc6393xb->irq);
+
+	tc6393xb->gpio.base = -1;
+
+	if (tcpd->gpio_base >= 0) {
+		retval = tc6393xb_register_gpio(tc6393xb, tcpd->gpio_base);
+		if (retval)
+			goto err_gpio_add;
+	}
+
+	if (tc6393xb->irq)
+		tc6393xb_attach_irq(dev);
+
+	tc6393xb_cells[TC6393XB_CELL_NAND].driver_data = tcpd->nand_data;
+
+	retval = mfd_add_devices(dev,
+			tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells),
+			iomem, tcpd->irq_base);
+
+	return 0;
+
+	if (tc6393xb->irq)
+		tc6393xb_detach_irq(dev);
+
+err_gpio_add:
+	if (tc6393xb->gpio.base != -1)
+		temp = gpiochip_remove(&tc6393xb->gpio);
+err_hw_init:
+	tcpd->disable(dev);
+err_clk_enable:
+	clk_disable(tc6393xb->clk);
+err_enable:
+	iounmap(tc6393xb->scr);
+err_ioremap:
+	release_resource(&tc6393xb->rscr);
+err_request_scr:
+	clk_put(tc6393xb->clk);
+err_clk_get:
+	kfree(tc6393xb);
+err_kzalloc:
+	return retval;
+}
+
+static int __devexit tc6393xb_remove(struct platform_device *dev)
+{
+	struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
+	struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+	int ret;
+
+	mfd_remove_devices(dev);
+
+	if (tc6393xb->irq)
+		tc6393xb_detach_irq(dev);
+
+	if (tc6393xb->gpio.base != -1) {
+		ret = gpiochip_remove(&tc6393xb->gpio);
+		if (ret) {
+			dev_err(&dev->dev, "Can't remove gpio chip: %d\n", ret);
+			return ret;
+		}
+	}
+
+	ret = tcpd->disable(dev);
+
+	clk_disable(tc6393xb->clk);
+
+	iounmap(tc6393xb->scr);
+
+	release_resource(&tc6393xb->rscr);
+
+	platform_set_drvdata(dev, NULL);
+
+	clk_put(tc6393xb->clk);
+
+	kfree(tc6393xb);
+
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static int tc6393xb_suspend(struct platform_device *dev, pm_message_t state)
+{
+	struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
+	struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
+	int i;
+
+
+	tc6393xb->suspend_state.ccr = ioread16(tc6393xb->scr + SCR_CCR);
+	tc6393xb->suspend_state.fer = ioread8(tc6393xb->scr + SCR_FER);
+
+	for (i = 0; i < 3; i++) {
+		tc6393xb->suspend_state.gpo_dsr[i] =
+			ioread8(tc6393xb->scr + SCR_GPO_DSR(i));
+		tc6393xb->suspend_state.gpo_doecr[i] =
+			ioread8(tc6393xb->scr + SCR_GPO_DOECR(i));
+		tc6393xb->suspend_state.gpi_bcr[i] =
+			ioread8(tc6393xb->scr + SCR_GPI_BCR(i));
+	}
+
+	return tcpd->suspend(dev);
+}
+
+static int tc6393xb_resume(struct platform_device *dev)
+{
+	struct tc6393xb_platform_data *tcpd = dev->dev.platform_data;
+	int ret = tcpd->resume(dev);
+
+	if (ret)
+		return ret;
+
+	return tc6393xb_hw_init(dev);
+}
+#else
+#define tc6393xb_suspend NULL
+#define tc6393xb_resume NULL
+#endif
+
+static struct platform_driver tc6393xb_driver = {
+	.probe = tc6393xb_probe,
+	.remove = __devexit_p(tc6393xb_remove),
+	.suspend = tc6393xb_suspend,
+	.resume = tc6393xb_resume,
+
+	.driver = {
+		.name = "tc6393xb",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init tc6393xb_init(void)
+{
+	return platform_driver_register(&tc6393xb_driver);
+}
+
+static void __exit tc6393xb_exit(void)
+{
+	platform_driver_unregister(&tc6393xb_driver);
+}
+
+subsys_initcall(tc6393xb_init);
+module_exit(tc6393xb_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov and Dirk Opfer");
+MODULE_DESCRIPTION("tc6393xb Toshiba Mobile IO Controller");
+MODULE_ALIAS("platform:tc6393xb");
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 1921b8d..ce67d97 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -420,4 +420,17 @@
 	  this feature will allow for direct communication between SSIs
 	  based on a network adapter and DMA messaging.
 
+config HP_ILO
+	tristate "Channel interface driver for HP iLO/iLO2 processor"
+	default n
+	help
+	  The channel interface driver allows applications to communicate
+	  with iLO/iLO2 management processors present on HP ProLiant
+	  servers.  Upon loading, the driver creates /dev/hpilo/dXccbN files,
+	  which can be used to gather data from the management processor,
+	  via read and write system calls.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called hpilo.
+
 endif # MISC_DEVICES
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index a6dac6a..688fe76 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -27,3 +27,4 @@
 obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
 obj-$(CONFIG_KGDB_TESTS)	+= kgdbts.o
 obj-$(CONFIG_SGI_XP)		+= sgi-xp/
+obj-$(CONFIG_HP_ILO)		+= hpilo.o
diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c
new file mode 100644
index 0000000..05e2982
--- /dev/null
+++ b/drivers/misc/hpilo.c
@@ -0,0 +1,768 @@
+/*
+ * Driver for HP iLO/iLO2 management processor.
+ *
+ * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
+ *	David Altobelli <david.altobelli@hp.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/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/file.h>
+#include <linux/cdev.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include "hpilo.h"
+
+static struct class *ilo_class;
+static unsigned int ilo_major;
+static char ilo_hwdev[MAX_ILO_DEV];
+
+static inline int get_entry_id(int entry)
+{
+	return (entry & ENTRY_MASK_DESCRIPTOR) >> ENTRY_BITPOS_DESCRIPTOR;
+}
+
+static inline int get_entry_len(int entry)
+{
+	return ((entry & ENTRY_MASK_QWORDS) >> ENTRY_BITPOS_QWORDS) << 3;
+}
+
+static inline int mk_entry(int id, int len)
+{
+	int qlen = len & 7 ? (len >> 3) + 1 : len >> 3;
+	return id << ENTRY_BITPOS_DESCRIPTOR | qlen << ENTRY_BITPOS_QWORDS;
+}
+
+static inline int desc_mem_sz(int nr_entry)
+{
+	return nr_entry << L2_QENTRY_SZ;
+}
+
+/*
+ * FIFO queues, shared with hardware.
+ *
+ * If a queue has empty slots, an entry is added to the queue tail,
+ * and that entry is marked as occupied.
+ * Entries can be dequeued from the head of the list, when the device
+ * has marked the entry as consumed.
+ *
+ * Returns true on successful queue/dequeue, false on failure.
+ */
+static int fifo_enqueue(struct ilo_hwinfo *hw, char *fifobar, int entry)
+{
+	struct fifo *fifo_q = FIFOBARTOHANDLE(fifobar);
+	int ret = 0;
+
+	spin_lock(&hw->fifo_lock);
+	if (!(fifo_q->fifobar[(fifo_q->tail + 1) & fifo_q->imask]
+	      & ENTRY_MASK_O)) {
+		fifo_q->fifobar[fifo_q->tail & fifo_q->imask] |=
+				(entry & ENTRY_MASK_NOSTATE) | fifo_q->merge;
+		fifo_q->tail += 1;
+		ret = 1;
+	}
+	spin_unlock(&hw->fifo_lock);
+
+	return ret;
+}
+
+static int fifo_dequeue(struct ilo_hwinfo *hw, char *fifobar, int *entry)
+{
+	struct fifo *fifo_q = FIFOBARTOHANDLE(fifobar);
+	int ret = 0;
+	u64 c;
+
+	spin_lock(&hw->fifo_lock);
+	c = fifo_q->fifobar[fifo_q->head & fifo_q->imask];
+	if (c & ENTRY_MASK_C) {
+		if (entry)
+			*entry = c & ENTRY_MASK_NOSTATE;
+
+		fifo_q->fifobar[fifo_q->head & fifo_q->imask] =
+							(c | ENTRY_MASK) + 1;
+		fifo_q->head += 1;
+		ret = 1;
+	}
+	spin_unlock(&hw->fifo_lock);
+
+	return ret;
+}
+
+static int ilo_pkt_enqueue(struct ilo_hwinfo *hw, struct ccb *ccb,
+			   int dir, int id, int len)
+{
+	char *fifobar;
+	int entry;
+
+	if (dir == SENDQ)
+		fifobar = ccb->ccb_u1.send_fifobar;
+	else
+		fifobar = ccb->ccb_u3.recv_fifobar;
+
+	entry = mk_entry(id, len);
+	return fifo_enqueue(hw, fifobar, entry);
+}
+
+static int ilo_pkt_dequeue(struct ilo_hwinfo *hw, struct ccb *ccb,
+			   int dir, int *id, int *len, void **pkt)
+{
+	char *fifobar, *desc;
+	int entry = 0, pkt_id = 0;
+	int ret;
+
+	if (dir == SENDQ) {
+		fifobar = ccb->ccb_u1.send_fifobar;
+		desc = ccb->ccb_u2.send_desc;
+	} else {
+		fifobar = ccb->ccb_u3.recv_fifobar;
+		desc = ccb->ccb_u4.recv_desc;
+	}
+
+	ret = fifo_dequeue(hw, fifobar, &entry);
+	if (ret) {
+		pkt_id = get_entry_id(entry);
+		if (id)
+			*id = pkt_id;
+		if (len)
+			*len = get_entry_len(entry);
+		if (pkt)
+			*pkt = (void *)(desc + desc_mem_sz(pkt_id));
+	}
+
+	return ret;
+}
+
+static inline void doorbell_set(struct ccb *ccb)
+{
+	iowrite8(1, ccb->ccb_u5.db_base);
+}
+
+static inline void doorbell_clr(struct ccb *ccb)
+{
+	iowrite8(2, ccb->ccb_u5.db_base);
+}
+static inline int ctrl_set(int l2sz, int idxmask, int desclim)
+{
+	int active = 0, go = 1;
+	return l2sz << CTRL_BITPOS_L2SZ |
+	       idxmask << CTRL_BITPOS_FIFOINDEXMASK |
+	       desclim << CTRL_BITPOS_DESCLIMIT |
+	       active << CTRL_BITPOS_A |
+	       go << CTRL_BITPOS_G;
+}
+static void ctrl_setup(struct ccb *ccb, int nr_desc, int l2desc_sz)
+{
+	/* for simplicity, use the same parameters for send and recv ctrls */
+	ccb->send_ctrl = ctrl_set(l2desc_sz, nr_desc-1, nr_desc-1);
+	ccb->recv_ctrl = ctrl_set(l2desc_sz, nr_desc-1, nr_desc-1);
+}
+
+static inline int fifo_sz(int nr_entry)
+{
+	/* size of a fifo is determined by the number of entries it contains */
+	return (nr_entry * sizeof(u64)) + FIFOHANDLESIZE;
+}
+
+static void fifo_setup(void *base_addr, int nr_entry)
+{
+	struct fifo *fifo_q = base_addr;
+	int i;
+
+	/* set up an empty fifo */
+	fifo_q->head = 0;
+	fifo_q->tail = 0;
+	fifo_q->reset = 0;
+	fifo_q->nrents = nr_entry;
+	fifo_q->imask = nr_entry - 1;
+	fifo_q->merge = ENTRY_MASK_O;
+
+	for (i = 0; i < nr_entry; i++)
+		fifo_q->fifobar[i] = 0;
+}
+
+static void ilo_ccb_close(struct pci_dev *pdev, struct ccb_data *data)
+{
+	struct ccb *driver_ccb;
+	struct ccb __iomem *device_ccb;
+	int retries;
+
+	driver_ccb = &data->driver_ccb;
+	device_ccb = data->mapped_ccb;
+
+	/* complicated dance to tell the hw we are stopping */
+	doorbell_clr(driver_ccb);
+	iowrite32(ioread32(&device_ccb->send_ctrl) & ~(1 << CTRL_BITPOS_G),
+		  &device_ccb->send_ctrl);
+	iowrite32(ioread32(&device_ccb->recv_ctrl) & ~(1 << CTRL_BITPOS_G),
+		  &device_ccb->recv_ctrl);
+
+	/* give iLO some time to process stop request */
+	for (retries = 1000; retries > 0; retries--) {
+		doorbell_set(driver_ccb);
+		udelay(1);
+		if (!(ioread32(&device_ccb->send_ctrl) & (1 << CTRL_BITPOS_A))
+		    &&
+		    !(ioread32(&device_ccb->recv_ctrl) & (1 << CTRL_BITPOS_A)))
+			break;
+	}
+	if (retries == 0)
+		dev_err(&pdev->dev, "Closing, but controller still active\n");
+
+	/* clear the hw ccb */
+	memset_io(device_ccb, 0, sizeof(struct ccb));
+
+	/* free resources used to back send/recv queues */
+	pci_free_consistent(pdev, data->dma_size, data->dma_va, data->dma_pa);
+}
+
+static int ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot)
+{
+	char *dma_va, *dma_pa;
+	int pkt_id, pkt_sz, i, error;
+	struct ccb *driver_ccb, *ilo_ccb;
+	struct pci_dev *pdev;
+
+	driver_ccb = &data->driver_ccb;
+	ilo_ccb = &data->ilo_ccb;
+	pdev = hw->ilo_dev;
+
+	data->dma_size = 2 * fifo_sz(NR_QENTRY) +
+			 2 * desc_mem_sz(NR_QENTRY) +
+			 ILO_START_ALIGN + ILO_CACHE_SZ;
+
+	error = -ENOMEM;
+	data->dma_va = pci_alloc_consistent(pdev, data->dma_size,
+					    &data->dma_pa);
+	if (!data->dma_va)
+		goto out;
+
+	dma_va = (char *)data->dma_va;
+	dma_pa = (char *)data->dma_pa;
+
+	memset(dma_va, 0, data->dma_size);
+
+	dma_va = (char *)roundup((unsigned long)dma_va, ILO_START_ALIGN);
+	dma_pa = (char *)roundup((unsigned long)dma_pa, ILO_START_ALIGN);
+
+	/*
+	 * Create two ccb's, one with virt addrs, one with phys addrs.
+	 * Copy the phys addr ccb to device shared mem.
+	 */
+	ctrl_setup(driver_ccb, NR_QENTRY, L2_QENTRY_SZ);
+	ctrl_setup(ilo_ccb, NR_QENTRY, L2_QENTRY_SZ);
+
+	fifo_setup(dma_va, NR_QENTRY);
+	driver_ccb->ccb_u1.send_fifobar = dma_va + FIFOHANDLESIZE;
+	ilo_ccb->ccb_u1.send_fifobar = dma_pa + FIFOHANDLESIZE;
+	dma_va += fifo_sz(NR_QENTRY);
+	dma_pa += fifo_sz(NR_QENTRY);
+
+	dma_va = (char *)roundup((unsigned long)dma_va, ILO_CACHE_SZ);
+	dma_pa = (char *)roundup((unsigned long)dma_pa, ILO_CACHE_SZ);
+
+	fifo_setup(dma_va, NR_QENTRY);
+	driver_ccb->ccb_u3.recv_fifobar = dma_va + FIFOHANDLESIZE;
+	ilo_ccb->ccb_u3.recv_fifobar = dma_pa + FIFOHANDLESIZE;
+	dma_va += fifo_sz(NR_QENTRY);
+	dma_pa += fifo_sz(NR_QENTRY);
+
+	driver_ccb->ccb_u2.send_desc = dma_va;
+	ilo_ccb->ccb_u2.send_desc = dma_pa;
+	dma_pa += desc_mem_sz(NR_QENTRY);
+	dma_va += desc_mem_sz(NR_QENTRY);
+
+	driver_ccb->ccb_u4.recv_desc = dma_va;
+	ilo_ccb->ccb_u4.recv_desc = dma_pa;
+
+	driver_ccb->channel = slot;
+	ilo_ccb->channel = slot;
+
+	driver_ccb->ccb_u5.db_base = hw->db_vaddr + (slot << L2_DB_SIZE);
+	ilo_ccb->ccb_u5.db_base = NULL; /* hw ccb's doorbell is not used */
+
+	/* copy the ccb with physical addrs to device memory */
+	data->mapped_ccb = (struct ccb __iomem *)
+				(hw->ram_vaddr + (slot * ILOHW_CCB_SZ));
+	memcpy_toio(data->mapped_ccb, ilo_ccb, sizeof(struct ccb));
+
+	/* put packets on the send and receive queues */
+	pkt_sz = 0;
+	for (pkt_id = 0; pkt_id < NR_QENTRY; pkt_id++) {
+		ilo_pkt_enqueue(hw, driver_ccb, SENDQ, pkt_id, pkt_sz);
+		doorbell_set(driver_ccb);
+	}
+
+	pkt_sz = desc_mem_sz(1);
+	for (pkt_id = 0; pkt_id < NR_QENTRY; pkt_id++)
+		ilo_pkt_enqueue(hw, driver_ccb, RECVQ, pkt_id, pkt_sz);
+
+	doorbell_clr(driver_ccb);
+
+	/* make sure iLO is really handling requests */
+	for (i = 1000; i > 0; i--) {
+		if (ilo_pkt_dequeue(hw, driver_ccb, SENDQ, &pkt_id, NULL, NULL))
+			break;
+		udelay(1);
+	}
+
+	if (i) {
+		ilo_pkt_enqueue(hw, driver_ccb, SENDQ, pkt_id, 0);
+		doorbell_set(driver_ccb);
+	} else {
+		dev_err(&pdev->dev, "Open could not dequeue a packet\n");
+		error = -EBUSY;
+		goto free;
+	}
+
+	return 0;
+free:
+	pci_free_consistent(pdev, data->dma_size, data->dma_va, data->dma_pa);
+out:
+	return error;
+}
+
+static inline int is_channel_reset(struct ccb *ccb)
+{
+	/* check for this particular channel needing a reset */
+	return FIFOBARTOHANDLE(ccb->ccb_u1.send_fifobar)->reset;
+}
+
+static inline void set_channel_reset(struct ccb *ccb)
+{
+	/* set a flag indicating this channel needs a reset */
+	FIFOBARTOHANDLE(ccb->ccb_u1.send_fifobar)->reset = 1;
+}
+
+static inline int is_device_reset(struct ilo_hwinfo *hw)
+{
+	/* check for global reset condition */
+	return ioread32(&hw->mmio_vaddr[DB_OUT]) & (1 << DB_RESET);
+}
+
+static inline void clear_device(struct ilo_hwinfo *hw)
+{
+	/* clear the device (reset bits, pending channel entries) */
+	iowrite32(-1, &hw->mmio_vaddr[DB_OUT]);
+}
+
+static void ilo_locked_reset(struct ilo_hwinfo *hw)
+{
+	int slot;
+
+	/*
+	 * Mapped memory is zeroed on ilo reset, so set a per ccb flag
+	 * to indicate that this ccb needs to be closed and reopened.
+	 */
+	for (slot = 0; slot < MAX_CCB; slot++) {
+		if (!hw->ccb_alloc[slot])
+			continue;
+		set_channel_reset(&hw->ccb_alloc[slot]->driver_ccb);
+	}
+
+	clear_device(hw);
+}
+
+static void ilo_reset(struct ilo_hwinfo *hw)
+{
+	spin_lock(&hw->alloc_lock);
+
+	/* reset might have been handled after lock was taken */
+	if (is_device_reset(hw))
+		ilo_locked_reset(hw);
+
+	spin_unlock(&hw->alloc_lock);
+}
+
+static ssize_t ilo_read(struct file *fp, char __user *buf,
+			size_t len, loff_t *off)
+{
+	int err, found, cnt, pkt_id, pkt_len;
+	struct ccb_data *data;
+	struct ccb *driver_ccb;
+	struct ilo_hwinfo *hw;
+	void *pkt;
+
+	data = fp->private_data;
+	driver_ccb = &data->driver_ccb;
+	hw = data->ilo_hw;
+
+	if (is_device_reset(hw) || is_channel_reset(driver_ccb)) {
+		/*
+		 * If the device has been reset, applications
+		 * need to close and reopen all ccbs.
+		 */
+		ilo_reset(hw);
+		return -ENODEV;
+	}
+
+	/*
+	 * This function is to be called when data is expected
+	 * in the channel, and will return an error if no packet is found
+	 * during the loop below.  The sleep/retry logic is to allow
+	 * applications to call read() immediately post write(),
+	 * and give iLO some time to process the sent packet.
+	 */
+	cnt = 20;
+	do {
+		/* look for a received packet */
+		found = ilo_pkt_dequeue(hw, driver_ccb, RECVQ, &pkt_id,
+					&pkt_len, &pkt);
+		if (found)
+			break;
+		cnt--;
+		msleep(100);
+	} while (!found && cnt);
+
+	if (!found)
+		return -EAGAIN;
+
+	/* only copy the length of the received packet */
+	if (pkt_len < len)
+		len = pkt_len;
+
+	err = copy_to_user(buf, pkt, len);
+
+	/* return the received packet to the queue */
+	ilo_pkt_enqueue(hw, driver_ccb, RECVQ, pkt_id, desc_mem_sz(1));
+
+	return err ? -EFAULT : len;
+}
+
+static ssize_t ilo_write(struct file *fp, const char __user *buf,
+			 size_t len, loff_t *off)
+{
+	int err, pkt_id, pkt_len;
+	struct ccb_data *data;
+	struct ccb *driver_ccb;
+	struct ilo_hwinfo *hw;
+	void *pkt;
+
+	data = fp->private_data;
+	driver_ccb = &data->driver_ccb;
+	hw = data->ilo_hw;
+
+	if (is_device_reset(hw) || is_channel_reset(driver_ccb)) {
+		/*
+		 * If the device has been reset, applications
+		 * need to close and reopen all ccbs.
+		 */
+		ilo_reset(hw);
+		return -ENODEV;
+	}
+
+	/* get a packet to send the user command */
+	if (!ilo_pkt_dequeue(hw, driver_ccb, SENDQ, &pkt_id, &pkt_len, &pkt))
+		return -EBUSY;
+
+	/* limit the length to the length of the packet */
+	if (pkt_len < len)
+		len = pkt_len;
+
+	/* on failure, set the len to 0 to return empty packet to the device */
+	err = copy_from_user(pkt, buf, len);
+	if (err)
+		len = 0;
+
+	/* send the packet */
+	ilo_pkt_enqueue(hw, driver_ccb, SENDQ, pkt_id, len);
+	doorbell_set(driver_ccb);
+
+	return err ? -EFAULT : len;
+}
+
+static int ilo_close(struct inode *ip, struct file *fp)
+{
+	int slot;
+	struct ccb_data *data;
+	struct ilo_hwinfo *hw;
+
+	slot = iminor(ip) % MAX_CCB;
+	hw = container_of(ip->i_cdev, struct ilo_hwinfo, cdev);
+
+	spin_lock(&hw->alloc_lock);
+
+	if (is_device_reset(hw))
+		ilo_locked_reset(hw);
+
+	if (hw->ccb_alloc[slot]->ccb_cnt == 1) {
+
+		data = fp->private_data;
+
+		ilo_ccb_close(hw->ilo_dev, data);
+
+		kfree(data);
+		hw->ccb_alloc[slot] = NULL;
+	} else
+		hw->ccb_alloc[slot]->ccb_cnt--;
+
+	spin_unlock(&hw->alloc_lock);
+
+	return 0;
+}
+
+static int ilo_open(struct inode *ip, struct file *fp)
+{
+	int slot, error;
+	struct ccb_data *data;
+	struct ilo_hwinfo *hw;
+
+	slot = iminor(ip) % MAX_CCB;
+	hw = container_of(ip->i_cdev, struct ilo_hwinfo, cdev);
+
+	/* new ccb allocation */
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	spin_lock(&hw->alloc_lock);
+
+	if (is_device_reset(hw))
+		ilo_locked_reset(hw);
+
+	/* each fd private_data holds sw/hw view of ccb */
+	if (hw->ccb_alloc[slot] == NULL) {
+		/* create a channel control block for this minor */
+		error = ilo_ccb_open(hw, data, slot);
+		if (!error) {
+			hw->ccb_alloc[slot] = data;
+			hw->ccb_alloc[slot]->ccb_cnt = 1;
+			hw->ccb_alloc[slot]->ccb_excl = fp->f_flags & O_EXCL;
+			hw->ccb_alloc[slot]->ilo_hw = hw;
+		} else
+			kfree(data);
+	} else {
+		kfree(data);
+		if (fp->f_flags & O_EXCL || hw->ccb_alloc[slot]->ccb_excl) {
+			/*
+			 * The channel exists, and either this open
+			 * or a previous open of this channel wants
+			 * exclusive access.
+			 */
+			error = -EBUSY;
+		} else {
+			hw->ccb_alloc[slot]->ccb_cnt++;
+			error = 0;
+		}
+	}
+	spin_unlock(&hw->alloc_lock);
+
+	if (!error)
+		fp->private_data = hw->ccb_alloc[slot];
+
+	return error;
+}
+
+static const struct file_operations ilo_fops = {
+	.owner		= THIS_MODULE,
+	.read		= ilo_read,
+	.write		= ilo_write,
+	.open 		= ilo_open,
+	.release 	= ilo_close,
+};
+
+static void ilo_unmap_device(struct pci_dev *pdev, struct ilo_hwinfo *hw)
+{
+	pci_iounmap(pdev, hw->db_vaddr);
+	pci_iounmap(pdev, hw->ram_vaddr);
+	pci_iounmap(pdev, hw->mmio_vaddr);
+}
+
+static int __devinit ilo_map_device(struct pci_dev *pdev, struct ilo_hwinfo *hw)
+{
+	int error = -ENOMEM;
+
+	/* map the memory mapped i/o registers */
+	hw->mmio_vaddr = pci_iomap(pdev, 1, 0);
+	if (hw->mmio_vaddr == NULL) {
+		dev_err(&pdev->dev, "Error mapping mmio\n");
+		goto out;
+	}
+
+	/* map the adapter shared memory region */
+	hw->ram_vaddr = pci_iomap(pdev, 2, MAX_CCB * ILOHW_CCB_SZ);
+	if (hw->ram_vaddr == NULL) {
+		dev_err(&pdev->dev, "Error mapping shared mem\n");
+		goto mmio_free;
+	}
+
+	/* map the doorbell aperture */
+	hw->db_vaddr = pci_iomap(pdev, 3, MAX_CCB * ONE_DB_SIZE);
+	if (hw->db_vaddr == NULL) {
+		dev_err(&pdev->dev, "Error mapping doorbell\n");
+		goto ram_free;
+	}
+
+	return 0;
+ram_free:
+	pci_iounmap(pdev, hw->ram_vaddr);
+mmio_free:
+	pci_iounmap(pdev, hw->mmio_vaddr);
+out:
+	return error;
+}
+
+static void ilo_remove(struct pci_dev *pdev)
+{
+	int i, minor;
+	struct ilo_hwinfo *ilo_hw = pci_get_drvdata(pdev);
+
+	clear_device(ilo_hw);
+
+	minor = MINOR(ilo_hw->cdev.dev);
+	for (i = minor; i < minor + MAX_CCB; i++)
+		device_destroy(ilo_class, MKDEV(ilo_major, i));
+
+	cdev_del(&ilo_hw->cdev);
+	ilo_unmap_device(pdev, ilo_hw);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	kfree(ilo_hw);
+	ilo_hwdev[(minor / MAX_CCB)] = 0;
+}
+
+static int __devinit ilo_probe(struct pci_dev *pdev,
+			       const struct pci_device_id *ent)
+{
+	int devnum, minor, start, error;
+	struct ilo_hwinfo *ilo_hw;
+
+	/* find a free range for device files */
+	for (devnum = 0; devnum < MAX_ILO_DEV; devnum++) {
+		if (ilo_hwdev[devnum] == 0) {
+			ilo_hwdev[devnum] = 1;
+			break;
+		}
+	}
+
+	if (devnum == MAX_ILO_DEV) {
+		dev_err(&pdev->dev, "Error finding free device\n");
+		return -ENODEV;
+	}
+
+	/* track global allocations for this device */
+	error = -ENOMEM;
+	ilo_hw = kzalloc(sizeof(*ilo_hw), GFP_KERNEL);
+	if (!ilo_hw)
+		goto out;
+
+	ilo_hw->ilo_dev = pdev;
+	spin_lock_init(&ilo_hw->alloc_lock);
+	spin_lock_init(&ilo_hw->fifo_lock);
+
+	error = pci_enable_device(pdev);
+	if (error)
+		goto free;
+
+	pci_set_master(pdev);
+
+	error = pci_request_regions(pdev, ILO_NAME);
+	if (error)
+		goto disable;
+
+	error = ilo_map_device(pdev, ilo_hw);
+	if (error)
+		goto free_regions;
+
+	pci_set_drvdata(pdev, ilo_hw);
+	clear_device(ilo_hw);
+
+	cdev_init(&ilo_hw->cdev, &ilo_fops);
+	ilo_hw->cdev.owner = THIS_MODULE;
+	start = devnum * MAX_CCB;
+	error = cdev_add(&ilo_hw->cdev, MKDEV(ilo_major, start), MAX_CCB);
+	if (error) {
+		dev_err(&pdev->dev, "Could not add cdev\n");
+		goto unmap;
+	}
+
+	for (minor = 0 ; minor < MAX_CCB; minor++) {
+		struct device *dev;
+		dev = device_create(ilo_class, &pdev->dev,
+				    MKDEV(ilo_major, minor), NULL,
+				    "hpilo!d%dccb%d", devnum, minor);
+		if (IS_ERR(dev))
+			dev_err(&pdev->dev, "Could not create files\n");
+	}
+
+	return 0;
+unmap:
+	ilo_unmap_device(pdev, ilo_hw);
+free_regions:
+	pci_release_regions(pdev);
+disable:
+	pci_disable_device(pdev);
+free:
+	kfree(ilo_hw);
+out:
+	ilo_hwdev[devnum] = 0;
+	return error;
+}
+
+static struct pci_device_id ilo_devices[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB204) },
+	{ }
+};
+MODULE_DEVICE_TABLE(pci, ilo_devices);
+
+static struct pci_driver ilo_driver = {
+	.name 	  = ILO_NAME,
+	.id_table = ilo_devices,
+	.probe 	  = ilo_probe,
+	.remove   = __devexit_p(ilo_remove),
+};
+
+static int __init ilo_init(void)
+{
+	int error;
+	dev_t dev;
+
+	ilo_class = class_create(THIS_MODULE, "iLO");
+	if (IS_ERR(ilo_class)) {
+		error = PTR_ERR(ilo_class);
+		goto out;
+	}
+
+	error = alloc_chrdev_region(&dev, 0, MAX_OPEN, ILO_NAME);
+	if (error)
+		goto class_destroy;
+
+	ilo_major = MAJOR(dev);
+
+	error =	pci_register_driver(&ilo_driver);
+	if (error)
+		goto chr_remove;
+
+	return 0;
+chr_remove:
+	unregister_chrdev_region(dev, MAX_OPEN);
+class_destroy:
+	class_destroy(ilo_class);
+out:
+	return error;
+}
+
+static void __exit ilo_exit(void)
+{
+	pci_unregister_driver(&ilo_driver);
+	unregister_chrdev_region(MKDEV(ilo_major, 0), MAX_OPEN);
+	class_destroy(ilo_class);
+}
+
+MODULE_VERSION("0.05");
+MODULE_ALIAS(ILO_NAME);
+MODULE_DESCRIPTION(ILO_NAME);
+MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>");
+MODULE_LICENSE("GPL v2");
+
+module_init(ilo_init);
+module_exit(ilo_exit);
diff --git a/drivers/misc/hpilo.h b/drivers/misc/hpilo.h
new file mode 100644
index 0000000..a281207
--- /dev/null
+++ b/drivers/misc/hpilo.h
@@ -0,0 +1,189 @@
+/*
+ * linux/drivers/char/hpilo.h
+ *
+ * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
+ *	David Altobelli <david.altobelli@hp.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.
+ */
+#ifndef __HPILO_H
+#define __HPILO_H
+
+#define ILO_NAME "hpilo"
+
+/* max number of open channel control blocks per device, hw limited to 32 */
+#define MAX_CCB		8
+/* max number of supported devices */
+#define MAX_ILO_DEV	1
+/* max number of files */
+#define MAX_OPEN	(MAX_CCB * MAX_ILO_DEV)
+
+/*
+ * Per device, used to track global memory allocations.
+ */
+struct ilo_hwinfo {
+	/* mmio registers on device */
+	char __iomem *mmio_vaddr;
+
+	/* doorbell registers on device */
+	char __iomem *db_vaddr;
+
+	/* shared memory on device used for channel control blocks */
+	char __iomem *ram_vaddr;
+
+	/* files corresponding to this device */
+	struct ccb_data *ccb_alloc[MAX_CCB];
+
+	struct pci_dev *ilo_dev;
+
+	spinlock_t alloc_lock;
+	spinlock_t fifo_lock;
+
+	struct cdev cdev;
+};
+
+/* offset from mmio_vaddr */
+#define DB_OUT		0xD4
+/* DB_OUT reset bit */
+#define DB_RESET	26
+
+/*
+ * Channel control block. Used to manage hardware queues.
+ * The format must match hw's version.  The hw ccb is 128 bytes,
+ * but the context area shouldn't be touched by the driver.
+ */
+#define ILOSW_CCB_SZ	64
+#define ILOHW_CCB_SZ 	128
+struct ccb {
+	union {
+		char *send_fifobar;
+		u64 padding1;
+	} ccb_u1;
+	union {
+		char *send_desc;
+		u64 padding2;
+	} ccb_u2;
+	u64 send_ctrl;
+
+	union {
+		char *recv_fifobar;
+		u64 padding3;
+	} ccb_u3;
+	union {
+		char *recv_desc;
+		u64 padding4;
+	} ccb_u4;
+	u64 recv_ctrl;
+
+	union {
+		char __iomem *db_base;
+		u64 padding5;
+	} ccb_u5;
+
+	u64 channel;
+
+	/* unused context area (64 bytes) */
+};
+
+/* ccb queue parameters */
+#define SENDQ		1
+#define RECVQ 		2
+#define NR_QENTRY    	4
+#define L2_QENTRY_SZ 	12
+
+/* ccb ctrl bitfields */
+#define CTRL_BITPOS_L2SZ             0
+#define CTRL_BITPOS_FIFOINDEXMASK    4
+#define CTRL_BITPOS_DESCLIMIT        18
+#define CTRL_BITPOS_A                30
+#define CTRL_BITPOS_G                31
+
+/* ccb doorbell macros */
+#define L2_DB_SIZE		14
+#define ONE_DB_SIZE		(1 << L2_DB_SIZE)
+
+/*
+ * Per fd structure used to track the ccb allocated to that dev file.
+ */
+struct ccb_data {
+	/* software version of ccb, using virtual addrs */
+	struct ccb  driver_ccb;
+
+	/* hardware version of ccb, using physical addrs */
+	struct ccb  ilo_ccb;
+
+	/* hardware ccb is written to this shared mapped device memory */
+	struct ccb __iomem *mapped_ccb;
+
+	/* dma'able memory used for send/recv queues */
+	void       *dma_va;
+	dma_addr_t  dma_pa;
+	size_t      dma_size;
+
+	/* pointer to hardware device info */
+	struct ilo_hwinfo *ilo_hw;
+
+	/* usage count, to allow for shared ccb's */
+	int	    ccb_cnt;
+
+	/* open wanted exclusive access to this ccb */
+	int	    ccb_excl;
+};
+
+/*
+ * FIFO queue structure, shared with hw.
+ */
+#define ILO_START_ALIGN	4096
+#define ILO_CACHE_SZ 	 128
+struct fifo {
+    u64 nrents;	/* user requested number of fifo entries */
+    u64 imask;  /* mask to extract valid fifo index */
+    u64 merge;	/*  O/C bits to merge in during enqueue operation */
+    u64 reset;	/* set to non-zero when the target device resets */
+    u8  pad_0[ILO_CACHE_SZ - (sizeof(u64) * 4)];
+
+    u64 head;
+    u8  pad_1[ILO_CACHE_SZ - (sizeof(u64))];
+
+    u64 tail;
+    u8  pad_2[ILO_CACHE_SZ - (sizeof(u64))];
+
+    u64 fifobar[1];
+};
+
+/* convert between struct fifo, and the fifobar, which is saved in the ccb */
+#define FIFOHANDLESIZE (sizeof(struct fifo) - sizeof(u64))
+#define FIFOBARTOHANDLE(_fifo) \
+	((struct fifo *)(((char *)(_fifo)) - FIFOHANDLESIZE))
+
+/* the number of qwords to consume from the entry descriptor */
+#define ENTRY_BITPOS_QWORDS      0
+/* descriptor index number (within a specified queue) */
+#define ENTRY_BITPOS_DESCRIPTOR  10
+/* state bit, fifo entry consumed by consumer */
+#define ENTRY_BITPOS_C           22
+/* state bit, fifo entry is occupied */
+#define ENTRY_BITPOS_O           23
+
+#define ENTRY_BITS_QWORDS        10
+#define ENTRY_BITS_DESCRIPTOR    12
+#define ENTRY_BITS_C             1
+#define ENTRY_BITS_O             1
+#define ENTRY_BITS_TOTAL	\
+	(ENTRY_BITS_C + ENTRY_BITS_O + \
+	 ENTRY_BITS_QWORDS + ENTRY_BITS_DESCRIPTOR)
+
+/* extract various entry fields */
+#define ENTRY_MASK ((1 << ENTRY_BITS_TOTAL) - 1)
+#define ENTRY_MASK_C (((1 << ENTRY_BITS_C) - 1) << ENTRY_BITPOS_C)
+#define ENTRY_MASK_O (((1 << ENTRY_BITS_O) - 1) << ENTRY_BITPOS_O)
+#define ENTRY_MASK_QWORDS \
+	(((1 << ENTRY_BITS_QWORDS) - 1) << ENTRY_BITPOS_QWORDS)
+#define ENTRY_MASK_DESCRIPTOR \
+	(((1 << ENTRY_BITS_DESCRIPTOR) - 1) << ENTRY_BITPOS_DESCRIPTOR)
+
+#define ENTRY_MASK_NOSTATE (ENTRY_MASK >> (ENTRY_BITS_C + ENTRY_BITS_O))
+
+#endif /* __HPILO_H */
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
index 1861624..4ce3bdc 100644
--- a/drivers/misc/phantom.c
+++ b/drivers/misc/phantom.c
@@ -399,8 +399,9 @@
 		goto err_irq;
 	}
 
-	if (IS_ERR(device_create(phantom_class, &pdev->dev, MKDEV(phantom_major,
-			minor), "phantom%u", minor)))
+	if (IS_ERR(device_create_drvdata(phantom_class, &pdev->dev,
+					 MKDEV(phantom_major, minor),
+					 NULL, "phantom%u", minor)))
 		dev_err(&pdev->dev, "can't create device\n");
 
 	pci_set_drvdata(pdev, pht);
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index d6b9b48..a067fe4 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -21,13 +21,17 @@
 #define RESULT_UNSUP_HOST	2
 #define RESULT_UNSUP_CARD	3
 
-#define BUFFER_SIZE	(PAGE_SIZE * 4)
+#define BUFFER_ORDER		2
+#define BUFFER_SIZE		(PAGE_SIZE << BUFFER_ORDER)
 
 struct mmc_test_card {
 	struct mmc_card	*card;
 
 	u8		scratch[BUFFER_SIZE];
 	u8		*buffer;
+#ifdef CONFIG_HIGHMEM
+	struct page	*highmem;
+#endif
 };
 
 /*******************************************************************/
@@ -384,14 +388,16 @@
 	int ret, i;
 	unsigned long flags;
 
+	BUG_ON(blocks * blksz > BUFFER_SIZE);
+
 	if (write) {
 		for (i = 0;i < blocks * blksz;i++)
 			test->scratch[i] = i;
 	} else {
-		memset(test->scratch, 0, BUFFER_SIZE);
+		memset(test->scratch, 0, blocks * blksz);
 	}
 	local_irq_save(flags);
-	sg_copy_from_buffer(sg, sg_len, test->scratch, BUFFER_SIZE);
+	sg_copy_from_buffer(sg, sg_len, test->scratch, blocks * blksz);
 	local_irq_restore(flags);
 
 	ret = mmc_test_set_blksize(test, blksz);
@@ -438,7 +444,7 @@
 		}
 	} else {
 		local_irq_save(flags);
-		sg_copy_to_buffer(sg, sg_len, test->scratch, BUFFER_SIZE);
+		sg_copy_to_buffer(sg, sg_len, test->scratch, blocks * blksz);
 		local_irq_restore(flags);
 		for (i = 0;i < blocks * blksz;i++) {
 			if (test->scratch[i] != (u8)i)
@@ -799,6 +805,157 @@
 	return 0;
 }
 
+static int mmc_test_bigsg_write(struct mmc_test_card *test)
+{
+	int ret;
+	unsigned int size;
+	struct scatterlist sg;
+
+	if (test->card->host->max_blk_count == 1)
+		return RESULT_UNSUP_HOST;
+
+	size = PAGE_SIZE * 2;
+	size = min(size, test->card->host->max_req_size);
+	size = min(size, test->card->host->max_seg_size);
+	size = min(size, test->card->host->max_blk_count * 512);
+
+	memset(test->buffer, 0, BUFFER_SIZE);
+
+	if (size < 1024)
+		return RESULT_UNSUP_HOST;
+
+	sg_init_table(&sg, 1);
+	sg_init_one(&sg, test->buffer, BUFFER_SIZE);
+
+	ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int mmc_test_bigsg_read(struct mmc_test_card *test)
+{
+	int ret, i;
+	unsigned int size;
+	struct scatterlist sg;
+
+	if (test->card->host->max_blk_count == 1)
+		return RESULT_UNSUP_HOST;
+
+	size = PAGE_SIZE * 2;
+	size = min(size, test->card->host->max_req_size);
+	size = min(size, test->card->host->max_seg_size);
+	size = min(size, test->card->host->max_blk_count * 512);
+
+	if (size < 1024)
+		return RESULT_UNSUP_HOST;
+
+	memset(test->buffer, 0xCD, BUFFER_SIZE);
+
+	sg_init_table(&sg, 1);
+	sg_init_one(&sg, test->buffer, BUFFER_SIZE);
+	ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
+	if (ret)
+		return ret;
+
+	/* mmc_test_transfer() doesn't check for read overflows */
+	for (i = size;i < BUFFER_SIZE;i++) {
+		if (test->buffer[i] != 0xCD)
+			return RESULT_FAIL;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_HIGHMEM
+
+static int mmc_test_write_high(struct mmc_test_card *test)
+{
+	int ret;
+	struct scatterlist sg;
+
+	sg_init_table(&sg, 1);
+	sg_set_page(&sg, test->highmem, 512, 0);
+
+	ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int mmc_test_read_high(struct mmc_test_card *test)
+{
+	int ret;
+	struct scatterlist sg;
+
+	sg_init_table(&sg, 1);
+	sg_set_page(&sg, test->highmem, 512, 0);
+
+	ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int mmc_test_multi_write_high(struct mmc_test_card *test)
+{
+	int ret;
+	unsigned int size;
+	struct scatterlist sg;
+
+	if (test->card->host->max_blk_count == 1)
+		return RESULT_UNSUP_HOST;
+
+	size = PAGE_SIZE * 2;
+	size = min(size, test->card->host->max_req_size);
+	size = min(size, test->card->host->max_seg_size);
+	size = min(size, test->card->host->max_blk_count * 512);
+
+	if (size < 1024)
+		return RESULT_UNSUP_HOST;
+
+	sg_init_table(&sg, 1);
+	sg_set_page(&sg, test->highmem, size, 0);
+
+	ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int mmc_test_multi_read_high(struct mmc_test_card *test)
+{
+	int ret;
+	unsigned int size;
+	struct scatterlist sg;
+
+	if (test->card->host->max_blk_count == 1)
+		return RESULT_UNSUP_HOST;
+
+	size = PAGE_SIZE * 2;
+	size = min(size, test->card->host->max_req_size);
+	size = min(size, test->card->host->max_seg_size);
+	size = min(size, test->card->host->max_blk_count * 512);
+
+	if (size < 1024)
+		return RESULT_UNSUP_HOST;
+
+	sg_init_table(&sg, 1);
+	sg_set_page(&sg, test->highmem, size, 0);
+
+	ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+#endif /* CONFIG_HIGHMEM */
+
 static const struct mmc_test_case mmc_test_cases[] = {
 	{
 		.name = "Basic write (no data verification)",
@@ -913,6 +1070,53 @@
 		.name = "Correct xfer_size at read (midway failure)",
 		.run = mmc_test_multi_xfersize_read,
 	},
+
+	{
+		.name = "Over-sized SG list write",
+		.prepare = mmc_test_prepare_write,
+		.run = mmc_test_bigsg_write,
+		.cleanup = mmc_test_cleanup,
+	},
+
+	{
+		.name = "Over-sized SG list read",
+		.prepare = mmc_test_prepare_read,
+		.run = mmc_test_bigsg_read,
+		.cleanup = mmc_test_cleanup,
+	},
+
+#ifdef CONFIG_HIGHMEM
+
+	{
+		.name = "Highmem write",
+		.prepare = mmc_test_prepare_write,
+		.run = mmc_test_write_high,
+		.cleanup = mmc_test_cleanup,
+	},
+
+	{
+		.name = "Highmem read",
+		.prepare = mmc_test_prepare_read,
+		.run = mmc_test_read_high,
+		.cleanup = mmc_test_cleanup,
+	},
+
+	{
+		.name = "Multi-block highmem write",
+		.prepare = mmc_test_prepare_write,
+		.run = mmc_test_multi_write_high,
+		.cleanup = mmc_test_cleanup,
+	},
+
+	{
+		.name = "Multi-block highmem read",
+		.prepare = mmc_test_prepare_read,
+		.run = mmc_test_multi_read_high,
+		.cleanup = mmc_test_cleanup,
+	},
+
+#endif /* CONFIG_HIGHMEM */
+
 };
 
 static struct mutex mmc_test_lock;
@@ -1014,12 +1218,23 @@
 	test->card = card;
 
 	test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL);
+#ifdef CONFIG_HIGHMEM
+	test->highmem = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, BUFFER_ORDER);
+#endif
+
+#ifdef CONFIG_HIGHMEM
+	if (test->buffer && test->highmem) {
+#else
 	if (test->buffer) {
+#endif
 		mutex_lock(&mmc_test_lock);
 		mmc_test_run(test, testcase);
 		mutex_unlock(&mmc_test_lock);
 	}
 
+#ifdef CONFIG_HIGHMEM
+	__free_pages(test->highmem, BUFFER_ORDER);
+#endif
 	kfree(test->buffer);
 	kfree(test);
 
@@ -1041,6 +1256,8 @@
 	if (ret)
 		return ret;
 
+	dev_info(&card->dev, "Card claimed for testing.\n");
+
 	return 0;
 }
 
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 7731dde..3dee97e 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -148,7 +148,7 @@
 			printk(KERN_WARNING "%s: unable to allocate "
 				"bounce buffer\n", mmc_card_name(card));
 		} else {
-			blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_HIGH);
+			blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY);
 			blk_queue_max_sectors(mq->queue, bouncesz / 512);
 			blk_queue_max_phys_segments(mq->queue, bouncesz / 512);
 			blk_queue_max_hw_segments(mq->queue, bouncesz / 512);
@@ -290,55 +290,15 @@
 	}
 }
 
-static void copy_sg(struct scatterlist *dst, unsigned int dst_len,
-	struct scatterlist *src, unsigned int src_len)
-{
-	unsigned int chunk;
-	char *dst_buf, *src_buf;
-	unsigned int dst_size, src_size;
-
-	dst_buf = NULL;
-	src_buf = NULL;
-	dst_size = 0;
-	src_size = 0;
-
-	while (src_len) {
-		BUG_ON(dst_len == 0);
-
-		if (dst_size == 0) {
-			dst_buf = sg_virt(dst);
-			dst_size = dst->length;
-		}
-
-		if (src_size == 0) {
-			src_buf = sg_virt(src);
-			src_size = src->length;
-		}
-
-		chunk = min(dst_size, src_size);
-
-		memcpy(dst_buf, src_buf, chunk);
-
-		dst_buf += chunk;
-		src_buf += chunk;
-		dst_size -= chunk;
-		src_size -= chunk;
-
-		if (dst_size == 0) {
-			dst++;
-			dst_len--;
-		}
-
-		if (src_size == 0) {
-			src++;
-			src_len--;
-		}
-	}
-}
-
+/*
+ * Prepare the sg list(s) to be handed of to the host driver
+ */
 unsigned int mmc_queue_map_sg(struct mmc_queue *mq)
 {
 	unsigned int sg_len;
+	size_t buflen;
+	struct scatterlist *sg;
+	int i;
 
 	if (!mq->bounce_buf)
 		return blk_rq_map_sg(mq->queue, mq->req, mq->sg);
@@ -349,47 +309,52 @@
 
 	mq->bounce_sg_len = sg_len;
 
-	/*
-	 * Shortcut in the event we only get a single entry.
-	 */
-	if (sg_len == 1) {
-		memcpy(mq->sg, mq->bounce_sg, sizeof(struct scatterlist));
-		return 1;
-	}
+	buflen = 0;
+	for_each_sg(mq->bounce_sg, sg, sg_len, i)
+		buflen += sg->length;
 
-	sg_init_one(mq->sg, mq->bounce_buf, 0);
-
-	while (sg_len) {
-		mq->sg[0].length += mq->bounce_sg[sg_len - 1].length;
-		sg_len--;
-	}
+	sg_init_one(mq->sg, mq->bounce_buf, buflen);
 
 	return 1;
 }
 
+/*
+ * If writing, bounce the data to the buffer before the request
+ * is sent to the host driver
+ */
 void mmc_queue_bounce_pre(struct mmc_queue *mq)
 {
+	unsigned long flags;
+
 	if (!mq->bounce_buf)
 		return;
 
-	if (mq->bounce_sg_len == 1)
-		return;
 	if (rq_data_dir(mq->req) != WRITE)
 		return;
 
-	copy_sg(mq->sg, 1, mq->bounce_sg, mq->bounce_sg_len);
+	local_irq_save(flags);
+	sg_copy_to_buffer(mq->bounce_sg, mq->bounce_sg_len,
+		mq->bounce_buf, mq->sg[0].length);
+	local_irq_restore(flags);
 }
 
+/*
+ * If reading, bounce the data from the buffer after the request
+ * has been handled by the host driver
+ */
 void mmc_queue_bounce_post(struct mmc_queue *mq)
 {
+	unsigned long flags;
+
 	if (!mq->bounce_buf)
 		return;
 
-	if (mq->bounce_sg_len == 1)
-		return;
 	if (rq_data_dir(mq->req) != READ)
 		return;
 
-	copy_sg(mq->bounce_sg, mq->bounce_sg_len, mq->sg, 1);
+	local_irq_save(flags);
+	sg_copy_from_buffer(mq->bounce_sg, mq->bounce_sg_len,
+		mq->bounce_buf, mq->sg[0].length);
+	local_irq_restore(flags);
 }
 
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index 3f15eb2..99b2091 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -1043,7 +1043,7 @@
 		goto out6;
 	}
 
-	platform_set_drvdata(pdev, mmc);
+	platform_set_drvdata(pdev, host);
 
 	printk(KERN_INFO DRIVER_NAME ": MMC Controller %d set up at %8.8X"
 		" (mode=%s)\n", pdev->id, host->iobase,
@@ -1087,13 +1087,10 @@
 
 static int __devexit au1xmmc_remove(struct platform_device *pdev)
 {
-	struct mmc_host *mmc = platform_get_drvdata(pdev);
-	struct au1xmmc_host *host;
+	struct au1xmmc_host *host = platform_get_drvdata(pdev);
 
-	if (mmc) {
-		host  = mmc_priv(mmc);
-
-		mmc_remove_host(mmc);
+	if (host) {
+		mmc_remove_host(host->mmc);
 
 #ifdef CONFIG_LEDS_CLASS
 		if (host->platdata && host->platdata->led)
@@ -1101,8 +1098,8 @@
 #endif
 
 		if (host->platdata && host->platdata->cd_setup &&
-		    !(mmc->caps & MMC_CAP_NEEDS_POLL))
-			host->platdata->cd_setup(mmc, 0);
+		    !(host->mmc->caps & MMC_CAP_NEEDS_POLL))
+			host->platdata->cd_setup(host->mmc, 0);
 
 		au_writel(0, HOST_ENABLE(host));
 		au_writel(0, HOST_CONFIG(host));
@@ -1122,16 +1119,49 @@
 		release_resource(host->ioarea);
 		kfree(host->ioarea);
 
-		mmc_free_host(mmc);
+		mmc_free_host(host->mmc);
+		platform_set_drvdata(pdev, NULL);
 	}
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static int au1xmmc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct au1xmmc_host *host = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = mmc_suspend_host(host->mmc, state);
+	if (ret)
+		return ret;
+
+	au_writel(0, HOST_CONFIG2(host));
+	au_writel(0, HOST_CONFIG(host));
+	au_writel(0xffffffff, HOST_STATUS(host));
+	au_writel(0, HOST_ENABLE(host));
+	au_sync();
+
+	return 0;
+}
+
+static int au1xmmc_resume(struct platform_device *pdev)
+{
+	struct au1xmmc_host *host = platform_get_drvdata(pdev);
+
+	au1xmmc_reset_controller(host);
+
+	return mmc_resume_host(host->mmc);
+}
+#else
+#define au1xmmc_suspend NULL
+#define au1xmmc_resume NULL
+#endif
+
 static struct platform_driver au1xmmc_driver = {
 	.probe         = au1xmmc_probe,
 	.remove        = au1xmmc_remove,
-	.suspend       = NULL,
-	.resume        = NULL,
+	.suspend       = au1xmmc_suspend,
+	.resume        = au1xmmc_resume,
 	.driver        = {
 		.name  = DRIVER_NAME,
 		.owner = THIS_MODULE,
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index d39f597..a8e18fe 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -177,7 +177,7 @@
 	if (dalgn)
 		DALGN |= (1 << host->dma);
 	else
-		DALGN &= (1 << host->dma);
+		DALGN &= ~(1 << host->dma);
 	DDADR(host->dma) = host->sg_dma;
 	DCSR(host->dma) = DCSR_RUN;
 }
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index 6a1e4994..be550c2 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -1331,21 +1331,30 @@
 	return ret;
 }
 
+static void s3cmci_shutdown(struct platform_device *pdev)
+{
+	struct mmc_host	*mmc = platform_get_drvdata(pdev);
+	struct s3cmci_host *host = mmc_priv(mmc);
+
+	if (host->irq_cd >= 0)
+		free_irq(host->irq_cd, host);
+
+	mmc_remove_host(mmc);
+	clk_disable(host->clk);
+}
+
 static int __devexit s3cmci_remove(struct platform_device *pdev)
 {
 	struct mmc_host		*mmc  = platform_get_drvdata(pdev);
 	struct s3cmci_host	*host = mmc_priv(mmc);
 
-	mmc_remove_host(mmc);
+	s3cmci_shutdown(pdev);
 
-	clk_disable(host->clk);
 	clk_put(host->clk);
 
 	tasklet_disable(&host->pio_tasklet);
 	s3c2410_dma_free(S3CMCI_DMA, &s3cmci_dma_client);
 
-	if (host->irq_cd >= 0)
-		free_irq(host->irq_cd, host);
 	free_irq(host->irq, host);
 
 	iounmap(host->base);
@@ -1355,17 +1364,17 @@
 	return 0;
 }
 
-static int __devinit s3cmci_probe_2410(struct platform_device *dev)
+static int __devinit s3cmci_2410_probe(struct platform_device *dev)
 {
 	return s3cmci_probe(dev, 0);
 }
 
-static int __devinit s3cmci_probe_2412(struct platform_device *dev)
+static int __devinit s3cmci_2412_probe(struct platform_device *dev)
 {
 	return s3cmci_probe(dev, 1);
 }
 
-static int __devinit s3cmci_probe_2440(struct platform_device *dev)
+static int __devinit s3cmci_2440_probe(struct platform_device *dev)
 {
 	return s3cmci_probe(dev, 1);
 }
@@ -1392,29 +1401,32 @@
 #endif /* CONFIG_PM */
 
 
-static struct platform_driver s3cmci_driver_2410 = {
+static struct platform_driver s3cmci_2410_driver = {
 	.driver.name	= "s3c2410-sdi",
 	.driver.owner	= THIS_MODULE,
-	.probe		= s3cmci_probe_2410,
+	.probe		= s3cmci_2410_probe,
 	.remove		= __devexit_p(s3cmci_remove),
+	.shutdown	= s3cmci_shutdown,
 	.suspend	= s3cmci_suspend,
 	.resume		= s3cmci_resume,
 };
 
-static struct platform_driver s3cmci_driver_2412 = {
+static struct platform_driver s3cmci_2412_driver = {
 	.driver.name	= "s3c2412-sdi",
 	.driver.owner	= THIS_MODULE,
-	.probe		= s3cmci_probe_2412,
+	.probe		= s3cmci_2412_probe,
 	.remove		= __devexit_p(s3cmci_remove),
+	.shutdown	= s3cmci_shutdown,
 	.suspend	= s3cmci_suspend,
 	.resume		= s3cmci_resume,
 };
 
-static struct platform_driver s3cmci_driver_2440 = {
+static struct platform_driver s3cmci_2440_driver = {
 	.driver.name	= "s3c2440-sdi",
 	.driver.owner	= THIS_MODULE,
-	.probe		= s3cmci_probe_2440,
+	.probe		= s3cmci_2440_probe,
 	.remove		= __devexit_p(s3cmci_remove),
+	.shutdown	= s3cmci_shutdown,
 	.suspend	= s3cmci_suspend,
 	.resume		= s3cmci_resume,
 };
@@ -1422,17 +1434,17 @@
 
 static int __init s3cmci_init(void)
 {
-	platform_driver_register(&s3cmci_driver_2410);
-	platform_driver_register(&s3cmci_driver_2412);
-	platform_driver_register(&s3cmci_driver_2440);
+	platform_driver_register(&s3cmci_2410_driver);
+	platform_driver_register(&s3cmci_2412_driver);
+	platform_driver_register(&s3cmci_2440_driver);
 	return 0;
 }
 
 static void __exit s3cmci_exit(void)
 {
-	platform_driver_unregister(&s3cmci_driver_2410);
-	platform_driver_unregister(&s3cmci_driver_2412);
-	platform_driver_unregister(&s3cmci_driver_2440);
+	platform_driver_unregister(&s3cmci_2410_driver);
+	platform_driver_unregister(&s3cmci_2412_driver);
+	platform_driver_unregister(&s3cmci_2440_driver);
 }
 
 module_init(s3cmci_init);
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 17701c3..c3a5db7 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -173,119 +173,95 @@
  *                                                                           *
 \*****************************************************************************/
 
-static inline char* sdhci_sg_to_buffer(struct sdhci_host* host)
-{
-	return sg_virt(host->cur_sg);
-}
-
-static inline int sdhci_next_sg(struct sdhci_host* host)
-{
-	/*
-	 * Skip to next SG entry.
-	 */
-	host->cur_sg++;
-	host->num_sg--;
-
-	/*
-	 * Any entries left?
-	 */
-	if (host->num_sg > 0) {
-		host->offset = 0;
-		host->remain = host->cur_sg->length;
-	}
-
-	return host->num_sg;
-}
-
 static void sdhci_read_block_pio(struct sdhci_host *host)
 {
-	int blksize, chunk_remain;
-	u32 data;
-	char *buffer;
-	int size;
+	unsigned long flags;
+	size_t blksize, len, chunk;
+	u32 scratch;
+	u8 *buf;
 
 	DBG("PIO reading\n");
 
 	blksize = host->data->blksz;
-	chunk_remain = 0;
-	data = 0;
+	chunk = 0;
 
-	buffer = sdhci_sg_to_buffer(host) + host->offset;
+	local_irq_save(flags);
 
 	while (blksize) {
-		if (chunk_remain == 0) {
-			data = readl(host->ioaddr + SDHCI_BUFFER);
-			chunk_remain = min(blksize, 4);
-		}
+		if (!sg_miter_next(&host->sg_miter))
+			BUG();
 
-		size = min(host->remain, chunk_remain);
+		len = min(host->sg_miter.length, blksize);
 
-		chunk_remain -= size;
-		blksize -= size;
-		host->offset += size;
-		host->remain -= size;
+		blksize -= len;
+		host->sg_miter.consumed = len;
 
-		while (size) {
-			*buffer = data & 0xFF;
-			buffer++;
-			data >>= 8;
-			size--;
-		}
+		buf = host->sg_miter.addr;
 
-		if (host->remain == 0) {
-			if (sdhci_next_sg(host) == 0) {
-				BUG_ON(blksize != 0);
-				return;
+		while (len) {
+			if (chunk == 0) {
+				scratch = readl(host->ioaddr + SDHCI_BUFFER);
+				chunk = 4;
 			}
-			buffer = sdhci_sg_to_buffer(host);
+
+			*buf = scratch & 0xFF;
+
+			buf++;
+			scratch >>= 8;
+			chunk--;
+			len--;
 		}
 	}
+
+	sg_miter_stop(&host->sg_miter);
+
+	local_irq_restore(flags);
 }
 
 static void sdhci_write_block_pio(struct sdhci_host *host)
 {
-	int blksize, chunk_remain;
-	u32 data;
-	char *buffer;
-	int bytes, size;
+	unsigned long flags;
+	size_t blksize, len, chunk;
+	u32 scratch;
+	u8 *buf;
 
 	DBG("PIO writing\n");
 
 	blksize = host->data->blksz;
-	chunk_remain = 4;
-	data = 0;
+	chunk = 0;
+	scratch = 0;
 
-	bytes = 0;
-	buffer = sdhci_sg_to_buffer(host) + host->offset;
+	local_irq_save(flags);
 
 	while (blksize) {
-		size = min(host->remain, chunk_remain);
+		if (!sg_miter_next(&host->sg_miter))
+			BUG();
 
-		chunk_remain -= size;
-		blksize -= size;
-		host->offset += size;
-		host->remain -= size;
+		len = min(host->sg_miter.length, blksize);
 
-		while (size) {
-			data >>= 8;
-			data |= (u32)*buffer << 24;
-			buffer++;
-			size--;
-		}
+		blksize -= len;
+		host->sg_miter.consumed = len;
 
-		if (chunk_remain == 0) {
-			writel(data, host->ioaddr + SDHCI_BUFFER);
-			chunk_remain = min(blksize, 4);
-		}
+		buf = host->sg_miter.addr;
 
-		if (host->remain == 0) {
-			if (sdhci_next_sg(host) == 0) {
-				BUG_ON(blksize != 0);
-				return;
+		while (len) {
+			scratch |= (u32)*buf << (chunk * 8);
+
+			buf++;
+			chunk++;
+			len--;
+
+			if ((chunk == 4) || ((len == 0) && (blksize == 0))) {
+				writel(scratch, host->ioaddr + SDHCI_BUFFER);
+				chunk = 0;
+				scratch = 0;
 			}
-			buffer = sdhci_sg_to_buffer(host);
 		}
 	}
+
+	sg_miter_stop(&host->sg_miter);
+
+	local_irq_restore(flags);
 }
 
 static void sdhci_transfer_pio(struct sdhci_host *host)
@@ -294,7 +270,7 @@
 
 	BUG_ON(!host->data);
 
-	if (host->num_sg == 0)
+	if (host->blocks == 0)
 		return;
 
 	if (host->data->flags & MMC_DATA_READ)
@@ -308,7 +284,8 @@
 		else
 			sdhci_write_block_pio(host);
 
-		if (host->num_sg == 0)
+		host->blocks--;
+		if (host->blocks == 0)
 			break;
 	}
 
@@ -389,6 +366,7 @@
 		if (offset) {
 			if (data->flags & MMC_DATA_WRITE) {
 				buffer = sdhci_kmap_atomic(sg, &flags);
+				WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3));
 				memcpy(align, buffer, offset);
 				sdhci_kunmap_atomic(buffer, &flags);
 			}
@@ -510,6 +488,7 @@
 				size = 4 - (sg_dma_address(sg) & 0x3);
 
 				buffer = sdhci_kmap_atomic(sg, &flags);
+				WARN_ON(((long)buffer & PAGE_MASK) > (PAGE_SIZE - 3));
 				memcpy(buffer, align, size);
 				sdhci_kunmap_atomic(buffer, &flags);
 
@@ -687,7 +666,7 @@
 				WARN_ON(1);
 				host->flags &= ~SDHCI_USE_DMA;
 			} else {
-				WARN_ON(count != 1);
+				WARN_ON(sg_cnt != 1);
 				writel(sg_dma_address(data->sg),
 					host->ioaddr + SDHCI_DMA_ADDRESS);
 			}
@@ -711,11 +690,9 @@
 	}
 
 	if (!(host->flags & SDHCI_REQ_USE_DMA)) {
-		host->cur_sg = data->sg;
-		host->num_sg = data->sg_len;
-
-		host->offset = 0;
-		host->remain = host->cur_sg->length;
+		sg_miter_start(&host->sg_miter,
+			data->sg, data->sg_len, SG_MITER_ATOMIC);
+		host->blocks = data->blocks;
 	}
 
 	/* We do not handle DMA boundaries, so set it to max (512 KiB) */
@@ -1581,9 +1558,15 @@
 		}
 	}
 
-	/* XXX: Hack to get MMC layer to avoid highmem */
-	if (!(host->flags & SDHCI_USE_DMA))
-		mmc_dev(host->mmc)->dma_mask = NULL;
+	/*
+	 * If we use DMA, then it's up to the caller to set the DMA
+	 * mask, but PIO does not need the hw shim so we set a new
+	 * mask here in that case.
+	 */
+	if (!(host->flags & SDHCI_USE_DMA)) {
+		host->dma_mask = DMA_BIT_MASK(64);
+		mmc_dev(host->mmc)->dma_mask = &host->dma_mask;
+	}
 
 	host->max_clk =
 		(caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 5bb3552..a06bf8b 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -212,6 +212,7 @@
 
 	/* Internal data */
 	struct mmc_host		*mmc;		/* MMC structure */
+	u64			dma_mask;	/* custom DMA mask */
 
 #ifdef CONFIG_LEDS_CLASS
 	struct led_classdev	led;		/* LED control */
@@ -238,10 +239,8 @@
 	struct mmc_data		*data;		/* Current data request */
 	unsigned int		data_early:1;	/* Data finished before cmd */
 
-	struct scatterlist	*cur_sg;	/* We're working on this */
-	int			num_sg;		/* Entries left */
-	int			offset;		/* Offset into current sg */
-	int			remain;		/* Bytes left in current */
+	struct sg_mapping_iter	sg_miter;	/* SG state for PIO */
+	unsigned int		blocks;		/* remaining PIO blocks */
 
 	int			sg_count;	/* Mapped sg entries */
 
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index 519d942..7b72a1b 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -241,6 +241,7 @@
 {
 	struct block_device *bdev;
 	struct block2mtd_dev *dev;
+	char *name;
 
 	if (!devname)
 		return NULL;
@@ -279,12 +280,13 @@
 
 	/* Setup the MTD structure */
 	/* make the name contain the block device in */
-	dev->mtd.name = kmalloc(sizeof("block2mtd: ") + strlen(devname),
+	name = kmalloc(sizeof("block2mtd: ") + strlen(devname) + 1,
 			GFP_KERNEL);
-	if (!dev->mtd.name)
+	if (!name)
 		goto devinit_err;
 
-	sprintf(dev->mtd.name, "block2mtd: %s", devname);
+	sprintf(name, "block2mtd: %s", devname);
+	dev->mtd.name = name;
 
 	dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
 	dev->mtd.erasesize = erase_size;
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 129d429..aef9f4b 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -28,10 +28,13 @@
 	if (!mtd)
 		return;
 
-	device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2), "mtd%d", mtd->index);
+	device_create_drvdata(mtd_class, NULL,
+			      MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
+			      NULL, "mtd%d", mtd->index);
 
-	device_create(mtd_class, NULL,
-		      MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1), "mtd%dro", mtd->index);
+	device_create_drvdata(mtd_class, NULL,
+			      MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
+			      NULL, "mtd%dro", mtd->index);
 }
 
 static void mtd_notify_remove(struct mtd_info* mtd)
diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/cmx270_nand.c
index cb663ef..fc8529b 100644
--- a/drivers/mtd/nand/cmx270_nand.c
+++ b/drivers/mtd/nand/cmx270_nand.c
@@ -20,9 +20,11 @@
 
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
+#include <linux/gpio.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/mach-types.h>
 
 #include <asm/arch/hardware.h>
 #include <asm/arch/pxa-regs.h>
@@ -30,20 +32,6 @@
 #define GPIO_NAND_CS	(11)
 #define GPIO_NAND_RB	(89)
 
-/* This macro needed to ensure in-order operation of GPIO and local
- * bus. Without both asm command and dummy uncached read there're
- * states when NAND access is broken. I've looked for such macro(s) in
- * include/asm-arm but found nothing approptiate.
- * dmac_clean_range is close, but is makes cache invalidation
- * unnecessary here and it cannot be used in module
- */
-#define DRAIN_WB() \
-	do { \
-		unsigned char dummy; \
-		asm volatile ("mcr p15, 0, r0, c7, c10, 4":::"r0"); \
-		dummy=*((unsigned char*)UNCACHED_ADDR); \
-	} while(0)
-
 /* MTD structure for CM-X270 board */
 static struct mtd_info *cmx270_nand_mtd;
 
@@ -103,14 +91,14 @@
 
 static inline void nand_cs_on(void)
 {
-	GPCR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS);
+	gpio_set_value(GPIO_NAND_CS, 0);
 }
 
 static void nand_cs_off(void)
 {
-	DRAIN_WB();
+	dsb();
 
-	GPSR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS);
+	gpio_set_value(GPIO_NAND_CS, 1);
 }
 
 /*
@@ -122,7 +110,7 @@
 	struct nand_chip* this = mtd->priv;
 	unsigned int nandaddr = (unsigned int)this->IO_ADDR_W;
 
-	DRAIN_WB();
+	dsb();
 
 	if (ctrl & NAND_CTRL_CHANGE) {
 		if ( ctrl & NAND_ALE )
@@ -139,12 +127,12 @@
 			nand_cs_off();
 	}
 
-	DRAIN_WB();
+	dsb();
 	this->IO_ADDR_W = (void __iomem*)nandaddr;
 	if (dat != NAND_CMD_NONE)
 		writel((dat << 16), this->IO_ADDR_W);
 
-	DRAIN_WB();
+	dsb();
 }
 
 /*
@@ -152,9 +140,9 @@
  */
 static int cmx270_device_ready(struct mtd_info *mtd)
 {
-	DRAIN_WB();
+	dsb();
 
-	return (GPLR(GPIO_NAND_RB) & GPIO_bit(GPIO_NAND_RB));
+	return (gpio_get_value(GPIO_NAND_RB));
 }
 
 /*
@@ -168,20 +156,40 @@
 	int mtd_parts_nb = 0;
 	int ret;
 
+	if (!machine_is_armcore())
+		return -ENODEV;
+
+	ret = gpio_request(GPIO_NAND_CS, "NAND CS");
+	if (ret) {
+		pr_warning("CM-X270: failed to request NAND CS gpio\n");
+		return ret;
+	}
+
+	gpio_direction_output(GPIO_NAND_CS, 1);
+
+	ret = gpio_request(GPIO_NAND_RB, "NAND R/B");
+	if (ret) {
+		pr_warning("CM-X270: failed to request NAND R/B gpio\n");
+		goto err_gpio_request;
+	}
+
+	gpio_direction_input(GPIO_NAND_RB);
+
 	/* Allocate memory for MTD device structure and private data */
 	cmx270_nand_mtd = kzalloc(sizeof(struct mtd_info) +
 				  sizeof(struct nand_chip),
 				  GFP_KERNEL);
 	if (!cmx270_nand_mtd) {
-		printk("Unable to allocate CM-X270 NAND MTD device structure.\n");
-		return -ENOMEM;
+		pr_debug("Unable to allocate CM-X270 NAND MTD device structure.\n");
+		ret = -ENOMEM;
+		goto err_kzalloc;
 	}
 
 	cmx270_nand_io = ioremap(PXA_CS1_PHYS, 12);
 	if (!cmx270_nand_io) {
-		printk("Unable to ioremap NAND device\n");
+		pr_debug("Unable to ioremap NAND device\n");
 		ret = -EINVAL;
-		goto err1;
+		goto err_ioremap;
 	}
 
 	/* Get pointer to private data */
@@ -209,9 +217,9 @@
 
 	/* Scan to find existence of the device */
 	if (nand_scan (cmx270_nand_mtd, 1)) {
-		printk(KERN_NOTICE "No NAND device\n");
+		pr_notice("No NAND device\n");
 		ret = -ENXIO;
-		goto err2;
+		goto err_scan;
 	}
 
 #ifdef CONFIG_MTD_CMDLINE_PARTS
@@ -229,18 +237,22 @@
 	}
 
 	/* Register the partitions */
-	printk(KERN_NOTICE "Using %s partition definition\n", part_type);
+	pr_notice("Using %s partition definition\n", part_type);
 	ret = add_mtd_partitions(cmx270_nand_mtd, mtd_parts, mtd_parts_nb);
 	if (ret)
-		goto err2;
+		goto err_scan;
 
 	/* Return happy */
 	return 0;
 
-err2:
+err_scan:
 	iounmap(cmx270_nand_io);
-err1:
+err_ioremap:
 	kfree(cmx270_nand_mtd);
+err_kzalloc:
+	gpio_free(GPIO_NAND_RB);
+err_gpio_request:
+	gpio_free(GPIO_NAND_CS);
 
 	return ret;
 
@@ -255,6 +267,9 @@
 	/* Release resources, unregister device */
 	nand_release(cmx270_nand_mtd);
 
+	gpio_free(GPIO_NAND_RB);
+	gpio_free(GPIO_NAND_CS);
+
 	iounmap(cmx270_nand_io);
 
 	/* Free the MTD device structure */
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index aabad8c..8db4e6b 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -1010,7 +1010,7 @@
 	static int printed_version;
 	int retval, print_info;
 	struct vortex_chip_info * const vci = &vortex_info_tbl[chip_idx];
-	char *print_name = "3c59x";
+	const char *print_name = "3c59x";
 	struct pci_dev *pdev = NULL;
 	struct eisa_device *edev = NULL;
 	DECLARE_MAC_BUF(mac);
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 75317a1..8a5b0d2 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -98,7 +98,6 @@
 #include <linux/compiler.h>
 #include <linux/pci.h>
 #include <linux/init.h>
-#include <linux/ioport.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/rtnetlink.h>
@@ -120,11 +119,6 @@
                                  NETIF_MSG_LINK)
 
 
-/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */
-#ifdef CONFIG_8139TOO_PIO
-#define USE_IO_OPS 1
-#endif
-
 /* define to 1, 2 or 3 to enable copious debugging info */
 #define RTL8139_DEBUG 0
 
@@ -156,6 +150,13 @@
 static int media[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 
+/* Whether to use MMIO or PIO. Default to MMIO. */
+#ifdef CONFIG_8139TOO_PIO
+static int use_io = 1;
+#else
+static int use_io = 0;
+#endif
+
 /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
    The RTL chips use a 64 element hash table based on the Ethernet CRC.  */
 static int multicast_filter_limit = 32;
@@ -614,6 +615,8 @@
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
+module_param(use_io, int, 0);
+MODULE_PARM_DESC(use_io, "Force use of I/O access mode. 0=MMIO 1=PIO");
 module_param(multicast_filter_limit, int, 0);
 module_param_array(media, int, NULL, 0);
 module_param_array(full_duplex, int, NULL, 0);
@@ -709,13 +712,8 @@
 	assert (tp->pci_dev != NULL);
 	pdev = tp->pci_dev;
 
-#ifdef USE_IO_OPS
-	if (tp->mmio_addr)
-		ioport_unmap (tp->mmio_addr);
-#else
 	if (tp->mmio_addr)
 		pci_iounmap (pdev, tp->mmio_addr);
-#endif /* USE_IO_OPS */
 
 	/* it's ok to call this even if we have no regions to free */
 	pci_release_regions (pdev);
@@ -790,32 +788,33 @@
 	DPRINTK("PIO region size == 0x%02X\n", pio_len);
 	DPRINTK("MMIO region size == 0x%02lX\n", mmio_len);
 
-#ifdef USE_IO_OPS
-	/* make sure PCI base addr 0 is PIO */
-	if (!(pio_flags & IORESOURCE_IO)) {
-		dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n");
-		rc = -ENODEV;
-		goto err_out;
+retry:
+	if (use_io) {
+		/* make sure PCI base addr 0 is PIO */
+		if (!(pio_flags & IORESOURCE_IO)) {
+			dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n");
+			rc = -ENODEV;
+			goto err_out;
+		}
+		/* check for weird/broken PCI region reporting */
+		if (pio_len < RTL_MIN_IO_SIZE) {
+			dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n");
+			rc = -ENODEV;
+			goto err_out;
+		}
+	} else {
+		/* make sure PCI base addr 1 is MMIO */
+		if (!(mmio_flags & IORESOURCE_MEM)) {
+			dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n");
+			rc = -ENODEV;
+			goto err_out;
+		}
+		if (mmio_len < RTL_MIN_IO_SIZE) {
+			dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n");
+			rc = -ENODEV;
+			goto err_out;
+		}
 	}
-	/* check for weird/broken PCI region reporting */
-	if (pio_len < RTL_MIN_IO_SIZE) {
-		dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n");
-		rc = -ENODEV;
-		goto err_out;
-	}
-#else
-	/* make sure PCI base addr 1 is MMIO */
-	if (!(mmio_flags & IORESOURCE_MEM)) {
-		dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n");
-		rc = -ENODEV;
-		goto err_out;
-	}
-	if (mmio_len < RTL_MIN_IO_SIZE) {
-		dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n");
-		rc = -ENODEV;
-		goto err_out;
-	}
-#endif
 
 	rc = pci_request_regions (pdev, DRV_NAME);
 	if (rc)
@@ -825,28 +824,28 @@
 	/* enable PCI bus-mastering */
 	pci_set_master (pdev);
 
-#ifdef USE_IO_OPS
-	ioaddr = ioport_map(pio_start, pio_len);
-	if (!ioaddr) {
-		dev_err(&pdev->dev, "cannot map PIO, aborting\n");
-		rc = -EIO;
-		goto err_out;
+	if (use_io) {
+		ioaddr = pci_iomap(pdev, 0, 0);
+		if (!ioaddr) {
+			dev_err(&pdev->dev, "cannot map PIO, aborting\n");
+			rc = -EIO;
+			goto err_out;
+		}
+		dev->base_addr = pio_start;
+		tp->regs_len = pio_len;
+	} else {
+		/* ioremap MMIO region */
+		ioaddr = pci_iomap(pdev, 1, 0);
+		if (ioaddr == NULL) {
+			dev_err(&pdev->dev, "cannot remap MMIO, trying PIO\n");
+			pci_release_regions(pdev);
+			use_io = 1;
+			goto retry;
+		}
+		dev->base_addr = (long) ioaddr;
+		tp->regs_len = mmio_len;
 	}
-	dev->base_addr = pio_start;
 	tp->mmio_addr = ioaddr;
-	tp->regs_len = pio_len;
-#else
-	/* ioremap MMIO region */
-	ioaddr = pci_iomap(pdev, 1, 0);
-	if (ioaddr == NULL) {
-		dev_err(&pdev->dev, "cannot remap MMIO, aborting\n");
-		rc = -EIO;
-		goto err_out;
-	}
-	dev->base_addr = (long) ioaddr;
-	tp->mmio_addr = ioaddr;
-	tp->regs_len = mmio_len;
-#endif /* USE_IO_OPS */
 
 	/* Bring old chips out of low-power mode. */
 	RTL_W8 (HltClk, 'R');
@@ -952,6 +951,14 @@
 			   "Use the \"8139cp\" driver for improved performance and stability.\n");
 	}
 
+	if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
+	    pdev->device == PCI_DEVICE_ID_REALTEK_8139 &&
+	    pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS &&
+	    pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) {
+		printk(KERN_INFO "8139too: OQO Model 2 detected. Forcing PIO\n");
+		use_io = 1;
+	}
+
 	i = rtl8139_init_board (pdev, &dev);
 	if (i < 0)
 		return i;
@@ -2381,20 +2388,24 @@
 	np->msg_enable = datum;
 }
 
-/* TODO: we are too slack to do reg dumping for pio, for now */
-#ifdef CONFIG_8139TOO_PIO
-#define rtl8139_get_regs_len	NULL
-#define rtl8139_get_regs	NULL
-#else
 static int rtl8139_get_regs_len(struct net_device *dev)
 {
-	struct rtl8139_private *np = netdev_priv(dev);
+	struct rtl8139_private *np;
+	/* TODO: we are too slack to do reg dumping for pio, for now */
+	if (use_io)
+		return 0;
+	np = netdev_priv(dev);
 	return np->regs_len;
 }
 
 static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf)
 {
-	struct rtl8139_private *np = netdev_priv(dev);
+	struct rtl8139_private *np;
+
+	/* TODO: we are too slack to do reg dumping for pio, for now */
+	if (use_io)
+		return;
+	np = netdev_priv(dev);
 
 	regs->version = RTL_REGS_VER;
 
@@ -2402,7 +2413,6 @@
 	memcpy_fromio(regbuf, np->mmio_addr, regs->len);
 	spin_unlock_irq(&np->lock);
 }
-#endif /* CONFIG_8139TOO_MMIO */
 
 static int rtl8139_get_sset_count(struct net_device *dev, int sset)
 {
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 3e5e64c..fa533c2 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1926,20 +1926,6 @@
 	  To compile this driver as a module, choose M here. The module
 	  will be called e1000.
 
-config E1000_NAPI
-	bool "Use Rx Polling (NAPI)"
-	depends on E1000
-	help
-	  NAPI is a new driver API designed to reduce CPU and interrupt load
-	  when the driver is receiving lots of packets from the card. It is
-	  still somewhat experimental and thus not yet enabled by default.
-
-	  If your estimated Rx load is 10kpps or more, or if the card will be
-	  deployed on potentially unfriendly networks (e.g. in a firewall),
-	  then say Y here.
-
-	  If in doubt, say N.
-
 config E1000_DISABLE_PACKET_SPLIT
 	bool "Disable Packet Split for PCI express adapters"
 	depends on E1000
@@ -2304,6 +2290,17 @@
 	  To compile this driver as a module, choose M here.  The module
 	  will be called atl1.
 
+config ATL1E
+	tristate "Atheros L1E Gigabit Ethernet support (EXPERIMENTAL)"
+	depends on PCI && EXPERIMENTAL
+	select CRC32
+	select MII
+	help
+	  This driver supports the Atheros L1E gigabit ethernet adapter.
+
+	  To compile this driver as a module, choose M here.  The module
+	  will be called atl1e.
+
 endif # NETDEV_1000
 
 #
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 4b17a9a..7629c90 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -15,6 +15,7 @@
 obj-$(CONFIG_CAN) += can/
 obj-$(CONFIG_BONDING) += bonding/
 obj-$(CONFIG_ATL1) += atlx/
+obj-$(CONFIG_ATL1E) += atl1e/
 obj-$(CONFIG_GIANFAR) += gianfar_driver.o
 obj-$(CONFIG_TEHUTI) += tehuti.o
 
diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c
index 1e39e78..ffae266 100644
--- a/drivers/net/arm/at91_ether.c
+++ b/drivers/net/arm/at91_ether.c
@@ -677,7 +677,7 @@
 {
 	strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
 	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-	strlcpy(info->bus_info, dev->dev.parent->bus_id, sizeof(info->bus_info));
+	strlcpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info));
 }
 
 static const struct ethtool_ops at91ether_ethtool_ops = {
@@ -820,7 +820,7 @@
 		lp->skb = skb;
 		lp->skb_length = skb->len;
 		lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE);
-		lp->stats.tx_bytes += skb->len;
+		dev->stats.tx_bytes += skb->len;
 
 		/* Set address of the data in the Transmit Address register */
 		at91_emac_write(AT91_EMAC_TAR, lp->skb_physaddr);
@@ -843,34 +843,33 @@
  */
 static struct net_device_stats *at91ether_stats(struct net_device *dev)
 {
-	struct at91_private *lp = netdev_priv(dev);
 	int ale, lenerr, seqe, lcol, ecol;
 
 	if (netif_running(dev)) {
-		lp->stats.rx_packets += at91_emac_read(AT91_EMAC_OK);		/* Good frames received */
+		dev->stats.rx_packets += at91_emac_read(AT91_EMAC_OK);		/* Good frames received */
 		ale = at91_emac_read(AT91_EMAC_ALE);
-		lp->stats.rx_frame_errors += ale;				/* Alignment errors */
+		dev->stats.rx_frame_errors += ale;				/* Alignment errors */
 		lenerr = at91_emac_read(AT91_EMAC_ELR) + at91_emac_read(AT91_EMAC_USF);
-		lp->stats.rx_length_errors += lenerr;				/* Excessive Length or Undersize Frame error */
+		dev->stats.rx_length_errors += lenerr;				/* Excessive Length or Undersize Frame error */
 		seqe = at91_emac_read(AT91_EMAC_SEQE);
-		lp->stats.rx_crc_errors += seqe;				/* CRC error */
-		lp->stats.rx_fifo_errors += at91_emac_read(AT91_EMAC_DRFC);	/* Receive buffer not available */
-		lp->stats.rx_errors += (ale + lenerr + seqe
+		dev->stats.rx_crc_errors += seqe;				/* CRC error */
+		dev->stats.rx_fifo_errors += at91_emac_read(AT91_EMAC_DRFC);	/* Receive buffer not available */
+		dev->stats.rx_errors += (ale + lenerr + seqe
 			+ at91_emac_read(AT91_EMAC_CDE) + at91_emac_read(AT91_EMAC_RJB));
 
-		lp->stats.tx_packets += at91_emac_read(AT91_EMAC_FRA);		/* Frames successfully transmitted */
-		lp->stats.tx_fifo_errors += at91_emac_read(AT91_EMAC_TUE);	/* Transmit FIFO underruns */
-		lp->stats.tx_carrier_errors += at91_emac_read(AT91_EMAC_CSE);	/* Carrier Sense errors */
-		lp->stats.tx_heartbeat_errors += at91_emac_read(AT91_EMAC_SQEE);/* Heartbeat error */
+		dev->stats.tx_packets += at91_emac_read(AT91_EMAC_FRA);		/* Frames successfully transmitted */
+		dev->stats.tx_fifo_errors += at91_emac_read(AT91_EMAC_TUE);	/* Transmit FIFO underruns */
+		dev->stats.tx_carrier_errors += at91_emac_read(AT91_EMAC_CSE);	/* Carrier Sense errors */
+		dev->stats.tx_heartbeat_errors += at91_emac_read(AT91_EMAC_SQEE);/* Heartbeat error */
 
 		lcol = at91_emac_read(AT91_EMAC_LCOL);
 		ecol = at91_emac_read(AT91_EMAC_ECOL);
-		lp->stats.tx_window_errors += lcol;			/* Late collisions */
-		lp->stats.tx_aborted_errors += ecol;			/* 16 collisions */
+		dev->stats.tx_window_errors += lcol;			/* Late collisions */
+		dev->stats.tx_aborted_errors += ecol;			/* 16 collisions */
 
-		lp->stats.collisions += (at91_emac_read(AT91_EMAC_SCOL) + at91_emac_read(AT91_EMAC_MCOL) + lcol + ecol);
+		dev->stats.collisions += (at91_emac_read(AT91_EMAC_SCOL) + at91_emac_read(AT91_EMAC_MCOL) + lcol + ecol);
 	}
-	return &lp->stats;
+	return &dev->stats;
 }
 
 /*
@@ -896,16 +895,16 @@
 
 			skb->protocol = eth_type_trans(skb, dev);
 			dev->last_rx = jiffies;
-			lp->stats.rx_bytes += pktlen;
+			dev->stats.rx_bytes += pktlen;
 			netif_rx(skb);
 		}
 		else {
-			lp->stats.rx_dropped += 1;
+			dev->stats.rx_dropped += 1;
 			printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
 		}
 
 		if (dlist->descriptors[lp->rxBuffIndex].size & EMAC_MULTICAST)
-			lp->stats.multicast++;
+			dev->stats.multicast++;
 
 		dlist->descriptors[lp->rxBuffIndex].addr &= ~EMAC_DESC_DONE;	/* reset ownership bit */
 		if (lp->rxBuffIndex == MAX_RX_DESCR-1)				/* wrap after last buffer */
@@ -934,7 +933,7 @@
 	if (intstatus & AT91_EMAC_TCOM) {	/* Transmit complete */
 		/* The TCOM bit is set even if the transmission failed. */
 		if (intstatus & (AT91_EMAC_TUND | AT91_EMAC_RTRY))
-			lp->stats.tx_errors += 1;
+			dev->stats.tx_errors += 1;
 
 		if (lp->skb) {
 			dev_kfree_skb_irq(lp->skb);
diff --git a/drivers/net/arm/at91_ether.h b/drivers/net/arm/at91_ether.h
index a38fd2d..353f4da 100644
--- a/drivers/net/arm/at91_ether.h
+++ b/drivers/net/arm/at91_ether.h
@@ -84,7 +84,6 @@
 
 struct at91_private
 {
-	struct net_device_stats stats;
 	struct mii_if_info mii;			/* ethtool support */
 	struct at91_eth_data board_data;	/* board-specific configuration */
 	struct clk *ether_clk;			/* clock */
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
index ecd8fc6..7a14980 100644
--- a/drivers/net/arm/ep93xx_eth.c
+++ b/drivers/net/arm/ep93xx_eth.c
@@ -848,7 +848,7 @@
 
 	ep->res = request_mem_region(pdev->resource[0].start,
 			pdev->resource[0].end - pdev->resource[0].start + 1,
-			pdev->dev.bus_id);
+			dev_name(&pdev->dev));
 	if (ep->res == NULL) {
 		dev_err(&pdev->dev, "Could not reserve memory region\n");
 		err = -ENOMEM;
diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c
index e9d15ec..5c5f1e4 100644
--- a/drivers/net/arm/etherh.c
+++ b/drivers/net/arm/etherh.c
@@ -535,7 +535,7 @@
 	
 	if (!ecard_readchunk(&cd, ec, 0xf5, 0)) {
 		printk(KERN_ERR "%s: unable to read podule description string\n",
-		       ec->dev.bus_id);
+		       dev_name(&ec->dev));
 		goto no_addr;
 	}
 
@@ -554,7 +554,7 @@
 	}
 
 	printk(KERN_ERR "%s: unable to parse MAC address: %s\n",
-	       ec->dev.bus_id, cd.d.string);
+	       dev_name(&ec->dev), cd.d.string);
 
  no_addr:
 	return -ENODEV;
@@ -585,7 +585,7 @@
 {
 	strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
 	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-	strlcpy(info->bus_info, dev->dev.parent->bus_id,
+	strlcpy(info->bus_info, dev_name(dev->dev.parent),
 		sizeof(info->bus_info));
 }
 
diff --git a/drivers/net/atl1e/Makefile b/drivers/net/atl1e/Makefile
new file mode 100644
index 0000000..bc11be8
--- /dev/null
+++ b/drivers/net/atl1e/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_ATL1E)	+= atl1e.o
+atl1e-objs		+= atl1e_main.o atl1e_hw.o atl1e_ethtool.o atl1e_param.o
diff --git a/drivers/net/atl1e/atl1e.h b/drivers/net/atl1e/atl1e.h
new file mode 100644
index 0000000..b645fa0
--- /dev/null
+++ b/drivers/net/atl1e/atl1e.h
@@ -0,0 +1,503 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ * Copyright(c) 2007 xiong huang <xiong.huang@atheros.com>
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _ATL1E_H_
+#define _ATL1E_H_
+
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/udp.h>
+#include <linux/mii.h>
+#include <linux/io.h>
+#include <linux/vmalloc.h>
+#include <linux/pagemap.h>
+#include <linux/tcp.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+#include <linux/workqueue.h>
+#include <net/checksum.h>
+#include <net/ip6_checksum.h>
+
+#include "atl1e_hw.h"
+
+#define PCI_REG_COMMAND	 0x04    /* PCI Command Register */
+#define CMD_IO_SPACE	 0x0001
+#define CMD_MEMORY_SPACE 0x0002
+#define CMD_BUS_MASTER   0x0004
+
+#define BAR_0   0
+#define BAR_1   1
+#define BAR_5   5
+
+/* Wake Up Filter Control */
+#define AT_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
+#define AT_WUFC_MAG  0x00000002 /* Magic Packet Wakeup Enable */
+#define AT_WUFC_EX   0x00000004 /* Directed Exact Wakeup Enable */
+#define AT_WUFC_MC   0x00000008 /* Multicast Wakeup Enable */
+#define AT_WUFC_BC   0x00000010 /* Broadcast Wakeup Enable */
+
+#define SPEED_0		   0xffff
+#define HALF_DUPLEX        1
+#define FULL_DUPLEX        2
+
+/* Error Codes */
+#define AT_ERR_EEPROM      1
+#define AT_ERR_PHY         2
+#define AT_ERR_CONFIG      3
+#define AT_ERR_PARAM       4
+#define AT_ERR_MAC_TYPE    5
+#define AT_ERR_PHY_TYPE    6
+#define AT_ERR_PHY_SPEED   7
+#define AT_ERR_PHY_RES     8
+#define AT_ERR_TIMEOUT     9
+
+#define MAX_JUMBO_FRAME_SIZE 0x2000
+
+#define AT_VLAN_TAG_TO_TPD_TAG(_vlan, _tpd)    \
+	_tpd = (((_vlan) << (4)) | (((_vlan) >> 13) & 7) |\
+		 (((_vlan) >> 9) & 8))
+
+#define AT_TPD_TAG_TO_VLAN_TAG(_tpd, _vlan)    \
+	_vlan = (((_tpd) >> 8) | (((_tpd) & 0x77) << 9) |\
+		   (((_tdp) & 0x88) << 5))
+
+#define AT_MAX_RECEIVE_QUEUE    4
+#define AT_PAGE_NUM_PER_QUEUE   2
+
+#define AT_DMA_HI_ADDR_MASK     0xffffffff00000000ULL
+#define AT_DMA_LO_ADDR_MASK     0x00000000ffffffffULL
+
+#define AT_TX_WATCHDOG  (5 * HZ)
+#define AT_MAX_INT_WORK		10
+#define AT_TWSI_EEPROM_TIMEOUT 	100
+#define AT_HW_MAX_IDLE_DELAY 	10
+#define AT_SUSPEND_LINK_TIMEOUT 28
+
+#define AT_REGS_LEN	75
+#define AT_EEPROM_LEN 	512
+#define AT_ADV_MASK	(ADVERTISE_10_HALF  |\
+			 ADVERTISE_10_FULL  |\
+			 ADVERTISE_100_HALF |\
+			 ADVERTISE_100_FULL |\
+			 ADVERTISE_1000_FULL)
+
+/* tpd word 2 */
+#define TPD_BUFLEN_MASK 	0x3FFF
+#define TPD_BUFLEN_SHIFT        0
+#define TPD_DMAINT_MASK		0x0001
+#define TPD_DMAINT_SHIFT        14
+#define TPD_PKTNT_MASK          0x0001
+#define TPD_PKTINT_SHIFT        15
+#define TPD_VLANTAG_MASK        0xFFFF
+#define TPD_VLAN_SHIFT          16
+
+/* tpd word 3 bits 0:4 */
+#define TPD_EOP_MASK            0x0001
+#define TPD_EOP_SHIFT           0
+#define TPD_IP_VERSION_MASK	0x0001
+#define TPD_IP_VERSION_SHIFT	1	/* 0 : IPV4, 1 : IPV6 */
+#define TPD_INS_VL_TAG_MASK	0x0001
+#define TPD_INS_VL_TAG_SHIFT	2
+#define TPD_CC_SEGMENT_EN_MASK	0x0001
+#define TPD_CC_SEGMENT_EN_SHIFT	3
+#define TPD_SEGMENT_EN_MASK     0x0001
+#define TPD_SEGMENT_EN_SHIFT    4
+
+/* tdp word 3 bits 5:7 if ip version is 0 */
+#define TPD_IP_CSUM_MASK        0x0001
+#define TPD_IP_CSUM_SHIFT       5
+#define TPD_TCP_CSUM_MASK       0x0001
+#define TPD_TCP_CSUM_SHIFT      6
+#define TPD_UDP_CSUM_MASK       0x0001
+#define TPD_UDP_CSUM_SHIFT      7
+
+/* tdp word 3 bits 5:7 if ip version is 1 */
+#define TPD_V6_IPHLLO_MASK	0x0007
+#define TPD_V6_IPHLLO_SHIFT	7
+
+/* tpd word 3 bits 8:9 bit */
+#define TPD_VL_TAGGED_MASK      0x0001
+#define TPD_VL_TAGGED_SHIFT     8
+#define TPD_ETHTYPE_MASK        0x0001
+#define TPD_ETHTYPE_SHIFT       9
+
+/* tdp word 3 bits 10:13 if ip version is 0 */
+#define TDP_V4_IPHL_MASK	0x000F
+#define TPD_V4_IPHL_SHIFT	10
+
+/* tdp word 3 bits 10:13 if ip version is 1 */
+#define TPD_V6_IPHLHI_MASK	0x000F
+#define TPD_V6_IPHLHI_SHIFT	10
+
+/* tpd word 3 bit 14:31 if segment enabled */
+#define TPD_TCPHDRLEN_MASK      0x000F
+#define TPD_TCPHDRLEN_SHIFT     14
+#define TPD_HDRFLAG_MASK        0x0001
+#define TPD_HDRFLAG_SHIFT       18
+#define TPD_MSS_MASK            0x1FFF
+#define TPD_MSS_SHIFT           19
+
+/* tdp word 3 bit 16:31 if custom csum enabled */
+#define TPD_PLOADOFFSET_MASK    0x00FF
+#define TPD_PLOADOFFSET_SHIFT   16
+#define TPD_CCSUMOFFSET_MASK    0x00FF
+#define TPD_CCSUMOFFSET_SHIFT   24
+
+struct atl1e_tpd_desc {
+	__le64 buffer_addr;
+	__le32 word2;
+	__le32 word3;
+};
+
+/* how about 0x2000 */
+#define MAX_TX_BUF_LEN      0x2000
+#define MAX_TX_BUF_SHIFT    13
+/*#define MAX_TX_BUF_LEN  0x3000 */
+
+/* rrs word 1 bit 0:31 */
+#define RRS_RX_CSUM_MASK	0xFFFF
+#define RRS_RX_CSUM_SHIFT	0
+#define RRS_PKT_SIZE_MASK	0x3FFF
+#define RRS_PKT_SIZE_SHIFT	16
+#define RRS_CPU_NUM_MASK	0x0003
+#define	RRS_CPU_NUM_SHIFT	30
+
+#define	RRS_IS_RSS_IPV4		0x0001
+#define RRS_IS_RSS_IPV4_TCP	0x0002
+#define RRS_IS_RSS_IPV6		0x0004
+#define RRS_IS_RSS_IPV6_TCP	0x0008
+#define RRS_IS_IPV6		0x0010
+#define RRS_IS_IP_FRAG		0x0020
+#define RRS_IS_IP_DF		0x0040
+#define RRS_IS_802_3		0x0080
+#define RRS_IS_VLAN_TAG		0x0100
+#define RRS_IS_ERR_FRAME	0x0200
+#define RRS_IS_IPV4		0x0400
+#define RRS_IS_UDP		0x0800
+#define RRS_IS_TCP		0x1000
+#define RRS_IS_BCAST		0x2000
+#define RRS_IS_MCAST		0x4000
+#define RRS_IS_PAUSE		0x8000
+
+#define RRS_ERR_BAD_CRC		0x0001
+#define RRS_ERR_CODE		0x0002
+#define RRS_ERR_DRIBBLE		0x0004
+#define RRS_ERR_RUNT		0x0008
+#define RRS_ERR_RX_OVERFLOW	0x0010
+#define RRS_ERR_TRUNC		0x0020
+#define RRS_ERR_IP_CSUM		0x0040
+#define RRS_ERR_L4_CSUM		0x0080
+#define RRS_ERR_LENGTH		0x0100
+#define RRS_ERR_DES_ADDR	0x0200
+
+struct atl1e_recv_ret_status {
+	u16 seq_num;
+	u16 hash_lo;
+	__le32	word1;
+	u16 pkt_flag;
+	u16 err_flag;
+	u16 hash_hi;
+	u16 vtag;
+};
+
+enum atl1e_dma_req_block {
+	atl1e_dma_req_128 = 0,
+	atl1e_dma_req_256 = 1,
+	atl1e_dma_req_512 = 2,
+	atl1e_dma_req_1024 = 3,
+	atl1e_dma_req_2048 = 4,
+	atl1e_dma_req_4096 = 5
+};
+
+enum atl1e_rrs_type {
+	atl1e_rrs_disable = 0,
+	atl1e_rrs_ipv4 = 1,
+	atl1e_rrs_ipv4_tcp = 2,
+	atl1e_rrs_ipv6 = 4,
+	atl1e_rrs_ipv6_tcp = 8
+};
+
+enum atl1e_nic_type {
+	athr_l1e = 0,
+	athr_l2e_revA = 1,
+	athr_l2e_revB = 2
+};
+
+struct atl1e_hw_stats {
+	/* rx */
+	unsigned long rx_ok;	      /* The number of good packet received. */
+	unsigned long rx_bcast;       /* The number of good broadcast packet received. */
+	unsigned long rx_mcast;       /* The number of good multicast packet received. */
+	unsigned long rx_pause;       /* The number of Pause packet received. */
+	unsigned long rx_ctrl;        /* The number of Control packet received other than Pause frame. */
+	unsigned long rx_fcs_err;     /* The number of packets with bad FCS. */
+	unsigned long rx_len_err;     /* The number of packets with mismatch of length field and actual size. */
+	unsigned long rx_byte_cnt;    /* The number of bytes of good packet received. FCS is NOT included. */
+	unsigned long rx_runt;        /* The number of packets received that are less than 64 byte long and with good FCS. */
+	unsigned long rx_frag;        /* The number of packets received that are less than 64 byte long and with bad FCS. */
+	unsigned long rx_sz_64;       /* The number of good and bad packets received that are 64 byte long. */
+	unsigned long rx_sz_65_127;   /* The number of good and bad packets received that are between 65 and 127-byte long. */
+	unsigned long rx_sz_128_255;  /* The number of good and bad packets received that are between 128 and 255-byte long. */
+	unsigned long rx_sz_256_511;  /* The number of good and bad packets received that are between 256 and 511-byte long. */
+	unsigned long rx_sz_512_1023; /* The number of good and bad packets received that are between 512 and 1023-byte long. */
+	unsigned long rx_sz_1024_1518;    /* The number of good and bad packets received that are between 1024 and 1518-byte long. */
+	unsigned long rx_sz_1519_max; /* The number of good and bad packets received that are between 1519-byte and MTU. */
+	unsigned long rx_sz_ov;       /* The number of good and bad packets received that are more than MTU size truncated by Selene. */
+	unsigned long rx_rxf_ov;      /* The number of frame dropped due to occurrence of RX FIFO overflow. */
+	unsigned long rx_rrd_ov;      /* The number of frame dropped due to occurrence of RRD overflow. */
+	unsigned long rx_align_err;   /* Alignment Error */
+	unsigned long rx_bcast_byte_cnt;  /* The byte count of broadcast packet received, excluding FCS. */
+	unsigned long rx_mcast_byte_cnt;  /* The byte count of multicast packet received, excluding FCS. */
+	unsigned long rx_err_addr;    /* The number of packets dropped due to address filtering. */
+
+	/* tx */
+	unsigned long tx_ok;      /* The number of good packet transmitted. */
+	unsigned long tx_bcast;       /* The number of good broadcast packet transmitted. */
+	unsigned long tx_mcast;       /* The number of good multicast packet transmitted. */
+	unsigned long tx_pause;       /* The number of Pause packet transmitted. */
+	unsigned long tx_exc_defer;   /* The number of packets transmitted with excessive deferral. */
+	unsigned long tx_ctrl;        /* The number of packets transmitted is a control frame, excluding Pause frame. */
+	unsigned long tx_defer;       /* The number of packets transmitted that is deferred. */
+	unsigned long tx_byte_cnt;    /* The number of bytes of data transmitted. FCS is NOT included. */
+	unsigned long tx_sz_64;       /* The number of good and bad packets transmitted that are 64 byte long. */
+	unsigned long tx_sz_65_127;   /* The number of good and bad packets transmitted that are between 65 and 127-byte long. */
+	unsigned long tx_sz_128_255;  /* The number of good and bad packets transmitted that are between 128 and 255-byte long. */
+	unsigned long tx_sz_256_511;  /* The number of good and bad packets transmitted that are between 256 and 511-byte long. */
+	unsigned long tx_sz_512_1023; /* The number of good and bad packets transmitted that are between 512 and 1023-byte long. */
+	unsigned long tx_sz_1024_1518;    /* The number of good and bad packets transmitted that are between 1024 and 1518-byte long. */
+	unsigned long tx_sz_1519_max; /* The number of good and bad packets transmitted that are between 1519-byte and MTU. */
+	unsigned long tx_1_col;       /* The number of packets subsequently transmitted successfully with a single prior collision. */
+	unsigned long tx_2_col;       /* The number of packets subsequently transmitted successfully with multiple prior collisions. */
+	unsigned long tx_late_col;    /* The number of packets transmitted with late collisions. */
+	unsigned long tx_abort_col;   /* The number of transmit packets aborted due to excessive collisions. */
+	unsigned long tx_underrun;    /* The number of transmit packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */
+	unsigned long tx_rd_eop;      /* The number of times that read beyond the EOP into the next frame area when TRD was not written timely */
+	unsigned long tx_len_err;     /* The number of transmit packets with length field does NOT match the actual frame size. */
+	unsigned long tx_trunc;       /* The number of transmit packets truncated due to size exceeding MTU. */
+	unsigned long tx_bcast_byte;  /* The byte count of broadcast packet transmitted, excluding FCS. */
+	unsigned long tx_mcast_byte;  /* The byte count of multicast packet transmitted, excluding FCS. */
+};
+
+struct atl1e_hw {
+	u8 __iomem      *hw_addr;            /* inner register address */
+	resource_size_t mem_rang;
+	struct atl1e_adapter *adapter;
+	enum atl1e_nic_type  nic_type;
+	u16 device_id;
+	u16 vendor_id;
+	u16 subsystem_id;
+	u16 subsystem_vendor_id;
+	u8  revision_id;
+	u16 pci_cmd_word;
+	u8 mac_addr[ETH_ALEN];
+	u8 perm_mac_addr[ETH_ALEN];
+	u8 preamble_len;
+	u16 max_frame_size;
+	u16 rx_jumbo_th;
+	u16 tx_jumbo_th;
+
+	u16 media_type;
+#define MEDIA_TYPE_AUTO_SENSOR  0
+#define MEDIA_TYPE_100M_FULL    1
+#define MEDIA_TYPE_100M_HALF    2
+#define MEDIA_TYPE_10M_FULL     3
+#define MEDIA_TYPE_10M_HALF     4
+
+	u16 autoneg_advertised;
+#define ADVERTISE_10_HALF               0x0001
+#define ADVERTISE_10_FULL               0x0002
+#define ADVERTISE_100_HALF              0x0004
+#define ADVERTISE_100_FULL              0x0008
+#define ADVERTISE_1000_HALF             0x0010 /* Not used, just FYI */
+#define ADVERTISE_1000_FULL             0x0020
+	u16 mii_autoneg_adv_reg;
+	u16 mii_1000t_ctrl_reg;
+
+	u16 imt;        /* Interrupt Moderator timer ( 2us resolution) */
+	u16 ict;        /* Interrupt Clear timer (2us resolution) */
+	u32 smb_timer;
+	u16 rrd_thresh; /* Threshold of number of RRD produced to trigger
+			  interrupt request */
+	u16 tpd_thresh;
+	u16 rx_count_down; /* 2us resolution */
+	u16 tx_count_down;
+
+	u8 tpd_burst;   /* Number of TPD to prefetch in cache-aligned burst. */
+	enum atl1e_rrs_type rrs_type;
+	u32 base_cpu;
+	u32 indirect_tab;
+
+	enum atl1e_dma_req_block dmar_block;
+	enum atl1e_dma_req_block dmaw_block;
+	u8 dmaw_dly_cnt;
+	u8 dmar_dly_cnt;
+
+	bool phy_configured;
+	bool re_autoneg;
+	bool emi_ca;
+};
+
+/*
+ * wrapper around a pointer to a socket buffer,
+ * so a DMA handle can be stored along with the buffer
+ */
+struct atl1e_tx_buffer {
+	struct sk_buff *skb;
+	u16 length;
+	dma_addr_t dma;
+};
+
+struct atl1e_rx_page {
+	dma_addr_t	dma;    /* receive rage DMA address */
+	u8		*addr;   /* receive rage virtual address */
+	dma_addr_t	write_offset_dma;  /* the DMA address which contain the
+					      receive data offset in the page */
+	u32		*write_offset_addr; /* the virtaul address which contain
+					     the receive data offset in the page */
+	u32		read_offset;       /* the offset where we have read */
+};
+
+struct atl1e_rx_page_desc {
+	struct atl1e_rx_page   rx_page[AT_PAGE_NUM_PER_QUEUE];
+	u8  rx_using;
+	u16 rx_nxseq;
+};
+
+/* transmit packet descriptor (tpd) ring */
+struct atl1e_tx_ring {
+	struct atl1e_tpd_desc *desc;  /* descriptor ring virtual address  */
+	dma_addr_t	   dma;    /* descriptor ring physical address */
+	u16       	   count;  /* the count of transmit rings  */
+	rwlock_t	   tx_lock;
+	u16		   next_to_use;
+	atomic_t	   next_to_clean;
+	struct atl1e_tx_buffer *tx_buffer;
+	dma_addr_t	   cmb_dma;
+	u32		   *cmb;
+};
+
+/* receive packet descriptor ring */
+struct atl1e_rx_ring {
+	void        	*desc;
+	dma_addr_t  	dma;
+	int         	size;
+	u32	    	page_size; /* bytes length of rxf page */
+	u32		real_page_size; /* real_page_size = page_size + jumbo + aliagn */
+	struct atl1e_rx_page_desc	rx_page_desc[AT_MAX_RECEIVE_QUEUE];
+};
+
+/* board specific private data structure */
+struct atl1e_adapter {
+	struct net_device   *netdev;
+	struct pci_dev      *pdev;
+	struct vlan_group   *vlgrp;
+	struct napi_struct  napi;
+	struct mii_if_info  mii;    /* MII interface info */
+	struct atl1e_hw        hw;
+	struct atl1e_hw_stats  hw_stats;
+	struct net_device_stats net_stats;
+
+	bool have_msi;
+	u32 wol;
+	u16 link_speed;
+	u16 link_duplex;
+
+	spinlock_t mdio_lock;
+	spinlock_t tx_lock;
+	atomic_t irq_sem;
+
+	struct work_struct reset_task;
+	struct work_struct link_chg_task;
+	struct timer_list watchdog_timer;
+	struct timer_list phy_config_timer;
+
+	/* All Descriptor memory */
+	dma_addr_t  	ring_dma;
+	void     	*ring_vir_addr;
+	int             ring_size;
+
+	struct atl1e_tx_ring tx_ring;
+	struct atl1e_rx_ring rx_ring;
+	int num_rx_queues;
+	unsigned long flags;
+#define __AT_TESTING        0x0001
+#define __AT_RESETTING      0x0002
+#define __AT_DOWN           0x0003
+
+	u32 bd_number;     /* board number;*/
+	u32 pci_state[16];
+	u32 *config_space;
+};
+
+#define AT_WRITE_REG(a, reg, value) ( \
+		writel((value), ((a)->hw_addr + reg)))
+
+#define AT_WRITE_FLUSH(a) (\
+		readl((a)->hw_addr))
+
+#define AT_READ_REG(a, reg) ( \
+		readl((a)->hw_addr + reg))
+
+#define AT_WRITE_REGB(a, reg, value) (\
+		writeb((value), ((a)->hw_addr + reg)))
+
+#define AT_READ_REGB(a, reg) (\
+		readb((a)->hw_addr + reg))
+
+#define AT_WRITE_REGW(a, reg, value) (\
+		writew((value), ((a)->hw_addr + reg)))
+
+#define AT_READ_REGW(a, reg) (\
+		readw((a)->hw_addr + reg))
+
+#define AT_WRITE_REG_ARRAY(a, reg, offset, value) ( \
+		writel((value), (((a)->hw_addr + reg) + ((offset) << 2))))
+
+#define AT_READ_REG_ARRAY(a, reg, offset) ( \
+		readl(((a)->hw_addr + reg) + ((offset) << 2)))
+
+extern char atl1e_driver_name[];
+extern char atl1e_driver_version[];
+
+extern void atl1e_check_options(struct atl1e_adapter *adapter);
+extern int atl1e_up(struct atl1e_adapter *adapter);
+extern void atl1e_down(struct atl1e_adapter *adapter);
+extern void atl1e_reinit_locked(struct atl1e_adapter *adapter);
+extern s32 atl1e_reset_hw(struct atl1e_hw *hw);
+extern void atl1e_set_ethtool_ops(struct net_device *netdev);
+#endif /* _ATL1_E_H_ */
diff --git a/drivers/net/atl1e/atl1e_ethtool.c b/drivers/net/atl1e/atl1e_ethtool.c
new file mode 100644
index 0000000..cdc3b85
--- /dev/null
+++ b/drivers/net/atl1e/atl1e_ethtool.c
@@ -0,0 +1,405 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  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/netdevice.h>
+#include <linux/ethtool.h>
+
+#include "atl1e.h"
+
+static int atl1e_get_settings(struct net_device *netdev,
+			      struct ethtool_cmd *ecmd)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	struct atl1e_hw *hw = &adapter->hw;
+
+	ecmd->supported = (SUPPORTED_10baseT_Half  |
+			   SUPPORTED_10baseT_Full  |
+			   SUPPORTED_100baseT_Half |
+			   SUPPORTED_100baseT_Full |
+			   SUPPORTED_Autoneg       |
+			   SUPPORTED_TP);
+	if (hw->nic_type == athr_l1e)
+		ecmd->supported |= SUPPORTED_1000baseT_Full;
+
+	ecmd->advertising = ADVERTISED_TP;
+
+	ecmd->advertising |= ADVERTISED_Autoneg;
+	ecmd->advertising |= hw->autoneg_advertised;
+
+	ecmd->port = PORT_TP;
+	ecmd->phy_address = 0;
+	ecmd->transceiver = XCVR_INTERNAL;
+
+	if (adapter->link_speed != SPEED_0) {
+		ecmd->speed = adapter->link_speed;
+		if (adapter->link_duplex == FULL_DUPLEX)
+			ecmd->duplex = DUPLEX_FULL;
+		else
+			ecmd->duplex = DUPLEX_HALF;
+	} else {
+		ecmd->speed = -1;
+		ecmd->duplex = -1;
+	}
+
+	ecmd->autoneg = AUTONEG_ENABLE;
+	return 0;
+}
+
+static int atl1e_set_settings(struct net_device *netdev,
+			      struct ethtool_cmd *ecmd)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	struct atl1e_hw *hw = &adapter->hw;
+
+	while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
+		msleep(1);
+
+	if (ecmd->autoneg == AUTONEG_ENABLE) {
+		u16 adv4, adv9;
+
+		if ((ecmd->advertising&ADVERTISE_1000_FULL)) {
+			if (hw->nic_type == athr_l1e) {
+				hw->autoneg_advertised =
+					ecmd->advertising & AT_ADV_MASK;
+			} else {
+				clear_bit(__AT_RESETTING, &adapter->flags);
+				return -EINVAL;
+			}
+		} else if (ecmd->advertising&ADVERTISE_1000_HALF) {
+			clear_bit(__AT_RESETTING, &adapter->flags);
+			return -EINVAL;
+		} else {
+			hw->autoneg_advertised =
+				ecmd->advertising & AT_ADV_MASK;
+		}
+		ecmd->advertising = hw->autoneg_advertised |
+				    ADVERTISED_TP | ADVERTISED_Autoneg;
+
+		adv4 = hw->mii_autoneg_adv_reg & ~MII_AR_SPEED_MASK;
+		adv9 = hw->mii_1000t_ctrl_reg & ~MII_AT001_CR_1000T_SPEED_MASK;
+		if (hw->autoneg_advertised & ADVERTISE_10_HALF)
+			adv4 |= MII_AR_10T_HD_CAPS;
+		if (hw->autoneg_advertised & ADVERTISE_10_FULL)
+			adv4 |= MII_AR_10T_FD_CAPS;
+		if (hw->autoneg_advertised & ADVERTISE_100_HALF)
+			adv4 |= MII_AR_100TX_HD_CAPS;
+		if (hw->autoneg_advertised & ADVERTISE_100_FULL)
+			adv4 |= MII_AR_100TX_FD_CAPS;
+		if (hw->autoneg_advertised & ADVERTISE_1000_FULL)
+			adv9 |= MII_AT001_CR_1000T_FD_CAPS;
+
+		if (adv4 != hw->mii_autoneg_adv_reg ||
+				adv9 != hw->mii_1000t_ctrl_reg) {
+			hw->mii_autoneg_adv_reg = adv4;
+			hw->mii_1000t_ctrl_reg = adv9;
+			hw->re_autoneg = true;
+		}
+
+	} else {
+		clear_bit(__AT_RESETTING, &adapter->flags);
+		return -EINVAL;
+	}
+
+	/* reset the link */
+
+	if (netif_running(adapter->netdev)) {
+		atl1e_down(adapter);
+		atl1e_up(adapter);
+	} else
+		atl1e_reset_hw(&adapter->hw);
+
+	clear_bit(__AT_RESETTING, &adapter->flags);
+	return 0;
+}
+
+static u32 atl1e_get_tx_csum(struct net_device *netdev)
+{
+	return (netdev->features & NETIF_F_HW_CSUM) != 0;
+}
+
+static u32 atl1e_get_msglevel(struct net_device *netdev)
+{
+#ifdef DBG
+	return 1;
+#else
+	return 0;
+#endif
+}
+
+static void atl1e_set_msglevel(struct net_device *netdev, u32 data)
+{
+}
+
+static int atl1e_get_regs_len(struct net_device *netdev)
+{
+	return AT_REGS_LEN * sizeof(u32);
+}
+
+static void atl1e_get_regs(struct net_device *netdev,
+			   struct ethtool_regs *regs, void *p)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	struct atl1e_hw *hw = &adapter->hw;
+	u32 *regs_buff = p;
+	u16 phy_data;
+
+	memset(p, 0, AT_REGS_LEN * sizeof(u32));
+
+	regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;
+
+	regs_buff[0]  = AT_READ_REG(hw, REG_VPD_CAP);
+	regs_buff[1]  = AT_READ_REG(hw, REG_SPI_FLASH_CTRL);
+	regs_buff[2]  = AT_READ_REG(hw, REG_SPI_FLASH_CONFIG);
+	regs_buff[3]  = AT_READ_REG(hw, REG_TWSI_CTRL);
+	regs_buff[4]  = AT_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL);
+	regs_buff[5]  = AT_READ_REG(hw, REG_MASTER_CTRL);
+	regs_buff[6]  = AT_READ_REG(hw, REG_MANUAL_TIMER_INIT);
+	regs_buff[7]  = AT_READ_REG(hw, REG_IRQ_MODU_TIMER_INIT);
+	regs_buff[8]  = AT_READ_REG(hw, REG_GPHY_CTRL);
+	regs_buff[9]  = AT_READ_REG(hw, REG_CMBDISDMA_TIMER);
+	regs_buff[10] = AT_READ_REG(hw, REG_IDLE_STATUS);
+	regs_buff[11] = AT_READ_REG(hw, REG_MDIO_CTRL);
+	regs_buff[12] = AT_READ_REG(hw, REG_SERDES_LOCK);
+	regs_buff[13] = AT_READ_REG(hw, REG_MAC_CTRL);
+	regs_buff[14] = AT_READ_REG(hw, REG_MAC_IPG_IFG);
+	regs_buff[15] = AT_READ_REG(hw, REG_MAC_STA_ADDR);
+	regs_buff[16] = AT_READ_REG(hw, REG_MAC_STA_ADDR+4);
+	regs_buff[17] = AT_READ_REG(hw, REG_RX_HASH_TABLE);
+	regs_buff[18] = AT_READ_REG(hw, REG_RX_HASH_TABLE+4);
+	regs_buff[19] = AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL);
+	regs_buff[20] = AT_READ_REG(hw, REG_MTU);
+	regs_buff[21] = AT_READ_REG(hw, REG_WOL_CTRL);
+	regs_buff[22] = AT_READ_REG(hw, REG_SRAM_TRD_ADDR);
+	regs_buff[23] = AT_READ_REG(hw, REG_SRAM_TRD_LEN);
+	regs_buff[24] = AT_READ_REG(hw, REG_SRAM_RXF_ADDR);
+	regs_buff[25] = AT_READ_REG(hw, REG_SRAM_RXF_LEN);
+	regs_buff[26] = AT_READ_REG(hw, REG_SRAM_TXF_ADDR);
+	regs_buff[27] = AT_READ_REG(hw, REG_SRAM_TXF_LEN);
+	regs_buff[28] = AT_READ_REG(hw, REG_SRAM_TCPH_ADDR);
+	regs_buff[29] = AT_READ_REG(hw, REG_SRAM_PKTH_ADDR);
+
+	atl1e_read_phy_reg(hw, MII_BMCR, &phy_data);
+	regs_buff[73] = (u32)phy_data;
+	atl1e_read_phy_reg(hw, MII_BMSR, &phy_data);
+	regs_buff[74] = (u32)phy_data;
+}
+
+static int atl1e_get_eeprom_len(struct net_device *netdev)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+	if (!atl1e_check_eeprom_exist(&adapter->hw))
+		return AT_EEPROM_LEN;
+	else
+		return 0;
+}
+
+static int atl1e_get_eeprom(struct net_device *netdev,
+		struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	struct atl1e_hw *hw = &adapter->hw;
+	u32 *eeprom_buff;
+	int first_dword, last_dword;
+	int ret_val = 0;
+	int i;
+
+	if (eeprom->len == 0)
+		return -EINVAL;
+
+	if (atl1e_check_eeprom_exist(hw)) /* not exist */
+		return -EINVAL;
+
+	eeprom->magic = hw->vendor_id | (hw->device_id << 16);
+
+	first_dword = eeprom->offset >> 2;
+	last_dword = (eeprom->offset + eeprom->len - 1) >> 2;
+
+	eeprom_buff = kmalloc(sizeof(u32) *
+			(last_dword - first_dword + 1), GFP_KERNEL);
+	if (eeprom_buff == NULL)
+		return -ENOMEM;
+
+	for (i = first_dword; i < last_dword; i++) {
+		if (!atl1e_read_eeprom(hw, i * 4, &(eeprom_buff[i-first_dword]))) {
+			kfree(eeprom_buff);
+			return -EIO;
+		}
+	}
+
+	memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3),
+			eeprom->len);
+	kfree(eeprom_buff);
+
+	return ret_val;
+}
+
+static int atl1e_set_eeprom(struct net_device *netdev,
+			    struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	struct atl1e_hw *hw = &adapter->hw;
+	u32 *eeprom_buff;
+	u32 *ptr;
+	int first_dword, last_dword;
+	int ret_val = 0;
+	int i;
+
+	if (eeprom->len == 0)
+		return -EOPNOTSUPP;
+
+	if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
+		return -EINVAL;
+
+	first_dword = eeprom->offset >> 2;
+	last_dword = (eeprom->offset + eeprom->len - 1) >> 2;
+	eeprom_buff = kmalloc(AT_EEPROM_LEN, GFP_KERNEL);
+	if (eeprom_buff == NULL)
+		return -ENOMEM;
+
+	ptr = (u32 *)eeprom_buff;
+
+	if (eeprom->offset & 3) {
+		/* need read/modify/write of first changed EEPROM word */
+		/* only the second byte of the word is being modified */
+		if (!atl1e_read_eeprom(hw, first_dword * 4, &(eeprom_buff[0]))) {
+			ret_val = -EIO;
+			goto out;
+		}
+		ptr++;
+	}
+	if (((eeprom->offset + eeprom->len) & 3)) {
+		/* need read/modify/write of last changed EEPROM word */
+		/* only the first byte of the word is being modified */
+
+		if (!atl1e_read_eeprom(hw, last_dword * 4,
+				&(eeprom_buff[last_dword - first_dword]))) {
+			ret_val = -EIO;
+			goto out;
+		}
+	}
+
+	/* Device's eeprom is always little-endian, word addressable */
+	memcpy(ptr, bytes, eeprom->len);
+
+	for (i = 0; i < last_dword - first_dword + 1; i++) {
+		if (!atl1e_write_eeprom(hw, ((first_dword + i) * 4),
+				  eeprom_buff[i])) {
+			ret_val = -EIO;
+			goto out;
+		}
+	}
+out:
+	kfree(eeprom_buff);
+	return ret_val;
+}
+
+static void atl1e_get_drvinfo(struct net_device *netdev,
+		struct ethtool_drvinfo *drvinfo)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+	strncpy(drvinfo->driver,  atl1e_driver_name, 32);
+	strncpy(drvinfo->version, atl1e_driver_version, 32);
+	strncpy(drvinfo->fw_version, "L1e", 32);
+	strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
+	drvinfo->n_stats = 0;
+	drvinfo->testinfo_len = 0;
+	drvinfo->regdump_len = atl1e_get_regs_len(netdev);
+	drvinfo->eedump_len = atl1e_get_eeprom_len(netdev);
+}
+
+static void atl1e_get_wol(struct net_device *netdev,
+			  struct ethtool_wolinfo *wol)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+	wol->supported = WAKE_MAGIC | WAKE_PHY;
+	wol->wolopts = 0;
+
+	if (adapter->wol & AT_WUFC_EX)
+		wol->wolopts |= WAKE_UCAST;
+	if (adapter->wol & AT_WUFC_MC)
+		wol->wolopts |= WAKE_MCAST;
+	if (adapter->wol & AT_WUFC_BC)
+		wol->wolopts |= WAKE_BCAST;
+	if (adapter->wol & AT_WUFC_MAG)
+		wol->wolopts |= WAKE_MAGIC;
+	if (adapter->wol & AT_WUFC_LNKC)
+		wol->wolopts |= WAKE_PHY;
+
+	return;
+}
+
+static int atl1e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+	if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE |
+			    WAKE_MCAST | WAKE_BCAST | WAKE_MCAST))
+		return -EOPNOTSUPP;
+	/* these settings will always override what we currently have */
+	adapter->wol = 0;
+
+	if (wol->wolopts & WAKE_MAGIC)
+		adapter->wol |= AT_WUFC_MAG;
+	if (wol->wolopts & WAKE_PHY)
+		adapter->wol |= AT_WUFC_LNKC;
+
+	return 0;
+}
+
+static int atl1e_nway_reset(struct net_device *netdev)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	if (netif_running(netdev))
+		atl1e_reinit_locked(adapter);
+	return 0;
+}
+
+static struct ethtool_ops atl1e_ethtool_ops = {
+	.get_settings           = atl1e_get_settings,
+	.set_settings           = atl1e_set_settings,
+	.get_drvinfo            = atl1e_get_drvinfo,
+	.get_regs_len           = atl1e_get_regs_len,
+	.get_regs               = atl1e_get_regs,
+	.get_wol                = atl1e_get_wol,
+	.set_wol                = atl1e_set_wol,
+	.get_msglevel           = atl1e_get_msglevel,
+	.set_msglevel           = atl1e_set_msglevel,
+	.nway_reset             = atl1e_nway_reset,
+	.get_link               = ethtool_op_get_link,
+	.get_eeprom_len         = atl1e_get_eeprom_len,
+	.get_eeprom             = atl1e_get_eeprom,
+	.set_eeprom             = atl1e_set_eeprom,
+	.get_tx_csum            = atl1e_get_tx_csum,
+	.get_sg                 = ethtool_op_get_sg,
+	.set_sg                 = ethtool_op_set_sg,
+#ifdef NETIF_F_TSO
+	.get_tso                = ethtool_op_get_tso,
+#endif
+};
+
+void atl1e_set_ethtool_ops(struct net_device *netdev)
+{
+	SET_ETHTOOL_OPS(netdev, &atl1e_ethtool_ops);
+}
diff --git a/drivers/net/atl1e/atl1e_hw.c b/drivers/net/atl1e/atl1e_hw.c
new file mode 100644
index 0000000..949e753
--- /dev/null
+++ b/drivers/net/atl1e/atl1e_hw.c
@@ -0,0 +1,664 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  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/pci.h>
+#include <linux/delay.h>
+#include <linux/mii.h>
+#include <linux/crc32.h>
+
+#include "atl1e.h"
+
+/*
+ * check_eeprom_exist
+ * return 0 if eeprom exist
+ */
+int atl1e_check_eeprom_exist(struct atl1e_hw *hw)
+{
+	u32 value;
+
+	value = AT_READ_REG(hw, REG_SPI_FLASH_CTRL);
+	if (value & SPI_FLASH_CTRL_EN_VPD) {
+		value &= ~SPI_FLASH_CTRL_EN_VPD;
+		AT_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value);
+	}
+	value = AT_READ_REGW(hw, REG_PCIE_CAP_LIST);
+	return ((value & 0xFF00) == 0x6C00) ? 0 : 1;
+}
+
+void atl1e_hw_set_mac_addr(struct atl1e_hw *hw)
+{
+	u32 value;
+	/*
+	 * 00-0B-6A-F6-00-DC
+	 * 0:  6AF600DC 1: 000B
+	 * low dword
+	 */
+	value = (((u32)hw->mac_addr[2]) << 24) |
+		(((u32)hw->mac_addr[3]) << 16) |
+		(((u32)hw->mac_addr[4]) << 8)  |
+		(((u32)hw->mac_addr[5])) ;
+	AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value);
+	/* hight dword */
+	value = (((u32)hw->mac_addr[0]) << 8) |
+		(((u32)hw->mac_addr[1])) ;
+	AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value);
+}
+
+/*
+ * atl1e_get_permanent_address
+ * return 0 if get valid mac address,
+ */
+static int atl1e_get_permanent_address(struct atl1e_hw *hw)
+{
+	u32 addr[2];
+	u32 i;
+	u32 twsi_ctrl_data;
+	u8  eth_addr[ETH_ALEN];
+
+	if (is_valid_ether_addr(hw->perm_mac_addr))
+		return 0;
+
+	/* init */
+	addr[0] = addr[1] = 0;
+
+	if (!atl1e_check_eeprom_exist(hw)) {
+		/* eeprom exist */
+		twsi_ctrl_data = AT_READ_REG(hw, REG_TWSI_CTRL);
+		twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART;
+		AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data);
+		for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) {
+			msleep(10);
+			twsi_ctrl_data = AT_READ_REG(hw, REG_TWSI_CTRL);
+			if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0)
+				break;
+		}
+		if (i >= AT_TWSI_EEPROM_TIMEOUT)
+			return AT_ERR_TIMEOUT;
+	}
+
+	/* maybe MAC-address is from BIOS */
+	addr[0] = AT_READ_REG(hw, REG_MAC_STA_ADDR);
+	addr[1] = AT_READ_REG(hw, REG_MAC_STA_ADDR + 4);
+	*(u32 *) &eth_addr[2] = swab32(addr[0]);
+	*(u16 *) &eth_addr[0] = swab16(*(u16 *)&addr[1]);
+
+	if (is_valid_ether_addr(eth_addr)) {
+		memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+		return 0;
+	}
+
+	return AT_ERR_EEPROM;
+}
+
+bool atl1e_write_eeprom(struct atl1e_hw *hw, u32 offset, u32 value)
+{
+	return true;
+}
+
+bool atl1e_read_eeprom(struct atl1e_hw *hw, u32 offset, u32 *p_value)
+{
+	int i;
+	u32 control;
+
+	if (offset & 3)
+		return false; /* address do not align */
+
+	AT_WRITE_REG(hw, REG_VPD_DATA, 0);
+	control = (offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT;
+	AT_WRITE_REG(hw, REG_VPD_CAP, control);
+
+	for (i = 0; i < 10; i++) {
+		msleep(2);
+		control = AT_READ_REG(hw, REG_VPD_CAP);
+		if (control & VPD_CAP_VPD_FLAG)
+			break;
+	}
+	if (control & VPD_CAP_VPD_FLAG) {
+		*p_value = AT_READ_REG(hw, REG_VPD_DATA);
+		return true;
+	}
+	return false; /* timeout */
+}
+
+void atl1e_force_ps(struct atl1e_hw *hw)
+{
+	AT_WRITE_REGW(hw, REG_GPHY_CTRL,
+			GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET);
+}
+
+/*
+ * Reads the adapter's MAC address from the EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ */
+int atl1e_read_mac_addr(struct atl1e_hw *hw)
+{
+	int err = 0;
+
+	err = atl1e_get_permanent_address(hw);
+	if (err)
+		return AT_ERR_EEPROM;
+	memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr));
+	return 0;
+}
+
+/*
+ * atl1e_hash_mc_addr
+ *  purpose
+ *      set hash value for a multicast address
+ *      hash calcu processing :
+ *          1. calcu 32bit CRC for multicast address
+ *          2. reverse crc with MSB to LSB
+ */
+u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr)
+{
+	u32 crc32;
+	u32 value = 0;
+	int i;
+
+	crc32 = ether_crc_le(6, mc_addr);
+	crc32 = ~crc32;
+	for (i = 0; i < 32; i++)
+		value |= (((crc32 >> i) & 1) << (31 - i));
+
+	return value;
+}
+
+/*
+ * Sets the bit in the multicast table corresponding to the hash value.
+ * hw - Struct containing variables accessed by shared code
+ * hash_value - Multicast address hash value
+ */
+void atl1e_hash_set(struct atl1e_hw *hw, u32 hash_value)
+{
+	u32 hash_bit, hash_reg;
+	u32 mta;
+
+	/*
+	 * The HASH Table  is a register array of 2 32-bit registers.
+	 * It is treated like an array of 64 bits.  We want to set
+	 * bit BitArray[hash_value]. So we figure out what register
+	 * the bit is in, read it, OR in the new bit, then write
+	 * back the new value.  The register is determined by the
+	 * upper 7 bits of the hash value and the bit within that
+	 * register are determined by the lower 5 bits of the value.
+	 */
+	hash_reg = (hash_value >> 31) & 0x1;
+	hash_bit = (hash_value >> 26) & 0x1F;
+
+	mta = AT_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg);
+
+	mta |= (1 << hash_bit);
+
+	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta);
+}
+/*
+ * Reads the value from a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to read
+ */
+int atl1e_read_phy_reg(struct atl1e_hw *hw, u16 reg_addr, u16 *phy_data)
+{
+	u32 val;
+	int i;
+
+	val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
+		MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW |
+		MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+
+	AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
+
+	wmb();
+
+	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+		udelay(2);
+		val = AT_READ_REG(hw, REG_MDIO_CTRL);
+		if (!(val & (MDIO_START | MDIO_BUSY)))
+			break;
+		wmb();
+	}
+	if (!(val & (MDIO_START | MDIO_BUSY))) {
+		*phy_data = (u16)val;
+		return 0;
+	}
+
+	return AT_ERR_PHY;
+}
+
+/*
+ * Writes a value to a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to write
+ * data - data to write to the PHY
+ */
+int atl1e_write_phy_reg(struct atl1e_hw *hw, u32 reg_addr, u16 phy_data)
+{
+	int i;
+	u32 val;
+
+	val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT |
+	       (reg_addr&MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
+	       MDIO_SUP_PREAMBLE |
+	       MDIO_START |
+	       MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+
+	AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
+	wmb();
+
+	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+		udelay(2);
+		val = AT_READ_REG(hw, REG_MDIO_CTRL);
+		if (!(val & (MDIO_START | MDIO_BUSY)))
+			break;
+		wmb();
+	}
+
+	if (!(val & (MDIO_START | MDIO_BUSY)))
+		return 0;
+
+	return AT_ERR_PHY;
+}
+
+/*
+ * atl1e_init_pcie - init PCIE module
+ */
+static void atl1e_init_pcie(struct atl1e_hw *hw)
+{
+	u32 value;
+	/* comment 2lines below to save more power when sususpend
+	   value = LTSSM_TEST_MODE_DEF;
+	   AT_WRITE_REG(hw, REG_LTSSM_TEST_MODE, value);
+	 */
+
+	/* pcie flow control mode change */
+	value = AT_READ_REG(hw, 0x1008);
+	value |= 0x8000;
+	AT_WRITE_REG(hw, 0x1008, value);
+}
+/*
+ * Configures PHY autoneg and flow control advertisement settings
+ *
+ * hw - Struct containing variables accessed by shared code
+ */
+static int atl1e_phy_setup_autoneg_adv(struct atl1e_hw *hw)
+{
+	s32 ret_val;
+	u16 mii_autoneg_adv_reg;
+	u16 mii_1000t_ctrl_reg;
+
+	if (0 != hw->mii_autoneg_adv_reg)
+		return 0;
+	/* Read the MII Auto-Neg Advertisement Register (Address 4/9). */
+	mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;
+	mii_1000t_ctrl_reg  = MII_AT001_CR_1000T_DEFAULT_CAP_MASK;
+
+	/*
+	 * Need to parse autoneg_advertised  and set up
+	 * the appropriate PHY registers.  First we will parse for
+	 * autoneg_advertised software override.  Since we can advertise
+	 * a plethora of combinations, we need to check each bit
+	 * individually.
+	 */
+
+	/*
+	 * First we clear all the 10/100 mb speed bits in the Auto-Neg
+	 * Advertisement Register (Address 4) and the 1000 mb speed bits in
+	 * the  1000Base-T control Register (Address 9).
+	 */
+	mii_autoneg_adv_reg &= ~MII_AR_SPEED_MASK;
+	mii_1000t_ctrl_reg  &= ~MII_AT001_CR_1000T_SPEED_MASK;
+
+	/*
+	 * Need to parse MediaType and setup the
+	 * appropriate PHY registers.
+	 */
+	switch (hw->media_type) {
+	case MEDIA_TYPE_AUTO_SENSOR:
+		mii_autoneg_adv_reg |= (MII_AR_10T_HD_CAPS   |
+					MII_AR_10T_FD_CAPS   |
+					MII_AR_100TX_HD_CAPS |
+					MII_AR_100TX_FD_CAPS);
+		hw->autoneg_advertised = ADVERTISE_10_HALF  |
+					 ADVERTISE_10_FULL  |
+					 ADVERTISE_100_HALF |
+					 ADVERTISE_100_FULL;
+		if (hw->nic_type == athr_l1e) {
+			mii_1000t_ctrl_reg |=
+				MII_AT001_CR_1000T_FD_CAPS;
+			hw->autoneg_advertised |= ADVERTISE_1000_FULL;
+		}
+		break;
+
+	case MEDIA_TYPE_100M_FULL:
+		mii_autoneg_adv_reg   |= MII_AR_100TX_FD_CAPS;
+		hw->autoneg_advertised = ADVERTISE_100_FULL;
+		break;
+
+	case MEDIA_TYPE_100M_HALF:
+		mii_autoneg_adv_reg   |= MII_AR_100TX_HD_CAPS;
+		hw->autoneg_advertised = ADVERTISE_100_HALF;
+		break;
+
+	case MEDIA_TYPE_10M_FULL:
+		mii_autoneg_adv_reg   |= MII_AR_10T_FD_CAPS;
+		hw->autoneg_advertised = ADVERTISE_10_FULL;
+		break;
+
+	default:
+		mii_autoneg_adv_reg   |= MII_AR_10T_HD_CAPS;
+		hw->autoneg_advertised = ADVERTISE_10_HALF;
+		break;
+	}
+
+	/* flow control fixed to enable all */
+	mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE);
+
+	hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;
+	hw->mii_1000t_ctrl_reg  = mii_1000t_ctrl_reg;
+
+	ret_val = atl1e_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);
+	if (ret_val)
+		return ret_val;
+
+	if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) {
+		ret_val = atl1e_write_phy_reg(hw, MII_AT001_CR,
+					   mii_1000t_ctrl_reg);
+		if (ret_val)
+			return ret_val;
+	}
+
+	return 0;
+}
+
+
+/*
+ * Resets the PHY and make all config validate
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * Sets bit 15 and 12 of the MII control regiser (for F001 bug)
+ */
+int atl1e_phy_commit(struct atl1e_hw *hw)
+{
+	struct atl1e_adapter *adapter = (struct atl1e_adapter *)hw->adapter;
+	struct pci_dev *pdev = adapter->pdev;
+	int ret_val;
+	u16 phy_data;
+
+	phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG;
+
+	ret_val = atl1e_write_phy_reg(hw, MII_BMCR, phy_data);
+	if (ret_val) {
+		u32 val;
+		int i;
+		/**************************************
+		 * pcie serdes link may be down !
+		 **************************************/
+		for (i = 0; i < 25; i++) {
+			msleep(1);
+			val = AT_READ_REG(hw, REG_MDIO_CTRL);
+			if (!(val & (MDIO_START | MDIO_BUSY)))
+				break;
+		}
+
+		if (0 != (val & (MDIO_START | MDIO_BUSY))) {
+			dev_err(&pdev->dev,
+				"pcie linkdown at least for 25ms\n");
+			return ret_val;
+		}
+
+		dev_err(&pdev->dev, "pcie linkup after %d ms\n", i);
+	}
+	return 0;
+}
+
+int atl1e_phy_init(struct atl1e_hw *hw)
+{
+	struct atl1e_adapter *adapter = (struct atl1e_adapter *)hw->adapter;
+	struct pci_dev *pdev = adapter->pdev;
+	s32 ret_val;
+	u16 phy_val;
+
+	if (hw->phy_configured) {
+		if (hw->re_autoneg) {
+			hw->re_autoneg = false;
+			return atl1e_restart_autoneg(hw);
+		}
+		return 0;
+	}
+
+	/* RESET GPHY Core */
+	AT_WRITE_REGW(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT);
+	msleep(2);
+	AT_WRITE_REGW(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT |
+		      GPHY_CTRL_EXT_RESET);
+	msleep(2);
+
+	/* patches */
+	/* p1. eable hibernation mode */
+	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0xB);
+	if (ret_val)
+		return ret_val;
+	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0xBC00);
+	if (ret_val)
+		return ret_val;
+	/* p2. set Class A/B for all modes */
+	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0);
+	if (ret_val)
+		return ret_val;
+	phy_val = 0x02ef;
+	/* remove Class AB */
+	/* phy_val = hw->emi_ca ? 0x02ef : 0x02df; */
+	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, phy_val);
+	if (ret_val)
+		return ret_val;
+	/* p3. 10B ??? */
+	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x12);
+	if (ret_val)
+		return ret_val;
+	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x4C04);
+	if (ret_val)
+		return ret_val;
+	/* p4. 1000T power */
+	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x4);
+	if (ret_val)
+		return ret_val;
+	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x8BBB);
+	if (ret_val)
+		return ret_val;
+
+	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x5);
+	if (ret_val)
+		return ret_val;
+	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x2C46);
+	if (ret_val)
+		return ret_val;
+
+	msleep(1);
+
+	/*Enable PHY LinkChange Interrupt */
+	ret_val = atl1e_write_phy_reg(hw, MII_INT_CTRL, 0xC00);
+	if (ret_val) {
+		dev_err(&pdev->dev, "Error enable PHY linkChange Interrupt\n");
+		return ret_val;
+	}
+	/* setup AutoNeg parameters */
+	ret_val = atl1e_phy_setup_autoneg_adv(hw);
+	if (ret_val) {
+		dev_err(&pdev->dev, "Error Setting up Auto-Negotiation\n");
+		return ret_val;
+	}
+	/* SW.Reset & En-Auto-Neg to restart Auto-Neg*/
+	dev_dbg(&pdev->dev, "Restarting Auto-Neg");
+	ret_val = atl1e_phy_commit(hw);
+	if (ret_val) {
+		dev_err(&pdev->dev, "Error Resetting the phy");
+		return ret_val;
+	}
+
+	hw->phy_configured = true;
+
+	return 0;
+}
+
+/*
+ * Reset the transmit and receive units; mask and clear all interrupts.
+ * hw - Struct containing variables accessed by shared code
+ * return : 0  or  idle status (if error)
+ */
+int atl1e_reset_hw(struct atl1e_hw *hw)
+{
+	struct atl1e_adapter *adapter = (struct atl1e_adapter *)hw->adapter;
+	struct pci_dev *pdev = adapter->pdev;
+
+	u32 idle_status_data = 0;
+	u16 pci_cfg_cmd_word = 0;
+	int timeout = 0;
+
+	/* Workaround for PCI problem when BIOS sets MMRBC incorrectly. */
+	pci_read_config_word(pdev, PCI_REG_COMMAND, &pci_cfg_cmd_word);
+	if ((pci_cfg_cmd_word & (CMD_IO_SPACE |
+				CMD_MEMORY_SPACE | CMD_BUS_MASTER))
+			!= (CMD_IO_SPACE | CMD_MEMORY_SPACE | CMD_BUS_MASTER)) {
+		pci_cfg_cmd_word |= (CMD_IO_SPACE |
+				     CMD_MEMORY_SPACE | CMD_BUS_MASTER);
+		pci_write_config_word(pdev, PCI_REG_COMMAND, pci_cfg_cmd_word);
+	}
+
+	/*
+	 * Issue Soft Reset to the MAC.  This will reset the chip's
+	 * transmit, receive, DMA.  It will not effect
+	 * the current PCI configuration.  The global reset bit is self-
+	 * clearing, and should clear within a microsecond.
+	 */
+	AT_WRITE_REG(hw, REG_MASTER_CTRL,
+			MASTER_CTRL_LED_MODE | MASTER_CTRL_SOFT_RST);
+	wmb();
+	msleep(1);
+
+	/* Wait at least 10ms for All module to be Idle */
+	for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) {
+		idle_status_data = AT_READ_REG(hw, REG_IDLE_STATUS);
+		if (idle_status_data == 0)
+			break;
+		msleep(1);
+		cpu_relax();
+	}
+
+	if (timeout >= AT_HW_MAX_IDLE_DELAY) {
+		dev_err(&pdev->dev,
+			"MAC state machine cann't be idle since"
+			" disabled for 10ms second\n");
+		return AT_ERR_TIMEOUT;
+	}
+
+	return 0;
+}
+
+
+/*
+ * Performs basic configuration of the adapter.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * Assumes that the controller has previously been reset and is in a
+ * post-reset uninitialized state. Initializes multicast table,
+ * and  Calls routines to setup link
+ * Leaves the transmit and receive units disabled and uninitialized.
+ */
+int atl1e_init_hw(struct atl1e_hw *hw)
+{
+	s32 ret_val = 0;
+
+	atl1e_init_pcie(hw);
+
+	/* Zero out the Multicast HASH table */
+	/* clear the old settings from the multicast hash table */
+	AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);
+	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);
+
+	ret_val = atl1e_phy_init(hw);
+
+	return ret_val;
+}
+
+/*
+ * Detects the current speed and duplex settings of the hardware.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * speed - Speed of the connection
+ * duplex - Duplex setting of the connection
+ */
+int atl1e_get_speed_and_duplex(struct atl1e_hw *hw, u16 *speed, u16 *duplex)
+{
+	int err;
+	u16 phy_data;
+
+	/* Read   PHY Specific Status Register (17) */
+	err = atl1e_read_phy_reg(hw, MII_AT001_PSSR, &phy_data);
+	if (err)
+		return err;
+
+	if (!(phy_data & MII_AT001_PSSR_SPD_DPLX_RESOLVED))
+		return AT_ERR_PHY_RES;
+
+	switch (phy_data & MII_AT001_PSSR_SPEED) {
+	case MII_AT001_PSSR_1000MBS:
+		*speed = SPEED_1000;
+		break;
+	case MII_AT001_PSSR_100MBS:
+		*speed = SPEED_100;
+		break;
+	case MII_AT001_PSSR_10MBS:
+		*speed = SPEED_10;
+		break;
+	default:
+		return AT_ERR_PHY_SPEED;
+		break;
+	}
+
+	if (phy_data & MII_AT001_PSSR_DPLX)
+		*duplex = FULL_DUPLEX;
+	else
+		*duplex = HALF_DUPLEX;
+
+	return 0;
+}
+
+int atl1e_restart_autoneg(struct atl1e_hw *hw)
+{
+	int err = 0;
+
+	err = atl1e_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
+	if (err)
+		return err;
+
+	if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) {
+		err = atl1e_write_phy_reg(hw, MII_AT001_CR,
+				       hw->mii_1000t_ctrl_reg);
+		if (err)
+			return err;
+	}
+
+	err = atl1e_write_phy_reg(hw, MII_BMCR,
+			MII_CR_RESET | MII_CR_AUTO_NEG_EN |
+			MII_CR_RESTART_AUTO_NEG);
+	return err;
+}
+
diff --git a/drivers/net/atl1e/atl1e_hw.h b/drivers/net/atl1e/atl1e_hw.h
new file mode 100644
index 0000000..5ea2f4d
--- /dev/null
+++ b/drivers/net/atl1e/atl1e_hw.h
@@ -0,0 +1,793 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _ATHL1E_HW_H_
+#define _ATHL1E_HW_H_
+
+#include <linux/types.h>
+#include <linux/mii.h>
+
+struct atl1e_adapter;
+struct atl1e_hw;
+
+/* function prototype */
+s32 atl1e_reset_hw(struct atl1e_hw *hw);
+s32 atl1e_read_mac_addr(struct atl1e_hw *hw);
+s32 atl1e_init_hw(struct atl1e_hw *hw);
+s32 atl1e_phy_commit(struct atl1e_hw *hw);
+s32 atl1e_get_speed_and_duplex(struct atl1e_hw *hw, u16 *speed, u16 *duplex);
+u32 atl1e_auto_get_fc(struct atl1e_adapter *adapter, u16 duplex);
+u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr);
+void atl1e_hash_set(struct atl1e_hw *hw, u32 hash_value);
+s32 atl1e_read_phy_reg(struct atl1e_hw *hw, u16 reg_addr, u16 *phy_data);
+s32 atl1e_write_phy_reg(struct atl1e_hw *hw, u32 reg_addr, u16 phy_data);
+s32 atl1e_validate_mdi_setting(struct atl1e_hw *hw);
+void atl1e_hw_set_mac_addr(struct atl1e_hw *hw);
+bool atl1e_read_eeprom(struct atl1e_hw *hw, u32 offset, u32 *p_value);
+bool atl1e_write_eeprom(struct atl1e_hw *hw, u32 offset, u32 value);
+s32 atl1e_phy_enter_power_saving(struct atl1e_hw *hw);
+s32 atl1e_phy_leave_power_saving(struct atl1e_hw *hw);
+s32 atl1e_phy_init(struct atl1e_hw *hw);
+int atl1e_check_eeprom_exist(struct atl1e_hw *hw);
+void atl1e_force_ps(struct atl1e_hw *hw);
+s32 atl1e_restart_autoneg(struct atl1e_hw *hw);
+
+/* register definition */
+#define REG_PM_CTRLSTAT             0x44
+
+#define REG_PCIE_CAP_LIST           0x58
+
+#define REG_DEVICE_CAP              0x5C
+#define     DEVICE_CAP_MAX_PAYLOAD_MASK     0x7
+#define     DEVICE_CAP_MAX_PAYLOAD_SHIFT    0
+
+#define REG_DEVICE_CTRL             0x60
+#define     DEVICE_CTRL_MAX_PAYLOAD_MASK    0x7
+#define     DEVICE_CTRL_MAX_PAYLOAD_SHIFT   5
+#define     DEVICE_CTRL_MAX_RREQ_SZ_MASK    0x7
+#define     DEVICE_CTRL_MAX_RREQ_SZ_SHIFT   12
+
+#define REG_VPD_CAP                 0x6C
+#define     VPD_CAP_ID_MASK                 0xff
+#define     VPD_CAP_ID_SHIFT                0
+#define     VPD_CAP_NEXT_PTR_MASK           0xFF
+#define     VPD_CAP_NEXT_PTR_SHIFT          8
+#define     VPD_CAP_VPD_ADDR_MASK           0x7FFF
+#define     VPD_CAP_VPD_ADDR_SHIFT          16
+#define     VPD_CAP_VPD_FLAG                0x80000000
+
+#define REG_VPD_DATA                0x70
+
+#define REG_SPI_FLASH_CTRL          0x200
+#define     SPI_FLASH_CTRL_STS_NON_RDY      0x1
+#define     SPI_FLASH_CTRL_STS_WEN          0x2
+#define     SPI_FLASH_CTRL_STS_WPEN         0x80
+#define     SPI_FLASH_CTRL_DEV_STS_MASK     0xFF
+#define     SPI_FLASH_CTRL_DEV_STS_SHIFT    0
+#define     SPI_FLASH_CTRL_INS_MASK         0x7
+#define     SPI_FLASH_CTRL_INS_SHIFT        8
+#define     SPI_FLASH_CTRL_START            0x800
+#define     SPI_FLASH_CTRL_EN_VPD           0x2000
+#define     SPI_FLASH_CTRL_LDSTART          0x8000
+#define     SPI_FLASH_CTRL_CS_HI_MASK       0x3
+#define     SPI_FLASH_CTRL_CS_HI_SHIFT      16
+#define     SPI_FLASH_CTRL_CS_HOLD_MASK     0x3
+#define     SPI_FLASH_CTRL_CS_HOLD_SHIFT    18
+#define     SPI_FLASH_CTRL_CLK_LO_MASK      0x3
+#define     SPI_FLASH_CTRL_CLK_LO_SHIFT     20
+#define     SPI_FLASH_CTRL_CLK_HI_MASK      0x3
+#define     SPI_FLASH_CTRL_CLK_HI_SHIFT     22
+#define     SPI_FLASH_CTRL_CS_SETUP_MASK    0x3
+#define     SPI_FLASH_CTRL_CS_SETUP_SHIFT   24
+#define     SPI_FLASH_CTRL_EROM_PGSZ_MASK   0x3
+#define     SPI_FLASH_CTRL_EROM_PGSZ_SHIFT  26
+#define     SPI_FLASH_CTRL_WAIT_READY       0x10000000
+
+#define REG_SPI_ADDR                0x204
+
+#define REG_SPI_DATA                0x208
+
+#define REG_SPI_FLASH_CONFIG        0x20C
+#define     SPI_FLASH_CONFIG_LD_ADDR_MASK   0xFFFFFF
+#define     SPI_FLASH_CONFIG_LD_ADDR_SHIFT  0
+#define     SPI_FLASH_CONFIG_VPD_ADDR_MASK  0x3
+#define     SPI_FLASH_CONFIG_VPD_ADDR_SHIFT 24
+#define     SPI_FLASH_CONFIG_LD_EXIST       0x4000000
+
+
+#define REG_SPI_FLASH_OP_PROGRAM    0x210
+#define REG_SPI_FLASH_OP_SC_ERASE   0x211
+#define REG_SPI_FLASH_OP_CHIP_ERASE 0x212
+#define REG_SPI_FLASH_OP_RDID       0x213
+#define REG_SPI_FLASH_OP_WREN       0x214
+#define REG_SPI_FLASH_OP_RDSR       0x215
+#define REG_SPI_FLASH_OP_WRSR       0x216
+#define REG_SPI_FLASH_OP_READ       0x217
+
+#define REG_TWSI_CTRL               0x218
+#define     TWSI_CTRL_LD_OFFSET_MASK        0xFF
+#define     TWSI_CTRL_LD_OFFSET_SHIFT       0
+#define     TWSI_CTRL_LD_SLV_ADDR_MASK      0x7
+#define     TWSI_CTRL_LD_SLV_ADDR_SHIFT     8
+#define     TWSI_CTRL_SW_LDSTART            0x800
+#define     TWSI_CTRL_HW_LDSTART            0x1000
+#define     TWSI_CTRL_SMB_SLV_ADDR_MASK     0x0x7F
+#define     TWSI_CTRL_SMB_SLV_ADDR_SHIFT    15
+#define     TWSI_CTRL_LD_EXIST              0x400000
+#define     TWSI_CTRL_READ_FREQ_SEL_MASK    0x3
+#define     TWSI_CTRL_READ_FREQ_SEL_SHIFT   23
+#define     TWSI_CTRL_FREQ_SEL_100K         0
+#define     TWSI_CTRL_FREQ_SEL_200K         1
+#define     TWSI_CTRL_FREQ_SEL_300K         2
+#define     TWSI_CTRL_FREQ_SEL_400K         3
+#define     TWSI_CTRL_SMB_SLV_ADDR
+#define     TWSI_CTRL_WRITE_FREQ_SEL_MASK   0x3
+#define     TWSI_CTRL_WRITE_FREQ_SEL_SHIFT  24
+
+
+#define REG_PCIE_DEV_MISC_CTRL      0x21C
+#define     PCIE_DEV_MISC_CTRL_EXT_PIPE     0x2
+#define     PCIE_DEV_MISC_CTRL_RETRY_BUFDIS 0x1
+#define     PCIE_DEV_MISC_CTRL_SPIROM_EXIST 0x4
+#define     PCIE_DEV_MISC_CTRL_SERDES_ENDIAN    0x8
+#define     PCIE_DEV_MISC_CTRL_SERDES_SEL_DIN   0x10
+
+#define REG_PCIE_PHYMISC	    0x1000
+#define PCIE_PHYMISC_FORCE_RCV_DET	0x4
+
+#define REG_LTSSM_TEST_MODE         0x12FC
+#define         LTSSM_TEST_MODE_DEF     0xE000
+
+/* Selene Master Control Register */
+#define REG_MASTER_CTRL             0x1400
+#define     MASTER_CTRL_SOFT_RST            0x1
+#define     MASTER_CTRL_MTIMER_EN           0x2
+#define     MASTER_CTRL_ITIMER_EN           0x4
+#define     MASTER_CTRL_MANUAL_INT          0x8
+#define     MASTER_CTRL_ITIMER2_EN          0x20
+#define     MASTER_CTRL_INT_RDCLR           0x40
+#define     MASTER_CTRL_LED_MODE	    0x200
+#define     MASTER_CTRL_REV_NUM_SHIFT       16
+#define     MASTER_CTRL_REV_NUM_MASK        0xff
+#define     MASTER_CTRL_DEV_ID_SHIFT        24
+#define     MASTER_CTRL_DEV_ID_MASK         0xff
+
+/* Timer Initial Value Register */
+#define REG_MANUAL_TIMER_INIT       0x1404
+
+
+/* IRQ ModeratorTimer Initial Value Register */
+#define REG_IRQ_MODU_TIMER_INIT     0x1408   /* w */
+#define REG_IRQ_MODU_TIMER2_INIT    0x140A   /* w */
+
+
+#define REG_GPHY_CTRL               0x140C
+#define     GPHY_CTRL_EXT_RESET         1
+#define     GPHY_CTRL_PIPE_MOD          2
+#define     GPHY_CTRL_TEST_MODE_MASK    3
+#define     GPHY_CTRL_TEST_MODE_SHIFT   2
+#define     GPHY_CTRL_BERT_START        0x10
+#define     GPHY_CTRL_GATE_25M_EN       0x20
+#define     GPHY_CTRL_LPW_EXIT          0x40
+#define     GPHY_CTRL_PHY_IDDQ          0x80
+#define     GPHY_CTRL_PHY_IDDQ_DIS      0x100
+#define     GPHY_CTRL_PCLK_SEL_DIS      0x200
+#define     GPHY_CTRL_HIB_EN            0x400
+#define     GPHY_CTRL_HIB_PULSE         0x800
+#define     GPHY_CTRL_SEL_ANA_RST       0x1000
+#define     GPHY_CTRL_PHY_PLL_ON        0x2000
+#define     GPHY_CTRL_PWDOWN_HW		0x4000
+#define     GPHY_CTRL_DEFAULT (\
+		GPHY_CTRL_PHY_PLL_ON	|\
+		GPHY_CTRL_SEL_ANA_RST	|\
+		GPHY_CTRL_HIB_PULSE	|\
+		GPHY_CTRL_HIB_EN)
+
+#define     GPHY_CTRL_PW_WOL_DIS (\
+		GPHY_CTRL_PHY_PLL_ON	|\
+		GPHY_CTRL_SEL_ANA_RST	|\
+		GPHY_CTRL_HIB_PULSE	|\
+		GPHY_CTRL_HIB_EN	|\
+		GPHY_CTRL_PWDOWN_HW	|\
+		GPHY_CTRL_PCLK_SEL_DIS	|\
+		GPHY_CTRL_PHY_IDDQ)
+
+/* IRQ Anti-Lost Timer Initial Value Register */
+#define REG_CMBDISDMA_TIMER         0x140E
+
+
+/* Block IDLE Status Register */
+#define REG_IDLE_STATUS  	0x1410
+#define     IDLE_STATUS_RXMAC       1    /* 1: RXMAC state machine is in non-IDLE state. 0: RXMAC is idling */
+#define     IDLE_STATUS_TXMAC       2    /* 1: TXMAC state machine is in non-IDLE state. 0: TXMAC is idling */
+#define     IDLE_STATUS_RXQ         4    /* 1: RXQ state machine is in non-IDLE state.   0: RXQ is idling   */
+#define     IDLE_STATUS_TXQ         8    /* 1: TXQ state machine is in non-IDLE state.   0: TXQ is idling   */
+#define     IDLE_STATUS_DMAR        0x10 /* 1: DMAR state machine is in non-IDLE state.  0: DMAR is idling  */
+#define     IDLE_STATUS_DMAW        0x20 /* 1: DMAW state machine is in non-IDLE state.  0: DMAW is idling  */
+#define     IDLE_STATUS_SMB         0x40 /* 1: SMB state machine is in non-IDLE state.   0: SMB is idling   */
+#define     IDLE_STATUS_CMB         0x80 /* 1: CMB state machine is in non-IDLE state.   0: CMB is idling   */
+
+/* MDIO Control Register */
+#define REG_MDIO_CTRL           0x1414
+#define     MDIO_DATA_MASK          0xffff  /* On MDIO write, the 16-bit control data to write to PHY MII management register */
+#define     MDIO_DATA_SHIFT         0       /* On MDIO read, the 16-bit status data that was read from the PHY MII management register*/
+#define     MDIO_REG_ADDR_MASK      0x1f    /* MDIO register address */
+#define     MDIO_REG_ADDR_SHIFT     16
+#define     MDIO_RW                 0x200000      /* 1: read, 0: write */
+#define     MDIO_SUP_PREAMBLE       0x400000      /* Suppress preamble */
+#define     MDIO_START              0x800000      /* Write 1 to initiate the MDIO master. And this bit is self cleared after one cycle*/
+#define     MDIO_CLK_SEL_SHIFT      24
+#define     MDIO_CLK_25_4           0
+#define     MDIO_CLK_25_6           2
+#define     MDIO_CLK_25_8           3
+#define     MDIO_CLK_25_10          4
+#define     MDIO_CLK_25_14          5
+#define     MDIO_CLK_25_20          6
+#define     MDIO_CLK_25_28          7
+#define     MDIO_BUSY               0x8000000
+#define     MDIO_AP_EN              0x10000000
+#define MDIO_WAIT_TIMES         10
+
+/* MII PHY Status Register */
+#define REG_PHY_STATUS           0x1418
+#define     PHY_STATUS_100M	      0x20000
+#define     PHY_STATUS_EMI_CA	      0x40000
+
+/* BIST Control and Status Register0 (for the Packet Memory) */
+#define REG_BIST0_CTRL              0x141c
+#define     BIST0_NOW                   0x1 /* 1: To trigger BIST0 logic. This bit stays high during the */
+/* BIST process and reset to zero when BIST is done */
+#define     BIST0_SRAM_FAIL             0x2 /* 1: The SRAM failure is un-repairable because it has address */
+/* decoder failure or more than 1 cell stuck-to-x failure */
+#define     BIST0_FUSE_FLAG             0x4 /* 1: Indicating one cell has been fixed */
+
+/* BIST Control and Status Register1(for the retry buffer of PCI Express) */
+#define REG_BIST1_CTRL              0x1420
+#define     BIST1_NOW                   0x1 /* 1: To trigger BIST0 logic. This bit stays high during the */
+/* BIST process and reset to zero when BIST is done */
+#define     BIST1_SRAM_FAIL             0x2 /* 1: The SRAM failure is un-repairable because it has address */
+/* decoder failure or more than 1 cell stuck-to-x failure.*/
+#define     BIST1_FUSE_FLAG             0x4
+
+/* SerDes Lock Detect Control and Status Register */
+#define REG_SERDES_LOCK             0x1424
+#define     SERDES_LOCK_DETECT          1  /* 1: SerDes lock detected . This signal comes from Analog SerDes */
+#define     SERDES_LOCK_DETECT_EN       2  /* 1: Enable SerDes Lock detect function */
+
+/* MAC Control Register  */
+#define REG_MAC_CTRL                0x1480
+#define     MAC_CTRL_TX_EN              1  /* 1: Transmit Enable */
+#define     MAC_CTRL_RX_EN              2  /* 1: Receive Enable */
+#define     MAC_CTRL_TX_FLOW            4  /* 1: Transmit Flow Control Enable */
+#define     MAC_CTRL_RX_FLOW            8  /* 1: Receive Flow Control Enable */
+#define     MAC_CTRL_LOOPBACK           0x10      /* 1: Loop back at G/MII Interface */
+#define     MAC_CTRL_DUPLX              0x20      /* 1: Full-duplex mode  0: Half-duplex mode */
+#define     MAC_CTRL_ADD_CRC            0x40      /* 1: Instruct MAC to attach CRC on all egress Ethernet frames */
+#define     MAC_CTRL_PAD                0x80      /* 1: Instruct MAC to pad short frames to 60-bytes, and then attach CRC. This bit has higher priority over CRC_EN */
+#define     MAC_CTRL_LENCHK             0x100     /* 1: Instruct MAC to check if length field matches the real packet length */
+#define     MAC_CTRL_HUGE_EN            0x200     /* 1: receive Jumbo frame enable */
+#define     MAC_CTRL_PRMLEN_SHIFT       10        /* Preamble length */
+#define     MAC_CTRL_PRMLEN_MASK        0xf
+#define     MAC_CTRL_RMV_VLAN           0x4000    /* 1: to remove VLAN Tag automatically from all receive packets */
+#define     MAC_CTRL_PROMIS_EN          0x8000    /* 1: Promiscuous Mode Enable */
+#define     MAC_CTRL_TX_PAUSE           0x10000   /* 1: transmit test pause */
+#define     MAC_CTRL_SCNT               0x20000   /* 1: shortcut slot time counter */
+#define     MAC_CTRL_SRST_TX            0x40000   /* 1: synchronized reset Transmit MAC module */
+#define     MAC_CTRL_TX_SIMURST         0x80000   /* 1: transmit simulation reset */
+#define     MAC_CTRL_SPEED_SHIFT        20        /* 10: gigabit 01:10M/100M */
+#define     MAC_CTRL_SPEED_MASK         0x300000
+#define     MAC_CTRL_SPEED_1000         2
+#define     MAC_CTRL_SPEED_10_100       1
+#define     MAC_CTRL_DBG_TX_BKPRESURE   0x400000  /* 1: transmit maximum backoff (half-duplex test bit) */
+#define     MAC_CTRL_TX_HUGE            0x800000  /* 1: transmit huge enable */
+#define     MAC_CTRL_RX_CHKSUM_EN       0x1000000 /* 1: RX checksum enable */
+#define     MAC_CTRL_MC_ALL_EN          0x2000000 /* 1: upload all multicast frame without error to system */
+#define     MAC_CTRL_BC_EN              0x4000000 /* 1: upload all broadcast frame without error to system */
+#define     MAC_CTRL_DBG                0x8000000 /* 1: upload all received frame to system (Debug Mode) */
+
+/* MAC IPG/IFG Control Register  */
+#define REG_MAC_IPG_IFG             0x1484
+#define     MAC_IPG_IFG_IPGT_SHIFT      0     /* Desired back to back inter-packet gap. The default is 96-bit time */
+#define     MAC_IPG_IFG_IPGT_MASK       0x7f
+#define     MAC_IPG_IFG_MIFG_SHIFT      8     /* Minimum number of IFG to enforce in between RX frames */
+#define     MAC_IPG_IFG_MIFG_MASK       0xff  /* Frame gap below such IFP is dropped */
+#define     MAC_IPG_IFG_IPGR1_SHIFT     16    /* 64bit Carrier-Sense window */
+#define     MAC_IPG_IFG_IPGR1_MASK      0x7f
+#define     MAC_IPG_IFG_IPGR2_SHIFT     24    /* 96-bit IPG window */
+#define     MAC_IPG_IFG_IPGR2_MASK      0x7f
+
+/* MAC STATION ADDRESS  */
+#define REG_MAC_STA_ADDR            0x1488
+
+/* Hash table for multicast address */
+#define REG_RX_HASH_TABLE           0x1490
+
+
+/* MAC Half-Duplex Control Register */
+#define REG_MAC_HALF_DUPLX_CTRL     0x1498
+#define     MAC_HALF_DUPLX_CTRL_LCOL_SHIFT   0      /* Collision Window */
+#define     MAC_HALF_DUPLX_CTRL_LCOL_MASK    0x3ff
+#define     MAC_HALF_DUPLX_CTRL_RETRY_SHIFT  12     /* Retransmission maximum, afterwards the packet will be discarded */
+#define     MAC_HALF_DUPLX_CTRL_RETRY_MASK   0xf
+#define     MAC_HALF_DUPLX_CTRL_EXC_DEF_EN   0x10000 /* 1: Allow the transmission of a packet which has been excessively deferred */
+#define     MAC_HALF_DUPLX_CTRL_NO_BACK_C    0x20000 /* 1: No back-off on collision, immediately start the retransmission */
+#define     MAC_HALF_DUPLX_CTRL_NO_BACK_P    0x40000 /* 1: No back-off on backpressure, immediately start the transmission after back pressure */
+#define     MAC_HALF_DUPLX_CTRL_ABEBE        0x80000 /* 1: Alternative Binary Exponential Back-off Enabled */
+#define     MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT  20      /* Maximum binary exponential number */
+#define     MAC_HALF_DUPLX_CTRL_ABEBT_MASK   0xf
+#define     MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT 24      /* IPG to start JAM for collision based flow control in half-duplex */
+#define     MAC_HALF_DUPLX_CTRL_JAMIPG_MASK  0xf     /* mode. In unit of 8-bit time */
+
+/* Maximum Frame Length Control Register   */
+#define REG_MTU                     0x149c
+
+/* Wake-On-Lan control register */
+#define REG_WOL_CTRL                0x14a0
+#define     WOL_PATTERN_EN                  0x00000001
+#define     WOL_PATTERN_PME_EN              0x00000002
+#define     WOL_MAGIC_EN                    0x00000004
+#define     WOL_MAGIC_PME_EN                0x00000008
+#define     WOL_LINK_CHG_EN                 0x00000010
+#define     WOL_LINK_CHG_PME_EN             0x00000020
+#define     WOL_PATTERN_ST                  0x00000100
+#define     WOL_MAGIC_ST                    0x00000200
+#define     WOL_LINKCHG_ST                  0x00000400
+#define     WOL_CLK_SWITCH_EN               0x00008000
+#define     WOL_PT0_EN                      0x00010000
+#define     WOL_PT1_EN                      0x00020000
+#define     WOL_PT2_EN                      0x00040000
+#define     WOL_PT3_EN                      0x00080000
+#define     WOL_PT4_EN                      0x00100000
+#define     WOL_PT5_EN                      0x00200000
+#define     WOL_PT6_EN                      0x00400000
+/* WOL Length ( 2 DWORD ) */
+#define REG_WOL_PATTERN_LEN         0x14a4
+#define     WOL_PT_LEN_MASK                 0x7f
+#define     WOL_PT0_LEN_SHIFT               0
+#define     WOL_PT1_LEN_SHIFT               8
+#define     WOL_PT2_LEN_SHIFT               16
+#define     WOL_PT3_LEN_SHIFT               24
+#define     WOL_PT4_LEN_SHIFT               0
+#define     WOL_PT5_LEN_SHIFT               8
+#define     WOL_PT6_LEN_SHIFT               16
+
+/* Internal SRAM Partition Register */
+#define REG_SRAM_TRD_ADDR           0x1518
+#define REG_SRAM_TRD_LEN            0x151C
+#define REG_SRAM_RXF_ADDR           0x1520
+#define REG_SRAM_RXF_LEN            0x1524
+#define REG_SRAM_TXF_ADDR           0x1528
+#define REG_SRAM_TXF_LEN            0x152C
+#define REG_SRAM_TCPH_ADDR          0x1530
+#define REG_SRAM_PKTH_ADDR          0x1532
+
+/* Load Ptr Register */
+#define REG_LOAD_PTR                0x1534  /* Software sets this bit after the initialization of the head and tail */
+
+/*
+ * addresses of all descriptors, as well as the following descriptor
+ * control register, which triggers each function block to load the head
+ * pointer to prepare for the operation. This bit is then self-cleared
+ * after one cycle.
+ */
+
+/* Descriptor Control register  */
+#define REG_RXF3_BASE_ADDR_HI           0x153C
+#define REG_DESC_BASE_ADDR_HI           0x1540
+#define REG_RXF0_BASE_ADDR_HI           0x1540 /* share with DESC BASE ADDR HI */
+#define REG_HOST_RXF0_PAGE0_LO          0x1544
+#define REG_HOST_RXF0_PAGE1_LO          0x1548
+#define REG_TPD_BASE_ADDR_LO            0x154C
+#define REG_RXF1_BASE_ADDR_HI           0x1550
+#define REG_RXF2_BASE_ADDR_HI           0x1554
+#define REG_HOST_RXFPAGE_SIZE           0x1558
+#define REG_TPD_RING_SIZE               0x155C
+/* RSS about */
+#define REG_RSS_KEY0                    0x14B0
+#define REG_RSS_KEY1                    0x14B4
+#define REG_RSS_KEY2                    0x14B8
+#define REG_RSS_KEY3                    0x14BC
+#define REG_RSS_KEY4                    0x14C0
+#define REG_RSS_KEY5                    0x14C4
+#define REG_RSS_KEY6                    0x14C8
+#define REG_RSS_KEY7                    0x14CC
+#define REG_RSS_KEY8                    0x14D0
+#define REG_RSS_KEY9                    0x14D4
+#define REG_IDT_TABLE4                  0x14E0
+#define REG_IDT_TABLE5                  0x14E4
+#define REG_IDT_TABLE6                  0x14E8
+#define REG_IDT_TABLE7                  0x14EC
+#define REG_IDT_TABLE0                  0x1560
+#define REG_IDT_TABLE1                  0x1564
+#define REG_IDT_TABLE2                  0x1568
+#define REG_IDT_TABLE3                  0x156C
+#define REG_IDT_TABLE                   REG_IDT_TABLE0
+#define REG_RSS_HASH_VALUE              0x1570
+#define REG_RSS_HASH_FLAG               0x1574
+#define REG_BASE_CPU_NUMBER             0x157C
+
+
+/* TXQ Control Register */
+#define REG_TXQ_CTRL                0x1580
+#define     TXQ_CTRL_NUM_TPD_BURST_MASK     0xF
+#define     TXQ_CTRL_NUM_TPD_BURST_SHIFT    0
+#define     TXQ_CTRL_EN                     0x20  /* 1: Enable TXQ */
+#define     TXQ_CTRL_ENH_MODE               0x40  /* Performance enhancement mode, in which up to two back-to-back DMA read commands might be dispatched. */
+#define     TXQ_CTRL_TXF_BURST_NUM_SHIFT    16    /* Number of data byte to read in a cache-aligned burst. Each SRAM entry is 8-byte in length. */
+#define     TXQ_CTRL_TXF_BURST_NUM_MASK     0xffff
+
+/* Jumbo packet Threshold for task offload */
+#define REG_TX_EARLY_TH                     0x1584 /* Jumbo frame threshold in QWORD unit. Packet greater than */
+/* JUMBO_TASK_OFFLOAD_THRESHOLD will not be task offloaded. */
+#define     TX_TX_EARLY_TH_MASK             0x7ff
+#define     TX_TX_EARLY_TH_SHIFT            0
+
+
+/* RXQ Control Register */
+#define REG_RXQ_CTRL                0x15A0
+#define         RXQ_CTRL_PBA_ALIGN_32                   0   /* rx-packet alignment */
+#define         RXQ_CTRL_PBA_ALIGN_64                   1
+#define         RXQ_CTRL_PBA_ALIGN_128                  2
+#define         RXQ_CTRL_PBA_ALIGN_256                  3
+#define         RXQ_CTRL_Q1_EN				0x10
+#define         RXQ_CTRL_Q2_EN				0x20
+#define         RXQ_CTRL_Q3_EN				0x40
+#define         RXQ_CTRL_IPV6_XSUM_VERIFY_EN		0x80
+#define         RXQ_CTRL_HASH_TLEN_SHIFT                8
+#define         RXQ_CTRL_HASH_TLEN_MASK                 0xFF
+#define         RXQ_CTRL_HASH_TYPE_IPV4                 0x10000
+#define         RXQ_CTRL_HASH_TYPE_IPV4_TCP             0x20000
+#define         RXQ_CTRL_HASH_TYPE_IPV6                 0x40000
+#define         RXQ_CTRL_HASH_TYPE_IPV6_TCP             0x80000
+#define         RXQ_CTRL_RSS_MODE_DISABLE               0
+#define         RXQ_CTRL_RSS_MODE_SQSINT                0x4000000
+#define         RXQ_CTRL_RSS_MODE_MQUESINT              0x8000000
+#define         RXQ_CTRL_RSS_MODE_MQUEMINT              0xC000000
+#define         RXQ_CTRL_NIP_QUEUE_SEL_TBL              0x10000000
+#define         RXQ_CTRL_HASH_ENABLE                    0x20000000
+#define         RXQ_CTRL_CUT_THRU_EN                    0x40000000
+#define         RXQ_CTRL_EN                             0x80000000
+
+/* Rx jumbo packet threshold and rrd  retirement timer  */
+#define REG_RXQ_JMBOSZ_RRDTIM       0x15A4
+/*
+ * Jumbo packet threshold for non-VLAN packet, in QWORD (64-bit) unit.
+ * When the packet length greater than or equal to this value, RXQ
+ * shall start cut-through forwarding of the received packet.
+ */
+#define         RXQ_JMBOSZ_TH_MASK      0x7ff
+#define         RXQ_JMBOSZ_TH_SHIFT         0  /* RRD retirement timer. Decrement by 1 after every 512ns passes*/
+#define         RXQ_JMBO_LKAH_MASK          0xf
+#define         RXQ_JMBO_LKAH_SHIFT         11
+
+/* RXF flow control register */
+#define REG_RXQ_RXF_PAUSE_THRESH    0x15A8
+#define     RXQ_RXF_PAUSE_TH_HI_SHIFT       0
+#define     RXQ_RXF_PAUSE_TH_HI_MASK        0xfff
+#define     RXQ_RXF_PAUSE_TH_LO_SHIFT       16
+#define     RXQ_RXF_PAUSE_TH_LO_MASK        0xfff
+
+
+/* DMA Engine Control Register */
+#define REG_DMA_CTRL                0x15C0
+#define     DMA_CTRL_DMAR_IN_ORDER          0x1
+#define     DMA_CTRL_DMAR_ENH_ORDER         0x2
+#define     DMA_CTRL_DMAR_OUT_ORDER         0x4
+#define     DMA_CTRL_RCB_VALUE              0x8
+#define     DMA_CTRL_DMAR_BURST_LEN_SHIFT   4
+#define     DMA_CTRL_DMAR_BURST_LEN_MASK    7
+#define     DMA_CTRL_DMAW_BURST_LEN_SHIFT   7
+#define     DMA_CTRL_DMAW_BURST_LEN_MASK    7
+#define     DMA_CTRL_DMAR_REQ_PRI           0x400
+#define     DMA_CTRL_DMAR_DLY_CNT_MASK      0x1F
+#define     DMA_CTRL_DMAR_DLY_CNT_SHIFT     11
+#define     DMA_CTRL_DMAW_DLY_CNT_MASK      0xF
+#define     DMA_CTRL_DMAW_DLY_CNT_SHIFT     16
+#define     DMA_CTRL_TXCMB_EN               0x100000
+#define     DMA_CTRL_RXCMB_EN				0x200000
+
+
+/* CMB/SMB Control Register */
+#define REG_SMB_STAT_TIMER                      0x15C4
+#define REG_TRIG_RRD_THRESH                     0x15CA
+#define REG_TRIG_TPD_THRESH                     0x15C8
+#define REG_TRIG_TXTIMER                        0x15CC
+#define REG_TRIG_RXTIMER                        0x15CE
+
+/* HOST RXF Page 1,2,3 address */
+#define REG_HOST_RXF1_PAGE0_LO                  0x15D0
+#define REG_HOST_RXF1_PAGE1_LO                  0x15D4
+#define REG_HOST_RXF2_PAGE0_LO                  0x15D8
+#define REG_HOST_RXF2_PAGE1_LO                  0x15DC
+#define REG_HOST_RXF3_PAGE0_LO                  0x15E0
+#define REG_HOST_RXF3_PAGE1_LO                  0x15E4
+
+/* Mail box */
+#define REG_MB_RXF1_RADDR                       0x15B4
+#define REG_MB_RXF2_RADDR                       0x15B8
+#define REG_MB_RXF3_RADDR                       0x15BC
+#define REG_MB_TPD_PROD_IDX                     0x15F0
+
+/* RXF-Page 0-3  PageNo & Valid bit */
+#define REG_HOST_RXF0_PAGE0_VLD     0x15F4
+#define     HOST_RXF_VALID              1
+#define     HOST_RXF_PAGENO_SHIFT       1
+#define     HOST_RXF_PAGENO_MASK        0x7F
+#define REG_HOST_RXF0_PAGE1_VLD     0x15F5
+#define REG_HOST_RXF1_PAGE0_VLD     0x15F6
+#define REG_HOST_RXF1_PAGE1_VLD     0x15F7
+#define REG_HOST_RXF2_PAGE0_VLD     0x15F8
+#define REG_HOST_RXF2_PAGE1_VLD     0x15F9
+#define REG_HOST_RXF3_PAGE0_VLD     0x15FA
+#define REG_HOST_RXF3_PAGE1_VLD     0x15FB
+
+/* Interrupt Status Register */
+#define REG_ISR    0x1600
+#define  ISR_SMB   		1
+#define  ISR_TIMER		2       /* Interrupt when Timer is counted down to zero */
+/*
+ * Software manual interrupt, for debug. Set when SW_MAN_INT_EN is set
+ * in Table 51 Selene Master Control Register (Offset 0x1400).
+ */
+#define  ISR_MANUAL         	4
+#define  ISR_HW_RXF_OV          8        /* RXF overflow interrupt */
+#define  ISR_HOST_RXF0_OV       0x10
+#define  ISR_HOST_RXF1_OV       0x20
+#define  ISR_HOST_RXF2_OV       0x40
+#define  ISR_HOST_RXF3_OV       0x80
+#define  ISR_TXF_UN             0x100
+#define  ISR_RX0_PAGE_FULL      0x200
+#define  ISR_DMAR_TO_RST        0x400
+#define  ISR_DMAW_TO_RST        0x800
+#define  ISR_GPHY               0x1000
+#define  ISR_TX_CREDIT          0x2000
+#define  ISR_GPHY_LPW           0x4000    /* GPHY low power state interrupt */
+#define  ISR_RX_PKT             0x10000   /* One packet received, triggered by RFD */
+#define  ISR_TX_PKT             0x20000   /* One packet transmitted, triggered by TPD */
+#define  ISR_TX_DMA             0x40000
+#define  ISR_RX_PKT_1           0x80000
+#define  ISR_RX_PKT_2           0x100000
+#define  ISR_RX_PKT_3           0x200000
+#define  ISR_MAC_RX             0x400000
+#define  ISR_MAC_TX             0x800000
+#define  ISR_UR_DETECTED        0x1000000
+#define  ISR_FERR_DETECTED      0x2000000
+#define  ISR_NFERR_DETECTED     0x4000000
+#define  ISR_CERR_DETECTED      0x8000000
+#define  ISR_PHY_LINKDOWN       0x10000000
+#define  ISR_DIS_INT            0x80000000
+
+
+/* Interrupt Mask Register */
+#define REG_IMR 0x1604
+
+
+#define IMR_NORMAL_MASK (\
+		ISR_SMB	        |\
+		ISR_TXF_UN      |\
+		ISR_HW_RXF_OV   |\
+		ISR_HOST_RXF0_OV|\
+		ISR_MANUAL      |\
+		ISR_GPHY        |\
+		ISR_GPHY_LPW    |\
+		ISR_DMAR_TO_RST |\
+		ISR_DMAW_TO_RST |\
+		ISR_PHY_LINKDOWN|\
+		ISR_RX_PKT      |\
+		ISR_TX_PKT)
+
+#define ISR_TX_EVENT (ISR_TXF_UN | ISR_TX_PKT)
+#define ISR_RX_EVENT (ISR_HOST_RXF0_OV | ISR_HW_RXF_OV | ISR_RX_PKT)
+
+#define REG_MAC_RX_STATUS_BIN 0x1700
+#define REG_MAC_RX_STATUS_END 0x175c
+#define REG_MAC_TX_STATUS_BIN 0x1760
+#define REG_MAC_TX_STATUS_END 0x17c0
+
+/* Hardware Offset Register */
+#define REG_HOST_RXF0_PAGEOFF 0x1800
+#define REG_TPD_CONS_IDX      0x1804
+#define REG_HOST_RXF1_PAGEOFF 0x1808
+#define REG_HOST_RXF2_PAGEOFF 0x180C
+#define REG_HOST_RXF3_PAGEOFF 0x1810
+
+/* RXF-Page 0-3 Offset DMA Address */
+#define REG_HOST_RXF0_MB0_LO  0x1820
+#define REG_HOST_RXF0_MB1_LO  0x1824
+#define REG_HOST_RXF1_MB0_LO  0x1828
+#define REG_HOST_RXF1_MB1_LO  0x182C
+#define REG_HOST_RXF2_MB0_LO  0x1830
+#define REG_HOST_RXF2_MB1_LO  0x1834
+#define REG_HOST_RXF3_MB0_LO  0x1838
+#define REG_HOST_RXF3_MB1_LO  0x183C
+
+/* Tpd CMB DMA Address */
+#define REG_HOST_TX_CMB_LO    0x1840
+#define REG_HOST_SMB_ADDR_LO  0x1844
+
+/* DEBUG ADDR */
+#define REG_DEBUG_DATA0 0x1900
+#define REG_DEBUG_DATA1 0x1904
+
+/***************************** MII definition ***************************************/
+/* PHY Common Register */
+#define MII_BMCR                        0x00
+#define MII_BMSR                        0x01
+#define MII_PHYSID1                     0x02
+#define MII_PHYSID2                     0x03
+#define MII_ADVERTISE                   0x04
+#define MII_LPA                         0x05
+#define MII_EXPANSION                   0x06
+#define MII_AT001_CR                    0x09
+#define MII_AT001_SR                    0x0A
+#define MII_AT001_ESR                   0x0F
+#define MII_AT001_PSCR                  0x10
+#define MII_AT001_PSSR                  0x11
+#define MII_INT_CTRL                    0x12
+#define MII_INT_STATUS                  0x13
+#define MII_SMARTSPEED                  0x14
+#define MII_RERRCOUNTER                 0x15
+#define MII_SREVISION                   0x16
+#define MII_RESV1                       0x17
+#define MII_LBRERROR                    0x18
+#define MII_PHYADDR                     0x19
+#define MII_RESV2                       0x1a
+#define MII_TPISTATUS                   0x1b
+#define MII_NCONFIG                     0x1c
+
+#define MII_DBG_ADDR			0x1D
+#define MII_DBG_DATA			0x1E
+
+
+/* PHY Control Register */
+#define MII_CR_SPEED_SELECT_MSB                  0x0040  /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_COLL_TEST_ENABLE                  0x0080  /* Collision test enable */
+#define MII_CR_FULL_DUPLEX                       0x0100  /* FDX =1, half duplex =0 */
+#define MII_CR_RESTART_AUTO_NEG                  0x0200  /* Restart auto negotiation */
+#define MII_CR_ISOLATE                           0x0400  /* Isolate PHY from MII */
+#define MII_CR_POWER_DOWN                        0x0800  /* Power down */
+#define MII_CR_AUTO_NEG_EN                       0x1000  /* Auto Neg Enable */
+#define MII_CR_SPEED_SELECT_LSB                  0x2000  /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_LOOPBACK                          0x4000  /* 0 = normal, 1 = loopback */
+#define MII_CR_RESET                             0x8000  /* 0 = normal, 1 = PHY reset */
+#define MII_CR_SPEED_MASK                        0x2040
+#define MII_CR_SPEED_1000                        0x0040
+#define MII_CR_SPEED_100                         0x2000
+#define MII_CR_SPEED_10                          0x0000
+
+
+/* PHY Status Register */
+#define MII_SR_EXTENDED_CAPS                     0x0001  /* Extended register capabilities */
+#define MII_SR_JABBER_DETECT                     0x0002  /* Jabber Detected */
+#define MII_SR_LINK_STATUS                       0x0004  /* Link Status 1 = link */
+#define MII_SR_AUTONEG_CAPS                      0x0008  /* Auto Neg Capable */
+#define MII_SR_REMOTE_FAULT                      0x0010  /* Remote Fault Detect */
+#define MII_SR_AUTONEG_COMPLETE                  0x0020  /* Auto Neg Complete */
+#define MII_SR_PREAMBLE_SUPPRESS                 0x0040  /* Preamble may be suppressed */
+#define MII_SR_EXTENDED_STATUS                   0x0100  /* Ext. status info in Reg 0x0F */
+#define MII_SR_100T2_HD_CAPS                     0x0200  /* 100T2 Half Duplex Capable */
+#define MII_SR_100T2_FD_CAPS                     0x0400  /* 100T2 Full Duplex Capable */
+#define MII_SR_10T_HD_CAPS                       0x0800  /* 10T   Half Duplex Capable */
+#define MII_SR_10T_FD_CAPS                       0x1000  /* 10T   Full Duplex Capable */
+#define MII_SR_100X_HD_CAPS                      0x2000  /* 100X  Half Duplex Capable */
+#define MII_SR_100X_FD_CAPS                      0x4000  /* 100X  Full Duplex Capable */
+#define MII_SR_100T4_CAPS                        0x8000  /* 100T4 Capable */
+
+/* Link partner ability register. */
+#define MII_LPA_SLCT                             0x001f  /* Same as advertise selector  */
+#define MII_LPA_10HALF                           0x0020  /* Can do 10mbps half-duplex   */
+#define MII_LPA_10FULL                           0x0040  /* Can do 10mbps full-duplex   */
+#define MII_LPA_100HALF                          0x0080  /* Can do 100mbps half-duplex  */
+#define MII_LPA_100FULL                          0x0100  /* Can do 100mbps full-duplex  */
+#define MII_LPA_100BASE4                         0x0200  /* 100BASE-T4  */
+#define MII_LPA_PAUSE                            0x0400  /* PAUSE */
+#define MII_LPA_ASYPAUSE                         0x0800  /* Asymmetrical PAUSE */
+#define MII_LPA_RFAULT                           0x2000  /* Link partner faulted        */
+#define MII_LPA_LPACK                            0x4000  /* Link partner acked us       */
+#define MII_LPA_NPAGE                            0x8000  /* Next page bit               */
+
+/* Autoneg Advertisement Register */
+#define MII_AR_SELECTOR_FIELD                   0x0001  /* indicates IEEE 802.3 CSMA/CD */
+#define MII_AR_10T_HD_CAPS                      0x0020  /* 10T   Half Duplex Capable */
+#define MII_AR_10T_FD_CAPS                      0x0040  /* 10T   Full Duplex Capable */
+#define MII_AR_100TX_HD_CAPS                    0x0080  /* 100TX Half Duplex Capable */
+#define MII_AR_100TX_FD_CAPS                    0x0100  /* 100TX Full Duplex Capable */
+#define MII_AR_100T4_CAPS                       0x0200  /* 100T4 Capable */
+#define MII_AR_PAUSE                            0x0400  /* Pause operation desired */
+#define MII_AR_ASM_DIR                          0x0800  /* Asymmetric Pause Direction bit */
+#define MII_AR_REMOTE_FAULT                     0x2000  /* Remote Fault detected */
+#define MII_AR_NEXT_PAGE                        0x8000  /* Next Page ability supported */
+#define MII_AR_SPEED_MASK                       0x01E0
+#define MII_AR_DEFAULT_CAP_MASK                 0x0DE0
+
+/* 1000BASE-T Control Register */
+#define MII_AT001_CR_1000T_HD_CAPS              0x0100  /* Advertise 1000T HD capability */
+#define MII_AT001_CR_1000T_FD_CAPS              0x0200  /* Advertise 1000T FD capability  */
+#define MII_AT001_CR_1000T_REPEATER_DTE         0x0400  /* 1=Repeater/switch device port */
+/* 0=DTE device */
+#define MII_AT001_CR_1000T_MS_VALUE             0x0800  /* 1=Configure PHY as Master */
+/* 0=Configure PHY as Slave */
+#define MII_AT001_CR_1000T_MS_ENABLE            0x1000  /* 1=Master/Slave manual config value */
+/* 0=Automatic Master/Slave config */
+#define MII_AT001_CR_1000T_TEST_MODE_NORMAL     0x0000  /* Normal Operation */
+#define MII_AT001_CR_1000T_TEST_MODE_1          0x2000  /* Transmit Waveform test */
+#define MII_AT001_CR_1000T_TEST_MODE_2          0x4000  /* Master Transmit Jitter test */
+#define MII_AT001_CR_1000T_TEST_MODE_3          0x6000  /* Slave Transmit Jitter test */
+#define MII_AT001_CR_1000T_TEST_MODE_4          0x8000  /* Transmitter Distortion test */
+#define MII_AT001_CR_1000T_SPEED_MASK           0x0300
+#define MII_AT001_CR_1000T_DEFAULT_CAP_MASK     0x0300
+
+/* 1000BASE-T Status Register */
+#define MII_AT001_SR_1000T_LP_HD_CAPS           0x0400  /* LP is 1000T HD capable */
+#define MII_AT001_SR_1000T_LP_FD_CAPS           0x0800  /* LP is 1000T FD capable */
+#define MII_AT001_SR_1000T_REMOTE_RX_STATUS     0x1000  /* Remote receiver OK */
+#define MII_AT001_SR_1000T_LOCAL_RX_STATUS      0x2000  /* Local receiver OK */
+#define MII_AT001_SR_1000T_MS_CONFIG_RES        0x4000  /* 1=Local TX is Master, 0=Slave */
+#define MII_AT001_SR_1000T_MS_CONFIG_FAULT      0x8000  /* Master/Slave config fault */
+#define MII_AT001_SR_1000T_REMOTE_RX_STATUS_SHIFT   12
+#define MII_AT001_SR_1000T_LOCAL_RX_STATUS_SHIFT    13
+
+/* Extended Status Register */
+#define MII_AT001_ESR_1000T_HD_CAPS             0x1000  /* 1000T HD capable */
+#define MII_AT001_ESR_1000T_FD_CAPS             0x2000  /* 1000T FD capable */
+#define MII_AT001_ESR_1000X_HD_CAPS             0x4000  /* 1000X HD capable */
+#define MII_AT001_ESR_1000X_FD_CAPS             0x8000  /* 1000X FD capable */
+
+/* AT001 PHY Specific Control Register */
+#define MII_AT001_PSCR_JABBER_DISABLE           0x0001  /* 1=Jabber Function disabled */
+#define MII_AT001_PSCR_POLARITY_REVERSAL        0x0002  /* 1=Polarity Reversal enabled */
+#define MII_AT001_PSCR_SQE_TEST                 0x0004  /* 1=SQE Test enabled */
+#define MII_AT001_PSCR_MAC_POWERDOWN            0x0008
+#define MII_AT001_PSCR_CLK125_DISABLE           0x0010  /* 1=CLK125 low,
+							 * 0=CLK125 toggling
+							 */
+#define MII_AT001_PSCR_MDI_MANUAL_MODE          0x0000  /* MDI Crossover Mode bits 6:5 */
+/* Manual MDI configuration */
+#define MII_AT001_PSCR_MDIX_MANUAL_MODE         0x0020  /* Manual MDIX configuration */
+#define MII_AT001_PSCR_AUTO_X_1000T             0x0040  /* 1000BASE-T: Auto crossover,
+							 *  100BASE-TX/10BASE-T:
+							 *  MDI Mode
+							 */
+#define MII_AT001_PSCR_AUTO_X_MODE              0x0060  /* Auto crossover enabled
+							 * all speeds.
+							 */
+#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE     0x0080
+/* 1=Enable Extended 10BASE-T distance
+ * (Lower 10BASE-T RX Threshold)
+ * 0=Normal 10BASE-T RX Threshold */
+#define MII_AT001_PSCR_MII_5BIT_ENABLE          0x0100
+/* 1=5-Bit interface in 100BASE-TX
+ * 0=MII interface in 100BASE-TX */
+#define MII_AT001_PSCR_SCRAMBLER_DISABLE        0x0200  /* 1=Scrambler disable */
+#define MII_AT001_PSCR_FORCE_LINK_GOOD          0x0400  /* 1=Force link good */
+#define MII_AT001_PSCR_ASSERT_CRS_ON_TX         0x0800  /* 1=Assert CRS on Transmit */
+#define MII_AT001_PSCR_POLARITY_REVERSAL_SHIFT    1
+#define MII_AT001_PSCR_AUTO_X_MODE_SHIFT          5
+#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7
+/* AT001 PHY Specific Status Register */
+#define MII_AT001_PSSR_SPD_DPLX_RESOLVED        0x0800  /* 1=Speed & Duplex resolved */
+#define MII_AT001_PSSR_DPLX                     0x2000  /* 1=Duplex 0=Half Duplex */
+#define MII_AT001_PSSR_SPEED                    0xC000  /* Speed, bits 14:15 */
+#define MII_AT001_PSSR_10MBS                    0x0000  /* 00=10Mbs */
+#define MII_AT001_PSSR_100MBS                   0x4000  /* 01=100Mbs */
+#define MII_AT001_PSSR_1000MBS                  0x8000  /* 10=1000Mbs */
+
+#endif /*_ATHL1E_HW_H_*/
diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c
new file mode 100644
index 0000000..35264c2
--- /dev/null
+++ b/drivers/net/atl1e/atl1e_main.c
@@ -0,0 +1,2599 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  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 "atl1e.h"
+
+#define DRV_VERSION "1.0.0.7-NAPI"
+
+char atl1e_driver_name[] = "ATL1E";
+char atl1e_driver_version[] = DRV_VERSION;
+#define PCI_DEVICE_ID_ATTANSIC_L1E      0x1026
+/*
+ * atl1e_pci_tbl - PCI Device ID Table
+ *
+ * Wildcard entries (PCI_ANY_ID) should come last
+ * Last entry must be all 0s
+ *
+ * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
+ *   Class, Class Mask, private data (not used) }
+ */
+static struct pci_device_id atl1e_pci_tbl[] = {
+	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1E)},
+	/* required last entry */
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, atl1e_pci_tbl);
+
+MODULE_AUTHOR("Atheros Corporation, <xiong.huang@atheros.com>, Jie Yang <jie.yang@atheros.com>");
+MODULE_DESCRIPTION("Atheros 1000M Ethernet Network Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+static inline void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter);
+
+static const u16
+atl1e_rx_page_vld_regs[AT_MAX_RECEIVE_QUEUE][AT_PAGE_NUM_PER_QUEUE] =
+{
+	{REG_HOST_RXF0_PAGE0_VLD, REG_HOST_RXF0_PAGE1_VLD},
+	{REG_HOST_RXF1_PAGE0_VLD, REG_HOST_RXF1_PAGE1_VLD},
+	{REG_HOST_RXF2_PAGE0_VLD, REG_HOST_RXF2_PAGE1_VLD},
+	{REG_HOST_RXF3_PAGE0_VLD, REG_HOST_RXF3_PAGE1_VLD}
+};
+
+static const u16 atl1e_rx_page_hi_addr_regs[AT_MAX_RECEIVE_QUEUE] =
+{
+	REG_RXF0_BASE_ADDR_HI,
+	REG_RXF1_BASE_ADDR_HI,
+	REG_RXF2_BASE_ADDR_HI,
+	REG_RXF3_BASE_ADDR_HI
+};
+
+static const u16
+atl1e_rx_page_lo_addr_regs[AT_MAX_RECEIVE_QUEUE][AT_PAGE_NUM_PER_QUEUE] =
+{
+	{REG_HOST_RXF0_PAGE0_LO, REG_HOST_RXF0_PAGE1_LO},
+	{REG_HOST_RXF1_PAGE0_LO, REG_HOST_RXF1_PAGE1_LO},
+	{REG_HOST_RXF2_PAGE0_LO, REG_HOST_RXF2_PAGE1_LO},
+	{REG_HOST_RXF3_PAGE0_LO, REG_HOST_RXF3_PAGE1_LO}
+};
+
+static const u16
+atl1e_rx_page_write_offset_regs[AT_MAX_RECEIVE_QUEUE][AT_PAGE_NUM_PER_QUEUE] =
+{
+	{REG_HOST_RXF0_MB0_LO,  REG_HOST_RXF0_MB1_LO},
+	{REG_HOST_RXF1_MB0_LO,  REG_HOST_RXF1_MB1_LO},
+	{REG_HOST_RXF2_MB0_LO,  REG_HOST_RXF2_MB1_LO},
+	{REG_HOST_RXF3_MB0_LO,  REG_HOST_RXF3_MB1_LO}
+};
+
+static const u16 atl1e_pay_load_size[] = {
+	128, 256, 512, 1024, 2048, 4096,
+};
+
+/*
+ * atl1e_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ */
+static inline void atl1e_irq_enable(struct atl1e_adapter *adapter)
+{
+	if (likely(atomic_dec_and_test(&adapter->irq_sem))) {
+		AT_WRITE_REG(&adapter->hw, REG_ISR, 0);
+		AT_WRITE_REG(&adapter->hw, REG_IMR, IMR_NORMAL_MASK);
+		AT_WRITE_FLUSH(&adapter->hw);
+	}
+}
+
+/*
+ * atl1e_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ */
+static inline void atl1e_irq_disable(struct atl1e_adapter *adapter)
+{
+	atomic_inc(&adapter->irq_sem);
+	AT_WRITE_REG(&adapter->hw, REG_IMR, 0);
+	AT_WRITE_FLUSH(&adapter->hw);
+	synchronize_irq(adapter->pdev->irq);
+}
+
+/*
+ * atl1e_irq_reset - reset interrupt confiure on the NIC
+ * @adapter: board private structure
+ */
+static inline void atl1e_irq_reset(struct atl1e_adapter *adapter)
+{
+	atomic_set(&adapter->irq_sem, 0);
+	AT_WRITE_REG(&adapter->hw, REG_ISR, 0);
+	AT_WRITE_REG(&adapter->hw, REG_IMR, 0);
+	AT_WRITE_FLUSH(&adapter->hw);
+}
+
+/*
+ * atl1e_phy_config - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
+ */
+static void atl1e_phy_config(unsigned long data)
+{
+	struct atl1e_adapter *adapter = (struct atl1e_adapter *) data;
+	struct atl1e_hw *hw = &adapter->hw;
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->mdio_lock, flags);
+	atl1e_restart_autoneg(hw);
+	spin_unlock_irqrestore(&adapter->mdio_lock, flags);
+}
+
+void atl1e_reinit_locked(struct atl1e_adapter *adapter)
+{
+
+	WARN_ON(in_interrupt());
+	while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
+		msleep(1);
+	atl1e_down(adapter);
+	atl1e_up(adapter);
+	clear_bit(__AT_RESETTING, &adapter->flags);
+}
+
+static void atl1e_reset_task(struct work_struct *work)
+{
+	struct atl1e_adapter *adapter;
+	adapter = container_of(work, struct atl1e_adapter, reset_task);
+
+	atl1e_reinit_locked(adapter);
+}
+
+static int atl1e_check_link(struct atl1e_adapter *adapter)
+{
+	struct atl1e_hw *hw = &adapter->hw;
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev    *pdev   = adapter->pdev;
+	int err = 0;
+	u16 speed, duplex, phy_data;
+
+	/* MII_BMSR must read twise */
+	atl1e_read_phy_reg(hw, MII_BMSR, &phy_data);
+	atl1e_read_phy_reg(hw, MII_BMSR, &phy_data);
+	if ((phy_data & BMSR_LSTATUS) == 0) {
+		/* link down */
+		if (netif_carrier_ok(netdev)) { /* old link state: Up */
+			u32 value;
+			/* disable rx */
+			value = AT_READ_REG(hw, REG_MAC_CTRL);
+			value &= ~MAC_CTRL_RX_EN;
+			AT_WRITE_REG(hw, REG_MAC_CTRL, value);
+			adapter->link_speed = SPEED_0;
+			netif_carrier_off(netdev);
+			netif_stop_queue(netdev);
+		}
+	} else {
+		/* Link Up */
+		err = atl1e_get_speed_and_duplex(hw, &speed, &duplex);
+		if (unlikely(err))
+			return err;
+
+		/* link result is our setting */
+		if (adapter->link_speed != speed ||
+		    adapter->link_duplex != duplex) {
+			adapter->link_speed  = speed;
+			adapter->link_duplex = duplex;
+			atl1e_setup_mac_ctrl(adapter);
+			dev_info(&pdev->dev,
+				"%s: %s NIC Link is Up<%d Mbps %s>\n",
+				atl1e_driver_name, netdev->name,
+				adapter->link_speed,
+				adapter->link_duplex == FULL_DUPLEX ?
+				"Full Duplex" : "Half Duplex");
+		}
+
+		if (!netif_carrier_ok(netdev)) {
+			/* Link down -> Up */
+			netif_carrier_on(netdev);
+			netif_wake_queue(netdev);
+		}
+	}
+	return 0;
+}
+
+/*
+ * atl1e_link_chg_task - deal with link change event Out of interrupt context
+ * @netdev: network interface device structure
+ */
+static void atl1e_link_chg_task(struct work_struct *work)
+{
+	struct atl1e_adapter *adapter;
+	unsigned long flags;
+
+	adapter = container_of(work, struct atl1e_adapter, link_chg_task);
+	spin_lock_irqsave(&adapter->mdio_lock, flags);
+	atl1e_check_link(adapter);
+	spin_unlock_irqrestore(&adapter->mdio_lock, flags);
+}
+
+static void atl1e_link_chg_event(struct atl1e_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev    *pdev   = adapter->pdev;
+	u16 phy_data = 0;
+	u16 link_up = 0;
+
+	spin_lock(&adapter->mdio_lock);
+	atl1e_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+	atl1e_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+	spin_unlock(&adapter->mdio_lock);
+	link_up = phy_data & BMSR_LSTATUS;
+	/* notify upper layer link down ASAP */
+	if (!link_up) {
+		if (netif_carrier_ok(netdev)) {
+			/* old link state: Up */
+			dev_info(&pdev->dev, "%s: %s NIC Link is Down\n",
+					atl1e_driver_name, netdev->name);
+			adapter->link_speed = SPEED_0;
+			netif_stop_queue(netdev);
+		}
+	}
+	schedule_work(&adapter->link_chg_task);
+}
+
+static void atl1e_del_timer(struct atl1e_adapter *adapter)
+{
+	del_timer_sync(&adapter->phy_config_timer);
+}
+
+static void atl1e_cancel_work(struct atl1e_adapter *adapter)
+{
+	cancel_work_sync(&adapter->reset_task);
+	cancel_work_sync(&adapter->link_chg_task);
+}
+
+/*
+ * atl1e_tx_timeout - Respond to a Tx Hang
+ * @netdev: network interface device structure
+ */
+static void atl1e_tx_timeout(struct net_device *netdev)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+	/* Do the reset outside of interrupt context */
+	schedule_work(&adapter->reset_task);
+}
+
+/*
+ * atl1e_set_multi - Multicast and Promiscuous mode set
+ * @netdev: network interface device structure
+ *
+ * The set_multi entry point is called whenever the multicast address
+ * list or the network interface flags are updated.  This routine is
+ * responsible for configuring the hardware for proper multicast,
+ * promiscuous mode, and all-multi behavior.
+ */
+static void atl1e_set_multi(struct net_device *netdev)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	struct atl1e_hw *hw = &adapter->hw;
+	struct dev_mc_list *mc_ptr;
+	u32 mac_ctrl_data = 0;
+	u32 hash_value;
+
+	/* Check for Promiscuous and All Multicast modes */
+	mac_ctrl_data = AT_READ_REG(hw, REG_MAC_CTRL);
+
+	if (netdev->flags & IFF_PROMISC) {
+		mac_ctrl_data |= MAC_CTRL_PROMIS_EN;
+	} else if (netdev->flags & IFF_ALLMULTI) {
+		mac_ctrl_data |= MAC_CTRL_MC_ALL_EN;
+		mac_ctrl_data &= ~MAC_CTRL_PROMIS_EN;
+	} else {
+		mac_ctrl_data &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
+	}
+
+	AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
+
+	/* clear the old settings from the multicast hash table */
+	AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);
+	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);
+
+	/* comoute mc addresses' hash value ,and put it into hash table */
+	for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
+		hash_value = atl1e_hash_mc_addr(hw, mc_ptr->dmi_addr);
+		atl1e_hash_set(hw, hash_value);
+	}
+}
+
+static void atl1e_vlan_rx_register(struct net_device *netdev,
+				   struct vlan_group *grp)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	struct pci_dev *pdev = adapter->pdev;
+	u32 mac_ctrl_data = 0;
+
+	dev_dbg(&pdev->dev, "atl1e_vlan_rx_register\n");
+
+	atl1e_irq_disable(adapter);
+
+	adapter->vlgrp = grp;
+	mac_ctrl_data = AT_READ_REG(&adapter->hw, REG_MAC_CTRL);
+
+	if (grp) {
+		/* enable VLAN tag insert/strip */
+		mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
+	} else {
+		/* disable VLAN tag insert/strip */
+		mac_ctrl_data &= ~MAC_CTRL_RMV_VLAN;
+	}
+
+	AT_WRITE_REG(&adapter->hw, REG_MAC_CTRL, mac_ctrl_data);
+	atl1e_irq_enable(adapter);
+}
+
+static void atl1e_restore_vlan(struct atl1e_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+
+	dev_dbg(&pdev->dev, "atl1e_restore_vlan !");
+	atl1e_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+}
+/*
+ * atl1e_set_mac - Change the Ethernet Address of the NIC
+ * @netdev: network interface device structure
+ * @p: pointer to an address structure
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1e_set_mac_addr(struct net_device *netdev, void *p)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	struct sockaddr *addr = p;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	if (netif_running(netdev))
+		return -EBUSY;
+
+	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+	memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
+
+	atl1e_hw_set_mac_addr(&adapter->hw);
+
+	return 0;
+}
+
+/*
+ * atl1e_change_mtu - Change the Maximum Transfer Unit
+ * @netdev: network interface device structure
+ * @new_mtu: new value for maximum frame size
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1e_change_mtu(struct net_device *netdev, int new_mtu)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	int old_mtu   = netdev->mtu;
+	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
+
+	if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
+			(max_frame > MAX_JUMBO_FRAME_SIZE)) {
+		dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
+		return -EINVAL;
+	}
+	/* set MTU */
+	if (old_mtu != new_mtu && netif_running(netdev)) {
+		while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
+			msleep(1);
+		netdev->mtu = new_mtu;
+		adapter->hw.max_frame_size = new_mtu;
+		adapter->hw.rx_jumbo_th = (max_frame + 7) >> 3;
+		atl1e_down(adapter);
+		atl1e_up(adapter);
+		clear_bit(__AT_RESETTING, &adapter->flags);
+	}
+	return 0;
+}
+
+/*
+ *  caller should hold mdio_lock
+ */
+static int atl1e_mdio_read(struct net_device *netdev, int phy_id, int reg_num)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	u16 result;
+
+	atl1e_read_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, &result);
+	return result;
+}
+
+static void atl1e_mdio_write(struct net_device *netdev, int phy_id,
+			     int reg_num, int val)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+	atl1e_write_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, val);
+}
+
+/*
+ * atl1e_mii_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1e_mii_ioctl(struct net_device *netdev,
+			   struct ifreq *ifr, int cmd)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	struct pci_dev *pdev = adapter->pdev;
+	struct mii_ioctl_data *data = if_mii(ifr);
+	unsigned long flags;
+	int retval = 0;
+
+	if (!netif_running(netdev))
+		return -EINVAL;
+
+	spin_lock_irqsave(&adapter->mdio_lock, flags);
+	switch (cmd) {
+	case SIOCGMIIPHY:
+		data->phy_id = 0;
+		break;
+
+	case SIOCGMIIREG:
+		if (!capable(CAP_NET_ADMIN)) {
+			retval = -EPERM;
+			goto out;
+		}
+		if (atl1e_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
+				    &data->val_out)) {
+			retval = -EIO;
+			goto out;
+		}
+		break;
+
+	case SIOCSMIIREG:
+		if (!capable(CAP_NET_ADMIN)) {
+			retval = -EPERM;
+			goto out;
+		}
+		if (data->reg_num & ~(0x1F)) {
+			retval = -EFAULT;
+			goto out;
+		}
+
+		dev_dbg(&pdev->dev, "<atl1e_mii_ioctl> write %x %x",
+				data->reg_num, data->val_in);
+		if (atl1e_write_phy_reg(&adapter->hw,
+				     data->reg_num, data->val_in)) {
+			retval = -EIO;
+			goto out;
+		}
+		break;
+
+	default:
+		retval = -EOPNOTSUPP;
+		break;
+	}
+out:
+	spin_unlock_irqrestore(&adapter->mdio_lock, flags);
+	return retval;
+
+}
+
+/*
+ * atl1e_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1e_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	switch (cmd) {
+	case SIOCGMIIPHY:
+	case SIOCGMIIREG:
+	case SIOCSMIIREG:
+		return atl1e_mii_ioctl(netdev, ifr, cmd);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static void atl1e_setup_pcicmd(struct pci_dev *pdev)
+{
+	u16 cmd;
+
+	pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+	cmd &= ~(PCI_COMMAND_INTX_DISABLE | PCI_COMMAND_IO);
+	cmd |=  (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+	pci_write_config_word(pdev, PCI_COMMAND, cmd);
+
+	/*
+	 * some motherboards BIOS(PXE/EFI) driver may set PME
+	 * while they transfer control to OS (Windows/Linux)
+	 * so we should clear this bit before NIC work normally
+	 */
+	pci_write_config_dword(pdev, REG_PM_CTRLSTAT, 0);
+	msleep(1);
+}
+
+/*
+ * atl1e_alloc_queues - Allocate memory for all rings
+ * @adapter: board private structure to initialize
+ *
+ */
+static int __devinit atl1e_alloc_queues(struct atl1e_adapter *adapter)
+{
+	return 0;
+}
+
+/*
+ * atl1e_sw_init - Initialize general software structures (struct atl1e_adapter)
+ * @adapter: board private structure to initialize
+ *
+ * atl1e_sw_init initializes the Adapter private data structure.
+ * Fields are initialized based on PCI device information and
+ * OS network device settings (MTU size).
+ */
+static int __devinit atl1e_sw_init(struct atl1e_adapter *adapter)
+{
+	struct atl1e_hw *hw   = &adapter->hw;
+	struct pci_dev	*pdev = adapter->pdev;
+	u32 phy_status_data = 0;
+
+	adapter->wol = 0;
+	adapter->link_speed = SPEED_0;   /* hardware init */
+	adapter->link_duplex = FULL_DUPLEX;
+	adapter->num_rx_queues = 1;
+
+	/* PCI config space info */
+	hw->vendor_id = pdev->vendor;
+	hw->device_id = pdev->device;
+	hw->subsystem_vendor_id = pdev->subsystem_vendor;
+	hw->subsystem_id = pdev->subsystem_device;
+
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
+	pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
+
+	phy_status_data = AT_READ_REG(hw, REG_PHY_STATUS);
+	/* nic type */
+	if (hw->revision_id >= 0xF0) {
+		hw->nic_type = athr_l2e_revB;
+	} else {
+		if (phy_status_data & PHY_STATUS_100M)
+			hw->nic_type = athr_l1e;
+		else
+			hw->nic_type = athr_l2e_revA;
+	}
+
+	phy_status_data = AT_READ_REG(hw, REG_PHY_STATUS);
+
+	if (phy_status_data & PHY_STATUS_EMI_CA)
+		hw->emi_ca = true;
+	else
+		hw->emi_ca = false;
+
+	hw->phy_configured = false;
+	hw->preamble_len = 7;
+	hw->max_frame_size = adapter->netdev->mtu;
+	hw->rx_jumbo_th = (hw->max_frame_size + ETH_HLEN +
+				VLAN_HLEN + ETH_FCS_LEN + 7) >> 3;
+
+	hw->rrs_type = atl1e_rrs_disable;
+	hw->indirect_tab = 0;
+	hw->base_cpu = 0;
+
+	/* need confirm */
+
+	hw->ict = 50000;                 /* 100ms */
+	hw->smb_timer = 200000;          /* 200ms  */
+	hw->tpd_burst = 5;
+	hw->rrd_thresh = 1;
+	hw->tpd_thresh = adapter->tx_ring.count / 2;
+	hw->rx_count_down = 4;  /* 2us resolution */
+	hw->tx_count_down = hw->imt * 4 / 3;
+	hw->dmar_block = atl1e_dma_req_1024;
+	hw->dmaw_block = atl1e_dma_req_1024;
+	hw->dmar_dly_cnt = 15;
+	hw->dmaw_dly_cnt = 4;
+
+	if (atl1e_alloc_queues(adapter)) {
+		dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
+		return -ENOMEM;
+	}
+
+	atomic_set(&adapter->irq_sem, 1);
+	spin_lock_init(&adapter->mdio_lock);
+	spin_lock_init(&adapter->tx_lock);
+
+	set_bit(__AT_DOWN, &adapter->flags);
+
+	return 0;
+}
+
+/*
+ * atl1e_clean_tx_ring - Free Tx-skb
+ * @adapter: board private structure
+ */
+static void atl1e_clean_tx_ring(struct atl1e_adapter *adapter)
+{
+	struct atl1e_tx_ring *tx_ring = (struct atl1e_tx_ring *)
+				&adapter->tx_ring;
+	struct atl1e_tx_buffer *tx_buffer = NULL;
+	struct pci_dev *pdev = adapter->pdev;
+	u16 index, ring_count;
+
+	if (tx_ring->desc == NULL || tx_ring->tx_buffer == NULL)
+		return;
+
+	ring_count = tx_ring->count;
+	/* first unmmap dma */
+	for (index = 0; index < ring_count; index++) {
+		tx_buffer = &tx_ring->tx_buffer[index];
+		if (tx_buffer->dma) {
+			pci_unmap_page(pdev, tx_buffer->dma,
+					tx_buffer->length, PCI_DMA_TODEVICE);
+			tx_buffer->dma = 0;
+		}
+	}
+	/* second free skb */
+	for (index = 0; index < ring_count; index++) {
+		tx_buffer = &tx_ring->tx_buffer[index];
+		if (tx_buffer->skb) {
+			dev_kfree_skb_any(tx_buffer->skb);
+			tx_buffer->skb = NULL;
+		}
+	}
+	/* Zero out Tx-buffers */
+	memset(tx_ring->desc, 0, sizeof(struct atl1e_tpd_desc) *
+				ring_count);
+	memset(tx_ring->tx_buffer, 0, sizeof(struct atl1e_tx_buffer) *
+				ring_count);
+}
+
+/*
+ * atl1e_clean_rx_ring - Free rx-reservation skbs
+ * @adapter: board private structure
+ */
+static void atl1e_clean_rx_ring(struct atl1e_adapter *adapter)
+{
+	struct atl1e_rx_ring *rx_ring =
+		(struct atl1e_rx_ring *)&adapter->rx_ring;
+	struct atl1e_rx_page_desc *rx_page_desc = rx_ring->rx_page_desc;
+	u16 i, j;
+
+
+	if (adapter->ring_vir_addr == NULL)
+		return;
+	/* Zero out the descriptor ring */
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+			if (rx_page_desc[i].rx_page[j].addr != NULL) {
+				memset(rx_page_desc[i].rx_page[j].addr, 0,
+						rx_ring->real_page_size);
+			}
+		}
+	}
+}
+
+static void atl1e_cal_ring_size(struct atl1e_adapter *adapter, u32 *ring_size)
+{
+	*ring_size = ((u32)(adapter->tx_ring.count *
+		     sizeof(struct atl1e_tpd_desc) + 7
+			/* tx ring, qword align */
+		     + adapter->rx_ring.real_page_size * AT_PAGE_NUM_PER_QUEUE *
+			adapter->num_rx_queues + 31
+			/* rx ring,  32 bytes align */
+		     + (1 + AT_PAGE_NUM_PER_QUEUE * adapter->num_rx_queues) *
+			sizeof(u32) + 3));
+			/* tx, rx cmd, dword align   */
+}
+
+static void atl1e_init_ring_resources(struct atl1e_adapter *adapter)
+{
+	struct atl1e_tx_ring *tx_ring = NULL;
+	struct atl1e_rx_ring *rx_ring = NULL;
+
+	tx_ring = &adapter->tx_ring;
+	rx_ring = &adapter->rx_ring;
+
+	rx_ring->real_page_size = adapter->rx_ring.page_size
+				 + adapter->hw.max_frame_size
+				 + ETH_HLEN + VLAN_HLEN
+				 + ETH_FCS_LEN;
+	rx_ring->real_page_size = roundup(rx_ring->real_page_size, 32);
+	atl1e_cal_ring_size(adapter, &adapter->ring_size);
+
+	adapter->ring_vir_addr = NULL;
+	adapter->rx_ring.desc = NULL;
+	rwlock_init(&adapter->tx_ring.tx_lock);
+
+	return;
+}
+
+/*
+ * Read / Write Ptr Initialize:
+ */
+static void atl1e_init_ring_ptrs(struct atl1e_adapter *adapter)
+{
+	struct atl1e_tx_ring *tx_ring = NULL;
+	struct atl1e_rx_ring *rx_ring = NULL;
+	struct atl1e_rx_page_desc *rx_page_desc = NULL;
+	int i, j;
+
+	tx_ring = &adapter->tx_ring;
+	rx_ring = &adapter->rx_ring;
+	rx_page_desc = rx_ring->rx_page_desc;
+
+	tx_ring->next_to_use = 0;
+	atomic_set(&tx_ring->next_to_clean, 0);
+
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		rx_page_desc[i].rx_using  = 0;
+		rx_page_desc[i].rx_nxseq = 0;
+		for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+			*rx_page_desc[i].rx_page[j].write_offset_addr = 0;
+			rx_page_desc[i].rx_page[j].read_offset = 0;
+		}
+	}
+}
+
+/*
+ * atl1e_free_ring_resources - Free Tx / RX descriptor Resources
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ */
+static void atl1e_free_ring_resources(struct atl1e_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+
+	atl1e_clean_tx_ring(adapter);
+	atl1e_clean_rx_ring(adapter);
+
+	if (adapter->ring_vir_addr) {
+		pci_free_consistent(pdev, adapter->ring_size,
+				adapter->ring_vir_addr, adapter->ring_dma);
+		adapter->ring_vir_addr = NULL;
+	}
+
+	if (adapter->tx_ring.tx_buffer) {
+		kfree(adapter->tx_ring.tx_buffer);
+		adapter->tx_ring.tx_buffer = NULL;
+	}
+}
+
+/*
+ * atl1e_setup_mem_resources - allocate Tx / RX descriptor resources
+ * @adapter: board private structure
+ *
+ * Return 0 on success, negative on failure
+ */
+static int atl1e_setup_ring_resources(struct atl1e_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	struct atl1e_tx_ring *tx_ring;
+	struct atl1e_rx_ring *rx_ring;
+	struct atl1e_rx_page_desc  *rx_page_desc;
+	int size, i, j;
+	u32 offset = 0;
+	int err = 0;
+
+	if (adapter->ring_vir_addr != NULL)
+		return 0; /* alloced already */
+
+	tx_ring = &adapter->tx_ring;
+	rx_ring = &adapter->rx_ring;
+
+	/* real ring DMA buffer */
+
+	size = adapter->ring_size;
+	adapter->ring_vir_addr = pci_alloc_consistent(pdev,
+			adapter->ring_size, &adapter->ring_dma);
+
+	if (adapter->ring_vir_addr == NULL) {
+		dev_err(&pdev->dev, "pci_alloc_consistent failed, "
+				    "size = D%d", size);
+		return -ENOMEM;
+	}
+
+	memset(adapter->ring_vir_addr, 0, adapter->ring_size);
+
+	rx_page_desc = rx_ring->rx_page_desc;
+
+	/* Init TPD Ring */
+	tx_ring->dma = roundup(adapter->ring_dma, 8);
+	offset = tx_ring->dma - adapter->ring_dma;
+	tx_ring->desc = (struct atl1e_tpd_desc *)
+			(adapter->ring_vir_addr + offset);
+	size = sizeof(struct atl1e_tx_buffer) * (tx_ring->count);
+	tx_ring->tx_buffer = kzalloc(size, GFP_KERNEL);
+	if (tx_ring->tx_buffer == NULL) {
+		dev_err(&pdev->dev, "kzalloc failed , size = D%d", size);
+		err = -ENOMEM;
+		goto failed;
+	}
+
+	/* Init RXF-Pages */
+	offset += (sizeof(struct atl1e_tpd_desc) * tx_ring->count);
+	offset = roundup(offset, 32);
+
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+			rx_page_desc[i].rx_page[j].dma =
+				adapter->ring_dma + offset;
+			rx_page_desc[i].rx_page[j].addr =
+				adapter->ring_vir_addr + offset;
+			offset += rx_ring->real_page_size;
+		}
+	}
+
+	/* Init CMB dma address */
+	tx_ring->cmb_dma = adapter->ring_dma + offset;
+	tx_ring->cmb     = (u32 *)(adapter->ring_vir_addr + offset);
+	offset += sizeof(u32);
+
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+			rx_page_desc[i].rx_page[j].write_offset_dma =
+				adapter->ring_dma + offset;
+			rx_page_desc[i].rx_page[j].write_offset_addr =
+				adapter->ring_vir_addr + offset;
+			offset += sizeof(u32);
+		}
+	}
+
+	if (unlikely(offset > adapter->ring_size)) {
+		dev_err(&pdev->dev, "offset(%d) > ring size(%d) !!\n",
+				offset, adapter->ring_size);
+		err = -1;
+		goto failed;
+	}
+
+	return 0;
+failed:
+	if (adapter->ring_vir_addr != NULL) {
+		pci_free_consistent(pdev, adapter->ring_size,
+				adapter->ring_vir_addr, adapter->ring_dma);
+		adapter->ring_vir_addr = NULL;
+	}
+	return err;
+}
+
+static inline void atl1e_configure_des_ring(const struct atl1e_adapter *adapter)
+{
+
+	struct atl1e_hw *hw = (struct atl1e_hw *)&adapter->hw;
+	struct atl1e_rx_ring *rx_ring =
+			(struct atl1e_rx_ring *)&adapter->rx_ring;
+	struct atl1e_tx_ring *tx_ring =
+			(struct atl1e_tx_ring *)&adapter->tx_ring;
+	struct atl1e_rx_page_desc *rx_page_desc = NULL;
+	int i, j;
+
+	AT_WRITE_REG(hw, REG_DESC_BASE_ADDR_HI,
+			(u32)((adapter->ring_dma & AT_DMA_HI_ADDR_MASK) >> 32));
+	AT_WRITE_REG(hw, REG_TPD_BASE_ADDR_LO,
+			(u32)((tx_ring->dma) & AT_DMA_LO_ADDR_MASK));
+	AT_WRITE_REG(hw, REG_TPD_RING_SIZE, (u16)(tx_ring->count));
+	AT_WRITE_REG(hw, REG_HOST_TX_CMB_LO,
+			(u32)((tx_ring->cmb_dma) & AT_DMA_LO_ADDR_MASK));
+
+	rx_page_desc = rx_ring->rx_page_desc;
+	/* RXF Page Physical address / Page Length */
+	for (i = 0; i < AT_MAX_RECEIVE_QUEUE; i++) {
+		AT_WRITE_REG(hw, atl1e_rx_page_hi_addr_regs[i],
+				 (u32)((adapter->ring_dma &
+				 AT_DMA_HI_ADDR_MASK) >> 32));
+		for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) {
+			u32 page_phy_addr;
+			u32 offset_phy_addr;
+
+			page_phy_addr = rx_page_desc[i].rx_page[j].dma;
+			offset_phy_addr =
+				   rx_page_desc[i].rx_page[j].write_offset_dma;
+
+			AT_WRITE_REG(hw, atl1e_rx_page_lo_addr_regs[i][j],
+					page_phy_addr & AT_DMA_LO_ADDR_MASK);
+			AT_WRITE_REG(hw, atl1e_rx_page_write_offset_regs[i][j],
+					offset_phy_addr & AT_DMA_LO_ADDR_MASK);
+			AT_WRITE_REGB(hw, atl1e_rx_page_vld_regs[i][j], 1);
+		}
+	}
+	/* Page Length */
+	AT_WRITE_REG(hw, REG_HOST_RXFPAGE_SIZE, rx_ring->page_size);
+	/* Load all of base address above */
+	AT_WRITE_REG(hw, REG_LOAD_PTR, 1);
+
+	return;
+}
+
+static inline void atl1e_configure_tx(struct atl1e_adapter *adapter)
+{
+	struct atl1e_hw *hw = (struct atl1e_hw *)&adapter->hw;
+	u32 dev_ctrl_data = 0;
+	u32 max_pay_load = 0;
+	u32 jumbo_thresh = 0;
+	u32 extra_size = 0;     /* Jumbo frame threshold in QWORD unit */
+
+	/* configure TXQ param */
+	if (hw->nic_type != athr_l2e_revB) {
+		extra_size = ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN;
+		if (hw->max_frame_size <= 1500) {
+			jumbo_thresh = hw->max_frame_size + extra_size;
+		} else if (hw->max_frame_size < 6*1024) {
+			jumbo_thresh =
+				(hw->max_frame_size + extra_size) * 2 / 3;
+		} else {
+			jumbo_thresh = (hw->max_frame_size + extra_size) / 2;
+		}
+		AT_WRITE_REG(hw, REG_TX_EARLY_TH, (jumbo_thresh + 7) >> 3);
+	}
+
+	dev_ctrl_data = AT_READ_REG(hw, REG_DEVICE_CTRL);
+
+	max_pay_load  = ((dev_ctrl_data >> DEVICE_CTRL_MAX_PAYLOAD_SHIFT)) &
+			DEVICE_CTRL_MAX_PAYLOAD_MASK;
+
+	hw->dmaw_block = min(max_pay_load, hw->dmaw_block);
+
+	max_pay_load  = ((dev_ctrl_data >> DEVICE_CTRL_MAX_RREQ_SZ_SHIFT)) &
+			DEVICE_CTRL_MAX_RREQ_SZ_MASK;
+	hw->dmar_block = min(max_pay_load, hw->dmar_block);
+
+	if (hw->nic_type != athr_l2e_revB)
+		AT_WRITE_REGW(hw, REG_TXQ_CTRL + 2,
+			      atl1e_pay_load_size[hw->dmar_block]);
+	/* enable TXQ */
+	AT_WRITE_REGW(hw, REG_TXQ_CTRL,
+			(((u16)hw->tpd_burst & TXQ_CTRL_NUM_TPD_BURST_MASK)
+			 << TXQ_CTRL_NUM_TPD_BURST_SHIFT)
+			| TXQ_CTRL_ENH_MODE | TXQ_CTRL_EN);
+	return;
+}
+
+static inline void atl1e_configure_rx(struct atl1e_adapter *adapter)
+{
+	struct atl1e_hw *hw = (struct atl1e_hw *)&adapter->hw;
+	u32 rxf_len  = 0;
+	u32 rxf_low  = 0;
+	u32 rxf_high = 0;
+	u32 rxf_thresh_data = 0;
+	u32 rxq_ctrl_data = 0;
+
+	if (hw->nic_type != athr_l2e_revB) {
+		AT_WRITE_REGW(hw, REG_RXQ_JMBOSZ_RRDTIM,
+			      (u16)((hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK) <<
+			      RXQ_JMBOSZ_TH_SHIFT |
+			      (1 & RXQ_JMBO_LKAH_MASK) <<
+			      RXQ_JMBO_LKAH_SHIFT));
+
+		rxf_len  = AT_READ_REG(hw, REG_SRAM_RXF_LEN);
+		rxf_high = rxf_len * 4 / 5;
+		rxf_low  = rxf_len / 5;
+		rxf_thresh_data = ((rxf_high  & RXQ_RXF_PAUSE_TH_HI_MASK)
+				  << RXQ_RXF_PAUSE_TH_HI_SHIFT) |
+				  ((rxf_low & RXQ_RXF_PAUSE_TH_LO_MASK)
+				  << RXQ_RXF_PAUSE_TH_LO_SHIFT);
+
+		AT_WRITE_REG(hw, REG_RXQ_RXF_PAUSE_THRESH, rxf_thresh_data);
+	}
+
+	/* RRS */
+	AT_WRITE_REG(hw, REG_IDT_TABLE, hw->indirect_tab);
+	AT_WRITE_REG(hw, REG_BASE_CPU_NUMBER, hw->base_cpu);
+
+	if (hw->rrs_type & atl1e_rrs_ipv4)
+		rxq_ctrl_data |= RXQ_CTRL_HASH_TYPE_IPV4;
+
+	if (hw->rrs_type & atl1e_rrs_ipv4_tcp)
+		rxq_ctrl_data |= RXQ_CTRL_HASH_TYPE_IPV4_TCP;
+
+	if (hw->rrs_type & atl1e_rrs_ipv6)
+		rxq_ctrl_data |= RXQ_CTRL_HASH_TYPE_IPV6;
+
+	if (hw->rrs_type & atl1e_rrs_ipv6_tcp)
+		rxq_ctrl_data |= RXQ_CTRL_HASH_TYPE_IPV6_TCP;
+
+	if (hw->rrs_type != atl1e_rrs_disable)
+		rxq_ctrl_data |=
+			(RXQ_CTRL_HASH_ENABLE | RXQ_CTRL_RSS_MODE_MQUESINT);
+
+	rxq_ctrl_data |= RXQ_CTRL_IPV6_XSUM_VERIFY_EN | RXQ_CTRL_PBA_ALIGN_32 |
+			 RXQ_CTRL_CUT_THRU_EN | RXQ_CTRL_EN;
+
+	AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data);
+	return;
+}
+
+static inline void atl1e_configure_dma(struct atl1e_adapter *adapter)
+{
+	struct atl1e_hw *hw = &adapter->hw;
+	u32 dma_ctrl_data = 0;
+
+	dma_ctrl_data = DMA_CTRL_RXCMB_EN;
+	dma_ctrl_data |= (((u32)hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
+		<< DMA_CTRL_DMAR_BURST_LEN_SHIFT;
+	dma_ctrl_data |= (((u32)hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK)
+		<< DMA_CTRL_DMAW_BURST_LEN_SHIFT;
+	dma_ctrl_data |= DMA_CTRL_DMAR_REQ_PRI | DMA_CTRL_DMAR_OUT_ORDER;
+	dma_ctrl_data |= (((u32)hw->dmar_dly_cnt) & DMA_CTRL_DMAR_DLY_CNT_MASK)
+		<< DMA_CTRL_DMAR_DLY_CNT_SHIFT;
+	dma_ctrl_data |= (((u32)hw->dmaw_dly_cnt) & DMA_CTRL_DMAW_DLY_CNT_MASK)
+		<< DMA_CTRL_DMAW_DLY_CNT_SHIFT;
+
+	AT_WRITE_REG(hw, REG_DMA_CTRL, dma_ctrl_data);
+	return;
+}
+
+static inline void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter)
+{
+	u32 value;
+	struct atl1e_hw *hw = &adapter->hw;
+	struct net_device *netdev = adapter->netdev;
+
+	/* Config MAC CTRL Register */
+	value = MAC_CTRL_TX_EN |
+		MAC_CTRL_RX_EN ;
+
+	if (FULL_DUPLEX == adapter->link_duplex)
+		value |= MAC_CTRL_DUPLX;
+
+	value |= ((u32)((SPEED_1000 == adapter->link_speed) ?
+			  MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) <<
+			  MAC_CTRL_SPEED_SHIFT);
+	value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
+
+	value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
+	value |= (((u32)adapter->hw.preamble_len &
+		  MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
+
+	if (adapter->vlgrp)
+		value |= MAC_CTRL_RMV_VLAN;
+
+	value |= MAC_CTRL_BC_EN;
+	if (netdev->flags & IFF_PROMISC)
+		value |= MAC_CTRL_PROMIS_EN;
+	if (netdev->flags & IFF_ALLMULTI)
+		value |= MAC_CTRL_MC_ALL_EN;
+
+	AT_WRITE_REG(hw, REG_MAC_CTRL, value);
+}
+
+/*
+ * atl1e_configure - Configure Transmit&Receive Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Tx /Rx unit of the MAC after a reset.
+ */
+static int atl1e_configure(struct atl1e_adapter *adapter)
+{
+	struct atl1e_hw *hw = &adapter->hw;
+	struct pci_dev *pdev = adapter->pdev;
+
+	u32 intr_status_data = 0;
+
+	/* clear interrupt status */
+	AT_WRITE_REG(hw, REG_ISR, ~0);
+
+	/* 1. set MAC Address */
+	atl1e_hw_set_mac_addr(hw);
+
+	/* 2. Init the Multicast HASH table done by set_muti */
+
+	/* 3. Clear any WOL status */
+	AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
+
+	/* 4. Descripter Ring BaseMem/Length/Read ptr/Write ptr
+	 *    TPD Ring/SMB/RXF0 Page CMBs, they use the same
+	 *    High 32bits memory */
+	atl1e_configure_des_ring(adapter);
+
+	/* 5. set Interrupt Moderator Timer */
+	AT_WRITE_REGW(hw, REG_IRQ_MODU_TIMER_INIT, hw->imt);
+	AT_WRITE_REGW(hw, REG_IRQ_MODU_TIMER2_INIT, hw->imt);
+	AT_WRITE_REG(hw, REG_MASTER_CTRL, MASTER_CTRL_LED_MODE |
+			MASTER_CTRL_ITIMER_EN | MASTER_CTRL_ITIMER2_EN);
+
+	/* 6. rx/tx threshold to trig interrupt */
+	AT_WRITE_REGW(hw, REG_TRIG_RRD_THRESH, hw->rrd_thresh);
+	AT_WRITE_REGW(hw, REG_TRIG_TPD_THRESH, hw->tpd_thresh);
+	AT_WRITE_REGW(hw, REG_TRIG_RXTIMER, hw->rx_count_down);
+	AT_WRITE_REGW(hw, REG_TRIG_TXTIMER, hw->tx_count_down);
+
+	/* 7. set Interrupt Clear Timer */
+	AT_WRITE_REGW(hw, REG_CMBDISDMA_TIMER, hw->ict);
+
+	/* 8. set MTU */
+	AT_WRITE_REG(hw, REG_MTU, hw->max_frame_size + ETH_HLEN +
+			VLAN_HLEN + ETH_FCS_LEN);
+
+	/* 9. config TXQ early tx threshold */
+	atl1e_configure_tx(adapter);
+
+	/* 10. config RXQ */
+	atl1e_configure_rx(adapter);
+
+	/* 11. config  DMA Engine */
+	atl1e_configure_dma(adapter);
+
+	/* 12. smb timer to trig interrupt */
+	AT_WRITE_REG(hw, REG_SMB_STAT_TIMER, hw->smb_timer);
+
+	intr_status_data = AT_READ_REG(hw, REG_ISR);
+	if (unlikely((intr_status_data & ISR_PHY_LINKDOWN) != 0)) {
+		dev_err(&pdev->dev, "atl1e_configure failed,"
+				"PCIE phy link down\n");
+		return -1;
+	}
+
+	AT_WRITE_REG(hw, REG_ISR, 0x7fffffff);
+	return 0;
+}
+
+/*
+ * atl1e_get_stats - Get System Network Statistics
+ * @netdev: network interface device structure
+ *
+ * Returns the address of the device statistics structure.
+ * The statistics are actually updated from the timer callback.
+ */
+static struct net_device_stats *atl1e_get_stats(struct net_device *netdev)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	struct atl1e_hw_stats  *hw_stats = &adapter->hw_stats;
+	struct net_device_stats *net_stats = &adapter->net_stats;
+
+	net_stats->rx_packets = hw_stats->rx_ok;
+	net_stats->tx_packets = hw_stats->tx_ok;
+	net_stats->rx_bytes   = hw_stats->rx_byte_cnt;
+	net_stats->tx_bytes   = hw_stats->tx_byte_cnt;
+	net_stats->multicast  = hw_stats->rx_mcast;
+	net_stats->collisions = hw_stats->tx_1_col +
+				hw_stats->tx_2_col * 2 +
+				hw_stats->tx_late_col + hw_stats->tx_abort_col;
+
+	net_stats->rx_errors  = hw_stats->rx_frag + hw_stats->rx_fcs_err +
+				hw_stats->rx_len_err + hw_stats->rx_sz_ov +
+				hw_stats->rx_rrd_ov + hw_stats->rx_align_err;
+	net_stats->rx_fifo_errors   = hw_stats->rx_rxf_ov;
+	net_stats->rx_length_errors = hw_stats->rx_len_err;
+	net_stats->rx_crc_errors    = hw_stats->rx_fcs_err;
+	net_stats->rx_frame_errors  = hw_stats->rx_align_err;
+	net_stats->rx_over_errors   = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov;
+
+	net_stats->rx_missed_errors = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov;
+
+	net_stats->tx_errors = hw_stats->tx_late_col + hw_stats->tx_abort_col +
+			       hw_stats->tx_underrun + hw_stats->tx_trunc;
+	net_stats->tx_fifo_errors    = hw_stats->tx_underrun;
+	net_stats->tx_aborted_errors = hw_stats->tx_abort_col;
+	net_stats->tx_window_errors  = hw_stats->tx_late_col;
+
+	return &adapter->net_stats;
+}
+
+static void atl1e_update_hw_stats(struct atl1e_adapter *adapter)
+{
+	u16 hw_reg_addr = 0;
+	unsigned long *stats_item = NULL;
+
+	/* update rx status */
+	hw_reg_addr = REG_MAC_RX_STATUS_BIN;
+	stats_item  = &adapter->hw_stats.rx_ok;
+	while (hw_reg_addr <= REG_MAC_RX_STATUS_END) {
+		*stats_item += AT_READ_REG(&adapter->hw, hw_reg_addr);
+		stats_item++;
+		hw_reg_addr += 4;
+	}
+	/* update tx status */
+	hw_reg_addr = REG_MAC_TX_STATUS_BIN;
+	stats_item  = &adapter->hw_stats.tx_ok;
+	while (hw_reg_addr <= REG_MAC_TX_STATUS_END) {
+		*stats_item += AT_READ_REG(&adapter->hw, hw_reg_addr);
+		stats_item++;
+		hw_reg_addr += 4;
+	}
+}
+
+static inline void atl1e_clear_phy_int(struct atl1e_adapter *adapter)
+{
+	u16 phy_data;
+
+	spin_lock(&adapter->mdio_lock);
+	atl1e_read_phy_reg(&adapter->hw, MII_INT_STATUS, &phy_data);
+	spin_unlock(&adapter->mdio_lock);
+}
+
+static bool atl1e_clean_tx_irq(struct atl1e_adapter *adapter)
+{
+	struct atl1e_tx_ring *tx_ring = (struct atl1e_tx_ring *)
+					&adapter->tx_ring;
+	struct atl1e_tx_buffer *tx_buffer = NULL;
+	u16 hw_next_to_clean = AT_READ_REGW(&adapter->hw, REG_TPD_CONS_IDX);
+	u16 next_to_clean = atomic_read(&tx_ring->next_to_clean);
+
+	while (next_to_clean != hw_next_to_clean) {
+		tx_buffer = &tx_ring->tx_buffer[next_to_clean];
+		if (tx_buffer->dma) {
+			pci_unmap_page(adapter->pdev, tx_buffer->dma,
+					tx_buffer->length, PCI_DMA_TODEVICE);
+			tx_buffer->dma = 0;
+		}
+
+		if (tx_buffer->skb) {
+			dev_kfree_skb_irq(tx_buffer->skb);
+			tx_buffer->skb = NULL;
+		}
+
+		if (++next_to_clean == tx_ring->count)
+			next_to_clean = 0;
+	}
+
+	atomic_set(&tx_ring->next_to_clean, next_to_clean);
+
+	if (netif_queue_stopped(adapter->netdev) &&
+			netif_carrier_ok(adapter->netdev)) {
+		netif_wake_queue(adapter->netdev);
+	}
+
+	return true;
+}
+
+/*
+ * atl1e_intr - Interrupt Handler
+ * @irq: interrupt number
+ * @data: pointer to a network interface device structure
+ * @pt_regs: CPU registers structure
+ */
+static irqreturn_t atl1e_intr(int irq, void *data)
+{
+	struct net_device *netdev  = data;
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	struct pci_dev *pdev = adapter->pdev;
+	struct atl1e_hw *hw = &adapter->hw;
+	int max_ints = AT_MAX_INT_WORK;
+	int handled = IRQ_NONE;
+	u32 status;
+
+	do {
+		status = AT_READ_REG(hw, REG_ISR);
+		if ((status & IMR_NORMAL_MASK) == 0 ||
+				(status & ISR_DIS_INT) != 0) {
+			if (max_ints != AT_MAX_INT_WORK)
+				handled = IRQ_HANDLED;
+			break;
+		}
+		/* link event */
+		if (status & ISR_GPHY)
+			atl1e_clear_phy_int(adapter);
+		/* Ack ISR */
+		AT_WRITE_REG(hw, REG_ISR, status | ISR_DIS_INT);
+
+		handled = IRQ_HANDLED;
+		/* check if PCIE PHY Link down */
+		if (status & ISR_PHY_LINKDOWN) {
+			dev_err(&pdev->dev,
+				"pcie phy linkdown %x\n", status);
+			if (netif_running(adapter->netdev)) {
+				/* reset MAC */
+				atl1e_irq_reset(adapter);
+				schedule_work(&adapter->reset_task);
+				break;
+			}
+		}
+
+		/* check if DMA read/write error */
+		if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) {
+			dev_err(&pdev->dev,
+				"PCIE DMA RW error (status = 0x%x)\n",
+				status);
+			atl1e_irq_reset(adapter);
+			schedule_work(&adapter->reset_task);
+			break;
+		}
+
+		if (status & ISR_SMB)
+			atl1e_update_hw_stats(adapter);
+
+		/* link event */
+		if (status & (ISR_GPHY | ISR_MANUAL)) {
+			adapter->net_stats.tx_carrier_errors++;
+			atl1e_link_chg_event(adapter);
+			break;
+		}
+
+		/* transmit event */
+		if (status & ISR_TX_EVENT)
+			atl1e_clean_tx_irq(adapter);
+
+		if (status & ISR_RX_EVENT) {
+			/*
+			 * disable rx interrupts, without
+			 * the synchronize_irq bit
+			 */
+			AT_WRITE_REG(hw, REG_IMR,
+				     IMR_NORMAL_MASK & ~ISR_RX_EVENT);
+			AT_WRITE_FLUSH(hw);
+			if (likely(netif_rx_schedule_prep(netdev,
+				   &adapter->napi)))
+				__netif_rx_schedule(netdev, &adapter->napi);
+		}
+	} while (--max_ints > 0);
+	/* re-enable Interrupt*/
+	AT_WRITE_REG(&adapter->hw, REG_ISR, 0);
+
+	return handled;
+}
+
+static inline void atl1e_rx_checksum(struct atl1e_adapter *adapter,
+		  struct sk_buff *skb, struct atl1e_recv_ret_status *prrs)
+{
+	u8 *packet = (u8 *)(prrs + 1);
+	struct iphdr *iph;
+	u16 head_len = ETH_HLEN;
+	u16 pkt_flags;
+	u16 err_flags;
+
+	skb->ip_summed = CHECKSUM_NONE;
+	pkt_flags = prrs->pkt_flag;
+	err_flags = prrs->err_flag;
+	if (((pkt_flags & RRS_IS_IPV4) || (pkt_flags & RRS_IS_IPV6)) &&
+		((pkt_flags & RRS_IS_TCP) || (pkt_flags & RRS_IS_UDP))) {
+		if (pkt_flags & RRS_IS_IPV4) {
+			if (pkt_flags & RRS_IS_802_3)
+				head_len += 8;
+			iph = (struct iphdr *) (packet + head_len);
+			if (iph->frag_off != 0 && !(pkt_flags & RRS_IS_IP_DF))
+				goto hw_xsum;
+		}
+		if (!(err_flags & (RRS_ERR_IP_CSUM | RRS_ERR_L4_CSUM))) {
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+			return;
+		}
+	}
+
+hw_xsum :
+	return;
+}
+
+static struct atl1e_rx_page *atl1e_get_rx_page(struct atl1e_adapter *adapter,
+					       u8 que)
+{
+	struct atl1e_rx_page_desc *rx_page_desc =
+		(struct atl1e_rx_page_desc *) adapter->rx_ring.rx_page_desc;
+	u8 rx_using = rx_page_desc[que].rx_using;
+
+	return (struct atl1e_rx_page *)&(rx_page_desc[que].rx_page[rx_using]);
+}
+
+static void atl1e_clean_rx_irq(struct atl1e_adapter *adapter, u8 que,
+		   int *work_done, int work_to_do)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	struct net_device *netdev  = adapter->netdev;
+	struct atl1e_rx_ring *rx_ring = (struct atl1e_rx_ring *)
+					 &adapter->rx_ring;
+	struct atl1e_rx_page_desc *rx_page_desc =
+		(struct atl1e_rx_page_desc *) rx_ring->rx_page_desc;
+	struct sk_buff *skb = NULL;
+	struct atl1e_rx_page *rx_page = atl1e_get_rx_page(adapter, que);
+	u32 packet_size, write_offset;
+	struct atl1e_recv_ret_status *prrs;
+
+	write_offset = *(rx_page->write_offset_addr);
+	if (likely(rx_page->read_offset < write_offset)) {
+		do {
+			if (*work_done >= work_to_do)
+				break;
+			(*work_done)++;
+			/* get new packet's  rrs */
+			prrs = (struct atl1e_recv_ret_status *) (rx_page->addr +
+						 rx_page->read_offset);
+			/* check sequence number */
+			if (prrs->seq_num != rx_page_desc[que].rx_nxseq) {
+				dev_err(&pdev->dev,
+					"rx sequence number"
+					" error (rx=%d) (expect=%d)\n",
+					prrs->seq_num,
+					rx_page_desc[que].rx_nxseq);
+				rx_page_desc[que].rx_nxseq++;
+				/* just for debug use */
+				AT_WRITE_REG(&adapter->hw, REG_DEBUG_DATA0,
+					     (((u32)prrs->seq_num) << 16) |
+					     rx_page_desc[que].rx_nxseq);
+				goto fatal_err;
+			}
+			rx_page_desc[que].rx_nxseq++;
+
+			/* error packet */
+			if (prrs->pkt_flag & RRS_IS_ERR_FRAME) {
+				if (prrs->err_flag & (RRS_ERR_BAD_CRC |
+					RRS_ERR_DRIBBLE | RRS_ERR_CODE |
+					RRS_ERR_TRUNC)) {
+				/* hardware error, discard this packet*/
+					dev_err(&pdev->dev,
+						"rx packet desc error %x\n",
+						*((u32 *)prrs + 1));
+					goto skip_pkt;
+				}
+			}
+
+			packet_size = ((prrs->word1 >> RRS_PKT_SIZE_SHIFT) &
+					RRS_PKT_SIZE_MASK) - 4; /* CRC */
+			skb = netdev_alloc_skb(netdev,
+					       packet_size + NET_IP_ALIGN);
+			if (skb == NULL) {
+				dev_warn(&pdev->dev, "%s: Memory squeeze,"
+					"deferring packet.\n", netdev->name);
+				goto skip_pkt;
+			}
+			skb_reserve(skb, NET_IP_ALIGN);
+			skb->dev = netdev;
+			memcpy(skb->data, (u8 *)(prrs + 1), packet_size);
+			skb_put(skb, packet_size);
+			skb->protocol = eth_type_trans(skb, netdev);
+			atl1e_rx_checksum(adapter, skb, prrs);
+
+			if (unlikely(adapter->vlgrp &&
+				(prrs->pkt_flag & RRS_IS_VLAN_TAG))) {
+				u16 vlan_tag = (prrs->vtag >> 4) |
+					       ((prrs->vtag & 7) << 13) |
+					       ((prrs->vtag & 8) << 9);
+				dev_dbg(&pdev->dev,
+					"RXD VLAN TAG<RRD>=0x%04x\n",
+					prrs->vtag);
+				vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
+							 vlan_tag);
+			} else {
+				netif_receive_skb(skb);
+			}
+
+			netdev->last_rx = jiffies;
+skip_pkt:
+	/* skip current packet whether it's ok or not. */
+			rx_page->read_offset +=
+				(((u32)((prrs->word1 >> RRS_PKT_SIZE_SHIFT) &
+				RRS_PKT_SIZE_MASK) +
+				sizeof(struct atl1e_recv_ret_status) + 31) &
+						0xFFFFFFE0);
+
+			if (rx_page->read_offset >= rx_ring->page_size) {
+				/* mark this page clean */
+				u16 reg_addr;
+				u8  rx_using;
+
+				rx_page->read_offset =
+					*(rx_page->write_offset_addr) = 0;
+				rx_using = rx_page_desc[que].rx_using;
+				reg_addr =
+					atl1e_rx_page_vld_regs[que][rx_using];
+				AT_WRITE_REGB(&adapter->hw, reg_addr, 1);
+				rx_page_desc[que].rx_using ^= 1;
+				rx_page = atl1e_get_rx_page(adapter, que);
+			}
+			write_offset = *(rx_page->write_offset_addr);
+		} while (rx_page->read_offset < write_offset);
+	}
+
+	return;
+
+fatal_err:
+	if (!test_bit(__AT_DOWN, &adapter->flags))
+		schedule_work(&adapter->reset_task);
+}
+
+/*
+ * atl1e_clean - NAPI Rx polling callback
+ * @adapter: board private structure
+ */
+static int atl1e_clean(struct napi_struct *napi, int budget)
+{
+	struct atl1e_adapter *adapter =
+			container_of(napi, struct atl1e_adapter, napi);
+	struct net_device *netdev  = adapter->netdev;
+	struct pci_dev    *pdev    = adapter->pdev;
+	u32 imr_data;
+	int work_done = 0;
+
+	/* Keep link state information with original netdev */
+	if (!netif_carrier_ok(adapter->netdev))
+		goto quit_polling;
+
+	atl1e_clean_rx_irq(adapter, 0, &work_done, budget);
+
+	/* If no Tx and not enough Rx work done, exit the polling mode */
+	if (work_done < budget) {
+quit_polling:
+		netif_rx_complete(netdev, napi);
+		imr_data = AT_READ_REG(&adapter->hw, REG_IMR);
+		AT_WRITE_REG(&adapter->hw, REG_IMR, imr_data | ISR_RX_EVENT);
+		/* test debug */
+		if (test_bit(__AT_DOWN, &adapter->flags)) {
+			atomic_dec(&adapter->irq_sem);
+			dev_err(&pdev->dev,
+				"atl1e_clean is called when AT_DOWN\n");
+		}
+		/* reenable RX intr */
+		/*atl1e_irq_enable(adapter); */
+
+	}
+	return work_done;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+
+/*
+ * Polling 'interrupt' - used by things like netconsole to send skbs
+ * without having to re-enable interrupts. It's not called while
+ * the interrupt routine is executing.
+ */
+static void atl1e_netpoll(struct net_device *netdev)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+	disable_irq(adapter->pdev->irq);
+	atl1e_intr(adapter->pdev->irq, netdev);
+	enable_irq(adapter->pdev->irq);
+}
+#endif
+
+static inline u16 atl1e_tpd_avail(struct atl1e_adapter *adapter)
+{
+	struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
+	u16 next_to_use = 0;
+	u16 next_to_clean = 0;
+
+	next_to_clean = atomic_read(&tx_ring->next_to_clean);
+	next_to_use   = tx_ring->next_to_use;
+
+	return (u16)(next_to_clean > next_to_use) ?
+		(next_to_clean - next_to_use - 1) :
+		(tx_ring->count + next_to_clean - next_to_use - 1);
+}
+
+/*
+ * get next usable tpd
+ * Note: should call atl1e_tdp_avail to make sure
+ * there is enough tpd to use
+ */
+static struct atl1e_tpd_desc *atl1e_get_tpd(struct atl1e_adapter *adapter)
+{
+	struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
+	u16 next_to_use = 0;
+
+	next_to_use = tx_ring->next_to_use;
+	if (++tx_ring->next_to_use == tx_ring->count)
+		tx_ring->next_to_use = 0;
+
+	memset(&tx_ring->desc[next_to_use], 0, sizeof(struct atl1e_tpd_desc));
+	return (struct atl1e_tpd_desc *)&tx_ring->desc[next_to_use];
+}
+
+static struct atl1e_tx_buffer *
+atl1e_get_tx_buffer(struct atl1e_adapter *adapter, struct atl1e_tpd_desc *tpd)
+{
+	struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
+
+	return &tx_ring->tx_buffer[tpd - tx_ring->desc];
+}
+
+/* Calculate the transmit packet descript needed*/
+static u16 atl1e_cal_tdp_req(const struct sk_buff *skb)
+{
+	int i = 0;
+	u16 tpd_req = 1;
+	u16 fg_size = 0;
+	u16 proto_hdr_len = 0;
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		fg_size = skb_shinfo(skb)->frags[i].size;
+		tpd_req += ((fg_size + MAX_TX_BUF_LEN - 1) >> MAX_TX_BUF_SHIFT);
+	}
+
+	if (skb_is_gso(skb)) {
+		if (skb->protocol == ntohs(ETH_P_IP) ||
+		   (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6)) {
+			proto_hdr_len = skb_transport_offset(skb) +
+					tcp_hdrlen(skb);
+			if (proto_hdr_len < skb_headlen(skb)) {
+				tpd_req += ((skb_headlen(skb) - proto_hdr_len +
+					   MAX_TX_BUF_LEN - 1) >>
+					   MAX_TX_BUF_SHIFT);
+			}
+		}
+
+	}
+	return tpd_req;
+}
+
+static int atl1e_tso_csum(struct atl1e_adapter *adapter,
+		       struct sk_buff *skb, struct atl1e_tpd_desc *tpd)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	u8 hdr_len;
+	u32 real_len;
+	unsigned short offload_type;
+	int err;
+
+	if (skb_is_gso(skb)) {
+		if (skb_header_cloned(skb)) {
+			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+			if (unlikely(err))
+				return -1;
+		}
+		offload_type = skb_shinfo(skb)->gso_type;
+
+		if (offload_type & SKB_GSO_TCPV4) {
+			real_len = (((unsigned char *)ip_hdr(skb) - skb->data)
+					+ ntohs(ip_hdr(skb)->tot_len));
+
+			if (real_len < skb->len)
+				pskb_trim(skb, real_len);
+
+			hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
+			if (unlikely(skb->len == hdr_len)) {
+				/* only xsum need */
+				dev_warn(&pdev->dev,
+				      "IPV4 tso with zero data??\n");
+				goto check_sum;
+			} else {
+				ip_hdr(skb)->check = 0;
+				ip_hdr(skb)->tot_len = 0;
+				tcp_hdr(skb)->check = ~csum_tcpudp_magic(
+							ip_hdr(skb)->saddr,
+							ip_hdr(skb)->daddr,
+							0, IPPROTO_TCP, 0);
+				tpd->word3 |= (ip_hdr(skb)->ihl &
+					TDP_V4_IPHL_MASK) <<
+					TPD_V4_IPHL_SHIFT;
+				tpd->word3 |= ((tcp_hdrlen(skb) >> 2) &
+					TPD_TCPHDRLEN_MASK) <<
+					TPD_TCPHDRLEN_SHIFT;
+				tpd->word3 |= ((skb_shinfo(skb)->gso_size) &
+					TPD_MSS_MASK) << TPD_MSS_SHIFT;
+				tpd->word3 |= 1 << TPD_SEGMENT_EN_SHIFT;
+			}
+			return 0;
+		}
+
+		if (offload_type & SKB_GSO_TCPV6) {
+			real_len = (((unsigned char *)ipv6_hdr(skb) - skb->data)
+					+ ntohs(ipv6_hdr(skb)->payload_len));
+			if (real_len < skb->len)
+				pskb_trim(skb, real_len);
+
+			/* check payload == 0 byte ? */
+			hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
+			if (unlikely(skb->len == hdr_len)) {
+				/* only xsum need */
+				dev_warn(&pdev->dev,
+					"IPV6 tso with zero data??\n");
+				goto check_sum;
+			} else {
+				tcp_hdr(skb)->check = ~csum_ipv6_magic(
+						&ipv6_hdr(skb)->saddr,
+						&ipv6_hdr(skb)->daddr,
+						0, IPPROTO_TCP, 0);
+				tpd->word3 |= 1 << TPD_IP_VERSION_SHIFT;
+				hdr_len >>= 1;
+				tpd->word3 |= (hdr_len & TPD_V6_IPHLLO_MASK) <<
+					TPD_V6_IPHLLO_SHIFT;
+				tpd->word3 |= ((hdr_len >> 3) &
+					TPD_V6_IPHLHI_MASK) <<
+					TPD_V6_IPHLHI_SHIFT;
+				tpd->word3 |= (tcp_hdrlen(skb) >> 2 &
+					TPD_TCPHDRLEN_MASK) <<
+					TPD_TCPHDRLEN_SHIFT;
+				tpd->word3 |= ((skb_shinfo(skb)->gso_size) &
+					TPD_MSS_MASK) << TPD_MSS_SHIFT;
+					tpd->word3 |= 1 << TPD_SEGMENT_EN_SHIFT;
+			}
+		}
+		return 0;
+	}
+
+check_sum:
+	if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+		u8 css, cso;
+
+		cso = skb_transport_offset(skb);
+		if (unlikely(cso & 0x1)) {
+			dev_err(&adapter->pdev->dev,
+			   "pay load offset should not ant event number\n");
+			return -1;
+		} else {
+			css = cso + skb->csum_offset;
+			tpd->word3 |= (cso & TPD_PLOADOFFSET_MASK) <<
+					TPD_PLOADOFFSET_SHIFT;
+			tpd->word3 |= (css & TPD_CCSUMOFFSET_MASK) <<
+					TPD_CCSUMOFFSET_SHIFT;
+			tpd->word3 |= 1 << TPD_CC_SEGMENT_EN_SHIFT;
+		}
+	}
+
+	return 0;
+}
+
+static void atl1e_tx_map(struct atl1e_adapter *adapter,
+		      struct sk_buff *skb, struct atl1e_tpd_desc *tpd)
+{
+	struct atl1e_tpd_desc *use_tpd = NULL;
+	struct atl1e_tx_buffer *tx_buffer = NULL;
+	u16 buf_len = skb->len - skb->data_len;
+	u16 map_len = 0;
+	u16 mapped_len = 0;
+	u16 hdr_len = 0;
+	u16 nr_frags;
+	u16 f;
+	int segment;
+
+	nr_frags = skb_shinfo(skb)->nr_frags;
+	segment = (tpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK;
+	if (segment) {
+		/* TSO */
+		map_len = hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+		use_tpd = tpd;
+
+		tx_buffer = atl1e_get_tx_buffer(adapter, use_tpd);
+		tx_buffer->length = map_len;
+		tx_buffer->dma = pci_map_single(adapter->pdev,
+					skb->data, hdr_len, PCI_DMA_TODEVICE);
+		mapped_len += map_len;
+		use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
+		use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
+			((cpu_to_le32(tx_buffer->length) &
+			TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT);
+	}
+
+	while (mapped_len < buf_len) {
+		/* mapped_len == 0, means we should use the first tpd,
+		   which is given by caller  */
+		if (mapped_len == 0) {
+			use_tpd = tpd;
+		} else {
+			use_tpd = atl1e_get_tpd(adapter);
+			memcpy(use_tpd, tpd, sizeof(struct atl1e_tpd_desc));
+		}
+		tx_buffer = atl1e_get_tx_buffer(adapter, use_tpd);
+		tx_buffer->skb = NULL;
+
+		tx_buffer->length = map_len =
+			((buf_len - mapped_len) >= MAX_TX_BUF_LEN) ?
+			MAX_TX_BUF_LEN : (buf_len - mapped_len);
+		tx_buffer->dma =
+			pci_map_single(adapter->pdev, skb->data + mapped_len,
+					map_len, PCI_DMA_TODEVICE);
+		mapped_len  += map_len;
+		use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
+		use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
+			((cpu_to_le32(tx_buffer->length) &
+			TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT);
+	}
+
+	for (f = 0; f < nr_frags; f++) {
+		struct skb_frag_struct *frag;
+		u16 i;
+		u16 seg_num;
+
+		frag = &skb_shinfo(skb)->frags[f];
+		buf_len = frag->size;
+
+		seg_num = (buf_len + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN;
+		for (i = 0; i < seg_num; i++) {
+			use_tpd = atl1e_get_tpd(adapter);
+			memcpy(use_tpd, tpd, sizeof(struct atl1e_tpd_desc));
+
+			tx_buffer = atl1e_get_tx_buffer(adapter, use_tpd);
+			if (tx_buffer->skb)
+				BUG();
+
+			tx_buffer->skb = NULL;
+			tx_buffer->length =
+				(buf_len > MAX_TX_BUF_LEN) ?
+				MAX_TX_BUF_LEN : buf_len;
+			buf_len -= tx_buffer->length;
+
+			tx_buffer->dma =
+				pci_map_page(adapter->pdev, frag->page,
+						frag->page_offset +
+						(i * MAX_TX_BUF_LEN),
+						tx_buffer->length,
+						PCI_DMA_TODEVICE);
+			use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma);
+			use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) |
+					((cpu_to_le32(tx_buffer->length) &
+					TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT);
+		}
+	}
+
+	if ((tpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK)
+		/* note this one is a tcp header */
+		tpd->word3 |= 1 << TPD_HDRFLAG_SHIFT;
+	/* The last tpd */
+
+	use_tpd->word3 |= 1 << TPD_EOP_SHIFT;
+	/* The last buffer info contain the skb address,
+	   so it will be free after unmap */
+	tx_buffer->skb = skb;
+}
+
+static void atl1e_tx_queue(struct atl1e_adapter *adapter, u16 count,
+			   struct atl1e_tpd_desc *tpd)
+{
+	struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
+	/* Force memory writes to complete before letting h/w
+	 * know there are new descriptors to fetch.  (Only
+	 * applicable for weak-ordered memory model archs,
+	 * such as IA-64). */
+	wmb();
+	AT_WRITE_REG(&adapter->hw, REG_MB_TPD_PROD_IDX, tx_ring->next_to_use);
+}
+
+static int atl1e_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	unsigned long flags;
+	u16 tpd_req = 1;
+	struct atl1e_tpd_desc *tpd;
+
+	if (test_bit(__AT_DOWN, &adapter->flags)) {
+		dev_kfree_skb_any(skb);
+		return NETDEV_TX_OK;
+	}
+
+	if (unlikely(skb->len <= 0)) {
+		dev_kfree_skb_any(skb);
+		return NETDEV_TX_OK;
+	}
+	tpd_req = atl1e_cal_tdp_req(skb);
+	if (!spin_trylock_irqsave(&adapter->tx_lock, flags))
+		return NETDEV_TX_LOCKED;
+
+	if (atl1e_tpd_avail(adapter) < tpd_req) {
+		/* no enough descriptor, just stop queue */
+		netif_stop_queue(netdev);
+		spin_unlock_irqrestore(&adapter->tx_lock, flags);
+		return NETDEV_TX_BUSY;
+	}
+
+	tpd = atl1e_get_tpd(adapter);
+
+	if (unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
+		u16 vlan_tag = vlan_tx_tag_get(skb);
+		u16 atl1e_vlan_tag;
+
+		tpd->word3 |= 1 << TPD_INS_VL_TAG_SHIFT;
+		AT_VLAN_TAG_TO_TPD_TAG(vlan_tag, atl1e_vlan_tag);
+		tpd->word2 |= (atl1e_vlan_tag & TPD_VLANTAG_MASK) <<
+				TPD_VLAN_SHIFT;
+	}
+
+	if (skb->protocol == ntohs(ETH_P_8021Q))
+		tpd->word3 |= 1 << TPD_VL_TAGGED_SHIFT;
+
+	if (skb_network_offset(skb) != ETH_HLEN)
+		tpd->word3 |= 1 << TPD_ETHTYPE_SHIFT; /* 802.3 frame */
+
+	/* do TSO and check sum */
+	if (atl1e_tso_csum(adapter, skb, tpd) != 0) {
+		spin_unlock_irqrestore(&adapter->tx_lock, flags);
+		dev_kfree_skb_any(skb);
+		return NETDEV_TX_OK;
+	}
+
+	atl1e_tx_map(adapter, skb, tpd);
+	atl1e_tx_queue(adapter, tpd_req, tpd);
+
+	netdev->trans_start = jiffies;
+	spin_unlock_irqrestore(&adapter->tx_lock, flags);
+	return NETDEV_TX_OK;
+}
+
+static void atl1e_free_irq(struct atl1e_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+
+	free_irq(adapter->pdev->irq, netdev);
+
+	if (adapter->have_msi)
+		pci_disable_msi(adapter->pdev);
+}
+
+static int atl1e_request_irq(struct atl1e_adapter *adapter)
+{
+	struct pci_dev    *pdev   = adapter->pdev;
+	struct net_device *netdev = adapter->netdev;
+	int flags = 0;
+	int err = 0;
+
+	adapter->have_msi = true;
+	err = pci_enable_msi(adapter->pdev);
+	if (err) {
+		dev_dbg(&pdev->dev,
+			"Unable to allocate MSI interrupt Error: %d\n", err);
+		adapter->have_msi = false;
+	} else
+		netdev->irq = pdev->irq;
+
+
+	if (!adapter->have_msi)
+		flags |= IRQF_SHARED;
+	err = request_irq(adapter->pdev->irq, &atl1e_intr, flags,
+			netdev->name, netdev);
+	if (err) {
+		dev_dbg(&pdev->dev,
+			"Unable to allocate interrupt Error: %d\n", err);
+		if (adapter->have_msi)
+			pci_disable_msi(adapter->pdev);
+		return err;
+	}
+	dev_dbg(&pdev->dev, "atl1e_request_irq OK\n");
+	return err;
+}
+
+int atl1e_up(struct atl1e_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	int err = 0;
+	u32 val;
+
+	/* hardware has been reset, we need to reload some things */
+	err = atl1e_init_hw(&adapter->hw);
+	if (err) {
+		err = -EIO;
+		return err;
+	}
+	atl1e_init_ring_ptrs(adapter);
+	atl1e_set_multi(netdev);
+	atl1e_restore_vlan(adapter);
+
+	if (atl1e_configure(adapter)) {
+		err = -EIO;
+		goto err_up;
+	}
+
+	clear_bit(__AT_DOWN, &adapter->flags);
+	napi_enable(&adapter->napi);
+	atl1e_irq_enable(adapter);
+	val = AT_READ_REG(&adapter->hw, REG_MASTER_CTRL);
+	AT_WRITE_REG(&adapter->hw, REG_MASTER_CTRL,
+		      val | MASTER_CTRL_MANUAL_INT);
+
+err_up:
+	return err;
+}
+
+void atl1e_down(struct atl1e_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+
+	/* signal that we're down so the interrupt handler does not
+	 * reschedule our watchdog timer */
+	set_bit(__AT_DOWN, &adapter->flags);
+
+#ifdef NETIF_F_LLTX
+	netif_stop_queue(netdev);
+#else
+	netif_tx_disable(netdev);
+#endif
+
+	/* reset MAC to disable all RX/TX */
+	atl1e_reset_hw(&adapter->hw);
+	msleep(1);
+
+	napi_disable(&adapter->napi);
+	atl1e_del_timer(adapter);
+	atl1e_irq_disable(adapter);
+
+	netif_carrier_off(netdev);
+	adapter->link_speed = SPEED_0;
+	adapter->link_duplex = -1;
+	atl1e_clean_tx_ring(adapter);
+	atl1e_clean_rx_ring(adapter);
+}
+
+/*
+ * atl1e_open - Called when a network interface is made active
+ * @netdev: network interface device structure
+ *
+ * Returns 0 on success, negative value on failure
+ *
+ * The open entry point is called when a network interface is made
+ * active by the system (IFF_UP).  At this point all resources needed
+ * for transmit and receive operations are allocated, the interrupt
+ * handler is registered with the OS, the watchdog timer is started,
+ * and the stack is notified that the interface is ready.
+ */
+static int atl1e_open(struct net_device *netdev)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	int err;
+
+	/* disallow open during test */
+	if (test_bit(__AT_TESTING, &adapter->flags))
+		return -EBUSY;
+
+	/* allocate rx/tx dma buffer & descriptors */
+	atl1e_init_ring_resources(adapter);
+	err = atl1e_setup_ring_resources(adapter);
+	if (unlikely(err))
+		return err;
+
+	err = atl1e_request_irq(adapter);
+	if (unlikely(err))
+		goto err_req_irq;
+
+	err = atl1e_up(adapter);
+	if (unlikely(err))
+		goto err_up;
+
+	return 0;
+
+err_up:
+	atl1e_free_irq(adapter);
+err_req_irq:
+	atl1e_free_ring_resources(adapter);
+	atl1e_reset_hw(&adapter->hw);
+
+	return err;
+}
+
+/*
+ * atl1e_close - Disables a network interface
+ * @netdev: network interface device structure
+ *
+ * Returns 0, this is not allowed to fail
+ *
+ * The close entry point is called when an interface is de-activated
+ * by the OS.  The hardware is still under the drivers control, but
+ * needs to be disabled.  A global MAC reset is issued to stop the
+ * hardware, and all transmit and receive resources are freed.
+ */
+static int atl1e_close(struct net_device *netdev)
+{
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+	WARN_ON(test_bit(__AT_RESETTING, &adapter->flags));
+	atl1e_down(adapter);
+	atl1e_free_irq(adapter);
+	atl1e_free_ring_resources(adapter);
+
+	return 0;
+}
+
+static int atl1e_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	struct atl1e_hw *hw = &adapter->hw;
+	u32 ctrl = 0;
+	u32 mac_ctrl_data = 0;
+	u32 wol_ctrl_data = 0;
+	u16 mii_advertise_data = 0;
+	u16 mii_bmsr_data = 0;
+	u16 mii_intr_status_data = 0;
+	u32 wufc = adapter->wol;
+	u32 i;
+#ifdef CONFIG_PM
+	int retval = 0;
+#endif
+
+	if (netif_running(netdev)) {
+		WARN_ON(test_bit(__AT_RESETTING, &adapter->flags));
+		atl1e_down(adapter);
+	}
+	netif_device_detach(netdev);
+
+#ifdef CONFIG_PM
+	retval = pci_save_state(pdev);
+	if (retval)
+		return retval;
+#endif
+
+	if (wufc) {
+		/* get link status */
+		atl1e_read_phy_reg(hw, MII_BMSR, (u16 *)&mii_bmsr_data);
+		atl1e_read_phy_reg(hw, MII_BMSR, (u16 *)&mii_bmsr_data);
+
+		mii_advertise_data = MII_AR_10T_HD_CAPS;
+
+		if ((atl1e_write_phy_reg(hw, MII_AT001_CR, 0) != 0) ||
+		    (atl1e_write_phy_reg(hw,
+			   MII_ADVERTISE, mii_advertise_data) != 0) ||
+		    (atl1e_phy_commit(hw)) != 0) {
+			dev_dbg(&pdev->dev, "set phy register failed\n");
+			goto wol_dis;
+		}
+
+		hw->phy_configured = false; /* re-init PHY when resume */
+
+		/* turn on magic packet wol */
+		if (wufc & AT_WUFC_MAG)
+			wol_ctrl_data |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
+
+		if (wufc & AT_WUFC_LNKC) {
+		/* if orignal link status is link, just wait for retrive link */
+			if (mii_bmsr_data & BMSR_LSTATUS) {
+				for (i = 0; i < AT_SUSPEND_LINK_TIMEOUT; i++) {
+					msleep(100);
+					atl1e_read_phy_reg(hw, MII_BMSR,
+							(u16 *)&mii_bmsr_data);
+					if (mii_bmsr_data & BMSR_LSTATUS)
+						break;
+				}
+
+				if ((mii_bmsr_data & BMSR_LSTATUS) == 0)
+					dev_dbg(&pdev->dev,
+						"%s: Link may change"
+						"when suspend\n",
+						atl1e_driver_name);
+			}
+			wol_ctrl_data |=  WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN;
+			/* only link up can wake up */
+			if (atl1e_write_phy_reg(hw, MII_INT_CTRL, 0x400) != 0) {
+				dev_dbg(&pdev->dev, "%s: read write phy "
+						  "register failed.\n",
+						  atl1e_driver_name);
+				goto wol_dis;
+			}
+		}
+		/* clear phy interrupt */
+		atl1e_read_phy_reg(hw, MII_INT_STATUS, &mii_intr_status_data);
+		/* Config MAC Ctrl register */
+		mac_ctrl_data = MAC_CTRL_RX_EN;
+		/* set to 10/100M halt duplex */
+		mac_ctrl_data |= MAC_CTRL_SPEED_10_100 << MAC_CTRL_SPEED_SHIFT;
+		mac_ctrl_data |= (((u32)adapter->hw.preamble_len &
+				 MAC_CTRL_PRMLEN_MASK) <<
+				 MAC_CTRL_PRMLEN_SHIFT);
+
+		if (adapter->vlgrp)
+			mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
+
+		/* magic packet maybe Broadcast&multicast&Unicast frame */
+		if (wufc & AT_WUFC_MAG)
+			mac_ctrl_data |= MAC_CTRL_BC_EN;
+
+		dev_dbg(&pdev->dev,
+			"%s: suspend MAC=0x%x\n",
+			atl1e_driver_name, mac_ctrl_data);
+
+		AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data);
+		AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
+		/* pcie patch */
+		ctrl = AT_READ_REG(hw, REG_PCIE_PHYMISC);
+		ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
+		AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);
+		pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
+		goto suspend_exit;
+	}
+wol_dis:
+
+	/* WOL disabled */
+	AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
+
+	/* pcie patch */
+	ctrl = AT_READ_REG(hw, REG_PCIE_PHYMISC);
+	ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
+	AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);
+
+	atl1e_force_ps(hw);
+	hw->phy_configured = false; /* re-init PHY when resume */
+
+	pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
+
+suspend_exit:
+
+	if (netif_running(netdev))
+		atl1e_free_irq(adapter);
+
+	pci_disable_device(pdev);
+
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int atl1e_resume(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+	u32 err;
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+
+	err = pci_enable_device(pdev);
+	if (err) {
+		dev_err(&pdev->dev, "ATL1e: Cannot enable PCI"
+				" device from suspend\n");
+		return err;
+	}
+
+	pci_set_master(pdev);
+
+	AT_READ_REG(&adapter->hw, REG_WOL_CTRL); /* clear WOL status */
+
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	pci_enable_wake(pdev, PCI_D3cold, 0);
+
+	AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0);
+
+	if (netif_running(netdev))
+		err = atl1e_request_irq(adapter);
+		if (err)
+			return err;
+
+	atl1e_reset_hw(&adapter->hw);
+
+	if (netif_running(netdev))
+		atl1e_up(adapter);
+
+	netif_device_attach(netdev);
+
+	return 0;
+}
+#endif
+
+static void atl1e_shutdown(struct pci_dev *pdev)
+{
+	atl1e_suspend(pdev, PMSG_SUSPEND);
+}
+
+static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
+{
+	SET_NETDEV_DEV(netdev, &pdev->dev);
+	pci_set_drvdata(pdev, netdev);
+
+	netdev->irq  = pdev->irq;
+	netdev->open = &atl1e_open;
+	netdev->stop = &atl1e_close;
+	netdev->hard_start_xmit = &atl1e_xmit_frame;
+	netdev->get_stats = &atl1e_get_stats;
+	netdev->set_multicast_list = &atl1e_set_multi;
+	netdev->set_mac_address = &atl1e_set_mac_addr;
+	netdev->change_mtu = &atl1e_change_mtu;
+	netdev->do_ioctl = &atl1e_ioctl;
+	netdev->tx_timeout = &atl1e_tx_timeout;
+	netdev->watchdog_timeo = AT_TX_WATCHDOG;
+	netdev->vlan_rx_register = atl1e_vlan_rx_register;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	netdev->poll_controller = atl1e_netpoll;
+#endif
+	atl1e_set_ethtool_ops(netdev);
+
+	netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM |
+		NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+	netdev->features |= NETIF_F_LLTX;
+	netdev->features |= NETIF_F_TSO;
+	netdev->features |= NETIF_F_TSO6;
+
+	return 0;
+}
+
+/*
+ * atl1e_probe - Device Initialization Routine
+ * @pdev: PCI device information struct
+ * @ent: entry in atl1e_pci_tbl
+ *
+ * Returns 0 on success, negative on failure
+ *
+ * atl1e_probe initializes an adapter identified by a pci_dev structure.
+ * The OS initialization, configuring of the adapter private structure,
+ * and a hardware reset occur.
+ */
+static int __devinit atl1e_probe(struct pci_dev *pdev,
+				 const struct pci_device_id *ent)
+{
+	struct net_device *netdev;
+	struct atl1e_adapter *adapter = NULL;
+	static int cards_found;
+
+	int err = 0;
+
+	err = pci_enable_device(pdev);
+	if (err) {
+		dev_err(&pdev->dev, "cannot enable PCI device\n");
+		return err;
+	}
+
+	/*
+	 * The atl1e chip can DMA to 64-bit addresses, but it uses a single
+	 * shared register for the high 32 bits, so only a single, aligned,
+	 * 4 GB physical address range can be used at a time.
+	 *
+	 * Supporting 64-bit DMA on this hardware is more trouble than it's
+	 * worth.  It is far easier to limit to 32-bit DMA than update
+	 * various kernel subsystems to support the mechanics required by a
+	 * fixed-high-32-bit system.
+	 */
+	if ((pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) ||
+	    (pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK) != 0)) {
+		dev_err(&pdev->dev, "No usable DMA configuration,aborting\n");
+		goto err_dma;
+	}
+
+	err = pci_request_regions(pdev, atl1e_driver_name);
+	if (err) {
+		dev_err(&pdev->dev, "cannot obtain PCI resources\n");
+		goto err_pci_reg;
+	}
+
+	pci_set_master(pdev);
+
+	netdev = alloc_etherdev(sizeof(struct atl1e_adapter));
+	if (netdev == NULL) {
+		err = -ENOMEM;
+		dev_err(&pdev->dev, "etherdev alloc failed\n");
+		goto err_alloc_etherdev;
+	}
+
+	err = atl1e_init_netdev(netdev, pdev);
+	if (err) {
+		dev_err(&pdev->dev, "init netdevice failed\n");
+		goto err_init_netdev;
+	}
+	adapter = netdev_priv(netdev);
+	adapter->bd_number = cards_found;
+	adapter->netdev = netdev;
+	adapter->pdev = pdev;
+	adapter->hw.adapter = adapter;
+	adapter->hw.hw_addr = pci_iomap(pdev, BAR_0, 0);
+	if (!adapter->hw.hw_addr) {
+		err = -EIO;
+		dev_err(&pdev->dev, "cannot map device registers\n");
+		goto err_ioremap;
+	}
+	netdev->base_addr = (unsigned long)adapter->hw.hw_addr;
+
+	/* init mii data */
+	adapter->mii.dev = netdev;
+	adapter->mii.mdio_read  = atl1e_mdio_read;
+	adapter->mii.mdio_write = atl1e_mdio_write;
+	adapter->mii.phy_id_mask = 0x1f;
+	adapter->mii.reg_num_mask = MDIO_REG_ADDR_MASK;
+
+	netif_napi_add(netdev, &adapter->napi, atl1e_clean, 64);
+
+	init_timer(&adapter->phy_config_timer);
+	adapter->phy_config_timer.function = &atl1e_phy_config;
+	adapter->phy_config_timer.data = (unsigned long) adapter;
+
+	/* get user settings */
+	atl1e_check_options(adapter);
+	/*
+	 * Mark all PCI regions associated with PCI device
+	 * pdev as being reserved by owner atl1e_driver_name
+	 * Enables bus-mastering on the device and calls
+	 * pcibios_set_master to do the needed arch specific settings
+	 */
+	atl1e_setup_pcicmd(pdev);
+	/* setup the private structure */
+	err = atl1e_sw_init(adapter);
+	if (err) {
+		dev_err(&pdev->dev, "net device private data init failed\n");
+		goto err_sw_init;
+	}
+
+	/* Init GPHY as early as possible due to power saving issue  */
+	spin_lock(&adapter->mdio_lock);
+	atl1e_phy_init(&adapter->hw);
+	spin_unlock(&adapter->mdio_lock);
+	/* reset the controller to
+	 * put the device in a known good starting state */
+	err = atl1e_reset_hw(&adapter->hw);
+	if (err) {
+		err = -EIO;
+		goto err_reset;
+	}
+
+	if (atl1e_read_mac_addr(&adapter->hw) != 0) {
+		err = -EIO;
+		dev_err(&pdev->dev, "get mac address failed\n");
+		goto err_eeprom;
+	}
+
+	memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
+	memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);
+	dev_dbg(&pdev->dev, "mac address : %02x-%02x-%02x-%02x-%02x-%02x\n",
+			adapter->hw.mac_addr[0], adapter->hw.mac_addr[1],
+			adapter->hw.mac_addr[2], adapter->hw.mac_addr[3],
+			adapter->hw.mac_addr[4], adapter->hw.mac_addr[5]);
+
+	INIT_WORK(&adapter->reset_task, atl1e_reset_task);
+	INIT_WORK(&adapter->link_chg_task, atl1e_link_chg_task);
+	err = register_netdev(netdev);
+	if (err) {
+		dev_err(&pdev->dev, "register netdevice failed\n");
+		goto err_register;
+	}
+
+	/* assume we have no link for now */
+	netif_stop_queue(netdev);
+	netif_carrier_off(netdev);
+
+	cards_found++;
+
+	return 0;
+
+err_reset:
+err_register:
+err_sw_init:
+err_eeprom:
+	iounmap(adapter->hw.hw_addr);
+err_init_netdev:
+err_ioremap:
+	free_netdev(netdev);
+err_alloc_etherdev:
+	pci_release_regions(pdev);
+err_pci_reg:
+err_dma:
+	pci_disable_device(pdev);
+	return err;
+}
+
+/*
+ * atl1e_remove - Device Removal Routine
+ * @pdev: PCI device information struct
+ *
+ * atl1e_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device.  The could be caused by a
+ * Hot-Plug event, or because the driver is going to be removed from
+ * memory.
+ */
+static void __devexit atl1e_remove(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1e_adapter *adapter = netdev_priv(netdev);
+
+	/*
+	 * flush_scheduled work may reschedule our watchdog task, so
+	 * explicitly disable watchdog tasks from being rescheduled
+	 */
+	set_bit(__AT_DOWN, &adapter->flags);
+
+	atl1e_del_timer(adapter);
+	atl1e_cancel_work(adapter);
+
+	unregister_netdev(netdev);
+	atl1e_free_ring_resources(adapter);
+	atl1e_force_ps(&adapter->hw);
+	iounmap(adapter->hw.hw_addr);
+	pci_release_regions(pdev);
+	free_netdev(netdev);
+	pci_disable_device(pdev);
+}
+
+/*
+ * atl1e_io_error_detected - called when PCI error is detected
+ * @pdev: Pointer to PCI device
+ * @state: The current pci connection state
+ *
+ * This function is called after a PCI bus error affecting
+ * this device has been detected.
+ */
+static pci_ers_result_t
+atl1e_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1e_adapter *adapter = netdev->priv;
+
+	netif_device_detach(netdev);
+
+	if (netif_running(netdev))
+		atl1e_down(adapter);
+
+	pci_disable_device(pdev);
+
+	/* Request a slot slot reset. */
+	return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/*
+ * atl1e_io_slot_reset - called after the pci bus has been reset.
+ * @pdev: Pointer to PCI device
+ *
+ * Restart the card from scratch, as if from a cold-boot. Implementation
+ * resembles the first-half of the e1000_resume routine.
+ */
+static pci_ers_result_t atl1e_io_slot_reset(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1e_adapter *adapter = netdev->priv;
+
+	if (pci_enable_device(pdev)) {
+		dev_err(&pdev->dev,
+		       "ATL1e: Cannot re-enable PCI device after reset.\n");
+		return PCI_ERS_RESULT_DISCONNECT;
+	}
+	pci_set_master(pdev);
+
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	pci_enable_wake(pdev, PCI_D3cold, 0);
+
+	atl1e_reset_hw(&adapter->hw);
+
+	return PCI_ERS_RESULT_RECOVERED;
+}
+
+/*
+ * atl1e_io_resume - called when traffic can start flowing again.
+ * @pdev: Pointer to PCI device
+ *
+ * This callback is called when the error recovery driver tells us that
+ * its OK to resume normal operation. Implementation resembles the
+ * second-half of the atl1e_resume routine.
+ */
+static void atl1e_io_resume(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1e_adapter *adapter = netdev->priv;
+
+	if (netif_running(netdev)) {
+		if (atl1e_up(adapter)) {
+			dev_err(&pdev->dev,
+			  "ATL1e: can't bring device back up after reset\n");
+			return;
+		}
+	}
+
+	netif_device_attach(netdev);
+}
+
+static struct pci_error_handlers atl1e_err_handler = {
+	.error_detected = atl1e_io_error_detected,
+	.slot_reset = atl1e_io_slot_reset,
+	.resume = atl1e_io_resume,
+};
+
+static struct pci_driver atl1e_driver = {
+	.name     = atl1e_driver_name,
+	.id_table = atl1e_pci_tbl,
+	.probe    = atl1e_probe,
+	.remove   = __devexit_p(atl1e_remove),
+	/* Power Managment Hooks */
+#ifdef CONFIG_PM
+	.suspend  = atl1e_suspend,
+	.resume   = atl1e_resume,
+#endif
+	.shutdown = atl1e_shutdown,
+	.err_handler = &atl1e_err_handler
+};
+
+/*
+ * atl1e_init_module - Driver Registration Routine
+ *
+ * atl1e_init_module is the first routine called when the driver is
+ * loaded. All it does is register with the PCI subsystem.
+ */
+static int __init atl1e_init_module(void)
+{
+	return pci_register_driver(&atl1e_driver);
+}
+
+/*
+ * atl1e_exit_module - Driver Exit Cleanup Routine
+ *
+ * atl1e_exit_module is called just before the driver is removed
+ * from memory.
+ */
+static void __exit atl1e_exit_module(void)
+{
+	pci_unregister_driver(&atl1e_driver);
+}
+
+module_init(atl1e_init_module);
+module_exit(atl1e_exit_module);
diff --git a/drivers/net/atl1e/atl1e_param.c b/drivers/net/atl1e/atl1e_param.c
new file mode 100644
index 0000000..f72abb3
--- /dev/null
+++ b/drivers/net/atl1e/atl1e_param.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  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/netdevice.h>
+
+#include "atl1e.h"
+
+/* This is the only thing that needs to be changed to adjust the
+ * maximum number of ports that the driver can manage.
+ */
+
+#define ATL1E_MAX_NIC 32
+
+#define OPTION_UNSET    -1
+#define OPTION_DISABLED 0
+#define OPTION_ENABLED  1
+
+/* All parameters are treated the same, as an integer array of values.
+ * This macro just reduces the need to repeat the same declaration code
+ * over and over (plus this helps to avoid typo bugs).
+ */
+#define ATL1E_PARAM_INIT { [0 ... ATL1E_MAX_NIC] = OPTION_UNSET }
+
+#define ATL1E_PARAM(x, desc) \
+	static int __devinitdata x[ATL1E_MAX_NIC + 1] = ATL1E_PARAM_INIT; \
+	static int num_##x; \
+	module_param_array_named(x, x, int, &num_##x, 0); \
+	MODULE_PARM_DESC(x, desc);
+
+/* Transmit Memory count
+ *
+ * Valid Range: 64-2048
+ *
+ * Default Value: 128
+ */
+#define ATL1E_MIN_TX_DESC_CNT		32
+#define ATL1E_MAX_TX_DESC_CNT		1020
+#define ATL1E_DEFAULT_TX_DESC_CNT	128
+ATL1E_PARAM(tx_desc_cnt, "Transmit description count");
+
+/* Receive Memory Block Count
+ *
+ * Valid Range: 16-512
+ *
+ * Default Value: 128
+ */
+#define ATL1E_MIN_RX_MEM_SIZE		8    /* 8KB   */
+#define ATL1E_MAX_RX_MEM_SIZE		1024 /* 1MB   */
+#define ATL1E_DEFAULT_RX_MEM_SIZE	256  /* 128KB */
+ATL1E_PARAM(rx_mem_size, "memory size of rx buffer(KB)");
+
+/* User Specified MediaType Override
+ *
+ * Valid Range: 0-5
+ *  - 0    - auto-negotiate at all supported speeds
+ *  - 1    - only link at 100Mbps Full Duplex
+ *  - 2    - only link at 100Mbps Half Duplex
+ *  - 3    - only link at 10Mbps Full Duplex
+ *  - 4    - only link at 10Mbps Half Duplex
+ * Default Value: 0
+ */
+
+ATL1E_PARAM(media_type, "MediaType Select");
+
+/* Interrupt Moderate Timer in units of 2 us
+ *
+ * Valid Range: 10-65535
+ *
+ * Default Value: 45000(90ms)
+ */
+#define INT_MOD_DEFAULT_CNT             100 /* 200us */
+#define INT_MOD_MAX_CNT                 65000
+#define INT_MOD_MIN_CNT                 50
+ATL1E_PARAM(int_mod_timer, "Interrupt Moderator Timer");
+
+#define AUTONEG_ADV_DEFAULT  0x2F
+#define AUTONEG_ADV_MASK     0x2F
+#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
+
+#define FLASH_VENDOR_DEFAULT    0
+#define FLASH_VENDOR_MIN        0
+#define FLASH_VENDOR_MAX        2
+
+struct atl1e_option {
+	enum { enable_option, range_option, list_option } type;
+	char *name;
+	char *err;
+	int  def;
+	union {
+		struct { /* range_option info */
+			int min;
+			int max;
+		} r;
+		struct { /* list_option info */
+			int nr;
+			struct atl1e_opt_list { int i; char *str; } *p;
+		} l;
+	} arg;
+};
+
+static int __devinit atl1e_validate_option(int *value, struct atl1e_option *opt, struct pci_dev *pdev)
+{
+	if (*value == OPTION_UNSET) {
+		*value = opt->def;
+		return 0;
+	}
+
+	switch (opt->type) {
+	case enable_option:
+		switch (*value) {
+		case OPTION_ENABLED:
+			dev_info(&pdev->dev, "%s Enabled\n", opt->name);
+			return 0;
+		case OPTION_DISABLED:
+			dev_info(&pdev->dev, "%s Disabled\n", opt->name);
+			return 0;
+		}
+		break;
+	case range_option:
+		if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
+			dev_info(&pdev->dev, "%s set to %i\n", opt->name, *value);
+			return 0;
+		}
+		break;
+	case list_option:{
+			int i;
+			struct atl1e_opt_list *ent;
+
+			for (i = 0; i < opt->arg.l.nr; i++) {
+				ent = &opt->arg.l.p[i];
+				if (*value == ent->i) {
+					if (ent->str[0] != '\0')
+						dev_info(&pdev->dev, "%s\n",
+							ent->str);
+					return 0;
+				}
+			}
+			break;
+		}
+	default:
+		BUG();
+	}
+
+	dev_info(&pdev->dev, "Invalid %s specified (%i) %s\n",
+			opt->name, *value, opt->err);
+	*value = opt->def;
+	return -1;
+}
+
+/*
+ * atl1e_check_options - Range Checking for Command Line Parameters
+ * @adapter: board private structure
+ *
+ * This routine checks all command line parameters for valid user
+ * input.  If an invalid value is given, or if no user specified
+ * value exists, a default value is used.  The final value is stored
+ * in a variable in the adapter structure.
+ */
+void __devinit atl1e_check_options(struct atl1e_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	int bd = adapter->bd_number;
+	if (bd >= ATL1E_MAX_NIC) {
+		dev_notice(&pdev->dev, "no configuration for board #%i\n", bd);
+		dev_notice(&pdev->dev, "Using defaults for all values\n");
+	}
+
+	{ 		/* Transmit Ring Size */
+		struct atl1e_option opt = {
+			.type = range_option,
+			.name = "Transmit Ddescription Count",
+			.err  = "using default of "
+				__MODULE_STRING(ATL1E_DEFAULT_TX_DESC_CNT),
+			.def  = ATL1E_DEFAULT_TX_DESC_CNT,
+			.arg  = { .r = { .min = ATL1E_MIN_TX_DESC_CNT,
+					 .max = ATL1E_MAX_TX_DESC_CNT} }
+		};
+		int val;
+		if (num_tx_desc_cnt > bd) {
+			val = tx_desc_cnt[bd];
+			atl1e_validate_option(&val, &opt, pdev);
+			adapter->tx_ring.count = (u16) val & 0xFFFC;
+		} else
+			adapter->tx_ring.count = (u16)opt.def;
+	}
+
+	{ 		/* Receive Memory Block Count */
+		struct atl1e_option opt = {
+			.type = range_option,
+			.name = "Memory size of rx buffer(KB)",
+			.err  = "using default of "
+				__MODULE_STRING(ATL1E_DEFAULT_RX_MEM_SIZE),
+			.def  = ATL1E_DEFAULT_RX_MEM_SIZE,
+			.arg  = { .r = { .min = ATL1E_MIN_RX_MEM_SIZE,
+					 .max = ATL1E_MAX_RX_MEM_SIZE} }
+		};
+		int val;
+		if (num_rx_mem_size > bd) {
+			val = rx_mem_size[bd];
+			atl1e_validate_option(&val, &opt, pdev);
+			adapter->rx_ring.page_size = (u32)val * 1024;
+		} else {
+			adapter->rx_ring.page_size = (u32)opt.def * 1024;
+		}
+	}
+
+	{ 		/* Interrupt Moderate Timer */
+		struct atl1e_option opt = {
+			.type = range_option,
+			.name = "Interrupt Moderate Timer",
+			.err  = "using default of "
+				__MODULE_STRING(INT_MOD_DEFAULT_CNT),
+			.def  = INT_MOD_DEFAULT_CNT,
+			.arg  = { .r = { .min = INT_MOD_MIN_CNT,
+					 .max = INT_MOD_MAX_CNT} }
+		} ;
+		int val;
+		if (num_int_mod_timer > bd) {
+			val = int_mod_timer[bd];
+			atl1e_validate_option(&val, &opt, pdev);
+			adapter->hw.imt = (u16) val;
+		} else
+			adapter->hw.imt = (u16)(opt.def);
+	}
+
+	{ 		/* MediaType */
+		struct atl1e_option opt = {
+			.type = range_option,
+			.name = "Speed/Duplex Selection",
+			.err  = "using default of "
+				__MODULE_STRING(MEDIA_TYPE_AUTO_SENSOR),
+			.def  = MEDIA_TYPE_AUTO_SENSOR,
+			.arg  = { .r = { .min = MEDIA_TYPE_AUTO_SENSOR,
+					 .max = MEDIA_TYPE_10M_HALF} }
+		} ;
+		int val;
+		if (num_media_type > bd) {
+			val = media_type[bd];
+			atl1e_validate_option(&val, &opt, pdev);
+			adapter->hw.media_type = (u16) val;
+		} else
+			adapter->hw.media_type = (u16)(opt.def);
+
+	}
+}
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c
index 3e22e78..f12e3d1 100644
--- a/drivers/net/atlx/atl1.c
+++ b/drivers/net/atlx/atl1.c
@@ -1308,7 +1308,6 @@
 				dev_info(&adapter->pdev->dev, "link is down\n");
 			adapter->link_speed = SPEED_0;
 			netif_carrier_off(netdev);
-			netif_stop_queue(netdev);
 		}
 		return 0;
 	}
@@ -1358,7 +1357,6 @@
 		if (!netif_carrier_ok(netdev)) {
 			/* Link down -> Up */
 			netif_carrier_on(netdev);
-			netif_wake_queue(netdev);
 		}
 		return 0;
 	}
@@ -2627,6 +2625,7 @@
 	mod_timer(&adapter->watchdog_timer, jiffies);
 	atlx_irq_enable(adapter);
 	atl1_check_link(adapter);
+	netif_start_queue(netdev);
 	return 0;
 
 err_up:
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index 3ab61e40..cb8be49 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -911,9 +911,8 @@
 	if(phydev->link != aup->old_link) {
 		// link state changed
 
-		if (phydev->link) // link went up
-			netif_tx_schedule_all(dev);
-		else { // link went down
+		if (!phydev->link) {
+			/* link went down */
 			aup->old_speed = 0;
 			aup->old_duplex = -1;
 		}
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
index a6a3da8..a8ec60e 100644
--- a/drivers/net/bfin_mac.c
+++ b/drivers/net/bfin_mac.c
@@ -357,7 +357,6 @@
 		if (!lp->old_link) {
 			new_state = 1;
 			lp->old_link = 1;
-			netif_tx_schedule_all(dev);
 		}
 	} else if (lp->old_link) {
 		new_state = 1;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 9737c06..a641eea 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -5041,6 +5041,7 @@
 }
 
 static struct lock_class_key bonding_netdev_xmit_lock_key;
+static struct lock_class_key bonding_netdev_addr_lock_key;
 
 static void bond_set_lockdep_class_one(struct net_device *dev,
 				       struct netdev_queue *txq,
@@ -5052,6 +5053,8 @@
 
 static void bond_set_lockdep_class(struct net_device *dev)
 {
+	lockdep_set_class(&dev->addr_list_lock,
+			  &bonding_netdev_addr_lock_key);
 	netdev_for_each_tx_queue(dev, bond_set_lockdep_class_one, NULL);
 }
 
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
index fbd4280..a7800e5 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/cpmac.c
@@ -945,10 +945,8 @@
 		if (!priv->oldlink) {
 			new_state = 1;
 			priv->oldlink = 1;
-			netif_tx_schedule_all(dev);
 		}
 	} else if (priv->oldlink) {
-		netif_tx_stop_all_queues(dev);
 		new_state = 1;
 		priv->oldlink = 0;
 		priv->oldspeed = 0;
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 952e10d..0b0f1c4 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -888,19 +888,22 @@
 			dev_dbg(db->dev, "RST: RX Len:%x\n", RxLen);
 		}
 
-		if (rxhdr.RxStatus & 0xbf) {
+		/* rxhdr.RxStatus is identical to RSR register. */
+		if (rxhdr.RxStatus & (RSR_FOE | RSR_CE | RSR_AE |
+				      RSR_PLE | RSR_RWTO |
+				      RSR_LCS | RSR_RF)) {
 			GoodPacket = false;
-			if (rxhdr.RxStatus & 0x01) {
+			if (rxhdr.RxStatus & RSR_FOE) {
 				if (netif_msg_rx_err(db))
 					dev_dbg(db->dev, "fifo error\n");
 				dev->stats.rx_fifo_errors++;
 			}
-			if (rxhdr.RxStatus & 0x02) {
+			if (rxhdr.RxStatus & RSR_CE) {
 				if (netif_msg_rx_err(db))
 					dev_dbg(db->dev, "crc error\n");
 				dev->stats.rx_crc_errors++;
 			}
-			if (rxhdr.RxStatus & 0x80) {
+			if (rxhdr.RxStatus & RSR_RF) {
 				if (netif_msg_rx_err(db))
 					dev_dbg(db->dev, "length error\n");
 				dev->stats.rx_length_errors++;
@@ -1067,7 +1070,7 @@
 	/* Fill the phyxcer register into REG_0C */
 	iow(db, DM9000_EPAR, DM9000_PHY | reg);
 
-	iow(db, DM9000_EPCR, 0xc);	/* Issue phyxcer read command */
+	iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS);	/* Issue phyxcer read command */
 
 	writeb(reg_save, db->io_addr);
 	spin_unlock_irqrestore(&db->lock,flags);
@@ -1118,7 +1121,7 @@
 	iow(db, DM9000_EPDRL, value);
 	iow(db, DM9000_EPDRH, value >> 8);
 
-	iow(db, DM9000_EPCR, 0xa);	/* Issue phyxcer write command */
+	iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW);	/* Issue phyxcer write command */
 
 	writeb(reg_save, db->io_addr);
 	spin_unlock_irqrestore(&db->lock, flags);
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 31feae1..19e317e 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -90,10 +90,13 @@
 #define E1000_ERR(args...) printk(KERN_ERR "e1000: " args)
 
 #define PFX "e1000: "
-#define DPRINTK(nlevel, klevel, fmt, args...) \
-	(void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \
-	printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \
-		__FUNCTION__ , ## args))
+
+#define DPRINTK(nlevel, klevel, fmt, args...)				\
+do {									\
+	if (NETIF_MSG_##nlevel & adapter->msg_enable)			\
+		printk(KERN_##klevel PFX "%s: %s: " fmt,		\
+		       adapter->netdev->name, __func__, ##args);	\
+} while (0)
 
 #define E1000_MAX_INTR 10
 
@@ -151,9 +154,9 @@
 #define E1000_MASTER_SLAVE	e1000_ms_hw_default
 #endif
 
-#define E1000_MNG_VLAN_NONE -1
+#define E1000_MNG_VLAN_NONE (-1)
 /* Number of packet split data buffers (not including the header buffer) */
-#define PS_PAGE_BUFFERS MAX_PS_BUFFERS-1
+#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1)
 
 /* wrapper around a pointer to a socket buffer,
  * so a DMA handle can be stored along with the buffer */
@@ -165,9 +168,13 @@
 	u16 next_to_watch;
 };
 
+struct e1000_ps_page {
+	struct page *ps_page[PS_PAGE_BUFFERS];
+};
 
-struct e1000_ps_page { struct page *ps_page[PS_PAGE_BUFFERS]; };
-struct e1000_ps_page_dma { u64 ps_page_dma[PS_PAGE_BUFFERS]; };
+struct e1000_ps_page_dma {
+	u64 ps_page_dma[PS_PAGE_BUFFERS];
+};
 
 struct e1000_tx_ring {
 	/* pointer to the descriptor ring memory */
@@ -217,13 +224,13 @@
 	u16 rdt;
 };
 
-#define E1000_DESC_UNUSED(R) \
-	((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
-	(R)->next_to_clean - (R)->next_to_use - 1)
+#define E1000_DESC_UNUSED(R)						\
+	((((R)->next_to_clean > (R)->next_to_use)			\
+	  ? 0 : (R)->count) + (R)->next_to_clean - (R)->next_to_use - 1)
 
-#define E1000_RX_DESC_PS(R, i)	    \
+#define E1000_RX_DESC_PS(R, i)						\
 	(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
-#define E1000_RX_DESC_EXT(R, i)	    \
+#define E1000_RX_DESC_EXT(R, i)						\
 	(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
 #define E1000_GET_DESC(R, i, type)	(&(((struct type *)((R).desc))[i]))
 #define E1000_RX_DESC(R, i)		E1000_GET_DESC(R, i, e1000_rx_desc)
@@ -246,9 +253,7 @@
 	u16 link_speed;
 	u16 link_duplex;
 	spinlock_t stats_lock;
-#ifdef CONFIG_E1000_NAPI
 	spinlock_t tx_queue_lock;
-#endif
 	unsigned int total_tx_bytes;
 	unsigned int total_tx_packets;
 	unsigned int total_rx_bytes;
@@ -286,22 +291,16 @@
 	bool detect_tx_hung;
 
 	/* RX */
-#ifdef CONFIG_E1000_NAPI
-	bool (*clean_rx) (struct e1000_adapter *adapter,
-			  struct e1000_rx_ring *rx_ring,
-			  int *work_done, int work_to_do);
-#else
-	bool (*clean_rx) (struct e1000_adapter *adapter,
-			  struct e1000_rx_ring *rx_ring);
-#endif
-	void (*alloc_rx_buf) (struct e1000_adapter *adapter,
-			      struct e1000_rx_ring *rx_ring,
-				int cleaned_count);
+	bool (*clean_rx)(struct e1000_adapter *adapter,
+			 struct e1000_rx_ring *rx_ring,
+			 int *work_done, int work_to_do);
+	void (*alloc_rx_buf)(struct e1000_adapter *adapter,
+			     struct e1000_rx_ring *rx_ring,
+			     int cleaned_count);
 	struct e1000_rx_ring *rx_ring;      /* One per active queue */
-#ifdef CONFIG_E1000_NAPI
 	struct napi_struct napi;
 	struct net_device *polling_netdev;  /* One per active queue */
-#endif
+
 	int num_tx_queues;
 	int num_rx_queues;
 
@@ -317,7 +316,6 @@
 	u64 gorcl_old;
 	u16 rx_ps_bsize0;
 
-
 	/* OS defined structs */
 	struct net_device *netdev;
 	struct pci_dev *pdev;
@@ -342,6 +340,10 @@
 	bool quad_port_a;
 	unsigned long flags;
 	u32 eeprom_wol;
+
+	/* for ioport free */
+	int bars;
+	int need_ioport;
 };
 
 enum e1000_state_t {
@@ -353,9 +355,18 @@
 extern char e1000_driver_name[];
 extern const char e1000_driver_version[];
 
+extern int e1000_up(struct e1000_adapter *adapter);
+extern void e1000_down(struct e1000_adapter *adapter);
+extern void e1000_reinit_locked(struct e1000_adapter *adapter);
+extern void e1000_reset(struct e1000_adapter *adapter);
+extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx);
+extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
+extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
+extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
+extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
+extern void e1000_update_stats(struct e1000_adapter *adapter);
 extern void e1000_power_up_phy(struct e1000_adapter *);
 extern void e1000_set_ethtool_ops(struct net_device *netdev);
 extern void e1000_check_options(struct e1000_adapter *adapter);
 
-
 #endif /* _E1000_H_ */
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index a3f6a9c..6a3893a 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -29,21 +29,8 @@
 /* ethtool support for e1000 */
 
 #include "e1000.h"
-
 #include <asm/uaccess.h>
 
-extern int e1000_up(struct e1000_adapter *adapter);
-extern void e1000_down(struct e1000_adapter *adapter);
-extern void e1000_reinit_locked(struct e1000_adapter *adapter);
-extern void e1000_reset(struct e1000_adapter *adapter);
-extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx);
-extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
-extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
-extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
-extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
-extern void e1000_update_stats(struct e1000_adapter *adapter);
-
-
 struct e1000_stats {
 	char stat_string[ETH_GSTRING_LEN];
 	int sizeof_stat;
@@ -112,8 +99,8 @@
 };
 #define E1000_TEST_LEN	ARRAY_SIZE(e1000_gstrings_test)
 
-static int
-e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+static int e1000_get_settings(struct net_device *netdev,
+			      struct ethtool_cmd *ecmd)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
@@ -162,7 +149,7 @@
 			ecmd->transceiver = XCVR_EXTERNAL;
 	}
 
-	if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU) {
+	if (er32(STATUS) & E1000_STATUS_LU) {
 
 		e1000_get_speed_and_duplex(hw, &adapter->link_speed,
 		                                   &adapter->link_duplex);
@@ -185,8 +172,8 @@
 	return 0;
 }
 
-static int
-e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+static int e1000_set_settings(struct net_device *netdev,
+			      struct ethtool_cmd *ecmd)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
@@ -231,9 +218,8 @@
 	return 0;
 }
 
-static void
-e1000_get_pauseparam(struct net_device *netdev,
-                     struct ethtool_pauseparam *pause)
+static void e1000_get_pauseparam(struct net_device *netdev,
+				 struct ethtool_pauseparam *pause)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
@@ -251,9 +237,8 @@
 	}
 }
 
-static int
-e1000_set_pauseparam(struct net_device *netdev,
-                     struct ethtool_pauseparam *pause)
+static int e1000_set_pauseparam(struct net_device *netdev,
+				struct ethtool_pauseparam *pause)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
@@ -289,15 +274,13 @@
 	return retval;
 }
 
-static u32
-e1000_get_rx_csum(struct net_device *netdev)
+static u32 e1000_get_rx_csum(struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	return adapter->rx_csum;
 }
 
-static int
-e1000_set_rx_csum(struct net_device *netdev, u32 data)
+static int e1000_set_rx_csum(struct net_device *netdev, u32 data)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	adapter->rx_csum = data;
@@ -309,18 +292,17 @@
 	return 0;
 }
 
-static u32
-e1000_get_tx_csum(struct net_device *netdev)
+static u32 e1000_get_tx_csum(struct net_device *netdev)
 {
 	return (netdev->features & NETIF_F_HW_CSUM) != 0;
 }
 
-static int
-e1000_set_tx_csum(struct net_device *netdev, u32 data)
+static int e1000_set_tx_csum(struct net_device *netdev, u32 data)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
 
-	if (adapter->hw.mac_type < e1000_82543) {
+	if (hw->mac_type < e1000_82543) {
 		if (!data)
 			return -EINVAL;
 		return 0;
@@ -334,12 +316,13 @@
 	return 0;
 }
 
-static int
-e1000_set_tso(struct net_device *netdev, u32 data)
+static int e1000_set_tso(struct net_device *netdev, u32 data)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
-	if ((adapter->hw.mac_type < e1000_82544) ||
-	    (adapter->hw.mac_type == e1000_82547))
+	struct e1000_hw *hw = &adapter->hw;
+
+	if ((hw->mac_type < e1000_82544) ||
+	    (hw->mac_type == e1000_82547))
 		return data ? -EINVAL : 0;
 
 	if (data)
@@ -357,30 +340,26 @@
 	return 0;
 }
 
-static u32
-e1000_get_msglevel(struct net_device *netdev)
+static u32 e1000_get_msglevel(struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	return adapter->msg_enable;
 }
 
-static void
-e1000_set_msglevel(struct net_device *netdev, u32 data)
+static void e1000_set_msglevel(struct net_device *netdev, u32 data)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	adapter->msg_enable = data;
 }
 
-static int
-e1000_get_regs_len(struct net_device *netdev)
+static int e1000_get_regs_len(struct net_device *netdev)
 {
 #define E1000_REGS_LEN 32
 	return E1000_REGS_LEN * sizeof(u32);
 }
 
-static void
-e1000_get_regs(struct net_device *netdev,
-	       struct ethtool_regs *regs, void *p)
+static void e1000_get_regs(struct net_device *netdev, struct ethtool_regs *regs,
+			   void *p)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
@@ -391,22 +370,22 @@
 
 	regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;
 
-	regs_buff[0]  = E1000_READ_REG(hw, CTRL);
-	regs_buff[1]  = E1000_READ_REG(hw, STATUS);
+	regs_buff[0]  = er32(CTRL);
+	regs_buff[1]  = er32(STATUS);
 
-	regs_buff[2]  = E1000_READ_REG(hw, RCTL);
-	regs_buff[3]  = E1000_READ_REG(hw, RDLEN);
-	regs_buff[4]  = E1000_READ_REG(hw, RDH);
-	regs_buff[5]  = E1000_READ_REG(hw, RDT);
-	regs_buff[6]  = E1000_READ_REG(hw, RDTR);
+	regs_buff[2]  = er32(RCTL);
+	regs_buff[3]  = er32(RDLEN);
+	regs_buff[4]  = er32(RDH);
+	regs_buff[5]  = er32(RDT);
+	regs_buff[6]  = er32(RDTR);
 
-	regs_buff[7]  = E1000_READ_REG(hw, TCTL);
-	regs_buff[8]  = E1000_READ_REG(hw, TDLEN);
-	regs_buff[9]  = E1000_READ_REG(hw, TDH);
-	regs_buff[10] = E1000_READ_REG(hw, TDT);
-	regs_buff[11] = E1000_READ_REG(hw, TIDV);
+	regs_buff[7]  = er32(TCTL);
+	regs_buff[8]  = er32(TDLEN);
+	regs_buff[9]  = er32(TDH);
+	regs_buff[10] = er32(TDT);
+	regs_buff[11] = er32(TIDV);
 
-	regs_buff[12] = adapter->hw.phy_type;  /* PHY type (IGP=1, M88=0) */
+	regs_buff[12] = hw->phy_type;  /* PHY type (IGP=1, M88=0) */
 	if (hw->phy_type == e1000_phy_igp) {
 		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
 				    IGP01E1000_PHY_AGC_A);
@@ -464,20 +443,20 @@
 	if (hw->mac_type >= e1000_82540 &&
 	    hw->mac_type < e1000_82571 &&
 	    hw->media_type == e1000_media_type_copper) {
-		regs_buff[26] = E1000_READ_REG(hw, MANC);
+		regs_buff[26] = er32(MANC);
 	}
 }
 
-static int
-e1000_get_eeprom_len(struct net_device *netdev)
+static int e1000_get_eeprom_len(struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
-	return adapter->hw.eeprom.word_size * 2;
+	struct e1000_hw *hw = &adapter->hw;
+
+	return hw->eeprom.word_size * 2;
 }
 
-static int
-e1000_get_eeprom(struct net_device *netdev,
-                      struct ethtool_eeprom *eeprom, u8 *bytes)
+static int e1000_get_eeprom(struct net_device *netdev,
+			    struct ethtool_eeprom *eeprom, u8 *bytes)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
@@ -504,10 +483,12 @@
 					    last_word - first_word + 1,
 					    eeprom_buff);
 	else {
-		for (i = 0; i < last_word - first_word + 1; i++)
-			if ((ret_val = e1000_read_eeprom(hw, first_word + i, 1,
-							&eeprom_buff[i])))
+		for (i = 0; i < last_word - first_word + 1; i++) {
+			ret_val = e1000_read_eeprom(hw, first_word + i, 1,
+						    &eeprom_buff[i]);
+			if (ret_val)
 				break;
+		}
 	}
 
 	/* Device's eeprom is always little-endian, word addressable */
@@ -521,9 +502,8 @@
 	return ret_val;
 }
 
-static int
-e1000_set_eeprom(struct net_device *netdev,
-                      struct ethtool_eeprom *eeprom, u8 *bytes)
+static int e1000_set_eeprom(struct net_device *netdev,
+			    struct ethtool_eeprom *eeprom, u8 *bytes)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
@@ -584,11 +564,11 @@
 	return ret_val;
 }
 
-static void
-e1000_get_drvinfo(struct net_device *netdev,
-                       struct ethtool_drvinfo *drvinfo)
+static void e1000_get_drvinfo(struct net_device *netdev,
+			      struct ethtool_drvinfo *drvinfo)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
 	char firmware_version[32];
 	u16 eeprom_data;
 
@@ -597,8 +577,8 @@
 
 	/* EEPROM image version # is reported as firmware version # for
 	 * 8257{1|2|3} controllers */
-	e1000_read_eeprom(&adapter->hw, 5, 1, &eeprom_data);
-	switch (adapter->hw.mac_type) {
+	e1000_read_eeprom(hw, 5, 1, &eeprom_data);
+	switch (hw->mac_type) {
 	case e1000_82571:
 	case e1000_82572:
 	case e1000_82573:
@@ -619,12 +599,12 @@
 	drvinfo->eedump_len = e1000_get_eeprom_len(netdev);
 }
 
-static void
-e1000_get_ringparam(struct net_device *netdev,
-                    struct ethtool_ringparam *ring)
+static void e1000_get_ringparam(struct net_device *netdev,
+				struct ethtool_ringparam *ring)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
-	e1000_mac_type mac_type = adapter->hw.mac_type;
+	struct e1000_hw *hw = &adapter->hw;
+	e1000_mac_type mac_type = hw->mac_type;
 	struct e1000_tx_ring *txdr = adapter->tx_ring;
 	struct e1000_rx_ring *rxdr = adapter->rx_ring;
 
@@ -640,12 +620,12 @@
 	ring->rx_jumbo_pending = 0;
 }
 
-static int
-e1000_set_ringparam(struct net_device *netdev,
-                    struct ethtool_ringparam *ring)
+static int e1000_set_ringparam(struct net_device *netdev,
+			       struct ethtool_ringparam *ring)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
-	e1000_mac_type mac_type = adapter->hw.mac_type;
+	struct e1000_hw *hw = &adapter->hw;
+	e1000_mac_type mac_type = hw->mac_type;
 	struct e1000_tx_ring *txdr, *tx_old;
 	struct e1000_rx_ring *rxdr, *rx_old;
 	int i, err;
@@ -691,9 +671,11 @@
 
 	if (netif_running(adapter->netdev)) {
 		/* Try to get new resources before deleting old */
-		if ((err = e1000_setup_all_rx_resources(adapter)))
+		err = e1000_setup_all_rx_resources(adapter);
+		if (err)
 			goto err_setup_rx;
-		if ((err = e1000_setup_all_tx_resources(adapter)))
+		err = e1000_setup_all_tx_resources(adapter);
+		if (err)
 			goto err_setup_tx;
 
 		/* save the new, restore the old in order to free it,
@@ -707,7 +689,8 @@
 		kfree(rx_old);
 		adapter->rx_ring = rxdr;
 		adapter->tx_ring = txdr;
-		if ((err = e1000_up(adapter)))
+		err = e1000_up(adapter);
+		if (err)
 			goto err_setup;
 	}
 
@@ -728,12 +711,13 @@
 	return err;
 }
 
-static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data,
-			     int reg, u32 mask, u32 write)
+static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data, int reg,
+			     u32 mask, u32 write)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	static const u32 test[] =
 		{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
-	u8 __iomem *address = adapter->hw.hw_addr + reg;
+	u8 __iomem *address = hw->hw_addr + reg;
 	u32 read;
 	int i;
 
@@ -751,10 +735,11 @@
 	return false;
 }
 
-static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data,
-			      int reg, u32 mask, u32 write)
+static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data, int reg,
+			      u32 mask, u32 write)
 {
-	u8 __iomem *address = adapter->hw.hw_addr + reg;
+	struct e1000_hw *hw = &adapter->hw;
+	u8 __iomem *address = hw->hw_addr + reg;
 	u32 read;
 
 	writel(write & mask, address);
@@ -772,7 +757,7 @@
 #define REG_PATTERN_TEST(reg, mask, write)			     \
 	do {							     \
 		if (reg_pattern_test(adapter, data,		     \
-			     (adapter->hw.mac_type >= e1000_82543)   \
+			     (hw->mac_type >= e1000_82543)   \
 			     ? E1000_##reg : E1000_82542_##reg,	     \
 			     mask, write))			     \
 			return 1;				     \
@@ -781,22 +766,22 @@
 #define REG_SET_AND_CHECK(reg, mask, write)			     \
 	do {							     \
 		if (reg_set_and_check(adapter, data,		     \
-			      (adapter->hw.mac_type >= e1000_82543)  \
+			      (hw->mac_type >= e1000_82543)  \
 			      ? E1000_##reg : E1000_82542_##reg,     \
 			      mask, write))			     \
 			return 1;				     \
 	} while (0)
 
-static int
-e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
+static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
 {
 	u32 value, before, after;
 	u32 i, toggle;
+	struct e1000_hw *hw = &adapter->hw;
 
 	/* The status register is Read Only, so a write should fail.
 	 * Some bits that get toggled are ignored.
 	 */
-	switch (adapter->hw.mac_type) {
+	switch (hw->mac_type) {
 	/* there are several bits on newer hardware that are r/w */
 	case e1000_82571:
 	case e1000_82572:
@@ -812,10 +797,10 @@
 		break;
 	}
 
-	before = E1000_READ_REG(&adapter->hw, STATUS);
-	value = (E1000_READ_REG(&adapter->hw, STATUS) & toggle);
-	E1000_WRITE_REG(&adapter->hw, STATUS, toggle);
-	after = E1000_READ_REG(&adapter->hw, STATUS) & toggle;
+	before = er32(STATUS);
+	value = (er32(STATUS) & toggle);
+	ew32(STATUS, toggle);
+	after = er32(STATUS) & toggle;
 	if (value != after) {
 		DPRINTK(DRV, ERR, "failed STATUS register test got: "
 		        "0x%08X expected: 0x%08X\n", after, value);
@@ -823,9 +808,9 @@
 		return 1;
 	}
 	/* restore previous status */
-	E1000_WRITE_REG(&adapter->hw, STATUS, before);
+	ew32(STATUS, before);
 
-	if (adapter->hw.mac_type != e1000_ich8lan) {
+	if (hw->mac_type != e1000_ich8lan) {
 		REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF);
 		REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF);
 		REG_PATTERN_TEST(FCT, 0x0000FFFF, 0xFFFFFFFF);
@@ -845,20 +830,20 @@
 
 	REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x00000000);
 
-	before = (adapter->hw.mac_type == e1000_ich8lan ?
+	before = (hw->mac_type == e1000_ich8lan ?
 	          0x06C3B33E : 0x06DFB3FE);
 	REG_SET_AND_CHECK(RCTL, before, 0x003FFFFB);
 	REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000);
 
-	if (adapter->hw.mac_type >= e1000_82543) {
+	if (hw->mac_type >= e1000_82543) {
 
 		REG_SET_AND_CHECK(RCTL, before, 0xFFFFFFFF);
 		REG_PATTERN_TEST(RDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
-		if (adapter->hw.mac_type != e1000_ich8lan)
+		if (hw->mac_type != e1000_ich8lan)
 			REG_PATTERN_TEST(TXCW, 0xC000FFFF, 0x0000FFFF);
 		REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
 		REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF);
-		value = (adapter->hw.mac_type == e1000_ich8lan ?
+		value = (hw->mac_type == e1000_ich8lan ?
 		         E1000_RAR_ENTRIES_ICH8LAN : E1000_RAR_ENTRIES);
 		for (i = 0; i < value; i++) {
 			REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), 0x8003FFFF,
@@ -874,7 +859,7 @@
 
 	}
 
-	value = (adapter->hw.mac_type == e1000_ich8lan ?
+	value = (hw->mac_type == e1000_ich8lan ?
 			E1000_MC_TBL_SIZE_ICH8LAN : E1000_MC_TBL_SIZE);
 	for (i = 0; i < value; i++)
 		REG_PATTERN_TEST(MTA + (i << 2), 0xFFFFFFFF, 0xFFFFFFFF);
@@ -883,9 +868,9 @@
 	return 0;
 }
 
-static int
-e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data)
+static int e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	u16 temp;
 	u16 checksum = 0;
 	u16 i;
@@ -893,7 +878,7 @@
 	*data = 0;
 	/* Read and add up the contents of the EEPROM */
 	for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
-		if ((e1000_read_eeprom(&adapter->hw, i, 1, &temp)) < 0) {
+		if ((e1000_read_eeprom(hw, i, 1, &temp)) < 0) {
 			*data = 1;
 			break;
 		}
@@ -901,30 +886,30 @@
 	}
 
 	/* If Checksum is not Correct return error else test passed */
-	if ((checksum != (u16) EEPROM_SUM) && !(*data))
+	if ((checksum != (u16)EEPROM_SUM) && !(*data))
 		*data = 2;
 
 	return *data;
 }
 
-static irqreturn_t
-e1000_test_intr(int irq, void *data)
+static irqreturn_t e1000_test_intr(int irq, void *data)
 {
-	struct net_device *netdev = (struct net_device *) data;
+	struct net_device *netdev = (struct net_device *)data;
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
 
-	adapter->test_icr |= E1000_READ_REG(&adapter->hw, ICR);
+	adapter->test_icr |= er32(ICR);
 
 	return IRQ_HANDLED;
 }
 
-static int
-e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
+static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
 {
 	struct net_device *netdev = adapter->netdev;
 	u32 mask, i = 0;
 	bool shared_int = true;
 	u32 irq = adapter->pdev->irq;
+	struct e1000_hw *hw = &adapter->hw;
 
 	*data = 0;
 
@@ -942,13 +927,13 @@
 	        (shared_int ? "shared" : "unshared"));
 
 	/* Disable all the interrupts */
-	E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF);
+	ew32(IMC, 0xFFFFFFFF);
 	msleep(10);
 
 	/* Test each interrupt */
 	for (; i < 10; i++) {
 
-		if (adapter->hw.mac_type == e1000_ich8lan && i == 8)
+		if (hw->mac_type == e1000_ich8lan && i == 8)
 			continue;
 
 		/* Interrupt to test */
@@ -962,8 +947,8 @@
 			 * test failed.
 			 */
 			adapter->test_icr = 0;
-			E1000_WRITE_REG(&adapter->hw, IMC, mask);
-			E1000_WRITE_REG(&adapter->hw, ICS, mask);
+			ew32(IMC, mask);
+			ew32(ICS, mask);
 			msleep(10);
 
 			if (adapter->test_icr & mask) {
@@ -979,8 +964,8 @@
 		 * test failed.
 		 */
 		adapter->test_icr = 0;
-		E1000_WRITE_REG(&adapter->hw, IMS, mask);
-		E1000_WRITE_REG(&adapter->hw, ICS, mask);
+		ew32(IMS, mask);
+		ew32(ICS, mask);
 		msleep(10);
 
 		if (!(adapter->test_icr & mask)) {
@@ -996,8 +981,8 @@
 			 * test failed.
 			 */
 			adapter->test_icr = 0;
-			E1000_WRITE_REG(&adapter->hw, IMC, ~mask & 0x00007FFF);
-			E1000_WRITE_REG(&adapter->hw, ICS, ~mask & 0x00007FFF);
+			ew32(IMC, ~mask & 0x00007FFF);
+			ew32(ICS, ~mask & 0x00007FFF);
 			msleep(10);
 
 			if (adapter->test_icr) {
@@ -1008,7 +993,7 @@
 	}
 
 	/* Disable all the interrupts */
-	E1000_WRITE_REG(&adapter->hw, IMC, 0xFFFFFFFF);
+	ew32(IMC, 0xFFFFFFFF);
 	msleep(10);
 
 	/* Unhook test interrupt handler */
@@ -1017,8 +1002,7 @@
 	return *data;
 }
 
-static void
-e1000_free_desc_rings(struct e1000_adapter *adapter)
+static void e1000_free_desc_rings(struct e1000_adapter *adapter)
 {
 	struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
 	struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
@@ -1064,9 +1048,9 @@
 	return;
 }
 
-static int
-e1000_setup_desc_rings(struct e1000_adapter *adapter)
+static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
 	struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
 	struct pci_dev *pdev = adapter->pdev;
@@ -1078,41 +1062,39 @@
 	if (!txdr->count)
 		txdr->count = E1000_DEFAULT_TXD;
 
-	if (!(txdr->buffer_info = kcalloc(txdr->count,
-	                                  sizeof(struct e1000_buffer),
-		                          GFP_KERNEL))) {
+	txdr->buffer_info = kcalloc(txdr->count, sizeof(struct e1000_buffer),
+				    GFP_KERNEL);
+	if (!txdr->buffer_info) {
 		ret_val = 1;
 		goto err_nomem;
 	}
 
 	txdr->size = txdr->count * sizeof(struct e1000_tx_desc);
 	txdr->size = ALIGN(txdr->size, 4096);
-	if (!(txdr->desc = pci_alloc_consistent(pdev, txdr->size,
-	                                        &txdr->dma))) {
+	txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
+	if (!txdr->desc) {
 		ret_val = 2;
 		goto err_nomem;
 	}
 	memset(txdr->desc, 0, txdr->size);
 	txdr->next_to_use = txdr->next_to_clean = 0;
 
-	E1000_WRITE_REG(&adapter->hw, TDBAL,
-			((u64) txdr->dma & 0x00000000FFFFFFFF));
-	E1000_WRITE_REG(&adapter->hw, TDBAH, ((u64) txdr->dma >> 32));
-	E1000_WRITE_REG(&adapter->hw, TDLEN,
-			txdr->count * sizeof(struct e1000_tx_desc));
-	E1000_WRITE_REG(&adapter->hw, TDH, 0);
-	E1000_WRITE_REG(&adapter->hw, TDT, 0);
-	E1000_WRITE_REG(&adapter->hw, TCTL,
-			E1000_TCTL_PSP | E1000_TCTL_EN |
-			E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT |
-			E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT);
+	ew32(TDBAL, ((u64)txdr->dma & 0x00000000FFFFFFFF));
+	ew32(TDBAH, ((u64)txdr->dma >> 32));
+	ew32(TDLEN, txdr->count * sizeof(struct e1000_tx_desc));
+	ew32(TDH, 0);
+	ew32(TDT, 0);
+	ew32(TCTL, E1000_TCTL_PSP | E1000_TCTL_EN |
+	     E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT |
+	     E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT);
 
 	for (i = 0; i < txdr->count; i++) {
 		struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*txdr, i);
 		struct sk_buff *skb;
 		unsigned int size = 1024;
 
-		if (!(skb = alloc_skb(size, GFP_KERNEL))) {
+		skb = alloc_skb(size, GFP_KERNEL);
+		if (!skb) {
 			ret_val = 3;
 			goto err_nomem;
 		}
@@ -1135,40 +1117,40 @@
 	if (!rxdr->count)
 		rxdr->count = E1000_DEFAULT_RXD;
 
-	if (!(rxdr->buffer_info = kcalloc(rxdr->count,
-	                                  sizeof(struct e1000_buffer),
-	                                  GFP_KERNEL))) {
+	rxdr->buffer_info = kcalloc(rxdr->count, sizeof(struct e1000_buffer),
+				    GFP_KERNEL);
+	if (!rxdr->buffer_info) {
 		ret_val = 4;
 		goto err_nomem;
 	}
 
 	rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc);
-	if (!(rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma))) {
+	rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
+	if (!rxdr->desc) {
 		ret_val = 5;
 		goto err_nomem;
 	}
 	memset(rxdr->desc, 0, rxdr->size);
 	rxdr->next_to_use = rxdr->next_to_clean = 0;
 
-	rctl = E1000_READ_REG(&adapter->hw, RCTL);
-	E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN);
-	E1000_WRITE_REG(&adapter->hw, RDBAL,
-			((u64) rxdr->dma & 0xFFFFFFFF));
-	E1000_WRITE_REG(&adapter->hw, RDBAH, ((u64) rxdr->dma >> 32));
-	E1000_WRITE_REG(&adapter->hw, RDLEN, rxdr->size);
-	E1000_WRITE_REG(&adapter->hw, RDH, 0);
-	E1000_WRITE_REG(&adapter->hw, RDT, 0);
+	rctl = er32(RCTL);
+	ew32(RCTL, rctl & ~E1000_RCTL_EN);
+	ew32(RDBAL, ((u64)rxdr->dma & 0xFFFFFFFF));
+	ew32(RDBAH, ((u64)rxdr->dma >> 32));
+	ew32(RDLEN, rxdr->size);
+	ew32(RDH, 0);
+	ew32(RDT, 0);
 	rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 |
 		E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
-		(adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT);
-	E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+		(hw->mc_filter_type << E1000_RCTL_MO_SHIFT);
+	ew32(RCTL, rctl);
 
 	for (i = 0; i < rxdr->count; i++) {
 		struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rxdr, i);
 		struct sk_buff *skb;
 
-		if (!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN,
-				GFP_KERNEL))) {
+		skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN, GFP_KERNEL);
+		if (!skb) {
 			ret_val = 6;
 			goto err_nomem;
 		}
@@ -1189,73 +1171,74 @@
 	return ret_val;
 }
 
-static void
-e1000_phy_disable_receiver(struct e1000_adapter *adapter)
+static void e1000_phy_disable_receiver(struct e1000_adapter *adapter)
 {
+	struct e1000_hw *hw = &adapter->hw;
+
 	/* Write out to PHY registers 29 and 30 to disable the Receiver. */
-	e1000_write_phy_reg(&adapter->hw, 29, 0x001F);
-	e1000_write_phy_reg(&adapter->hw, 30, 0x8FFC);
-	e1000_write_phy_reg(&adapter->hw, 29, 0x001A);
-	e1000_write_phy_reg(&adapter->hw, 30, 0x8FF0);
+	e1000_write_phy_reg(hw, 29, 0x001F);
+	e1000_write_phy_reg(hw, 30, 0x8FFC);
+	e1000_write_phy_reg(hw, 29, 0x001A);
+	e1000_write_phy_reg(hw, 30, 0x8FF0);
 }
 
-static void
-e1000_phy_reset_clk_and_crs(struct e1000_adapter *adapter)
+static void e1000_phy_reset_clk_and_crs(struct e1000_adapter *adapter)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	u16 phy_reg;
 
 	/* Because we reset the PHY above, we need to re-force TX_CLK in the
 	 * Extended PHY Specific Control Register to 25MHz clock.  This
 	 * value defaults back to a 2.5MHz clock when the PHY is reset.
 	 */
-	e1000_read_phy_reg(&adapter->hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
+	e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
 	phy_reg |= M88E1000_EPSCR_TX_CLK_25;
-	e1000_write_phy_reg(&adapter->hw,
+	e1000_write_phy_reg(hw,
 		M88E1000_EXT_PHY_SPEC_CTRL, phy_reg);
 
 	/* In addition, because of the s/w reset above, we need to enable
 	 * CRS on TX.  This must be set for both full and half duplex
 	 * operation.
 	 */
-	e1000_read_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, &phy_reg);
+	e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_reg);
 	phy_reg |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
-	e1000_write_phy_reg(&adapter->hw,
+	e1000_write_phy_reg(hw,
 		M88E1000_PHY_SPEC_CTRL, phy_reg);
 }
 
-static int
-e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter)
+static int e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	u32 ctrl_reg;
 	u16 phy_reg;
 
 	/* Setup the Device Control Register for PHY loopback test. */
 
-	ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL);
+	ctrl_reg = er32(CTRL);
 	ctrl_reg |= (E1000_CTRL_ILOS |		/* Invert Loss-Of-Signal */
 		     E1000_CTRL_FRCSPD |	/* Set the Force Speed Bit */
 		     E1000_CTRL_FRCDPX |	/* Set the Force Duplex Bit */
 		     E1000_CTRL_SPD_1000 |	/* Force Speed to 1000 */
 		     E1000_CTRL_FD);		/* Force Duplex to FULL */
 
-	E1000_WRITE_REG(&adapter->hw, CTRL, ctrl_reg);
+	ew32(CTRL, ctrl_reg);
 
 	/* Read the PHY Specific Control Register (0x10) */
-	e1000_read_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, &phy_reg);
+	e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_reg);
 
 	/* Clear Auto-Crossover bits in PHY Specific Control Register
 	 * (bits 6:5).
 	 */
 	phy_reg &= ~M88E1000_PSCR_AUTO_X_MODE;
-	e1000_write_phy_reg(&adapter->hw, M88E1000_PHY_SPEC_CTRL, phy_reg);
+	e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_reg);
 
 	/* Perform software reset on the PHY */
-	e1000_phy_reset(&adapter->hw);
+	e1000_phy_reset(hw);
 
 	/* Have to setup TX_CLK and TX_CRS after software reset */
 	e1000_phy_reset_clk_and_crs(adapter);
 
-	e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x8100);
+	e1000_write_phy_reg(hw, PHY_CTRL, 0x8100);
 
 	/* Wait for reset to complete. */
 	udelay(500);
@@ -1267,55 +1250,55 @@
 	e1000_phy_disable_receiver(adapter);
 
 	/* Set the loopback bit in the PHY control register. */
-	e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
+	e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg);
 	phy_reg |= MII_CR_LOOPBACK;
-	e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
+	e1000_write_phy_reg(hw, PHY_CTRL, phy_reg);
 
 	/* Setup TX_CLK and TX_CRS one more time. */
 	e1000_phy_reset_clk_and_crs(adapter);
 
 	/* Check Phy Configuration */
-	e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
+	e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg);
 	if (phy_reg != 0x4100)
 		 return 9;
 
-	e1000_read_phy_reg(&adapter->hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
+	e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
 	if (phy_reg != 0x0070)
 		return 10;
 
-	e1000_read_phy_reg(&adapter->hw, 29, &phy_reg);
+	e1000_read_phy_reg(hw, 29, &phy_reg);
 	if (phy_reg != 0x001A)
 		return 11;
 
 	return 0;
 }
 
-static int
-e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
+static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	u32 ctrl_reg = 0;
 	u32 stat_reg = 0;
 
-	adapter->hw.autoneg = false;
+	hw->autoneg = false;
 
-	if (adapter->hw.phy_type == e1000_phy_m88) {
+	if (hw->phy_type == e1000_phy_m88) {
 		/* Auto-MDI/MDIX Off */
-		e1000_write_phy_reg(&adapter->hw,
+		e1000_write_phy_reg(hw,
 				    M88E1000_PHY_SPEC_CTRL, 0x0808);
 		/* reset to update Auto-MDI/MDIX */
-		e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x9140);
+		e1000_write_phy_reg(hw, PHY_CTRL, 0x9140);
 		/* autoneg off */
-		e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x8140);
-	} else if (adapter->hw.phy_type == e1000_phy_gg82563)
-		e1000_write_phy_reg(&adapter->hw,
+		e1000_write_phy_reg(hw, PHY_CTRL, 0x8140);
+	} else if (hw->phy_type == e1000_phy_gg82563)
+		e1000_write_phy_reg(hw,
 		                    GG82563_PHY_KMRN_MODE_CTRL,
 		                    0x1CC);
 
-	ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL);
+	ctrl_reg = er32(CTRL);
 
-	if (adapter->hw.phy_type == e1000_phy_ife) {
+	if (hw->phy_type == e1000_phy_ife) {
 		/* force 100, set loopback */
-		e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x6100);
+		e1000_write_phy_reg(hw, PHY_CTRL, 0x6100);
 
 		/* Now set up the MAC to the same speed/duplex as the PHY. */
 		ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
@@ -1325,10 +1308,10 @@
 			     E1000_CTRL_FD);	 /* Force Duplex to FULL */
 	} else {
 		/* force 1000, set loopback */
-		e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x4140);
+		e1000_write_phy_reg(hw, PHY_CTRL, 0x4140);
 
 		/* Now set up the MAC to the same speed/duplex as the PHY. */
-		ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL);
+		ctrl_reg = er32(CTRL);
 		ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
 		ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
 			     E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
@@ -1336,23 +1319,23 @@
 			     E1000_CTRL_FD);	 /* Force Duplex to FULL */
 	}
 
-	if (adapter->hw.media_type == e1000_media_type_copper &&
-	   adapter->hw.phy_type == e1000_phy_m88)
+	if (hw->media_type == e1000_media_type_copper &&
+	   hw->phy_type == e1000_phy_m88)
 		ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */
 	else {
 		/* Set the ILOS bit on the fiber Nic is half
 		 * duplex link is detected. */
-		stat_reg = E1000_READ_REG(&adapter->hw, STATUS);
+		stat_reg = er32(STATUS);
 		if ((stat_reg & E1000_STATUS_FD) == 0)
 			ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU);
 	}
 
-	E1000_WRITE_REG(&adapter->hw, CTRL, ctrl_reg);
+	ew32(CTRL, ctrl_reg);
 
 	/* Disable the receiver on the PHY so when a cable is plugged in, the
 	 * PHY does not begin to autoneg when a cable is reconnected to the NIC.
 	 */
-	if (adapter->hw.phy_type == e1000_phy_m88)
+	if (hw->phy_type == e1000_phy_m88)
 		e1000_phy_disable_receiver(adapter);
 
 	udelay(500);
@@ -1360,15 +1343,15 @@
 	return 0;
 }
 
-static int
-e1000_set_phy_loopback(struct e1000_adapter *adapter)
+static int e1000_set_phy_loopback(struct e1000_adapter *adapter)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	u16 phy_reg = 0;
 	u16 count = 0;
 
-	switch (adapter->hw.mac_type) {
+	switch (hw->mac_type) {
 	case e1000_82543:
-		if (adapter->hw.media_type == e1000_media_type_copper) {
+		if (hw->media_type == e1000_media_type_copper) {
 			/* Attempt to setup Loopback mode on Non-integrated PHY.
 			 * Some PHY registers get corrupted at random, so
 			 * attempt this 10 times.
@@ -1402,9 +1385,9 @@
 		/* Default PHY loopback work is to read the MII
 		 * control register and assert bit 14 (loopback mode).
 		 */
-		e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
+		e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg);
 		phy_reg |= MII_CR_LOOPBACK;
-		e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
+		e1000_write_phy_reg(hw, PHY_CTRL, phy_reg);
 		return 0;
 		break;
 	}
@@ -1412,8 +1395,7 @@
 	return 8;
 }
 
-static int
-e1000_setup_loopback_test(struct e1000_adapter *adapter)
+static int e1000_setup_loopback_test(struct e1000_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
 	u32 rctl;
@@ -1431,14 +1413,14 @@
 		case e1000_82572:
 #define E1000_SERDES_LB_ON 0x410
 			e1000_set_phy_loopback(adapter);
-			E1000_WRITE_REG(hw, SCTL, E1000_SERDES_LB_ON);
+			ew32(SCTL, E1000_SERDES_LB_ON);
 			msleep(10);
 			return 0;
 			break;
 		default:
-			rctl = E1000_READ_REG(hw, RCTL);
+			rctl = er32(RCTL);
 			rctl |= E1000_RCTL_LBM_TCVR;
-			E1000_WRITE_REG(hw, RCTL, rctl);
+			ew32(RCTL, rctl);
 			return 0;
 		}
 	} else if (hw->media_type == e1000_media_type_copper)
@@ -1447,16 +1429,15 @@
 	return 7;
 }
 
-static void
-e1000_loopback_cleanup(struct e1000_adapter *adapter)
+static void e1000_loopback_cleanup(struct e1000_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
 	u32 rctl;
 	u16 phy_reg;
 
-	rctl = E1000_READ_REG(hw, RCTL);
+	rctl = er32(RCTL);
 	rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
-	E1000_WRITE_REG(hw, RCTL, rctl);
+	ew32(RCTL, rctl);
 
 	switch (hw->mac_type) {
 	case e1000_82571:
@@ -1464,7 +1445,7 @@
 		if (hw->media_type == e1000_media_type_fiber ||
 		    hw->media_type == e1000_media_type_internal_serdes) {
 #define E1000_SERDES_LB_OFF 0x400
-			E1000_WRITE_REG(hw, SCTL, E1000_SERDES_LB_OFF);
+			ew32(SCTL, E1000_SERDES_LB_OFF);
 			msleep(10);
 			break;
 		}
@@ -1489,8 +1470,8 @@
 	}
 }
 
-static void
-e1000_create_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
+static void e1000_create_lbtest_frame(struct sk_buff *skb,
+				      unsigned int frame_size)
 {
 	memset(skb->data, 0xFF, frame_size);
 	frame_size &= ~1;
@@ -1499,8 +1480,8 @@
 	memset(&skb->data[frame_size / 2 + 12], 0xAF, 1);
 }
 
-static int
-e1000_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
+static int e1000_check_lbtest_frame(struct sk_buff *skb,
+				    unsigned int frame_size)
 {
 	frame_size &= ~1;
 	if (*(skb->data + 3) == 0xFF) {
@@ -1512,16 +1493,16 @@
 	return 13;
 }
 
-static int
-e1000_run_loopback_test(struct e1000_adapter *adapter)
+static int e1000_run_loopback_test(struct e1000_adapter *adapter)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	struct e1000_tx_ring *txdr = &adapter->test_tx_ring;
 	struct e1000_rx_ring *rxdr = &adapter->test_rx_ring;
 	struct pci_dev *pdev = adapter->pdev;
 	int i, j, k, l, lc, good_cnt, ret_val=0;
 	unsigned long time;
 
-	E1000_WRITE_REG(&adapter->hw, RDT, rxdr->count - 1);
+	ew32(RDT, rxdr->count - 1);
 
 	/* Calculate the loop count based on the largest descriptor ring
 	 * The idea is to wrap the largest ring a number of times using 64
@@ -1544,7 +1525,7 @@
 				    	PCI_DMA_TODEVICE);
 			if (unlikely(++k == txdr->count)) k = 0;
 		}
-		E1000_WRITE_REG(&adapter->hw, TDT, k);
+		ew32(TDT, k);
 		msleep(200);
 		time = jiffies; /* set the start time for the receive */
 		good_cnt = 0;
@@ -1577,21 +1558,24 @@
 	return ret_val;
 }
 
-static int
-e1000_loopback_test(struct e1000_adapter *adapter, u64 *data)
+static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data)
 {
+	struct e1000_hw *hw = &adapter->hw;
+
 	/* PHY loopback cannot be performed if SoL/IDER
 	 * sessions are active */
-	if (e1000_check_phy_reset_block(&adapter->hw)) {
+	if (e1000_check_phy_reset_block(hw)) {
 		DPRINTK(DRV, ERR, "Cannot do PHY loopback test "
 		        "when SoL/IDER is active.\n");
 		*data = 0;
 		goto out;
 	}
 
-	if ((*data = e1000_setup_desc_rings(adapter)))
+	*data = e1000_setup_desc_rings(adapter);
+	if (*data)
 		goto out;
-	if ((*data = e1000_setup_loopback_test(adapter)))
+	*data = e1000_setup_loopback_test(adapter);
+	if (*data)
 		goto err_loopback;
 	*data = e1000_run_loopback_test(adapter);
 	e1000_loopback_cleanup(adapter);
@@ -1602,38 +1586,37 @@
 	return *data;
 }
 
-static int
-e1000_link_test(struct e1000_adapter *adapter, u64 *data)
+static int e1000_link_test(struct e1000_adapter *adapter, u64 *data)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	*data = 0;
-	if (adapter->hw.media_type == e1000_media_type_internal_serdes) {
+	if (hw->media_type == e1000_media_type_internal_serdes) {
 		int i = 0;
-		adapter->hw.serdes_link_down = true;
+		hw->serdes_link_down = true;
 
 		/* On some blade server designs, link establishment
 		 * could take as long as 2-3 minutes */
 		do {
-			e1000_check_for_link(&adapter->hw);
-			if (!adapter->hw.serdes_link_down)
+			e1000_check_for_link(hw);
+			if (!hw->serdes_link_down)
 				return *data;
 			msleep(20);
 		} while (i++ < 3750);
 
 		*data = 1;
 	} else {
-		e1000_check_for_link(&adapter->hw);
-		if (adapter->hw.autoneg)  /* if auto_neg is set wait for it */
+		e1000_check_for_link(hw);
+		if (hw->autoneg)  /* if auto_neg is set wait for it */
 			msleep(4000);
 
-		if (!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) {
+		if (!(er32(STATUS) & E1000_STATUS_LU)) {
 			*data = 1;
 		}
 	}
 	return *data;
 }
 
-static int
-e1000_get_sset_count(struct net_device *netdev, int sset)
+static int e1000_get_sset_count(struct net_device *netdev, int sset)
 {
 	switch (sset) {
 	case ETH_SS_TEST:
@@ -1645,11 +1628,11 @@
 	}
 }
 
-static void
-e1000_diag_test(struct net_device *netdev,
-		   struct ethtool_test *eth_test, u64 *data)
+static void e1000_diag_test(struct net_device *netdev,
+			    struct ethtool_test *eth_test, u64 *data)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
 	bool if_running = netif_running(netdev);
 
 	set_bit(__E1000_TESTING, &adapter->flags);
@@ -1657,9 +1640,9 @@
 		/* Offline tests */
 
 		/* save speed, duplex, autoneg settings */
-		u16 autoneg_advertised = adapter->hw.autoneg_advertised;
-		u8 forced_speed_duplex = adapter->hw.forced_speed_duplex;
-		u8 autoneg = adapter->hw.autoneg;
+		u16 autoneg_advertised = hw->autoneg_advertised;
+		u8 forced_speed_duplex = hw->forced_speed_duplex;
+		u8 autoneg = hw->autoneg;
 
 		DPRINTK(HW, INFO, "offline testing starting\n");
 
@@ -1692,9 +1675,9 @@
 			eth_test->flags |= ETH_TEST_FL_FAILED;
 
 		/* restore speed, duplex, autoneg settings */
-		adapter->hw.autoneg_advertised = autoneg_advertised;
-		adapter->hw.forced_speed_duplex = forced_speed_duplex;
-		adapter->hw.autoneg = autoneg;
+		hw->autoneg_advertised = autoneg_advertised;
+		hw->forced_speed_duplex = forced_speed_duplex;
+		hw->autoneg = autoneg;
 
 		e1000_reset(adapter);
 		clear_bit(__E1000_TESTING, &adapter->flags);
@@ -1717,7 +1700,8 @@
 	msleep_interruptible(4 * 1000);
 }
 
-static int e1000_wol_exclusion(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
+static int e1000_wol_exclusion(struct e1000_adapter *adapter,
+			       struct ethtool_wolinfo *wol)
 {
 	struct e1000_hw *hw = &adapter->hw;
 	int retval = 1; /* fail by default */
@@ -1742,7 +1726,7 @@
 	case E1000_DEV_ID_82571EB_SERDES:
 	case E1000_DEV_ID_82571EB_COPPER:
 		/* Wake events not supported on port B */
-		if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) {
+		if (er32(STATUS) & E1000_STATUS_FUNC_1) {
 			wol->supported = 0;
 			break;
 		}
@@ -1766,7 +1750,7 @@
 		/* dual port cards only support WoL on port A from now on
 		 * unless it was enabled in the eeprom for port B
 		 * so exclude FUNC_1 ports from having WoL enabled */
-		if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1 &&
+		if (er32(STATUS) & E1000_STATUS_FUNC_1 &&
 		    !adapter->eeprom_wol) {
 			wol->supported = 0;
 			break;
@@ -1778,10 +1762,11 @@
 	return retval;
 }
 
-static void
-e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+static void e1000_get_wol(struct net_device *netdev,
+			  struct ethtool_wolinfo *wol)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
 
 	wol->supported = WAKE_UCAST | WAKE_MCAST |
 	                 WAKE_BCAST | WAKE_MAGIC;
@@ -1793,7 +1778,7 @@
 		return;
 
 	/* apply any specific unsupported masks here */
-	switch (adapter->hw.device_id) {
+	switch (hw->device_id) {
 	case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
 		/* KSP3 does not suppport UCAST wake-ups */
 		wol->supported &= ~WAKE_UCAST;
@@ -1818,8 +1803,7 @@
 	return;
 }
 
-static int
-e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
@@ -1863,61 +1847,60 @@
 /* bit defines for adapter->led_status */
 #define E1000_LED_ON		0
 
-static void
-e1000_led_blink_callback(unsigned long data)
+static void e1000_led_blink_callback(unsigned long data)
 {
 	struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+	struct e1000_hw *hw = &adapter->hw;
 
 	if (test_and_change_bit(E1000_LED_ON, &adapter->led_status))
-		e1000_led_off(&adapter->hw);
+		e1000_led_off(hw);
 	else
-		e1000_led_on(&adapter->hw);
+		e1000_led_on(hw);
 
 	mod_timer(&adapter->blink_timer, jiffies + E1000_ID_INTERVAL);
 }
 
-static int
-e1000_phys_id(struct net_device *netdev, u32 data)
+static int e1000_phys_id(struct net_device *netdev, u32 data)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
 
 	if (!data)
 		data = INT_MAX;
 
-	if (adapter->hw.mac_type < e1000_82571) {
+	if (hw->mac_type < e1000_82571) {
 		if (!adapter->blink_timer.function) {
 			init_timer(&adapter->blink_timer);
 			adapter->blink_timer.function = e1000_led_blink_callback;
-			adapter->blink_timer.data = (unsigned long) adapter;
+			adapter->blink_timer.data = (unsigned long)adapter;
 		}
-		e1000_setup_led(&adapter->hw);
+		e1000_setup_led(hw);
 		mod_timer(&adapter->blink_timer, jiffies);
 		msleep_interruptible(data * 1000);
 		del_timer_sync(&adapter->blink_timer);
-	} else if (adapter->hw.phy_type == e1000_phy_ife) {
+	} else if (hw->phy_type == e1000_phy_ife) {
 		if (!adapter->blink_timer.function) {
 			init_timer(&adapter->blink_timer);
 			adapter->blink_timer.function = e1000_led_blink_callback;
-			adapter->blink_timer.data = (unsigned long) adapter;
+			adapter->blink_timer.data = (unsigned long)adapter;
 		}
 		mod_timer(&adapter->blink_timer, jiffies);
 		msleep_interruptible(data * 1000);
 		del_timer_sync(&adapter->blink_timer);
 		e1000_write_phy_reg(&(adapter->hw), IFE_PHY_SPECIAL_CONTROL_LED, 0);
 	} else {
-		e1000_blink_led_start(&adapter->hw);
+		e1000_blink_led_start(hw);
 		msleep_interruptible(data * 1000);
 	}
 
-	e1000_led_off(&adapter->hw);
+	e1000_led_off(hw);
 	clear_bit(E1000_LED_ON, &adapter->led_status);
-	e1000_cleanup_led(&adapter->hw);
+	e1000_cleanup_led(hw);
 
 	return 0;
 }
 
-static int
-e1000_nway_reset(struct net_device *netdev)
+static int e1000_nway_reset(struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	if (netif_running(netdev))
@@ -1925,9 +1908,8 @@
 	return 0;
 }
 
-static void
-e1000_get_ethtool_stats(struct net_device *netdev,
-		struct ethtool_stats *stats, u64 *data)
+static void e1000_get_ethtool_stats(struct net_device *netdev,
+				    struct ethtool_stats *stats, u64 *data)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	int i;
@@ -1941,8 +1923,8 @@
 /*	BUG_ON(i != E1000_STATS_LEN); */
 }
 
-static void
-e1000_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
+static void e1000_get_strings(struct net_device *netdev, u32 stringset,
+			      u8 *data)
 {
 	u8 *p = data;
 	int i;
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 9a4b6cb..9d6edf3 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -42,48 +42,65 @@
 
 static u8 e1000_arc_subsystem_valid(struct e1000_hw *hw);
 static s32 e1000_check_downshift(struct e1000_hw *hw);
-static s32 e1000_check_polarity(struct e1000_hw *hw, e1000_rev_polarity *polarity);
+static s32 e1000_check_polarity(struct e1000_hw *hw,
+				e1000_rev_polarity *polarity);
 static void e1000_clear_hw_cntrs(struct e1000_hw *hw);
 static void e1000_clear_vfta(struct e1000_hw *hw);
 static s32 e1000_commit_shadow_ram(struct e1000_hw *hw);
 static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw,
-						  bool link_up);
+					      bool link_up);
 static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw);
 static s32 e1000_detect_gig_phy(struct e1000_hw *hw);
 static s32 e1000_erase_ich8_4k_segment(struct e1000_hw *hw, u32 bank);
 static s32 e1000_get_auto_rd_done(struct e1000_hw *hw);
-static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length, u16 *max_length);
+static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length,
+				  u16 *max_length);
 static s32 e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw);
 static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw);
 static s32 e1000_get_software_flag(struct e1000_hw *hw);
 static s32 e1000_ich8_cycle_init(struct e1000_hw *hw);
 static s32 e1000_ich8_flash_cycle(struct e1000_hw *hw, u32 timeout);
 static s32 e1000_id_led_init(struct e1000_hw *hw);
-static s32 e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw, u32 cnf_base_addr, u32 cnf_size);
+static s32 e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
+						 u32 cnf_base_addr,
+						 u32 cnf_size);
 static s32 e1000_init_lcd_from_nvm(struct e1000_hw *hw);
 static void e1000_init_rx_addrs(struct e1000_hw *hw);
 static void e1000_initialize_hardware_bits(struct e1000_hw *hw);
 static bool e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw);
 static s32 e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw);
 static s32 e1000_mng_enable_host_if(struct e1000_hw *hw);
-static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length, u16 offset, u8 *sum);
-static s32 e1000_mng_write_cmd_header(struct e1000_hw* hw, struct e1000_host_mng_command_header* hdr);
+static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length,
+				   u16 offset, u8 *sum);
+static s32 e1000_mng_write_cmd_header(struct e1000_hw* hw,
+				      struct e1000_host_mng_command_header
+				      *hdr);
 static s32 e1000_mng_write_commit(struct e1000_hw *hw);
-static s32 e1000_phy_ife_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
-static s32 e1000_phy_igp_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
-static s32 e1000_read_eeprom_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
-static s32 e1000_write_eeprom_eewr(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
+static s32 e1000_phy_ife_get_info(struct e1000_hw *hw,
+				  struct e1000_phy_info *phy_info);
+static s32 e1000_phy_igp_get_info(struct e1000_hw *hw,
+				  struct e1000_phy_info *phy_info);
+static s32 e1000_read_eeprom_eerd(struct e1000_hw *hw, u16 offset, u16 words,
+				  u16 *data);
+static s32 e1000_write_eeprom_eewr(struct e1000_hw *hw, u16 offset, u16 words,
+				   u16 *data);
 static s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd);
-static s32 e1000_phy_m88_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
+static s32 e1000_phy_m88_get_info(struct e1000_hw *hw,
+				  struct e1000_phy_info *phy_info);
 static void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw);
 static s32 e1000_read_ich8_byte(struct e1000_hw *hw, u32 index, u8 *data);
-static s32 e1000_verify_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte);
+static s32 e1000_verify_write_ich8_byte(struct e1000_hw *hw, u32 index,
+					u8 byte);
 static s32 e1000_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte);
 static s32 e1000_read_ich8_word(struct e1000_hw *hw, u32 index, u16 *data);
-static s32 e1000_read_ich8_data(struct e1000_hw *hw, u32 index, u32 size, u16 *data);
-static s32 e1000_write_ich8_data(struct e1000_hw *hw, u32 index, u32 size, u16 data);
-static s32 e1000_read_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
-static s32 e1000_write_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
+static s32 e1000_read_ich8_data(struct e1000_hw *hw, u32 index, u32 size,
+				u16 *data);
+static s32 e1000_write_ich8_data(struct e1000_hw *hw, u32 index, u32 size,
+				 u16 data);
+static s32 e1000_read_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
+				  u16 *data);
+static s32 e1000_write_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
+				   u16 *data);
 static void e1000_release_software_flag(struct e1000_hw *hw);
 static s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active);
 static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active);
@@ -101,23 +118,21 @@
 static void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl);
 static void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl);
 static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data,
-                                     u16 count);
+				     u16 count);
 static u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw);
 static s32 e1000_phy_reset_dsp(struct e1000_hw *hw);
 static s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset,
                                       u16 words, u16 *data);
-static s32 e1000_write_eeprom_microwire(struct e1000_hw *hw,
-                                            u16 offset, u16 words,
-                                            u16 *data);
+static s32 e1000_write_eeprom_microwire(struct e1000_hw *hw, u16 offset,
+					u16 words, u16 *data);
 static s32 e1000_spi_eeprom_ready(struct e1000_hw *hw);
 static void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd);
 static void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd);
-static void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data,
-                                    u16 count);
+static void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data, u16 count);
 static s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
-                                      u16 phy_data);
+				  u16 phy_data);
 static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw,u32 reg_addr,
-                                     u16 *phy_data);
+				 u16 *phy_data);
 static u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count);
 static s32 e1000_acquire_eeprom(struct e1000_hw *hw);
 static void e1000_release_eeprom(struct e1000_hw *hw);
@@ -127,8 +142,7 @@
 static s32 e1000_set_phy_mode(struct e1000_hw *hw);
 static s32 e1000_host_if_read_cookie(struct e1000_hw *hw, u8 *buffer);
 static u8 e1000_calculate_mng_checksum(char *buffer, u32 length);
-static s32 e1000_configure_kmrn_for_10_100(struct e1000_hw *hw,
-                                               u16 duplex);
+static s32 e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, u16 duplex);
 static s32 e1000_configure_kmrn_for_1000(struct e1000_hw *hw);
 
 /* IGP cable length table */
@@ -159,8 +173,7 @@
  *
  * hw - Struct containing variables accessed by shared code
  *****************************************************************************/
-static s32
-e1000_set_phy_type(struct e1000_hw *hw)
+static s32 e1000_set_phy_type(struct e1000_hw *hw)
 {
     DEBUGFUNC("e1000_set_phy_type");
 
@@ -210,8 +223,7 @@
  *
  * hw - Struct containing variables accessed by shared code
  *****************************************************************************/
-static void
-e1000_phy_init_script(struct e1000_hw *hw)
+static void e1000_phy_init_script(struct e1000_hw *hw)
 {
     u32 ret_val;
     u16 phy_saved_data;
@@ -306,8 +318,7 @@
  *
  * hw - Struct containing variables accessed by shared code
  *****************************************************************************/
-s32
-e1000_set_mac_type(struct e1000_hw *hw)
+s32 e1000_set_mac_type(struct e1000_hw *hw)
 {
 	DEBUGFUNC("e1000_set_mac_type");
 
@@ -474,8 +485,7 @@
  *
  * hw - Struct containing variables accessed by shared code
  * **************************************************************************/
-void
-e1000_set_media_type(struct e1000_hw *hw)
+void e1000_set_media_type(struct e1000_hw *hw)
 {
     u32 status;
 
@@ -510,7 +520,7 @@
             hw->media_type = e1000_media_type_copper;
             break;
         default:
-            status = E1000_READ_REG(hw, STATUS);
+            status = er32(STATUS);
             if (status & E1000_STATUS_TBIMODE) {
                 hw->media_type = e1000_media_type_fiber;
                 /* tbi_compatibility not valid on fiber */
@@ -528,8 +538,7 @@
  *
  * hw - Struct containing variables accessed by shared code
  *****************************************************************************/
-s32
-e1000_reset_hw(struct e1000_hw *hw)
+s32 e1000_reset_hw(struct e1000_hw *hw)
 {
     u32 ctrl;
     u32 ctrl_ext;
@@ -559,15 +568,15 @@
 
     /* Clear interrupt mask to stop board from generating interrupts */
     DEBUGOUT("Masking off all interrupts\n");
-    E1000_WRITE_REG(hw, IMC, 0xffffffff);
+    ew32(IMC, 0xffffffff);
 
     /* Disable the Transmit and Receive units.  Then delay to allow
      * any pending transactions to complete before we hit the MAC with
      * the global reset.
      */
-    E1000_WRITE_REG(hw, RCTL, 0);
-    E1000_WRITE_REG(hw, TCTL, E1000_TCTL_PSP);
-    E1000_WRITE_FLUSH(hw);
+    ew32(RCTL, 0);
+    ew32(TCTL, E1000_TCTL_PSP);
+    E1000_WRITE_FLUSH();
 
     /* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */
     hw->tbi_compatibility_on = false;
@@ -577,11 +586,11 @@
      */
     msleep(10);
 
-    ctrl = E1000_READ_REG(hw, CTRL);
+    ctrl = er32(CTRL);
 
     /* Must reset the PHY before resetting the MAC */
     if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
-        E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_PHY_RST));
+        ew32(CTRL, (ctrl | E1000_CTRL_PHY_RST));
         msleep(5);
     }
 
@@ -590,12 +599,12 @@
     if (hw->mac_type == e1000_82573) {
         timeout = 10;
 
-        extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL);
+        extcnf_ctrl = er32(EXTCNF_CTRL);
         extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
 
         do {
-            E1000_WRITE_REG(hw, EXTCNF_CTRL, extcnf_ctrl);
-            extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL);
+            ew32(EXTCNF_CTRL, extcnf_ctrl);
+            extcnf_ctrl = er32(EXTCNF_CTRL);
 
             if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP)
                 break;
@@ -610,9 +619,9 @@
     /* Workaround for ICH8 bit corruption issue in FIFO memory */
     if (hw->mac_type == e1000_ich8lan) {
         /* Set Tx and Rx buffer allocation to 8k apiece. */
-        E1000_WRITE_REG(hw, PBA, E1000_PBA_8K);
+        ew32(PBA, E1000_PBA_8K);
         /* Set Packet Buffer Size to 16k. */
-        E1000_WRITE_REG(hw, PBS, E1000_PBS_16K);
+        ew32(PBS, E1000_PBS_16K);
     }
 
     /* Issue a global reset to the MAC.  This will reset the chip's
@@ -636,7 +645,7 @@
         case e1000_82545_rev_3:
         case e1000_82546_rev_3:
             /* Reset is performed on a shadow of the control register */
-            E1000_WRITE_REG(hw, CTRL_DUP, (ctrl | E1000_CTRL_RST));
+            ew32(CTRL_DUP, (ctrl | E1000_CTRL_RST));
             break;
         case e1000_ich8lan:
             if (!hw->phy_reset_disable &&
@@ -649,11 +658,11 @@
             }
 
             e1000_get_software_flag(hw);
-            E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST));
+            ew32(CTRL, (ctrl | E1000_CTRL_RST));
             msleep(5);
             break;
         default:
-            E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST));
+            ew32(CTRL, (ctrl | E1000_CTRL_RST));
             break;
     }
 
@@ -668,10 +677,10 @@
         case e1000_82544:
             /* Wait for reset to complete */
             udelay(10);
-            ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+            ctrl_ext = er32(CTRL_EXT);
             ctrl_ext |= E1000_CTRL_EXT_EE_RST;
-            E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
-            E1000_WRITE_FLUSH(hw);
+            ew32(CTRL_EXT, ctrl_ext);
+            E1000_WRITE_FLUSH();
             /* Wait for EEPROM reload */
             msleep(2);
             break;
@@ -685,10 +694,10 @@
         case e1000_82573:
             if (!e1000_is_onboard_nvm_eeprom(hw)) {
                 udelay(10);
-                ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+                ctrl_ext = er32(CTRL_EXT);
                 ctrl_ext |= E1000_CTRL_EXT_EE_RST;
-                E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
-                E1000_WRITE_FLUSH(hw);
+                ew32(CTRL_EXT, ctrl_ext);
+                E1000_WRITE_FLUSH();
             }
             /* fall through */
         default:
@@ -701,27 +710,27 @@
 
     /* Disable HW ARPs on ASF enabled adapters */
     if (hw->mac_type >= e1000_82540 && hw->mac_type <= e1000_82547_rev_2) {
-        manc = E1000_READ_REG(hw, MANC);
+        manc = er32(MANC);
         manc &= ~(E1000_MANC_ARP_EN);
-        E1000_WRITE_REG(hw, MANC, manc);
+        ew32(MANC, manc);
     }
 
     if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
         e1000_phy_init_script(hw);
 
         /* Configure activity LED after PHY reset */
-        led_ctrl = E1000_READ_REG(hw, LEDCTL);
+        led_ctrl = er32(LEDCTL);
         led_ctrl &= IGP_ACTIVITY_LED_MASK;
         led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
-        E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
+        ew32(LEDCTL, led_ctrl);
     }
 
     /* Clear interrupt mask to stop board from generating interrupts */
     DEBUGOUT("Masking off all interrupts\n");
-    E1000_WRITE_REG(hw, IMC, 0xffffffff);
+    ew32(IMC, 0xffffffff);
 
     /* Clear any pending interrupt events. */
-    icr = E1000_READ_REG(hw, ICR);
+    icr = er32(ICR);
 
     /* If MWI was previously enabled, reenable it. */
     if (hw->mac_type == e1000_82542_rev2_0) {
@@ -730,9 +739,9 @@
     }
 
     if (hw->mac_type == e1000_ich8lan) {
-        u32 kab = E1000_READ_REG(hw, KABGTXD);
+        u32 kab = er32(KABGTXD);
         kab |= E1000_KABGTXD_BGSQLBIAS;
-        E1000_WRITE_REG(hw, KABGTXD, kab);
+        ew32(KABGTXD, kab);
     }
 
     return E1000_SUCCESS;
@@ -747,8 +756,7 @@
  * This function contains hardware limitation workarounds for PCI-E adapters
  *
  *****************************************************************************/
-static void
-e1000_initialize_hardware_bits(struct e1000_hw *hw)
+static void e1000_initialize_hardware_bits(struct e1000_hw *hw)
 {
     if ((hw->mac_type >= e1000_82571) && (!hw->initialize_hw_bits_disable)) {
         /* Settings common to all PCI-express silicon */
@@ -758,22 +766,22 @@
         u32 reg_txdctl, reg_txdctl1;
 
         /* link autonegotiation/sync workarounds */
-        reg_tarc0 = E1000_READ_REG(hw, TARC0);
+        reg_tarc0 = er32(TARC0);
         reg_tarc0 &= ~((1 << 30)|(1 << 29)|(1 << 28)|(1 << 27));
 
         /* Enable not-done TX descriptor counting */
-        reg_txdctl = E1000_READ_REG(hw, TXDCTL);
+        reg_txdctl = er32(TXDCTL);
         reg_txdctl |= E1000_TXDCTL_COUNT_DESC;
-        E1000_WRITE_REG(hw, TXDCTL, reg_txdctl);
-        reg_txdctl1 = E1000_READ_REG(hw, TXDCTL1);
+        ew32(TXDCTL, reg_txdctl);
+        reg_txdctl1 = er32(TXDCTL1);
         reg_txdctl1 |= E1000_TXDCTL_COUNT_DESC;
-        E1000_WRITE_REG(hw, TXDCTL1, reg_txdctl1);
+        ew32(TXDCTL1, reg_txdctl1);
 
         switch (hw->mac_type) {
             case e1000_82571:
             case e1000_82572:
                 /* Clear PHY TX compatible mode bits */
-                reg_tarc1 = E1000_READ_REG(hw, TARC1);
+                reg_tarc1 = er32(TARC1);
                 reg_tarc1 &= ~((1 << 30)|(1 << 29));
 
                 /* link autonegotiation/sync workarounds */
@@ -783,25 +791,25 @@
                 reg_tarc1 |= ((1 << 26)|(1 << 25)|(1 << 24));
 
                 /* Multiple read bit is reversed polarity */
-                reg_tctl = E1000_READ_REG(hw, TCTL);
+                reg_tctl = er32(TCTL);
                 if (reg_tctl & E1000_TCTL_MULR)
                     reg_tarc1 &= ~(1 << 28);
                 else
                     reg_tarc1 |= (1 << 28);
 
-                E1000_WRITE_REG(hw, TARC1, reg_tarc1);
+                ew32(TARC1, reg_tarc1);
                 break;
             case e1000_82573:
-                reg_ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+                reg_ctrl_ext = er32(CTRL_EXT);
                 reg_ctrl_ext &= ~(1 << 23);
                 reg_ctrl_ext |= (1 << 22);
 
                 /* TX byte count fix */
-                reg_ctrl = E1000_READ_REG(hw, CTRL);
+                reg_ctrl = er32(CTRL);
                 reg_ctrl &= ~(1 << 29);
 
-                E1000_WRITE_REG(hw, CTRL_EXT, reg_ctrl_ext);
-                E1000_WRITE_REG(hw, CTRL, reg_ctrl);
+                ew32(CTRL_EXT, reg_ctrl_ext);
+                ew32(CTRL, reg_ctrl);
                 break;
             case e1000_80003es2lan:
                 /* improve small packet performace for fiber/serdes */
@@ -811,14 +819,14 @@
                 }
 
                 /* Multiple read bit is reversed polarity */
-                reg_tctl = E1000_READ_REG(hw, TCTL);
-                reg_tarc1 = E1000_READ_REG(hw, TARC1);
+                reg_tctl = er32(TCTL);
+                reg_tarc1 = er32(TARC1);
                 if (reg_tctl & E1000_TCTL_MULR)
                     reg_tarc1 &= ~(1 << 28);
                 else
                     reg_tarc1 |= (1 << 28);
 
-                E1000_WRITE_REG(hw, TARC1, reg_tarc1);
+                ew32(TARC1, reg_tarc1);
                 break;
             case e1000_ich8lan:
                 /* Reduce concurrent DMA requests to 3 from 4 */
@@ -827,16 +835,16 @@
                      (hw->device_id != E1000_DEV_ID_ICH8_IGP_M)))
                     reg_tarc0 |= ((1 << 29)|(1 << 28));
 
-                reg_ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+                reg_ctrl_ext = er32(CTRL_EXT);
                 reg_ctrl_ext |= (1 << 22);
-                E1000_WRITE_REG(hw, CTRL_EXT, reg_ctrl_ext);
+                ew32(CTRL_EXT, reg_ctrl_ext);
 
                 /* workaround TX hang with TSO=on */
                 reg_tarc0 |= ((1 << 27)|(1 << 26)|(1 << 24)|(1 << 23));
 
                 /* Multiple read bit is reversed polarity */
-                reg_tctl = E1000_READ_REG(hw, TCTL);
-                reg_tarc1 = E1000_READ_REG(hw, TARC1);
+                reg_tctl = er32(TCTL);
+                reg_tarc1 = er32(TARC1);
                 if (reg_tctl & E1000_TCTL_MULR)
                     reg_tarc1 &= ~(1 << 28);
                 else
@@ -845,13 +853,13 @@
                 /* workaround TX hang with TSO=on */
                 reg_tarc1 |= ((1 << 30)|(1 << 26)|(1 << 24));
 
-                E1000_WRITE_REG(hw, TARC1, reg_tarc1);
+                ew32(TARC1, reg_tarc1);
                 break;
             default:
                 break;
         }
 
-        E1000_WRITE_REG(hw, TARC0, reg_tarc0);
+        ew32(TARC0, reg_tarc0);
     }
 }
 
@@ -866,8 +874,7 @@
  * configuration and flow control settings. Clears all on-chip counters. Leaves
  * the transmit and receive units disabled and uninitialized.
  *****************************************************************************/
-s32
-e1000_init_hw(struct e1000_hw *hw)
+s32 e1000_init_hw(struct e1000_hw *hw)
 {
     u32 ctrl;
     u32 i;
@@ -883,9 +890,9 @@
         ((hw->revision_id < 3) ||
          ((hw->device_id != E1000_DEV_ID_ICH8_IGP_M_AMT) &&
           (hw->device_id != E1000_DEV_ID_ICH8_IGP_M)))) {
-            reg_data = E1000_READ_REG(hw, STATUS);
+            reg_data = er32(STATUS);
             reg_data &= ~0x80000000;
-            E1000_WRITE_REG(hw, STATUS, reg_data);
+            ew32(STATUS, reg_data);
     }
 
     /* Initialize Identification LED */
@@ -906,7 +913,7 @@
     /* VET hardcoded to standard value and VFTA removed in ICH8 LAN */
     if (hw->mac_type != e1000_ich8lan) {
         if (hw->mac_type < e1000_82545_rev_3)
-            E1000_WRITE_REG(hw, VET, 0);
+            ew32(VET, 0);
         e1000_clear_vfta(hw);
     }
 
@@ -914,8 +921,8 @@
     if (hw->mac_type == e1000_82542_rev2_0) {
         DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
         e1000_pci_clear_mwi(hw);
-        E1000_WRITE_REG(hw, RCTL, E1000_RCTL_RST);
-        E1000_WRITE_FLUSH(hw);
+        ew32(RCTL, E1000_RCTL_RST);
+        E1000_WRITE_FLUSH();
         msleep(5);
     }
 
@@ -926,8 +933,8 @@
 
     /* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */
     if (hw->mac_type == e1000_82542_rev2_0) {
-        E1000_WRITE_REG(hw, RCTL, 0);
-        E1000_WRITE_FLUSH(hw);
+        ew32(RCTL, 0);
+        E1000_WRITE_FLUSH();
         msleep(1);
         if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
             e1000_pci_set_mwi(hw);
@@ -942,7 +949,7 @@
         E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
         /* use write flush to prevent Memory Write Block (MWB) from
          * occuring when accessing our register space */
-        E1000_WRITE_FLUSH(hw);
+        E1000_WRITE_FLUSH();
     }
 
     /* Set the PCI priority bit correctly in the CTRL register.  This
@@ -951,8 +958,8 @@
      * 82542 and 82543 silicon.
      */
     if (hw->dma_fairness && hw->mac_type <= e1000_82543) {
-        ctrl = E1000_READ_REG(hw, CTRL);
-        E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PRIOR);
+        ctrl = er32(CTRL);
+        ew32(CTRL, ctrl | E1000_CTRL_PRIOR);
     }
 
     switch (hw->mac_type) {
@@ -975,9 +982,9 @@
 
     /* Set the transmit descriptor write-back policy */
     if (hw->mac_type > e1000_82544) {
-        ctrl = E1000_READ_REG(hw, TXDCTL);
+        ctrl = er32(TXDCTL);
         ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB;
-        E1000_WRITE_REG(hw, TXDCTL, ctrl);
+        ew32(TXDCTL, ctrl);
     }
 
     if (hw->mac_type == e1000_82573) {
@@ -989,21 +996,21 @@
         break;
     case e1000_80003es2lan:
         /* Enable retransmit on late collisions */
-        reg_data = E1000_READ_REG(hw, TCTL);
+        reg_data = er32(TCTL);
         reg_data |= E1000_TCTL_RTLC;
-        E1000_WRITE_REG(hw, TCTL, reg_data);
+        ew32(TCTL, reg_data);
 
         /* Configure Gigabit Carry Extend Padding */
-        reg_data = E1000_READ_REG(hw, TCTL_EXT);
+        reg_data = er32(TCTL_EXT);
         reg_data &= ~E1000_TCTL_EXT_GCEX_MASK;
         reg_data |= DEFAULT_80003ES2LAN_TCTL_EXT_GCEX;
-        E1000_WRITE_REG(hw, TCTL_EXT, reg_data);
+        ew32(TCTL_EXT, reg_data);
 
         /* Configure Transmit Inter-Packet Gap */
-        reg_data = E1000_READ_REG(hw, TIPG);
+        reg_data = er32(TIPG);
         reg_data &= ~E1000_TIPG_IPGT_MASK;
         reg_data |= DEFAULT_80003ES2LAN_TIPG_IPGT_1000;
-        E1000_WRITE_REG(hw, TIPG, reg_data);
+        ew32(TIPG, reg_data);
 
         reg_data = E1000_READ_REG_ARRAY(hw, FFLT, 0x0001);
         reg_data &= ~0x00100000;
@@ -1012,17 +1019,17 @@
     case e1000_82571:
     case e1000_82572:
     case e1000_ich8lan:
-        ctrl = E1000_READ_REG(hw, TXDCTL1);
+        ctrl = er32(TXDCTL1);
         ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB;
-        E1000_WRITE_REG(hw, TXDCTL1, ctrl);
+        ew32(TXDCTL1, ctrl);
         break;
     }
 
 
     if (hw->mac_type == e1000_82573) {
-        u32 gcr = E1000_READ_REG(hw, GCR);
+        u32 gcr = er32(GCR);
         gcr |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
-        E1000_WRITE_REG(hw, GCR, gcr);
+        ew32(GCR, gcr);
     }
 
     /* Clear all of the statistics registers (clear on read).  It is
@@ -1039,11 +1046,11 @@
 
     if (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER ||
         hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3) {
-        ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+        ctrl_ext = er32(CTRL_EXT);
         /* Relaxed ordering must be disabled to avoid a parity
          * error crash in a PCI slot. */
         ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
-        E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+        ew32(CTRL_EXT, ctrl_ext);
     }
 
     return ret_val;
@@ -1054,8 +1061,7 @@
  *
  * hw - Struct containing variables accessed by shared code.
  *****************************************************************************/
-static s32
-e1000_adjust_serdes_amplitude(struct e1000_hw *hw)
+static s32 e1000_adjust_serdes_amplitude(struct e1000_hw *hw)
 {
     u16 eeprom_data;
     s32  ret_val;
@@ -1100,8 +1106,7 @@
  * established. Assumes the hardware has previously been reset and the
  * transmitter and receiver are not enabled.
  *****************************************************************************/
-s32
-e1000_setup_link(struct e1000_hw *hw)
+s32 e1000_setup_link(struct e1000_hw *hw)
 {
     u32 ctrl_ext;
     s32 ret_val;
@@ -1176,7 +1181,7 @@
         }
         ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) <<
                     SWDPIO__EXT_SHIFT);
-        E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+        ew32(CTRL_EXT, ctrl_ext);
     }
 
     /* Call the necessary subroutine to configure the link. */
@@ -1193,12 +1198,12 @@
 
     /* FCAL/H and FCT are hardcoded to standard values in e1000_ich8lan. */
     if (hw->mac_type != e1000_ich8lan) {
-        E1000_WRITE_REG(hw, FCT, FLOW_CONTROL_TYPE);
-        E1000_WRITE_REG(hw, FCAH, FLOW_CONTROL_ADDRESS_HIGH);
-        E1000_WRITE_REG(hw, FCAL, FLOW_CONTROL_ADDRESS_LOW);
+        ew32(FCT, FLOW_CONTROL_TYPE);
+        ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH);
+        ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW);
     }
 
-    E1000_WRITE_REG(hw, FCTTV, hw->fc_pause_time);
+    ew32(FCTTV, hw->fc_pause_time);
 
     /* Set the flow control receive threshold registers.  Normally,
      * these registers will be set to a default threshold that may be
@@ -1207,18 +1212,18 @@
      * registers will be set to 0.
      */
     if (!(hw->fc & E1000_FC_TX_PAUSE)) {
-        E1000_WRITE_REG(hw, FCRTL, 0);
-        E1000_WRITE_REG(hw, FCRTH, 0);
+        ew32(FCRTL, 0);
+        ew32(FCRTH, 0);
     } else {
         /* We need to set up the Receive Threshold high and low water marks
          * as well as (optionally) enabling the transmission of XON frames.
          */
         if (hw->fc_send_xon) {
-            E1000_WRITE_REG(hw, FCRTL, (hw->fc_low_water | E1000_FCRTL_XONE));
-            E1000_WRITE_REG(hw, FCRTH, hw->fc_high_water);
+            ew32(FCRTL, (hw->fc_low_water | E1000_FCRTL_XONE));
+            ew32(FCRTH, hw->fc_high_water);
         } else {
-            E1000_WRITE_REG(hw, FCRTL, hw->fc_low_water);
-            E1000_WRITE_REG(hw, FCRTH, hw->fc_high_water);
+            ew32(FCRTL, hw->fc_low_water);
+            ew32(FCRTH, hw->fc_high_water);
         }
     }
     return ret_val;
@@ -1233,8 +1238,7 @@
  * link. Assumes the hardware has been previously reset and the transmitter
  * and receiver are not enabled.
  *****************************************************************************/
-static s32
-e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
+static s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
 {
     u32 ctrl;
     u32 status;
@@ -1251,7 +1255,7 @@
      * loopback mode is disabled during initialization.
      */
     if (hw->mac_type == e1000_82571 || hw->mac_type == e1000_82572)
-        E1000_WRITE_REG(hw, SCTL, E1000_DISABLE_SERDES_LOOPBACK);
+        ew32(SCTL, E1000_DISABLE_SERDES_LOOPBACK);
 
     /* On adapters with a MAC newer than 82544, SWDP 1 will be
      * set when the optics detect a signal. On older adapters, it will be
@@ -1259,7 +1263,7 @@
      * If we're on serdes media, adjust the output amplitude to value
      * set in the EEPROM.
      */
-    ctrl = E1000_READ_REG(hw, CTRL);
+    ctrl = er32(CTRL);
     if (hw->media_type == e1000_media_type_fiber)
         signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
 
@@ -1330,9 +1334,9 @@
      */
     DEBUGOUT("Auto-negotiation enabled\n");
 
-    E1000_WRITE_REG(hw, TXCW, txcw);
-    E1000_WRITE_REG(hw, CTRL, ctrl);
-    E1000_WRITE_FLUSH(hw);
+    ew32(TXCW, txcw);
+    ew32(CTRL, ctrl);
+    E1000_WRITE_FLUSH();
 
     hw->txcw = txcw;
     msleep(1);
@@ -1344,11 +1348,11 @@
      * For internal serdes, we just assume a signal is present, then poll.
      */
     if (hw->media_type == e1000_media_type_internal_serdes ||
-       (E1000_READ_REG(hw, CTRL) & E1000_CTRL_SWDPIN1) == signal) {
+       (er32(CTRL) & E1000_CTRL_SWDPIN1) == signal) {
         DEBUGOUT("Looking for Link\n");
         for (i = 0; i < (LINK_UP_TIMEOUT / 10); i++) {
             msleep(10);
-            status = E1000_READ_REG(hw, STATUS);
+            status = er32(STATUS);
             if (status & E1000_STATUS_LU) break;
         }
         if (i == (LINK_UP_TIMEOUT / 10)) {
@@ -1380,8 +1384,7 @@
 *
 * hw - Struct containing variables accessed by shared code
 ******************************************************************************/
-static s32
-e1000_copper_link_preconfig(struct e1000_hw *hw)
+static s32 e1000_copper_link_preconfig(struct e1000_hw *hw)
 {
     u32 ctrl;
     s32 ret_val;
@@ -1389,7 +1392,7 @@
 
     DEBUGFUNC("e1000_copper_link_preconfig");
 
-    ctrl = E1000_READ_REG(hw, CTRL);
+    ctrl = er32(CTRL);
     /* With 82543, we need to force speed and duplex on the MAC equal to what
      * the PHY speed and duplex configuration is. In addition, we need to
      * perform a hardware reset on the PHY to take it out of reset.
@@ -1397,10 +1400,10 @@
     if (hw->mac_type > e1000_82543) {
         ctrl |= E1000_CTRL_SLU;
         ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
-        E1000_WRITE_REG(hw, CTRL, ctrl);
+        ew32(CTRL, ctrl);
     } else {
         ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU);
-        E1000_WRITE_REG(hw, CTRL, ctrl);
+        ew32(CTRL, ctrl);
         ret_val = e1000_phy_hw_reset(hw);
         if (ret_val)
             return ret_val;
@@ -1440,8 +1443,7 @@
 *
 * hw - Struct containing variables accessed by shared code
 *********************************************************************/
-static s32
-e1000_copper_link_igp_setup(struct e1000_hw *hw)
+static s32 e1000_copper_link_igp_setup(struct e1000_hw *hw)
 {
     u32 led_ctrl;
     s32 ret_val;
@@ -1462,10 +1464,10 @@
     msleep(15);
     if (hw->mac_type != e1000_ich8lan) {
     /* Configure activity LED after PHY reset */
-    led_ctrl = E1000_READ_REG(hw, LEDCTL);
+    led_ctrl = er32(LEDCTL);
     led_ctrl &= IGP_ACTIVITY_LED_MASK;
     led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
-    E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
+    ew32(LEDCTL, led_ctrl);
     }
 
     /* The NVM settings will configure LPLU in D3 for IGP2 and IGP3 PHYs */
@@ -1587,8 +1589,7 @@
 *
 * hw - Struct containing variables accessed by shared code
 *********************************************************************/
-static s32
-e1000_copper_link_ggp_setup(struct e1000_hw *hw)
+static s32 e1000_copper_link_ggp_setup(struct e1000_hw *hw)
 {
     s32 ret_val;
     u16 phy_data;
@@ -1679,9 +1680,9 @@
         if (ret_val)
             return ret_val;
 
-        reg_data = E1000_READ_REG(hw, CTRL_EXT);
+        reg_data = er32(CTRL_EXT);
         reg_data &= ~(E1000_CTRL_EXT_LINK_MODE_MASK);
-        E1000_WRITE_REG(hw, CTRL_EXT, reg_data);
+        ew32(CTRL_EXT, reg_data);
 
         ret_val = e1000_read_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
                                           &phy_data);
@@ -1735,8 +1736,7 @@
 *
 * hw - Struct containing variables accessed by shared code
 *********************************************************************/
-static s32
-e1000_copper_link_mgp_setup(struct e1000_hw *hw)
+static s32 e1000_copper_link_mgp_setup(struct e1000_hw *hw)
 {
     s32 ret_val;
     u16 phy_data;
@@ -1839,8 +1839,7 @@
 *
 * hw - Struct containing variables accessed by shared code
 *********************************************************************/
-static s32
-e1000_copper_link_autoneg(struct e1000_hw *hw)
+static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
 {
     s32 ret_val;
     u16 phy_data;
@@ -1910,8 +1909,7 @@
 *
 * hw - Struct containing variables accessed by shared code
 ******************************************************************************/
-static s32
-e1000_copper_link_postconfig(struct e1000_hw *hw)
+static s32 e1000_copper_link_postconfig(struct e1000_hw *hw)
 {
     s32 ret_val;
     DEBUGFUNC("e1000_copper_link_postconfig");
@@ -1948,8 +1946,7 @@
 *
 * hw - Struct containing variables accessed by shared code
 ******************************************************************************/
-static s32
-e1000_setup_copper_link(struct e1000_hw *hw)
+static s32 e1000_setup_copper_link(struct e1000_hw *hw)
 {
     s32 ret_val;
     u16 i;
@@ -2062,8 +2059,7 @@
 *
 * hw - Struct containing variables accessed by shared code
 ******************************************************************************/
-static s32
-e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, u16 duplex)
+static s32 e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, u16 duplex)
 {
     s32 ret_val = E1000_SUCCESS;
     u32 tipg;
@@ -2078,10 +2074,10 @@
         return ret_val;
 
     /* Configure Transmit Inter-Packet Gap */
-    tipg = E1000_READ_REG(hw, TIPG);
+    tipg = er32(TIPG);
     tipg &= ~E1000_TIPG_IPGT_MASK;
     tipg |= DEFAULT_80003ES2LAN_TIPG_IPGT_10_100;
-    E1000_WRITE_REG(hw, TIPG, tipg);
+    ew32(TIPG, tipg);
 
     ret_val = e1000_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data);
 
@@ -2098,8 +2094,7 @@
     return ret_val;
 }
 
-static s32
-e1000_configure_kmrn_for_1000(struct e1000_hw *hw)
+static s32 e1000_configure_kmrn_for_1000(struct e1000_hw *hw)
 {
     s32 ret_val = E1000_SUCCESS;
     u16 reg_data;
@@ -2114,10 +2109,10 @@
         return ret_val;
 
     /* Configure Transmit Inter-Packet Gap */
-    tipg = E1000_READ_REG(hw, TIPG);
+    tipg = er32(TIPG);
     tipg &= ~E1000_TIPG_IPGT_MASK;
     tipg |= DEFAULT_80003ES2LAN_TIPG_IPGT_1000;
-    E1000_WRITE_REG(hw, TIPG, tipg);
+    ew32(TIPG, tipg);
 
     ret_val = e1000_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, &reg_data);
 
@@ -2135,8 +2130,7 @@
 *
 * hw - Struct containing variables accessed by shared code
 ******************************************************************************/
-s32
-e1000_phy_setup_autoneg(struct e1000_hw *hw)
+s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
 {
     s32 ret_val;
     u16 mii_autoneg_adv_reg;
@@ -2284,8 +2278,7 @@
 *
 * hw - Struct containing variables accessed by shared code
 ******************************************************************************/
-static s32
-e1000_phy_force_speed_duplex(struct e1000_hw *hw)
+static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw)
 {
     u32 ctrl;
     s32 ret_val;
@@ -2302,7 +2295,7 @@
     DEBUGOUT1("hw->fc = %d\n", hw->fc);
 
     /* Read the Device Control Register. */
-    ctrl = E1000_READ_REG(hw, CTRL);
+    ctrl = er32(CTRL);
 
     /* Set the bits to Force Speed and Duplex in the Device Ctrl Reg. */
     ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
@@ -2357,7 +2350,7 @@
     e1000_config_collision_dist(hw);
 
     /* Write the configured values back to the Device Control Reg. */
-    E1000_WRITE_REG(hw, CTRL, ctrl);
+    ew32(CTRL, ctrl);
 
     if ((hw->phy_type == e1000_phy_m88) ||
         (hw->phy_type == e1000_phy_gg82563)) {
@@ -2535,8 +2528,7 @@
 * Link should have been established previously. Reads the speed and duplex
 * information from the Device Status register.
 ******************************************************************************/
-void
-e1000_config_collision_dist(struct e1000_hw *hw)
+void e1000_config_collision_dist(struct e1000_hw *hw)
 {
     u32 tctl, coll_dist;
 
@@ -2547,13 +2539,13 @@
     else
         coll_dist = E1000_COLLISION_DISTANCE;
 
-    tctl = E1000_READ_REG(hw, TCTL);
+    tctl = er32(TCTL);
 
     tctl &= ~E1000_TCTL_COLD;
     tctl |= coll_dist << E1000_COLD_SHIFT;
 
-    E1000_WRITE_REG(hw, TCTL, tctl);
-    E1000_WRITE_FLUSH(hw);
+    ew32(TCTL, tctl);
+    E1000_WRITE_FLUSH();
 }
 
 /******************************************************************************
@@ -2565,8 +2557,7 @@
 * The contents of the PHY register containing the needed information need to
 * be passed in.
 ******************************************************************************/
-static s32
-e1000_config_mac_to_phy(struct e1000_hw *hw)
+static s32 e1000_config_mac_to_phy(struct e1000_hw *hw)
 {
     u32 ctrl;
     s32 ret_val;
@@ -2582,7 +2573,7 @@
     /* Read the Device Control Register and set the bits to Force Speed
      * and Duplex.
      */
-    ctrl = E1000_READ_REG(hw, CTRL);
+    ctrl = er32(CTRL);
     ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
     ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS);
 
@@ -2609,7 +2600,7 @@
         ctrl |= E1000_CTRL_SPD_100;
 
     /* Write the configured values back to the Device Control Reg. */
-    E1000_WRITE_REG(hw, CTRL, ctrl);
+    ew32(CTRL, ctrl);
     return E1000_SUCCESS;
 }
 
@@ -2624,15 +2615,14 @@
  * by the PHY rather than the MAC. Software must also configure these
  * bits when link is forced on a fiber connection.
  *****************************************************************************/
-s32
-e1000_force_mac_fc(struct e1000_hw *hw)
+s32 e1000_force_mac_fc(struct e1000_hw *hw)
 {
     u32 ctrl;
 
     DEBUGFUNC("e1000_force_mac_fc");
 
     /* Get the current configuration of the Device Control Register */
-    ctrl = E1000_READ_REG(hw, CTRL);
+    ctrl = er32(CTRL);
 
     /* Because we didn't get link via the internal auto-negotiation
      * mechanism (we either forced link or we got link via PHY
@@ -2676,7 +2666,7 @@
     if (hw->mac_type == e1000_82542_rev2_0)
         ctrl &= (~E1000_CTRL_TFCE);
 
-    E1000_WRITE_REG(hw, CTRL, ctrl);
+    ew32(CTRL, ctrl);
     return E1000_SUCCESS;
 }
 
@@ -2691,8 +2681,7 @@
  * based on the flow control negotiated by the PHY. In TBI mode, the TFCE
  * and RFCE bits will be automaticaly set to the negotiated flow control mode.
  *****************************************************************************/
-static s32
-e1000_config_fc_after_link_up(struct e1000_hw *hw)
+static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw)
 {
     s32 ret_val;
     u16 mii_status_reg;
@@ -2896,8 +2885,7 @@
  *
  * Called by any function that needs to check the link status of the adapter.
  *****************************************************************************/
-s32
-e1000_check_for_link(struct e1000_hw *hw)
+s32 e1000_check_for_link(struct e1000_hw *hw)
 {
     u32 rxcw = 0;
     u32 ctrl;
@@ -2910,8 +2898,8 @@
 
     DEBUGFUNC("e1000_check_for_link");
 
-    ctrl = E1000_READ_REG(hw, CTRL);
-    status = E1000_READ_REG(hw, STATUS);
+    ctrl = er32(CTRL);
+    status = er32(STATUS);
 
     /* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be
      * set when the optics detect a signal. On older adapters, it will be
@@ -2919,7 +2907,7 @@
      */
     if ((hw->media_type == e1000_media_type_fiber) ||
         (hw->media_type == e1000_media_type_internal_serdes)) {
-        rxcw = E1000_READ_REG(hw, RXCW);
+        rxcw = er32(RXCW);
 
         if (hw->media_type == e1000_media_type_fiber) {
             signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
@@ -2965,11 +2953,11 @@
                 (!hw->autoneg) &&
                 (hw->forced_speed_duplex == e1000_10_full ||
                  hw->forced_speed_duplex == e1000_10_half)) {
-                E1000_WRITE_REG(hw, IMC, 0xffffffff);
+                ew32(IMC, 0xffffffff);
                 ret_val = e1000_polarity_reversal_workaround(hw);
-                icr = E1000_READ_REG(hw, ICR);
-                E1000_WRITE_REG(hw, ICS, (icr & ~E1000_ICS_LSC));
-                E1000_WRITE_REG(hw, IMS, IMS_ENABLE_MASK);
+                icr = er32(ICR);
+                ew32(ICS, (icr & ~E1000_ICS_LSC));
+                ew32(IMS, IMS_ENABLE_MASK);
             }
 
         } else {
@@ -3034,9 +3022,9 @@
                  */
                 if (hw->tbi_compatibility_on) {
                     /* If we previously were in the mode, turn it off. */
-                    rctl = E1000_READ_REG(hw, RCTL);
+                    rctl = er32(RCTL);
                     rctl &= ~E1000_RCTL_SBP;
-                    E1000_WRITE_REG(hw, RCTL, rctl);
+                    ew32(RCTL, rctl);
                     hw->tbi_compatibility_on = false;
                 }
             } else {
@@ -3047,9 +3035,9 @@
                  */
                 if (!hw->tbi_compatibility_on) {
                     hw->tbi_compatibility_on = true;
-                    rctl = E1000_READ_REG(hw, RCTL);
+                    rctl = er32(RCTL);
                     rctl |= E1000_RCTL_SBP;
-                    E1000_WRITE_REG(hw, RCTL, rctl);
+                    ew32(RCTL, rctl);
                 }
             }
         }
@@ -3073,12 +3061,12 @@
         DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
 
         /* Disable auto-negotiation in the TXCW register */
-        E1000_WRITE_REG(hw, TXCW, (hw->txcw & ~E1000_TXCW_ANE));
+        ew32(TXCW, (hw->txcw & ~E1000_TXCW_ANE));
 
         /* Force link-up and also force full-duplex. */
-        ctrl = E1000_READ_REG(hw, CTRL);
+        ctrl = er32(CTRL);
         ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
-        E1000_WRITE_REG(hw, CTRL, ctrl);
+        ew32(CTRL, ctrl);
 
         /* Configure Flow Control after forcing link up. */
         ret_val = e1000_config_fc_after_link_up(hw);
@@ -3096,8 +3084,8 @@
               (hw->media_type == e1000_media_type_internal_serdes)) &&
               (ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
         DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
-        E1000_WRITE_REG(hw, TXCW, hw->txcw);
-        E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU));
+        ew32(TXCW, hw->txcw);
+        ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
 
         hw->serdes_link_down = false;
     }
@@ -3105,10 +3093,10 @@
      * based on MAC synchronization for internal serdes media type.
      */
     else if ((hw->media_type == e1000_media_type_internal_serdes) &&
-             !(E1000_TXCW_ANE & E1000_READ_REG(hw, TXCW))) {
+             !(E1000_TXCW_ANE & er32(TXCW))) {
         /* SYNCH bit and IV bit are sticky. */
         udelay(10);
-        if (E1000_RXCW_SYNCH & E1000_READ_REG(hw, RXCW)) {
+        if (E1000_RXCW_SYNCH & er32(RXCW)) {
             if (!(rxcw & E1000_RXCW_IV)) {
                 hw->serdes_link_down = false;
                 DEBUGOUT("SERDES: Link is up.\n");
@@ -3119,8 +3107,8 @@
         }
     }
     if ((hw->media_type == e1000_media_type_internal_serdes) &&
-        (E1000_TXCW_ANE & E1000_READ_REG(hw, TXCW))) {
-        hw->serdes_link_down = !(E1000_STATUS_LU & E1000_READ_REG(hw, STATUS));
+        (E1000_TXCW_ANE & er32(TXCW))) {
+        hw->serdes_link_down = !(E1000_STATUS_LU & er32(STATUS));
     }
     return E1000_SUCCESS;
 }
@@ -3132,10 +3120,7 @@
  * speed - Speed of the connection
  * duplex - Duplex setting of the connection
  *****************************************************************************/
-s32
-e1000_get_speed_and_duplex(struct e1000_hw *hw,
-                           u16 *speed,
-                           u16 *duplex)
+s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex)
 {
     u32 status;
     s32 ret_val;
@@ -3144,7 +3129,7 @@
     DEBUGFUNC("e1000_get_speed_and_duplex");
 
     if (hw->mac_type >= e1000_82543) {
-        status = E1000_READ_REG(hw, STATUS);
+        status = er32(STATUS);
         if (status & E1000_STATUS_SPEED_1000) {
             *speed = SPEED_1000;
             DEBUGOUT("1000 Mbs, ");
@@ -3214,8 +3199,7 @@
 *
 * hw - Struct containing variables accessed by shared code
 ******************************************************************************/
-static s32
-e1000_wait_autoneg(struct e1000_hw *hw)
+static s32 e1000_wait_autoneg(struct e1000_hw *hw)
 {
     s32 ret_val;
     u16 i;
@@ -3249,15 +3233,13 @@
 * hw - Struct containing variables accessed by shared code
 * ctrl - Device control register's current value
 ******************************************************************************/
-static void
-e1000_raise_mdi_clk(struct e1000_hw *hw,
-                    u32 *ctrl)
+static void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl)
 {
     /* Raise the clock input to the Management Data Clock (by setting the MDC
      * bit), and then delay 10 microseconds.
      */
-    E1000_WRITE_REG(hw, CTRL, (*ctrl | E1000_CTRL_MDC));
-    E1000_WRITE_FLUSH(hw);
+    ew32(CTRL, (*ctrl | E1000_CTRL_MDC));
+    E1000_WRITE_FLUSH();
     udelay(10);
 }
 
@@ -3267,15 +3249,13 @@
 * hw - Struct containing variables accessed by shared code
 * ctrl - Device control register's current value
 ******************************************************************************/
-static void
-e1000_lower_mdi_clk(struct e1000_hw *hw,
-                    u32 *ctrl)
+static void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl)
 {
     /* Lower the clock input to the Management Data Clock (by clearing the MDC
      * bit), and then delay 10 microseconds.
      */
-    E1000_WRITE_REG(hw, CTRL, (*ctrl & ~E1000_CTRL_MDC));
-    E1000_WRITE_FLUSH(hw);
+    ew32(CTRL, (*ctrl & ~E1000_CTRL_MDC));
+    E1000_WRITE_FLUSH();
     udelay(10);
 }
 
@@ -3288,10 +3268,7 @@
 *
 * Bits are shifted out in MSB to LSB order.
 ******************************************************************************/
-static void
-e1000_shift_out_mdi_bits(struct e1000_hw *hw,
-                         u32 data,
-                         u16 count)
+static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data, u16 count)
 {
     u32 ctrl;
     u32 mask;
@@ -3303,7 +3280,7 @@
     mask = 0x01;
     mask <<= (count - 1);
 
-    ctrl = E1000_READ_REG(hw, CTRL);
+    ctrl = er32(CTRL);
 
     /* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */
     ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR);
@@ -3319,8 +3296,8 @@
         else
             ctrl &= ~E1000_CTRL_MDIO;
 
-        E1000_WRITE_REG(hw, CTRL, ctrl);
-        E1000_WRITE_FLUSH(hw);
+        ew32(CTRL, ctrl);
+        E1000_WRITE_FLUSH();
 
         udelay(10);
 
@@ -3338,8 +3315,7 @@
 *
 * Bits are shifted in in MSB to LSB order.
 ******************************************************************************/
-static u16
-e1000_shift_in_mdi_bits(struct e1000_hw *hw)
+static u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw)
 {
     u32 ctrl;
     u16 data = 0;
@@ -3352,14 +3328,14 @@
      * by raising the input to the Management Data Clock (setting the MDC bit),
      * and then reading the value of the MDIO bit.
      */
-    ctrl = E1000_READ_REG(hw, CTRL);
+    ctrl = er32(CTRL);
 
     /* Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as input. */
     ctrl &= ~E1000_CTRL_MDIO_DIR;
     ctrl &= ~E1000_CTRL_MDIO;
 
-    E1000_WRITE_REG(hw, CTRL, ctrl);
-    E1000_WRITE_FLUSH(hw);
+    ew32(CTRL, ctrl);
+    E1000_WRITE_FLUSH();
 
     /* Raise and Lower the clock before reading in the data. This accounts for
      * the turnaround bits. The first clock occurred when we clocked out the
@@ -3371,7 +3347,7 @@
     for (data = 0, i = 0; i < 16; i++) {
         data = data << 1;
         e1000_raise_mdi_clk(hw, &ctrl);
-        ctrl = E1000_READ_REG(hw, CTRL);
+        ctrl = er32(CTRL);
         /* Check to see if we shifted in a "1". */
         if (ctrl & E1000_CTRL_MDIO)
             data |= 1;
@@ -3384,8 +3360,7 @@
     return data;
 }
 
-static s32
-e1000_swfw_sync_acquire(struct e1000_hw *hw, u16 mask)
+static s32 e1000_swfw_sync_acquire(struct e1000_hw *hw, u16 mask)
 {
     u32 swfw_sync = 0;
     u32 swmask = mask;
@@ -3404,7 +3379,7 @@
             if (e1000_get_hw_eeprom_semaphore(hw))
                 return -E1000_ERR_SWFW_SYNC;
 
-            swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC);
+            swfw_sync = er32(SW_FW_SYNC);
             if (!(swfw_sync & (fwmask | swmask))) {
                 break;
             }
@@ -3422,14 +3397,13 @@
     }
 
     swfw_sync |= swmask;
-    E1000_WRITE_REG(hw, SW_FW_SYNC, swfw_sync);
+    ew32(SW_FW_SYNC, swfw_sync);
 
     e1000_put_hw_eeprom_semaphore(hw);
     return E1000_SUCCESS;
 }
 
-static void
-e1000_swfw_sync_release(struct e1000_hw *hw, u16 mask)
+static void e1000_swfw_sync_release(struct e1000_hw *hw, u16 mask)
 {
     u32 swfw_sync;
     u32 swmask = mask;
@@ -3451,9 +3425,9 @@
     while (e1000_get_hw_eeprom_semaphore(hw) != E1000_SUCCESS);
         /* empty */
 
-    swfw_sync = E1000_READ_REG(hw, SW_FW_SYNC);
+    swfw_sync = er32(SW_FW_SYNC);
     swfw_sync &= ~swmask;
-    E1000_WRITE_REG(hw, SW_FW_SYNC, swfw_sync);
+    ew32(SW_FW_SYNC, swfw_sync);
 
     e1000_put_hw_eeprom_semaphore(hw);
 }
@@ -3464,10 +3438,7 @@
 * hw - Struct containing variables accessed by shared code
 * reg_addr - address of the PHY register to read
 ******************************************************************************/
-s32
-e1000_read_phy_reg(struct e1000_hw *hw,
-                   u32 reg_addr,
-                   u16 *phy_data)
+s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 *phy_data)
 {
     u32 ret_val;
     u16 swfw;
@@ -3475,7 +3446,7 @@
     DEBUGFUNC("e1000_read_phy_reg");
 
     if ((hw->mac_type == e1000_80003es2lan) &&
-        (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+        (er32(STATUS) & E1000_STATUS_FUNC_1)) {
         swfw = E1000_SWFW_PHY1_SM;
     } else {
         swfw = E1000_SWFW_PHY0_SM;
@@ -3523,9 +3494,8 @@
     return ret_val;
 }
 
-static s32
-e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
-                      u16 *phy_data)
+static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
+				 u16 *phy_data)
 {
     u32 i;
     u32 mdic = 0;
@@ -3547,12 +3517,12 @@
                 (phy_addr << E1000_MDIC_PHY_SHIFT) |
                 (E1000_MDIC_OP_READ));
 
-        E1000_WRITE_REG(hw, MDIC, mdic);
+        ew32(MDIC, mdic);
 
         /* Poll the ready bit to see if the MDI read completed */
         for (i = 0; i < 64; i++) {
             udelay(50);
-            mdic = E1000_READ_REG(hw, MDIC);
+            mdic = er32(MDIC);
             if (mdic & E1000_MDIC_READY) break;
         }
         if (!(mdic & E1000_MDIC_READY)) {
@@ -3563,7 +3533,7 @@
             DEBUGOUT("MDI Error\n");
             return -E1000_ERR_PHY;
         }
-        *phy_data = (u16) mdic;
+        *phy_data = (u16)mdic;
     } else {
         /* We must first send a preamble through the MDIO pin to signal the
          * beginning of an MII instruction.  This is done by sending 32
@@ -3603,9 +3573,7 @@
 * reg_addr - address of the PHY register to write
 * data - data to write to the PHY
 ******************************************************************************/
-s32
-e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr,
-                    u16 phy_data)
+s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 phy_data)
 {
     u32 ret_val;
     u16 swfw;
@@ -3613,7 +3581,7 @@
     DEBUGFUNC("e1000_write_phy_reg");
 
     if ((hw->mac_type == e1000_80003es2lan) &&
-        (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+        (er32(STATUS) & E1000_STATUS_FUNC_1)) {
         swfw = E1000_SWFW_PHY1_SM;
     } else {
         swfw = E1000_SWFW_PHY0_SM;
@@ -3661,9 +3629,8 @@
     return ret_val;
 }
 
-static s32
-e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
-                       u16 phy_data)
+static s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
+				  u16 phy_data)
 {
     u32 i;
     u32 mdic = 0;
@@ -3681,17 +3648,17 @@
          * for the PHY register in the MDI Control register.  The MAC will take
          * care of interfacing with the PHY to send the desired data.
          */
-        mdic = (((u32) phy_data) |
+        mdic = (((u32)phy_data) |
                 (reg_addr << E1000_MDIC_REG_SHIFT) |
                 (phy_addr << E1000_MDIC_PHY_SHIFT) |
                 (E1000_MDIC_OP_WRITE));
 
-        E1000_WRITE_REG(hw, MDIC, mdic);
+        ew32(MDIC, mdic);
 
         /* Poll the ready bit to see if the MDI read completed */
         for (i = 0; i < 641; i++) {
             udelay(5);
-            mdic = E1000_READ_REG(hw, MDIC);
+            mdic = er32(MDIC);
             if (mdic & E1000_MDIC_READY) break;
         }
         if (!(mdic & E1000_MDIC_READY)) {
@@ -3715,7 +3682,7 @@
         mdic = ((PHY_TURNAROUND) | (reg_addr << 2) | (phy_addr << 7) |
                 (PHY_OP_WRITE << 12) | (PHY_SOF << 14));
         mdic <<= 16;
-        mdic |= (u32) phy_data;
+        mdic |= (u32)phy_data;
 
         e1000_shift_out_mdi_bits(hw, mdic, 32);
     }
@@ -3723,17 +3690,14 @@
     return E1000_SUCCESS;
 }
 
-static s32
-e1000_read_kmrn_reg(struct e1000_hw *hw,
-                    u32 reg_addr,
-                    u16 *data)
+static s32 e1000_read_kmrn_reg(struct e1000_hw *hw, u32 reg_addr, u16 *data)
 {
     u32 reg_val;
     u16 swfw;
     DEBUGFUNC("e1000_read_kmrn_reg");
 
     if ((hw->mac_type == e1000_80003es2lan) &&
-        (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+        (er32(STATUS) & E1000_STATUS_FUNC_1)) {
         swfw = E1000_SWFW_PHY1_SM;
     } else {
         swfw = E1000_SWFW_PHY0_SM;
@@ -3745,28 +3709,25 @@
     reg_val = ((reg_addr << E1000_KUMCTRLSTA_OFFSET_SHIFT) &
               E1000_KUMCTRLSTA_OFFSET) |
               E1000_KUMCTRLSTA_REN;
-    E1000_WRITE_REG(hw, KUMCTRLSTA, reg_val);
+    ew32(KUMCTRLSTA, reg_val);
     udelay(2);
 
     /* Read the data returned */
-    reg_val = E1000_READ_REG(hw, KUMCTRLSTA);
+    reg_val = er32(KUMCTRLSTA);
     *data = (u16)reg_val;
 
     e1000_swfw_sync_release(hw, swfw);
     return E1000_SUCCESS;
 }
 
-static s32
-e1000_write_kmrn_reg(struct e1000_hw *hw,
-                     u32 reg_addr,
-                     u16 data)
+static s32 e1000_write_kmrn_reg(struct e1000_hw *hw, u32 reg_addr, u16 data)
 {
     u32 reg_val;
     u16 swfw;
     DEBUGFUNC("e1000_write_kmrn_reg");
 
     if ((hw->mac_type == e1000_80003es2lan) &&
-        (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+        (er32(STATUS) & E1000_STATUS_FUNC_1)) {
         swfw = E1000_SWFW_PHY1_SM;
     } else {
         swfw = E1000_SWFW_PHY0_SM;
@@ -3776,7 +3737,7 @@
 
     reg_val = ((reg_addr << E1000_KUMCTRLSTA_OFFSET_SHIFT) &
               E1000_KUMCTRLSTA_OFFSET) | data;
-    E1000_WRITE_REG(hw, KUMCTRLSTA, reg_val);
+    ew32(KUMCTRLSTA, reg_val);
     udelay(2);
 
     e1000_swfw_sync_release(hw, swfw);
@@ -3788,8 +3749,7 @@
 *
 * hw - Struct containing variables accessed by shared code
 ******************************************************************************/
-s32
-e1000_phy_hw_reset(struct e1000_hw *hw)
+s32 e1000_phy_hw_reset(struct e1000_hw *hw)
 {
     u32 ctrl, ctrl_ext;
     u32 led_ctrl;
@@ -3808,7 +3768,7 @@
 
     if (hw->mac_type > e1000_82543) {
         if ((hw->mac_type == e1000_80003es2lan) &&
-            (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
+            (er32(STATUS) & E1000_STATUS_FUNC_1)) {
             swfw = E1000_SWFW_PHY1_SM;
         } else {
             swfw = E1000_SWFW_PHY0_SM;
@@ -3823,17 +3783,17 @@
          * and deassert.  For e1000_82571 hardware and later, we instead delay
          * for 50us between and 10ms after the deassertion.
          */
-        ctrl = E1000_READ_REG(hw, CTRL);
-        E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST);
-        E1000_WRITE_FLUSH(hw);
+        ctrl = er32(CTRL);
+        ew32(CTRL, ctrl | E1000_CTRL_PHY_RST);
+        E1000_WRITE_FLUSH();
 
         if (hw->mac_type < e1000_82571)
             msleep(10);
         else
             udelay(100);
 
-        E1000_WRITE_REG(hw, CTRL, ctrl);
-        E1000_WRITE_FLUSH(hw);
+        ew32(CTRL, ctrl);
+        E1000_WRITE_FLUSH();
 
         if (hw->mac_type >= e1000_82571)
             mdelay(10);
@@ -3843,24 +3803,24 @@
         /* Read the Extended Device Control Register, assert the PHY_RESET_DIR
          * bit to put the PHY into reset. Then, take it out of reset.
          */
-        ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+        ctrl_ext = er32(CTRL_EXT);
         ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR;
         ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA;
-        E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
-        E1000_WRITE_FLUSH(hw);
+        ew32(CTRL_EXT, ctrl_ext);
+        E1000_WRITE_FLUSH();
         msleep(10);
         ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA;
-        E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
-        E1000_WRITE_FLUSH(hw);
+        ew32(CTRL_EXT, ctrl_ext);
+        E1000_WRITE_FLUSH();
     }
     udelay(150);
 
     if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
         /* Configure activity LED after PHY reset */
-        led_ctrl = E1000_READ_REG(hw, LEDCTL);
+        led_ctrl = er32(LEDCTL);
         led_ctrl &= IGP_ACTIVITY_LED_MASK;
         led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
-        E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
+        ew32(LEDCTL, led_ctrl);
     }
 
     /* Wait for FW to finish PHY configuration. */
@@ -3882,8 +3842,7 @@
 *
 * Sets bit 15 of the MII Control register
 ******************************************************************************/
-s32
-e1000_phy_reset(struct e1000_hw *hw)
+s32 e1000_phy_reset(struct e1000_hw *hw)
 {
     s32 ret_val;
     u16 phy_data;
@@ -3934,8 +3893,7 @@
 *
 * hw - struct containing variables accessed by shared code
 ******************************************************************************/
-void
-e1000_phy_powerdown_workaround(struct e1000_hw *hw)
+void e1000_phy_powerdown_workaround(struct e1000_hw *hw)
 {
     s32 reg;
     u16 phy_data;
@@ -3948,8 +3906,8 @@
 
     do {
         /* Disable link */
-        reg = E1000_READ_REG(hw, PHY_CTRL);
-        E1000_WRITE_REG(hw, PHY_CTRL, reg | E1000_PHY_CTRL_GBE_DISABLE |
+        reg = er32(PHY_CTRL);
+        ew32(PHY_CTRL, reg | E1000_PHY_CTRL_GBE_DISABLE |
                         E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
 
         /* Write VR power-down enable - bits 9:8 should be 10b */
@@ -3964,8 +3922,8 @@
             break;
 
         /* Issue PHY reset and repeat at most one more time */
-        reg = E1000_READ_REG(hw, CTRL);
-        E1000_WRITE_REG(hw, CTRL, reg | E1000_CTRL_PHY_RST);
+        reg = er32(CTRL);
+        ew32(CTRL, reg | E1000_CTRL_PHY_RST);
         retry++;
     } while (retry);
 
@@ -3987,8 +3945,7 @@
 *
 * hw - struct containing variables accessed by shared code
 ******************************************************************************/
-static s32
-e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw)
+static s32 e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw)
 {
     s32 ret_val;
     s32 reg;
@@ -4024,8 +3981,8 @@
             mdelay(5);
         }
         /* Disable GigE link negotiation */
-        reg = E1000_READ_REG(hw, PHY_CTRL);
-        E1000_WRITE_REG(hw, PHY_CTRL, reg | E1000_PHY_CTRL_GBE_DISABLE |
+        reg = er32(PHY_CTRL);
+        ew32(PHY_CTRL, reg | E1000_PHY_CTRL_GBE_DISABLE |
                         E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
 
         /* unable to acquire PCS lock */
@@ -4040,8 +3997,7 @@
 *
 * hw - Struct containing variables accessed by shared code
 ******************************************************************************/
-static s32
-e1000_detect_gig_phy(struct e1000_hw *hw)
+static s32 e1000_detect_gig_phy(struct e1000_hw *hw)
 {
     s32 phy_init_status, ret_val;
     u16 phy_id_high, phy_id_low;
@@ -4076,14 +4032,14 @@
     if (ret_val)
         return ret_val;
 
-    hw->phy_id = (u32) (phy_id_high << 16);
+    hw->phy_id = (u32)(phy_id_high << 16);
     udelay(20);
     ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low);
     if (ret_val)
         return ret_val;
 
-    hw->phy_id |= (u32) (phy_id_low & PHY_REVISION_MASK);
-    hw->phy_revision = (u32) phy_id_low & ~PHY_REVISION_MASK;
+    hw->phy_id |= (u32)(phy_id_low & PHY_REVISION_MASK);
+    hw->phy_revision = (u32)phy_id_low & ~PHY_REVISION_MASK;
 
     switch (hw->mac_type) {
     case e1000_82543:
@@ -4136,8 +4092,7 @@
 *
 * hw - Struct containing variables accessed by shared code
 ******************************************************************************/
-static s32
-e1000_phy_reset_dsp(struct e1000_hw *hw)
+static s32 e1000_phy_reset_dsp(struct e1000_hw *hw)
 {
     s32 ret_val;
     DEBUGFUNC("e1000_phy_reset_dsp");
@@ -4163,9 +4118,8 @@
 * hw - Struct containing variables accessed by shared code
 * phy_info - PHY information structure
 ******************************************************************************/
-static s32
-e1000_phy_igp_get_info(struct e1000_hw *hw,
-                       struct e1000_phy_info *phy_info)
+static s32 e1000_phy_igp_get_info(struct e1000_hw *hw,
+				  struct e1000_phy_info *phy_info)
 {
     s32 ret_val;
     u16 phy_data, min_length, max_length, average;
@@ -4240,9 +4194,8 @@
 * hw - Struct containing variables accessed by shared code
 * phy_info - PHY information structure
 ******************************************************************************/
-static s32
-e1000_phy_ife_get_info(struct e1000_hw *hw,
-                       struct e1000_phy_info *phy_info)
+static s32 e1000_phy_ife_get_info(struct e1000_hw *hw,
+				  struct e1000_phy_info *phy_info)
 {
     s32 ret_val;
     u16 phy_data;
@@ -4290,9 +4243,8 @@
 * hw - Struct containing variables accessed by shared code
 * phy_info - PHY information structure
 ******************************************************************************/
-static s32
-e1000_phy_m88_get_info(struct e1000_hw *hw,
-                       struct e1000_phy_info *phy_info)
+static s32 e1000_phy_m88_get_info(struct e1000_hw *hw,
+				  struct e1000_phy_info *phy_info)
 {
     s32 ret_val;
     u16 phy_data;
@@ -4369,9 +4321,7 @@
 * hw - Struct containing variables accessed by shared code
 * phy_info - PHY information structure
 ******************************************************************************/
-s32
-e1000_phy_get_info(struct e1000_hw *hw,
-                   struct e1000_phy_info *phy_info)
+s32 e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info)
 {
     s32 ret_val;
     u16 phy_data;
@@ -4415,8 +4365,7 @@
         return e1000_phy_m88_get_info(hw, phy_info);
 }
 
-s32
-e1000_validate_mdi_setting(struct e1000_hw *hw)
+s32 e1000_validate_mdi_setting(struct e1000_hw *hw)
 {
     DEBUGFUNC("e1000_validate_mdi_settings");
 
@@ -4436,11 +4385,10 @@
  *
  * hw - Struct containing variables accessed by shared code
  *****************************************************************************/
-s32
-e1000_init_eeprom_params(struct e1000_hw *hw)
+s32 e1000_init_eeprom_params(struct e1000_hw *hw)
 {
     struct e1000_eeprom_info *eeprom = &hw->eeprom;
-    u32 eecd = E1000_READ_REG(hw, EECD);
+    u32 eecd = er32(EECD);
     s32 ret_val = E1000_SUCCESS;
     u16 eeprom_size;
 
@@ -4542,7 +4490,7 @@
             /* Ensure that the Autonomous FLASH update bit is cleared due to
              * Flash update issue on parts which use a FLASH for NVM. */
             eecd &= ~E1000_EECD_AUPDEN;
-            E1000_WRITE_REG(hw, EECD, eecd);
+            ew32(EECD, eecd);
         }
         break;
     case e1000_80003es2lan:
@@ -4626,16 +4574,14 @@
  * hw - Struct containing variables accessed by shared code
  * eecd - EECD's current value
  *****************************************************************************/
-static void
-e1000_raise_ee_clk(struct e1000_hw *hw,
-                   u32 *eecd)
+static void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd)
 {
     /* Raise the clock input to the EEPROM (by setting the SK bit), and then
      * wait <delay> microseconds.
      */
     *eecd = *eecd | E1000_EECD_SK;
-    E1000_WRITE_REG(hw, EECD, *eecd);
-    E1000_WRITE_FLUSH(hw);
+    ew32(EECD, *eecd);
+    E1000_WRITE_FLUSH();
     udelay(hw->eeprom.delay_usec);
 }
 
@@ -4645,16 +4591,14 @@
  * hw - Struct containing variables accessed by shared code
  * eecd - EECD's current value
  *****************************************************************************/
-static void
-e1000_lower_ee_clk(struct e1000_hw *hw,
-                   u32 *eecd)
+static void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd)
 {
     /* Lower the clock input to the EEPROM (by clearing the SK bit), and then
      * wait 50 microseconds.
      */
     *eecd = *eecd & ~E1000_EECD_SK;
-    E1000_WRITE_REG(hw, EECD, *eecd);
-    E1000_WRITE_FLUSH(hw);
+    ew32(EECD, *eecd);
+    E1000_WRITE_FLUSH();
     udelay(hw->eeprom.delay_usec);
 }
 
@@ -4665,10 +4609,7 @@
  * data - data to send to the EEPROM
  * count - number of bits to shift out
  *****************************************************************************/
-static void
-e1000_shift_out_ee_bits(struct e1000_hw *hw,
-                        u16 data,
-                        u16 count)
+static void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data, u16 count)
 {
     struct e1000_eeprom_info *eeprom = &hw->eeprom;
     u32 eecd;
@@ -4679,7 +4620,7 @@
      * In order to do this, "data" must be broken down into bits.
      */
     mask = 0x01 << (count - 1);
-    eecd = E1000_READ_REG(hw, EECD);
+    eecd = er32(EECD);
     if (eeprom->type == e1000_eeprom_microwire) {
         eecd &= ~E1000_EECD_DO;
     } else if (eeprom->type == e1000_eeprom_spi) {
@@ -4696,8 +4637,8 @@
         if (data & mask)
             eecd |= E1000_EECD_DI;
 
-        E1000_WRITE_REG(hw, EECD, eecd);
-        E1000_WRITE_FLUSH(hw);
+        ew32(EECD, eecd);
+        E1000_WRITE_FLUSH();
 
         udelay(eeprom->delay_usec);
 
@@ -4710,7 +4651,7 @@
 
     /* We leave the "DI" bit set to "0" when we leave this routine. */
     eecd &= ~E1000_EECD_DI;
-    E1000_WRITE_REG(hw, EECD, eecd);
+    ew32(EECD, eecd);
 }
 
 /******************************************************************************
@@ -4718,9 +4659,7 @@
  *
  * hw - Struct containing variables accessed by shared code
  *****************************************************************************/
-static u16
-e1000_shift_in_ee_bits(struct e1000_hw *hw,
-                       u16 count)
+static u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count)
 {
     u32 eecd;
     u32 i;
@@ -4733,7 +4672,7 @@
      * always be clear.
      */
 
-    eecd = E1000_READ_REG(hw, EECD);
+    eecd = er32(EECD);
 
     eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
     data = 0;
@@ -4742,7 +4681,7 @@
         data = data << 1;
         e1000_raise_ee_clk(hw, &eecd);
 
-        eecd = E1000_READ_REG(hw, EECD);
+        eecd = er32(EECD);
 
         eecd &= ~(E1000_EECD_DI);
         if (eecd & E1000_EECD_DO)
@@ -4762,8 +4701,7 @@
  * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This
  * function should be called before issuing a command to the EEPROM.
  *****************************************************************************/
-static s32
-e1000_acquire_eeprom(struct e1000_hw *hw)
+static s32 e1000_acquire_eeprom(struct e1000_hw *hw)
 {
     struct e1000_eeprom_info *eeprom = &hw->eeprom;
     u32 eecd, i=0;
@@ -4772,23 +4710,23 @@
 
     if (e1000_swfw_sync_acquire(hw, E1000_SWFW_EEP_SM))
         return -E1000_ERR_SWFW_SYNC;
-    eecd = E1000_READ_REG(hw, EECD);
+    eecd = er32(EECD);
 
     if (hw->mac_type != e1000_82573) {
         /* Request EEPROM Access */
         if (hw->mac_type > e1000_82544) {
             eecd |= E1000_EECD_REQ;
-            E1000_WRITE_REG(hw, EECD, eecd);
-            eecd = E1000_READ_REG(hw, EECD);
+            ew32(EECD, eecd);
+            eecd = er32(EECD);
             while ((!(eecd & E1000_EECD_GNT)) &&
                   (i < E1000_EEPROM_GRANT_ATTEMPTS)) {
                 i++;
                 udelay(5);
-                eecd = E1000_READ_REG(hw, EECD);
+                eecd = er32(EECD);
             }
             if (!(eecd & E1000_EECD_GNT)) {
                 eecd &= ~E1000_EECD_REQ;
-                E1000_WRITE_REG(hw, EECD, eecd);
+                ew32(EECD, eecd);
                 DEBUGOUT("Could not acquire EEPROM grant\n");
                 e1000_swfw_sync_release(hw, E1000_SWFW_EEP_SM);
                 return -E1000_ERR_EEPROM;
@@ -4801,15 +4739,15 @@
     if (eeprom->type == e1000_eeprom_microwire) {
         /* Clear SK and DI */
         eecd &= ~(E1000_EECD_DI | E1000_EECD_SK);
-        E1000_WRITE_REG(hw, EECD, eecd);
+        ew32(EECD, eecd);
 
         /* Set CS */
         eecd |= E1000_EECD_CS;
-        E1000_WRITE_REG(hw, EECD, eecd);
+        ew32(EECD, eecd);
     } else if (eeprom->type == e1000_eeprom_spi) {
         /* Clear SK and CS */
         eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
-        E1000_WRITE_REG(hw, EECD, eecd);
+        ew32(EECD, eecd);
         udelay(1);
     }
 
@@ -4821,46 +4759,45 @@
  *
  * hw - Struct containing variables accessed by shared code
  *****************************************************************************/
-static void
-e1000_standby_eeprom(struct e1000_hw *hw)
+static void e1000_standby_eeprom(struct e1000_hw *hw)
 {
     struct e1000_eeprom_info *eeprom = &hw->eeprom;
     u32 eecd;
 
-    eecd = E1000_READ_REG(hw, EECD);
+    eecd = er32(EECD);
 
     if (eeprom->type == e1000_eeprom_microwire) {
         eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
-        E1000_WRITE_REG(hw, EECD, eecd);
-        E1000_WRITE_FLUSH(hw);
+        ew32(EECD, eecd);
+        E1000_WRITE_FLUSH();
         udelay(eeprom->delay_usec);
 
         /* Clock high */
         eecd |= E1000_EECD_SK;
-        E1000_WRITE_REG(hw, EECD, eecd);
-        E1000_WRITE_FLUSH(hw);
+        ew32(EECD, eecd);
+        E1000_WRITE_FLUSH();
         udelay(eeprom->delay_usec);
 
         /* Select EEPROM */
         eecd |= E1000_EECD_CS;
-        E1000_WRITE_REG(hw, EECD, eecd);
-        E1000_WRITE_FLUSH(hw);
+        ew32(EECD, eecd);
+        E1000_WRITE_FLUSH();
         udelay(eeprom->delay_usec);
 
         /* Clock low */
         eecd &= ~E1000_EECD_SK;
-        E1000_WRITE_REG(hw, EECD, eecd);
-        E1000_WRITE_FLUSH(hw);
+        ew32(EECD, eecd);
+        E1000_WRITE_FLUSH();
         udelay(eeprom->delay_usec);
     } else if (eeprom->type == e1000_eeprom_spi) {
         /* Toggle CS to flush commands */
         eecd |= E1000_EECD_CS;
-        E1000_WRITE_REG(hw, EECD, eecd);
-        E1000_WRITE_FLUSH(hw);
+        ew32(EECD, eecd);
+        E1000_WRITE_FLUSH();
         udelay(eeprom->delay_usec);
         eecd &= ~E1000_EECD_CS;
-        E1000_WRITE_REG(hw, EECD, eecd);
-        E1000_WRITE_FLUSH(hw);
+        ew32(EECD, eecd);
+        E1000_WRITE_FLUSH();
         udelay(eeprom->delay_usec);
     }
 }
@@ -4870,20 +4807,19 @@
  *
  * hw - Struct containing variables accessed by shared code
  *****************************************************************************/
-static void
-e1000_release_eeprom(struct e1000_hw *hw)
+static void e1000_release_eeprom(struct e1000_hw *hw)
 {
     u32 eecd;
 
     DEBUGFUNC("e1000_release_eeprom");
 
-    eecd = E1000_READ_REG(hw, EECD);
+    eecd = er32(EECD);
 
     if (hw->eeprom.type == e1000_eeprom_spi) {
         eecd |= E1000_EECD_CS;  /* Pull CS high */
         eecd &= ~E1000_EECD_SK; /* Lower SCK */
 
-        E1000_WRITE_REG(hw, EECD, eecd);
+        ew32(EECD, eecd);
 
         udelay(hw->eeprom.delay_usec);
     } else if (hw->eeprom.type == e1000_eeprom_microwire) {
@@ -4892,25 +4828,25 @@
         /* CS on Microwire is active-high */
         eecd &= ~(E1000_EECD_CS | E1000_EECD_DI);
 
-        E1000_WRITE_REG(hw, EECD, eecd);
+        ew32(EECD, eecd);
 
         /* Rising edge of clock */
         eecd |= E1000_EECD_SK;
-        E1000_WRITE_REG(hw, EECD, eecd);
-        E1000_WRITE_FLUSH(hw);
+        ew32(EECD, eecd);
+        E1000_WRITE_FLUSH();
         udelay(hw->eeprom.delay_usec);
 
         /* Falling edge of clock */
         eecd &= ~E1000_EECD_SK;
-        E1000_WRITE_REG(hw, EECD, eecd);
-        E1000_WRITE_FLUSH(hw);
+        ew32(EECD, eecd);
+        E1000_WRITE_FLUSH();
         udelay(hw->eeprom.delay_usec);
     }
 
     /* Stop requesting EEPROM access */
     if (hw->mac_type > e1000_82544) {
         eecd &= ~E1000_EECD_REQ;
-        E1000_WRITE_REG(hw, EECD, eecd);
+        ew32(EECD, eecd);
     }
 
     e1000_swfw_sync_release(hw, E1000_SWFW_EEP_SM);
@@ -4921,8 +4857,7 @@
  *
  * hw - Struct containing variables accessed by shared code
  *****************************************************************************/
-static s32
-e1000_spi_eeprom_ready(struct e1000_hw *hw)
+static s32 e1000_spi_eeprom_ready(struct e1000_hw *hw)
 {
     u16 retry_count = 0;
     u8 spi_stat_reg;
@@ -4967,11 +4902,7 @@
  * data - word read from the EEPROM
  * words - number of words to read
  *****************************************************************************/
-s32
-e1000_read_eeprom(struct e1000_hw *hw,
-                  u16 offset,
-                  u16 words,
-                  u16 *data)
+s32 e1000_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
 {
     struct e1000_eeprom_info *eeprom = &hw->eeprom;
     u32 i = 0;
@@ -5068,11 +4999,8 @@
  * data - word read from the EEPROM
  * words - number of words to read
  *****************************************************************************/
-static s32
-e1000_read_eeprom_eerd(struct e1000_hw *hw,
-                  u16 offset,
-                  u16 words,
-                  u16 *data)
+static s32 e1000_read_eeprom_eerd(struct e1000_hw *hw, u16 offset, u16 words,
+				  u16 *data)
 {
     u32 i, eerd = 0;
     s32 error = 0;
@@ -5081,13 +5009,13 @@
         eerd = ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) +
                          E1000_EEPROM_RW_REG_START;
 
-        E1000_WRITE_REG(hw, EERD, eerd);
+        ew32(EERD, eerd);
         error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_READ);
 
         if (error) {
             break;
         }
-        data[i] = (E1000_READ_REG(hw, EERD) >> E1000_EEPROM_RW_REG_DATA);
+        data[i] = (er32(EERD) >> E1000_EEPROM_RW_REG_DATA);
 
     }
 
@@ -5102,11 +5030,8 @@
  * data - word read from the EEPROM
  * words - number of words to read
  *****************************************************************************/
-static s32
-e1000_write_eeprom_eewr(struct e1000_hw *hw,
-                   u16 offset,
-                   u16 words,
-                   u16 *data)
+static s32 e1000_write_eeprom_eewr(struct e1000_hw *hw, u16 offset, u16 words,
+				   u16 *data)
 {
     u32    register_value = 0;
     u32    i              = 0;
@@ -5125,7 +5050,7 @@
             break;
         }
 
-        E1000_WRITE_REG(hw, EEWR, register_value);
+        ew32(EEWR, register_value);
 
         error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_WRITE);
 
@@ -5143,8 +5068,7 @@
  *
  * hw - Struct containing variables accessed by shared code
  *****************************************************************************/
-static s32
-e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd)
+static s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd)
 {
     u32 attempts = 100000;
     u32 i, reg = 0;
@@ -5152,9 +5076,9 @@
 
     for (i = 0; i < attempts; i++) {
         if (eerd == E1000_EEPROM_POLL_READ)
-            reg = E1000_READ_REG(hw, EERD);
+            reg = er32(EERD);
         else
-            reg = E1000_READ_REG(hw, EEWR);
+            reg = er32(EEWR);
 
         if (reg & E1000_EEPROM_RW_REG_DONE) {
             done = E1000_SUCCESS;
@@ -5171,8 +5095,7 @@
 *
 * hw - Struct containing variables accessed by shared code
 ****************************************************************************/
-static bool
-e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw)
+static bool e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw)
 {
     u32 eecd = 0;
 
@@ -5182,7 +5105,7 @@
         return false;
 
     if (hw->mac_type == e1000_82573) {
-        eecd = E1000_READ_REG(hw, EECD);
+        eecd = er32(EECD);
 
         /* Isolate bits 15 & 16 */
         eecd = ((eecd >> 15) & 0x03);
@@ -5204,8 +5127,7 @@
  * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is
  * valid.
  *****************************************************************************/
-s32
-e1000_validate_eeprom_checksum(struct e1000_hw *hw)
+s32 e1000_validate_eeprom_checksum(struct e1000_hw *hw)
 {
     u16 checksum = 0;
     u16 i, eeprom_data;
@@ -5252,7 +5174,7 @@
         checksum += eeprom_data;
     }
 
-    if (checksum == (u16) EEPROM_SUM)
+    if (checksum == (u16)EEPROM_SUM)
         return E1000_SUCCESS;
     else {
         DEBUGOUT("EEPROM Checksum Invalid\n");
@@ -5268,8 +5190,7 @@
  * Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA.
  * Writes the difference to word offset 63 of the EEPROM.
  *****************************************************************************/
-s32
-e1000_update_eeprom_checksum(struct e1000_hw *hw)
+s32 e1000_update_eeprom_checksum(struct e1000_hw *hw)
 {
     u32 ctrl_ext;
     u16 checksum = 0;
@@ -5284,7 +5205,7 @@
         }
         checksum += eeprom_data;
     }
-    checksum = (u16) EEPROM_SUM - checksum;
+    checksum = (u16)EEPROM_SUM - checksum;
     if (e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) {
         DEBUGOUT("EEPROM Write Error\n");
         return -E1000_ERR_EEPROM;
@@ -5294,9 +5215,9 @@
         e1000_commit_shadow_ram(hw);
         /* Reload the EEPROM, or else modifications will not appear
          * until after next adapter reset. */
-        ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+        ctrl_ext = er32(CTRL_EXT);
         ctrl_ext |= E1000_CTRL_EXT_EE_RST;
-        E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+        ew32(CTRL_EXT, ctrl_ext);
         msleep(10);
     }
     return E1000_SUCCESS;
@@ -5313,11 +5234,7 @@
  * If e1000_update_eeprom_checksum is not called after this function, the
  * EEPROM will most likely contain an invalid checksum.
  *****************************************************************************/
-s32
-e1000_write_eeprom(struct e1000_hw *hw,
-                   u16 offset,
-                   u16 words,
-                   u16 *data)
+s32 e1000_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
 {
     struct e1000_eeprom_info *eeprom = &hw->eeprom;
     s32 status = 0;
@@ -5370,11 +5287,8 @@
  * data - pointer to array of 8 bit words to be written to the EEPROM
  *
  *****************************************************************************/
-static s32
-e1000_write_eeprom_spi(struct e1000_hw *hw,
-                       u16 offset,
-                       u16 words,
-                       u16 *data)
+static s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset, u16 words,
+				  u16 *data)
 {
     struct e1000_eeprom_info *eeprom = &hw->eeprom;
     u16 widx = 0;
@@ -5436,11 +5350,8 @@
  * data - pointer to array of 16 bit words to be written to the EEPROM
  *
  *****************************************************************************/
-static s32
-e1000_write_eeprom_microwire(struct e1000_hw *hw,
-                             u16 offset,
-                             u16 words,
-                             u16 *data)
+static s32 e1000_write_eeprom_microwire(struct e1000_hw *hw, u16 offset,
+					u16 words, u16 *data)
 {
     struct e1000_eeprom_info *eeprom = &hw->eeprom;
     u32 eecd;
@@ -5484,7 +5395,7 @@
          * If DO does not go high in 10 milliseconds, then error out.
          */
         for (i = 0; i < 200; i++) {
-            eecd = E1000_READ_REG(hw, EECD);
+            eecd = er32(EECD);
             if (eecd & E1000_EECD_DO) break;
             udelay(50);
         }
@@ -5523,8 +5434,7 @@
  * data - word read from the EEPROM
  * words - number of words to read
  *****************************************************************************/
-static s32
-e1000_commit_shadow_ram(struct e1000_hw *hw)
+static s32 e1000_commit_shadow_ram(struct e1000_hw *hw)
 {
     u32 attempts = 100000;
     u32 eecd = 0;
@@ -5539,9 +5449,9 @@
 
     if (hw->mac_type == e1000_82573) {
         /* The flop register will be used to determine if flash type is STM */
-        flop = E1000_READ_REG(hw, FLOP);
+        flop = er32(FLOP);
         for (i=0; i < attempts; i++) {
-            eecd = E1000_READ_REG(hw, EECD);
+            eecd = er32(EECD);
             if ((eecd & E1000_EECD_FLUPD) == 0) {
                 break;
             }
@@ -5554,14 +5464,14 @@
 
         /* If STM opcode located in bits 15:8 of flop, reset firmware */
         if ((flop & 0xFF00) == E1000_STM_OPCODE) {
-            E1000_WRITE_REG(hw, HICR, E1000_HICR_FW_RESET);
+            ew32(HICR, E1000_HICR_FW_RESET);
         }
 
         /* Perform the flash update */
-        E1000_WRITE_REG(hw, EECD, eecd | E1000_EECD_FLUPD);
+        ew32(EECD, eecd | E1000_EECD_FLUPD);
 
         for (i=0; i < attempts; i++) {
-            eecd = E1000_READ_REG(hw, EECD);
+            eecd = er32(EECD);
             if ((eecd & E1000_EECD_FLUPD) == 0) {
                 break;
             }
@@ -5577,7 +5487,7 @@
         /* We're writing to the opposite bank so if we're on bank 1,
          * write to bank 0 etc.  We also need to erase the segment that
          * is going to be written */
-        if (!(E1000_READ_REG(hw, EECD) & E1000_EECD_SEC1VAL)) {
+        if (!(er32(EECD) & E1000_EECD_SEC1VAL)) {
             new_bank_offset = hw->flash_bank_size * 2;
             old_bank_offset = 0;
             e1000_erase_ich8_4k_segment(hw, 1);
@@ -5687,8 +5597,7 @@
  *
  * hw - Struct containing variables accessed by shared code
  *****************************************************************************/
-s32
-e1000_read_mac_addr(struct e1000_hw * hw)
+s32 e1000_read_mac_addr(struct e1000_hw *hw)
 {
     u16 offset;
     u16 eeprom_data, i;
@@ -5701,8 +5610,8 @@
             DEBUGOUT("EEPROM Read Error\n");
             return -E1000_ERR_EEPROM;
         }
-        hw->perm_mac_addr[i] = (u8) (eeprom_data & 0x00FF);
-        hw->perm_mac_addr[i+1] = (u8) (eeprom_data >> 8);
+        hw->perm_mac_addr[i] = (u8)(eeprom_data & 0x00FF);
+        hw->perm_mac_addr[i+1] = (u8)(eeprom_data >> 8);
     }
 
     switch (hw->mac_type) {
@@ -5712,7 +5621,7 @@
     case e1000_82546_rev_3:
     case e1000_82571:
     case e1000_80003es2lan:
-        if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
+        if (er32(STATUS) & E1000_STATUS_FUNC_1)
             hw->perm_mac_addr[5] ^= 0x01;
         break;
     }
@@ -5731,8 +5640,7 @@
  * of the receive addresss registers. Clears the multicast table. Assumes
  * the receiver is in reset when the routine is called.
  *****************************************************************************/
-static void
-e1000_init_rx_addrs(struct e1000_hw *hw)
+static void e1000_init_rx_addrs(struct e1000_hw *hw)
 {
     u32 i;
     u32 rar_num;
@@ -5758,9 +5666,9 @@
     DEBUGOUT("Clearing RAR[1-15]\n");
     for (i = 1; i < rar_num; i++) {
         E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
-        E1000_WRITE_FLUSH(hw);
+        E1000_WRITE_FLUSH();
         E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
-        E1000_WRITE_FLUSH(hw);
+        E1000_WRITE_FLUSH();
     }
 }
 
@@ -5770,9 +5678,7 @@
  * hw - Struct containing variables accessed by shared code
  * mc_addr - the multicast address to hash
  *****************************************************************************/
-u32
-e1000_hash_mc_addr(struct e1000_hw *hw,
-                   u8 *mc_addr)
+u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
 {
     u32 hash_value = 0;
 
@@ -5787,37 +5693,37 @@
     case 0:
         if (hw->mac_type == e1000_ich8lan) {
             /* [47:38] i.e. 0x158 for above example address */
-            hash_value = ((mc_addr[4] >> 6) | (((u16) mc_addr[5]) << 2));
+            hash_value = ((mc_addr[4] >> 6) | (((u16)mc_addr[5]) << 2));
         } else {
             /* [47:36] i.e. 0x563 for above example address */
-            hash_value = ((mc_addr[4] >> 4) | (((u16) mc_addr[5]) << 4));
+            hash_value = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4));
         }
         break;
     case 1:
         if (hw->mac_type == e1000_ich8lan) {
             /* [46:37] i.e. 0x2B1 for above example address */
-            hash_value = ((mc_addr[4] >> 5) | (((u16) mc_addr[5]) << 3));
+            hash_value = ((mc_addr[4] >> 5) | (((u16)mc_addr[5]) << 3));
         } else {
             /* [46:35] i.e. 0xAC6 for above example address */
-            hash_value = ((mc_addr[4] >> 3) | (((u16) mc_addr[5]) << 5));
+            hash_value = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5));
         }
         break;
     case 2:
         if (hw->mac_type == e1000_ich8lan) {
             /*[45:36] i.e. 0x163 for above example address */
-            hash_value = ((mc_addr[4] >> 4) | (((u16) mc_addr[5]) << 4));
+            hash_value = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4));
         } else {
             /* [45:34] i.e. 0x5D8 for above example address */
-            hash_value = ((mc_addr[4] >> 2) | (((u16) mc_addr[5]) << 6));
+            hash_value = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6));
         }
         break;
     case 3:
         if (hw->mac_type == e1000_ich8lan) {
             /* [43:34] i.e. 0x18D for above example address */
-            hash_value = ((mc_addr[4] >> 2) | (((u16) mc_addr[5]) << 6));
+            hash_value = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6));
         } else {
             /* [43:32] i.e. 0x634 for above example address */
-            hash_value = ((mc_addr[4]) | (((u16) mc_addr[5]) << 8));
+            hash_value = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8));
         }
         break;
     }
@@ -5835,9 +5741,7 @@
  * hw - Struct containing variables accessed by shared code
  * hash_value - Multicast address hash value
  *****************************************************************************/
-void
-e1000_mta_set(struct e1000_hw *hw,
-              u32 hash_value)
+void e1000_mta_set(struct e1000_hw *hw, u32 hash_value)
 {
     u32 hash_bit, hash_reg;
     u32 mta;
@@ -5868,12 +5772,12 @@
     if ((hw->mac_type == e1000_82544) && ((hash_reg & 0x1) == 1)) {
         temp = E1000_READ_REG_ARRAY(hw, MTA, (hash_reg - 1));
         E1000_WRITE_REG_ARRAY(hw, MTA, hash_reg, mta);
-        E1000_WRITE_FLUSH(hw);
+        E1000_WRITE_FLUSH();
         E1000_WRITE_REG_ARRAY(hw, MTA, (hash_reg - 1), temp);
-        E1000_WRITE_FLUSH(hw);
+        E1000_WRITE_FLUSH();
     } else {
         E1000_WRITE_REG_ARRAY(hw, MTA, hash_reg, mta);
-        E1000_WRITE_FLUSH(hw);
+        E1000_WRITE_FLUSH();
     }
 }
 
@@ -5884,20 +5788,16 @@
  * addr - Address to put into receive address register
  * index - Receive address register to write
  *****************************************************************************/
-void
-e1000_rar_set(struct e1000_hw *hw,
-              u8 *addr,
-              u32 index)
+void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index)
 {
     u32 rar_low, rar_high;
 
     /* HW expects these in little endian so we reverse the byte order
      * from network order (big endian) to little endian
      */
-    rar_low = ((u32) addr[0] |
-               ((u32) addr[1] << 8) |
-               ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
-    rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
+    rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) |
+               ((u32)addr[2] << 16) | ((u32)addr[3] << 24));
+    rar_high = ((u32)addr[4] | ((u32)addr[5] << 8));
 
     /* Disable Rx and flush all Rx frames before enabling RSS to avoid Rx
      * unit hang.
@@ -5930,9 +5830,9 @@
     }
 
     E1000_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low);
-    E1000_WRITE_FLUSH(hw);
+    E1000_WRITE_FLUSH();
     E1000_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high);
-    E1000_WRITE_FLUSH(hw);
+    E1000_WRITE_FLUSH();
 }
 
 /******************************************************************************
@@ -5942,10 +5842,7 @@
  * offset - Offset in VLAN filer table to write
  * value - Value to write into VLAN filter table
  *****************************************************************************/
-void
-e1000_write_vfta(struct e1000_hw *hw,
-                 u32 offset,
-                 u32 value)
+void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
 {
     u32 temp;
 
@@ -5955,12 +5852,12 @@
     if ((hw->mac_type == e1000_82544) && ((offset & 0x1) == 1)) {
         temp = E1000_READ_REG_ARRAY(hw, VFTA, (offset - 1));
         E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value);
-        E1000_WRITE_FLUSH(hw);
+        E1000_WRITE_FLUSH();
         E1000_WRITE_REG_ARRAY(hw, VFTA, (offset - 1), temp);
-        E1000_WRITE_FLUSH(hw);
+        E1000_WRITE_FLUSH();
     } else {
         E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value);
-        E1000_WRITE_FLUSH(hw);
+        E1000_WRITE_FLUSH();
     }
 }
 
@@ -5969,8 +5866,7 @@
  *
  * hw - Struct containing variables accessed by shared code
  *****************************************************************************/
-static void
-e1000_clear_vfta(struct e1000_hw *hw)
+static void e1000_clear_vfta(struct e1000_hw *hw)
 {
     u32 offset;
     u32 vfta_value = 0;
@@ -5999,12 +5895,11 @@
          * manageability unit */
         vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0;
         E1000_WRITE_REG_ARRAY(hw, VFTA, offset, vfta_value);
-        E1000_WRITE_FLUSH(hw);
+        E1000_WRITE_FLUSH();
     }
 }
 
-static s32
-e1000_id_led_init(struct e1000_hw * hw)
+static s32 e1000_id_led_init(struct e1000_hw *hw)
 {
     u32 ledctl;
     const u32 ledctl_mask = 0x000000FF;
@@ -6020,7 +5915,7 @@
         return E1000_SUCCESS;
     }
 
-    ledctl = E1000_READ_REG(hw, LEDCTL);
+    ledctl = er32(LEDCTL);
     hw->ledctl_default = ledctl;
     hw->ledctl_mode1 = hw->ledctl_default;
     hw->ledctl_mode2 = hw->ledctl_default;
@@ -6086,8 +5981,7 @@
  *
  * hw - Struct containing variables accessed by shared code
  *****************************************************************************/
-s32
-e1000_setup_led(struct e1000_hw *hw)
+s32 e1000_setup_led(struct e1000_hw *hw)
 {
     u32 ledctl;
     s32 ret_val = E1000_SUCCESS;
@@ -6118,7 +6012,7 @@
         /* Fall Through */
     default:
         if (hw->media_type == e1000_media_type_fiber) {
-            ledctl = E1000_READ_REG(hw, LEDCTL);
+            ledctl = er32(LEDCTL);
             /* Save current LEDCTL settings */
             hw->ledctl_default = ledctl;
             /* Turn off LED0 */
@@ -6127,9 +6021,9 @@
                         E1000_LEDCTL_LED0_MODE_MASK);
             ledctl |= (E1000_LEDCTL_MODE_LED_OFF <<
                        E1000_LEDCTL_LED0_MODE_SHIFT);
-            E1000_WRITE_REG(hw, LEDCTL, ledctl);
+            ew32(LEDCTL, ledctl);
         } else if (hw->media_type == e1000_media_type_copper)
-            E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1);
+            ew32(LEDCTL, hw->ledctl_mode1);
         break;
     }
 
@@ -6145,8 +6039,7 @@
  *
  * hw - Struct containing variables accessed by shared code
  *****************************************************************************/
-s32
-e1000_blink_led_start(struct e1000_hw *hw)
+s32 e1000_blink_led_start(struct e1000_hw *hw)
 {
     s16  i;
     u32 ledctl_blink = 0;
@@ -6170,7 +6063,7 @@
                 ledctl_blink |= (E1000_LEDCTL_LED0_BLINK << (i * 8));
     }
 
-    E1000_WRITE_REG(hw, LEDCTL, ledctl_blink);
+    ew32(LEDCTL, ledctl_blink);
 
     return E1000_SUCCESS;
 }
@@ -6180,8 +6073,7 @@
  *
  * hw - Struct containing variables accessed by shared code
  *****************************************************************************/
-s32
-e1000_cleanup_led(struct e1000_hw *hw)
+s32 e1000_cleanup_led(struct e1000_hw *hw)
 {
     s32 ret_val = E1000_SUCCESS;
 
@@ -6210,7 +6102,7 @@
             break;
         }
         /* Restore LEDCTL settings */
-        E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_default);
+        ew32(LEDCTL, hw->ledctl_default);
         break;
     }
 
@@ -6222,10 +6114,9 @@
  *
  * hw - Struct containing variables accessed by shared code
  *****************************************************************************/
-s32
-e1000_led_on(struct e1000_hw *hw)
+s32 e1000_led_on(struct e1000_hw *hw)
 {
-    u32 ctrl = E1000_READ_REG(hw, CTRL);
+    u32 ctrl = er32(CTRL);
 
     DEBUGFUNC("e1000_led_on");
 
@@ -6257,13 +6148,13 @@
             e1000_write_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED,
                  (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_ON));
         } else if (hw->media_type == e1000_media_type_copper) {
-            E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode2);
+            ew32(LEDCTL, hw->ledctl_mode2);
             return E1000_SUCCESS;
         }
         break;
     }
 
-    E1000_WRITE_REG(hw, CTRL, ctrl);
+    ew32(CTRL, ctrl);
 
     return E1000_SUCCESS;
 }
@@ -6273,10 +6164,9 @@
  *
  * hw - Struct containing variables accessed by shared code
  *****************************************************************************/
-s32
-e1000_led_off(struct e1000_hw *hw)
+s32 e1000_led_off(struct e1000_hw *hw)
 {
-    u32 ctrl = E1000_READ_REG(hw, CTRL);
+    u32 ctrl = er32(CTRL);
 
     DEBUGFUNC("e1000_led_off");
 
@@ -6308,13 +6198,13 @@
             e1000_write_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED,
                  (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_OFF));
         } else if (hw->media_type == e1000_media_type_copper) {
-            E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1);
+            ew32(LEDCTL, hw->ledctl_mode1);
             return E1000_SUCCESS;
         }
         break;
     }
 
-    E1000_WRITE_REG(hw, CTRL, ctrl);
+    ew32(CTRL, ctrl);
 
     return E1000_SUCCESS;
 }
@@ -6324,98 +6214,97 @@
  *
  * hw - Struct containing variables accessed by shared code
  *****************************************************************************/
-static void
-e1000_clear_hw_cntrs(struct e1000_hw *hw)
+static void e1000_clear_hw_cntrs(struct e1000_hw *hw)
 {
     volatile u32 temp;
 
-    temp = E1000_READ_REG(hw, CRCERRS);
-    temp = E1000_READ_REG(hw, SYMERRS);
-    temp = E1000_READ_REG(hw, MPC);
-    temp = E1000_READ_REG(hw, SCC);
-    temp = E1000_READ_REG(hw, ECOL);
-    temp = E1000_READ_REG(hw, MCC);
-    temp = E1000_READ_REG(hw, LATECOL);
-    temp = E1000_READ_REG(hw, COLC);
-    temp = E1000_READ_REG(hw, DC);
-    temp = E1000_READ_REG(hw, SEC);
-    temp = E1000_READ_REG(hw, RLEC);
-    temp = E1000_READ_REG(hw, XONRXC);
-    temp = E1000_READ_REG(hw, XONTXC);
-    temp = E1000_READ_REG(hw, XOFFRXC);
-    temp = E1000_READ_REG(hw, XOFFTXC);
-    temp = E1000_READ_REG(hw, FCRUC);
+    temp = er32(CRCERRS);
+    temp = er32(SYMERRS);
+    temp = er32(MPC);
+    temp = er32(SCC);
+    temp = er32(ECOL);
+    temp = er32(MCC);
+    temp = er32(LATECOL);
+    temp = er32(COLC);
+    temp = er32(DC);
+    temp = er32(SEC);
+    temp = er32(RLEC);
+    temp = er32(XONRXC);
+    temp = er32(XONTXC);
+    temp = er32(XOFFRXC);
+    temp = er32(XOFFTXC);
+    temp = er32(FCRUC);
 
     if (hw->mac_type != e1000_ich8lan) {
-    temp = E1000_READ_REG(hw, PRC64);
-    temp = E1000_READ_REG(hw, PRC127);
-    temp = E1000_READ_REG(hw, PRC255);
-    temp = E1000_READ_REG(hw, PRC511);
-    temp = E1000_READ_REG(hw, PRC1023);
-    temp = E1000_READ_REG(hw, PRC1522);
+    temp = er32(PRC64);
+    temp = er32(PRC127);
+    temp = er32(PRC255);
+    temp = er32(PRC511);
+    temp = er32(PRC1023);
+    temp = er32(PRC1522);
     }
 
-    temp = E1000_READ_REG(hw, GPRC);
-    temp = E1000_READ_REG(hw, BPRC);
-    temp = E1000_READ_REG(hw, MPRC);
-    temp = E1000_READ_REG(hw, GPTC);
-    temp = E1000_READ_REG(hw, GORCL);
-    temp = E1000_READ_REG(hw, GORCH);
-    temp = E1000_READ_REG(hw, GOTCL);
-    temp = E1000_READ_REG(hw, GOTCH);
-    temp = E1000_READ_REG(hw, RNBC);
-    temp = E1000_READ_REG(hw, RUC);
-    temp = E1000_READ_REG(hw, RFC);
-    temp = E1000_READ_REG(hw, ROC);
-    temp = E1000_READ_REG(hw, RJC);
-    temp = E1000_READ_REG(hw, TORL);
-    temp = E1000_READ_REG(hw, TORH);
-    temp = E1000_READ_REG(hw, TOTL);
-    temp = E1000_READ_REG(hw, TOTH);
-    temp = E1000_READ_REG(hw, TPR);
-    temp = E1000_READ_REG(hw, TPT);
+    temp = er32(GPRC);
+    temp = er32(BPRC);
+    temp = er32(MPRC);
+    temp = er32(GPTC);
+    temp = er32(GORCL);
+    temp = er32(GORCH);
+    temp = er32(GOTCL);
+    temp = er32(GOTCH);
+    temp = er32(RNBC);
+    temp = er32(RUC);
+    temp = er32(RFC);
+    temp = er32(ROC);
+    temp = er32(RJC);
+    temp = er32(TORL);
+    temp = er32(TORH);
+    temp = er32(TOTL);
+    temp = er32(TOTH);
+    temp = er32(TPR);
+    temp = er32(TPT);
 
     if (hw->mac_type != e1000_ich8lan) {
-    temp = E1000_READ_REG(hw, PTC64);
-    temp = E1000_READ_REG(hw, PTC127);
-    temp = E1000_READ_REG(hw, PTC255);
-    temp = E1000_READ_REG(hw, PTC511);
-    temp = E1000_READ_REG(hw, PTC1023);
-    temp = E1000_READ_REG(hw, PTC1522);
+    temp = er32(PTC64);
+    temp = er32(PTC127);
+    temp = er32(PTC255);
+    temp = er32(PTC511);
+    temp = er32(PTC1023);
+    temp = er32(PTC1522);
     }
 
-    temp = E1000_READ_REG(hw, MPTC);
-    temp = E1000_READ_REG(hw, BPTC);
+    temp = er32(MPTC);
+    temp = er32(BPTC);
 
     if (hw->mac_type < e1000_82543) return;
 
-    temp = E1000_READ_REG(hw, ALGNERRC);
-    temp = E1000_READ_REG(hw, RXERRC);
-    temp = E1000_READ_REG(hw, TNCRS);
-    temp = E1000_READ_REG(hw, CEXTERR);
-    temp = E1000_READ_REG(hw, TSCTC);
-    temp = E1000_READ_REG(hw, TSCTFC);
+    temp = er32(ALGNERRC);
+    temp = er32(RXERRC);
+    temp = er32(TNCRS);
+    temp = er32(CEXTERR);
+    temp = er32(TSCTC);
+    temp = er32(TSCTFC);
 
     if (hw->mac_type <= e1000_82544) return;
 
-    temp = E1000_READ_REG(hw, MGTPRC);
-    temp = E1000_READ_REG(hw, MGTPDC);
-    temp = E1000_READ_REG(hw, MGTPTC);
+    temp = er32(MGTPRC);
+    temp = er32(MGTPDC);
+    temp = er32(MGTPTC);
 
     if (hw->mac_type <= e1000_82547_rev_2) return;
 
-    temp = E1000_READ_REG(hw, IAC);
-    temp = E1000_READ_REG(hw, ICRXOC);
+    temp = er32(IAC);
+    temp = er32(ICRXOC);
 
     if (hw->mac_type == e1000_ich8lan) return;
 
-    temp = E1000_READ_REG(hw, ICRXPTC);
-    temp = E1000_READ_REG(hw, ICRXATC);
-    temp = E1000_READ_REG(hw, ICTXPTC);
-    temp = E1000_READ_REG(hw, ICTXATC);
-    temp = E1000_READ_REG(hw, ICTXQEC);
-    temp = E1000_READ_REG(hw, ICTXQMTC);
-    temp = E1000_READ_REG(hw, ICRXDMTC);
+    temp = er32(ICRXPTC);
+    temp = er32(ICRXATC);
+    temp = er32(ICTXPTC);
+    temp = er32(ICTXATC);
+    temp = er32(ICTXQEC);
+    temp = er32(ICTXQMTC);
+    temp = er32(ICRXDMTC);
 }
 
 /******************************************************************************
@@ -6428,8 +6317,7 @@
  * current_ifs_val, ifs_min_val, ifs_max_val, ifs_step_size, and ifs_ratio
  * before calling this function.
  *****************************************************************************/
-void
-e1000_reset_adaptive(struct e1000_hw *hw)
+void e1000_reset_adaptive(struct e1000_hw *hw)
 {
     DEBUGFUNC("e1000_reset_adaptive");
 
@@ -6442,7 +6330,7 @@
             hw->ifs_ratio = IFS_RATIO;
         }
         hw->in_ifs_mode = false;
-        E1000_WRITE_REG(hw, AIT, 0);
+        ew32(AIT, 0);
     } else {
         DEBUGOUT("Not in Adaptive IFS mode!\n");
     }
@@ -6456,8 +6344,7 @@
  * tx_packets - Number of transmits since last callback
  * total_collisions - Number of collisions since last callback
  *****************************************************************************/
-void
-e1000_update_adaptive(struct e1000_hw *hw)
+void e1000_update_adaptive(struct e1000_hw *hw)
 {
     DEBUGFUNC("e1000_update_adaptive");
 
@@ -6470,14 +6357,14 @@
                         hw->current_ifs_val = hw->ifs_min_val;
                     else
                         hw->current_ifs_val += hw->ifs_step_size;
-                    E1000_WRITE_REG(hw, AIT, hw->current_ifs_val);
+                    ew32(AIT, hw->current_ifs_val);
                 }
             }
         } else {
             if (hw->in_ifs_mode && (hw->tx_packet_delta <= MIN_NUM_XMITS)) {
                 hw->current_ifs_val = 0;
                 hw->in_ifs_mode = false;
-                E1000_WRITE_REG(hw, AIT, 0);
+                ew32(AIT, 0);
             }
         }
     } else {
@@ -6492,11 +6379,8 @@
  * frame_len - The length of the frame in question
  * mac_addr - The Ethernet destination address of the frame in question
  *****************************************************************************/
-void
-e1000_tbi_adjust_stats(struct e1000_hw *hw,
-                       struct e1000_hw_stats *stats,
-                       u32 frame_len,
-                       u8 *mac_addr)
+void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats,
+			    u32 frame_len, u8 *mac_addr)
 {
     u64 carry_bit;
 
@@ -6527,7 +6411,7 @@
      * since the test for a multicast frame will test positive on
      * a broadcast frame.
      */
-    if ((mac_addr[0] == (u8) 0xff) && (mac_addr[1] == (u8) 0xff))
+    if ((mac_addr[0] == (u8)0xff) && (mac_addr[1] == (u8)0xff))
         /* Broadcast packet */
         stats->bprc++;
     else if (*mac_addr & 0x01)
@@ -6570,8 +6454,7 @@
  *
  * hw - Struct containing variables accessed by shared code
  *****************************************************************************/
-void
-e1000_get_bus_info(struct e1000_hw *hw)
+void e1000_get_bus_info(struct e1000_hw *hw)
 {
     s32 ret_val;
     u16 pci_ex_link_status;
@@ -6605,7 +6488,7 @@
         hw->bus_width = e1000_bus_width_pciex_1;
         break;
     default:
-        status = E1000_READ_REG(hw, STATUS);
+        status = er32(STATUS);
         hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
                        e1000_bus_type_pcix : e1000_bus_type_pci;
 
@@ -6645,10 +6528,7 @@
  * offset - offset to write to
  * value - value to write
  *****************************************************************************/
-static void
-e1000_write_reg_io(struct e1000_hw *hw,
-                   u32 offset,
-                   u32 value)
+static void e1000_write_reg_io(struct e1000_hw *hw, u32 offset, u32 value)
 {
     unsigned long io_addr = hw->io_base;
     unsigned long io_data = hw->io_base + 4;
@@ -6672,10 +6552,8 @@
  * register to the minimum and maximum range.
  * For IGP phy's, the function calculates the range by the AGC registers.
  *****************************************************************************/
-static s32
-e1000_get_cable_length(struct e1000_hw *hw,
-                       u16 *min_length,
-                       u16 *max_length)
+static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length,
+				  u16 *max_length)
 {
     s32 ret_val;
     u16 agc_value = 0;
@@ -6863,9 +6741,8 @@
  * return 0.  If the link speed is 1000 Mbps the polarity status is in the
  * IGP01E1000_PHY_PCS_INIT_REG.
  *****************************************************************************/
-static s32
-e1000_check_polarity(struct e1000_hw *hw,
-                     e1000_rev_polarity *polarity)
+static s32 e1000_check_polarity(struct e1000_hw *hw,
+				e1000_rev_polarity *polarity)
 {
     s32 ret_val;
     u16 phy_data;
@@ -6939,8 +6816,7 @@
  * Link Health register.  In IGP this bit is latched high, so the driver must
  * read it immediately after link is established.
  *****************************************************************************/
-static s32
-e1000_check_downshift(struct e1000_hw *hw)
+static s32 e1000_check_downshift(struct e1000_hw *hw)
 {
     s32 ret_val;
     u16 phy_data;
@@ -6985,9 +6861,7 @@
  *
  ****************************************************************************/
 
-static s32
-e1000_config_dsp_after_link_change(struct e1000_hw *hw,
-                                   bool link_up)
+static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw, bool link_up)
 {
     s32 ret_val;
     u16 phy_data, phy_saved_data, speed, duplex, i;
@@ -7173,8 +7047,7 @@
  *
  * hw - Struct containing variables accessed by shared code
  ****************************************************************************/
-static s32
-e1000_set_phy_mode(struct e1000_hw *hw)
+static s32 e1000_set_phy_mode(struct e1000_hw *hw)
 {
     s32 ret_val;
     u16 eeprom_data;
@@ -7218,9 +7091,7 @@
  *
  ****************************************************************************/
 
-static s32
-e1000_set_d3_lplu_state(struct e1000_hw *hw,
-                        bool active)
+static s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active)
 {
     u32 phy_ctrl = 0;
     s32 ret_val;
@@ -7242,7 +7113,7 @@
         /* MAC writes into PHY register based on the state transition
          * and start auto-negotiation. SW driver can overwrite the settings
          * in CSR PHY power control E1000_PHY_CTRL register. */
-        phy_ctrl = E1000_READ_REG(hw, PHY_CTRL);
+        phy_ctrl = er32(PHY_CTRL);
     } else {
         ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data);
         if (ret_val)
@@ -7259,7 +7130,7 @@
         } else {
             if (hw->mac_type == e1000_ich8lan) {
                 phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU;
-                E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl);
+                ew32(PHY_CTRL, phy_ctrl);
             } else {
                 phy_data &= ~IGP02E1000_PM_D3_LPLU;
                 ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
@@ -7310,7 +7181,7 @@
         } else {
             if (hw->mac_type == e1000_ich8lan) {
                 phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU;
-                E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl);
+                ew32(PHY_CTRL, phy_ctrl);
             } else {
                 phy_data |= IGP02E1000_PM_D3_LPLU;
                 ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
@@ -7348,9 +7219,7 @@
  *
  ****************************************************************************/
 
-static s32
-e1000_set_d0_lplu_state(struct e1000_hw *hw,
-                        bool active)
+static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active)
 {
     u32 phy_ctrl = 0;
     s32 ret_val;
@@ -7361,7 +7230,7 @@
         return E1000_SUCCESS;
 
     if (hw->mac_type == e1000_ich8lan) {
-        phy_ctrl = E1000_READ_REG(hw, PHY_CTRL);
+        phy_ctrl = er32(PHY_CTRL);
     } else {
         ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data);
         if (ret_val)
@@ -7371,7 +7240,7 @@
     if (!active) {
         if (hw->mac_type == e1000_ich8lan) {
             phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU;
-            E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl);
+            ew32(PHY_CTRL, phy_ctrl);
         } else {
             phy_data &= ~IGP02E1000_PM_D0_LPLU;
             ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data);
@@ -7412,7 +7281,7 @@
 
         if (hw->mac_type == e1000_ich8lan) {
             phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU;
-            E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl);
+            ew32(PHY_CTRL, phy_ctrl);
         } else {
             phy_data |= IGP02E1000_PM_D0_LPLU;
             ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data);
@@ -7439,8 +7308,7 @@
  *
  * hw - Struct containing variables accessed by shared code
  *****************************************************************************/
-static s32
-e1000_set_vco_speed(struct e1000_hw *hw)
+static s32 e1000_set_vco_speed(struct e1000_hw *hw)
 {
     s32  ret_val;
     u16 default_page = 0;
@@ -7503,8 +7371,7 @@
  *
  * returns: - E1000_SUCCESS .
  ****************************************************************************/
-static s32
-e1000_host_if_read_cookie(struct e1000_hw * hw, u8 *buffer)
+static s32 e1000_host_if_read_cookie(struct e1000_hw *hw, u8 *buffer)
 {
     u8 i;
     u32 offset = E1000_MNG_DHCP_COOKIE_OFFSET;
@@ -7514,7 +7381,7 @@
     offset = (offset >> 2);
 
     for (i = 0; i < length; i++) {
-        *((u32 *) buffer + i) =
+        *((u32 *)buffer + i) =
             E1000_READ_REG_ARRAY_DWORD(hw, HOST_IF, offset + i);
     }
     return E1000_SUCCESS;
@@ -7530,21 +7397,20 @@
  *            timeout
  *          - E1000_SUCCESS for success.
  ****************************************************************************/
-static s32
-e1000_mng_enable_host_if(struct e1000_hw * hw)
+static s32 e1000_mng_enable_host_if(struct e1000_hw *hw)
 {
     u32 hicr;
     u8 i;
 
     /* Check that the host interface is enabled. */
-    hicr = E1000_READ_REG(hw, HICR);
+    hicr = er32(HICR);
     if ((hicr & E1000_HICR_EN) == 0) {
         DEBUGOUT("E1000_HOST_EN bit disabled.\n");
         return -E1000_ERR_HOST_INTERFACE_COMMAND;
     }
     /* check the previous command is completed */
     for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
-        hicr = E1000_READ_REG(hw, HICR);
+        hicr = er32(HICR);
         if (!(hicr & E1000_HICR_C))
             break;
         mdelay(1);
@@ -7564,9 +7430,8 @@
  *
  * returns  - E1000_SUCCESS for success.
  ****************************************************************************/
-static s32
-e1000_mng_host_if_write(struct e1000_hw * hw, u8 *buffer,
-                        u16 length, u16 offset, u8 *sum)
+static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length,
+				   u16 offset, u8 *sum)
 {
     u8 *tmp;
     u8 *bufptr = buffer;
@@ -7632,9 +7497,8 @@
  *
  * returns  - E1000_SUCCESS for success.
  ****************************************************************************/
-static s32
-e1000_mng_write_cmd_header(struct e1000_hw * hw,
-                           struct e1000_host_mng_command_header * hdr)
+static s32 e1000_mng_write_cmd_header(struct e1000_hw *hw,
+				      struct e1000_host_mng_command_header *hdr)
 {
     u16 i;
     u8 sum;
@@ -7648,7 +7512,7 @@
     sum = hdr->checksum;
     hdr->checksum = 0;
 
-    buffer = (u8 *) hdr;
+    buffer = (u8 *)hdr;
     i = length;
     while (i--)
         sum += buffer[i];
@@ -7658,8 +7522,8 @@
     length >>= 2;
     /* The device driver writes the relevant command block into the ram area. */
     for (i = 0; i < length; i++) {
-        E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, i, *((u32 *) hdr + i));
-        E1000_WRITE_FLUSH(hw);
+        E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, i, *((u32 *)hdr + i));
+        E1000_WRITE_FLUSH();
     }
 
     return E1000_SUCCESS;
@@ -7672,14 +7536,13 @@
  *
  * returns  - E1000_SUCCESS for success.
  ****************************************************************************/
-static s32
-e1000_mng_write_commit(struct e1000_hw * hw)
+static s32 e1000_mng_write_commit(struct e1000_hw *hw)
 {
     u32 hicr;
 
-    hicr = E1000_READ_REG(hw, HICR);
+    hicr = er32(HICR);
     /* Setting this bit tells the ARC that a new command is pending. */
-    E1000_WRITE_REG(hw, HICR, hicr | E1000_HICR_C);
+    ew32(HICR, hicr | E1000_HICR_C);
 
     return E1000_SUCCESS;
 }
@@ -7690,12 +7553,11 @@
  *
  * returns  - true when the mode is IAMT or false.
  ****************************************************************************/
-bool
-e1000_check_mng_mode(struct e1000_hw *hw)
+bool e1000_check_mng_mode(struct e1000_hw *hw)
 {
     u32 fwsm;
 
-    fwsm = E1000_READ_REG(hw, FWSM);
+    fwsm = er32(FWSM);
 
     if (hw->mac_type == e1000_ich8lan) {
         if ((fwsm & E1000_FWSM_MODE_MASK) ==
@@ -7712,9 +7574,7 @@
 /*****************************************************************************
  * This function writes the dhcp info .
  ****************************************************************************/
-s32
-e1000_mng_write_dhcp_info(struct e1000_hw * hw, u8 *buffer,
-                          u16 length)
+s32 e1000_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length)
 {
     s32 ret_val;
     struct e1000_host_mng_command_header hdr;
@@ -7744,8 +7604,7 @@
  *
  * returns  - checksum of buffer contents.
  ****************************************************************************/
-static u8
-e1000_calculate_mng_checksum(char *buffer, u32 length)
+static u8 e1000_calculate_mng_checksum(char *buffer, u32 length)
 {
     u8 sum = 0;
     u32 i;
@@ -7756,7 +7615,7 @@
     for (i=0; i < length; i++)
         sum += buffer[i];
 
-    return (u8) (0 - sum);
+    return (u8)(0 - sum);
 }
 
 /*****************************************************************************
@@ -7764,8 +7623,7 @@
  *
  * returns  - true for packet filtering or false.
  ****************************************************************************/
-bool
-e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
+bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
 {
     /* called in init as well as watchdog timer functions */
 
@@ -7806,21 +7664,20 @@
  * returns: - true/false
  *
  *****************************************************************************/
-u32
-e1000_enable_mng_pass_thru(struct e1000_hw *hw)
+u32 e1000_enable_mng_pass_thru(struct e1000_hw *hw)
 {
     u32 manc;
     u32 fwsm, factps;
 
     if (hw->asf_firmware_present) {
-        manc = E1000_READ_REG(hw, MANC);
+        manc = er32(MANC);
 
         if (!(manc & E1000_MANC_RCV_TCO_EN) ||
             !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
             return false;
         if (e1000_arc_subsystem_valid(hw)) {
-            fwsm = E1000_READ_REG(hw, FWSM);
-            factps = E1000_READ_REG(hw, FACTPS);
+            fwsm = er32(FWSM);
+            factps = er32(FACTPS);
 
             if ((((fwsm & E1000_FWSM_MODE_MASK) >> E1000_FWSM_MODE_SHIFT) ==
                    e1000_mng_mode_pt) && !(factps & E1000_FACTPS_MNGCG))
@@ -7832,8 +7689,7 @@
     return false;
 }
 
-static s32
-e1000_polarity_reversal_workaround(struct e1000_hw *hw)
+static s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw)
 {
     s32 ret_val;
     u16 mii_status_reg;
@@ -7926,8 +7782,7 @@
  * returns: - none.
  *
  ***************************************************************************/
-static void
-e1000_set_pci_express_master_disable(struct e1000_hw *hw)
+static void e1000_set_pci_express_master_disable(struct e1000_hw *hw)
 {
     u32 ctrl;
 
@@ -7936,9 +7791,9 @@
     if (hw->bus_type != e1000_bus_type_pci_express)
         return;
 
-    ctrl = E1000_READ_REG(hw, CTRL);
+    ctrl = er32(CTRL);
     ctrl |= E1000_CTRL_GIO_MASTER_DISABLE;
-    E1000_WRITE_REG(hw, CTRL, ctrl);
+    ew32(CTRL, ctrl);
 }
 
 /*******************************************************************************
@@ -7952,8 +7807,7 @@
  *            E1000_SUCCESS master requests disabled.
  *
  ******************************************************************************/
-s32
-e1000_disable_pciex_master(struct e1000_hw *hw)
+s32 e1000_disable_pciex_master(struct e1000_hw *hw)
 {
     s32 timeout = MASTER_DISABLE_TIMEOUT;   /* 80ms */
 
@@ -7965,7 +7819,7 @@
     e1000_set_pci_express_master_disable(hw);
 
     while (timeout) {
-        if (!(E1000_READ_REG(hw, STATUS) & E1000_STATUS_GIO_MASTER_ENABLE))
+        if (!(er32(STATUS) & E1000_STATUS_GIO_MASTER_ENABLE))
             break;
         else
             udelay(100);
@@ -7990,8 +7844,7 @@
  *            E1000_SUCCESS at any other case.
  *
  ******************************************************************************/
-static s32
-e1000_get_auto_rd_done(struct e1000_hw *hw)
+static s32 e1000_get_auto_rd_done(struct e1000_hw *hw)
 {
     s32 timeout = AUTO_READ_DONE_TIMEOUT;
 
@@ -8007,7 +7860,7 @@
     case e1000_80003es2lan:
     case e1000_ich8lan:
         while (timeout) {
-            if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD)
+            if (er32(EECD) & E1000_EECD_AUTO_RD)
                 break;
             else msleep(1);
             timeout--;
@@ -8038,8 +7891,7 @@
  *            E1000_SUCCESS at any other case.
  *
  ***************************************************************************/
-static s32
-e1000_get_phy_cfg_done(struct e1000_hw *hw)
+static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw)
 {
     s32 timeout = PHY_CFG_TIMEOUT;
     u32 cfg_mask = E1000_EEPROM_CFG_DONE;
@@ -8052,13 +7904,13 @@
         break;
     case e1000_80003es2lan:
         /* Separate *_CFG_DONE_* bit for each port */
-        if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
+        if (er32(STATUS) & E1000_STATUS_FUNC_1)
             cfg_mask = E1000_EEPROM_CFG_DONE_PORT_1;
         /* Fall Through */
     case e1000_82571:
     case e1000_82572:
         while (timeout) {
-            if (E1000_READ_REG(hw, EEMNGCTL) & cfg_mask)
+            if (er32(EEMNGCTL) & cfg_mask)
                 break;
             else
                 msleep(1);
@@ -8085,8 +7937,7 @@
  *            E1000_SUCCESS at any other case.
  *
  ***************************************************************************/
-static s32
-e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
+static s32 e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
 {
     s32 timeout;
     u32 swsm;
@@ -8105,11 +7956,11 @@
     /* Get the FW semaphore. */
     timeout = hw->eeprom.word_size + 1;
     while (timeout) {
-        swsm = E1000_READ_REG(hw, SWSM);
+        swsm = er32(SWSM);
         swsm |= E1000_SWSM_SWESMBI;
-        E1000_WRITE_REG(hw, SWSM, swsm);
+        ew32(SWSM, swsm);
         /* if we managed to set the bit we got the semaphore. */
-        swsm = E1000_READ_REG(hw, SWSM);
+        swsm = er32(SWSM);
         if (swsm & E1000_SWSM_SWESMBI)
             break;
 
@@ -8135,8 +7986,7 @@
  * returns: - None.
  *
  ***************************************************************************/
-static void
-e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
+static void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
 {
     u32 swsm;
 
@@ -8145,13 +7995,13 @@
     if (!hw->eeprom_semaphore_present)
         return;
 
-    swsm = E1000_READ_REG(hw, SWSM);
+    swsm = er32(SWSM);
     if (hw->mac_type == e1000_80003es2lan) {
         /* Release both semaphores. */
         swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
     } else
         swsm &= ~(E1000_SWSM_SWESMBI);
-    E1000_WRITE_REG(hw, SWSM, swsm);
+    ew32(SWSM, swsm);
 }
 
 /***************************************************************************
@@ -8164,8 +8014,7 @@
  *            E1000_SUCCESS at any other case.
  *
  ***************************************************************************/
-static s32
-e1000_get_software_semaphore(struct e1000_hw *hw)
+static s32 e1000_get_software_semaphore(struct e1000_hw *hw)
 {
     s32 timeout = hw->eeprom.word_size + 1;
     u32 swsm;
@@ -8177,7 +8026,7 @@
     }
 
     while (timeout) {
-        swsm = E1000_READ_REG(hw, SWSM);
+        swsm = er32(SWSM);
         /* If SMBI bit cleared, it is now set and we hold the semaphore */
         if (!(swsm & E1000_SWSM_SMBI))
             break;
@@ -8200,8 +8049,7 @@
  * hw: Struct containing variables accessed by shared code
  *
  ***************************************************************************/
-static void
-e1000_release_software_semaphore(struct e1000_hw *hw)
+static void e1000_release_software_semaphore(struct e1000_hw *hw)
 {
     u32 swsm;
 
@@ -8211,10 +8059,10 @@
         return;
     }
 
-    swsm = E1000_READ_REG(hw, SWSM);
+    swsm = er32(SWSM);
     /* Release the SW semaphores.*/
     swsm &= ~E1000_SWSM_SMBI;
-    E1000_WRITE_REG(hw, SWSM, swsm);
+    ew32(SWSM, swsm);
 }
 
 /******************************************************************************
@@ -8228,26 +8076,24 @@
  *            E1000_SUCCESS
  *
  *****************************************************************************/
-s32
-e1000_check_phy_reset_block(struct e1000_hw *hw)
+s32 e1000_check_phy_reset_block(struct e1000_hw *hw)
 {
     u32 manc = 0;
     u32 fwsm = 0;
 
     if (hw->mac_type == e1000_ich8lan) {
-        fwsm = E1000_READ_REG(hw, FWSM);
+        fwsm = er32(FWSM);
         return (fwsm & E1000_FWSM_RSPCIPHY) ? E1000_SUCCESS
                                             : E1000_BLK_PHY_RESET;
     }
 
     if (hw->mac_type > e1000_82547_rev_2)
-        manc = E1000_READ_REG(hw, MANC);
+        manc = er32(MANC);
     return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ?
         E1000_BLK_PHY_RESET : E1000_SUCCESS;
 }
 
-static u8
-e1000_arc_subsystem_valid(struct e1000_hw *hw)
+static u8 e1000_arc_subsystem_valid(struct e1000_hw *hw)
 {
     u32 fwsm;
 
@@ -8261,7 +8107,7 @@
     case e1000_82572:
     case e1000_82573:
     case e1000_80003es2lan:
-        fwsm = E1000_READ_REG(hw, FWSM);
+        fwsm = er32(FWSM);
         if ((fwsm & E1000_FWSM_MODE_MASK) != 0)
             return true;
         break;
@@ -8283,8 +8129,7 @@
  * returns: E1000_SUCCESS
  *
  *****************************************************************************/
-static s32
-e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, u32 no_snoop)
+static s32 e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, u32 no_snoop)
 {
     u32 gcr_reg = 0;
 
@@ -8297,19 +8142,19 @@
         return E1000_SUCCESS;
 
     if (no_snoop) {
-        gcr_reg = E1000_READ_REG(hw, GCR);
+        gcr_reg = er32(GCR);
         gcr_reg &= ~(PCI_EX_NO_SNOOP_ALL);
         gcr_reg |= no_snoop;
-        E1000_WRITE_REG(hw, GCR, gcr_reg);
+        ew32(GCR, gcr_reg);
     }
     if (hw->mac_type == e1000_ich8lan) {
         u32 ctrl_ext;
 
-        E1000_WRITE_REG(hw, GCR, PCI_EX_82566_SNOOP_ALL);
+        ew32(GCR, PCI_EX_82566_SNOOP_ALL);
 
-        ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+        ctrl_ext = er32(CTRL_EXT);
         ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
-        E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+        ew32(CTRL_EXT, ctrl_ext);
     }
 
     return E1000_SUCCESS;
@@ -8324,8 +8169,7 @@
  * hw: Struct containing variables accessed by shared code
  *
  ***************************************************************************/
-static s32
-e1000_get_software_flag(struct e1000_hw *hw)
+static s32 e1000_get_software_flag(struct e1000_hw *hw)
 {
     s32 timeout = PHY_CFG_TIMEOUT;
     u32 extcnf_ctrl;
@@ -8334,11 +8178,11 @@
 
     if (hw->mac_type == e1000_ich8lan) {
         while (timeout) {
-            extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL);
+            extcnf_ctrl = er32(EXTCNF_CTRL);
             extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG;
-            E1000_WRITE_REG(hw, EXTCNF_CTRL, extcnf_ctrl);
+            ew32(EXTCNF_CTRL, extcnf_ctrl);
 
-            extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL);
+            extcnf_ctrl = er32(EXTCNF_CTRL);
             if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)
                 break;
             mdelay(1);
@@ -8363,17 +8207,16 @@
  * hw: Struct containing variables accessed by shared code
  *
  ***************************************************************************/
-static void
-e1000_release_software_flag(struct e1000_hw *hw)
+static void e1000_release_software_flag(struct e1000_hw *hw)
 {
     u32 extcnf_ctrl;
 
     DEBUGFUNC("e1000_release_software_flag");
 
     if (hw->mac_type == e1000_ich8lan) {
-        extcnf_ctrl= E1000_READ_REG(hw, EXTCNF_CTRL);
+        extcnf_ctrl= er32(EXTCNF_CTRL);
         extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
-        E1000_WRITE_REG(hw, EXTCNF_CTRL, extcnf_ctrl);
+        ew32(EXTCNF_CTRL, extcnf_ctrl);
     }
 
     return;
@@ -8388,9 +8231,8 @@
  * data - word read from the EEPROM
  * words - number of words to read
  *****************************************************************************/
-static s32
-e1000_read_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
-                       u16 *data)
+static s32 e1000_read_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
+				  u16 *data)
 {
     s32  error = E1000_SUCCESS;
     u32 flash_bank = 0;
@@ -8405,7 +8247,7 @@
      * to be updated with each read.
      */
     /* Value of bit 22 corresponds to the flash bank we're on. */
-    flash_bank = (E1000_READ_REG(hw, EECD) & E1000_EECD_SEC1VAL) ? 1 : 0;
+    flash_bank = (er32(EECD) & E1000_EECD_SEC1VAL) ? 1 : 0;
 
     /* Adjust offset appropriately if we're on bank 1 - adjust for word size */
     bank_offset = flash_bank * (hw->flash_bank_size * 2);
@@ -8444,9 +8286,8 @@
  * words - number of words to write
  * data - words to write to the EEPROM
  *****************************************************************************/
-static s32
-e1000_write_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
-                        u16 *data)
+static s32 e1000_write_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
+				   u16 *data)
 {
     u32 i = 0;
     s32 error = E1000_SUCCESS;
@@ -8491,8 +8332,7 @@
  *
  * hw - The pointer to the hw structure
  ****************************************************************************/
-static s32
-e1000_ich8_cycle_init(struct e1000_hw *hw)
+static s32 e1000_ich8_cycle_init(struct e1000_hw *hw)
 {
     union ich8_hws_flash_status hsfsts;
     s32 error = E1000_ERR_EEPROM;
@@ -8558,8 +8398,7 @@
  *
  * hw - The pointer to the hw structure
  ****************************************************************************/
-static s32
-e1000_ich8_flash_cycle(struct e1000_hw *hw, u32 timeout)
+static s32 e1000_ich8_flash_cycle(struct e1000_hw *hw, u32 timeout)
 {
     union ich8_hws_flash_ctrl hsflctl;
     union ich8_hws_flash_status hsfsts;
@@ -8593,9 +8432,8 @@
  * size - Size of data to read, 1=byte 2=word
  * data - Pointer to the word to store the value read.
  *****************************************************************************/
-static s32
-e1000_read_ich8_data(struct e1000_hw *hw, u32 index,
-                     u32 size, u16* data)
+static s32 e1000_read_ich8_data(struct e1000_hw *hw, u32 index, u32 size,
+				u16 *data)
 {
     union ich8_hws_flash_status hsfsts;
     union ich8_hws_flash_ctrl hsflctl;
@@ -8672,9 +8510,8 @@
  * size - Size of data to read, 1=byte 2=word
  * data - The byte(s) to write to the NVM.
  *****************************************************************************/
-static s32
-e1000_write_ich8_data(struct e1000_hw *hw, u32 index, u32 size,
-                      u16 data)
+static s32 e1000_write_ich8_data(struct e1000_hw *hw, u32 index, u32 size,
+				 u16 data)
 {
     union ich8_hws_flash_status hsfsts;
     union ich8_hws_flash_ctrl hsflctl;
@@ -8747,8 +8584,7 @@
  * index - The index of the byte to read.
  * data - Pointer to a byte to store the value read.
  *****************************************************************************/
-static s32
-e1000_read_ich8_byte(struct e1000_hw *hw, u32 index, u8* data)
+static s32 e1000_read_ich8_byte(struct e1000_hw *hw, u32 index, u8 *data)
 {
     s32 status = E1000_SUCCESS;
     u16 word = 0;
@@ -8770,8 +8606,7 @@
  * index - The index of the byte to write.
  * byte - The byte to write to the NVM.
  *****************************************************************************/
-static s32
-e1000_verify_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte)
+static s32 e1000_verify_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte)
 {
     s32 error = E1000_SUCCESS;
     s32 program_retries = 0;
@@ -8803,8 +8638,7 @@
  * index - The index of the byte to read.
  * data - The byte to write to the NVM.
  *****************************************************************************/
-static s32
-e1000_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 data)
+static s32 e1000_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 data)
 {
     s32 status = E1000_SUCCESS;
     u16 word = (u16)data;
@@ -8821,8 +8655,7 @@
  * index - The starting byte index of the word to read.
  * data - Pointer to a word to store the value read.
  *****************************************************************************/
-static s32
-e1000_read_ich8_word(struct e1000_hw *hw, u32 index, u16 *data)
+static s32 e1000_read_ich8_word(struct e1000_hw *hw, u32 index, u16 *data)
 {
     s32 status = E1000_SUCCESS;
     status = e1000_read_ich8_data(hw, index, 2, data);
@@ -8840,8 +8673,7 @@
  * amount of NVM used in each bank is a *minimum* of 4 KBytes, but in fact the
  * bank size may be 4, 8 or 64 KBytes
  *****************************************************************************/
-static s32
-e1000_erase_ich8_4k_segment(struct e1000_hw *hw, u32 bank)
+static s32 e1000_erase_ich8_4k_segment(struct e1000_hw *hw, u32 bank)
 {
     union ich8_hws_flash_status hsfsts;
     union ich8_hws_flash_ctrl hsflctl;
@@ -8930,9 +8762,9 @@
     return error;
 }
 
-static s32
-e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
-                                      u32 cnf_base_addr, u32 cnf_size)
+static s32 e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
+						 u32 cnf_base_addr,
+						 u32 cnf_size)
 {
     u32 ret_val = E1000_SUCCESS;
     u16 word_addr, reg_data, reg_addr;
@@ -8972,8 +8804,7 @@
  *
  * hw: Struct containing variables accessed by shared code
  *****************************************************************************/
-static s32
-e1000_init_lcd_from_nvm(struct e1000_hw *hw)
+static s32 e1000_init_lcd_from_nvm(struct e1000_hw *hw)
 {
     u32 reg_data, cnf_base_addr, cnf_size, ret_val, loop;
 
@@ -8981,32 +8812,32 @@
           return E1000_SUCCESS;
 
     /* Check if SW needs configure the PHY */
-    reg_data = E1000_READ_REG(hw, FEXTNVM);
+    reg_data = er32(FEXTNVM);
     if (!(reg_data & FEXTNVM_SW_CONFIG))
         return E1000_SUCCESS;
 
     /* Wait for basic configuration completes before proceeding*/
     loop = 0;
     do {
-        reg_data = E1000_READ_REG(hw, STATUS) & E1000_STATUS_LAN_INIT_DONE;
+        reg_data = er32(STATUS) & E1000_STATUS_LAN_INIT_DONE;
         udelay(100);
         loop++;
     } while ((!reg_data) && (loop < 50));
 
     /* Clear the Init Done bit for the next init event */
-    reg_data = E1000_READ_REG(hw, STATUS);
+    reg_data = er32(STATUS);
     reg_data &= ~E1000_STATUS_LAN_INIT_DONE;
-    E1000_WRITE_REG(hw, STATUS, reg_data);
+    ew32(STATUS, reg_data);
 
     /* Make sure HW does not configure LCD from PHY extended configuration
        before SW configuration */
-    reg_data = E1000_READ_REG(hw, EXTCNF_CTRL);
+    reg_data = er32(EXTCNF_CTRL);
     if ((reg_data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE) == 0x0000) {
-        reg_data = E1000_READ_REG(hw, EXTCNF_SIZE);
+        reg_data = er32(EXTCNF_SIZE);
         cnf_size = reg_data & E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH;
         cnf_size >>= 16;
         if (cnf_size) {
-            reg_data = E1000_READ_REG(hw, EXTCNF_CTRL);
+            reg_data = er32(EXTCNF_CTRL);
             cnf_base_addr = reg_data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER;
             /* cnf_base_addr is in DWORD */
             cnf_base_addr >>= 16;
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index cf12b05..ad6da7b 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -31,12 +31,7 @@
 
 char e1000_driver_name[] = "e1000";
 static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
-#ifndef CONFIG_E1000_NAPI
-#define DRIVERNAPI
-#else
-#define DRIVERNAPI "-NAPI"
-#endif
-#define DRV_VERSION "7.3.20-k2"DRIVERNAPI
+#define DRV_VERSION "7.3.20-k3-NAPI"
 const char e1000_driver_version[] = DRV_VERSION;
 static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
 
@@ -138,7 +133,6 @@
 static irqreturn_t e1000_intr_msi(int irq, void *data);
 static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
 			       struct e1000_tx_ring *tx_ring);
-#ifdef CONFIG_E1000_NAPI
 static int e1000_clean(struct napi_struct *napi, int budget);
 static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
 			       struct e1000_rx_ring *rx_ring,
@@ -146,12 +140,6 @@
 static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
 				  struct e1000_rx_ring *rx_ring,
 				  int *work_done, int work_to_do);
-#else
-static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
-			       struct e1000_rx_ring *rx_ring);
-static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
-				  struct e1000_rx_ring *rx_ring);
-#endif
 static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
                                    struct e1000_rx_ring *rx_ring,
 				   int cleaned_count);
@@ -232,8 +220,7 @@
  * loaded. All it does is register with the PCI subsystem.
  **/
 
-static int __init
-e1000_init_module(void)
+static int __init e1000_init_module(void)
 {
 	int ret;
 	printk(KERN_INFO "%s - version %s\n",
@@ -261,8 +248,7 @@
  * from memory.
  **/
 
-static void __exit
-e1000_exit_module(void)
+static void __exit e1000_exit_module(void)
 {
 	pci_unregister_driver(&e1000_driver);
 }
@@ -271,12 +257,13 @@
 
 static int e1000_request_irq(struct e1000_adapter *adapter)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
 	irq_handler_t handler = e1000_intr;
 	int irq_flags = IRQF_SHARED;
 	int err;
 
-	if (adapter->hw.mac_type >= e1000_82571) {
+	if (hw->mac_type >= e1000_82571) {
 		adapter->have_msi = !pci_enable_msi(adapter->pdev);
 		if (adapter->have_msi) {
 			handler = e1000_intr_msi;
@@ -311,11 +298,12 @@
  * @adapter: board private structure
  **/
 
-static void
-e1000_irq_disable(struct e1000_adapter *adapter)
+static void e1000_irq_disable(struct e1000_adapter *adapter)
 {
-	E1000_WRITE_REG(&adapter->hw, IMC, ~0);
-	E1000_WRITE_FLUSH(&adapter->hw);
+	struct e1000_hw *hw = &adapter->hw;
+
+	ew32(IMC, ~0);
+	E1000_WRITE_FLUSH();
 	synchronize_irq(adapter->pdev->irq);
 }
 
@@ -324,22 +312,23 @@
  * @adapter: board private structure
  **/
 
-static void
-e1000_irq_enable(struct e1000_adapter *adapter)
+static void e1000_irq_enable(struct e1000_adapter *adapter)
 {
-	E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK);
-	E1000_WRITE_FLUSH(&adapter->hw);
+	struct e1000_hw *hw = &adapter->hw;
+
+	ew32(IMS, IMS_ENABLE_MASK);
+	E1000_WRITE_FLUSH();
 }
 
-static void
-e1000_update_mng_vlan(struct e1000_adapter *adapter)
+static void e1000_update_mng_vlan(struct e1000_adapter *adapter)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
-	u16 vid = adapter->hw.mng_cookie.vlan_id;
+	u16 vid = hw->mng_cookie.vlan_id;
 	u16 old_vid = adapter->mng_vlan_id;
 	if (adapter->vlgrp) {
 		if (!vlan_group_get_device(adapter->vlgrp, vid)) {
-			if (adapter->hw.mng_cookie.status &
+			if (hw->mng_cookie.status &
 				E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) {
 				e1000_vlan_rx_add_vid(netdev, vid);
 				adapter->mng_vlan_id = vid;
@@ -366,26 +355,24 @@
  *
  **/
 
-static void
-e1000_release_hw_control(struct e1000_adapter *adapter)
+static void e1000_release_hw_control(struct e1000_adapter *adapter)
 {
 	u32 ctrl_ext;
 	u32 swsm;
+	struct e1000_hw *hw = &adapter->hw;
 
 	/* Let firmware taken over control of h/w */
-	switch (adapter->hw.mac_type) {
+	switch (hw->mac_type) {
 	case e1000_82573:
-		swsm = E1000_READ_REG(&adapter->hw, SWSM);
-		E1000_WRITE_REG(&adapter->hw, SWSM,
-				swsm & ~E1000_SWSM_DRV_LOAD);
+		swsm = er32(SWSM);
+		ew32(SWSM, swsm & ~E1000_SWSM_DRV_LOAD);
 		break;
 	case e1000_82571:
 	case e1000_82572:
 	case e1000_80003es2lan:
 	case e1000_ich8lan:
-		ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
-		E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
-				ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
+		ctrl_ext = er32(CTRL_EXT);
+		ew32(CTRL_EXT, ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
 		break;
 	default:
 		break;
@@ -403,37 +390,36 @@
  *
  **/
 
-static void
-e1000_get_hw_control(struct e1000_adapter *adapter)
+static void e1000_get_hw_control(struct e1000_adapter *adapter)
 {
 	u32 ctrl_ext;
 	u32 swsm;
+	struct e1000_hw *hw = &adapter->hw;
 
 	/* Let firmware know the driver has taken over */
-	switch (adapter->hw.mac_type) {
+	switch (hw->mac_type) {
 	case e1000_82573:
-		swsm = E1000_READ_REG(&adapter->hw, SWSM);
-		E1000_WRITE_REG(&adapter->hw, SWSM,
-				swsm | E1000_SWSM_DRV_LOAD);
+		swsm = er32(SWSM);
+		ew32(SWSM, swsm | E1000_SWSM_DRV_LOAD);
 		break;
 	case e1000_82571:
 	case e1000_82572:
 	case e1000_80003es2lan:
 	case e1000_ich8lan:
-		ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
-		E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
-				ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
+		ctrl_ext = er32(CTRL_EXT);
+		ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
 		break;
 	default:
 		break;
 	}
 }
 
-static void
-e1000_init_manageability(struct e1000_adapter *adapter)
+static void e1000_init_manageability(struct e1000_adapter *adapter)
 {
+	struct e1000_hw *hw = &adapter->hw;
+
 	if (adapter->en_mng_pt) {
-		u32 manc = E1000_READ_REG(&adapter->hw, MANC);
+		u32 manc = er32(MANC);
 
 		/* disable hardware interception of ARP */
 		manc &= ~(E1000_MANC_ARP_EN);
@@ -441,37 +427,38 @@
 		/* enable receiving management packets to the host */
 		/* this will probably generate destination unreachable messages
 		 * from the host OS, but the packets will be handled on SMBUS */
-		if (adapter->hw.has_manc2h) {
-			u32 manc2h = E1000_READ_REG(&adapter->hw, MANC2H);
+		if (hw->has_manc2h) {
+			u32 manc2h = er32(MANC2H);
 
 			manc |= E1000_MANC_EN_MNG2HOST;
 #define E1000_MNG2HOST_PORT_623 (1 << 5)
 #define E1000_MNG2HOST_PORT_664 (1 << 6)
 			manc2h |= E1000_MNG2HOST_PORT_623;
 			manc2h |= E1000_MNG2HOST_PORT_664;
-			E1000_WRITE_REG(&adapter->hw, MANC2H, manc2h);
+			ew32(MANC2H, manc2h);
 		}
 
-		E1000_WRITE_REG(&adapter->hw, MANC, manc);
+		ew32(MANC, manc);
 	}
 }
 
-static void
-e1000_release_manageability(struct e1000_adapter *adapter)
+static void e1000_release_manageability(struct e1000_adapter *adapter)
 {
+	struct e1000_hw *hw = &adapter->hw;
+
 	if (adapter->en_mng_pt) {
-		u32 manc = E1000_READ_REG(&adapter->hw, MANC);
+		u32 manc = er32(MANC);
 
 		/* re-enable hardware interception of ARP */
 		manc |= E1000_MANC_ARP_EN;
 
-		if (adapter->hw.has_manc2h)
+		if (hw->has_manc2h)
 			manc &= ~E1000_MANC_EN_MNG2HOST;
 
 		/* don't explicitly have to mess with MANC2H since
 		 * MANC has an enable disable that gates MANC2H */
 
-		E1000_WRITE_REG(&adapter->hw, MANC, manc);
+		ew32(MANC, manc);
 	}
 }
 
@@ -506,18 +493,19 @@
 
 int e1000_up(struct e1000_adapter *adapter)
 {
+	struct e1000_hw *hw = &adapter->hw;
+
 	/* hardware has been reset, we need to reload some things */
 	e1000_configure(adapter);
 
 	clear_bit(__E1000_DOWN, &adapter->flags);
 
-#ifdef CONFIG_E1000_NAPI
 	napi_enable(&adapter->napi);
-#endif
+
 	e1000_irq_enable(adapter);
 
 	/* fire a link change interrupt to start the watchdog */
-	E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_LSC);
+	ew32(ICS, E1000_ICS_LSC);
 	return 0;
 }
 
@@ -533,30 +521,33 @@
 
 void e1000_power_up_phy(struct e1000_adapter *adapter)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	u16 mii_reg = 0;
 
 	/* Just clear the power down bit to wake the phy back up */
-	if (adapter->hw.media_type == e1000_media_type_copper) {
+	if (hw->media_type == e1000_media_type_copper) {
 		/* according to the manual, the phy will retain its
 		 * settings across a power-down/up cycle */
-		e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
+		e1000_read_phy_reg(hw, PHY_CTRL, &mii_reg);
 		mii_reg &= ~MII_CR_POWER_DOWN;
-		e1000_write_phy_reg(&adapter->hw, PHY_CTRL, mii_reg);
+		e1000_write_phy_reg(hw, PHY_CTRL, mii_reg);
 	}
 }
 
 static void e1000_power_down_phy(struct e1000_adapter *adapter)
 {
+	struct e1000_hw *hw = &adapter->hw;
+
 	/* Power down the PHY so no link is implied when interface is down *
 	 * The PHY cannot be powered down if any of the following is true *
 	 * (a) WoL is enabled
 	 * (b) AMT is active
 	 * (c) SoL/IDER session is active */
-	if (!adapter->wol && adapter->hw.mac_type >= e1000_82540 &&
-	   adapter->hw.media_type == e1000_media_type_copper) {
+	if (!adapter->wol && hw->mac_type >= e1000_82540 &&
+	   hw->media_type == e1000_media_type_copper) {
 		u16 mii_reg = 0;
 
-		switch (adapter->hw.mac_type) {
+		switch (hw->mac_type) {
 		case e1000_82540:
 		case e1000_82545:
 		case e1000_82545_rev_3:
@@ -566,8 +557,7 @@
 		case e1000_82541_rev_2:
 		case e1000_82547:
 		case e1000_82547_rev_2:
-			if (E1000_READ_REG(&adapter->hw, MANC) &
-			    E1000_MANC_SMBUS_EN)
+			if (er32(MANC) & E1000_MANC_SMBUS_EN)
 				goto out;
 			break;
 		case e1000_82571:
@@ -575,24 +565,23 @@
 		case e1000_82573:
 		case e1000_80003es2lan:
 		case e1000_ich8lan:
-			if (e1000_check_mng_mode(&adapter->hw) ||
-			    e1000_check_phy_reset_block(&adapter->hw))
+			if (e1000_check_mng_mode(hw) ||
+			    e1000_check_phy_reset_block(hw))
 				goto out;
 			break;
 		default:
 			goto out;
 		}
-		e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
+		e1000_read_phy_reg(hw, PHY_CTRL, &mii_reg);
 		mii_reg |= MII_CR_POWER_DOWN;
-		e1000_write_phy_reg(&adapter->hw, PHY_CTRL, mii_reg);
+		e1000_write_phy_reg(hw, PHY_CTRL, mii_reg);
 		mdelay(1);
 	}
 out:
 	return;
 }
 
-void
-e1000_down(struct e1000_adapter *adapter)
+void e1000_down(struct e1000_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
 
@@ -600,9 +589,8 @@
 	 * reschedule our watchdog timer */
 	set_bit(__E1000_DOWN, &adapter->flags);
 
-#ifdef CONFIG_E1000_NAPI
 	napi_disable(&adapter->napi);
-#endif
+
 	e1000_irq_disable(adapter);
 
 	del_timer_sync(&adapter->tx_fifo_stall_timer);
@@ -620,8 +608,7 @@
 	e1000_clean_all_rx_rings(adapter);
 }
 
-void
-e1000_reinit_locked(struct e1000_adapter *adapter)
+void e1000_reinit_locked(struct e1000_adapter *adapter)
 {
 	WARN_ON(in_interrupt());
 	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
@@ -631,9 +618,9 @@
 	clear_bit(__E1000_RESETTING, &adapter->flags);
 }
 
-void
-e1000_reset(struct e1000_adapter *adapter)
+void e1000_reset(struct e1000_adapter *adapter)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	u32 pba = 0, tx_space, min_tx_space, min_rx_space;
 	u16 fc_high_water_mark = E1000_FC_HIGH_DIFF;
 	bool legacy_pba_adjust = false;
@@ -642,7 +629,7 @@
 	 * To take effect CTRL.RST is required.
 	 */
 
-	switch (adapter->hw.mac_type) {
+	switch (hw->mac_type) {
 	case e1000_82542_rev2_0:
 	case e1000_82542_rev2_1:
 	case e1000_82543:
@@ -683,16 +670,16 @@
 		if (adapter->netdev->mtu > E1000_RXBUFFER_8192)
 			pba -= 8; /* allocate more FIFO for Tx */
 
-		if (adapter->hw.mac_type == e1000_82547) {
+		if (hw->mac_type == e1000_82547) {
 			adapter->tx_fifo_head = 0;
 			adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT;
 			adapter->tx_fifo_size =
 				(E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT;
 			atomic_set(&adapter->tx_fifo_stall, 0);
 		}
-	} else if (adapter->hw.max_frame_size > MAXIMUM_ETHERNET_FRAME_SIZE) {
+	} else if (hw->max_frame_size > MAXIMUM_ETHERNET_FRAME_SIZE) {
 		/* adjust PBA for jumbo frames */
-		E1000_WRITE_REG(&adapter->hw, PBA, pba);
+		ew32(PBA, pba);
 
 		/* To maintain wire speed transmits, the Tx FIFO should be
 		 * large enough to accomodate two full transmit packets,
@@ -700,7 +687,7 @@
 		 * the Rx FIFO should be large enough to accomodate at least
 		 * one full receive packet and is similarly rounded up and
 		 * expressed in KB. */
-		pba = E1000_READ_REG(&adapter->hw, PBA);
+		pba = er32(PBA);
 		/* upper 16 bits has Tx packet buffer allocation size in KB */
 		tx_space = pba >> 16;
 		/* lower 16 bits has Rx packet buffer allocation size in KB */
@@ -723,7 +710,7 @@
 			pba = pba - (min_tx_space - tx_space);
 
 			/* PCI/PCIx hardware has PBA alignment constraints */
-			switch (adapter->hw.mac_type) {
+			switch (hw->mac_type) {
 			case e1000_82545 ... e1000_82546_rev_3:
 				pba &= ~(E1000_PBA_8K - 1);
 				break;
@@ -734,7 +721,7 @@
 			/* if short on rx space, rx wins and must trump tx
 			 * adjustment or use Early Receive if available */
 			if (pba < min_rx_space) {
-				switch (adapter->hw.mac_type) {
+				switch (hw->mac_type) {
 				case e1000_82573:
 					/* ERT enabled in e1000_configure_rx */
 					break;
@@ -746,7 +733,7 @@
 		}
 	}
 
-	E1000_WRITE_REG(&adapter->hw, PBA, pba);
+	ew32(PBA, pba);
 
 	/* flow control settings */
 	/* Set the FC high water mark to 90% of the FIFO size.
@@ -759,54 +746,54 @@
 	if (pba < E1000_PBA_16K)
 		fc_high_water_mark = (pba * 1024) - 1600;
 
-	adapter->hw.fc_high_water = fc_high_water_mark;
-	adapter->hw.fc_low_water = fc_high_water_mark - 8;
-	if (adapter->hw.mac_type == e1000_80003es2lan)
-		adapter->hw.fc_pause_time = 0xFFFF;
+	hw->fc_high_water = fc_high_water_mark;
+	hw->fc_low_water = fc_high_water_mark - 8;
+	if (hw->mac_type == e1000_80003es2lan)
+		hw->fc_pause_time = 0xFFFF;
 	else
-		adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME;
-	adapter->hw.fc_send_xon = 1;
-	adapter->hw.fc = adapter->hw.original_fc;
+		hw->fc_pause_time = E1000_FC_PAUSE_TIME;
+	hw->fc_send_xon = 1;
+	hw->fc = hw->original_fc;
 
 	/* Allow time for pending master requests to run */
-	e1000_reset_hw(&adapter->hw);
-	if (adapter->hw.mac_type >= e1000_82544)
-		E1000_WRITE_REG(&adapter->hw, WUC, 0);
+	e1000_reset_hw(hw);
+	if (hw->mac_type >= e1000_82544)
+		ew32(WUC, 0);
 
-	if (e1000_init_hw(&adapter->hw))
+	if (e1000_init_hw(hw))
 		DPRINTK(PROBE, ERR, "Hardware Error\n");
 	e1000_update_mng_vlan(adapter);
 
 	/* if (adapter->hwflags & HWFLAGS_PHY_PWR_BIT) { */
-	if (adapter->hw.mac_type >= e1000_82544 &&
-	    adapter->hw.mac_type <= e1000_82547_rev_2 &&
-	    adapter->hw.autoneg == 1 &&
-	    adapter->hw.autoneg_advertised == ADVERTISE_1000_FULL) {
-		u32 ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+	if (hw->mac_type >= e1000_82544 &&
+	    hw->mac_type <= e1000_82547_rev_2 &&
+	    hw->autoneg == 1 &&
+	    hw->autoneg_advertised == ADVERTISE_1000_FULL) {
+		u32 ctrl = er32(CTRL);
 		/* clear phy power management bit if we are in gig only mode,
 		 * which if enabled will attempt negotiation to 100Mb, which
 		 * can cause a loss of link at power off or driver unload */
 		ctrl &= ~E1000_CTRL_SWDPIN3;
-		E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
+		ew32(CTRL, ctrl);
 	}
 
 	/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
-	E1000_WRITE_REG(&adapter->hw, VET, ETHERNET_IEEE_VLAN_TYPE);
+	ew32(VET, ETHERNET_IEEE_VLAN_TYPE);
 
-	e1000_reset_adaptive(&adapter->hw);
-	e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
+	e1000_reset_adaptive(hw);
+	e1000_phy_get_info(hw, &adapter->phy_info);
 
 	if (!adapter->smart_power_down &&
-	    (adapter->hw.mac_type == e1000_82571 ||
-	     adapter->hw.mac_type == e1000_82572)) {
+	    (hw->mac_type == e1000_82571 ||
+	     hw->mac_type == e1000_82572)) {
 		u16 phy_data = 0;
 		/* speed up time to link by disabling smart power down, ignore
 		 * the return value of this function because there is nothing
 		 * different we would do if it failed */
-		e1000_read_phy_reg(&adapter->hw, IGP02E1000_PHY_POWER_MGMT,
+		e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
 		                   &phy_data);
 		phy_data &= ~IGP02E1000_PM_SPD;
-		e1000_write_phy_reg(&adapter->hw, IGP02E1000_PHY_POWER_MGMT,
+		e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
 		                    phy_data);
 	}
 
@@ -865,13 +852,49 @@
 	printk(KERN_ERR "to enable this network device.\n");
 	printk(KERN_ERR "Please inspect the EEPROM dump and report the issue "
 	       "to your hardware vendor\n");
-	printk(KERN_ERR "or Intel Customer Support: linux-nics@intel.com\n");
+	printk(KERN_ERR "or Intel Customer Support.\n");
 	printk(KERN_ERR "/*********************/\n");
 
 	kfree(data);
 }
 
 /**
+ * e1000_is_need_ioport - determine if an adapter needs ioport resources or not
+ * @pdev: PCI device information struct
+ *
+ * Return true if an adapter needs ioport resources
+ **/
+static int e1000_is_need_ioport(struct pci_dev *pdev)
+{
+	switch (pdev->device) {
+	case E1000_DEV_ID_82540EM:
+	case E1000_DEV_ID_82540EM_LOM:
+	case E1000_DEV_ID_82540EP:
+	case E1000_DEV_ID_82540EP_LOM:
+	case E1000_DEV_ID_82540EP_LP:
+	case E1000_DEV_ID_82541EI:
+	case E1000_DEV_ID_82541EI_MOBILE:
+	case E1000_DEV_ID_82541ER:
+	case E1000_DEV_ID_82541ER_LOM:
+	case E1000_DEV_ID_82541GI:
+	case E1000_DEV_ID_82541GI_LF:
+	case E1000_DEV_ID_82541GI_MOBILE:
+	case E1000_DEV_ID_82544EI_COPPER:
+	case E1000_DEV_ID_82544EI_FIBER:
+	case E1000_DEV_ID_82544GC_COPPER:
+	case E1000_DEV_ID_82544GC_LOM:
+	case E1000_DEV_ID_82545EM_COPPER:
+	case E1000_DEV_ID_82545EM_FIBER:
+	case E1000_DEV_ID_82546EB_COPPER:
+	case E1000_DEV_ID_82546EB_FIBER:
+	case E1000_DEV_ID_82546EB_QUAD_COPPER:
+		return true;
+	default:
+		return false;
+	}
+}
+
+/**
  * e1000_probe - Device Initialization Routine
  * @pdev: PCI device information struct
  * @ent: entry in e1000_pci_tbl
@@ -882,37 +905,51 @@
  * The OS initialization, configuring of the adapter private structure,
  * and a hardware reset occur.
  **/
-
-static int __devinit
-e1000_probe(struct pci_dev *pdev,
-            const struct pci_device_id *ent)
+static int __devinit e1000_probe(struct pci_dev *pdev,
+				 const struct pci_device_id *ent)
 {
 	struct net_device *netdev;
 	struct e1000_adapter *adapter;
+	struct e1000_hw *hw;
 
 	static int cards_found = 0;
 	static int global_quad_port_a = 0; /* global ksp3 port a indication */
 	int i, err, pci_using_dac;
 	u16 eeprom_data = 0;
 	u16 eeprom_apme_mask = E1000_EEPROM_APME;
+	int bars, need_ioport;
 	DECLARE_MAC_BUF(mac);
 
-	if ((err = pci_enable_device(pdev)))
+	/* do not allocate ioport bars when not needed */
+	need_ioport = e1000_is_need_ioport(pdev);
+	if (need_ioport) {
+		bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
+		err = pci_enable_device(pdev);
+	} else {
+		bars = pci_select_bars(pdev, IORESOURCE_MEM);
+		err = pci_enable_device(pdev);
+	}
+	if (err)
 		return err;
 
-	if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)) &&
-	    !(err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))) {
+	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK) &&
+	    !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) {
 		pci_using_dac = 1;
 	} else {
-		if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) &&
-		    (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))) {
-			E1000_ERR("No usable DMA configuration, aborting\n");
-			goto err_dma;
+		err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+		if (err) {
+			err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+			if (err) {
+				E1000_ERR("No usable DMA configuration, "
+					  "aborting\n");
+				goto err_dma;
+			}
 		}
 		pci_using_dac = 0;
 	}
 
-	if ((err = pci_request_regions(pdev, e1000_driver_name)))
+	err = pci_request_selected_regions(pdev, bars, e1000_driver_name);
+	if (err)
 		goto err_pci_reg;
 
 	pci_set_master(pdev);
@@ -928,21 +965,27 @@
 	adapter = netdev_priv(netdev);
 	adapter->netdev = netdev;
 	adapter->pdev = pdev;
-	adapter->hw.back = adapter;
 	adapter->msg_enable = (1 << debug) - 1;
+	adapter->bars = bars;
+	adapter->need_ioport = need_ioport;
+
+	hw = &adapter->hw;
+	hw->back = adapter;
 
 	err = -EIO;
-	adapter->hw.hw_addr = ioremap(pci_resource_start(pdev, BAR_0),
-				      pci_resource_len(pdev, BAR_0));
-	if (!adapter->hw.hw_addr)
+	hw->hw_addr = ioremap(pci_resource_start(pdev, BAR_0),
+			      pci_resource_len(pdev, BAR_0));
+	if (!hw->hw_addr)
 		goto err_ioremap;
 
-	for (i = BAR_1; i <= BAR_5; i++) {
-		if (pci_resource_len(pdev, i) == 0)
-			continue;
-		if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
-			adapter->hw.io_base = pci_resource_start(pdev, i);
-			break;
+	if (adapter->need_ioport) {
+		for (i = BAR_1; i <= BAR_5; i++) {
+			if (pci_resource_len(pdev, i) == 0)
+				continue;
+			if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
+				hw->io_base = pci_resource_start(pdev, i);
+				break;
+			}
 		}
 	}
 
@@ -957,9 +1000,7 @@
 	e1000_set_ethtool_ops(netdev);
 	netdev->tx_timeout = &e1000_tx_timeout;
 	netdev->watchdog_timeo = 5 * HZ;
-#ifdef CONFIG_E1000_NAPI
 	netif_napi_add(netdev, &adapter->napi, e1000_clean, 64);
-#endif
 	netdev->vlan_rx_register = e1000_vlan_rx_register;
 	netdev->vlan_rx_add_vid = e1000_vlan_rx_add_vid;
 	netdev->vlan_rx_kill_vid = e1000_vlan_rx_kill_vid;
@@ -972,49 +1013,50 @@
 
 	/* setup the private structure */
 
-	if ((err = e1000_sw_init(adapter)))
+	err = e1000_sw_init(adapter);
+	if (err)
 		goto err_sw_init;
 
 	err = -EIO;
 	/* Flash BAR mapping must happen after e1000_sw_init
 	 * because it depends on mac_type */
-	if ((adapter->hw.mac_type == e1000_ich8lan) &&
+	if ((hw->mac_type == e1000_ich8lan) &&
 	   (pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
-		adapter->hw.flash_address =
+		hw->flash_address =
 			ioremap(pci_resource_start(pdev, 1),
 				pci_resource_len(pdev, 1));
-		if (!adapter->hw.flash_address)
+		if (!hw->flash_address)
 			goto err_flashmap;
 	}
 
-	if (e1000_check_phy_reset_block(&adapter->hw))
+	if (e1000_check_phy_reset_block(hw))
 		DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n");
 
-	if (adapter->hw.mac_type >= e1000_82543) {
+	if (hw->mac_type >= e1000_82543) {
 		netdev->features = NETIF_F_SG |
 				   NETIF_F_HW_CSUM |
 				   NETIF_F_HW_VLAN_TX |
 				   NETIF_F_HW_VLAN_RX |
 				   NETIF_F_HW_VLAN_FILTER;
-		if (adapter->hw.mac_type == e1000_ich8lan)
+		if (hw->mac_type == e1000_ich8lan)
 			netdev->features &= ~NETIF_F_HW_VLAN_FILTER;
 	}
 
-	if ((adapter->hw.mac_type >= e1000_82544) &&
-	   (adapter->hw.mac_type != e1000_82547))
+	if ((hw->mac_type >= e1000_82544) &&
+	   (hw->mac_type != e1000_82547))
 		netdev->features |= NETIF_F_TSO;
 
-	if (adapter->hw.mac_type > e1000_82547_rev_2)
+	if (hw->mac_type > e1000_82547_rev_2)
 		netdev->features |= NETIF_F_TSO6;
 	if (pci_using_dac)
 		netdev->features |= NETIF_F_HIGHDMA;
 
 	netdev->features |= NETIF_F_LLTX;
 
-	adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw);
+	adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw);
 
 	/* initialize eeprom parameters */
-	if (e1000_init_eeprom_params(&adapter->hw)) {
+	if (e1000_init_eeprom_params(hw)) {
 		E1000_ERR("EEPROM initialization failed\n");
 		goto err_eeprom;
 	}
@@ -1022,10 +1064,10 @@
 	/* before reading the EEPROM, reset the controller to
 	 * put the device in a known good starting state */
 
-	e1000_reset_hw(&adapter->hw);
+	e1000_reset_hw(hw);
 
 	/* make sure the EEPROM is good */
-	if (e1000_validate_eeprom_checksum(&adapter->hw) < 0) {
+	if (e1000_validate_eeprom_checksum(hw) < 0) {
 		DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n");
 		e1000_dump_eeprom(adapter);
 		/*
@@ -1036,24 +1078,24 @@
 		 * interface after manually setting a hw addr using
 		 * `ip set address`
 		 */
-		memset(adapter->hw.mac_addr, 0, netdev->addr_len);
+		memset(hw->mac_addr, 0, netdev->addr_len);
 	} else {
 		/* copy the MAC address out of the EEPROM */
-		if (e1000_read_mac_addr(&adapter->hw))
+		if (e1000_read_mac_addr(hw))
 			DPRINTK(PROBE, ERR, "EEPROM Read Error\n");
 	}
 	/* don't block initalization here due to bad MAC address */
-	memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
-	memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);
+	memcpy(netdev->dev_addr, hw->mac_addr, netdev->addr_len);
+	memcpy(netdev->perm_addr, hw->mac_addr, netdev->addr_len);
 
 	if (!is_valid_ether_addr(netdev->perm_addr))
 		DPRINTK(PROBE, ERR, "Invalid MAC Address\n");
 
-	e1000_get_bus_info(&adapter->hw);
+	e1000_get_bus_info(hw);
 
 	init_timer(&adapter->tx_fifo_stall_timer);
 	adapter->tx_fifo_stall_timer.function = &e1000_82547_tx_fifo_stall;
-	adapter->tx_fifo_stall_timer.data = (unsigned long) adapter;
+	adapter->tx_fifo_stall_timer.data = (unsigned long)adapter;
 
 	init_timer(&adapter->watchdog_timer);
 	adapter->watchdog_timer.function = &e1000_watchdog;
@@ -1061,7 +1103,7 @@
 
 	init_timer(&adapter->phy_info_timer);
 	adapter->phy_info_timer.function = &e1000_update_phy_info;
-	adapter->phy_info_timer.data = (unsigned long) adapter;
+	adapter->phy_info_timer.data = (unsigned long)adapter;
 
 	INIT_WORK(&adapter->reset_task, e1000_reset_task);
 
@@ -1072,18 +1114,18 @@
 	 * enable the ACPI Magic Packet filter
 	 */
 
-	switch (adapter->hw.mac_type) {
+	switch (hw->mac_type) {
 	case e1000_82542_rev2_0:
 	case e1000_82542_rev2_1:
 	case e1000_82543:
 		break;
 	case e1000_82544:
-		e1000_read_eeprom(&adapter->hw,
+		e1000_read_eeprom(hw,
 			EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data);
 		eeprom_apme_mask = E1000_EEPROM_82544_APM;
 		break;
 	case e1000_ich8lan:
-		e1000_read_eeprom(&adapter->hw,
+		e1000_read_eeprom(hw,
 			EEPROM_INIT_CONTROL1_REG, 1, &eeprom_data);
 		eeprom_apme_mask = E1000_EEPROM_ICH8_APME;
 		break;
@@ -1091,14 +1133,14 @@
 	case e1000_82546_rev_3:
 	case e1000_82571:
 	case e1000_80003es2lan:
-		if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1){
-			e1000_read_eeprom(&adapter->hw,
+		if (er32(STATUS) & E1000_STATUS_FUNC_1){
+			e1000_read_eeprom(hw,
 				EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);
 			break;
 		}
 		/* Fall Through */
 	default:
-		e1000_read_eeprom(&adapter->hw,
+		e1000_read_eeprom(hw,
 			EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
 		break;
 	}
@@ -1117,7 +1159,7 @@
 	case E1000_DEV_ID_82571EB_FIBER:
 		/* Wake events only supported on port A for dual fiber
 		 * regardless of eeprom setting */
-		if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1)
+		if (er32(STATUS) & E1000_STATUS_FUNC_1)
 			adapter->eeprom_wol = 0;
 		break;
 	case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
@@ -1140,8 +1182,6 @@
 	adapter->wol = adapter->eeprom_wol;
 
 	/* print bus type/speed/width info */
-	{
-	struct e1000_hw *hw = &adapter->hw;
 	DPRINTK(PROBE, INFO, "(PCI%s:%s:%s) ",
 		((hw->bus_type == e1000_bus_type_pcix) ? "-X" :
 		 (hw->bus_type == e1000_bus_type_pci_express ? " Express":"")),
@@ -1154,11 +1194,10 @@
 		 (hw->bus_width == e1000_bus_width_pciex_4) ? "Width x4" :
 		 (hw->bus_width == e1000_bus_width_pciex_1) ? "Width x1" :
 		 "32-bit"));
-	}
 
 	printk("%s\n", print_mac(mac, netdev->dev_addr));
 
-	if (adapter->hw.bus_type == e1000_bus_type_pci_express) {
+	if (hw->bus_type == e1000_bus_type_pci_express) {
 		DPRINTK(PROBE, WARNING, "This device (id %04x:%04x) will no "
 			"longer be supported by this driver in the future.\n",
 			pdev->vendor, pdev->device);
@@ -1173,8 +1212,8 @@
 	 * DRV_LOAD until the interface is up.  For all other cases,
 	 * let the f/w know that the h/w is now under the control
 	 * of the driver. */
-	if (adapter->hw.mac_type != e1000_82573 ||
-	    !e1000_check_mng_mode(&adapter->hw))
+	if (hw->mac_type != e1000_82573 ||
+	    !e1000_check_mng_mode(hw))
 		e1000_get_hw_control(adapter);
 
 	/* tell the stack to leave us alone until e1000_open() is called */
@@ -1182,7 +1221,8 @@
 	netif_stop_queue(netdev);
 
 	strcpy(netdev->name, "eth%d");
-	if ((err = register_netdev(netdev)))
+	err = register_netdev(netdev);
+	if (err)
 		goto err_register;
 
 	DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n");
@@ -1193,28 +1233,24 @@
 err_register:
 	e1000_release_hw_control(adapter);
 err_eeprom:
-	if (!e1000_check_phy_reset_block(&adapter->hw))
-		e1000_phy_hw_reset(&adapter->hw);
+	if (!e1000_check_phy_reset_block(hw))
+		e1000_phy_hw_reset(hw);
 
-	if (adapter->hw.flash_address)
-		iounmap(adapter->hw.flash_address);
+	if (hw->flash_address)
+		iounmap(hw->flash_address);
 err_flashmap:
-#ifdef CONFIG_E1000_NAPI
 	for (i = 0; i < adapter->num_rx_queues; i++)
 		dev_put(&adapter->polling_netdev[i]);
-#endif
 
 	kfree(adapter->tx_ring);
 	kfree(adapter->rx_ring);
-#ifdef CONFIG_E1000_NAPI
 	kfree(adapter->polling_netdev);
-#endif
 err_sw_init:
-	iounmap(adapter->hw.hw_addr);
+	iounmap(hw->hw_addr);
 err_ioremap:
 	free_netdev(netdev);
 err_alloc_etherdev:
-	pci_release_regions(pdev);
+	pci_release_selected_regions(pdev, bars);
 err_pci_reg:
 err_dma:
 	pci_disable_device(pdev);
@@ -1231,14 +1267,12 @@
  * memory.
  **/
 
-static void __devexit
-e1000_remove(struct pci_dev *pdev)
+static void __devexit e1000_remove(struct pci_dev *pdev)
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct e1000_adapter *adapter = netdev_priv(netdev);
-#ifdef CONFIG_E1000_NAPI
+	struct e1000_hw *hw = &adapter->hw;
 	int i;
-#endif
 
 	cancel_work_sync(&adapter->reset_task);
 
@@ -1248,26 +1282,22 @@
 	 * would have already happened in close and is redundant. */
 	e1000_release_hw_control(adapter);
 
-#ifdef CONFIG_E1000_NAPI
 	for (i = 0; i < adapter->num_rx_queues; i++)
 		dev_put(&adapter->polling_netdev[i]);
-#endif
 
 	unregister_netdev(netdev);
 
-	if (!e1000_check_phy_reset_block(&adapter->hw))
-		e1000_phy_hw_reset(&adapter->hw);
+	if (!e1000_check_phy_reset_block(hw))
+		e1000_phy_hw_reset(hw);
 
 	kfree(adapter->tx_ring);
 	kfree(adapter->rx_ring);
-#ifdef CONFIG_E1000_NAPI
 	kfree(adapter->polling_netdev);
-#endif
 
-	iounmap(adapter->hw.hw_addr);
-	if (adapter->hw.flash_address)
-		iounmap(adapter->hw.flash_address);
-	pci_release_regions(pdev);
+	iounmap(hw->hw_addr);
+	if (hw->flash_address)
+		iounmap(hw->flash_address);
+	pci_release_selected_regions(pdev, adapter->bars);
 
 	free_netdev(netdev);
 
@@ -1283,15 +1313,12 @@
  * OS network device settings (MTU size).
  **/
 
-static int __devinit
-e1000_sw_init(struct e1000_adapter *adapter)
+static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
-#ifdef CONFIG_E1000_NAPI
 	int i;
-#endif
 
 	/* PCI config space info */
 
@@ -1349,14 +1376,12 @@
 		return -ENOMEM;
 	}
 
-#ifdef CONFIG_E1000_NAPI
 	for (i = 0; i < adapter->num_rx_queues; i++) {
 		adapter->polling_netdev[i].priv = adapter;
 		dev_hold(&adapter->polling_netdev[i]);
 		set_bit(__LINK_STATE_START, &adapter->polling_netdev[i].state);
 	}
 	spin_lock_init(&adapter->tx_queue_lock);
-#endif
 
 	/* Explicitly disable IRQ since the NIC can be in any state. */
 	e1000_irq_disable(adapter);
@@ -1377,8 +1402,7 @@
  * intended for Multiqueue, but should work fine with a single queue.
  **/
 
-static int __devinit
-e1000_alloc_queues(struct e1000_adapter *adapter)
+static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter)
 {
 	adapter->tx_ring = kcalloc(adapter->num_tx_queues,
 	                           sizeof(struct e1000_tx_ring), GFP_KERNEL);
@@ -1392,7 +1416,6 @@
 		return -ENOMEM;
 	}
 
-#ifdef CONFIG_E1000_NAPI
 	adapter->polling_netdev = kcalloc(adapter->num_rx_queues,
 	                                  sizeof(struct net_device),
 	                                  GFP_KERNEL);
@@ -1401,7 +1424,6 @@
 		kfree(adapter->rx_ring);
 		return -ENOMEM;
 	}
-#endif
 
 	return E1000_SUCCESS;
 }
@@ -1419,10 +1441,10 @@
  * and the stack is notified that the interface is ready.
  **/
 
-static int
-e1000_open(struct net_device *netdev)
+static int e1000_open(struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
 	int err;
 
 	/* disallow open during test */
@@ -1442,15 +1464,15 @@
 	e1000_power_up_phy(adapter);
 
 	adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
-	if ((adapter->hw.mng_cookie.status &
+	if ((hw->mng_cookie.status &
 			  E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
 		e1000_update_mng_vlan(adapter);
 	}
 
 	/* If AMT is enabled, let the firmware know that the network
 	 * interface is now open */
-	if (adapter->hw.mac_type == e1000_82573 &&
-	    e1000_check_mng_mode(&adapter->hw))
+	if (hw->mac_type == e1000_82573 &&
+	    e1000_check_mng_mode(hw))
 		e1000_get_hw_control(adapter);
 
 	/* before we allocate an interrupt, we must be ready to handle it.
@@ -1466,16 +1488,14 @@
 	/* From here on the code is the same as e1000_up() */
 	clear_bit(__E1000_DOWN, &adapter->flags);
 
-#ifdef CONFIG_E1000_NAPI
 	napi_enable(&adapter->napi);
-#endif
 
 	e1000_irq_enable(adapter);
 
 	netif_start_queue(netdev);
 
 	/* fire a link status change interrupt to start the watchdog */
-	E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_LSC);
+	ew32(ICS, E1000_ICS_LSC);
 
 	return E1000_SUCCESS;
 
@@ -1503,10 +1523,10 @@
  * hardware, and all transmit and receive resources are freed.
  **/
 
-static int
-e1000_close(struct net_device *netdev)
+static int e1000_close(struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
 
 	WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
 	e1000_down(adapter);
@@ -1518,7 +1538,7 @@
 
 	/* kill manageability vlan ID if supported, but not if a vlan with
 	 * the same ID is registered on the host OS (let 8021q kill it) */
-	if ((adapter->hw.mng_cookie.status &
+	if ((hw->mng_cookie.status &
 			  E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
 	     !(adapter->vlgrp &&
 	       vlan_group_get_device(adapter->vlgrp, adapter->mng_vlan_id))) {
@@ -1527,8 +1547,8 @@
 
 	/* If AMT is enabled, let the firmware know that the network
 	 * interface is now closed */
-	if (adapter->hw.mac_type == e1000_82573 &&
-	    e1000_check_mng_mode(&adapter->hw))
+	if (hw->mac_type == e1000_82573 &&
+	    e1000_check_mng_mode(hw))
 		e1000_release_hw_control(adapter);
 
 	return 0;
@@ -1540,17 +1560,17 @@
  * @start: address of beginning of memory
  * @len: length of memory
  **/
-static bool
-e1000_check_64k_bound(struct e1000_adapter *adapter,
-		      void *start, unsigned long len)
+static bool e1000_check_64k_bound(struct e1000_adapter *adapter, void *start,
+				  unsigned long len)
 {
-	unsigned long begin = (unsigned long) start;
+	struct e1000_hw *hw = &adapter->hw;
+	unsigned long begin = (unsigned long)start;
 	unsigned long end = begin + len;
 
 	/* First rev 82545 and 82546 need to not allow any memory
 	 * write location to cross 64k boundary due to errata 23 */
-	if (adapter->hw.mac_type == e1000_82545 ||
-	    adapter->hw.mac_type == e1000_82546) {
+	if (hw->mac_type == e1000_82545 ||
+	    hw->mac_type == e1000_82546) {
 		return ((begin ^ (end - 1)) >> 16) != 0 ? false : true;
 	}
 
@@ -1565,9 +1585,8 @@
  * Return 0 on success, negative on failure
  **/
 
-static int
-e1000_setup_tx_resources(struct e1000_adapter *adapter,
-                         struct e1000_tx_ring *txdr)
+static int e1000_setup_tx_resources(struct e1000_adapter *adapter,
+				    struct e1000_tx_ring *txdr)
 {
 	struct pci_dev *pdev = adapter->pdev;
 	int size;
@@ -1641,8 +1660,7 @@
  * Return 0 on success, negative on failure
  **/
 
-int
-e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
+int e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
 {
 	int i, err = 0;
 
@@ -1668,8 +1686,7 @@
  * Configure the Tx unit of the MAC after a reset.
  **/
 
-static void
-e1000_configure_tx(struct e1000_adapter *adapter)
+static void e1000_configure_tx(struct e1000_adapter *adapter)
 {
 	u64 tdba;
 	struct e1000_hw *hw = &adapter->hw;
@@ -1684,18 +1701,18 @@
 		tdba = adapter->tx_ring[0].dma;
 		tdlen = adapter->tx_ring[0].count *
 			sizeof(struct e1000_tx_desc);
-		E1000_WRITE_REG(hw, TDLEN, tdlen);
-		E1000_WRITE_REG(hw, TDBAH, (tdba >> 32));
-		E1000_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL));
-		E1000_WRITE_REG(hw, TDT, 0);
-		E1000_WRITE_REG(hw, TDH, 0);
+		ew32(TDLEN, tdlen);
+		ew32(TDBAH, (tdba >> 32));
+		ew32(TDBAL, (tdba & 0x00000000ffffffffULL));
+		ew32(TDT, 0);
+		ew32(TDH, 0);
 		adapter->tx_ring[0].tdh = ((hw->mac_type >= e1000_82543) ? E1000_TDH : E1000_82542_TDH);
 		adapter->tx_ring[0].tdt = ((hw->mac_type >= e1000_82543) ? E1000_TDT : E1000_82542_TDT);
 		break;
 	}
 
 	/* Set the default values for the Tx Inter Packet Gap timer */
-	if (adapter->hw.mac_type <= e1000_82547_rev_2 &&
+	if (hw->mac_type <= e1000_82547_rev_2 &&
 	    (hw->media_type == e1000_media_type_fiber ||
 	     hw->media_type == e1000_media_type_internal_serdes))
 		tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
@@ -1720,34 +1737,34 @@
 	}
 	tipg |= ipgr1 << E1000_TIPG_IPGR1_SHIFT;
 	tipg |= ipgr2 << E1000_TIPG_IPGR2_SHIFT;
-	E1000_WRITE_REG(hw, TIPG, tipg);
+	ew32(TIPG, tipg);
 
 	/* Set the Tx Interrupt Delay register */
 
-	E1000_WRITE_REG(hw, TIDV, adapter->tx_int_delay);
+	ew32(TIDV, adapter->tx_int_delay);
 	if (hw->mac_type >= e1000_82540)
-		E1000_WRITE_REG(hw, TADV, adapter->tx_abs_int_delay);
+		ew32(TADV, adapter->tx_abs_int_delay);
 
 	/* Program the Transmit Control Register */
 
-	tctl = E1000_READ_REG(hw, TCTL);
+	tctl = er32(TCTL);
 	tctl &= ~E1000_TCTL_CT;
 	tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC |
 		(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
 
 	if (hw->mac_type == e1000_82571 || hw->mac_type == e1000_82572) {
-		tarc = E1000_READ_REG(hw, TARC0);
+		tarc = er32(TARC0);
 		/* set the speed mode bit, we'll clear it if we're not at
 		 * gigabit link later */
 		tarc |= (1 << 21);
-		E1000_WRITE_REG(hw, TARC0, tarc);
+		ew32(TARC0, tarc);
 	} else if (hw->mac_type == e1000_80003es2lan) {
-		tarc = E1000_READ_REG(hw, TARC0);
+		tarc = er32(TARC0);
 		tarc |= 1;
-		E1000_WRITE_REG(hw, TARC0, tarc);
-		tarc = E1000_READ_REG(hw, TARC1);
+		ew32(TARC0, tarc);
+		tarc = er32(TARC1);
 		tarc |= 1;
-		E1000_WRITE_REG(hw, TARC1, tarc);
+		ew32(TARC1, tarc);
 	}
 
 	e1000_config_collision_dist(hw);
@@ -1770,7 +1787,7 @@
 	    hw->bus_type == e1000_bus_type_pcix)
 		adapter->pcix_82544 = 1;
 
-	E1000_WRITE_REG(hw, TCTL, tctl);
+	ew32(TCTL, tctl);
 
 }
 
@@ -1782,10 +1799,10 @@
  * Returns 0 on success, negative on failure
  **/
 
-static int
-e1000_setup_rx_resources(struct e1000_adapter *adapter,
-                         struct e1000_rx_ring *rxdr)
+static int e1000_setup_rx_resources(struct e1000_adapter *adapter,
+				    struct e1000_rx_ring *rxdr)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	struct pci_dev *pdev = adapter->pdev;
 	int size, desc_len;
 
@@ -1818,7 +1835,7 @@
 		return -ENOMEM;
 	}
 
-	if (adapter->hw.mac_type <= e1000_82547_rev_2)
+	if (hw->mac_type <= e1000_82547_rev_2)
 		desc_len = sizeof(struct e1000_rx_desc);
 	else
 		desc_len = sizeof(union e1000_rx_desc_packet_split);
@@ -1887,8 +1904,7 @@
  * Return 0 on success, negative on failure
  **/
 
-int
-e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
+int e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
 {
 	int i, err = 0;
 
@@ -1913,24 +1929,24 @@
  **/
 #define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \
 			(((S) & (PAGE_SIZE - 1)) ? 1 : 0))
-static void
-e1000_setup_rctl(struct e1000_adapter *adapter)
+static void e1000_setup_rctl(struct e1000_adapter *adapter)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	u32 rctl, rfctl;
 	u32 psrctl = 0;
 #ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT
 	u32 pages = 0;
 #endif
 
-	rctl = E1000_READ_REG(&adapter->hw, RCTL);
+	rctl = er32(RCTL);
 
 	rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
 
 	rctl |= E1000_RCTL_EN | E1000_RCTL_BAM |
 		E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
-		(adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT);
+		(hw->mc_filter_type << E1000_RCTL_MO_SHIFT);
 
-	if (adapter->hw.tbi_compatibility_on == 1)
+	if (hw->tbi_compatibility_on == 1)
 		rctl |= E1000_RCTL_SBP;
 	else
 		rctl &= ~E1000_RCTL_SBP;
@@ -1983,7 +1999,7 @@
 	/* allocations using alloc_page take too long for regular MTU
 	 * so only enable packet split for jumbo frames */
 	pages = PAGE_USE_COUNT(adapter->netdev->mtu);
-	if ((adapter->hw.mac_type >= e1000_82571) && (pages <= 3) &&
+	if ((hw->mac_type >= e1000_82571) && (pages <= 3) &&
 	    PAGE_SIZE <= 16384 && (rctl & E1000_RCTL_LPE))
 		adapter->rx_ps_pages = pages;
 	else
@@ -1991,14 +2007,14 @@
 #endif
 	if (adapter->rx_ps_pages) {
 		/* Configure extra packet-split registers */
-		rfctl = E1000_READ_REG(&adapter->hw, RFCTL);
+		rfctl = er32(RFCTL);
 		rfctl |= E1000_RFCTL_EXTEN;
 		/* disable packet split support for IPv6 extension headers,
 		 * because some malformed IPv6 headers can hang the RX */
 		rfctl |= (E1000_RFCTL_IPV6_EX_DIS |
 		          E1000_RFCTL_NEW_IPV6_EXT_DIS);
 
-		E1000_WRITE_REG(&adapter->hw, RFCTL, rfctl);
+		ew32(RFCTL, rfctl);
 
 		rctl |= E1000_RCTL_DTYP_PS;
 
@@ -2018,10 +2034,10 @@
 			break;
 		}
 
-		E1000_WRITE_REG(&adapter->hw, PSRCTL, psrctl);
+		ew32(PSRCTL, psrctl);
 	}
 
-	E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+	ew32(RCTL, rctl);
 }
 
 /**
@@ -2031,8 +2047,7 @@
  * Configure the Rx unit of the MAC after a reset.
  **/
 
-static void
-e1000_configure_rx(struct e1000_adapter *adapter)
+static void e1000_configure_rx(struct e1000_adapter *adapter)
 {
 	u64 rdba;
 	struct e1000_hw *hw = &adapter->hw;
@@ -2052,30 +2067,27 @@
 	}
 
 	/* disable receives while setting up the descriptors */
-	rctl = E1000_READ_REG(hw, RCTL);
-	E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN);
+	rctl = er32(RCTL);
+	ew32(RCTL, rctl & ~E1000_RCTL_EN);
 
 	/* set the Receive Delay Timer Register */
-	E1000_WRITE_REG(hw, RDTR, adapter->rx_int_delay);
+	ew32(RDTR, adapter->rx_int_delay);
 
 	if (hw->mac_type >= e1000_82540) {
-		E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay);
+		ew32(RADV, adapter->rx_abs_int_delay);
 		if (adapter->itr_setting != 0)
-			E1000_WRITE_REG(hw, ITR,
-				1000000000 / (adapter->itr * 256));
+			ew32(ITR, 1000000000 / (adapter->itr * 256));
 	}
 
 	if (hw->mac_type >= e1000_82571) {
-		ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+		ctrl_ext = er32(CTRL_EXT);
 		/* Reset delay timers after every interrupt */
 		ctrl_ext |= E1000_CTRL_EXT_INT_TIMER_CLR;
-#ifdef CONFIG_E1000_NAPI
 		/* Auto-Mask interrupts upon ICR access */
 		ctrl_ext |= E1000_CTRL_EXT_IAME;
-		E1000_WRITE_REG(hw, IAM, 0xffffffff);
-#endif
-		E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
-		E1000_WRITE_FLUSH(hw);
+		ew32(IAM, 0xffffffff);
+		ew32(CTRL_EXT, ctrl_ext);
+		E1000_WRITE_FLUSH();
 	}
 
 	/* Setup the HW Rx Head and Tail Descriptor Pointers and
@@ -2084,11 +2096,11 @@
 	case 1:
 	default:
 		rdba = adapter->rx_ring[0].dma;
-		E1000_WRITE_REG(hw, RDLEN, rdlen);
-		E1000_WRITE_REG(hw, RDBAH, (rdba >> 32));
-		E1000_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL));
-		E1000_WRITE_REG(hw, RDT, 0);
-		E1000_WRITE_REG(hw, RDH, 0);
+		ew32(RDLEN, rdlen);
+		ew32(RDBAH, (rdba >> 32));
+		ew32(RDBAL, (rdba & 0x00000000ffffffffULL));
+		ew32(RDT, 0);
+		ew32(RDH, 0);
 		adapter->rx_ring[0].rdh = ((hw->mac_type >= e1000_82543) ? E1000_RDH : E1000_82542_RDH);
 		adapter->rx_ring[0].rdt = ((hw->mac_type >= e1000_82543) ? E1000_RDT : E1000_82542_RDT);
 		break;
@@ -2096,7 +2108,7 @@
 
 	/* Enable 82543 Receive Checksum Offload for TCP and UDP */
 	if (hw->mac_type >= e1000_82543) {
-		rxcsum = E1000_READ_REG(hw, RXCSUM);
+		rxcsum = er32(RXCSUM);
 		if (adapter->rx_csum) {
 			rxcsum |= E1000_RXCSUM_TUOFL;
 
@@ -2110,17 +2122,17 @@
 			rxcsum &= ~E1000_RXCSUM_TUOFL;
 			/* don't need to clear IPPCSE as it defaults to 0 */
 		}
-		E1000_WRITE_REG(hw, RXCSUM, rxcsum);
+		ew32(RXCSUM, rxcsum);
 	}
 
 	/* enable early receives on 82573, only takes effect if using > 2048
 	 * byte total frame size.  for example only for jumbo frames */
 #define E1000_ERT_2048 0x100
 	if (hw->mac_type == e1000_82573)
-		E1000_WRITE_REG(hw, ERT, E1000_ERT_2048);
+		ew32(ERT, E1000_ERT_2048);
 
 	/* Enable Receives */
-	E1000_WRITE_REG(hw, RCTL, rctl);
+	ew32(RCTL, rctl);
 }
 
 /**
@@ -2131,9 +2143,8 @@
  * Free all transmit software resources
  **/
 
-static void
-e1000_free_tx_resources(struct e1000_adapter *adapter,
-                        struct e1000_tx_ring *tx_ring)
+static void e1000_free_tx_resources(struct e1000_adapter *adapter,
+				    struct e1000_tx_ring *tx_ring)
 {
 	struct pci_dev *pdev = adapter->pdev;
 
@@ -2154,8 +2165,7 @@
  * Free all transmit software resources
  **/
 
-void
-e1000_free_all_tx_resources(struct e1000_adapter *adapter)
+void e1000_free_all_tx_resources(struct e1000_adapter *adapter)
 {
 	int i;
 
@@ -2163,9 +2173,8 @@
 		e1000_free_tx_resources(adapter, &adapter->tx_ring[i]);
 }
 
-static void
-e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
-			struct e1000_buffer *buffer_info)
+static void e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
+					     struct e1000_buffer *buffer_info)
 {
 	if (buffer_info->dma) {
 		pci_unmap_page(adapter->pdev,
@@ -2187,10 +2196,10 @@
  * @tx_ring: ring to be cleaned
  **/
 
-static void
-e1000_clean_tx_ring(struct e1000_adapter *adapter,
-                    struct e1000_tx_ring *tx_ring)
+static void e1000_clean_tx_ring(struct e1000_adapter *adapter,
+				struct e1000_tx_ring *tx_ring)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	struct e1000_buffer *buffer_info;
 	unsigned long size;
 	unsigned int i;
@@ -2213,8 +2222,8 @@
 	tx_ring->next_to_clean = 0;
 	tx_ring->last_tx_tso = 0;
 
-	writel(0, adapter->hw.hw_addr + tx_ring->tdh);
-	writel(0, adapter->hw.hw_addr + tx_ring->tdt);
+	writel(0, hw->hw_addr + tx_ring->tdh);
+	writel(0, hw->hw_addr + tx_ring->tdt);
 }
 
 /**
@@ -2222,8 +2231,7 @@
  * @adapter: board private structure
  **/
 
-static void
-e1000_clean_all_tx_rings(struct e1000_adapter *adapter)
+static void e1000_clean_all_tx_rings(struct e1000_adapter *adapter)
 {
 	int i;
 
@@ -2239,9 +2247,8 @@
  * Free all receive software resources
  **/
 
-static void
-e1000_free_rx_resources(struct e1000_adapter *adapter,
-                        struct e1000_rx_ring *rx_ring)
+static void e1000_free_rx_resources(struct e1000_adapter *adapter,
+				    struct e1000_rx_ring *rx_ring)
 {
 	struct pci_dev *pdev = adapter->pdev;
 
@@ -2266,8 +2273,7 @@
  * Free all receive software resources
  **/
 
-void
-e1000_free_all_rx_resources(struct e1000_adapter *adapter)
+void e1000_free_all_rx_resources(struct e1000_adapter *adapter)
 {
 	int i;
 
@@ -2281,10 +2287,10 @@
  * @rx_ring: ring to free buffers from
  **/
 
-static void
-e1000_clean_rx_ring(struct e1000_adapter *adapter,
-                    struct e1000_rx_ring *rx_ring)
+static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
+				struct e1000_rx_ring *rx_ring)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	struct e1000_buffer *buffer_info;
 	struct e1000_ps_page *ps_page;
 	struct e1000_ps_page_dma *ps_page_dma;
@@ -2331,8 +2337,8 @@
 	rx_ring->next_to_clean = 0;
 	rx_ring->next_to_use = 0;
 
-	writel(0, adapter->hw.hw_addr + rx_ring->rdh);
-	writel(0, adapter->hw.hw_addr + rx_ring->rdt);
+	writel(0, hw->hw_addr + rx_ring->rdh);
+	writel(0, hw->hw_addr + rx_ring->rdt);
 }
 
 /**
@@ -2340,8 +2346,7 @@
  * @adapter: board private structure
  **/
 
-static void
-e1000_clean_all_rx_rings(struct e1000_adapter *adapter)
+static void e1000_clean_all_rx_rings(struct e1000_adapter *adapter)
 {
 	int i;
 
@@ -2352,38 +2357,38 @@
 /* The 82542 2.0 (revision 2) needs to have the receive unit in reset
  * and memory write and invalidate disabled for certain operations
  */
-static void
-e1000_enter_82542_rst(struct e1000_adapter *adapter)
+static void e1000_enter_82542_rst(struct e1000_adapter *adapter)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
 	u32 rctl;
 
-	e1000_pci_clear_mwi(&adapter->hw);
+	e1000_pci_clear_mwi(hw);
 
-	rctl = E1000_READ_REG(&adapter->hw, RCTL);
+	rctl = er32(RCTL);
 	rctl |= E1000_RCTL_RST;
-	E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
-	E1000_WRITE_FLUSH(&adapter->hw);
+	ew32(RCTL, rctl);
+	E1000_WRITE_FLUSH();
 	mdelay(5);
 
 	if (netif_running(netdev))
 		e1000_clean_all_rx_rings(adapter);
 }
 
-static void
-e1000_leave_82542_rst(struct e1000_adapter *adapter)
+static void e1000_leave_82542_rst(struct e1000_adapter *adapter)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
 	u32 rctl;
 
-	rctl = E1000_READ_REG(&adapter->hw, RCTL);
+	rctl = er32(RCTL);
 	rctl &= ~E1000_RCTL_RST;
-	E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
-	E1000_WRITE_FLUSH(&adapter->hw);
+	ew32(RCTL, rctl);
+	E1000_WRITE_FLUSH();
 	mdelay(5);
 
-	if (adapter->hw.pci_cmd_word & PCI_COMMAND_INVALIDATE)
-		e1000_pci_set_mwi(&adapter->hw);
+	if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
+		e1000_pci_set_mwi(hw);
 
 	if (netif_running(netdev)) {
 		/* No need to loop, because 82542 supports only 1 queue */
@@ -2401,10 +2406,10 @@
  * Returns 0 on success, negative on failure
  **/
 
-static int
-e1000_set_mac(struct net_device *netdev, void *p)
+static int e1000_set_mac(struct net_device *netdev, void *p)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
 	struct sockaddr *addr = p;
 
 	if (!is_valid_ether_addr(addr->sa_data))
@@ -2412,19 +2417,19 @@
 
 	/* 82542 2.0 needs to be in reset to write receive address registers */
 
-	if (adapter->hw.mac_type == e1000_82542_rev2_0)
+	if (hw->mac_type == e1000_82542_rev2_0)
 		e1000_enter_82542_rst(adapter);
 
 	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-	memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
+	memcpy(hw->mac_addr, addr->sa_data, netdev->addr_len);
 
-	e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, 0);
+	e1000_rar_set(hw, hw->mac_addr, 0);
 
 	/* With 82571 controllers, LAA may be overwritten (with the default)
 	 * due to controller reset from the other port. */
-	if (adapter->hw.mac_type == e1000_82571) {
+	if (hw->mac_type == e1000_82571) {
 		/* activate the work around */
-		adapter->hw.laa_is_present = 1;
+		hw->laa_is_present = 1;
 
 		/* Hold a copy of the LAA in RAR[14] This is done so that
 		 * between the time RAR[0] gets clobbered  and the time it
@@ -2432,11 +2437,11 @@
 		 * of the RARs and no incoming packets directed to this port
 		 * are dropped. Eventaully the LAA will be in RAR[0] and
 		 * RAR[14] */
-		e1000_rar_set(&adapter->hw, adapter->hw.mac_addr,
+		e1000_rar_set(hw, hw->mac_addr,
 					E1000_RAR_ENTRIES - 1);
 	}
 
-	if (adapter->hw.mac_type == e1000_82542_rev2_0)
+	if (hw->mac_type == e1000_82542_rev2_0)
 		e1000_leave_82542_rst(adapter);
 
 	return 0;
@@ -2452,8 +2457,7 @@
  * promiscuous mode, and all-multi behavior.
  **/
 
-static void
-e1000_set_rx_mode(struct net_device *netdev)
+static void e1000_set_rx_mode(struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
@@ -2466,16 +2470,16 @@
 				E1000_NUM_MTA_REGISTERS_ICH8LAN :
 				E1000_NUM_MTA_REGISTERS;
 
-	if (adapter->hw.mac_type == e1000_ich8lan)
+	if (hw->mac_type == e1000_ich8lan)
 		rar_entries = E1000_RAR_ENTRIES_ICH8LAN;
 
 	/* reserve RAR[14] for LAA over-write work-around */
-	if (adapter->hw.mac_type == e1000_82571)
+	if (hw->mac_type == e1000_82571)
 		rar_entries--;
 
 	/* Check for Promiscuous and All Multicast modes */
 
-	rctl = E1000_READ_REG(hw, RCTL);
+	rctl = er32(RCTL);
 
 	if (netdev->flags & IFF_PROMISC) {
 		rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
@@ -2498,7 +2502,7 @@
 		uc_ptr = netdev->uc_list;
 	}
 
-	E1000_WRITE_REG(hw, RCTL, rctl);
+	ew32(RCTL, rctl);
 
 	/* 82542 2.0 needs to be in reset to write receive address registers */
 
@@ -2524,9 +2528,9 @@
 			mc_ptr = mc_ptr->next;
 		} else {
 			E1000_WRITE_REG_ARRAY(hw, RA, i << 1, 0);
-			E1000_WRITE_FLUSH(hw);
+			E1000_WRITE_FLUSH();
 			E1000_WRITE_REG_ARRAY(hw, RA, (i << 1) + 1, 0);
-			E1000_WRITE_FLUSH(hw);
+			E1000_WRITE_FLUSH();
 		}
 	}
 	WARN_ON(uc_ptr != NULL);
@@ -2535,7 +2539,7 @@
 
 	for (i = 0; i < mta_reg_count; i++) {
 		E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
-		E1000_WRITE_FLUSH(hw);
+		E1000_WRITE_FLUSH();
 	}
 
 	/* load any remaining addresses into the hash table */
@@ -2552,11 +2556,11 @@
 /* Need to wait a few seconds after link up to get diagnostic information from
  * the phy */
 
-static void
-e1000_update_phy_info(unsigned long data)
+static void e1000_update_phy_info(unsigned long data)
 {
-	struct e1000_adapter *adapter = (struct e1000_adapter *) data;
-	e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
+	struct e1000_adapter *adapter = (struct e1000_adapter *)data;
+	struct e1000_hw *hw = &adapter->hw;
+	e1000_phy_get_info(hw, &adapter->phy_info);
 }
 
 /**
@@ -2564,33 +2568,25 @@
  * @data: pointer to adapter cast into an unsigned long
  **/
 
-static void
-e1000_82547_tx_fifo_stall(unsigned long data)
+static void e1000_82547_tx_fifo_stall(unsigned long data)
 {
-	struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+	struct e1000_adapter *adapter = (struct e1000_adapter *)data;
+	struct e1000_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
 	u32 tctl;
 
 	if (atomic_read(&adapter->tx_fifo_stall)) {
-		if ((E1000_READ_REG(&adapter->hw, TDT) ==
-		    E1000_READ_REG(&adapter->hw, TDH)) &&
-		   (E1000_READ_REG(&adapter->hw, TDFT) ==
-		    E1000_READ_REG(&adapter->hw, TDFH)) &&
-		   (E1000_READ_REG(&adapter->hw, TDFTS) ==
-		    E1000_READ_REG(&adapter->hw, TDFHS))) {
-			tctl = E1000_READ_REG(&adapter->hw, TCTL);
-			E1000_WRITE_REG(&adapter->hw, TCTL,
-					tctl & ~E1000_TCTL_EN);
-			E1000_WRITE_REG(&adapter->hw, TDFT,
-					adapter->tx_head_addr);
-			E1000_WRITE_REG(&adapter->hw, TDFH,
-					adapter->tx_head_addr);
-			E1000_WRITE_REG(&adapter->hw, TDFTS,
-					adapter->tx_head_addr);
-			E1000_WRITE_REG(&adapter->hw, TDFHS,
-					adapter->tx_head_addr);
-			E1000_WRITE_REG(&adapter->hw, TCTL, tctl);
-			E1000_WRITE_FLUSH(&adapter->hw);
+		if ((er32(TDT) == er32(TDH)) &&
+		   (er32(TDFT) == er32(TDFH)) &&
+		   (er32(TDFTS) == er32(TDFHS))) {
+			tctl = er32(TCTL);
+			ew32(TCTL, tctl & ~E1000_TCTL_EN);
+			ew32(TDFT, adapter->tx_head_addr);
+			ew32(TDFH, adapter->tx_head_addr);
+			ew32(TDFTS, adapter->tx_head_addr);
+			ew32(TDFHS, adapter->tx_head_addr);
+			ew32(TCTL, tctl);
+			E1000_WRITE_FLUSH();
 
 			adapter->tx_fifo_head = 0;
 			atomic_set(&adapter->tx_fifo_stall, 0);
@@ -2605,45 +2601,45 @@
  * e1000_watchdog - Timer Call-back
  * @data: pointer to adapter cast into an unsigned long
  **/
-static void
-e1000_watchdog(unsigned long data)
+static void e1000_watchdog(unsigned long data)
 {
-	struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+	struct e1000_adapter *adapter = (struct e1000_adapter *)data;
+	struct e1000_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
 	struct e1000_tx_ring *txdr = adapter->tx_ring;
 	u32 link, tctl;
 	s32 ret_val;
 
-	ret_val = e1000_check_for_link(&adapter->hw);
+	ret_val = e1000_check_for_link(hw);
 	if ((ret_val == E1000_ERR_PHY) &&
-	    (adapter->hw.phy_type == e1000_phy_igp_3) &&
-	    (E1000_READ_REG(&adapter->hw, CTRL) & E1000_PHY_CTRL_GBE_DISABLE)) {
+	    (hw->phy_type == e1000_phy_igp_3) &&
+	    (er32(CTRL) & E1000_PHY_CTRL_GBE_DISABLE)) {
 		/* See e1000_kumeran_lock_loss_workaround() */
 		DPRINTK(LINK, INFO,
 			"Gigabit has been disabled, downgrading speed\n");
 	}
 
-	if (adapter->hw.mac_type == e1000_82573) {
-		e1000_enable_tx_pkt_filtering(&adapter->hw);
-		if (adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id)
+	if (hw->mac_type == e1000_82573) {
+		e1000_enable_tx_pkt_filtering(hw);
+		if (adapter->mng_vlan_id != hw->mng_cookie.vlan_id)
 			e1000_update_mng_vlan(adapter);
 	}
 
-	if ((adapter->hw.media_type == e1000_media_type_internal_serdes) &&
-	   !(E1000_READ_REG(&adapter->hw, TXCW) & E1000_TXCW_ANE))
-		link = !adapter->hw.serdes_link_down;
+	if ((hw->media_type == e1000_media_type_internal_serdes) &&
+	   !(er32(TXCW) & E1000_TXCW_ANE))
+		link = !hw->serdes_link_down;
 	else
-		link = E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU;
+		link = er32(STATUS) & E1000_STATUS_LU;
 
 	if (link) {
 		if (!netif_carrier_ok(netdev)) {
 			u32 ctrl;
 			bool txb2b = true;
-			e1000_get_speed_and_duplex(&adapter->hw,
+			e1000_get_speed_and_duplex(hw,
 			                           &adapter->link_speed,
 			                           &adapter->link_duplex);
 
-			ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+			ctrl = er32(CTRL);
 			DPRINTK(LINK, INFO, "NIC Link is Up %d Mbps %s, "
 			        "Flow Control: %s\n",
 			        adapter->link_speed,
@@ -2671,19 +2667,19 @@
 				break;
 			}
 
-			if ((adapter->hw.mac_type == e1000_82571 ||
-			     adapter->hw.mac_type == e1000_82572) &&
+			if ((hw->mac_type == e1000_82571 ||
+			     hw->mac_type == e1000_82572) &&
 			    !txb2b) {
 				u32 tarc0;
-				tarc0 = E1000_READ_REG(&adapter->hw, TARC0);
+				tarc0 = er32(TARC0);
 				tarc0 &= ~(1 << 21);
-				E1000_WRITE_REG(&adapter->hw, TARC0, tarc0);
+				ew32(TARC0, tarc0);
 			}
 
 			/* disable TSO for pcie and 10/100 speeds, to avoid
 			 * some hardware issues */
 			if (!adapter->tso_force &&
-			    adapter->hw.bus_type == e1000_bus_type_pci_express){
+			    hw->bus_type == e1000_bus_type_pci_express){
 				switch (adapter->link_speed) {
 				case SPEED_10:
 				case SPEED_100:
@@ -2704,9 +2700,9 @@
 
 			/* enable transmits in the hardware, need to do this
 			 * after setting TARC0 */
-			tctl = E1000_READ_REG(&adapter->hw, TCTL);
+			tctl = er32(TCTL);
 			tctl |= E1000_TCTL_EN;
-			E1000_WRITE_REG(&adapter->hw, TCTL, tctl);
+			ew32(TCTL, tctl);
 
 			netif_carrier_on(netdev);
 			netif_wake_queue(netdev);
@@ -2714,10 +2710,9 @@
 			adapter->smartspeed = 0;
 		} else {
 			/* make sure the receive unit is started */
-			if (adapter->hw.rx_needs_kicking) {
-				struct e1000_hw *hw = &adapter->hw;
-				u32 rctl = E1000_READ_REG(hw, RCTL);
-				E1000_WRITE_REG(hw, RCTL, rctl | E1000_RCTL_EN);
+			if (hw->rx_needs_kicking) {
+				u32 rctl = er32(RCTL);
+				ew32(RCTL, rctl | E1000_RCTL_EN);
 			}
 		}
 	} else {
@@ -2734,7 +2729,7 @@
 			 * disable receives in the ISR and
 			 * reset device here in the watchdog
 			 */
-			if (adapter->hw.mac_type == e1000_80003es2lan)
+			if (hw->mac_type == e1000_80003es2lan)
 				/* reset device */
 				schedule_work(&adapter->reset_task);
 		}
@@ -2744,9 +2739,9 @@
 
 	e1000_update_stats(adapter);
 
-	adapter->hw.tx_packet_delta = adapter->stats.tpt - adapter->tpt_old;
+	hw->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old;
 	adapter->tpt_old = adapter->stats.tpt;
-	adapter->hw.collision_delta = adapter->stats.colc - adapter->colc_old;
+	hw->collision_delta = adapter->stats.colc - adapter->colc_old;
 	adapter->colc_old = adapter->stats.colc;
 
 	adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old;
@@ -2754,7 +2749,7 @@
 	adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old;
 	adapter->gotcl_old = adapter->stats.gotcl;
 
-	e1000_update_adaptive(&adapter->hw);
+	e1000_update_adaptive(hw);
 
 	if (!netif_carrier_ok(netdev)) {
 		if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
@@ -2768,15 +2763,15 @@
 	}
 
 	/* Cause software interrupt to ensure rx ring is cleaned */
-	E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0);
+	ew32(ICS, E1000_ICS_RXDMT0);
 
 	/* Force detection of hung controller every watchdog period */
 	adapter->detect_tx_hung = true;
 
 	/* With 82571 controllers, LAA may be overwritten due to controller
 	 * reset from the other port. Set the appropriate LAA in RAR[0] */
-	if (adapter->hw.mac_type == e1000_82571 && adapter->hw.laa_is_present)
-		e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, 0);
+	if (hw->mac_type == e1000_82571 && hw->laa_is_present)
+		e1000_rar_set(hw, hw->mac_addr, 0);
 
 	/* Reset the timer */
 	mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + 2 * HZ));
@@ -2806,9 +2801,7 @@
  * @bytes: the number of bytes during this measurement interval
  **/
 static unsigned int e1000_update_itr(struct e1000_adapter *adapter,
-                                   u16 itr_setting,
-                                   int packets,
-                                   int bytes)
+				     u16 itr_setting, int packets, int bytes)
 {
 	unsigned int retval = itr_setting;
 	struct e1000_hw *hw = &adapter->hw;
@@ -2913,7 +2906,7 @@
 		             min(adapter->itr + (new_itr >> 2), new_itr) :
 		             new_itr;
 		adapter->itr = new_itr;
-		E1000_WRITE_REG(hw, ITR, 1000000000 / (new_itr * 256));
+		ew32(ITR, 1000000000 / (new_itr * 256));
 	}
 
 	return;
@@ -2926,9 +2919,8 @@
 #define E1000_TX_FLAGS_VLAN_MASK	0xffff0000
 #define E1000_TX_FLAGS_VLAN_SHIFT	16
 
-static int
-e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
-          struct sk_buff *skb)
+static int e1000_tso(struct e1000_adapter *adapter,
+		     struct e1000_tx_ring *tx_ring, struct sk_buff *skb)
 {
 	struct e1000_context_desc *context_desc;
 	struct e1000_buffer *buffer_info;
@@ -2999,9 +2991,8 @@
 	return false;
 }
 
-static bool
-e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
-              struct sk_buff *skb)
+static bool e1000_tx_csum(struct e1000_adapter *adapter,
+			  struct e1000_tx_ring *tx_ring, struct sk_buff *skb)
 {
 	struct e1000_context_desc *context_desc;
 	struct e1000_buffer *buffer_info;
@@ -3038,11 +3029,13 @@
 #define E1000_MAX_TXD_PWR	12
 #define E1000_MAX_DATA_PER_TXD	(1<<E1000_MAX_TXD_PWR)
 
-static int
-e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
-             struct sk_buff *skb, unsigned int first, unsigned int max_per_txd,
-             unsigned int nr_frags, unsigned int mss)
+static int e1000_tx_map(struct e1000_adapter *adapter,
+			struct e1000_tx_ring *tx_ring,
+			struct sk_buff *skb, unsigned int first,
+			unsigned int max_per_txd, unsigned int nr_frags,
+			unsigned int mss)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	struct e1000_buffer *buffer_info;
 	unsigned int len = skb->len;
 	unsigned int offset = 0, size, count = 0, i;
@@ -3073,7 +3066,7 @@
 		 * The fix is to make sure that the first descriptor of a
 		 * packet is smaller than 2048 - 16 - 16 (or 2016) bytes
 		 */
-		if (unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) &&
+		if (unlikely((hw->bus_type == e1000_bus_type_pcix) &&
 		                (size > 2015) && count == 0))
 		        size = 2015;
 
@@ -3145,10 +3138,11 @@
 	return count;
 }
 
-static void
-e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
-               int tx_flags, int count)
+static void e1000_tx_queue(struct e1000_adapter *adapter,
+			   struct e1000_tx_ring *tx_ring, int tx_flags,
+			   int count)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	struct e1000_tx_desc *tx_desc = NULL;
 	struct e1000_buffer *buffer_info;
 	u32 txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
@@ -3194,7 +3188,7 @@
 	wmb();
 
 	tx_ring->next_to_use = i;
-	writel(i, adapter->hw.hw_addr + tx_ring->tdt);
+	writel(i, hw->hw_addr + tx_ring->tdt);
 	/* we need this if more than one processor can write to our tail
 	 * at a time, it syncronizes IO on IA64/Altix systems */
 	mmiowb();
@@ -3212,8 +3206,8 @@
 #define E1000_FIFO_HDR			0x10
 #define E1000_82547_PAD_LEN		0x3E0
 
-static int
-e1000_82547_fifo_workaround(struct e1000_adapter *adapter, struct sk_buff *skb)
+static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
+				       struct sk_buff *skb)
 {
 	u32 fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head;
 	u32 skb_fifo_len = skb->len + E1000_FIFO_HDR;
@@ -3239,19 +3233,19 @@
 }
 
 #define MINIMUM_DHCP_PACKET_SIZE 282
-static int
-e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb)
+static int e1000_transfer_dhcp_info(struct e1000_adapter *adapter,
+				    struct sk_buff *skb)
 {
 	struct e1000_hw *hw =  &adapter->hw;
 	u16 length, offset;
 	if (vlan_tx_tag_present(skb)) {
-		if (!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) &&
-			( adapter->hw.mng_cookie.status &
+		if (!((vlan_tx_tag_get(skb) == hw->mng_cookie.vlan_id) &&
+			( hw->mng_cookie.status &
 			  E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) )
 			return 0;
 	}
 	if (skb->len > MINIMUM_DHCP_PACKET_SIZE) {
-		struct ethhdr *eth = (struct ethhdr *) skb->data;
+		struct ethhdr *eth = (struct ethhdr *)skb->data;
 		if ((htons(ETH_P_IP) == eth->h_proto)) {
 			const struct iphdr *ip =
 				(struct iphdr *)((u8 *)skb->data+14);
@@ -3304,10 +3298,10 @@
 }
 
 #define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 )
-static int
-e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
 	struct e1000_tx_ring *tx_ring;
 	unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD;
 	unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
@@ -3333,7 +3327,7 @@
 
 	/* 82571 and newer doesn't need the workaround that limited descriptor
 	 * length to 4kB */
-	if (adapter->hw.mac_type >= e1000_82571)
+	if (hw->mac_type >= e1000_82571)
 		max_per_txd = 8192;
 
 	mss = skb_shinfo(skb)->gso_size;
@@ -3353,7 +3347,7 @@
 		* frags into skb->data */
 		hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
 		if (skb->data_len && hdr_len == len) {
-			switch (adapter->hw.mac_type) {
+			switch (hw->mac_type) {
 				unsigned int pull_size;
 			case e1000_82544:
 				/* Make sure we have room to chop off 4 bytes,
@@ -3402,7 +3396,7 @@
 	/* work-around for errata 10 and it applies to all controllers
 	 * in PCI-X mode, so add one more descriptor to the count
 	 */
-	if (unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) &&
+	if (unlikely((hw->bus_type == e1000_bus_type_pcix) &&
 			(len > 2015)))
 		count++;
 
@@ -3414,8 +3408,8 @@
 		count += nr_frags;
 
 
-	if (adapter->hw.tx_pkt_filtering &&
-	    (adapter->hw.mac_type == e1000_82573))
+	if (hw->tx_pkt_filtering &&
+	    (hw->mac_type == e1000_82573))
 		e1000_transfer_dhcp_info(adapter, skb);
 
 	if (!spin_trylock_irqsave(&tx_ring->tx_lock, flags))
@@ -3429,7 +3423,7 @@
 		return NETDEV_TX_BUSY;
 	}
 
-	if (unlikely(adapter->hw.mac_type == e1000_82547)) {
+	if (unlikely(hw->mac_type == e1000_82547)) {
 		if (unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
 			netif_stop_queue(netdev);
 			mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1);
@@ -3482,8 +3476,7 @@
  * @netdev: network interface device structure
  **/
 
-static void
-e1000_tx_timeout(struct net_device *netdev)
+static void e1000_tx_timeout(struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 
@@ -3492,8 +3485,7 @@
 	schedule_work(&adapter->reset_task);
 }
 
-static void
-e1000_reset_task(struct work_struct *work)
+static void e1000_reset_task(struct work_struct *work)
 {
 	struct e1000_adapter *adapter =
 		container_of(work, struct e1000_adapter, reset_task);
@@ -3509,8 +3501,7 @@
  * The statistics are actually updated from the timer callback.
  **/
 
-static struct net_device_stats *
-e1000_get_stats(struct net_device *netdev)
+static struct net_device_stats *e1000_get_stats(struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 
@@ -3526,10 +3517,10 @@
  * Returns 0 on success, negative on failure
  **/
 
-static int
-e1000_change_mtu(struct net_device *netdev, int new_mtu)
+static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
 	int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
 	u16 eeprom_data = 0;
 
@@ -3540,7 +3531,7 @@
 	}
 
 	/* Adapter-specific max frame size limits. */
-	switch (adapter->hw.mac_type) {
+	switch (hw->mac_type) {
 	case e1000_undefined ... e1000_82542_rev2_1:
 	case e1000_ich8lan:
 		if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
@@ -3552,9 +3543,9 @@
 		/* Jumbo Frames not supported if:
 		 * - this is not an 82573L device
 		 * - ASPM is enabled in any way (0x1A bits 3:2) */
-		e1000_read_eeprom(&adapter->hw, EEPROM_INIT_3GIO_3, 1,
+		e1000_read_eeprom(hw, EEPROM_INIT_3GIO_3, 1,
 		                  &eeprom_data);
-		if ((adapter->hw.device_id != E1000_DEV_ID_82573L) ||
+		if ((hw->device_id != E1000_DEV_ID_82573L) ||
 		    (eeprom_data & EEPROM_WORD1A_ASPM_MASK)) {
 			if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
 				DPRINTK(PROBE, ERR,
@@ -3601,13 +3592,13 @@
 		adapter->rx_buffer_len = E1000_RXBUFFER_16384;
 
 	/* adjust allocation if LPE protects us, and we aren't using SBP */
-	if (!adapter->hw.tbi_compatibility_on &&
+	if (!hw->tbi_compatibility_on &&
 	    ((max_frame == MAXIMUM_ETHERNET_FRAME_SIZE) ||
 	     (max_frame == MAXIMUM_ETHERNET_VLAN_SIZE)))
 		adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
 
 	netdev->mtu = new_mtu;
-	adapter->hw.max_frame_size = max_frame;
+	hw->max_frame_size = max_frame;
 
 	if (netif_running(netdev))
 		e1000_reinit_locked(adapter);
@@ -3620,8 +3611,7 @@
  * @adapter: board private structure
  **/
 
-void
-e1000_update_stats(struct e1000_adapter *adapter)
+void e1000_update_stats(struct e1000_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
 	struct pci_dev *pdev = adapter->pdev;
@@ -3646,89 +3636,89 @@
 	 * be written while holding adapter->stats_lock
 	 */
 
-	adapter->stats.crcerrs += E1000_READ_REG(hw, CRCERRS);
-	adapter->stats.gprc += E1000_READ_REG(hw, GPRC);
-	adapter->stats.gorcl += E1000_READ_REG(hw, GORCL);
-	adapter->stats.gorch += E1000_READ_REG(hw, GORCH);
-	adapter->stats.bprc += E1000_READ_REG(hw, BPRC);
-	adapter->stats.mprc += E1000_READ_REG(hw, MPRC);
-	adapter->stats.roc += E1000_READ_REG(hw, ROC);
+	adapter->stats.crcerrs += er32(CRCERRS);
+	adapter->stats.gprc += er32(GPRC);
+	adapter->stats.gorcl += er32(GORCL);
+	adapter->stats.gorch += er32(GORCH);
+	adapter->stats.bprc += er32(BPRC);
+	adapter->stats.mprc += er32(MPRC);
+	adapter->stats.roc += er32(ROC);
 
-	if (adapter->hw.mac_type != e1000_ich8lan) {
-		adapter->stats.prc64 += E1000_READ_REG(hw, PRC64);
-		adapter->stats.prc127 += E1000_READ_REG(hw, PRC127);
-		adapter->stats.prc255 += E1000_READ_REG(hw, PRC255);
-		adapter->stats.prc511 += E1000_READ_REG(hw, PRC511);
-		adapter->stats.prc1023 += E1000_READ_REG(hw, PRC1023);
-		adapter->stats.prc1522 += E1000_READ_REG(hw, PRC1522);
+	if (hw->mac_type != e1000_ich8lan) {
+		adapter->stats.prc64 += er32(PRC64);
+		adapter->stats.prc127 += er32(PRC127);
+		adapter->stats.prc255 += er32(PRC255);
+		adapter->stats.prc511 += er32(PRC511);
+		adapter->stats.prc1023 += er32(PRC1023);
+		adapter->stats.prc1522 += er32(PRC1522);
 	}
 
-	adapter->stats.symerrs += E1000_READ_REG(hw, SYMERRS);
-	adapter->stats.mpc += E1000_READ_REG(hw, MPC);
-	adapter->stats.scc += E1000_READ_REG(hw, SCC);
-	adapter->stats.ecol += E1000_READ_REG(hw, ECOL);
-	adapter->stats.mcc += E1000_READ_REG(hw, MCC);
-	adapter->stats.latecol += E1000_READ_REG(hw, LATECOL);
-	adapter->stats.dc += E1000_READ_REG(hw, DC);
-	adapter->stats.sec += E1000_READ_REG(hw, SEC);
-	adapter->stats.rlec += E1000_READ_REG(hw, RLEC);
-	adapter->stats.xonrxc += E1000_READ_REG(hw, XONRXC);
-	adapter->stats.xontxc += E1000_READ_REG(hw, XONTXC);
-	adapter->stats.xoffrxc += E1000_READ_REG(hw, XOFFRXC);
-	adapter->stats.xofftxc += E1000_READ_REG(hw, XOFFTXC);
-	adapter->stats.fcruc += E1000_READ_REG(hw, FCRUC);
-	adapter->stats.gptc += E1000_READ_REG(hw, GPTC);
-	adapter->stats.gotcl += E1000_READ_REG(hw, GOTCL);
-	adapter->stats.gotch += E1000_READ_REG(hw, GOTCH);
-	adapter->stats.rnbc += E1000_READ_REG(hw, RNBC);
-	adapter->stats.ruc += E1000_READ_REG(hw, RUC);
-	adapter->stats.rfc += E1000_READ_REG(hw, RFC);
-	adapter->stats.rjc += E1000_READ_REG(hw, RJC);
-	adapter->stats.torl += E1000_READ_REG(hw, TORL);
-	adapter->stats.torh += E1000_READ_REG(hw, TORH);
-	adapter->stats.totl += E1000_READ_REG(hw, TOTL);
-	adapter->stats.toth += E1000_READ_REG(hw, TOTH);
-	adapter->stats.tpr += E1000_READ_REG(hw, TPR);
+	adapter->stats.symerrs += er32(SYMERRS);
+	adapter->stats.mpc += er32(MPC);
+	adapter->stats.scc += er32(SCC);
+	adapter->stats.ecol += er32(ECOL);
+	adapter->stats.mcc += er32(MCC);
+	adapter->stats.latecol += er32(LATECOL);
+	adapter->stats.dc += er32(DC);
+	adapter->stats.sec += er32(SEC);
+	adapter->stats.rlec += er32(RLEC);
+	adapter->stats.xonrxc += er32(XONRXC);
+	adapter->stats.xontxc += er32(XONTXC);
+	adapter->stats.xoffrxc += er32(XOFFRXC);
+	adapter->stats.xofftxc += er32(XOFFTXC);
+	adapter->stats.fcruc += er32(FCRUC);
+	adapter->stats.gptc += er32(GPTC);
+	adapter->stats.gotcl += er32(GOTCL);
+	adapter->stats.gotch += er32(GOTCH);
+	adapter->stats.rnbc += er32(RNBC);
+	adapter->stats.ruc += er32(RUC);
+	adapter->stats.rfc += er32(RFC);
+	adapter->stats.rjc += er32(RJC);
+	adapter->stats.torl += er32(TORL);
+	adapter->stats.torh += er32(TORH);
+	adapter->stats.totl += er32(TOTL);
+	adapter->stats.toth += er32(TOTH);
+	adapter->stats.tpr += er32(TPR);
 
-	if (adapter->hw.mac_type != e1000_ich8lan) {
-		adapter->stats.ptc64 += E1000_READ_REG(hw, PTC64);
-		adapter->stats.ptc127 += E1000_READ_REG(hw, PTC127);
-		adapter->stats.ptc255 += E1000_READ_REG(hw, PTC255);
-		adapter->stats.ptc511 += E1000_READ_REG(hw, PTC511);
-		adapter->stats.ptc1023 += E1000_READ_REG(hw, PTC1023);
-		adapter->stats.ptc1522 += E1000_READ_REG(hw, PTC1522);
+	if (hw->mac_type != e1000_ich8lan) {
+		adapter->stats.ptc64 += er32(PTC64);
+		adapter->stats.ptc127 += er32(PTC127);
+		adapter->stats.ptc255 += er32(PTC255);
+		adapter->stats.ptc511 += er32(PTC511);
+		adapter->stats.ptc1023 += er32(PTC1023);
+		adapter->stats.ptc1522 += er32(PTC1522);
 	}
 
-	adapter->stats.mptc += E1000_READ_REG(hw, MPTC);
-	adapter->stats.bptc += E1000_READ_REG(hw, BPTC);
+	adapter->stats.mptc += er32(MPTC);
+	adapter->stats.bptc += er32(BPTC);
 
 	/* used for adaptive IFS */
 
-	hw->tx_packet_delta = E1000_READ_REG(hw, TPT);
+	hw->tx_packet_delta = er32(TPT);
 	adapter->stats.tpt += hw->tx_packet_delta;
-	hw->collision_delta = E1000_READ_REG(hw, COLC);
+	hw->collision_delta = er32(COLC);
 	adapter->stats.colc += hw->collision_delta;
 
 	if (hw->mac_type >= e1000_82543) {
-		adapter->stats.algnerrc += E1000_READ_REG(hw, ALGNERRC);
-		adapter->stats.rxerrc += E1000_READ_REG(hw, RXERRC);
-		adapter->stats.tncrs += E1000_READ_REG(hw, TNCRS);
-		adapter->stats.cexterr += E1000_READ_REG(hw, CEXTERR);
-		adapter->stats.tsctc += E1000_READ_REG(hw, TSCTC);
-		adapter->stats.tsctfc += E1000_READ_REG(hw, TSCTFC);
+		adapter->stats.algnerrc += er32(ALGNERRC);
+		adapter->stats.rxerrc += er32(RXERRC);
+		adapter->stats.tncrs += er32(TNCRS);
+		adapter->stats.cexterr += er32(CEXTERR);
+		adapter->stats.tsctc += er32(TSCTC);
+		adapter->stats.tsctfc += er32(TSCTFC);
 	}
 	if (hw->mac_type > e1000_82547_rev_2) {
-		adapter->stats.iac += E1000_READ_REG(hw, IAC);
-		adapter->stats.icrxoc += E1000_READ_REG(hw, ICRXOC);
+		adapter->stats.iac += er32(IAC);
+		adapter->stats.icrxoc += er32(ICRXOC);
 
-		if (adapter->hw.mac_type != e1000_ich8lan) {
-			adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC);
-			adapter->stats.icrxatc += E1000_READ_REG(hw, ICRXATC);
-			adapter->stats.ictxptc += E1000_READ_REG(hw, ICTXPTC);
-			adapter->stats.ictxatc += E1000_READ_REG(hw, ICTXATC);
-			adapter->stats.ictxqec += E1000_READ_REG(hw, ICTXQEC);
-			adapter->stats.ictxqmtc += E1000_READ_REG(hw, ICTXQMTC);
-			adapter->stats.icrxdmtc += E1000_READ_REG(hw, ICRXDMTC);
+		if (hw->mac_type != e1000_ich8lan) {
+			adapter->stats.icrxptc += er32(ICRXPTC);
+			adapter->stats.icrxatc += er32(ICRXATC);
+			adapter->stats.ictxptc += er32(ICTXPTC);
+			adapter->stats.ictxatc += er32(ICTXATC);
+			adapter->stats.ictxqec += er32(ICTXQEC);
+			adapter->stats.ictxqmtc += er32(ICTXQMTC);
+			adapter->stats.icrxdmtc += er32(ICRXDMTC);
 		}
 	}
 
@@ -3756,7 +3746,7 @@
 	adapter->net_stats.tx_aborted_errors = adapter->stats.ecol;
 	adapter->net_stats.tx_window_errors = adapter->stats.latecol;
 	adapter->net_stats.tx_carrier_errors = adapter->stats.tncrs;
-	if (adapter->hw.bad_tx_carr_stats_fd &&
+	if (hw->bad_tx_carr_stats_fd &&
 	    adapter->link_duplex == FULL_DUPLEX) {
 		adapter->net_stats.tx_carrier_errors = 0;
 		adapter->stats.tncrs = 0;
@@ -3779,10 +3769,10 @@
 	}
 
 	/* Management Stats */
-	if (adapter->hw.has_smbus) {
-		adapter->stats.mgptc += E1000_READ_REG(hw, MGTPTC);
-		adapter->stats.mgprc += E1000_READ_REG(hw, MGTPRC);
-		adapter->stats.mgpdc += E1000_READ_REG(hw, MGTPDC);
+	if (hw->has_smbus) {
+		adapter->stats.mgptc += er32(MGTPTC);
+		adapter->stats.mgprc += er32(MGTPRC);
+		adapter->stats.mgpdc += er32(MGTPDC);
 	}
 
 	spin_unlock_irqrestore(&adapter->stats_lock, flags);
@@ -3794,16 +3784,12 @@
  * @data: pointer to a network interface device structure
  **/
 
-static irqreturn_t
-e1000_intr_msi(int irq, void *data)
+static irqreturn_t e1000_intr_msi(int irq, void *data)
 {
 	struct net_device *netdev = data;
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
-#ifndef CONFIG_E1000_NAPI
-	int i;
-#endif
-	u32 icr = E1000_READ_REG(hw, ICR);
+	u32 icr = er32(ICR);
 
 	/* in NAPI mode read ICR disables interrupts using IAM */
 
@@ -3813,17 +3799,16 @@
 		 * link down event; disable receives here in the ISR and reset
 		 * adapter in watchdog */
 		if (netif_carrier_ok(netdev) &&
-		    (adapter->hw.mac_type == e1000_80003es2lan)) {
+		    (hw->mac_type == e1000_80003es2lan)) {
 			/* disable receives */
-			u32 rctl = E1000_READ_REG(hw, RCTL);
-			E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN);
+			u32 rctl = er32(RCTL);
+			ew32(RCTL, rctl & ~E1000_RCTL_EN);
 		}
 		/* guard against interrupt when we're going down */
 		if (!test_bit(__E1000_DOWN, &adapter->flags))
 			mod_timer(&adapter->watchdog_timer, jiffies + 1);
 	}
 
-#ifdef CONFIG_E1000_NAPI
 	if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) {
 		adapter->total_tx_bytes = 0;
 		adapter->total_tx_packets = 0;
@@ -3832,20 +3817,6 @@
 		__netif_rx_schedule(netdev, &adapter->napi);
 	} else
 		e1000_irq_enable(adapter);
-#else
-	adapter->total_tx_bytes = 0;
-	adapter->total_rx_bytes = 0;
-	adapter->total_tx_packets = 0;
-	adapter->total_rx_packets = 0;
-
-	for (i = 0; i < E1000_MAX_INTR; i++)
-		if (unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) &
-		   !e1000_clean_tx_irq(adapter, adapter->tx_ring)))
-			break;
-
-	if (likely(adapter->itr_setting & 3))
-		e1000_set_itr(adapter);
-#endif
 
 	return IRQ_HANDLED;
 }
@@ -3856,20 +3827,16 @@
  * @data: pointer to a network interface device structure
  **/
 
-static irqreturn_t
-e1000_intr(int irq, void *data)
+static irqreturn_t e1000_intr(int irq, void *data)
 {
 	struct net_device *netdev = data;
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
-	u32 rctl, icr = E1000_READ_REG(hw, ICR);
-#ifndef CONFIG_E1000_NAPI
-	int i;
-#endif
+	u32 rctl, icr = er32(ICR);
+
 	if (unlikely(!icr))
 		return IRQ_NONE;  /* Not our interrupt */
 
-#ifdef CONFIG_E1000_NAPI
 	/* IMS will not auto-mask if INT_ASSERTED is not set, and if it is
 	 * not set, then the adapter didn't send an interrupt */
 	if (unlikely(hw->mac_type >= e1000_82571 &&
@@ -3878,7 +3845,6 @@
 
 	/* Interrupt Auto-Mask...upon reading ICR, interrupts are masked.  No
 	 * need for the IMC write */
-#endif
 
 	if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
 		hw->get_link_status = 1;
@@ -3888,21 +3854,20 @@
 		 * reset adapter in watchdog
 		 */
 		if (netif_carrier_ok(netdev) &&
-		    (adapter->hw.mac_type == e1000_80003es2lan)) {
+		    (hw->mac_type == e1000_80003es2lan)) {
 			/* disable receives */
-			rctl = E1000_READ_REG(hw, RCTL);
-			E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN);
+			rctl = er32(RCTL);
+			ew32(RCTL, rctl & ~E1000_RCTL_EN);
 		}
 		/* guard against interrupt when we're going down */
 		if (!test_bit(__E1000_DOWN, &adapter->flags))
 			mod_timer(&adapter->watchdog_timer, jiffies + 1);
 	}
 
-#ifdef CONFIG_E1000_NAPI
 	if (unlikely(hw->mac_type < e1000_82571)) {
 		/* disable interrupts, without the synchronize_irq bit */
-		E1000_WRITE_REG(hw, IMC, ~0);
-		E1000_WRITE_FLUSH(hw);
+		ew32(IMC, ~0);
+		E1000_WRITE_FLUSH();
 	}
 	if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) {
 		adapter->total_tx_bytes = 0;
@@ -3914,48 +3879,15 @@
 		/* this really should not happen! if it does it is basically a
 		 * bug, but not a hard error, so enable ints and continue */
 		e1000_irq_enable(adapter);
-#else
-	/* Writing IMC and IMS is needed for 82547.
-	 * Due to Hub Link bus being occupied, an interrupt
-	 * de-assertion message is not able to be sent.
-	 * When an interrupt assertion message is generated later,
-	 * two messages are re-ordered and sent out.
-	 * That causes APIC to think 82547 is in de-assertion
-	 * state, while 82547 is in assertion state, resulting
-	 * in dead lock. Writing IMC forces 82547 into
-	 * de-assertion state.
-	 */
-	if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
-		E1000_WRITE_REG(hw, IMC, ~0);
 
-	adapter->total_tx_bytes = 0;
-	adapter->total_rx_bytes = 0;
-	adapter->total_tx_packets = 0;
-	adapter->total_rx_packets = 0;
-
-	for (i = 0; i < E1000_MAX_INTR; i++)
-		if (unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) &
-		   !e1000_clean_tx_irq(adapter, adapter->tx_ring)))
-			break;
-
-	if (likely(adapter->itr_setting & 3))
-		e1000_set_itr(adapter);
-
-	if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
-		e1000_irq_enable(adapter);
-
-#endif
 	return IRQ_HANDLED;
 }
 
-#ifdef CONFIG_E1000_NAPI
 /**
  * e1000_clean - NAPI Rx polling callback
  * @adapter: board private structure
  **/
-
-static int
-e1000_clean(struct napi_struct *napi, int budget)
+static int e1000_clean(struct napi_struct *napi, int budget)
 {
 	struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, napi);
 	struct net_device *poll_dev = adapter->netdev;
@@ -3991,23 +3923,19 @@
 	return work_done;
 }
 
-#endif
 /**
  * e1000_clean_tx_irq - Reclaim resources after transmit completes
  * @adapter: board private structure
  **/
-
-static bool
-e1000_clean_tx_irq(struct e1000_adapter *adapter,
-                   struct e1000_tx_ring *tx_ring)
+static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
+			       struct e1000_tx_ring *tx_ring)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
 	struct e1000_tx_desc *tx_desc, *eop_desc;
 	struct e1000_buffer *buffer_info;
 	unsigned int i, eop;
-#ifdef CONFIG_E1000_NAPI
 	unsigned int count = 0;
-#endif
 	bool cleaned = false;
 	unsigned int total_tx_bytes=0, total_tx_packets=0;
 
@@ -4039,11 +3967,10 @@
 
 		eop = tx_ring->buffer_info[i].next_to_watch;
 		eop_desc = E1000_TX_DESC(*tx_ring, eop);
-#ifdef CONFIG_E1000_NAPI
 #define E1000_TX_WEIGHT 64
 		/* weight of a sort for tx, to avoid endless transmit cleanup */
-		if (count++ == E1000_TX_WEIGHT) break;
-#endif
+		if (count++ == E1000_TX_WEIGHT)
+			break;
 	}
 
 	tx_ring->next_to_clean = i;
@@ -4068,8 +3995,7 @@
 		if (tx_ring->buffer_info[eop].dma &&
 		    time_after(jiffies, tx_ring->buffer_info[eop].time_stamp +
 		               (adapter->tx_timeout_factor * HZ))
-		    && !(E1000_READ_REG(&adapter->hw, STATUS) &
-		         E1000_STATUS_TXOFF)) {
+		    && !(er32(STATUS) & E1000_STATUS_TXOFF)) {
 
 			/* detected Tx unit hang */
 			DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n"
@@ -4085,8 +4011,8 @@
 					"  next_to_watch.status <%x>\n",
 				(unsigned long)((tx_ring - adapter->tx_ring) /
 					sizeof(struct e1000_tx_ring)),
-				readl(adapter->hw.hw_addr + tx_ring->tdh),
-				readl(adapter->hw.hw_addr + tx_ring->tdt),
+				readl(hw->hw_addr + tx_ring->tdh),
+				readl(hw->hw_addr + tx_ring->tdt),
 				tx_ring->next_to_use,
 				tx_ring->next_to_clean,
 				tx_ring->buffer_info[eop].time_stamp,
@@ -4111,17 +4037,16 @@
  * @sk_buff:     socket buffer with received data
  **/
 
-static void
-e1000_rx_checksum(struct e1000_adapter *adapter,
-		  u32 status_err, u32 csum,
-		  struct sk_buff *skb)
+static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
+			      u32 csum, struct sk_buff *skb)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	u16 status = (u16)status_err;
 	u8 errors = (u8)(status_err >> 24);
 	skb->ip_summed = CHECKSUM_NONE;
 
 	/* 82543 or newer only */
-	if (unlikely(adapter->hw.mac_type < e1000_82543)) return;
+	if (unlikely(hw->mac_type < e1000_82543)) return;
 	/* Ignore Checksum bit is set */
 	if (unlikely(status & E1000_RXD_STAT_IXSM)) return;
 	/* TCP/UDP checksum error bit is set */
@@ -4131,7 +4056,7 @@
 		return;
 	}
 	/* TCP/UDP Checksum has not been calculated */
-	if (adapter->hw.mac_type <= e1000_82547_rev_2) {
+	if (hw->mac_type <= e1000_82547_rev_2) {
 		if (!(status & E1000_RXD_STAT_TCPCS))
 			return;
 	} else {
@@ -4142,7 +4067,7 @@
 	if (likely(status & E1000_RXD_STAT_TCPCS)) {
 		/* TCP checksum is good */
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
-	} else if (adapter->hw.mac_type > e1000_82547_rev_2) {
+	} else if (hw->mac_type > e1000_82547_rev_2) {
 		/* IP fragment with UDP payload */
 		/* Hardware complements the payload checksum, so we undo it
 		 * and then put the value in host order for further stack use.
@@ -4158,17 +4083,11 @@
  * e1000_clean_rx_irq - Send received data up the network stack; legacy
  * @adapter: board private structure
  **/
-
-static bool
-#ifdef CONFIG_E1000_NAPI
-e1000_clean_rx_irq(struct e1000_adapter *adapter,
-                   struct e1000_rx_ring *rx_ring,
-                   int *work_done, int work_to_do)
-#else
-e1000_clean_rx_irq(struct e1000_adapter *adapter,
-                   struct e1000_rx_ring *rx_ring)
-#endif
+static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
+			       struct e1000_rx_ring *rx_ring,
+			       int *work_done, int work_to_do)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
 	struct e1000_rx_desc *rx_desc, *next_rxd;
@@ -4189,11 +4108,10 @@
 		struct sk_buff *skb;
 		u8 status;
 
-#ifdef CONFIG_E1000_NAPI
 		if (*work_done >= work_to_do)
 			break;
 		(*work_done)++;
-#endif
+
 		status = rx_desc->status;
 		skb = buffer_info->skb;
 		buffer_info->skb = NULL;
@@ -4226,11 +4144,10 @@
 
 		if (unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
 			last_byte = *(skb->data + length - 1);
-			if (TBI_ACCEPT(&adapter->hw, status,
-			              rx_desc->errors, length, last_byte)) {
+			if (TBI_ACCEPT(hw, status, rx_desc->errors, length,
+				       last_byte)) {
 				spin_lock_irqsave(&adapter->stats_lock, flags);
-				e1000_tbi_adjust_stats(&adapter->hw,
-				                       &adapter->stats,
+				e1000_tbi_adjust_stats(hw, &adapter->stats,
 				                       length, skb->data);
 				spin_unlock_irqrestore(&adapter->stats_lock,
 				                       flags);
@@ -4280,7 +4197,7 @@
 				  le16_to_cpu(rx_desc->csum), skb);
 
 		skb->protocol = eth_type_trans(skb, netdev);
-#ifdef CONFIG_E1000_NAPI
+
 		if (unlikely(adapter->vlgrp &&
 			    (status & E1000_RXD_STAT_VP))) {
 			vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
@@ -4288,15 +4205,7 @@
 		} else {
 			netif_receive_skb(skb);
 		}
-#else /* CONFIG_E1000_NAPI */
-		if (unlikely(adapter->vlgrp &&
-			    (status & E1000_RXD_STAT_VP))) {
-			vlan_hwaccel_rx(skb, adapter->vlgrp,
-					le16_to_cpu(rx_desc->special));
-		} else {
-			netif_rx(skb);
-		}
-#endif /* CONFIG_E1000_NAPI */
+
 		netdev->last_rx = jiffies;
 
 next_desc:
@@ -4330,15 +4239,9 @@
  * @adapter: board private structure
  **/
 
-static bool
-#ifdef CONFIG_E1000_NAPI
-e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
-                      struct e1000_rx_ring *rx_ring,
-                      int *work_done, int work_to_do)
-#else
-e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
-                      struct e1000_rx_ring *rx_ring)
-#endif
+static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+				  struct e1000_rx_ring *rx_ring,
+				  int *work_done, int work_to_do)
 {
 	union e1000_rx_desc_packet_split *rx_desc, *next_rxd;
 	struct net_device *netdev = adapter->netdev;
@@ -4361,11 +4264,11 @@
 	while (staterr & E1000_RXD_STAT_DD) {
 		ps_page = &rx_ring->ps_page[i];
 		ps_page_dma = &rx_ring->ps_page_dma[i];
-#ifdef CONFIG_E1000_NAPI
+
 		if (unlikely(*work_done >= work_to_do))
 			break;
 		(*work_done)++;
-#endif
+
 		skb = buffer_info->skb;
 
 		/* in the packet split case this is header only */
@@ -4438,7 +4341,8 @@
 		}
 
 		for (j = 0; j < adapter->rx_ps_pages; j++) {
-			if (!(length= le16_to_cpu(rx_desc->wb.upper.length[j])))
+			length = le16_to_cpu(rx_desc->wb.upper.length[j]);
+			if (!length)
 				break;
 			pci_unmap_page(pdev, ps_page_dma->ps_page_dma[j],
 					PAGE_SIZE, PCI_DMA_FROMDEVICE);
@@ -4466,21 +4370,14 @@
 		if (likely(rx_desc->wb.upper.header_status &
 			   cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP)))
 			adapter->rx_hdr_split++;
-#ifdef CONFIG_E1000_NAPI
+
 		if (unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
 			vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
 				le16_to_cpu(rx_desc->wb.middle.vlan));
 		} else {
 			netif_receive_skb(skb);
 		}
-#else /* CONFIG_E1000_NAPI */
-		if (unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
-			vlan_hwaccel_rx(skb, adapter->vlgrp,
-				le16_to_cpu(rx_desc->wb.middle.vlan));
-		} else {
-			netif_rx(skb);
-		}
-#endif /* CONFIG_E1000_NAPI */
+
 		netdev->last_rx = jiffies;
 
 next_desc:
@@ -4517,11 +4414,11 @@
  * @adapter: address of board private structure
  **/
 
-static void
-e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
-                       struct e1000_rx_ring *rx_ring,
-		       int cleaned_count)
+static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
+				   struct e1000_rx_ring *rx_ring,
+				   int cleaned_count)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
 	struct e1000_rx_desc *rx_desc;
@@ -4619,7 +4516,7 @@
 		 * applicable for weak-ordered memory model archs,
 		 * such as IA-64). */
 		wmb();
-		writel(i, adapter->hw.hw_addr + rx_ring->rdt);
+		writel(i, hw->hw_addr + rx_ring->rdt);
 	}
 }
 
@@ -4628,11 +4525,11 @@
  * @adapter: address of board private structure
  **/
 
-static void
-e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
-                          struct e1000_rx_ring *rx_ring,
-			  int cleaned_count)
+static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
+				      struct e1000_rx_ring *rx_ring,
+				      int cleaned_count)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
 	union e1000_rx_desc_packet_split *rx_desc;
@@ -4717,7 +4614,7 @@
 		 * descriptors are 32 bytes...so we increment tail
 		 * twice as much.
 		 */
-		writel(i<<1, adapter->hw.hw_addr + rx_ring->rdt);
+		writel(i<<1, hw->hw_addr + rx_ring->rdt);
 	}
 }
 
@@ -4726,49 +4623,49 @@
  * @adapter:
  **/
 
-static void
-e1000_smartspeed(struct e1000_adapter *adapter)
+static void e1000_smartspeed(struct e1000_adapter *adapter)
 {
+	struct e1000_hw *hw = &adapter->hw;
 	u16 phy_status;
 	u16 phy_ctrl;
 
-	if ((adapter->hw.phy_type != e1000_phy_igp) || !adapter->hw.autoneg ||
-	   !(adapter->hw.autoneg_advertised & ADVERTISE_1000_FULL))
+	if ((hw->phy_type != e1000_phy_igp) || !hw->autoneg ||
+	   !(hw->autoneg_advertised & ADVERTISE_1000_FULL))
 		return;
 
 	if (adapter->smartspeed == 0) {
 		/* If Master/Slave config fault is asserted twice,
 		 * we assume back-to-back */
-		e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status);
+		e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_status);
 		if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
-		e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status);
+		e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_status);
 		if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
-		e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl);
+		e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_ctrl);
 		if (phy_ctrl & CR_1000T_MS_ENABLE) {
 			phy_ctrl &= ~CR_1000T_MS_ENABLE;
-			e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL,
+			e1000_write_phy_reg(hw, PHY_1000T_CTRL,
 					    phy_ctrl);
 			adapter->smartspeed++;
-			if (!e1000_phy_setup_autoneg(&adapter->hw) &&
-			   !e1000_read_phy_reg(&adapter->hw, PHY_CTRL,
+			if (!e1000_phy_setup_autoneg(hw) &&
+			   !e1000_read_phy_reg(hw, PHY_CTRL,
 				   	       &phy_ctrl)) {
 				phy_ctrl |= (MII_CR_AUTO_NEG_EN |
 					     MII_CR_RESTART_AUTO_NEG);
-				e1000_write_phy_reg(&adapter->hw, PHY_CTRL,
+				e1000_write_phy_reg(hw, PHY_CTRL,
 						    phy_ctrl);
 			}
 		}
 		return;
 	} else if (adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) {
 		/* If still no link, perhaps using 2/3 pair cable */
-		e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl);
+		e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_ctrl);
 		phy_ctrl |= CR_1000T_MS_ENABLE;
-		e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_ctrl);
-		if (!e1000_phy_setup_autoneg(&adapter->hw) &&
-		   !e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_ctrl)) {
+		e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_ctrl);
+		if (!e1000_phy_setup_autoneg(hw) &&
+		   !e1000_read_phy_reg(hw, PHY_CTRL, &phy_ctrl)) {
 			phy_ctrl |= (MII_CR_AUTO_NEG_EN |
 				     MII_CR_RESTART_AUTO_NEG);
-			e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_ctrl);
+			e1000_write_phy_reg(hw, PHY_CTRL, phy_ctrl);
 		}
 	}
 	/* Restart process after E1000_SMARTSPEED_MAX iterations */
@@ -4783,8 +4680,7 @@
  * @cmd:
  **/
 
-static int
-e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
 {
 	switch (cmd) {
 	case SIOCGMIIPHY:
@@ -4803,28 +4699,29 @@
  * @cmd:
  **/
 
-static int
-e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
+			   int cmd)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
 	struct mii_ioctl_data *data = if_mii(ifr);
 	int retval;
 	u16 mii_reg;
 	u16 spddplx;
 	unsigned long flags;
 
-	if (adapter->hw.media_type != e1000_media_type_copper)
+	if (hw->media_type != e1000_media_type_copper)
 		return -EOPNOTSUPP;
 
 	switch (cmd) {
 	case SIOCGMIIPHY:
-		data->phy_id = adapter->hw.phy_addr;
+		data->phy_id = hw->phy_addr;
 		break;
 	case SIOCGMIIREG:
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		spin_lock_irqsave(&adapter->stats_lock, flags);
-		if (e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
+		if (e1000_read_phy_reg(hw, data->reg_num & 0x1F,
 				   &data->val_out)) {
 			spin_unlock_irqrestore(&adapter->stats_lock, flags);
 			return -EIO;
@@ -4838,20 +4735,20 @@
 			return -EFAULT;
 		mii_reg = data->val_in;
 		spin_lock_irqsave(&adapter->stats_lock, flags);
-		if (e1000_write_phy_reg(&adapter->hw, data->reg_num,
+		if (e1000_write_phy_reg(hw, data->reg_num,
 					mii_reg)) {
 			spin_unlock_irqrestore(&adapter->stats_lock, flags);
 			return -EIO;
 		}
 		spin_unlock_irqrestore(&adapter->stats_lock, flags);
-		if (adapter->hw.media_type == e1000_media_type_copper) {
+		if (hw->media_type == e1000_media_type_copper) {
 			switch (data->reg_num) {
 			case PHY_CTRL:
 				if (mii_reg & MII_CR_POWER_DOWN)
 					break;
 				if (mii_reg & MII_CR_AUTO_NEG_EN) {
-					adapter->hw.autoneg = 1;
-					adapter->hw.autoneg_advertised = 0x2F;
+					hw->autoneg = 1;
+					hw->autoneg_advertised = 0x2F;
 				} else {
 					if (mii_reg & 0x40)
 						spddplx = SPEED_1000;
@@ -4874,7 +4771,7 @@
 				break;
 			case M88E1000_PHY_SPEC_CTRL:
 			case M88E1000_EXT_PHY_SPEC_CTRL:
-				if (e1000_phy_reset(&adapter->hw))
+				if (e1000_phy_reset(hw))
 					return -EIO;
 				break;
 			}
@@ -4897,8 +4794,7 @@
 	return E1000_SUCCESS;
 }
 
-void
-e1000_pci_set_mwi(struct e1000_hw *hw)
+void e1000_pci_set_mwi(struct e1000_hw *hw)
 {
 	struct e1000_adapter *adapter = hw->back;
 	int ret_val = pci_set_mwi(adapter->pdev);
@@ -4907,30 +4803,26 @@
 		DPRINTK(PROBE, ERR, "Error in setting MWI\n");
 }
 
-void
-e1000_pci_clear_mwi(struct e1000_hw *hw)
+void e1000_pci_clear_mwi(struct e1000_hw *hw)
 {
 	struct e1000_adapter *adapter = hw->back;
 
 	pci_clear_mwi(adapter->pdev);
 }
 
-int
-e1000_pcix_get_mmrbc(struct e1000_hw *hw)
+int e1000_pcix_get_mmrbc(struct e1000_hw *hw)
 {
 	struct e1000_adapter *adapter = hw->back;
 	return pcix_get_mmrbc(adapter->pdev);
 }
 
-void
-e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc)
+void e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc)
 {
 	struct e1000_adapter *adapter = hw->back;
 	pcix_set_mmrbc(adapter->pdev, mmrbc);
 }
 
-s32
-e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
+s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
 {
     struct e1000_adapter *adapter = hw->back;
     u16 cap_offset;
@@ -4944,16 +4836,16 @@
     return E1000_SUCCESS;
 }
 
-void
-e1000_io_write(struct e1000_hw *hw, unsigned long port, u32 value)
+void e1000_io_write(struct e1000_hw *hw, unsigned long port, u32 value)
 {
 	outl(value, port);
 }
 
-static void
-e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
+static void e1000_vlan_rx_register(struct net_device *netdev,
+				   struct vlan_group *grp)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
 	u32 ctrl, rctl;
 
 	if (!test_bit(__E1000_DOWN, &adapter->flags))
@@ -4962,22 +4854,22 @@
 
 	if (grp) {
 		/* enable VLAN tag insert/strip */
-		ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+		ctrl = er32(CTRL);
 		ctrl |= E1000_CTRL_VME;
-		E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
+		ew32(CTRL, ctrl);
 
 		if (adapter->hw.mac_type != e1000_ich8lan) {
 			/* enable VLAN receive filtering */
-			rctl = E1000_READ_REG(&adapter->hw, RCTL);
+			rctl = er32(RCTL);
 			rctl &= ~E1000_RCTL_CFIEN;
-			E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+			ew32(RCTL, rctl);
 			e1000_update_mng_vlan(adapter);
 		}
 	} else {
 		/* disable VLAN tag insert/strip */
-		ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+		ctrl = er32(CTRL);
 		ctrl &= ~E1000_CTRL_VME;
-		E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
+		ew32(CTRL, ctrl);
 
 		if (adapter->hw.mac_type != e1000_ich8lan) {
 			if (adapter->mng_vlan_id !=
@@ -4993,27 +4885,27 @@
 		e1000_irq_enable(adapter);
 }
 
-static void
-e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
+static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
 	u32 vfta, index;
 
-	if ((adapter->hw.mng_cookie.status &
+	if ((hw->mng_cookie.status &
 	     E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
 	    (vid == adapter->mng_vlan_id))
 		return;
 	/* add VID to filter table */
 	index = (vid >> 5) & 0x7F;
-	vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
+	vfta = E1000_READ_REG_ARRAY(hw, VFTA, index);
 	vfta |= (1 << (vid & 0x1F));
-	e1000_write_vfta(&adapter->hw, index, vfta);
+	e1000_write_vfta(hw, index, vfta);
 }
 
-static void
-e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
+static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
 	u32 vfta, index;
 
 	if (!test_bit(__E1000_DOWN, &adapter->flags))
@@ -5022,7 +4914,7 @@
 	if (!test_bit(__E1000_DOWN, &adapter->flags))
 		e1000_irq_enable(adapter);
 
-	if ((adapter->hw.mng_cookie.status &
+	if ((hw->mng_cookie.status &
 	     E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
 	    (vid == adapter->mng_vlan_id)) {
 		/* release control to f/w */
@@ -5032,13 +4924,12 @@
 
 	/* remove VID from filter table */
 	index = (vid >> 5) & 0x7F;
-	vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
+	vfta = E1000_READ_REG_ARRAY(hw, VFTA, index);
 	vfta &= ~(1 << (vid & 0x1F));
-	e1000_write_vfta(&adapter->hw, index, vfta);
+	e1000_write_vfta(hw, index, vfta);
 }
 
-static void
-e1000_restore_vlan(struct e1000_adapter *adapter)
+static void e1000_restore_vlan(struct e1000_adapter *adapter)
 {
 	e1000_vlan_rx_register(adapter->netdev, adapter->vlgrp);
 
@@ -5052,13 +4943,14 @@
 	}
 }
 
-int
-e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
+int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
 {
-	adapter->hw.autoneg = 0;
+	struct e1000_hw *hw = &adapter->hw;
+
+	hw->autoneg = 0;
 
 	/* Fiber NICs only allow 1000 gbps Full duplex */
-	if ((adapter->hw.media_type == e1000_media_type_fiber) &&
+	if ((hw->media_type == e1000_media_type_fiber) &&
 		spddplx != (SPEED_1000 + DUPLEX_FULL)) {
 		DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n");
 		return -EINVAL;
@@ -5066,20 +4958,20 @@
 
 	switch (spddplx) {
 	case SPEED_10 + DUPLEX_HALF:
-		adapter->hw.forced_speed_duplex = e1000_10_half;
+		hw->forced_speed_duplex = e1000_10_half;
 		break;
 	case SPEED_10 + DUPLEX_FULL:
-		adapter->hw.forced_speed_duplex = e1000_10_full;
+		hw->forced_speed_duplex = e1000_10_full;
 		break;
 	case SPEED_100 + DUPLEX_HALF:
-		adapter->hw.forced_speed_duplex = e1000_100_half;
+		hw->forced_speed_duplex = e1000_100_half;
 		break;
 	case SPEED_100 + DUPLEX_FULL:
-		adapter->hw.forced_speed_duplex = e1000_100_full;
+		hw->forced_speed_duplex = e1000_100_full;
 		break;
 	case SPEED_1000 + DUPLEX_FULL:
-		adapter->hw.autoneg = 1;
-		adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
+		hw->autoneg = 1;
+		hw->autoneg_advertised = ADVERTISE_1000_FULL;
 		break;
 	case SPEED_1000 + DUPLEX_HALF: /* not supported */
 	default:
@@ -5089,11 +4981,11 @@
 	return 0;
 }
 
-static int
-e1000_suspend(struct pci_dev *pdev, pm_message_t state)
+static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
 	u32 ctrl, ctrl_ext, rctl, status;
 	u32 wufc = adapter->wol;
 #ifdef CONFIG_PM
@@ -5113,7 +5005,7 @@
 		return retval;
 #endif
 
-	status = E1000_READ_REG(&adapter->hw, STATUS);
+	status = er32(STATUS);
 	if (status & E1000_STATUS_LU)
 		wufc &= ~E1000_WUFC_LNKC;
 
@@ -5123,40 +5015,40 @@
 
 		/* turn on all-multi mode if wake on multicast is enabled */
 		if (wufc & E1000_WUFC_MC) {
-			rctl = E1000_READ_REG(&adapter->hw, RCTL);
+			rctl = er32(RCTL);
 			rctl |= E1000_RCTL_MPE;
-			E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+			ew32(RCTL, rctl);
 		}
 
-		if (adapter->hw.mac_type >= e1000_82540) {
-			ctrl = E1000_READ_REG(&adapter->hw, CTRL);
+		if (hw->mac_type >= e1000_82540) {
+			ctrl = er32(CTRL);
 			/* advertise wake from D3Cold */
 			#define E1000_CTRL_ADVD3WUC 0x00100000
 			/* phy power management enable */
 			#define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000
 			ctrl |= E1000_CTRL_ADVD3WUC |
 				E1000_CTRL_EN_PHY_PWR_MGMT;
-			E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
+			ew32(CTRL, ctrl);
 		}
 
-		if (adapter->hw.media_type == e1000_media_type_fiber ||
-		   adapter->hw.media_type == e1000_media_type_internal_serdes) {
+		if (hw->media_type == e1000_media_type_fiber ||
+		   hw->media_type == e1000_media_type_internal_serdes) {
 			/* keep the laser running in D3 */
-			ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+			ctrl_ext = er32(CTRL_EXT);
 			ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA;
-			E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ctrl_ext);
+			ew32(CTRL_EXT, ctrl_ext);
 		}
 
 		/* Allow time for pending master requests to run */
-		e1000_disable_pciex_master(&adapter->hw);
+		e1000_disable_pciex_master(hw);
 
-		E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN);
-		E1000_WRITE_REG(&adapter->hw, WUFC, wufc);
+		ew32(WUC, E1000_WUC_PME_EN);
+		ew32(WUFC, wufc);
 		pci_enable_wake(pdev, PCI_D3hot, 1);
 		pci_enable_wake(pdev, PCI_D3cold, 1);
 	} else {
-		E1000_WRITE_REG(&adapter->hw, WUC, 0);
-		E1000_WRITE_REG(&adapter->hw, WUFC, 0);
+		ew32(WUC, 0);
+		ew32(WUFC, 0);
 		pci_enable_wake(pdev, PCI_D3hot, 0);
 		pci_enable_wake(pdev, PCI_D3cold, 0);
 	}
@@ -5169,8 +5061,8 @@
 		pci_enable_wake(pdev, PCI_D3cold, 1);
 	}
 
-	if (adapter->hw.phy_type == e1000_phy_igp_3)
-		e1000_phy_powerdown_workaround(&adapter->hw);
+	if (hw->phy_type == e1000_phy_igp_3)
+		e1000_phy_powerdown_workaround(hw);
 
 	if (netif_running(netdev))
 		e1000_free_irq(adapter);
@@ -5187,16 +5079,21 @@
 }
 
 #ifdef CONFIG_PM
-static int
-e1000_resume(struct pci_dev *pdev)
+static int e1000_resume(struct pci_dev *pdev)
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
 	u32 err;
 
 	pci_set_power_state(pdev, PCI_D0);
 	pci_restore_state(pdev);
-	if ((err = pci_enable_device(pdev))) {
+
+	if (adapter->need_ioport)
+		err = pci_enable_device(pdev);
+	else
+		err = pci_enable_device_mem(pdev);
+	if (err) {
 		printk(KERN_ERR "e1000: Cannot enable PCI device from suspend\n");
 		return err;
 	}
@@ -5205,12 +5102,15 @@
 	pci_enable_wake(pdev, PCI_D3hot, 0);
 	pci_enable_wake(pdev, PCI_D3cold, 0);
 
-	if (netif_running(netdev) && (err = e1000_request_irq(adapter)))
-		return err;
+	if (netif_running(netdev)) {
+		err = e1000_request_irq(adapter);
+		if (err)
+			return err;
+	}
 
 	e1000_power_up_phy(adapter);
 	e1000_reset(adapter);
-	E1000_WRITE_REG(&adapter->hw, WUS, ~0);
+	ew32(WUS, ~0);
 
 	e1000_init_manageability(adapter);
 
@@ -5223,8 +5123,8 @@
 	 * DRV_LOAD until the interface is up.  For all other cases,
 	 * let the f/w know that the h/w is now under the control
 	 * of the driver. */
-	if (adapter->hw.mac_type != e1000_82573 ||
-	    !e1000_check_mng_mode(&adapter->hw))
+	if (hw->mac_type != e1000_82573 ||
+	    !e1000_check_mng_mode(hw))
 		e1000_get_hw_control(adapter);
 
 	return 0;
@@ -5242,16 +5142,12 @@
  * without having to re-enable interrupts. It's not called while
  * the interrupt routine is executing.
  */
-static void
-e1000_netpoll(struct net_device *netdev)
+static void e1000_netpoll(struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 
 	disable_irq(adapter->pdev->irq);
 	e1000_intr(adapter->pdev->irq, netdev);
-#ifndef CONFIG_E1000_NAPI
-	adapter->clean_rx(adapter, adapter->rx_ring);
-#endif
 	enable_irq(adapter->pdev->irq);
 }
 #endif
@@ -5264,7 +5160,8 @@
  * This function is called after a PCI bus error affecting
  * this device has been detected.
  */
-static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
+static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
+						pci_channel_state_t state)
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct e1000_adapter *adapter = netdev->priv;
@@ -5290,8 +5187,14 @@
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct e1000_adapter *adapter = netdev->priv;
+	struct e1000_hw *hw = &adapter->hw;
+	int err;
 
-	if (pci_enable_device(pdev)) {
+	if (adapter->need_ioport)
+		err = pci_enable_device(pdev);
+	else
+		err = pci_enable_device_mem(pdev);
+	if (err) {
 		printk(KERN_ERR "e1000: Cannot re-enable PCI device after reset.\n");
 		return PCI_ERS_RESULT_DISCONNECT;
 	}
@@ -5301,7 +5204,7 @@
 	pci_enable_wake(pdev, PCI_D3cold, 0);
 
 	e1000_reset(adapter);
-	E1000_WRITE_REG(&adapter->hw, WUS, ~0);
+	ew32(WUS, ~0);
 
 	return PCI_ERS_RESULT_RECOVERED;
 }
@@ -5318,6 +5221,7 @@
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct e1000_adapter *adapter = netdev->priv;
+	struct e1000_hw *hw = &adapter->hw;
 
 	e1000_init_manageability(adapter);
 
@@ -5334,8 +5238,8 @@
 	 * DRV_LOAD until the interface is up.  For all other cases,
 	 * let the f/w know that the h/w is now under the control
 	 * of the driver. */
-	if (adapter->hw.mac_type != e1000_82573 ||
-	    !e1000_check_mng_mode(&adapter->hw))
+	if (hw->mac_type != e1000_82573 ||
+	    !e1000_check_mng_mode(hw))
 		e1000_get_hw_control(adapter);
 
 }
diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h
index 365626d..d929852 100644
--- a/drivers/net/e1000/e1000_osdep.h
+++ b/drivers/net/e1000/e1000_osdep.h
@@ -55,13 +55,13 @@
 #define DEBUGOUT7 DEBUGOUT3
 
 
-#define E1000_WRITE_REG(a, reg, value) ( \
-    writel((value), ((a)->hw_addr + \
-        (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg))))
+#define er32(reg)							\
+	(readl(hw->hw_addr + ((hw->mac_type >= e1000_82543)		\
+			       ? E1000_##reg : E1000_82542_##reg)))
 
-#define E1000_READ_REG(a, reg) ( \
-    readl((a)->hw_addr + \
-        (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg)))
+#define ew32(reg, value)						\
+	(writel((value), (hw->hw_addr + ((hw->mac_type >= e1000_82543)	\
+					 ? E1000_##reg : E1000_82542_##reg))))
 
 #define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
     writel((value), ((a)->hw_addr + \
@@ -96,7 +96,7 @@
         (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
         (offset)))
 
-#define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, STATUS)
+#define E1000_WRITE_FLUSH() er32(STATUS)
 
 #define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \
     writel((value), ((a)->flash_address + reg)))
diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
index e6565ce..b9f90a5 100644
--- a/drivers/net/e1000/e1000_param.c
+++ b/drivers/net/e1000/e1000_param.c
@@ -213,10 +213,9 @@
 	} arg;
 };
 
-static int __devinit
-e1000_validate_option(unsigned int *value,
-		      const struct e1000_option *opt,
-		      struct e1000_adapter *adapter)
+static int __devinit e1000_validate_option(unsigned int *value,
+					   const struct e1000_option *opt,
+					   struct e1000_adapter *adapter)
 {
 	if (*value == OPTION_UNSET) {
 		*value = opt->def;
@@ -278,8 +277,7 @@
  * in a variable in the adapter structure.
  **/
 
-void __devinit
-e1000_check_options(struct e1000_adapter *adapter)
+void __devinit e1000_check_options(struct e1000_adapter *adapter)
 {
 	int bd = adapter->bd_number;
 	if (bd >= E1000_MAX_NIC) {
@@ -551,8 +549,7 @@
  * Handles speed and duplex options on fiber adapters
  **/
 
-static void __devinit
-e1000_check_fiber_options(struct e1000_adapter *adapter)
+static void __devinit e1000_check_fiber_options(struct e1000_adapter *adapter)
 {
 	int bd = adapter->bd_number;
 	if (num_Speed > bd) {
@@ -579,8 +576,7 @@
  * Handles speed and duplex options on copper adapters
  **/
 
-static void __devinit
-e1000_check_copper_options(struct e1000_adapter *adapter)
+static void __devinit e1000_check_copper_options(struct e1000_adapter *adapter)
 {
 	unsigned int speed, dplx, an;
 	int bd = adapter->bd_number;
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
index ae9ecb7..4e4f683 100644
--- a/drivers/net/fec_mpc52xx.c
+++ b/drivers/net/fec_mpc52xx.c
@@ -197,9 +197,6 @@
 		if (priv->link == PHY_DOWN) {
 			new_state = 1;
 			priv->link = phydev->link;
-			netif_tx_schedule_all(dev);
-			netif_carrier_on(dev);
-			netif_start_queue(dev);
 		}
 
 	} else if (priv->link) {
@@ -207,8 +204,6 @@
 		priv->link = PHY_DOWN;
 		priv->speed = 0;
 		priv->duplex = -1;
-		netif_stop_queue(dev);
-		netif_carrier_off(dev);
 	}
 
 	if (new_state && netif_msg_link(priv))
diff --git a/drivers/net/fs_enet/Makefile b/drivers/net/fs_enet/Makefile
index 1ffbe07..d4a305e 100644
--- a/drivers/net/fs_enet/Makefile
+++ b/drivers/net/fs_enet/Makefile
@@ -8,12 +8,7 @@
 fs_enet-$(CONFIG_FS_ENET_HAS_FEC) += mac-fec.o
 fs_enet-$(CONFIG_FS_ENET_HAS_FCC) += mac-fcc.o
 
-ifeq ($(CONFIG_PPC_CPM_NEW_BINDING),y)
 obj-$(CONFIG_FS_ENET_MDIO_FEC) += mii-fec.o
 obj-$(CONFIG_FS_ENET_MDIO_FCC) += mii-bitbang.o
-else
-fs_enet-$(CONFIG_FS_ENET_MDIO_FEC) += mii-fec.o
-fs_enet-$(CONFIG_FS_ENET_MDIO_FCC) += mii-bitbang.o
-endif
 
 fs_enet-objs := fs_enet-main.o $(fs_enet-m)
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index 445763e..9a51ec8 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -36,26 +36,18 @@
 #include <linux/fs.h>
 #include <linux/platform_device.h>
 #include <linux/phy.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
 
 #include <linux/vmalloc.h>
 #include <asm/pgtable.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
-#include <linux/of_gpio.h>
-#include <linux/of_platform.h>
-#endif
-
 #include "fs_enet.h"
 
 /*************************************************/
 
-#ifndef CONFIG_PPC_CPM_NEW_BINDING
-static char version[] __devinitdata =
-    DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")" "\n";
-#endif
-
 MODULE_AUTHOR("Pantelis Antoniou <panto@intracom.gr>");
 MODULE_DESCRIPTION("Freescale Ethernet Driver");
 MODULE_LICENSE("GPL");
@@ -738,9 +730,6 @@
 		if (!fep->oldlink) {
 			new_state = 1;
 			fep->oldlink = 1;
-			netif_tx_schedule_all(dev);
-			netif_carrier_on(dev);
-			netif_start_queue(dev);
 		}
 
 		if (new_state)
@@ -750,8 +739,6 @@
 		fep->oldlink = 0;
 		fep->oldspeed = 0;
 		fep->oldduplex = -1;
-		netif_carrier_off(dev);
-		netif_stop_queue(dev);
 	}
 
 	if (new_state && netif_msg_link(fep))
@@ -826,6 +813,8 @@
 	}
 	phy_start(fep->phydev);
 
+	netif_start_queue(dev);
+
 	return 0;
 }
 
@@ -958,190 +947,6 @@
 extern int fs_mii_connect(struct net_device *dev);
 extern void fs_mii_disconnect(struct net_device *dev);
 
-#ifndef CONFIG_PPC_CPM_NEW_BINDING
-static struct net_device *fs_init_instance(struct device *dev,
-		struct fs_platform_info *fpi)
-{
-	struct net_device *ndev = NULL;
-	struct fs_enet_private *fep = NULL;
-	int privsize, i, r, err = 0, registered = 0;
-
-	fpi->fs_no = fs_get_id(fpi);
-	/* guard */
-	if ((unsigned int)fpi->fs_no >= FS_MAX_INDEX)
-		return ERR_PTR(-EINVAL);
-
-	privsize = sizeof(*fep) + (sizeof(struct sk_buff **) *
-			    (fpi->rx_ring + fpi->tx_ring));
-
-	ndev = alloc_etherdev(privsize);
-	if (!ndev) {
-		err = -ENOMEM;
-		goto err;
-	}
-
-	fep = netdev_priv(ndev);
-
-	fep->dev = dev;
-	dev_set_drvdata(dev, ndev);
-	fep->fpi = fpi;
-	if (fpi->init_ioports)
-		fpi->init_ioports((struct fs_platform_info *)fpi);
-
-#ifdef CONFIG_FS_ENET_HAS_FEC
-	if (fs_get_fec_index(fpi->fs_no) >= 0)
-		fep->ops = &fs_fec_ops;
-#endif
-
-#ifdef CONFIG_FS_ENET_HAS_SCC
-	if (fs_get_scc_index(fpi->fs_no) >=0)
-		fep->ops = &fs_scc_ops;
-#endif
-
-#ifdef CONFIG_FS_ENET_HAS_FCC
-	if (fs_get_fcc_index(fpi->fs_no) >= 0)
-		fep->ops = &fs_fcc_ops;
-#endif
-
-	if (fep->ops == NULL) {
-		printk(KERN_ERR DRV_MODULE_NAME
-		       ": %s No matching ops found (%d).\n",
-		       ndev->name, fpi->fs_no);
-		err = -EINVAL;
-		goto err;
-	}
-
-	r = (*fep->ops->setup_data)(ndev);
-	if (r != 0) {
-		printk(KERN_ERR DRV_MODULE_NAME
-		       ": %s setup_data failed\n",
-			ndev->name);
-		err = r;
-		goto err;
-	}
-
-	/* point rx_skbuff, tx_skbuff */
-	fep->rx_skbuff = (struct sk_buff **)&fep[1];
-	fep->tx_skbuff = fep->rx_skbuff + fpi->rx_ring;
-
-	/* init locks */
-	spin_lock_init(&fep->lock);
-	spin_lock_init(&fep->tx_lock);
-
-	/*
-	 * Set the Ethernet address.
-	 */
-	for (i = 0; i < 6; i++)
-		ndev->dev_addr[i] = fpi->macaddr[i];
-
-	r = (*fep->ops->allocate_bd)(ndev);
-
-	if (fep->ring_base == NULL) {
-		printk(KERN_ERR DRV_MODULE_NAME
-		       ": %s buffer descriptor alloc failed (%d).\n", ndev->name, r);
-		err = r;
-		goto err;
-	}
-
-	/*
-	 * Set receive and transmit descriptor base.
-	 */
-	fep->rx_bd_base = fep->ring_base;
-	fep->tx_bd_base = fep->rx_bd_base + fpi->rx_ring;
-
-	/* initialize ring size variables */
-	fep->tx_ring = fpi->tx_ring;
-	fep->rx_ring = fpi->rx_ring;
-
-	/*
-	 * The FEC Ethernet specific entries in the device structure.
-	 */
-	ndev->open = fs_enet_open;
-	ndev->hard_start_xmit = fs_enet_start_xmit;
-	ndev->tx_timeout = fs_timeout;
-	ndev->watchdog_timeo = 2 * HZ;
-	ndev->stop = fs_enet_close;
-	ndev->get_stats = fs_enet_get_stats;
-	ndev->set_multicast_list = fs_set_multicast_list;
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	ndev->poll_controller = fs_enet_netpoll;
-#endif
-
-	netif_napi_add(ndev, &fep->napi,
-		       fs_enet_rx_napi, fpi->napi_weight);
-
-	ndev->ethtool_ops = &fs_ethtool_ops;
-	ndev->do_ioctl = fs_ioctl;
-
-	init_timer(&fep->phy_timer_list);
-
-	netif_carrier_off(ndev);
-
-	err = register_netdev(ndev);
-	if (err != 0) {
-		printk(KERN_ERR DRV_MODULE_NAME
-		       ": %s register_netdev failed.\n", ndev->name);
-		goto err;
-	}
-	registered = 1;
-
-
-	return ndev;
-
-err:
-	if (ndev != NULL) {
-		if (registered)
-			unregister_netdev(ndev);
-
-		if (fep && fep->ops) {
-			(*fep->ops->free_bd)(ndev);
-			(*fep->ops->cleanup_data)(ndev);
-		}
-
-		free_netdev(ndev);
-	}
-
-	dev_set_drvdata(dev, NULL);
-
-	return ERR_PTR(err);
-}
-
-static int fs_cleanup_instance(struct net_device *ndev)
-{
-	struct fs_enet_private *fep;
-	const struct fs_platform_info *fpi;
-	struct device *dev;
-
-	if (ndev == NULL)
-		return -EINVAL;
-
-	fep = netdev_priv(ndev);
-	if (fep == NULL)
-		return -EINVAL;
-
-	fpi = fep->fpi;
-
-	unregister_netdev(ndev);
-
-	dma_free_coherent(fep->dev, (fpi->tx_ring + fpi->rx_ring) * sizeof(cbd_t),
-			  (void __force *)fep->ring_base, fep->ring_mem_addr);
-
-	/* reset it */
-	(*fep->ops->cleanup_data)(ndev);
-
-	dev = fep->dev;
-	if (dev != NULL) {
-		dev_set_drvdata(dev, NULL);
-		fep->dev = NULL;
-	}
-
-	free_netdev(ndev);
-
-	return 0;
-}
-#endif
-
 /**************************************************************************************/
 
 /* handy pointer to the immap */
@@ -1168,7 +973,6 @@
 
 /**************************************************************************************/
 
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
 static int __devinit find_phy(struct device_node *np,
                               struct fs_platform_info *fpi)
 {
@@ -1408,121 +1212,6 @@
 	of_unregister_platform_driver(&fs_enet_driver);
 	cleanup_immap();
 }
-#else
-static int __devinit fs_enet_probe(struct device *dev)
-{
-	struct net_device *ndev;
-
-	/* no fixup - no device */
-	if (dev->platform_data == NULL) {
-		printk(KERN_INFO "fs_enet: "
-				"probe called with no platform data; "
-				"remove unused devices\n");
-		return -ENODEV;
-	}
-
-	ndev = fs_init_instance(dev, dev->platform_data);
-	if (IS_ERR(ndev))
-		return PTR_ERR(ndev);
-	return 0;
-}
-
-static int fs_enet_remove(struct device *dev)
-{
-	return fs_cleanup_instance(dev_get_drvdata(dev));
-}
-
-static struct device_driver fs_enet_fec_driver = {
-	.name	  	= "fsl-cpm-fec",
-	.bus		= &platform_bus_type,
-	.probe		= fs_enet_probe,
-	.remove		= fs_enet_remove,
-#ifdef CONFIG_PM
-/*	.suspend	= fs_enet_suspend,	TODO */
-/*	.resume		= fs_enet_resume,	TODO */
-#endif
-};
-
-static struct device_driver fs_enet_scc_driver = {
-	.name	  	= "fsl-cpm-scc",
-	.bus		= &platform_bus_type,
-	.probe		= fs_enet_probe,
-	.remove		= fs_enet_remove,
-#ifdef CONFIG_PM
-/*	.suspend	= fs_enet_suspend,	TODO */
-/*	.resume		= fs_enet_resume,	TODO */
-#endif
-};
-
-static struct device_driver fs_enet_fcc_driver = {
-	.name	  	= "fsl-cpm-fcc",
-	.bus		= &platform_bus_type,
-	.probe		= fs_enet_probe,
-	.remove		= fs_enet_remove,
-#ifdef CONFIG_PM
-/*	.suspend	= fs_enet_suspend,	TODO */
-/*	.resume		= fs_enet_resume,	TODO */
-#endif
-};
-
-static int __init fs_init(void)
-{
-	int r;
-
-	printk(KERN_INFO
-			"%s", version);
-
-	r = setup_immap();
-	if (r != 0)
-		return r;
-
-#ifdef CONFIG_FS_ENET_HAS_FCC
-	/* let's insert mii stuff */
-	r = fs_enet_mdio_bb_init();
-
-	if (r != 0) {
-		printk(KERN_ERR DRV_MODULE_NAME
-			"BB PHY init failed.\n");
-		return r;
-	}
-	r = driver_register(&fs_enet_fcc_driver);
-	if (r != 0)
-		goto err;
-#endif
-
-#ifdef CONFIG_FS_ENET_HAS_FEC
-	r =  fs_enet_mdio_fec_init();
-	if (r != 0) {
-		printk(KERN_ERR DRV_MODULE_NAME
-			"FEC PHY init failed.\n");
-		return r;
-	}
-
-	r = driver_register(&fs_enet_fec_driver);
-	if (r != 0)
-		goto err;
-#endif
-
-#ifdef CONFIG_FS_ENET_HAS_SCC
-	r = driver_register(&fs_enet_scc_driver);
-	if (r != 0)
-		goto err;
-#endif
-
-	return 0;
-err:
-	cleanup_immap();
-	return r;
-}
-
-static void __exit fs_cleanup(void)
-{
-	driver_unregister(&fs_enet_fec_driver);
-	driver_unregister(&fs_enet_fcc_driver);
-	driver_unregister(&fs_enet_scc_driver);
-	cleanup_immap();
-}
-#endif
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void fs_enet_netpoll(struct net_device *dev)
diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h
index e05389c..db46d2e 100644
--- a/drivers/net/fs_enet/fs_enet.h
+++ b/drivers/net/fs_enet/fs_enet.h
@@ -138,10 +138,6 @@
 };
 
 /***************************************************************************/
-#ifndef CONFIG_PPC_CPM_NEW_BINDING
-int fs_enet_mdio_bb_init(void);
-int fs_enet_mdio_fec_init(void);
-#endif
 
 void fs_init_bds(struct net_device *dev);
 void fs_cleanup_bds(struct net_device *dev);
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c
index 8268b35..0a97fc2 100644
--- a/drivers/net/fs_enet/mac-fcc.c
+++ b/drivers/net/fs_enet/mac-fcc.c
@@ -33,6 +33,7 @@
 #include <linux/fs.h>
 #include <linux/platform_device.h>
 #include <linux/phy.h>
+#include <linux/of_device.h>
 
 #include <asm/immap_cpm2.h>
 #include <asm/mpc8260.h>
@@ -42,10 +43,6 @@
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
-#include <asm/of_device.h>
-#endif
-
 #include "fs_enet.h"
 
 /*************************************************/
@@ -87,7 +84,6 @@
 
 static int do_pd_setup(struct fs_enet_private *fep)
 {
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
 	struct of_device *ofdev = to_of_device(fep->dev);
 	struct fs_platform_info *fpi = fep->fpi;
 	int ret = -EINVAL;
@@ -125,44 +121,6 @@
 	iounmap(fep->fcc.fccp);
 out:
 	return ret;
-#else
-	struct platform_device *pdev = to_platform_device(fep->dev);
-	struct resource *r;
-
-	/* Fill out IRQ field */
-	fep->interrupt = platform_get_irq(pdev, 0);
-	if (fep->interrupt < 0)
-		return -EINVAL;
-
-	/* Attach the memory for the FCC Parameter RAM */
-	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_pram");
-	fep->fcc.ep = ioremap(r->start, r->end - r->start + 1);
-	if (fep->fcc.ep == NULL)
-		return -EINVAL;
-
-	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_regs");
-	fep->fcc.fccp = ioremap(r->start, r->end - r->start + 1);
-	if (fep->fcc.fccp == NULL)
-		return -EINVAL;
-
-	if (fep->fpi->fcc_regs_c) {
-		fep->fcc.fcccp = (void __iomem *)fep->fpi->fcc_regs_c;
-	} else {
-		r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-				"fcc_regs_c");
-		fep->fcc.fcccp = ioremap(r->start,
-				r->end - r->start + 1);
-	}
-
-	if (fep->fcc.fcccp == NULL)
-		return -EINVAL;
-
-	fep->fcc.mem = (void __iomem *)fep->fpi->mem_offset;
-	if (fep->fcc.mem == NULL)
-		return -EINVAL;
-
-	return 0;
-#endif
 }
 
 #define FCC_NAPI_RX_EVENT_MSK	(FCC_ENET_RXF | FCC_ENET_RXB)
@@ -173,17 +131,6 @@
 static int setup_data(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-#ifndef CONFIG_PPC_CPM_NEW_BINDING
-	struct fs_platform_info *fpi = fep->fpi;
-
-	fpi->cp_command = (fpi->cp_page << 26) |
-	                  (fpi->cp_block << 21) |
-	                  (12 << 6);
-
-	fep->fcc.idx = fs_get_fcc_index(fpi->fs_no);
-	if ((unsigned int)fep->fcc.idx >= 3)	/* max 3 FCCs */
-		return -EINVAL;
-#endif
 
 	if (do_pd_setup(fep) != 0)
 		return -EINVAL;
@@ -304,9 +251,6 @@
 	fcc_enet_t __iomem *ep = fep->fcc.ep;
 	dma_addr_t rx_bd_base_phys, tx_bd_base_phys;
 	u16 paddrh, paddrm, paddrl;
-#ifndef CONFIG_PPC_CPM_NEW_BINDING
-	u16 mem_addr;
-#endif
 	const unsigned char *mac;
 	int i;
 
@@ -338,19 +282,10 @@
 	 * this area.
 	 */
 
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
 	W16(ep, fen_genfcc.fcc_riptr, fpi->dpram_offset);
 	W16(ep, fen_genfcc.fcc_tiptr, fpi->dpram_offset + 32);
 
 	W16(ep, fen_padptr, fpi->dpram_offset + 64);
-#else
-	mem_addr = (u32) fep->fcc.mem;	/* de-fixup dpram offset */
-
-	W16(ep, fen_genfcc.fcc_riptr, (mem_addr & 0xffff));
-	W16(ep, fen_genfcc.fcc_tiptr, ((mem_addr + 32) & 0xffff));
-
-	W16(ep, fen_padptr, mem_addr + 64);
-#endif
 
 	/* fill with special symbol...  */
 	memset_io(fep->fcc.mem + fpi->dpram_offset + 64, 0x88, 32);
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
index 8a311d1..0a7d1c5 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -32,6 +32,7 @@
 #include <linux/bitops.h>
 #include <linux/fs.h>
 #include <linux/platform_device.h>
+#include <linux/of_device.h>
 
 #include <asm/irq.h>
 #include <asm/uaccess.h>
@@ -43,10 +44,6 @@
 #include <asm/cpm1.h>
 #endif
 
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
-#include <asm/of_device.h>
-#endif
-
 #include "fs_enet.h"
 #include "fec.h"
 
@@ -99,7 +96,6 @@
 
 static int do_pd_setup(struct fs_enet_private *fep)
 {
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
 	struct of_device *ofdev = to_of_device(fep->dev);
 
 	fep->interrupt = of_irq_to_resource(ofdev->node, 0, NULL);
@@ -111,23 +107,6 @@
 		return -EINVAL;
 
 	return 0;
-#else
-	struct platform_device *pdev = to_platform_device(fep->dev);
-	struct resource	*r;
-
-	/* Fill out IRQ field */
-	fep->interrupt = platform_get_irq_byname(pdev,"interrupt");
-	if (fep->interrupt < 0)
-		return -EINVAL;
-
-	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
-	fep->fec.fecp = ioremap(r->start, r->end - r->start + 1);
-
-	if(fep->fec.fecp == NULL)
-		return -EINVAL;
-
-	return 0;
-#endif
 }
 
 #define FEC_NAPI_RX_EVENT_MSK	(FEC_ENET_RXF | FEC_ENET_RXB)
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c
index e3557ec..029b3c7e 100644
--- a/drivers/net/fs_enet/mac-scc.c
+++ b/drivers/net/fs_enet/mac-scc.c
@@ -32,6 +32,7 @@
 #include <linux/bitops.h>
 #include <linux/fs.h>
 #include <linux/platform_device.h>
+#include <linux/of_platform.h>
 
 #include <asm/irq.h>
 #include <asm/uaccess.h>
@@ -43,10 +44,6 @@
 #include <asm/cpm1.h>
 #endif
 
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
-#include <linux/of_platform.h>
-#endif
-
 #include "fs_enet.h"
 
 /*************************************************/
@@ -99,7 +96,6 @@
 
 static int do_pd_setup(struct fs_enet_private *fep)
 {
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
 	struct of_device *ofdev = to_of_device(fep->dev);
 
 	fep->interrupt = of_irq_to_resource(ofdev->node, 0, NULL);
@@ -115,27 +111,6 @@
 		iounmap(fep->scc.sccp);
 		return -EINVAL;
 	}
-#else
-	struct platform_device *pdev = to_platform_device(fep->dev);
-	struct resource *r;
-
-	/* Fill out IRQ field */
-	fep->interrupt = platform_get_irq_byname(pdev, "interrupt");
-	if (fep->interrupt < 0)
-		return -EINVAL;
-
-	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
-	fep->scc.sccp = ioremap(r->start, r->end - r->start + 1);
-
-	if (fep->scc.sccp == NULL)
-		return -EINVAL;
-
-	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pram");
-	fep->scc.ep = ioremap(r->start, r->end - r->start + 1);
-
-	if (fep->scc.ep == NULL)
-		return -EINVAL;
-#endif
 
 	return 0;
 }
@@ -149,16 +124,6 @@
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
 
-#ifndef CONFIG_PPC_CPM_NEW_BINDING
-	struct fs_platform_info *fpi = fep->fpi;
-
-	fep->scc.idx = fs_get_scc_index(fpi->fs_no);
-	if ((unsigned int)fep->fcc.idx >= 4) /* max 4 SCCs */
-		return -EINVAL;
-
-	fpi->cp_command = fep->fcc.idx << 6;
-#endif
-
 	do_pd_setup(fep);
 
 	fep->scc.hthi = 0;
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
index 1620030..be4b72f 100644
--- a/drivers/net/fs_enet/mii-bitbang.c
+++ b/drivers/net/fs_enet/mii-bitbang.c
@@ -22,10 +22,7 @@
 #include <linux/mii.h>
 #include <linux/platform_device.h>
 #include <linux/mdio-bitbang.h>
-
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
 #include <linux/of_platform.h>
-#endif
 
 #include "fs_enet.h"
 
@@ -110,7 +107,6 @@
 	.get_mdio_data = mdio_read,
 };
 
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
 static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
                                          struct device_node *np)
 {
@@ -271,106 +267,3 @@
 
 module_init(fs_enet_mdio_bb_init);
 module_exit(fs_enet_mdio_bb_exit);
-#else
-static int __devinit fs_mii_bitbang_init(struct bb_info *bitbang,
-                                         struct fs_mii_bb_platform_info *fmpi)
-{
-	bitbang->dir = (u32 __iomem *)fmpi->mdio_dir.offset;
-	bitbang->dat = (u32 __iomem *)fmpi->mdio_dat.offset;
-	bitbang->mdio_msk = 1U << (31 - fmpi->mdio_dat.bit);
-	bitbang->mdc_msk = 1U << (31 - fmpi->mdc_dat.bit);
-
-	return 0;
-}
-
-static int __devinit fs_enet_mdio_probe(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct fs_mii_bb_platform_info *pdata;
-	struct mii_bus *new_bus;
-	struct bb_info *bitbang;
-	int err = 0;
-
-	if (NULL == dev)
-		return -EINVAL;
-
-	bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
-
-	if (NULL == bitbang)
-		return -ENOMEM;
-
-	bitbang->ctrl.ops = &bb_ops;
-
-	new_bus = alloc_mdio_bitbang(&bitbang->ctrl);
-
-	if (NULL == new_bus)
-		return -ENOMEM;
-
-	new_bus->name = "BB MII Bus",
-	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
-
-	new_bus->phy_mask = ~0x9;
-	pdata = (struct fs_mii_bb_platform_info *)pdev->dev.platform_data;
-
-	if (NULL == pdata) {
-		printk(KERN_ERR "gfar mdio %d: Missing platform data!\n", pdev->id);
-		return -ENODEV;
-	}
-
-	/*set up workspace*/
-	fs_mii_bitbang_init(bitbang, pdata);
-
-	new_bus->priv = bitbang;
-
-	new_bus->irq = pdata->irq;
-
-	new_bus->dev = dev;
-	dev_set_drvdata(dev, new_bus);
-
-	err = mdiobus_register(new_bus);
-
-	if (0 != err) {
-		printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
-				new_bus->name);
-		goto bus_register_fail;
-	}
-
-	return 0;
-
-bus_register_fail:
-	free_mdio_bitbang(new_bus);
-	kfree(bitbang);
-
-	return err;
-}
-
-static int fs_enet_mdio_remove(struct device *dev)
-{
-	struct mii_bus *bus = dev_get_drvdata(dev);
-
-	mdiobus_unregister(bus);
-
-	dev_set_drvdata(dev, NULL);
-
-	free_mdio_bitbang(bus);
-
-	return 0;
-}
-
-static struct device_driver fs_enet_bb_mdio_driver = {
-	.name = "fsl-bb-mdio",
-	.bus = &platform_bus_type,
-	.probe = fs_enet_mdio_probe,
-	.remove = fs_enet_mdio_remove,
-};
-
-int fs_enet_mdio_bb_init(void)
-{
-	return driver_register(&fs_enet_bb_mdio_driver);
-}
-
-void fs_enet_mdio_bb_exit(void)
-{
-	driver_unregister(&fs_enet_bb_mdio_driver);
-}
-#endif
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
index 8f6a43b..695f74c 100644
--- a/drivers/net/fs_enet/mii-fec.c
+++ b/drivers/net/fs_enet/mii-fec.c
@@ -31,15 +31,12 @@
 #include <linux/ethtool.h>
 #include <linux/bitops.h>
 #include <linux/platform_device.h>
+#include <linux/of_platform.h>
 
 #include <asm/pgtable.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
-#include <linux/of_platform.h>
-#endif
-
 #include "fs_enet.h"
 #include "fec.h"
 
@@ -51,52 +48,6 @@
 
 #define FEC_MII_LOOPS	10000
 
-#ifndef CONFIG_PPC_CPM_NEW_BINDING
-static int match_has_phy (struct device *dev, void* data)
-{
-	struct platform_device* pdev = container_of(dev, struct platform_device, dev);
-	struct fs_platform_info* fpi;
-	if(strcmp(pdev->name, (char*)data))
-	{
-	    return 0;
-	}
-
-	fpi = pdev->dev.platform_data;
-	if((fpi)&&(fpi->has_phy))
-		return 1;
-	return 0;
-}
-
-static int fs_mii_fec_init(struct fec_info* fec, struct fs_mii_fec_platform_info *fmpi)
-{
-	struct resource *r;
-	fec_t __iomem *fecp;
-	char* name = "fsl-cpm-fec";
-
-	/* we need fec in order to be useful */
-	struct platform_device *fec_pdev =
-		container_of(bus_find_device(&platform_bus_type, NULL, name, match_has_phy),
-				struct platform_device, dev);
-
-	if(fec_pdev == NULL) {
-		printk(KERN_ERR"Unable to find PHY for %s", name);
-		return -ENODEV;
-	}
-
-	r = platform_get_resource_byname(fec_pdev, IORESOURCE_MEM, "regs");
-
-	fec->fecp = fecp = ioremap(r->start,sizeof(fec_t));
-	fec->mii_speed = fmpi->mii_speed;
-
-	setbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);	/* MII enable */
-	setbits32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
-	out_be32(&fecp->fec_ievent, FEC_ENET_MII);
-	out_be32(&fecp->fec_mii_speed, fec->mii_speed);
-
-	return 0;
-}
-#endif
-
 static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location)
 {
 	struct fec_info* fec = bus->priv;
@@ -151,7 +102,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
 static void __devinit add_phy(struct mii_bus *bus, struct device_node *np)
 {
 	const u32 *data;
@@ -286,95 +236,3 @@
 
 module_init(fs_enet_mdio_fec_init);
 module_exit(fs_enet_mdio_fec_exit);
-#else
-static int __devinit fs_enet_fec_mdio_probe(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct fs_mii_fec_platform_info *pdata;
-	struct mii_bus *new_bus;
-	struct fec_info *fec;
-	int err = 0;
-	if (NULL == dev)
-		return -EINVAL;
-	new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
-
-	if (NULL == new_bus)
-		return -ENOMEM;
-
-	fec = kzalloc(sizeof(struct fec_info), GFP_KERNEL);
-
-	if (NULL == fec)
-		return -ENOMEM;
-
-	new_bus->name = "FEC MII Bus",
-	new_bus->read = &fs_enet_fec_mii_read,
-	new_bus->write = &fs_enet_fec_mii_write,
-	new_bus->reset = &fs_enet_fec_mii_reset,
-	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
-
-	pdata = (struct fs_mii_fec_platform_info *)pdev->dev.platform_data;
-
-	if (NULL == pdata) {
-		printk(KERN_ERR "fs_enet FEC mdio %d: Missing platform data!\n", pdev->id);
-		return -ENODEV;
-	}
-
-	/*set up workspace*/
-
-	fs_mii_fec_init(fec, pdata);
-	new_bus->priv = fec;
-
-	new_bus->irq = pdata->irq;
-
-	new_bus->dev = dev;
-	dev_set_drvdata(dev, new_bus);
-
-	err = mdiobus_register(new_bus);
-
-	if (0 != err) {
-		printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
-				new_bus->name);
-		goto bus_register_fail;
-	}
-
-	return 0;
-
-bus_register_fail:
-	kfree(new_bus);
-
-	return err;
-}
-
-
-static int fs_enet_fec_mdio_remove(struct device *dev)
-{
-	struct mii_bus *bus = dev_get_drvdata(dev);
-
-	mdiobus_unregister(bus);
-
-	dev_set_drvdata(dev, NULL);
-	kfree(bus->priv);
-
-	bus->priv = NULL;
-	kfree(bus);
-
-	return 0;
-}
-
-static struct device_driver fs_enet_fec_mdio_driver = {
-	.name = "fsl-cpm-fec-mdio",
-	.bus = &platform_bus_type,
-	.probe = fs_enet_fec_mdio_probe,
-	.remove = fs_enet_fec_mdio_remove,
-};
-
-int fs_enet_mdio_fec_init(void)
-{
-	return driver_register(&fs_enet_fec_mdio_driver);
-}
-
-void fs_enet_mdio_fec_exit(void)
-{
-	driver_unregister(&fs_enet_fec_mdio_driver);
-}
-#endif
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 45a6317..b8394cf1 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -134,6 +134,9 @@
 static void gfar_vlan_rx_register(struct net_device *netdev,
 		                struct vlan_group *grp);
 void gfar_halt(struct net_device *dev);
+#ifdef CONFIG_PM
+static void gfar_halt_nodisable(struct net_device *dev);
+#endif
 void gfar_start(struct net_device *dev);
 static void gfar_clear_exact_match(struct net_device *dev);
 static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr);
@@ -207,6 +210,7 @@
 
 	spin_lock_init(&priv->txlock);
 	spin_lock_init(&priv->rxlock);
+	spin_lock_init(&priv->bflock);
 
 	platform_set_drvdata(pdev, dev);
 
@@ -378,6 +382,103 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static int gfar_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+	struct gfar_private *priv = netdev_priv(dev);
+	unsigned long flags;
+	u32 tempval;
+
+	int magic_packet = priv->wol_en &&
+		(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+
+	netif_device_detach(dev);
+
+	if (netif_running(dev)) {
+		spin_lock_irqsave(&priv->txlock, flags);
+		spin_lock(&priv->rxlock);
+
+		gfar_halt_nodisable(dev);
+
+		/* Disable Tx, and Rx if wake-on-LAN is disabled. */
+		tempval = gfar_read(&priv->regs->maccfg1);
+
+		tempval &= ~MACCFG1_TX_EN;
+
+		if (!magic_packet)
+			tempval &= ~MACCFG1_RX_EN;
+
+		gfar_write(&priv->regs->maccfg1, tempval);
+
+		spin_unlock(&priv->rxlock);
+		spin_unlock_irqrestore(&priv->txlock, flags);
+
+#ifdef CONFIG_GFAR_NAPI
+		napi_disable(&priv->napi);
+#endif
+
+		if (magic_packet) {
+			/* Enable interrupt on Magic Packet */
+			gfar_write(&priv->regs->imask, IMASK_MAG);
+
+			/* Enable Magic Packet mode */
+			tempval = gfar_read(&priv->regs->maccfg2);
+			tempval |= MACCFG2_MPEN;
+			gfar_write(&priv->regs->maccfg2, tempval);
+		} else {
+			phy_stop(priv->phydev);
+		}
+	}
+
+	return 0;
+}
+
+static int gfar_resume(struct platform_device *pdev)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+	struct gfar_private *priv = netdev_priv(dev);
+	unsigned long flags;
+	u32 tempval;
+	int magic_packet = priv->wol_en &&
+		(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+
+	if (!netif_running(dev)) {
+		netif_device_attach(dev);
+		return 0;
+	}
+
+	if (!magic_packet && priv->phydev)
+		phy_start(priv->phydev);
+
+	/* Disable Magic Packet mode, in case something
+	 * else woke us up.
+	 */
+
+	spin_lock_irqsave(&priv->txlock, flags);
+	spin_lock(&priv->rxlock);
+
+	tempval = gfar_read(&priv->regs->maccfg2);
+	tempval &= ~MACCFG2_MPEN;
+	gfar_write(&priv->regs->maccfg2, tempval);
+
+	gfar_start(dev);
+
+	spin_unlock(&priv->rxlock);
+	spin_unlock_irqrestore(&priv->txlock, flags);
+
+	netif_device_attach(dev);
+
+#ifdef CONFIG_GFAR_NAPI
+	napi_enable(&priv->napi);
+#endif
+
+	return 0;
+}
+#else
+#define gfar_suspend NULL
+#define gfar_resume NULL
+#endif
 
 /* Reads the controller's registers to determine what interface
  * connects it to the PHY.
@@ -534,8 +635,9 @@
 }
 
 
+#ifdef CONFIG_PM
 /* Halt the receive and transmit queues */
-void gfar_halt(struct net_device *dev)
+static void gfar_halt_nodisable(struct net_device *dev)
 {
 	struct gfar_private *priv = netdev_priv(dev);
 	struct gfar __iomem *regs = priv->regs;
@@ -558,6 +660,15 @@
 			 (IEVENT_GRSC | IEVENT_GTSC)))
 			cpu_relax();
 	}
+}
+#endif
+
+/* Halt the receive and transmit queues */
+void gfar_halt(struct net_device *dev)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+	struct gfar __iomem *regs = priv->regs;
+	u32 tempval;
 
 	/* Disable Rx and Tx */
 	tempval = gfar_read(&regs->maccfg1);
@@ -1725,7 +1836,6 @@
 		if (!priv->oldlink) {
 			new_state = 1;
 			priv->oldlink = 1;
-			netif_tx_schedule_all(dev);
 		}
 	} else if (priv->oldlink) {
 		new_state = 1;
@@ -1910,7 +2020,12 @@
 	u32 events = gfar_read(&priv->regs->ievent);
 
 	/* Clear IEVENT */
-	gfar_write(&priv->regs->ievent, IEVENT_ERR_MASK);
+	gfar_write(&priv->regs->ievent, events & IEVENT_ERR_MASK);
+
+	/* Magic Packet is not an error. */
+	if ((priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) &&
+	    (events & IEVENT_MAG))
+		events &= ~IEVENT_MAG;
 
 	/* Hmm... */
 	if (netif_msg_rx_err(priv) || netif_msg_tx_err(priv))
@@ -1978,6 +2093,8 @@
 static struct platform_driver gfar_driver = {
 	.probe = gfar_probe,
 	.remove = gfar_remove,
+	.suspend = gfar_suspend,
+	.resume = gfar_resume,
 	.driver	= {
 		.name = "fsl-gianfar",
 		.owner = THIS_MODULE,
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index bead71c..d59df98 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -157,6 +157,7 @@
 #define MACCFG2_GMII            0x00000200
 #define MACCFG2_HUGEFRAME	0x00000020
 #define MACCFG2_LENGTHCHECK	0x00000010
+#define MACCFG2_MPEN		0x00000008
 
 #define ECNTRL_INIT_SETTINGS	0x00001000
 #define ECNTRL_TBI_MODE         0x00000020
@@ -229,6 +230,7 @@
 #define IEVENT_CRL		0x00020000
 #define IEVENT_XFUN		0x00010000
 #define IEVENT_RXB0		0x00008000
+#define IEVENT_MAG		0x00000800
 #define IEVENT_GRSC		0x00000100
 #define IEVENT_RXF0		0x00000080
 #define IEVENT_FIR		0x00000008
@@ -241,7 +243,8 @@
 #define IEVENT_ERR_MASK         \
 (IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \
  IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC \
- | IEVENT_CRL | IEVENT_XFUN | IEVENT_DPE | IEVENT_PERR)
+ | IEVENT_CRL | IEVENT_XFUN | IEVENT_DPE | IEVENT_PERR \
+ | IEVENT_MAG)
 
 #define IMASK_INIT_CLEAR	0x00000000
 #define IMASK_BABR              0x80000000
@@ -259,6 +262,7 @@
 #define IMASK_CRL		0x00020000
 #define IMASK_XFUN		0x00010000
 #define IMASK_RXB0              0x00008000
+#define IMASK_MAG		0x00000800
 #define IMASK_GTSC              0x00000100
 #define IMASK_RXFEN0		0x00000080
 #define IMASK_FIR		0x00000008
@@ -726,10 +730,14 @@
 	unsigned int fifo_starve;
 	unsigned int fifo_starve_off;
 
+	/* Bitfield update lock */
+	spinlock_t bflock;
+
 	unsigned char vlan_enable:1,
 		rx_csum_enable:1,
 		extended_hash:1,
-		bd_stash_en:1;
+		bd_stash_en:1,
+		wol_en:1; /* Wake-on-LAN enabled */
 	unsigned short padding;
 
 	unsigned int interruptTransmit;
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index 6007147..fb7d3cc 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -479,14 +479,13 @@
 static int gfar_set_rx_csum(struct net_device *dev, uint32_t data)
 {
 	struct gfar_private *priv = netdev_priv(dev);
+	unsigned long flags;
 	int err = 0;
 
 	if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
 		return -EOPNOTSUPP;
 
 	if (dev->flags & IFF_UP) {
-		unsigned long flags;
-
 		/* Halt TX and RX, and process the frames which
 		 * have already been received */
 		spin_lock_irqsave(&priv->txlock, flags);
@@ -502,7 +501,9 @@
 		stop_gfar(dev);
 	}
 
+	spin_lock_irqsave(&priv->bflock, flags);
 	priv->rx_csum_enable = data;
+	spin_unlock_irqrestore(&priv->bflock, flags);
 
 	if (dev->flags & IFF_UP)
 		err = startup_gfar(dev);
@@ -564,6 +565,38 @@
 	priv->msg_enable = data;
 }
 
+#ifdef CONFIG_PM
+static void gfar_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+
+	if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) {
+		wol->supported = WAKE_MAGIC;
+		wol->wolopts = priv->wol_en ? WAKE_MAGIC : 0;
+	} else {
+		wol->supported = wol->wolopts = 0;
+	}
+}
+
+static int gfar_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+	unsigned long flags;
+
+	if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) &&
+	    wol->wolopts != 0)
+		return -EINVAL;
+
+	if (wol->wolopts & ~WAKE_MAGIC)
+		return -EINVAL;
+
+	spin_lock_irqsave(&priv->bflock, flags);
+	priv->wol_en = wol->wolopts & WAKE_MAGIC ? 1 : 0;
+	spin_unlock_irqrestore(&priv->bflock, flags);
+
+	return 0;
+}
+#endif
 
 const struct ethtool_ops gfar_ethtool_ops = {
 	.get_settings = gfar_gsettings,
@@ -585,4 +618,8 @@
 	.set_tx_csum = gfar_set_tx_csum,
 	.get_msglevel = gfar_get_msglevel,
 	.set_msglevel = gfar_set_msglevel,
+#ifdef CONFIG_PM
+	.get_wol = gfar_get_wol,
+	.set_wol = gfar_set_wol,
+#endif
 };
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index b6500b2..58f4b1d 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -123,6 +123,7 @@
  * off into a separate class since they always nest.
  */
 static struct lock_class_key bpq_netdev_xmit_lock_key;
+static struct lock_class_key bpq_netdev_addr_lock_key;
 
 static void bpq_set_lockdep_class_one(struct net_device *dev,
 				      struct netdev_queue *txq,
@@ -133,6 +134,7 @@
 
 static void bpq_set_lockdep_class(struct net_device *dev)
 {
+	lockdep_set_class(&dev->addr_list_lock, &bpq_netdev_addr_lock_key);
 	netdev_for_each_tx_queue(dev, bpq_set_lockdep_class_one, NULL);
 }
 
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
index ae9629f..c258a05 100644
--- a/drivers/net/hamradio/hdlcdrv.c
+++ b/drivers/net/hamradio/hdlcdrv.c
@@ -88,6 +88,7 @@
 static inline void append_crc_ccitt(unsigned char *buffer, int len)
 {
  	unsigned int crc = crc_ccitt(0xffff, buffer, len) ^ 0xffff;
+	buffer += len;
 	*buffer++ = crc;
 	*buffer++ = crc >> 8;
 }
diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c
index c2c4f49..8239939 100644
--- a/drivers/net/hp-plus.c
+++ b/drivers/net/hp-plus.c
@@ -262,7 +262,7 @@
 	}
 
 	outw(Perf_Page, ioaddr + HP_PAGING);
-	NS8390_init(dev, 0);
+	NS8390p_init(dev, 0);
 	/* Leave the 8390 and HP chip reset. */
 	outw(inw(ioaddr + HPP_OPTION) & ~EnableIRQ, ioaddr + HPP_OPTION);
 
diff --git a/drivers/net/hp.c b/drivers/net/hp.c
index 8281209..0a8c649 100644
--- a/drivers/net/hp.c
+++ b/drivers/net/hp.c
@@ -389,7 +389,7 @@
 hp_init_card(struct net_device *dev)
 {
 	int irq = dev->irq;
-	NS8390_init(dev, 0);
+	NS8390p_init(dev, 0);
 	outb_p(irqmap[irq&0x0f] | HP_RUN,
 		   dev->base_addr - NIC_OFFSET + HP_CONFIGURE);
 	return;
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 1b7cb29..b602c4d 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -385,7 +385,7 @@
 
 	for (i = 0; i < adapter->num_rx_queues; i++) {
 		struct igb_ring *rx_ring = &adapter->rx_ring[i];
-		rx_ring->buddy = 0;
+		rx_ring->buddy = NULL;
 		igb_assign_vector(adapter, i, IGB_N0_QUEUE, vector++);
 		adapter->eims_enable_mask |= rx_ring->eims_value;
 		if (rx_ring->itr_val)
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index be7b723..e5f3da8 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -70,8 +70,6 @@
 	 board_82598 },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_SINGLE_PORT),
 	 board_82598 },
-	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AT_DUAL_PORT),
-	 board_82598 },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_CX4),
 	 board_82598 },
 
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 0496d16..daba82b 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -164,9 +164,7 @@
 	}
 
 	if (phydev->link != bp->link) {
-		if (phydev->link)
-			netif_tx_schedule_all(dev);
-		else {
+		if (!phydev->link) {
 			bp->speed = 0;
 			bp->duplex = -1;
 		}
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index efbc155..4239450 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -276,6 +276,7 @@
  * separate class since they always nest.
  */
 static struct lock_class_key macvlan_netdev_xmit_lock_key;
+static struct lock_class_key macvlan_netdev_addr_lock_key;
 
 #define MACVLAN_FEATURES \
 	(NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \
@@ -295,6 +296,8 @@
 
 static void macvlan_set_lockdep_class(struct net_device *dev)
 {
+	lockdep_set_class(&dev->addr_list_lock,
+			  &macvlan_netdev_addr_lock_key);
 	netdev_for_each_tx_queue(dev, macvlan_set_lockdep_class_one, NULL);
 }
 
diff --git a/drivers/net/meth.c b/drivers/net/meth.c
index 0b32648..4cb364e 100644
--- a/drivers/net/meth.c
+++ b/drivers/net/meth.c
@@ -287,7 +287,7 @@
 
 	/* Initial mode: 10 | Half-duplex | Accept normal packets */
 	priv->mac_ctrl = METH_ACCEPT_MCAST | METH_DEFAULT_IPG;
-	if (dev->flags | IFF_PROMISC)
+	if (dev->flags & IFF_PROMISC)
 		priv->mac_ctrl |= METH_PROMISC;
 	mace->eth.mac_ctrl = priv->mac_ctrl;
 
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 83a877f..8a97a00 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -2112,7 +2112,7 @@
 
 	mv643xx_eth_irq(dev->irq, dev);
 
-	wrl(mp, INT_MASK(mp->port_num), INT_TX_END | INT_RX | INT_CAUSE_EXT);
+	wrl(mp, INT_MASK(mp->port_num), INT_TX_END | INT_RX | INT_EXT);
 }
 #endif
 
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index b3981ed..3ab0e52 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -125,7 +125,6 @@
 
 struct myri10ge_rx_buf {
 	struct mcp_kreq_ether_recv __iomem *lanai;	/* lanai ptr for recv ring */
-	u8 __iomem *wc_fifo;	/* w/c rx dma addr fifo address */
 	struct mcp_kreq_ether_recv *shadow;	/* host shadow of recv ring */
 	struct myri10ge_rx_buffer_state *info;
 	struct page *page;
@@ -140,7 +139,6 @@
 
 struct myri10ge_tx_buf {
 	struct mcp_kreq_ether_send __iomem *lanai;	/* lanai ptr for sendq */
-	u8 __iomem *wc_fifo;	/* w/c send fifo address */
 	struct mcp_kreq_ether_send *req_list;	/* host shadow of sendq */
 	char *req_bytes;
 	struct myri10ge_tx_buffer_state *info;
@@ -332,10 +330,6 @@
 
 static int myri10ge_reset_recover = 1;
 
-static int myri10ge_wcfifo = 0;
-module_param(myri10ge_wcfifo, int, S_IRUGO);
-MODULE_PARM_DESC(myri10ge_wcfifo, "Enable WC Fifo when WC is enabled");
-
 static int myri10ge_max_slices = 1;
 module_param(myri10ge_max_slices, int, S_IRUGO);
 MODULE_PARM_DESC(myri10ge_max_slices, "Max tx/rx queues");
@@ -1218,14 +1212,8 @@
 
 		/* copy 8 descriptors to the firmware at a time */
 		if ((idx & 7) == 7) {
-			if (rx->wc_fifo == NULL)
-				myri10ge_submit_8rx(&rx->lanai[idx - 7],
-						    &rx->shadow[idx - 7]);
-			else {
-				mb();
-				myri10ge_pio_copy(rx->wc_fifo,
-						  &rx->shadow[idx - 7], 64);
-			}
+			myri10ge_submit_8rx(&rx->lanai[idx - 7],
+					    &rx->shadow[idx - 7]);
 		}
 	}
 }
@@ -2229,18 +2217,6 @@
 	ss->rx_big.lanai = (struct mcp_kreq_ether_recv __iomem *)
 	    (mgp->sram + cmd.data0);
 
-	if (myri10ge_wcfifo && mgp->wc_enabled) {
-		ss->tx.wc_fifo = (u8 __iomem *)
-		    mgp->sram + MXGEFW_ETH_SEND_4 + 64 * slice;
-		ss->rx_small.wc_fifo = (u8 __iomem *)
-		    mgp->sram + MXGEFW_ETH_RECV_SMALL + 64 * slice;
-		ss->rx_big.wc_fifo = (u8 __iomem *)
-		    mgp->sram + MXGEFW_ETH_RECV_BIG + 64 * slice;
-	} else {
-		ss->tx.wc_fifo = NULL;
-		ss->rx_small.wc_fifo = NULL;
-		ss->rx_big.wc_fifo = NULL;
-	}
 	return status;
 
 }
@@ -2573,27 +2549,6 @@
 	mb();
 }
 
-static inline void
-myri10ge_submit_req_wc(struct myri10ge_tx_buf *tx,
-		       struct mcp_kreq_ether_send *src, int cnt)
-{
-	tx->req += cnt;
-	mb();
-	while (cnt >= 4) {
-		myri10ge_pio_copy(tx->wc_fifo, src, 64);
-		mb();
-		src += 4;
-		cnt -= 4;
-	}
-	if (cnt > 0) {
-		/* pad it to 64 bytes.  The src is 64 bytes bigger than it
-		 * needs to be so that we don't overrun it */
-		myri10ge_pio_copy(tx->wc_fifo + MXGEFW_ETH_SEND_OFFSET(cnt),
-				  src, 64);
-		mb();
-	}
-}
-
 /*
  * Transmit a packet.  We need to split the packet so that a single
  * segment does not cross myri10ge->tx_boundary, so this makes segment
@@ -2830,10 +2785,7 @@
 					 MXGEFW_FLAGS_FIRST)));
 	idx = ((count - 1) + tx->req) & tx->mask;
 	tx->info[idx].last = 1;
-	if (tx->wc_fifo == NULL)
-		myri10ge_submit_req(tx, tx->req_list, count);
-	else
-		myri10ge_submit_req_wc(tx, tx->req_list, count);
+	myri10ge_submit_req(tx, tx->req_list, count);
 	tx->pkt_start++;
 	if ((avail - count) < MXGEFW_MAX_SEND_DESC) {
 		tx->stop_queue++;
@@ -3768,14 +3720,14 @@
 	if (mgp->sram_size > mgp->board_span) {
 		dev_err(&pdev->dev, "board span %ld bytes too small\n",
 			mgp->board_span);
-		goto abort_with_wc;
+		goto abort_with_mtrr;
 	}
-	mgp->sram = ioremap(mgp->iomem_base, mgp->board_span);
+	mgp->sram = ioremap_wc(mgp->iomem_base, mgp->board_span);
 	if (mgp->sram == NULL) {
 		dev_err(&pdev->dev, "ioremap failed for %ld bytes at 0x%lx\n",
 			mgp->board_span, mgp->iomem_base);
 		status = -ENXIO;
-		goto abort_with_wc;
+		goto abort_with_mtrr;
 	}
 	memcpy_fromio(mgp->eeprom_strings,
 		      mgp->sram + mgp->sram_size - MYRI10GE_EEPROM_STRINGS_SIZE,
@@ -3876,7 +3828,7 @@
 abort_with_ioremap:
 	iounmap(mgp->sram);
 
-abort_with_wc:
+abort_with_mtrr:
 #ifdef CONFIG_MTRR
 	if (mgp->mtrr >= 0)
 		mtrr_del(mgp->mtrr, mgp->iomem_base, mgp->board_span);
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index 1412697..2fec612 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -355,7 +355,7 @@
 	}
 
 	/* Read the 16 bytes of station address PROM.
-	   We must first initialize registers, similar to NS8390_init(eifdev, 0).
+	   We must first initialize registers, similar to NS8390p_init(eifdev, 0).
 	   We can't reliably read the SAPROM address without this.
 	   (I learned the hard way!). */
 	{
diff --git a/drivers/net/ne2.c b/drivers/net/ne2.c
index 8f72563..332df75a 100644
--- a/drivers/net/ne2.c
+++ b/drivers/net/ne2.c
@@ -404,7 +404,7 @@
 
 	/* Read the 16 bytes of station address PROM.
 	   We must first initialize registers, similar to
-	   NS8390_init(eifdev, 0).
+	   NS8390p_init(eifdev, 0).
 	   We can't reliably read the SAPROM address without this.
 	   (I learned the hard way!). */
 	{
diff --git a/drivers/net/netxen/Makefile b/drivers/net/netxen/Makefile
index a07cdc6..8e7c4c9 100644
--- a/drivers/net/netxen/Makefile
+++ b/drivers/net/netxen/Makefile
@@ -32,4 +32,4 @@
 obj-$(CONFIG_NETXEN_NIC) := netxen_nic.o
 
 netxen_nic-y := netxen_nic_hw.o netxen_nic_main.o netxen_nic_init.o \
-	netxen_nic_isr.o netxen_nic_ethtool.o netxen_nic_niu.o
+	netxen_nic_ethtool.o netxen_nic_niu.o netxen_nic_ctx.o
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index da4c4fb..8e73661 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -54,6 +54,7 @@
 
 #include <linux/mm.h>
 #include <linux/mman.h>
+#include <linux/vmalloc.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -63,10 +64,12 @@
 
 #include "netxen_nic_hw.h"
 
-#define _NETXEN_NIC_LINUX_MAJOR 3
-#define _NETXEN_NIC_LINUX_MINOR 4
-#define _NETXEN_NIC_LINUX_SUBVERSION 18
-#define NETXEN_NIC_LINUX_VERSIONID  "3.4.18"
+#define _NETXEN_NIC_LINUX_MAJOR 4
+#define _NETXEN_NIC_LINUX_MINOR 0
+#define _NETXEN_NIC_LINUX_SUBVERSION 0
+#define NETXEN_NIC_LINUX_VERSIONID  "4.0.0"
+
+#define NETXEN_VERSION_CODE(a, b, c)	(((a) << 16) + ((b) << 8) + (c))
 
 #define NETXEN_NUM_FLASH_SECTORS (64)
 #define NETXEN_FLASH_SECTOR_SIZE (64 * 1024)
@@ -84,7 +87,7 @@
 #define TX_RINGSIZE	\
 	(sizeof(struct netxen_cmd_buffer) * adapter->max_tx_desc_count)
 #define RCV_BUFFSIZE	\
-	(sizeof(struct netxen_rx_buffer) * rcv_desc->max_rx_desc_count)
+	(sizeof(struct netxen_rx_buffer) * rds_ring->max_rx_desc_count)
 #define find_diff_among(a,b,range) ((a)<(b)?((b)-(a)):((b)+(range)-(a)))
 
 #define NETXEN_NETDEV_STATUS		0x1
@@ -111,6 +114,13 @@
 
 #define NX_P2_C0		0x24
 #define NX_P2_C1		0x25
+#define NX_P3_A0		0x30
+#define NX_P3_A2		0x30
+#define NX_P3_B0		0x40
+#define NX_P3_B1		0x41
+
+#define NX_IS_REVISION_P2(REVISION)     (REVISION <= NX_P2_C1)
+#define NX_IS_REVISION_P3(REVISION)     (REVISION >= NX_P3_A0)
 
 #define FIRST_PAGE_GROUP_START	0
 #define FIRST_PAGE_GROUP_END	0x100000
@@ -125,6 +135,16 @@
 #define SECOND_PAGE_GROUP_SIZE SECOND_PAGE_GROUP_END - SECOND_PAGE_GROUP_START
 #define THIRD_PAGE_GROUP_SIZE  THIRD_PAGE_GROUP_END - THIRD_PAGE_GROUP_START
 
+#define P2_MAX_MTU                     (8000)
+#define P3_MAX_MTU                     (9600)
+#define NX_ETHERMTU                    1500
+#define NX_MAX_ETHERHDR                32 /* This contains some padding */
+
+#define NX_RX_NORMAL_BUF_MAX_LEN       (NX_MAX_ETHERHDR + NX_ETHERMTU)
+#define NX_P2_RX_JUMBO_BUF_MAX_LEN     (NX_MAX_ETHERHDR + P2_MAX_MTU)
+#define NX_P3_RX_JUMBO_BUF_MAX_LEN     (NX_MAX_ETHERHDR + P3_MAX_MTU)
+#define NX_CT_DEFAULT_RX_BUF_LEN	2048
+
 #define MAX_RX_BUFFER_LENGTH		1760
 #define MAX_RX_JUMBO_BUFFER_LENGTH 	8062
 #define MAX_RX_LRO_BUFFER_LENGTH	((48*1024)-512)
@@ -132,7 +152,6 @@
 #define RX_JUMBO_DMA_MAP_LEN	\
 	(MAX_RX_JUMBO_BUFFER_LENGTH - 2)
 #define RX_LRO_DMA_MAP_LEN		(MAX_RX_LRO_BUFFER_LENGTH - 2)
-#define NETXEN_ROM_ROUNDUP		0x80000000ULL
 
 /*
  * Maximum number of ring contexts
@@ -140,16 +159,16 @@
 #define MAX_RING_CTX 1
 
 /* Opcodes to be used with the commands */
-enum {
-	TX_ETHER_PKT = 0x01,
-/* The following opcodes are for IP checksum	*/
-	TX_TCP_PKT,
-	TX_UDP_PKT,
-	TX_IP_PKT,
-	TX_TCP_LSO,
-	TX_IPSEC,
-	TX_IPSEC_CMD
-};
+#define TX_ETHER_PKT	0x01
+#define TX_TCP_PKT	0x02
+#define TX_UDP_PKT	0x03
+#define TX_IP_PKT	0x04
+#define TX_TCP_LSO	0x05
+#define TX_TCP_LSO6	0x06
+#define TX_IPSEC	0x07
+#define TX_IPSEC_CMD	0x0a
+#define TX_TCPV6_PKT	0x0b
+#define TX_UDPV6_PKT	0x0c
 
 /* The following opcodes are for internal consumption. */
 #define NETXEN_CONTROL_OP	0x10
@@ -191,6 +210,7 @@
 #define MAX_RCV_DESCRIPTORS		16384
 #define MAX_CMD_DESCRIPTORS_HOST	(MAX_CMD_DESCRIPTORS / 4)
 #define MAX_RCV_DESCRIPTORS_1G		(MAX_RCV_DESCRIPTORS / 4)
+#define MAX_RCV_DESCRIPTORS_10G		8192
 #define MAX_JUMBO_RCV_DESCRIPTORS	1024
 #define MAX_LRO_RCV_DESCRIPTORS		64
 #define MAX_RCVSTATUS_DESCRIPTORS	MAX_RCV_DESCRIPTORS
@@ -219,8 +239,6 @@
 #define MPORT_MULTI_FUNCTION_MODE 0x2222
 
 #include "netxen_nic_phan_reg.h"
-extern unsigned long long netxen_dma_mask;
-extern unsigned long last_schedule_time;
 
 /*
  * NetXen host-peg signal message structure
@@ -289,7 +307,7 @@
 #define netxen_set_cmd_desc_port(cmd_desc, var)	\
 	((cmd_desc)->port_ctxid |= ((var) & 0x0F))
 #define netxen_set_cmd_desc_ctxid(cmd_desc, var)	\
-	((cmd_desc)->port_ctxid |= ((var) & 0xF0))
+	((cmd_desc)->port_ctxid |= ((var) << 4 & 0xF0))
 
 #define netxen_set_cmd_desc_flags(cmd_desc, val)	\
 	(cmd_desc)->flags_opcode = ((cmd_desc)->flags_opcode & \
@@ -377,8 +395,8 @@
 };
 
 /* opcode field in status_desc */
-#define RCV_NIC_PKT	(0xA)
-#define STATUS_NIC_PKT	((RCV_NIC_PKT) << 12)
+#define NETXEN_NIC_RXPKT_DESC  0x04
+#define NETXEN_OLD_RXPKT_DESC  0x3f
 
 /* for status field in status_desc */
 #define STATUS_NEED_CKSUM	(1)
@@ -410,6 +428,8 @@
 	(((sts_data) >> 28) & 0xFFFF)
 #define netxen_get_sts_prot(sts_data)	\
 	(((sts_data) >> 44) & 0x0F)
+#define netxen_get_sts_pkt_offset(sts_data)	\
+	(((sts_data) >> 48) & 0x1F)
 #define netxen_get_sts_opcode(sts_data)	\
 	(((sts_data) >> 58) & 0x03F)
 
@@ -424,17 +444,30 @@
 
 struct status_desc {
 	/* Bit pattern: 0-3 port, 4-7 status, 8-11 type, 12-27 total_length
-	   28-43 reference_handle, 44-47 protocol, 48-52 unused
+	   28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset
 	   53-55 desc_cnt, 56-57 owner, 58-63 opcode
 	 */
 	__le64 status_desc_data;
-	__le32 hash_value;
-	u8 hash_type;
-	u8 msg_type;
-	u8 unused;
-	/* Bit pattern: 0-6 lro_count indicates frag sequence,
-	   7 last_frag indicates last frag */
-	u8 lro;
+	union {
+		struct {
+			__le32 hash_value;
+			u8 hash_type;
+			u8 msg_type;
+			u8 unused;
+			union {
+				/* Bit pattern: 0-6 lro_count indicates frag
+				 * sequence, 7 last_frag indicates last frag
+				 */
+				u8 lro;
+
+				/* chained buffers */
+				u8 nr_frags;
+			};
+		};
+		struct {
+			__le16 frag_handles[4];
+		};
+	};
 } __attribute__ ((aligned(16)));
 
 enum {
@@ -464,7 +497,20 @@
 
 	NETXEN_BRDTYPE_P2_SB31_10G_IMEZ = 0x000d,
 	NETXEN_BRDTYPE_P2_SB31_10G_HMEZ = 0x000e,
-	NETXEN_BRDTYPE_P2_SB31_10G_CX4 = 0x000f
+	NETXEN_BRDTYPE_P2_SB31_10G_CX4 = 0x000f,
+
+	NETXEN_BRDTYPE_P3_REF_QG = 0x0021,
+	NETXEN_BRDTYPE_P3_HMEZ = 0x0022,
+	NETXEN_BRDTYPE_P3_10G_CX4_LP = 0x0023,
+	NETXEN_BRDTYPE_P3_4_GB = 0x0024,
+	NETXEN_BRDTYPE_P3_IMEZ = 0x0025,
+	NETXEN_BRDTYPE_P3_10G_SFP_PLUS = 0x0026,
+	NETXEN_BRDTYPE_P3_10000_BASE_T = 0x0027,
+	NETXEN_BRDTYPE_P3_XG_LOM = 0x0028,
+	NETXEN_BRDTYPE_P3_4_GB_MM = 0x0029,
+	NETXEN_BRDTYPE_P3_10G_CX4 = 0x0031,
+	NETXEN_BRDTYPE_P3_10G_XFP = 0x0032
+
 } netxen_brdtype_t;
 
 typedef enum {
@@ -747,6 +793,7 @@
 
 /* In rx_buffer, we do not need multiple fragments as is a single buffer */
 struct netxen_rx_buffer {
+	struct list_head list;
 	struct sk_buff *skb;
 	u64 dma;
 	u16 ref_handle;
@@ -765,7 +812,6 @@
  * contains interrupt info as well shared hardware info.
  */
 struct netxen_hardware_context {
-	struct pci_dev *pdev;
 	void __iomem *pci_base0;
 	void __iomem *pci_base1;
 	void __iomem *pci_base2;
@@ -773,15 +819,20 @@
 	unsigned long first_page_group_start;
 	void __iomem *db_base;
 	unsigned long db_len;
+	unsigned long pci_len0;
+
+	u8 cut_through;
+	int qdr_sn_window;
+	int ddr_mn_window;
+	unsigned long mn_win_crb;
+	unsigned long ms_win_crb;
 
 	u8 revision_id;
 	u16 board_type;
 	struct netxen_board_info boardcfg;
-	u32 xg_linkup;
-	u32 qg_linksup;
+	u32 linkup;
 	/* Address of cmd ring in Phantom */
 	struct cmd_desc_type0 *cmd_desc_head;
-	struct pci_dev *cmd_desc_pdev;
 	dma_addr_t cmd_desc_phys_addr;
 	struct netxen_adapter *adapter;
 	int pci_func;
@@ -813,17 +864,17 @@
  * Rcv Descriptor Context. One such per Rcv Descriptor. There may
  * be one Rcv Descriptor for normal packets, one for jumbo and may be others.
  */
-struct netxen_rcv_desc_ctx {
+struct nx_host_rds_ring {
 	u32 flags;
 	u32 producer;
-	u32 rcv_pending;	/* Num of bufs posted in phantom */
 	dma_addr_t phys_addr;
-	struct pci_dev *phys_pdev;
+	u32 crb_rcv_producer;	/* reg offset */
 	struct rcv_desc *desc_head;	/* address of rx ring in Phantom */
 	u32 max_rx_desc_count;
 	u32 dma_size;
 	u32 skb_size;
 	struct netxen_rx_buffer *rx_buf_arr;	/* rx buffers for receive   */
+	struct list_head free_list;
 	int begin_alloc;
 };
 
@@ -834,17 +885,319 @@
  * present elsewhere.
  */
 struct netxen_recv_context {
-	struct netxen_rcv_desc_ctx rcv_desc[NUM_RCV_DESC_RINGS];
-	u32 status_rx_producer;
+	u32 state;
+	u16 context_id;
+	u16 virt_port;
+
+	struct nx_host_rds_ring rds_rings[NUM_RCV_DESC_RINGS];
 	u32 status_rx_consumer;
+	u32 crb_sts_consumer;	/* reg offset */
 	dma_addr_t rcv_status_desc_phys_addr;
-	struct pci_dev *rcv_status_desc_pdev;
 	struct status_desc *rcv_status_desc_head;
 };
 
-#define NETXEN_NIC_MSI_ENABLED 0x02
-#define NETXEN_DMA_MASK	0xfffffffe
-#define NETXEN_DB_MAPSIZE_BYTES    0x1000
+/* New HW context creation */
+
+#define NX_OS_CRB_RETRY_COUNT	4000
+#define NX_CDRP_SIGNATURE_MAKE(pcifn, version) \
+	(((pcifn) & 0xff) | (((version) & 0xff) << 8) | (0xcafe << 16))
+
+#define NX_CDRP_CLEAR		0x00000000
+#define NX_CDRP_CMD_BIT		0x80000000
+
+/*
+ * All responses must have the NX_CDRP_CMD_BIT cleared
+ * in the crb NX_CDRP_CRB_OFFSET.
+ */
+#define NX_CDRP_FORM_RSP(rsp)	(rsp)
+#define NX_CDRP_IS_RSP(rsp)	(((rsp) & NX_CDRP_CMD_BIT) == 0)
+
+#define NX_CDRP_RSP_OK		0x00000001
+#define NX_CDRP_RSP_FAIL	0x00000002
+#define NX_CDRP_RSP_TIMEOUT	0x00000003
+
+/*
+ * All commands must have the NX_CDRP_CMD_BIT set in
+ * the crb NX_CDRP_CRB_OFFSET.
+ */
+#define NX_CDRP_FORM_CMD(cmd)	(NX_CDRP_CMD_BIT | (cmd))
+#define NX_CDRP_IS_CMD(cmd)	(((cmd) & NX_CDRP_CMD_BIT) != 0)
+
+#define NX_CDRP_CMD_SUBMIT_CAPABILITIES     0x00000001
+#define NX_CDRP_CMD_READ_MAX_RDS_PER_CTX    0x00000002
+#define NX_CDRP_CMD_READ_MAX_SDS_PER_CTX    0x00000003
+#define NX_CDRP_CMD_READ_MAX_RULES_PER_CTX  0x00000004
+#define NX_CDRP_CMD_READ_MAX_RX_CTX         0x00000005
+#define NX_CDRP_CMD_READ_MAX_TX_CTX         0x00000006
+#define NX_CDRP_CMD_CREATE_RX_CTX           0x00000007
+#define NX_CDRP_CMD_DESTROY_RX_CTX          0x00000008
+#define NX_CDRP_CMD_CREATE_TX_CTX           0x00000009
+#define NX_CDRP_CMD_DESTROY_TX_CTX          0x0000000a
+#define NX_CDRP_CMD_SETUP_STATISTICS        0x0000000e
+#define NX_CDRP_CMD_GET_STATISTICS          0x0000000f
+#define NX_CDRP_CMD_DELETE_STATISTICS       0x00000010
+#define NX_CDRP_CMD_SET_MTU                 0x00000012
+#define NX_CDRP_CMD_MAX                     0x00000013
+
+#define NX_RCODE_SUCCESS		0
+#define NX_RCODE_NO_HOST_MEM		1
+#define NX_RCODE_NO_HOST_RESOURCE	2
+#define NX_RCODE_NO_CARD_CRB		3
+#define NX_RCODE_NO_CARD_MEM		4
+#define NX_RCODE_NO_CARD_RESOURCE	5
+#define NX_RCODE_INVALID_ARGS		6
+#define NX_RCODE_INVALID_ACTION		7
+#define NX_RCODE_INVALID_STATE		8
+#define NX_RCODE_NOT_SUPPORTED		9
+#define NX_RCODE_NOT_PERMITTED		10
+#define NX_RCODE_NOT_READY		11
+#define NX_RCODE_DOES_NOT_EXIST		12
+#define NX_RCODE_ALREADY_EXISTS		13
+#define NX_RCODE_BAD_SIGNATURE		14
+#define NX_RCODE_CMD_NOT_IMPL		15
+#define NX_RCODE_CMD_INVALID		16
+#define NX_RCODE_TIMEOUT		17
+#define NX_RCODE_CMD_FAILED		18
+#define NX_RCODE_MAX_EXCEEDED		19
+#define NX_RCODE_MAX			20
+
+#define NX_DESTROY_CTX_RESET		0
+#define NX_DESTROY_CTX_D3_RESET		1
+#define NX_DESTROY_CTX_MAX		2
+
+/*
+ * Capabilities
+ */
+#define NX_CAP_BIT(class, bit)		(1 << bit)
+#define NX_CAP0_LEGACY_CONTEXT		NX_CAP_BIT(0, 0)
+#define NX_CAP0_MULTI_CONTEXT		NX_CAP_BIT(0, 1)
+#define NX_CAP0_LEGACY_MN		NX_CAP_BIT(0, 2)
+#define NX_CAP0_LEGACY_MS		NX_CAP_BIT(0, 3)
+#define NX_CAP0_CUT_THROUGH		NX_CAP_BIT(0, 4)
+#define NX_CAP0_LRO			NX_CAP_BIT(0, 5)
+#define NX_CAP0_LSO			NX_CAP_BIT(0, 6)
+#define NX_CAP0_JUMBO_CONTIGUOUS	NX_CAP_BIT(0, 7)
+#define NX_CAP0_LRO_CONTIGUOUS		NX_CAP_BIT(0, 8)
+
+/*
+ * Context state
+ */
+#define NX_HOST_CTX_STATE_FREED		0
+#define NX_HOST_CTX_STATE_ALLOCATED	1
+#define NX_HOST_CTX_STATE_ACTIVE	2
+#define NX_HOST_CTX_STATE_DISABLED	3
+#define NX_HOST_CTX_STATE_QUIESCED	4
+#define NX_HOST_CTX_STATE_MAX		5
+
+/*
+ * Rx context
+ */
+
+typedef struct {
+	u64 host_phys_addr;	/* Ring base addr */
+	u32 ring_size;		/* Ring entries */
+	u16 msi_index;
+	u16 rsvd;		/* Padding */
+} nx_hostrq_sds_ring_t;
+
+typedef struct {
+	u64 host_phys_addr;	/* Ring base addr */
+	u64 buff_size;		/* Packet buffer size */
+	u32 ring_size;		/* Ring entries */
+	u32 ring_kind;		/* Class of ring */
+} nx_hostrq_rds_ring_t;
+
+typedef struct {
+	u64 host_rsp_dma_addr;	/* Response dma'd here */
+	u32 capabilities[4];	/* Flag bit vector */
+	u32 host_int_crb_mode;	/* Interrupt crb usage */
+	u32 host_rds_crb_mode;	/* RDS crb usage */
+	/* These ring offsets are relative to data[0] below */
+	u32 rds_ring_offset;	/* Offset to RDS config */
+	u32 sds_ring_offset;	/* Offset to SDS config */
+	u16 num_rds_rings;	/* Count of RDS rings */
+	u16 num_sds_rings;	/* Count of SDS rings */
+	u16 rsvd1;		/* Padding */
+	u16 rsvd2;		/* Padding */
+	u8  reserved[128]; 	/* reserve space for future expansion*/
+	/* MUST BE 64-bit aligned.
+	   The following is packed:
+	   - N hostrq_rds_rings
+	   - N hostrq_sds_rings */
+	char data[0];
+} nx_hostrq_rx_ctx_t;
+
+typedef struct {
+	u32 host_producer_crb;	/* Crb to use */
+	u32 rsvd1;		/* Padding */
+} nx_cardrsp_rds_ring_t;
+
+typedef struct {
+	u32 host_consumer_crb;	/* Crb to use */
+	u32 interrupt_crb;	/* Crb to use */
+} nx_cardrsp_sds_ring_t;
+
+typedef struct {
+	/* These ring offsets are relative to data[0] below */
+	u32 rds_ring_offset;	/* Offset to RDS config */
+	u32 sds_ring_offset;	/* Offset to SDS config */
+	u32 host_ctx_state;	/* Starting State */
+	u32 num_fn_per_port;	/* How many PCI fn share the port */
+	u16 num_rds_rings;	/* Count of RDS rings */
+	u16 num_sds_rings;	/* Count of SDS rings */
+	u16 context_id;		/* Handle for context */
+	u8  phys_port;		/* Physical id of port */
+	u8  virt_port;		/* Virtual/Logical id of port */
+	u8  reserved[128];	/* save space for future expansion */
+	/*  MUST BE 64-bit aligned.
+	   The following is packed:
+	   - N cardrsp_rds_rings
+	   - N cardrs_sds_rings */
+	char data[0];
+} nx_cardrsp_rx_ctx_t;
+
+#define SIZEOF_HOSTRQ_RX(HOSTRQ_RX, rds_rings, sds_rings)	\
+	(sizeof(HOSTRQ_RX) + 					\
+	(rds_rings)*(sizeof(nx_hostrq_rds_ring_t)) +		\
+	(sds_rings)*(sizeof(nx_hostrq_sds_ring_t)))
+
+#define SIZEOF_CARDRSP_RX(CARDRSP_RX, rds_rings, sds_rings) 	\
+	(sizeof(CARDRSP_RX) + 					\
+	(rds_rings)*(sizeof(nx_cardrsp_rds_ring_t)) + 		\
+	(sds_rings)*(sizeof(nx_cardrsp_sds_ring_t)))
+
+/*
+ * Tx context
+ */
+
+typedef struct {
+	u64 host_phys_addr;	/* Ring base addr */
+	u32 ring_size;		/* Ring entries */
+	u32 rsvd;		/* Padding */
+} nx_hostrq_cds_ring_t;
+
+typedef struct {
+	u64 host_rsp_dma_addr;	/* Response dma'd here */
+	u64 cmd_cons_dma_addr;	/*  */
+	u64 dummy_dma_addr;	/*  */
+	u32 capabilities[4];	/* Flag bit vector */
+	u32 host_int_crb_mode;	/* Interrupt crb usage */
+	u32 rsvd1;		/* Padding */
+	u16 rsvd2;		/* Padding */
+	u16 interrupt_ctl;
+	u16 msi_index;
+	u16 rsvd3;		/* Padding */
+	nx_hostrq_cds_ring_t cds_ring;	/* Desc of cds ring */
+	u8  reserved[128];	/* future expansion */
+} nx_hostrq_tx_ctx_t;
+
+typedef struct {
+	u32 host_producer_crb;	/* Crb to use */
+	u32 interrupt_crb;	/* Crb to use */
+} nx_cardrsp_cds_ring_t;
+
+typedef struct {
+	u32 host_ctx_state;	/* Starting state */
+	u16 context_id;		/* Handle for context */
+	u8  phys_port;		/* Physical id of port */
+	u8  virt_port;		/* Virtual/Logical id of port */
+	nx_cardrsp_cds_ring_t cds_ring;	/* Card cds settings */
+	u8  reserved[128];	/* future expansion */
+} nx_cardrsp_tx_ctx_t;
+
+#define SIZEOF_HOSTRQ_TX(HOSTRQ_TX)	(sizeof(HOSTRQ_TX))
+#define SIZEOF_CARDRSP_TX(CARDRSP_TX)	(sizeof(CARDRSP_TX))
+
+/* CRB */
+
+#define NX_HOST_RDS_CRB_MODE_UNIQUE	0
+#define NX_HOST_RDS_CRB_MODE_SHARED	1
+#define NX_HOST_RDS_CRB_MODE_CUSTOM	2
+#define NX_HOST_RDS_CRB_MODE_MAX	3
+
+#define NX_HOST_INT_CRB_MODE_UNIQUE	0
+#define NX_HOST_INT_CRB_MODE_SHARED	1
+#define NX_HOST_INT_CRB_MODE_NORX	2
+#define NX_HOST_INT_CRB_MODE_NOTX	3
+#define NX_HOST_INT_CRB_MODE_NORXTX	4
+
+
+/* MAC */
+
+#define MC_COUNT_P2	16
+#define MC_COUNT_P3	38
+
+#define NETXEN_MAC_NOOP	0
+#define NETXEN_MAC_ADD	1
+#define NETXEN_MAC_DEL	2
+
+typedef struct nx_mac_list_s {
+	struct nx_mac_list_s *next;
+	uint8_t mac_addr[MAX_ADDR_LEN];
+} nx_mac_list_t;
+
+/*
+ * Interrupt coalescing defaults. The defaults are for 1500 MTU. It is
+ * adjusted based on configured MTU.
+ */
+#define NETXEN_DEFAULT_INTR_COALESCE_RX_TIME_US	3
+#define NETXEN_DEFAULT_INTR_COALESCE_RX_PACKETS	256
+#define NETXEN_DEFAULT_INTR_COALESCE_TX_PACKETS	64
+#define NETXEN_DEFAULT_INTR_COALESCE_TX_TIME_US	4
+
+#define NETXEN_NIC_INTR_DEFAULT			0x04
+
+typedef union {
+	struct {
+		uint16_t	rx_packets;
+		uint16_t	rx_time_us;
+		uint16_t	tx_packets;
+		uint16_t	tx_time_us;
+	} data;
+	uint64_t		word;
+} nx_nic_intr_coalesce_data_t;
+
+typedef struct {
+	uint16_t			stats_time_us;
+	uint16_t			rate_sample_time;
+	uint16_t			flags;
+	uint16_t			rsvd_1;
+	uint32_t			low_threshold;
+	uint32_t			high_threshold;
+	nx_nic_intr_coalesce_data_t	normal;
+	nx_nic_intr_coalesce_data_t	low;
+	nx_nic_intr_coalesce_data_t	high;
+	nx_nic_intr_coalesce_data_t	irq;
+} nx_nic_intr_coalesce_t;
+
+typedef struct {
+	u64 qhdr;
+	u64 req_hdr;
+	u64 words[6];
+} nx_nic_req_t;
+
+typedef struct {
+	u8 op;
+	u8 tag;
+	u8 mac_addr[6];
+} nx_mac_req_t;
+
+#define MAX_PENDING_DESC_BLOCK_SIZE	64
+
+#define NETXEN_NIC_MSI_ENABLED		0x02
+#define NETXEN_NIC_MSIX_ENABLED		0x04
+#define NETXEN_IS_MSI_FAMILY(adapter) \
+	((adapter)->flags & (NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED))
+
+#define MSIX_ENTRIES_PER_ADAPTER	8
+#define NETXEN_MSIX_TBL_SPACE		8192
+#define NETXEN_PCI_REG_MSIX_TBL		0x44
+
+#define NETXEN_DB_MAPSIZE_BYTES    	0x1000
+
+#define NETXEN_NETDEV_WEIGHT 120
+#define NETXEN_ADAPTER_UP_MAGIC 777
+#define NETXEN_NIC_PEG_TUNE 0
 
 struct netxen_dummy_dma {
 	void *addr;
@@ -854,46 +1207,65 @@
 struct netxen_adapter {
 	struct netxen_hardware_context ahw;
 
-	struct netxen_adapter *master;
 	struct net_device *netdev;
 	struct pci_dev *pdev;
+	int pci_using_dac;
 	struct napi_struct napi;
 	struct net_device_stats net_stats;
-	unsigned char mac_addr[ETH_ALEN];
 	int mtu;
 	int portnum;
 	u8 physical_port;
+	u16 tx_context_id;
+
+	uint8_t		mc_enabled;
+	uint8_t		max_mc_count;
+	nx_mac_list_t	*mac_list;
+
+	struct netxen_legacy_intr_set legacy_intr;
+	u32	crb_intr_mask;
 
 	struct work_struct watchdog_task;
 	struct timer_list watchdog_timer;
 	struct work_struct  tx_timeout_task;
 
 	u32 curr_window;
+	u32 crb_win;
+	rwlock_t adapter_lock;
+
+	uint64_t dma_mask;
 
 	u32 cmd_producer;
 	__le32 *cmd_consumer;
 	u32 last_cmd_consumer;
+	u32 crb_addr_cmd_producer;
+	u32 crb_addr_cmd_consumer;
 
 	u32 max_tx_desc_count;
 	u32 max_rx_desc_count;
 	u32 max_jumbo_rx_desc_count;
 	u32 max_lro_rx_desc_count;
 
+	int max_rds_rings;
+
 	u32 flags;
 	u32 irq;
 	int driver_mismatch;
 	u32 temp;
 
+	u32 fw_major;
+
+	u8 msix_supported;
+	u8 max_possible_rss_rings;
+	struct msix_entry msix_entries[MSIX_ENTRIES_PER_ADAPTER];
+
 	struct netxen_adapter_stats stats;
 
-	u16 portno;
 	u16 link_speed;
 	u16 link_duplex;
 	u16 state;
 	u16 link_autoneg;
 	int rx_csum;
 	int status;
-	spinlock_t stats_lock;
 
 	struct netxen_cmd_buffer *cmd_buf_arr;	/* Command buffers for xmit */
 
@@ -905,25 +1277,33 @@
 
 	int is_up;
 	struct netxen_dummy_dma dummy_dma;
+	nx_nic_intr_coalesce_t coal;
 
 	/* Context interface shared between card and host */
 	struct netxen_ring_ctx *ctx_desc;
-	struct pci_dev *ctx_desc_pdev;
 	dma_addr_t ctx_desc_phys_addr;
 	int intr_scheme;
 	int msi_mode;
 	int (*enable_phy_interrupts) (struct netxen_adapter *);
 	int (*disable_phy_interrupts) (struct netxen_adapter *);
-	void (*handle_phy_intr) (struct netxen_adapter *);
 	int (*macaddr_set) (struct netxen_adapter *, netxen_ethernet_macaddr_t);
 	int (*set_mtu) (struct netxen_adapter *, int);
 	int (*set_promisc) (struct netxen_adapter *, netxen_niu_prom_mode_t);
-	int (*unset_promisc) (struct netxen_adapter *, netxen_niu_prom_mode_t);
 	int (*phy_read) (struct netxen_adapter *, long reg, u32 *);
 	int (*phy_write) (struct netxen_adapter *, long reg, u32 val);
 	int (*init_port) (struct netxen_adapter *, int);
-	void (*init_niu) (struct netxen_adapter *);
 	int (*stop_port) (struct netxen_adapter *);
+
+	int (*hw_read_wx)(struct netxen_adapter *, ulong, void *, int);
+	int (*hw_write_wx)(struct netxen_adapter *, ulong, void *, int);
+	int (*pci_mem_read)(struct netxen_adapter *, u64, void *, int);
+	int (*pci_mem_write)(struct netxen_adapter *, u64, void *, int);
+	int (*pci_write_immediate)(struct netxen_adapter *, u64, u32);
+	u32 (*pci_read_immediate)(struct netxen_adapter *, u64);
+	void (*pci_write_normalize)(struct netxen_adapter *, u64, u32);
+	u32 (*pci_read_normalize)(struct netxen_adapter *, u64);
+	unsigned long (*pci_set_window)(struct netxen_adapter *,
+			unsigned long long);
 };				/* netxen_adapter structure */
 
 /*
@@ -988,8 +1368,6 @@
 int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter);
 int netxen_niu_xgbe_disable_phy_interrupts(struct netxen_adapter *adapter);
 int netxen_niu_gbe_disable_phy_interrupts(struct netxen_adapter *adapter);
-void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter);
-void netxen_nic_gbe_handle_phy_intr(struct netxen_adapter *adapter);
 int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
 			    __u32 * readval);
 int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter,
@@ -998,27 +1376,61 @@
 /* Functions available from netxen_nic_hw.c */
 int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu);
 int netxen_nic_set_mtu_gb(struct netxen_adapter *adapter, int new_mtu);
-void netxen_nic_init_niu_gb(struct netxen_adapter *adapter);
-void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw);
 void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val);
 int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off);
 void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value);
-void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 * value);
+void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 *value);
+void netxen_nic_write_w1(struct netxen_adapter *adapter, u32 index, u32 value);
+void netxen_nic_read_w1(struct netxen_adapter *adapter, u32 index, u32 *value);
 
 int netxen_nic_get_board_info(struct netxen_adapter *adapter);
-int netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data,
-			  int len);
-int netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
-			   int len);
+
+int netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter,
+		ulong off, void *data, int len);
+int netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter,
+		ulong off, void *data, int len);
+int netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter,
+		u64 off, void *data, int size);
+int netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter,
+		u64 off, void *data, int size);
+int netxen_nic_pci_write_immediate_128M(struct netxen_adapter *adapter,
+		u64 off, u32 data);
+u32 netxen_nic_pci_read_immediate_128M(struct netxen_adapter *adapter, u64 off);
+void netxen_nic_pci_write_normalize_128M(struct netxen_adapter *adapter,
+		u64 off, u32 data);
+u32 netxen_nic_pci_read_normalize_128M(struct netxen_adapter *adapter, u64 off);
+unsigned long netxen_nic_pci_set_window_128M(struct netxen_adapter *adapter,
+		unsigned long long addr);
+void netxen_nic_pci_change_crbwindow_128M(struct netxen_adapter *adapter,
+		u32 wndw);
+
+int netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter,
+		ulong off, void *data, int len);
+int netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter,
+		ulong off, void *data, int len);
+int netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter,
+		u64 off, void *data, int size);
+int netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter,
+		u64 off, void *data, int size);
 void netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
 				 unsigned long off, int data);
+int netxen_nic_pci_write_immediate_2M(struct netxen_adapter *adapter,
+		u64 off, u32 data);
+u32 netxen_nic_pci_read_immediate_2M(struct netxen_adapter *adapter, u64 off);
+void netxen_nic_pci_write_normalize_2M(struct netxen_adapter *adapter,
+		u64 off, u32 data);
+u32 netxen_nic_pci_read_normalize_2M(struct netxen_adapter *adapter, u64 off);
+unsigned long netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter,
+		unsigned long long addr);
 
 /* Functions from netxen_nic_init.c */
 void netxen_free_adapter_offload(struct netxen_adapter *adapter);
 int netxen_initialize_adapter_offload(struct netxen_adapter *adapter);
 int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val);
+int netxen_receive_peg_ready(struct netxen_adapter *adapter);
 int netxen_load_firmware(struct netxen_adapter *adapter);
 int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose);
+
 int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp);
 int netxen_rom_fast_read_words(struct netxen_adapter *adapter, int addr,
 				u8 *bytes, size_t size);
@@ -1032,33 +1444,43 @@
 
 int netxen_rom_se(struct netxen_adapter *adapter, int addr);
 
-/* Functions from netxen_nic_isr.c */
-void netxen_initialize_adapter_sw(struct netxen_adapter *adapter);
-void *netxen_alloc(struct pci_dev *pdev, size_t sz, dma_addr_t * ptr,
-		   struct pci_dev **used_dev);
+int netxen_alloc_sw_resources(struct netxen_adapter *adapter);
+void netxen_free_sw_resources(struct netxen_adapter *adapter);
+
+int netxen_alloc_hw_resources(struct netxen_adapter *adapter);
+void netxen_free_hw_resources(struct netxen_adapter *adapter);
+
+void netxen_release_rx_buffers(struct netxen_adapter *adapter);
+void netxen_release_tx_buffers(struct netxen_adapter *adapter);
+
 void netxen_initialize_adapter_ops(struct netxen_adapter *adapter);
 int netxen_init_firmware(struct netxen_adapter *adapter);
-void netxen_free_hw_resources(struct netxen_adapter *adapter);
 void netxen_tso_check(struct netxen_adapter *adapter,
 		      struct cmd_desc_type0 *desc, struct sk_buff *skb);
-int netxen_nic_hw_resources(struct netxen_adapter *adapter);
 void netxen_nic_clear_stats(struct netxen_adapter *adapter);
 void netxen_watchdog_task(struct work_struct *work);
 void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx,
 			    u32 ringid);
 int netxen_process_cmd_ring(struct netxen_adapter *adapter);
 u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max);
-void netxen_nic_set_multi(struct net_device *netdev);
+void netxen_p2_nic_set_multi(struct net_device *netdev);
+void netxen_p3_nic_set_multi(struct net_device *netdev);
+int netxen_config_intr_coalesce(struct netxen_adapter *adapter);
+
+u32 nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, u32 mtu);
 int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu);
+
 int netxen_nic_set_mac(struct net_device *netdev, void *p);
 struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev);
 
+void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
+		uint32_t crb_producer);
 
 /*
  * NetXen Board information
  */
 
-#define NETXEN_MAX_SHORT_NAME 16
+#define NETXEN_MAX_SHORT_NAME 32
 struct netxen_brdinfo {
 	netxen_brdtype_t brdtype;	/* type of board */
 	long ports;		/* max no of physical ports */
@@ -1072,6 +1494,17 @@
 	{NETXEN_BRDTYPE_P2_SB31_10G, 1, "XGb XFP"},
 	{NETXEN_BRDTYPE_P2_SB35_4G, 4, "Quad Gb"},
 	{NETXEN_BRDTYPE_P2_SB31_2G, 2, "Dual Gb"},
+	{NETXEN_BRDTYPE_P3_REF_QG,  4, "Reference Quad Gig "},
+	{NETXEN_BRDTYPE_P3_HMEZ,    2, "Dual XGb HMEZ"},
+	{NETXEN_BRDTYPE_P3_10G_CX4_LP,   2, "Dual XGb CX4 LP"},
+	{NETXEN_BRDTYPE_P3_4_GB,    4, "Quad Gig LP"},
+	{NETXEN_BRDTYPE_P3_IMEZ,    2, "Dual XGb IMEZ"},
+	{NETXEN_BRDTYPE_P3_10G_SFP_PLUS, 2, "Dual XGb SFP+ LP"},
+	{NETXEN_BRDTYPE_P3_10000_BASE_T, 1, "XGB 10G BaseT LP"},
+	{NETXEN_BRDTYPE_P3_XG_LOM,  2, "Dual XGb LOM"},
+	{NETXEN_BRDTYPE_P3_4_GB_MM, 4, "Quad GB - March Madness"},
+	{NETXEN_BRDTYPE_P3_10G_CX4, 2, "Reference Dual CX4 Option"},
+	{NETXEN_BRDTYPE_P3_10G_XFP, 1, "Reference Single XFP Option"}
 };
 
 #define NUM_SUPPORTED_BOARDS ARRAY_SIZE(netxen_boards)
@@ -1097,7 +1530,7 @@
 	u32 ctrl;
 
 	/* check if already inactive */
-	if (netxen_nic_hw_read_wx(adapter,
+	if (adapter->hw_read_wx(adapter,
 	    NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
 		printk(KERN_ERR "failed to read dma watchdog status\n");
 
@@ -1117,7 +1550,7 @@
 {
 	u32 ctrl;
 
-	if (netxen_nic_hw_read_wx(adapter,
+	if (adapter->hw_read_wx(adapter,
 	    NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
 		printk(KERN_ERR "failed to read dma watchdog status\n");
 
@@ -1129,7 +1562,7 @@
 {
 	u32 ctrl;
 
-	if (netxen_nic_hw_read_wx(adapter,
+	if (adapter->hw_read_wx(adapter,
 		NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
 		printk(KERN_ERR "failed to read dma watchdog status\n");
 
diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c
new file mode 100644
index 0000000..64babc5
--- /dev/null
+++ b/drivers/net/netxen/netxen_nic_ctx.c
@@ -0,0 +1,710 @@
+/*
+ * Copyright (C) 2003 - 2008 NetXen, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  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.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.
+ *
+ * Contact Information:
+ *    info@netxen.com
+ * NetXen,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ *
+ */
+
+#include "netxen_nic_hw.h"
+#include "netxen_nic.h"
+#include "netxen_nic_phan_reg.h"
+
+#define NXHAL_VERSION	1
+
+static int
+netxen_api_lock(struct netxen_adapter *adapter)
+{
+	u32 done = 0, timeout = 0;
+
+	for (;;) {
+		/* Acquire PCIE HW semaphore5 */
+		netxen_nic_read_w0(adapter,
+			NETXEN_PCIE_REG(PCIE_SEM5_LOCK), &done);
+
+		if (done == 1)
+			break;
+
+		if (++timeout >= NX_OS_CRB_RETRY_COUNT) {
+			printk(KERN_ERR "%s: lock timeout.\n", __func__);
+			return -1;
+		}
+
+		msleep(1);
+	}
+
+#if 0
+	netxen_nic_write_w1(adapter,
+		NETXEN_API_LOCK_ID, NX_OS_API_LOCK_DRIVER);
+#endif
+	return 0;
+}
+
+static int
+netxen_api_unlock(struct netxen_adapter *adapter)
+{
+	u32 val;
+
+	/* Release PCIE HW semaphore5 */
+	netxen_nic_read_w0(adapter,
+		NETXEN_PCIE_REG(PCIE_SEM5_UNLOCK), &val);
+	return 0;
+}
+
+static u32
+netxen_poll_rsp(struct netxen_adapter *adapter)
+{
+	u32 raw_rsp, rsp = NX_CDRP_RSP_OK;
+	int	timeout = 0;
+
+	do {
+		/* give atleast 1ms for firmware to respond */
+		msleep(1);
+
+		if (++timeout > NX_OS_CRB_RETRY_COUNT)
+			return NX_CDRP_RSP_TIMEOUT;
+
+		netxen_nic_read_w1(adapter, NX_CDRP_CRB_OFFSET,
+				&raw_rsp);
+
+		rsp = le32_to_cpu(raw_rsp);
+	} while (!NX_CDRP_IS_RSP(rsp));
+
+	return rsp;
+}
+
+static u32
+netxen_issue_cmd(struct netxen_adapter *adapter,
+	u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd)
+{
+	u32 rsp;
+	u32 signature = 0;
+	u32 rcode = NX_RCODE_SUCCESS;
+
+	signature = NX_CDRP_SIGNATURE_MAKE(pci_fn, version);
+
+	/* Acquire semaphore before accessing CRB */
+	if (netxen_api_lock(adapter))
+		return NX_RCODE_TIMEOUT;
+
+	netxen_nic_write_w1(adapter, NX_SIGN_CRB_OFFSET,
+			cpu_to_le32(signature));
+
+	netxen_nic_write_w1(adapter, NX_ARG1_CRB_OFFSET,
+			cpu_to_le32(arg1));
+
+	netxen_nic_write_w1(adapter, NX_ARG2_CRB_OFFSET,
+			cpu_to_le32(arg2));
+
+	netxen_nic_write_w1(adapter, NX_ARG3_CRB_OFFSET,
+			cpu_to_le32(arg3));
+
+	netxen_nic_write_w1(adapter, NX_CDRP_CRB_OFFSET,
+			cpu_to_le32(NX_CDRP_FORM_CMD(cmd)));
+
+	rsp = netxen_poll_rsp(adapter);
+
+	if (rsp == NX_CDRP_RSP_TIMEOUT) {
+		printk(KERN_ERR "%s: card response timeout.\n",
+				netxen_nic_driver_name);
+
+		rcode = NX_RCODE_TIMEOUT;
+	} else if (rsp == NX_CDRP_RSP_FAIL) {
+		netxen_nic_read_w1(adapter, NX_ARG1_CRB_OFFSET, &rcode);
+		rcode = le32_to_cpu(rcode);
+
+		printk(KERN_ERR "%s: failed card response code:0x%x\n",
+				netxen_nic_driver_name, rcode);
+	}
+
+	/* Release semaphore */
+	netxen_api_unlock(adapter);
+
+	return rcode;
+}
+
+u32
+nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, u32 mtu)
+{
+	u32 rcode = NX_RCODE_SUCCESS;
+	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx[0];
+
+	if (recv_ctx->state == NX_HOST_CTX_STATE_ACTIVE)
+		rcode = netxen_issue_cmd(adapter,
+				adapter->ahw.pci_func,
+				NXHAL_VERSION,
+				recv_ctx->context_id,
+				mtu,
+				0,
+				NX_CDRP_CMD_SET_MTU);
+
+	return rcode;
+}
+
+static int
+nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
+{
+	void *addr;
+	nx_hostrq_rx_ctx_t *prq;
+	nx_cardrsp_rx_ctx_t *prsp;
+	nx_hostrq_rds_ring_t *prq_rds;
+	nx_hostrq_sds_ring_t *prq_sds;
+	nx_cardrsp_rds_ring_t *prsp_rds;
+	nx_cardrsp_sds_ring_t *prsp_sds;
+	struct nx_host_rds_ring *rds_ring;
+
+	dma_addr_t hostrq_phys_addr, cardrsp_phys_addr;
+	u64 phys_addr;
+
+	int i, nrds_rings, nsds_rings;
+	size_t rq_size, rsp_size;
+	u32 cap, reg;
+
+	int err;
+
+	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx[0];
+
+	/* only one sds ring for now */
+	nrds_rings = adapter->max_rds_rings;
+	nsds_rings = 1;
+
+	rq_size =
+		SIZEOF_HOSTRQ_RX(nx_hostrq_rx_ctx_t, nrds_rings, nsds_rings);
+	rsp_size =
+		SIZEOF_CARDRSP_RX(nx_cardrsp_rx_ctx_t, nrds_rings, nsds_rings);
+
+	addr = pci_alloc_consistent(adapter->pdev,
+				rq_size, &hostrq_phys_addr);
+	if (addr == NULL)
+		return -ENOMEM;
+	prq = (nx_hostrq_rx_ctx_t *)addr;
+
+	addr = pci_alloc_consistent(adapter->pdev,
+			rsp_size, &cardrsp_phys_addr);
+	if (addr == NULL) {
+		err = -ENOMEM;
+		goto out_free_rq;
+	}
+	prsp = (nx_cardrsp_rx_ctx_t *)addr;
+
+	prq->host_rsp_dma_addr = cpu_to_le64(cardrsp_phys_addr);
+
+	cap = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN);
+	cap |= (NX_CAP0_JUMBO_CONTIGUOUS | NX_CAP0_LRO_CONTIGUOUS);
+
+	prq->capabilities[0] = cpu_to_le32(cap);
+	prq->host_int_crb_mode =
+		cpu_to_le32(NX_HOST_INT_CRB_MODE_SHARED);
+	prq->host_rds_crb_mode =
+		cpu_to_le32(NX_HOST_RDS_CRB_MODE_UNIQUE);
+
+	prq->num_rds_rings = cpu_to_le16(nrds_rings);
+	prq->num_sds_rings = cpu_to_le16(nsds_rings);
+	prq->rds_ring_offset = 0;
+	prq->sds_ring_offset = prq->rds_ring_offset +
+		(sizeof(nx_hostrq_rds_ring_t) * nrds_rings);
+
+	prq_rds = (nx_hostrq_rds_ring_t *)(prq->data + prq->rds_ring_offset);
+
+	for (i = 0; i < nrds_rings; i++) {
+
+		rds_ring = &recv_ctx->rds_rings[i];
+
+		prq_rds[i].host_phys_addr = cpu_to_le64(rds_ring->phys_addr);
+		prq_rds[i].ring_size = cpu_to_le32(rds_ring->max_rx_desc_count);
+		prq_rds[i].ring_kind = cpu_to_le32(i);
+		prq_rds[i].buff_size = cpu_to_le64(rds_ring->dma_size);
+	}
+
+	prq_sds = (nx_hostrq_sds_ring_t *)(prq->data + prq->sds_ring_offset);
+
+	prq_sds[0].host_phys_addr =
+		cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr);
+	prq_sds[0].ring_size = cpu_to_le32(adapter->max_rx_desc_count);
+	/* only one msix vector for now */
+	prq_sds[0].msi_index = cpu_to_le32(0);
+
+	/* now byteswap offsets */
+	prq->rds_ring_offset = cpu_to_le32(prq->rds_ring_offset);
+	prq->sds_ring_offset = cpu_to_le32(prq->sds_ring_offset);
+
+	phys_addr = hostrq_phys_addr;
+	err = netxen_issue_cmd(adapter,
+			adapter->ahw.pci_func,
+			NXHAL_VERSION,
+			(u32)(phys_addr >> 32),
+			(u32)(phys_addr & 0xffffffff),
+			rq_size,
+			NX_CDRP_CMD_CREATE_RX_CTX);
+	if (err) {
+		printk(KERN_WARNING
+			"Failed to create rx ctx in firmware%d\n", err);
+		goto out_free_rsp;
+	}
+
+
+	prsp_rds = ((nx_cardrsp_rds_ring_t *)
+			 &prsp->data[prsp->rds_ring_offset]);
+
+	for (i = 0; i < le32_to_cpu(prsp->num_rds_rings); i++) {
+		rds_ring = &recv_ctx->rds_rings[i];
+
+		reg = le32_to_cpu(prsp_rds[i].host_producer_crb);
+		rds_ring->crb_rcv_producer = NETXEN_NIC_REG(reg - 0x200);
+	}
+
+	prsp_sds = ((nx_cardrsp_sds_ring_t *)
+			&prsp->data[prsp->sds_ring_offset]);
+	reg = le32_to_cpu(prsp_sds[0].host_consumer_crb);
+	recv_ctx->crb_sts_consumer = NETXEN_NIC_REG(reg - 0x200);
+
+	reg = le32_to_cpu(prsp_sds[0].interrupt_crb);
+	adapter->crb_intr_mask = NETXEN_NIC_REG(reg - 0x200);
+
+	recv_ctx->state = le32_to_cpu(prsp->host_ctx_state);
+	recv_ctx->context_id = le16_to_cpu(prsp->context_id);
+	recv_ctx->virt_port = le16_to_cpu(prsp->virt_port);
+
+out_free_rsp:
+	pci_free_consistent(adapter->pdev, rsp_size, prsp, cardrsp_phys_addr);
+out_free_rq:
+	pci_free_consistent(adapter->pdev, rq_size, prq, hostrq_phys_addr);
+	return err;
+}
+
+static void
+nx_fw_cmd_destroy_rx_ctx(struct netxen_adapter *adapter)
+{
+	struct netxen_recv_context *recv_ctx = &adapter->recv_ctx[0];
+
+	if (netxen_issue_cmd(adapter,
+			adapter->ahw.pci_func,
+			NXHAL_VERSION,
+			recv_ctx->context_id,
+			NX_DESTROY_CTX_RESET,
+			0,
+			NX_CDRP_CMD_DESTROY_RX_CTX)) {
+
+		printk(KERN_WARNING
+			"%s: Failed to destroy rx ctx in firmware\n",
+			netxen_nic_driver_name);
+	}
+}
+
+static int
+nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter)
+{
+	nx_hostrq_tx_ctx_t	*prq;
+	nx_hostrq_cds_ring_t	*prq_cds;
+	nx_cardrsp_tx_ctx_t	*prsp;
+	void	*rq_addr, *rsp_addr;
+	size_t	rq_size, rsp_size;
+	u32	temp;
+	int	err = 0;
+	u64	offset, phys_addr;
+	dma_addr_t	rq_phys_addr, rsp_phys_addr;
+
+	rq_size = SIZEOF_HOSTRQ_TX(nx_hostrq_tx_ctx_t);
+	rq_addr = pci_alloc_consistent(adapter->pdev,
+		rq_size, &rq_phys_addr);
+	if (!rq_addr)
+		return -ENOMEM;
+
+	rsp_size = SIZEOF_CARDRSP_TX(nx_cardrsp_tx_ctx_t);
+	rsp_addr = pci_alloc_consistent(adapter->pdev,
+		rsp_size, &rsp_phys_addr);
+	if (!rsp_addr) {
+		err = -ENOMEM;
+		goto out_free_rq;
+	}
+
+	memset(rq_addr, 0, rq_size);
+	prq = (nx_hostrq_tx_ctx_t *)rq_addr;
+
+	memset(rsp_addr, 0, rsp_size);
+	prsp = (nx_cardrsp_tx_ctx_t *)rsp_addr;
+
+	prq->host_rsp_dma_addr = cpu_to_le64(rsp_phys_addr);
+
+	temp = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN | NX_CAP0_LSO);
+	prq->capabilities[0] = cpu_to_le32(temp);
+
+	prq->host_int_crb_mode =
+		cpu_to_le32(NX_HOST_INT_CRB_MODE_SHARED);
+
+	prq->interrupt_ctl = 0;
+	prq->msi_index = 0;
+
+	prq->dummy_dma_addr = cpu_to_le64(adapter->dummy_dma.phys_addr);
+
+	offset = adapter->ctx_desc_phys_addr+sizeof(struct netxen_ring_ctx);
+	prq->cmd_cons_dma_addr = cpu_to_le64(offset);
+
+	prq_cds = &prq->cds_ring;
+
+	prq_cds->host_phys_addr =
+		cpu_to_le64(adapter->ahw.cmd_desc_phys_addr);
+
+	prq_cds->ring_size = cpu_to_le32(adapter->max_tx_desc_count);
+
+	phys_addr = rq_phys_addr;
+	err = netxen_issue_cmd(adapter,
+			adapter->ahw.pci_func,
+			NXHAL_VERSION,
+			(u32)(phys_addr >> 32),
+			((u32)phys_addr & 0xffffffff),
+			rq_size,
+			NX_CDRP_CMD_CREATE_TX_CTX);
+
+	if (err == NX_RCODE_SUCCESS) {
+		temp = le32_to_cpu(prsp->cds_ring.host_producer_crb);
+		adapter->crb_addr_cmd_producer =
+			NETXEN_NIC_REG(temp - 0x200);
+#if 0
+		adapter->tx_state =
+			le32_to_cpu(prsp->host_ctx_state);
+#endif
+		adapter->tx_context_id =
+			le16_to_cpu(prsp->context_id);
+	} else {
+		printk(KERN_WARNING
+			"Failed to create tx ctx in firmware%d\n", err);
+		err = -EIO;
+	}
+
+	pci_free_consistent(adapter->pdev, rsp_size, rsp_addr, rsp_phys_addr);
+
+out_free_rq:
+	pci_free_consistent(adapter->pdev, rq_size, rq_addr, rq_phys_addr);
+
+	return err;
+}
+
+static void
+nx_fw_cmd_destroy_tx_ctx(struct netxen_adapter *adapter)
+{
+	if (netxen_issue_cmd(adapter,
+			adapter->ahw.pci_func,
+			NXHAL_VERSION,
+			adapter->tx_context_id,
+			NX_DESTROY_CTX_RESET,
+			0,
+			NX_CDRP_CMD_DESTROY_TX_CTX)) {
+
+		printk(KERN_WARNING
+			"%s: Failed to destroy tx ctx in firmware\n",
+			netxen_nic_driver_name);
+	}
+}
+
+static u64 ctx_addr_sig_regs[][3] = {
+	{NETXEN_NIC_REG(0x188), NETXEN_NIC_REG(0x18c), NETXEN_NIC_REG(0x1c0)},
+	{NETXEN_NIC_REG(0x190), NETXEN_NIC_REG(0x194), NETXEN_NIC_REG(0x1c4)},
+	{NETXEN_NIC_REG(0x198), NETXEN_NIC_REG(0x19c), NETXEN_NIC_REG(0x1c8)},
+	{NETXEN_NIC_REG(0x1a0), NETXEN_NIC_REG(0x1a4), NETXEN_NIC_REG(0x1cc)}
+};
+
+#define CRB_CTX_ADDR_REG_LO(FUNC_ID)	(ctx_addr_sig_regs[FUNC_ID][0])
+#define CRB_CTX_ADDR_REG_HI(FUNC_ID)	(ctx_addr_sig_regs[FUNC_ID][2])
+#define CRB_CTX_SIGNATURE_REG(FUNC_ID)	(ctx_addr_sig_regs[FUNC_ID][1])
+
+#define lower32(x)	((u32)((x) & 0xffffffff))
+#define upper32(x)	((u32)(((u64)(x) >> 32) & 0xffffffff))
+
+static struct netxen_recv_crb recv_crb_registers[] = {
+	/* Instance 0 */
+	{
+		/* crb_rcv_producer: */
+		{
+			NETXEN_NIC_REG(0x100),
+			/* Jumbo frames */
+			NETXEN_NIC_REG(0x110),
+			/* LRO */
+			NETXEN_NIC_REG(0x120)
+		},
+		/* crb_sts_consumer: */
+		NETXEN_NIC_REG(0x138),
+	},
+	/* Instance 1 */
+	{
+		/* crb_rcv_producer: */
+		{
+			NETXEN_NIC_REG(0x144),
+			/* Jumbo frames */
+			NETXEN_NIC_REG(0x154),
+			/* LRO */
+			NETXEN_NIC_REG(0x164)
+		},
+		/* crb_sts_consumer: */
+		NETXEN_NIC_REG(0x17c),
+	},
+	/* Instance 2 */
+	{
+		/* crb_rcv_producer: */
+		{
+			NETXEN_NIC_REG(0x1d8),
+			/* Jumbo frames */
+			NETXEN_NIC_REG(0x1f8),
+			/* LRO */
+			NETXEN_NIC_REG(0x208)
+		},
+		/* crb_sts_consumer: */
+		NETXEN_NIC_REG(0x220),
+	},
+	/* Instance 3 */
+	{
+		/* crb_rcv_producer: */
+		{
+			NETXEN_NIC_REG(0x22c),
+			/* Jumbo frames */
+			NETXEN_NIC_REG(0x23c),
+			/* LRO */
+			NETXEN_NIC_REG(0x24c)
+		},
+		/* crb_sts_consumer: */
+		NETXEN_NIC_REG(0x264),
+	},
+};
+
+static int
+netxen_init_old_ctx(struct netxen_adapter *adapter)
+{
+	struct netxen_recv_context *recv_ctx;
+	struct nx_host_rds_ring *rds_ring;
+	int ctx, ring;
+	int func_id = adapter->portnum;
+
+	adapter->ctx_desc->cmd_ring_addr =
+		cpu_to_le64(adapter->ahw.cmd_desc_phys_addr);
+	adapter->ctx_desc->cmd_ring_size =
+		cpu_to_le32(adapter->max_tx_desc_count);
+
+	for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
+		recv_ctx = &adapter->recv_ctx[ctx];
+
+		for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+			rds_ring = &recv_ctx->rds_rings[ring];
+
+			adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr =
+				cpu_to_le64(rds_ring->phys_addr);
+			adapter->ctx_desc->rcv_ctx[ring].rcv_ring_size =
+				cpu_to_le32(rds_ring->max_rx_desc_count);
+		}
+		adapter->ctx_desc->sts_ring_addr =
+			cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr);
+		adapter->ctx_desc->sts_ring_size =
+			cpu_to_le32(adapter->max_rx_desc_count);
+	}
+
+	adapter->pci_write_normalize(adapter, CRB_CTX_ADDR_REG_LO(func_id),
+			lower32(adapter->ctx_desc_phys_addr));
+	adapter->pci_write_normalize(adapter, CRB_CTX_ADDR_REG_HI(func_id),
+			upper32(adapter->ctx_desc_phys_addr));
+	adapter->pci_write_normalize(adapter, CRB_CTX_SIGNATURE_REG(func_id),
+			NETXEN_CTX_SIGNATURE | func_id);
+	return 0;
+}
+
+static uint32_t sw_int_mask[4] = {
+	CRB_SW_INT_MASK_0, CRB_SW_INT_MASK_1,
+	CRB_SW_INT_MASK_2, CRB_SW_INT_MASK_3
+};
+
+int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
+{
+	struct netxen_hardware_context *hw = &adapter->ahw;
+	u32 state = 0;
+	void *addr;
+	int err = 0;
+	int ctx, ring;
+	struct netxen_recv_context *recv_ctx;
+	struct nx_host_rds_ring *rds_ring;
+
+	err = netxen_receive_peg_ready(adapter);
+	if (err) {
+		printk(KERN_ERR "Rcv Peg initialization not complete:%x.\n",
+				state);
+		return err;
+	}
+
+	addr = pci_alloc_consistent(adapter->pdev,
+			sizeof(struct netxen_ring_ctx) + sizeof(uint32_t),
+			&adapter->ctx_desc_phys_addr);
+
+	if (addr == NULL) {
+		DPRINTK(ERR, "failed to allocate hw context\n");
+		return -ENOMEM;
+	}
+	memset(addr, 0, sizeof(struct netxen_ring_ctx));
+	adapter->ctx_desc = (struct netxen_ring_ctx *)addr;
+	adapter->ctx_desc->ctx_id = cpu_to_le32(adapter->portnum);
+	adapter->ctx_desc->cmd_consumer_offset =
+		cpu_to_le64(adapter->ctx_desc_phys_addr +
+			sizeof(struct netxen_ring_ctx));
+	adapter->cmd_consumer =
+		(__le32 *)(((char *)addr) + sizeof(struct netxen_ring_ctx));
+
+	/* cmd desc ring */
+	addr = pci_alloc_consistent(adapter->pdev,
+			sizeof(struct cmd_desc_type0) *
+			adapter->max_tx_desc_count,
+			&hw->cmd_desc_phys_addr);
+
+	if (addr == NULL) {
+		printk(KERN_ERR "%s failed to allocate tx desc ring\n",
+				netxen_nic_driver_name);
+		return -ENOMEM;
+	}
+
+	hw->cmd_desc_head = (struct cmd_desc_type0 *)addr;
+
+	for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
+		recv_ctx = &adapter->recv_ctx[ctx];
+
+		for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+			/* rx desc ring */
+			rds_ring = &recv_ctx->rds_rings[ring];
+			addr = pci_alloc_consistent(adapter->pdev,
+					RCV_DESC_RINGSIZE,
+					&rds_ring->phys_addr);
+			if (addr == NULL) {
+				printk(KERN_ERR "%s failed to allocate rx "
+					"desc ring[%d]\n",
+					netxen_nic_driver_name, ring);
+				err = -ENOMEM;
+				goto err_out_free;
+			}
+			rds_ring->desc_head = (struct rcv_desc *)addr;
+
+			if (adapter->fw_major < 4)
+				rds_ring->crb_rcv_producer =
+					recv_crb_registers[adapter->portnum].
+					crb_rcv_producer[ring];
+		}
+
+		/* status desc ring */
+		addr = pci_alloc_consistent(adapter->pdev,
+				STATUS_DESC_RINGSIZE,
+				&recv_ctx->rcv_status_desc_phys_addr);
+		if (addr == NULL) {
+			printk(KERN_ERR "%s failed to allocate sts desc ring\n",
+					netxen_nic_driver_name);
+			err = -ENOMEM;
+			goto err_out_free;
+		}
+		recv_ctx->rcv_status_desc_head = (struct status_desc *)addr;
+
+		if (adapter->fw_major < 4)
+			recv_ctx->crb_sts_consumer =
+				recv_crb_registers[adapter->portnum].
+				crb_sts_consumer;
+	}
+
+	if (adapter->fw_major >= 4) {
+		adapter->intr_scheme = INTR_SCHEME_PERPORT;
+		adapter->msi_mode = MSI_MODE_MULTIFUNC;
+
+		err = nx_fw_cmd_create_rx_ctx(adapter);
+		if (err)
+			goto err_out_free;
+		err = nx_fw_cmd_create_tx_ctx(adapter);
+		if (err)
+			goto err_out_free;
+	} else {
+
+		adapter->intr_scheme = adapter->pci_read_normalize(adapter,
+				CRB_NIC_CAPABILITIES_FW);
+		adapter->msi_mode = adapter->pci_read_normalize(adapter,
+				CRB_NIC_MSI_MODE_FW);
+		adapter->crb_intr_mask = sw_int_mask[adapter->portnum];
+
+		err = netxen_init_old_ctx(adapter);
+		if (err) {
+			netxen_free_hw_resources(adapter);
+			return err;
+		}
+
+	}
+
+	return 0;
+
+err_out_free:
+	netxen_free_hw_resources(adapter);
+	return err;
+}
+
+void netxen_free_hw_resources(struct netxen_adapter *adapter)
+{
+	struct netxen_recv_context *recv_ctx;
+	struct nx_host_rds_ring *rds_ring;
+	int ctx, ring;
+
+	if (adapter->fw_major >= 4) {
+		nx_fw_cmd_destroy_tx_ctx(adapter);
+		nx_fw_cmd_destroy_rx_ctx(adapter);
+	}
+
+	if (adapter->ctx_desc != NULL) {
+		pci_free_consistent(adapter->pdev,
+				sizeof(struct netxen_ring_ctx) +
+				sizeof(uint32_t),
+				adapter->ctx_desc,
+				adapter->ctx_desc_phys_addr);
+		adapter->ctx_desc = NULL;
+	}
+
+	if (adapter->ahw.cmd_desc_head != NULL) {
+		pci_free_consistent(adapter->pdev,
+				sizeof(struct cmd_desc_type0) *
+				adapter->max_tx_desc_count,
+				adapter->ahw.cmd_desc_head,
+				adapter->ahw.cmd_desc_phys_addr);
+		adapter->ahw.cmd_desc_head = NULL;
+	}
+
+	for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
+		recv_ctx = &adapter->recv_ctx[ctx];
+		for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+			rds_ring = &recv_ctx->rds_rings[ring];
+
+			if (rds_ring->desc_head != NULL) {
+				pci_free_consistent(adapter->pdev,
+						RCV_DESC_RINGSIZE,
+						rds_ring->desc_head,
+						rds_ring->phys_addr);
+				rds_ring->desc_head = NULL;
+			}
+		}
+
+		if (recv_ctx->rcv_status_desc_head != NULL) {
+			pci_free_consistent(adapter->pdev,
+					STATUS_DESC_RINGSIZE,
+					recv_ctx->rcv_status_desc_head,
+					recv_ctx->rcv_status_desc_phys_addr);
+			recv_ctx->rcv_status_desc_head = NULL;
+		}
+	}
+}
+
diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c
index 723487b..48ee06b 100644
--- a/drivers/net/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/netxen/netxen_nic_ethtool.c
@@ -93,17 +93,21 @@
 netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
 {
 	struct netxen_adapter *adapter = netdev_priv(dev);
+	unsigned long flags;
 	u32 fw_major = 0;
 	u32 fw_minor = 0;
 	u32 fw_build = 0;
 
 	strncpy(drvinfo->driver, netxen_nic_driver_name, 32);
 	strncpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID, 32);
-	fw_major = readl(NETXEN_CRB_NORMALIZE(adapter,
-					      NETXEN_FW_VERSION_MAJOR));
-	fw_minor = readl(NETXEN_CRB_NORMALIZE(adapter,
-					      NETXEN_FW_VERSION_MINOR));
-	fw_build = readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_FW_VERSION_SUB));
+	write_lock_irqsave(&adapter->adapter_lock, flags);
+	fw_major = adapter->pci_read_normalize(adapter,
+					NETXEN_FW_VERSION_MAJOR);
+	fw_minor = adapter->pci_read_normalize(adapter,
+					NETXEN_FW_VERSION_MINOR);
+	fw_build = adapter->pci_read_normalize(adapter,
+					NETXEN_FW_VERSION_SUB);
+	write_unlock_irqrestore(&adapter->adapter_lock, flags);
 	sprintf(drvinfo->fw_version, "%d.%d.%d", fw_major, fw_minor, fw_build);
 
 	strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
@@ -159,9 +163,16 @@
 	switch ((netxen_brdtype_t) boardinfo->board_type) {
 	case NETXEN_BRDTYPE_P2_SB35_4G:
 	case NETXEN_BRDTYPE_P2_SB31_2G:
+	case NETXEN_BRDTYPE_P3_REF_QG:
+	case NETXEN_BRDTYPE_P3_4_GB:
+	case NETXEN_BRDTYPE_P3_4_GB_MM:
+	case NETXEN_BRDTYPE_P3_10000_BASE_T:
+
 		ecmd->supported |= SUPPORTED_Autoneg;
 		ecmd->advertising |= ADVERTISED_Autoneg;
 	case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
+	case NETXEN_BRDTYPE_P3_10G_CX4:
+	case NETXEN_BRDTYPE_P3_10G_CX4_LP:
 		ecmd->supported |= SUPPORTED_TP;
 		ecmd->advertising |= ADVERTISED_TP;
 		ecmd->port = PORT_TP;
@@ -171,12 +182,17 @@
 		break;
 	case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
 	case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
+	case NETXEN_BRDTYPE_P3_IMEZ:
+	case NETXEN_BRDTYPE_P3_XG_LOM:
+	case NETXEN_BRDTYPE_P3_HMEZ:
 		ecmd->supported |= SUPPORTED_MII;
 		ecmd->advertising |= ADVERTISED_MII;
 		ecmd->port = PORT_FIBRE;
 		ecmd->autoneg = AUTONEG_DISABLE;
 		break;
 	case NETXEN_BRDTYPE_P2_SB31_10G:
+	case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
+	case NETXEN_BRDTYPE_P3_10G_XFP:
 		ecmd->supported |= SUPPORTED_FIBRE;
 		ecmd->advertising |= ADVERTISED_FIBRE;
 		ecmd->port = PORT_FIBRE;
@@ -349,19 +365,18 @@
 {
 	struct netxen_adapter *adapter = netdev_priv(dev);
 	__u32 mode, *regs_buff = p;
-	void __iomem *addr;
 	int i, window;
 
 	memset(p, 0, NETXEN_NIC_REGS_LEN);
 	regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) |
 	    (adapter->pdev)->device;
 	/* which mode */
-	NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_MODE, &regs_buff[0]);
+	adapter->hw_read_wx(adapter, NETXEN_NIU_MODE, &regs_buff[0], 4);
 	mode = regs_buff[0];
 
 	/* Common registers to all the modes */
-	NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER,
-				   &regs_buff[2]);
+	adapter->hw_read_wx(adapter,
+			NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER, &regs_buff[2], 4);
 	/* GB/XGB Mode */
 	mode = (mode / 2) - 1;
 	window = 0;
@@ -372,9 +387,9 @@
 				window = adapter->physical_port *
 					NETXEN_NIC_PORT_WINDOW;
 
-			NETXEN_NIC_LOCKED_READ_REG(niu_registers[mode].
-						   reg[i - 3] + window,
-						   &regs_buff[i]);
+			adapter->hw_read_wx(adapter,
+				niu_registers[mode].reg[i - 3] + window,
+				&regs_buff[i], 4);
 		}
 
 	}
@@ -398,7 +413,7 @@
 			return !val;
 		}
 	} else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
-		val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE));
+		val = adapter->pci_read_normalize(adapter, CRB_XG_STATE);
 		return (val == XG_LINK_UP) ? 0 : 1;
 	}
 	return -EIO;
@@ -427,6 +442,7 @@
 	return 0;
 }
 
+#if 0
 static int
 netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
 			u8 * bytes)
@@ -447,7 +463,6 @@
 		}
 		printk(KERN_INFO "%s: flash unlocked. \n",
 			netxen_nic_driver_name);
-		last_schedule_time = jiffies;
 		ret = netxen_flash_erase_secondary(adapter);
 		if (ret != FLASH_SUCCESS) {
 			printk(KERN_ERR "%s: Flash erase failed.\n",
@@ -497,6 +512,7 @@
 
 	return netxen_rom_fast_write_words(adapter, offset, bytes, eeprom->len);
 }
+#endif /* 0 */
 
 static void
 netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
@@ -508,9 +524,9 @@
 	ring->rx_jumbo_pending = 0;
 	for (i = 0; i < MAX_RCV_CTX; ++i) {
 		ring->rx_pending += adapter->recv_ctx[i].
-		    rcv_desc[RCV_DESC_NORMAL_CTXID].max_rx_desc_count;
+		    rds_rings[RCV_DESC_NORMAL_CTXID].max_rx_desc_count;
 		ring->rx_jumbo_pending += adapter->recv_ctx[i].
-		    rcv_desc[RCV_DESC_JUMBO_CTXID].max_rx_desc_count;
+		    rds_rings[RCV_DESC_JUMBO_CTXID].max_rx_desc_count;
 	}
 	ring->tx_pending = adapter->max_tx_desc_count;
 
@@ -655,7 +671,7 @@
 	data_written = (u32)0xa5a5a5a5;
 
 	netxen_nic_reg_write(adapter, CRB_SCRATCHPAD_TEST, data_written);
-	data_read = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_SCRATCHPAD_TEST));
+	data_read = adapter->pci_read_normalize(adapter, CRB_SCRATCHPAD_TEST);
 	if (data_written != data_read)
 		return 1;
 
@@ -736,6 +752,117 @@
 	return 0;
 }
 
+static u32 netxen_nic_get_tso(struct net_device *dev)
+{
+	struct netxen_adapter *adapter = netdev_priv(dev);
+
+	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+		return (dev->features & (NETIF_F_TSO | NETIF_F_TSO6)) != 0;
+
+	return (dev->features & NETIF_F_TSO) != 0;
+}
+
+static int netxen_nic_set_tso(struct net_device *dev, u32 data)
+{
+	if (data) {
+		struct netxen_adapter *adapter = netdev_priv(dev);
+
+		dev->features |= NETIF_F_TSO;
+		if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+			dev->features |= NETIF_F_TSO6;
+	} else
+		dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
+
+	return 0;
+}
+
+/*
+ * Set the coalescing parameters. Currently only normal is supported.
+ * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
+ * firmware coalescing to default.
+ */
+static int netxen_set_intr_coalesce(struct net_device *netdev,
+			struct ethtool_coalesce *ethcoal)
+{
+	struct netxen_adapter *adapter = netdev_priv(netdev);
+
+	if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))
+		return -EINVAL;
+
+	if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
+		return -EINVAL;
+
+	/*
+	* Return Error if unsupported values or
+	* unsupported parameters are set.
+	*/
+	if (ethcoal->rx_coalesce_usecs > 0xffff ||
+		ethcoal->rx_max_coalesced_frames > 0xffff ||
+		ethcoal->tx_coalesce_usecs > 0xffff ||
+		ethcoal->tx_max_coalesced_frames > 0xffff ||
+		ethcoal->rx_coalesce_usecs_irq ||
+		ethcoal->rx_max_coalesced_frames_irq ||
+		ethcoal->tx_coalesce_usecs_irq ||
+		ethcoal->tx_max_coalesced_frames_irq ||
+		ethcoal->stats_block_coalesce_usecs ||
+		ethcoal->use_adaptive_rx_coalesce ||
+		ethcoal->use_adaptive_tx_coalesce ||
+		ethcoal->pkt_rate_low ||
+		ethcoal->rx_coalesce_usecs_low ||
+		ethcoal->rx_max_coalesced_frames_low ||
+		ethcoal->tx_coalesce_usecs_low ||
+		ethcoal->tx_max_coalesced_frames_low ||
+		ethcoal->pkt_rate_high ||
+		ethcoal->rx_coalesce_usecs_high ||
+		ethcoal->rx_max_coalesced_frames_high ||
+		ethcoal->tx_coalesce_usecs_high ||
+		ethcoal->tx_max_coalesced_frames_high)
+		return -EINVAL;
+
+	if (!ethcoal->rx_coalesce_usecs ||
+		!ethcoal->rx_max_coalesced_frames) {
+		adapter->coal.flags = NETXEN_NIC_INTR_DEFAULT;
+		adapter->coal.normal.data.rx_time_us =
+			NETXEN_DEFAULT_INTR_COALESCE_RX_TIME_US;
+		adapter->coal.normal.data.rx_packets =
+			NETXEN_DEFAULT_INTR_COALESCE_RX_PACKETS;
+	} else {
+		adapter->coal.flags = 0;
+		adapter->coal.normal.data.rx_time_us =
+		ethcoal->rx_coalesce_usecs;
+		adapter->coal.normal.data.rx_packets =
+		ethcoal->rx_max_coalesced_frames;
+	}
+	adapter->coal.normal.data.tx_time_us = ethcoal->tx_coalesce_usecs;
+	adapter->coal.normal.data.tx_packets =
+	ethcoal->tx_max_coalesced_frames;
+
+	netxen_config_intr_coalesce(adapter);
+
+	return 0;
+}
+
+static int netxen_get_intr_coalesce(struct net_device *netdev,
+			struct ethtool_coalesce *ethcoal)
+{
+	struct netxen_adapter *adapter = netdev_priv(netdev);
+
+	if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))
+		return -EINVAL;
+
+	if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
+		return -EINVAL;
+
+	ethcoal->rx_coalesce_usecs = adapter->coal.normal.data.rx_time_us;
+	ethcoal->tx_coalesce_usecs = adapter->coal.normal.data.tx_time_us;
+	ethcoal->rx_max_coalesced_frames =
+		adapter->coal.normal.data.rx_packets;
+	ethcoal->tx_max_coalesced_frames =
+		adapter->coal.normal.data.tx_packets;
+
+	return 0;
+}
+
 struct ethtool_ops netxen_nic_ethtool_ops = {
 	.get_settings = netxen_nic_get_settings,
 	.set_settings = netxen_nic_set_settings,
@@ -745,17 +872,22 @@
 	.get_link = ethtool_op_get_link,
 	.get_eeprom_len = netxen_nic_get_eeprom_len,
 	.get_eeprom = netxen_nic_get_eeprom,
+#if 0
 	.set_eeprom = netxen_nic_set_eeprom,
+#endif
 	.get_ringparam = netxen_nic_get_ringparam,
 	.get_pauseparam = netxen_nic_get_pauseparam,
 	.set_pauseparam = netxen_nic_set_pauseparam,
 	.set_tx_csum = ethtool_op_set_tx_csum,
 	.set_sg = ethtool_op_set_sg,
-	.set_tso = ethtool_op_set_tso,
+	.get_tso = netxen_nic_get_tso,
+	.set_tso = netxen_nic_set_tso,
 	.self_test = netxen_nic_diag_test,
 	.get_strings = netxen_nic_get_strings,
 	.get_ethtool_stats = netxen_nic_get_ethtool_stats,
 	.get_sset_count = netxen_get_sset_count,
 	.get_rx_csum = netxen_nic_get_rx_csum,
 	.set_rx_csum = netxen_nic_set_rx_csum,
+	.get_coalesce = netxen_get_intr_coalesce,
+	.set_coalesce = netxen_set_intr_coalesce,
 };
diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h
index 24d027e..3ce13e4 100644
--- a/drivers/net/netxen/netxen_nic_hdr.h
+++ b/drivers/net/netxen/netxen_nic_hdr.h
@@ -126,7 +126,8 @@
 	NETXEN_HW_PEGR0_CRB_AGT_ADR,
 	NETXEN_HW_PEGR1_CRB_AGT_ADR,
 	NETXEN_HW_PEGR2_CRB_AGT_ADR,
-	NETXEN_HW_PEGR3_CRB_AGT_ADR
+	NETXEN_HW_PEGR3_CRB_AGT_ADR,
+	NETXEN_HW_PEGN4_CRB_AGT_ADR
 };
 
 /*  Hub 5 */
@@ -316,6 +317,8 @@
 	((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGN2_CRB_AGT_ADR)
 #define NETXEN_HW_CRB_HUB_AGT_ADR_PGN3	\
 	((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGN3_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGN4	\
+	((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGN4_CRB_AGT_ADR)
 #define NETXEN_HW_CRB_HUB_AGT_ADR_PGNC	\
 	((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGNC_CRB_AGT_ADR)
 #define NETXEN_HW_CRB_HUB_AGT_ADR_PGR0	\
@@ -435,6 +438,7 @@
 #define NETXEN_CRB_ROMUSB	\
 	NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_ROMUSB)
 #define NETXEN_CRB_I2Q		NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_I2Q)
+#define NETXEN_CRB_SMB		NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_SMB)
 #define NETXEN_CRB_MAX		NETXEN_PCI_CRB_WINDOW(64)
 
 #define NETXEN_CRB_PCIX_HOST	NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PH)
@@ -446,6 +450,7 @@
 #define NETXEN_CRB_PEG_NET_D	NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGND)
 #define NETXEN_CRB_PEG_NET_I	NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGNI)
 #define NETXEN_CRB_DDR_NET	NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_MN)
+#define NETXEN_CRB_QDR_NET	NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_SN)
 
 #define NETXEN_CRB_PCIX_MD	NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PS)
 #define NETXEN_CRB_PCIE		NETXEN_CRB_PCIX_MD
@@ -461,11 +466,20 @@
 #define ISR_INT_TARGET_MASK_F2     (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F2))
 #define ISR_INT_TARGET_STATUS_F3   (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F3))
 #define ISR_INT_TARGET_MASK_F3     (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F3))
+#define ISR_INT_TARGET_STATUS_F4   (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F4))
+#define ISR_INT_TARGET_MASK_F4     (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F4))
+#define ISR_INT_TARGET_STATUS_F5   (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F5))
+#define ISR_INT_TARGET_MASK_F5     (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F5))
+#define ISR_INT_TARGET_STATUS_F6   (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F6))
+#define ISR_INT_TARGET_MASK_F6     (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F6))
+#define ISR_INT_TARGET_STATUS_F7   (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F7))
+#define ISR_INT_TARGET_MASK_F7     (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F7))
 
 #define NETXEN_PCI_MAPSIZE	128
 #define NETXEN_PCI_DDR_NET	(0x00000000UL)
 #define NETXEN_PCI_QDR_NET	(0x04000000UL)
 #define NETXEN_PCI_DIRECT_CRB	(0x04400000UL)
+#define NETXEN_PCI_CAMQM	(0x04800000UL)
 #define NETXEN_PCI_CAMQM_MAX	(0x04ffffffUL)
 #define NETXEN_PCI_OCM0		(0x05000000UL)
 #define NETXEN_PCI_OCM0_MAX	(0x050fffffUL)
@@ -474,6 +488,13 @@
 #define NETXEN_PCI_CRBSPACE	(0x06000000UL)
 #define NETXEN_PCI_128MB_SIZE	(0x08000000UL)
 #define NETXEN_PCI_32MB_SIZE	(0x02000000UL)
+#define NETXEN_PCI_2MB_SIZE	(0x00200000UL)
+
+#define NETXEN_PCI_MN_2M	(0)
+#define NETXEN_PCI_MS_2M	(0x80000)
+#define NETXEN_PCI_OCM0_2M	(0x000c0000UL)
+#define NETXEN_PCI_CAMQM_2M_BASE	(0x000ff800UL)
+#define NETXEN_PCI_CAMQM_2M_END		(0x04800800UL)
 
 #define NETXEN_CRB_CAM	NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_CAM)
 
@@ -484,7 +505,14 @@
 #define NETXEN_ADDR_OCM1	(0x0000000200400000ULL)
 #define NETXEN_ADDR_OCM1_MAX	(0x00000002004fffffULL)
 #define NETXEN_ADDR_QDR_NET	(0x0000000300000000ULL)
-#define NETXEN_ADDR_QDR_NET_MAX (0x00000003003fffffULL)
+#define NETXEN_ADDR_QDR_NET_MAX_P2 (0x00000003003fffffULL)
+#define NETXEN_ADDR_QDR_NET_MAX_P3 (0x0000000303ffffffULL)
+
+/*
+ *   Register offsets for MN
+ */
+#define	NETXEN_MIU_CONTROL	(0x000)
+#define	NETXEN_MIU_MN_CONTROL	(NETXEN_CRB_DDR_NET+NETXEN_MIU_CONTROL)
 
 	/* 200ms delay in each loop */
 #define	NETXEN_NIU_PHY_WAITLEN		200000
@@ -550,6 +578,9 @@
 #define NETXEN_MULTICAST_ADDR_HI_2	(NETXEN_CRB_NIU + 0x1018)
 #define NETXEN_MULTICAST_ADDR_HI_3	(NETXEN_CRB_NIU + 0x101c)
 
+#define NETXEN_UNICAST_ADDR_BASE	(NETXEN_CRB_NIU + 0x1080)
+#define	NETXEN_MULTICAST_ADDR_BASE	(NETXEN_CRB_NIU + 0x1100)
+
 #define	NETXEN_NIU_GB_MAC_CONFIG_0(I)		\
 	(NETXEN_CRB_NIU + 0x30000 + (I)*0x10000)
 #define	NETXEN_NIU_GB_MAC_CONFIG_1(I)		\
@@ -630,16 +661,76 @@
 #define NETXEN_NIU_XG1_CONTROL_CHAR_CNT		(NETXEN_CRB_NIU + 0x80054)
 #define NETXEN_NIU_XG1_PAUSE_FRAME_CNT		(NETXEN_CRB_NIU + 0x80058)
 
+/* P3 802.3ap */
+#define NETXEN_NIU_AP_MAC_CONFIG_0(I)      (NETXEN_CRB_NIU+0xa0000+(I)*0x10000)
+#define NETXEN_NIU_AP_MAC_CONFIG_1(I)      (NETXEN_CRB_NIU+0xa0004+(I)*0x10000)
+#define NETXEN_NIU_AP_MAC_IPG_IFG(I)       (NETXEN_CRB_NIU+0xa0008+(I)*0x10000)
+#define NETXEN_NIU_AP_HALF_DUPLEX_CTRL(I)  (NETXEN_CRB_NIU+0xa000c+(I)*0x10000)
+#define NETXEN_NIU_AP_MAX_FRAME_SIZE(I)    (NETXEN_CRB_NIU+0xa0010+(I)*0x10000)
+#define NETXEN_NIU_AP_TEST_REG(I)          (NETXEN_CRB_NIU+0xa001c+(I)*0x10000)
+#define NETXEN_NIU_AP_MII_MGMT_CONFIG(I)   (NETXEN_CRB_NIU+0xa0020+(I)*0x10000)
+#define NETXEN_NIU_AP_MII_MGMT_COMMAND(I)  (NETXEN_CRB_NIU+0xa0024+(I)*0x10000)
+#define NETXEN_NIU_AP_MII_MGMT_ADDR(I)     (NETXEN_CRB_NIU+0xa0028+(I)*0x10000)
+#define NETXEN_NIU_AP_MII_MGMT_CTRL(I)     (NETXEN_CRB_NIU+0xa002c+(I)*0x10000)
+#define NETXEN_NIU_AP_MII_MGMT_STATUS(I)   (NETXEN_CRB_NIU+0xa0030+(I)*0x10000)
+#define NETXEN_NIU_AP_MII_MGMT_INDICATE(I) (NETXEN_CRB_NIU+0xa0034+(I)*0x10000)
+#define NETXEN_NIU_AP_INTERFACE_CTRL(I)    (NETXEN_CRB_NIU+0xa0038+(I)*0x10000)
+#define NETXEN_NIU_AP_INTERFACE_STATUS(I)  (NETXEN_CRB_NIU+0xa003c+(I)*0x10000)
+#define NETXEN_NIU_AP_STATION_ADDR_0(I)    (NETXEN_CRB_NIU+0xa0040+(I)*0x10000)
+#define NETXEN_NIU_AP_STATION_ADDR_1(I)    (NETXEN_CRB_NIU+0xa0044+(I)*0x10000)
+
+/*
+ *   Register offsets for MN
+ */
+#define	MIU_CONTROL	       (0x000)
+#define MIU_TEST_AGT_CTRL      (0x090)
+#define MIU_TEST_AGT_ADDR_LO   (0x094)
+#define MIU_TEST_AGT_ADDR_HI   (0x098)
+#define MIU_TEST_AGT_WRDATA_LO (0x0a0)
+#define MIU_TEST_AGT_WRDATA_HI (0x0a4)
+#define MIU_TEST_AGT_WRDATA(i) (0x0a0+(4*(i)))
+#define MIU_TEST_AGT_RDDATA_LO (0x0a8)
+#define MIU_TEST_AGT_RDDATA_HI (0x0ac)
+#define MIU_TEST_AGT_RDDATA(i) (0x0a8+(4*(i)))
+#define MIU_TEST_AGT_ADDR_MASK 0xfffffff8
+#define MIU_TEST_AGT_UPPER_ADDR(off) (0)
+
+/* MIU_TEST_AGT_CTRL flags. work for SIU as well */
+#define MIU_TA_CTL_START        1
+#define MIU_TA_CTL_ENABLE       2
+#define MIU_TA_CTL_WRITE        4
+#define MIU_TA_CTL_BUSY         8
+
+#define SIU_TEST_AGT_CTRL      (0x060)
+#define SIU_TEST_AGT_ADDR_LO   (0x064)
+#define SIU_TEST_AGT_ADDR_HI   (0x078)
+#define SIU_TEST_AGT_WRDATA_LO (0x068)
+#define SIU_TEST_AGT_WRDATA_HI (0x06c)
+#define SIU_TEST_AGT_WRDATA(i) (0x068+(4*(i)))
+#define SIU_TEST_AGT_RDDATA_LO (0x070)
+#define SIU_TEST_AGT_RDDATA_HI (0x074)
+#define SIU_TEST_AGT_RDDATA(i) (0x070+(4*(i)))
+
+#define SIU_TEST_AGT_ADDR_MASK 0x3ffff8
+#define SIU_TEST_AGT_UPPER_ADDR(off) ((off)>>22)
+
 /* XG Link status */
 #define XG_LINK_UP	0x10
 #define XG_LINK_DOWN	0x20
 
+#define XG_LINK_UP_P3	0x01
+#define XG_LINK_DOWN_P3	0x02
+#define XG_LINK_STATE_P3_MASK 0xf
+#define XG_LINK_STATE_P3(pcifn,val) \
+	(((val) >> ((pcifn) * 4)) & XG_LINK_STATE_P3_MASK)
+
 #define NETXEN_CAM_RAM_BASE	(NETXEN_CRB_CAM + 0x02000)
 #define NETXEN_CAM_RAM(reg)	(NETXEN_CAM_RAM_BASE + (reg))
 #define NETXEN_FW_VERSION_MAJOR (NETXEN_CAM_RAM(0x150))
 #define NETXEN_FW_VERSION_MINOR (NETXEN_CAM_RAM(0x154))
 #define NETXEN_FW_VERSION_SUB	(NETXEN_CAM_RAM(0x158))
 #define NETXEN_ROM_LOCK_ID	(NETXEN_CAM_RAM(0x100))
+#define NETXEN_CRB_WIN_LOCK_ID	(NETXEN_CAM_RAM(0x124))
 
 #define NETXEN_PHY_LOCK_ID	(NETXEN_CAM_RAM(0x120))
 
@@ -654,30 +745,71 @@
 #define PCIX_INT_VECTOR		(0x10100)
 #define PCIX_INT_MASK		(0x10104)
 
-#define PCIX_MN_WINDOW_F0	(0x10200)
-#define PCIX_MN_WINDOW(_f)	(PCIX_MN_WINDOW_F0 + (0x20 * (_f)))
-#define PCIX_MS_WINDOW		(0x10204)
-#define PCIX_SN_WINDOW_F0	(0x10208)
-#define PCIX_SN_WINDOW(_f)	(PCIX_SN_WINDOW_F0 + (0x20 * (_f)))
 #define PCIX_CRB_WINDOW		(0x10210)
 #define PCIX_CRB_WINDOW_F0	(0x10210)
 #define PCIX_CRB_WINDOW_F1	(0x10230)
 #define PCIX_CRB_WINDOW_F2	(0x10250)
 #define PCIX_CRB_WINDOW_F3	(0x10270)
+#define PCIX_CRB_WINDOW_F4	(0x102ac)
+#define PCIX_CRB_WINDOW_F5	(0x102bc)
+#define PCIX_CRB_WINDOW_F6	(0x102cc)
+#define PCIX_CRB_WINDOW_F7	(0x102dc)
+#define PCIE_CRB_WINDOW_REG(func)	(((func) < 4) ? \
+		(PCIX_CRB_WINDOW_F0 + (0x20 * (func))) :\
+		(PCIX_CRB_WINDOW_F4 + (0x10 * ((func)-4))))
+
+#define PCIX_MN_WINDOW		(0x10200)
+#define PCIX_MN_WINDOW_F0	(0x10200)
+#define PCIX_MN_WINDOW_F1	(0x10220)
+#define PCIX_MN_WINDOW_F2	(0x10240)
+#define PCIX_MN_WINDOW_F3	(0x10260)
+#define PCIX_MN_WINDOW_F4	(0x102a0)
+#define PCIX_MN_WINDOW_F5	(0x102b0)
+#define PCIX_MN_WINDOW_F6	(0x102c0)
+#define PCIX_MN_WINDOW_F7	(0x102d0)
+#define PCIE_MN_WINDOW_REG(func)	(((func) < 4) ? \
+		(PCIX_MN_WINDOW_F0 + (0x20 * (func))) :\
+		(PCIX_MN_WINDOW_F4 + (0x10 * ((func)-4))))
+
+#define PCIX_SN_WINDOW		(0x10208)
+#define PCIX_SN_WINDOW_F0	(0x10208)
+#define PCIX_SN_WINDOW_F1	(0x10228)
+#define PCIX_SN_WINDOW_F2	(0x10248)
+#define PCIX_SN_WINDOW_F3	(0x10268)
+#define PCIX_SN_WINDOW_F4	(0x102a8)
+#define PCIX_SN_WINDOW_F5	(0x102b8)
+#define PCIX_SN_WINDOW_F6	(0x102c8)
+#define PCIX_SN_WINDOW_F7	(0x102d8)
+#define PCIE_SN_WINDOW_REG(func)	(((func) < 4) ? \
+		(PCIX_SN_WINDOW_F0 + (0x20 * (func))) :\
+		(PCIX_SN_WINDOW_F4 + (0x10 * ((func)-4))))
 
 #define PCIX_TARGET_STATUS	(0x10118)
+#define PCIX_TARGET_STATUS_F1	(0x10160)
+#define PCIX_TARGET_STATUS_F2	(0x10164)
+#define PCIX_TARGET_STATUS_F3	(0x10168)
+#define PCIX_TARGET_STATUS_F4	(0x10360)
+#define PCIX_TARGET_STATUS_F5	(0x10364)
+#define PCIX_TARGET_STATUS_F6	(0x10368)
+#define PCIX_TARGET_STATUS_F7	(0x1036c)
+
 #define PCIX_TARGET_MASK	(0x10128)
-#define PCIX_TARGET_STATUS_F1 (0x10160)
-#define PCIX_TARGET_MASK_F1   (0x10170)
-#define PCIX_TARGET_STATUS_F2 (0x10164)
-#define PCIX_TARGET_MASK_F2   (0x10174)
-#define PCIX_TARGET_STATUS_F3 (0x10168)
-#define PCIX_TARGET_MASK_F3   (0x10178)
+#define PCIX_TARGET_MASK_F1	(0x10170)
+#define PCIX_TARGET_MASK_F2	(0x10174)
+#define PCIX_TARGET_MASK_F3	(0x10178)
+#define PCIX_TARGET_MASK_F4	(0x10370)
+#define PCIX_TARGET_MASK_F5	(0x10374)
+#define PCIX_TARGET_MASK_F6	(0x10378)
+#define PCIX_TARGET_MASK_F7	(0x1037c)
 
 #define PCIX_MSI_F0		(0x13000)
 #define PCIX_MSI_F1		(0x13004)
 #define PCIX_MSI_F2		(0x13008)
 #define PCIX_MSI_F3		(0x1300c)
+#define PCIX_MSI_F4		(0x13010)
+#define PCIX_MSI_F5		(0x13014)
+#define PCIX_MSI_F6		(0x13018)
+#define PCIX_MSI_F7		(0x1301c)
 #define PCIX_MSI_F(i)		(0x13000+((i)*4))
 
 #define PCIX_PS_MEM_SPACE	(0x90000)
@@ -695,11 +827,102 @@
 #define PCIE_SEM2_UNLOCK	(0x1c014)	/* Flash unlock */
 #define PCIE_SEM3_LOCK	  	(0x1c018)	/* Phy lock     */
 #define PCIE_SEM3_UNLOCK	(0x1c01c)	/* Phy unlock   */
+#define PCIE_SEM5_LOCK		(0x1c028)	/* API lock     */
+#define PCIE_SEM5_UNLOCK	(0x1c02c)	/* API unlock   */
+#define PCIE_SEM6_LOCK		(0x1c030)	/* sw lock      */
+#define PCIE_SEM6_UNLOCK	(0x1c034)	/* sw unlock    */
+#define PCIE_SEM7_LOCK		(0x1c038)	/* crb win lock */
+#define PCIE_SEM7_UNLOCK	(0x1c03c)	/* crbwin unlock*/
 
+#define PCIE_SETUP_FUNCTION	(0x12040)
+#define PCIE_SETUP_FUNCTION2	(0x12048)
 #define PCIE_TGT_SPLIT_CHICKEN	(0x12080)
+#define PCIE_CHICKEN3		(0x120c8)
 
 #define PCIE_MAX_MASTER_SPLIT	(0x14048)
 
+#define NETXEN_PORT_MODE_NONE		0
+#define NETXEN_PORT_MODE_XG		1
+#define NETXEN_PORT_MODE_GB		2
+#define NETXEN_PORT_MODE_802_3_AP	3
+#define NETXEN_PORT_MODE_AUTO_NEG	4
+#define NETXEN_PORT_MODE_AUTO_NEG_1G	5
+#define NETXEN_PORT_MODE_AUTO_NEG_XG	6
+#define NETXEN_PORT_MODE_ADDR		(NETXEN_CAM_RAM(0x24))
+#define NETXEN_WOL_PORT_MODE		(NETXEN_CAM_RAM(0x198))
+
 #define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL		(0x14)
 
+#define	ISR_MSI_INT_TRIGGER(FUNC) (NETXEN_PCIX_PS_REG(PCIX_MSI_F(FUNC)))
+
+/*
+ * PCI Interrupt Vector Values.
+ */
+#define	PCIX_INT_VECTOR_BIT_F0	0x0080
+#define	PCIX_INT_VECTOR_BIT_F1	0x0100
+#define	PCIX_INT_VECTOR_BIT_F2	0x0200
+#define	PCIX_INT_VECTOR_BIT_F3	0x0400
+#define	PCIX_INT_VECTOR_BIT_F4	0x0800
+#define	PCIX_INT_VECTOR_BIT_F5	0x1000
+#define	PCIX_INT_VECTOR_BIT_F6	0x2000
+#define	PCIX_INT_VECTOR_BIT_F7	0x4000
+
+struct netxen_legacy_intr_set {
+	uint32_t	int_vec_bit;
+	uint32_t	tgt_status_reg;
+	uint32_t	tgt_mask_reg;
+	uint32_t	pci_int_reg;
+};
+
+#define	NX_LEGACY_INTR_CONFIG						\
+{									\
+	{								\
+		.int_vec_bit	=	PCIX_INT_VECTOR_BIT_F0,		\
+		.tgt_status_reg	=	ISR_INT_TARGET_STATUS,		\
+		.tgt_mask_reg	=	ISR_INT_TARGET_MASK,		\
+		.pci_int_reg	=	ISR_MSI_INT_TRIGGER(0) },	\
+									\
+	{								\
+		.int_vec_bit	=	PCIX_INT_VECTOR_BIT_F1,		\
+		.tgt_status_reg	=	ISR_INT_TARGET_STATUS_F1,	\
+		.tgt_mask_reg	=	ISR_INT_TARGET_MASK_F1,		\
+		.pci_int_reg	=	ISR_MSI_INT_TRIGGER(1) },	\
+									\
+	{								\
+		.int_vec_bit	=	PCIX_INT_VECTOR_BIT_F2,		\
+		.tgt_status_reg	=	ISR_INT_TARGET_STATUS_F2,	\
+		.tgt_mask_reg	=	ISR_INT_TARGET_MASK_F2,		\
+		.pci_int_reg	=	ISR_MSI_INT_TRIGGER(2) },	\
+									\
+	{								\
+		.int_vec_bit	=	PCIX_INT_VECTOR_BIT_F3,		\
+		.tgt_status_reg	=	ISR_INT_TARGET_STATUS_F3,	\
+		.tgt_mask_reg	=	ISR_INT_TARGET_MASK_F3,		\
+		.pci_int_reg	=	ISR_MSI_INT_TRIGGER(3) },	\
+									\
+	{								\
+		.int_vec_bit	=	PCIX_INT_VECTOR_BIT_F4,		\
+		.tgt_status_reg	=	ISR_INT_TARGET_STATUS_F4,	\
+		.tgt_mask_reg	=	ISR_INT_TARGET_MASK_F4,		\
+		.pci_int_reg	=	ISR_MSI_INT_TRIGGER(4) },	\
+									\
+	{								\
+		.int_vec_bit	=	PCIX_INT_VECTOR_BIT_F5,		\
+		.tgt_status_reg	=	ISR_INT_TARGET_STATUS_F5,	\
+		.tgt_mask_reg	=	ISR_INT_TARGET_MASK_F5,		\
+		.pci_int_reg	=	ISR_MSI_INT_TRIGGER(5) },	\
+									\
+	{								\
+		.int_vec_bit	=	PCIX_INT_VECTOR_BIT_F6,		\
+		.tgt_status_reg	=	ISR_INT_TARGET_STATUS_F6,	\
+		.tgt_mask_reg	=	ISR_INT_TARGET_MASK_F6,		\
+		.pci_int_reg	=	ISR_MSI_INT_TRIGGER(6) },	\
+									\
+	{								\
+		.int_vec_bit	=	PCIX_INT_VECTOR_BIT_F7,		\
+		.tgt_status_reg	=	ISR_INT_TARGET_STATUS_F7,	\
+		.tgt_mask_reg	=	ISR_INT_TARGET_MASK_F7,		\
+		.pci_int_reg	=	ISR_MSI_INT_TRIGGER(7) },	\
+}
+
 #endif				/* __NETXEN_NIC_HDR_H_ */
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index c43d06b..96a3bc6 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -38,242 +38,262 @@
 
 #include <net/ip.h>
 
-struct netxen_recv_crb recv_crb_registers[] = {
-	/*
-	 * Instance 0.
-	 */
-	{
-	 /* rcv_desc_crb: */
-	 {
-	  {
-	   /* crb_rcv_producer_offset: */
-	   NETXEN_NIC_REG(0x100),
-	   /* crb_rcv_consumer_offset: */
-	   NETXEN_NIC_REG(0x104),
-	   /* crb_gloablrcv_ring: */
-	   NETXEN_NIC_REG(0x108),
-	   /* crb_rcv_ring_size */
-	   NETXEN_NIC_REG(0x10c),
+#define MASK(n) ((1ULL<<(n))-1)
+#define MN_WIN(addr) (((addr & 0x1fc0000) >> 1) | ((addr >> 25) & 0x3ff))
+#define OCM_WIN(addr) (((addr & 0x1ff0000) >> 1) | ((addr >> 25) & 0x3ff))
+#define MS_WIN(addr) (addr & 0x0ffc0000)
 
-	   },
-	  /* Jumbo frames */
-	  {
-	   /* crb_rcv_producer_offset: */
-	   NETXEN_NIC_REG(0x110),
-	   /* crb_rcv_consumer_offset: */
-	   NETXEN_NIC_REG(0x114),
-	   /* crb_gloablrcv_ring: */
-	   NETXEN_NIC_REG(0x118),
-	   /* crb_rcv_ring_size */
-	   NETXEN_NIC_REG(0x11c),
-	   },
-	  /* LRO */
-	  {
-	   /* crb_rcv_producer_offset: */
-	   NETXEN_NIC_REG(0x120),
-	   /* crb_rcv_consumer_offset: */
-	   NETXEN_NIC_REG(0x124),
-	   /* crb_gloablrcv_ring: */
-	   NETXEN_NIC_REG(0x128),
-	   /* crb_rcv_ring_size */
-	   NETXEN_NIC_REG(0x12c),
-	   }
-	  },
-	 /* crb_rcvstatus_ring: */
-	 NETXEN_NIC_REG(0x130),
-	 /* crb_rcv_status_producer: */
-	 NETXEN_NIC_REG(0x134),
-	 /* crb_rcv_status_consumer: */
-	 NETXEN_NIC_REG(0x138),
-	 /* crb_rcvpeg_state: */
-	 NETXEN_NIC_REG(0x13c),
-	 /* crb_status_ring_size */
-	 NETXEN_NIC_REG(0x140),
+#define GET_MEM_OFFS_2M(addr) (addr & MASK(18))
 
-	 },
-	/*
-	 * Instance 1,
-	 */
-	{
-	 /* rcv_desc_crb: */
-	 {
-	  {
-	   /* crb_rcv_producer_offset: */
-	   NETXEN_NIC_REG(0x144),
-	   /* crb_rcv_consumer_offset: */
-	   NETXEN_NIC_REG(0x148),
-	   /* crb_globalrcv_ring: */
-	   NETXEN_NIC_REG(0x14c),
-	   /* crb_rcv_ring_size */
-	   NETXEN_NIC_REG(0x150),
+#define CRB_BLK(off)	((off >> 20) & 0x3f)
+#define CRB_SUBBLK(off)	((off >> 16) & 0xf)
+#define CRB_WINDOW_2M	(0x130060)
+#define CRB_HI(off)	((crb_hub_agt[CRB_BLK(off)] << 20) | ((off) & 0xf0000))
+#define CRB_INDIRECT_2M	(0x1e0000UL)
 
-	   },
-	  /* Jumbo frames */
-	  {
-	   /* crb_rcv_producer_offset: */
-	   NETXEN_NIC_REG(0x154),
-	   /* crb_rcv_consumer_offset: */
-	   NETXEN_NIC_REG(0x158),
-	   /* crb_globalrcv_ring: */
-	   NETXEN_NIC_REG(0x15c),
-	   /* crb_rcv_ring_size */
-	   NETXEN_NIC_REG(0x160),
-	   },
-	  /* LRO */
-	  {
-	   /* crb_rcv_producer_offset: */
-	   NETXEN_NIC_REG(0x164),
-	   /* crb_rcv_consumer_offset: */
-	   NETXEN_NIC_REG(0x168),
-	   /* crb_globalrcv_ring: */
-	   NETXEN_NIC_REG(0x16c),
-	   /* crb_rcv_ring_size */
-	   NETXEN_NIC_REG(0x170),
-	   }
-
-	  },
-	 /* crb_rcvstatus_ring: */
-	 NETXEN_NIC_REG(0x174),
-	 /* crb_rcv_status_producer: */
-	 NETXEN_NIC_REG(0x178),
-	 /* crb_rcv_status_consumer: */
-	 NETXEN_NIC_REG(0x17c),
-	 /* crb_rcvpeg_state: */
-	 NETXEN_NIC_REG(0x180),
-	 /* crb_status_ring_size */
-	 NETXEN_NIC_REG(0x184),
-	 },
-	/*
-	 * Instance 2,
-	 */
-	{
-	  {
-	    {
-	    /* crb_rcv_producer_offset: */
-	    NETXEN_NIC_REG(0x1d8),
-	    /* crb_rcv_consumer_offset: */
-	    NETXEN_NIC_REG(0x1dc),
-	    /* crb_gloablrcv_ring: */
-	    NETXEN_NIC_REG(0x1f0),
-	    /* crb_rcv_ring_size */
-	    NETXEN_NIC_REG(0x1f4),
-	    },
-	    /* Jumbo frames */
-	    {
-	    /* crb_rcv_producer_offset: */
-	    NETXEN_NIC_REG(0x1f8),
-	    /* crb_rcv_consumer_offset: */
-	    NETXEN_NIC_REG(0x1fc),
-	    /* crb_gloablrcv_ring: */
-	    NETXEN_NIC_REG(0x200),
-	    /* crb_rcv_ring_size */
-	    NETXEN_NIC_REG(0x204),
-	    },
-	    /* LRO */
-	    {
-	    /* crb_rcv_producer_offset: */
-	    NETXEN_NIC_REG(0x208),
-	    /* crb_rcv_consumer_offset: */
-	    NETXEN_NIC_REG(0x20c),
-	    /* crb_gloablrcv_ring: */
-	    NETXEN_NIC_REG(0x210),
-	    /* crb_rcv_ring_size */
-	    NETXEN_NIC_REG(0x214),
-	    }
-	  },
-	  /* crb_rcvstatus_ring: */
-	  NETXEN_NIC_REG(0x218),
-	  /* crb_rcv_status_producer: */
-	  NETXEN_NIC_REG(0x21c),
-	  /* crb_rcv_status_consumer: */
-	  NETXEN_NIC_REG(0x220),
-	  /* crb_rcvpeg_state: */
-	  NETXEN_NIC_REG(0x224),
-	  /* crb_status_ring_size */
-	  NETXEN_NIC_REG(0x228),
-	},
-	/*
-	 * Instance 3,
-	 */
-	{
-	  {
-	    {
-	    /* crb_rcv_producer_offset: */
-	    NETXEN_NIC_REG(0x22c),
-	    /* crb_rcv_consumer_offset: */
-	    NETXEN_NIC_REG(0x230),
-	    /* crb_gloablrcv_ring: */
-	    NETXEN_NIC_REG(0x234),
-	    /* crb_rcv_ring_size */
-	    NETXEN_NIC_REG(0x238),
-	    },
-	    /* Jumbo frames */
-	    {
-	    /* crb_rcv_producer_offset: */
-	    NETXEN_NIC_REG(0x23c),
-	    /* crb_rcv_consumer_offset: */
-	    NETXEN_NIC_REG(0x240),
-	    /* crb_gloablrcv_ring: */
-	    NETXEN_NIC_REG(0x244),
-	    /* crb_rcv_ring_size */
-	    NETXEN_NIC_REG(0x248),
-	    },
-	    /* LRO */
-	    {
-	    /* crb_rcv_producer_offset: */
-	    NETXEN_NIC_REG(0x24c),
-	    /* crb_rcv_consumer_offset: */
-	    NETXEN_NIC_REG(0x250),
-	    /* crb_gloablrcv_ring: */
-	    NETXEN_NIC_REG(0x254),
-	    /* crb_rcv_ring_size */
-	    NETXEN_NIC_REG(0x258),
-	    }
-	  },
-	  /* crb_rcvstatus_ring: */
-	  NETXEN_NIC_REG(0x25c),
-	  /* crb_rcv_status_producer: */
-	  NETXEN_NIC_REG(0x260),
-	  /* crb_rcv_status_consumer: */
-	  NETXEN_NIC_REG(0x264),
-	  /* crb_rcvpeg_state: */
-	  NETXEN_NIC_REG(0x268),
-	  /* crb_status_ring_size */
-	  NETXEN_NIC_REG(0x26c),
-	},
+#define CRB_WIN_LOCK_TIMEOUT 100000000
+static crb_128M_2M_block_map_t crb_128M_2M_map[64] = {
+    {{{0, 0,         0,         0} } },		/* 0: PCI */
+    {{{1, 0x0100000, 0x0102000, 0x120000},	/* 1: PCIE */
+	  {1, 0x0110000, 0x0120000, 0x130000},
+	  {1, 0x0120000, 0x0122000, 0x124000},
+	  {1, 0x0130000, 0x0132000, 0x126000},
+	  {1, 0x0140000, 0x0142000, 0x128000},
+	  {1, 0x0150000, 0x0152000, 0x12a000},
+	  {1, 0x0160000, 0x0170000, 0x110000},
+	  {1, 0x0170000, 0x0172000, 0x12e000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {1, 0x01e0000, 0x01e0800, 0x122000},
+	  {0, 0x0000000, 0x0000000, 0x000000} } },
+	{{{1, 0x0200000, 0x0210000, 0x180000} } },/* 2: MN */
+    {{{0, 0,         0,         0} } },	    /* 3: */
+    {{{1, 0x0400000, 0x0401000, 0x169000} } },/* 4: P2NR1 */
+    {{{1, 0x0500000, 0x0510000, 0x140000} } },/* 5: SRE   */
+    {{{1, 0x0600000, 0x0610000, 0x1c0000} } },/* 6: NIU   */
+    {{{1, 0x0700000, 0x0704000, 0x1b8000} } },/* 7: QM    */
+    {{{1, 0x0800000, 0x0802000, 0x170000},  /* 8: SQM0  */
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {1, 0x08f0000, 0x08f2000, 0x172000} } },
+    {{{1, 0x0900000, 0x0902000, 0x174000},	/* 9: SQM1*/
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {1, 0x09f0000, 0x09f2000, 0x176000} } },
+    {{{0, 0x0a00000, 0x0a02000, 0x178000},	/* 10: SQM2*/
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {1, 0x0af0000, 0x0af2000, 0x17a000} } },
+    {{{0, 0x0b00000, 0x0b02000, 0x17c000},	/* 11: SQM3*/
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {0, 0x0000000, 0x0000000, 0x000000},
+      {1, 0x0bf0000, 0x0bf2000, 0x17e000} } },
+	{{{1, 0x0c00000, 0x0c04000, 0x1d4000} } },/* 12: I2Q */
+	{{{1, 0x0d00000, 0x0d04000, 0x1a4000} } },/* 13: TMR */
+	{{{1, 0x0e00000, 0x0e04000, 0x1a0000} } },/* 14: ROMUSB */
+	{{{1, 0x0f00000, 0x0f01000, 0x164000} } },/* 15: PEG4 */
+	{{{0, 0x1000000, 0x1004000, 0x1a8000} } },/* 16: XDMA */
+	{{{1, 0x1100000, 0x1101000, 0x160000} } },/* 17: PEG0 */
+	{{{1, 0x1200000, 0x1201000, 0x161000} } },/* 18: PEG1 */
+	{{{1, 0x1300000, 0x1301000, 0x162000} } },/* 19: PEG2 */
+	{{{1, 0x1400000, 0x1401000, 0x163000} } },/* 20: PEG3 */
+	{{{1, 0x1500000, 0x1501000, 0x165000} } },/* 21: P2ND */
+	{{{1, 0x1600000, 0x1601000, 0x166000} } },/* 22: P2NI */
+	{{{0, 0,         0,         0} } },	/* 23: */
+	{{{0, 0,         0,         0} } },	/* 24: */
+	{{{0, 0,         0,         0} } },	/* 25: */
+	{{{0, 0,         0,         0} } },	/* 26: */
+	{{{0, 0,         0,         0} } },	/* 27: */
+	{{{0, 0,         0,         0} } },	/* 28: */
+	{{{1, 0x1d00000, 0x1d10000, 0x190000} } },/* 29: MS */
+    {{{1, 0x1e00000, 0x1e01000, 0x16a000} } },/* 30: P2NR2 */
+    {{{1, 0x1f00000, 0x1f10000, 0x150000} } },/* 31: EPG */
+	{{{0} } },				/* 32: PCI */
+	{{{1, 0x2100000, 0x2102000, 0x120000},	/* 33: PCIE */
+	  {1, 0x2110000, 0x2120000, 0x130000},
+	  {1, 0x2120000, 0x2122000, 0x124000},
+	  {1, 0x2130000, 0x2132000, 0x126000},
+	  {1, 0x2140000, 0x2142000, 0x128000},
+	  {1, 0x2150000, 0x2152000, 0x12a000},
+	  {1, 0x2160000, 0x2170000, 0x110000},
+	  {1, 0x2170000, 0x2172000, 0x12e000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {0, 0x0000000, 0x0000000, 0x000000},
+	  {0, 0x0000000, 0x0000000, 0x000000} } },
+	{{{1, 0x2200000, 0x2204000, 0x1b0000} } },/* 34: CAM */
+	{{{0} } },				/* 35: */
+	{{{0} } },				/* 36: */
+	{{{0} } },				/* 37: */
+	{{{0} } },				/* 38: */
+	{{{0} } },				/* 39: */
+	{{{1, 0x2800000, 0x2804000, 0x1a4000} } },/* 40: TMR */
+	{{{1, 0x2900000, 0x2901000, 0x16b000} } },/* 41: P2NR3 */
+	{{{1, 0x2a00000, 0x2a00400, 0x1ac400} } },/* 42: RPMX1 */
+	{{{1, 0x2b00000, 0x2b00400, 0x1ac800} } },/* 43: RPMX2 */
+	{{{1, 0x2c00000, 0x2c00400, 0x1acc00} } },/* 44: RPMX3 */
+	{{{1, 0x2d00000, 0x2d00400, 0x1ad000} } },/* 45: RPMX4 */
+	{{{1, 0x2e00000, 0x2e00400, 0x1ad400} } },/* 46: RPMX5 */
+	{{{1, 0x2f00000, 0x2f00400, 0x1ad800} } },/* 47: RPMX6 */
+	{{{1, 0x3000000, 0x3000400, 0x1adc00} } },/* 48: RPMX7 */
+	{{{0, 0x3100000, 0x3104000, 0x1a8000} } },/* 49: XDMA */
+	{{{1, 0x3200000, 0x3204000, 0x1d4000} } },/* 50: I2Q */
+	{{{1, 0x3300000, 0x3304000, 0x1a0000} } },/* 51: ROMUSB */
+	{{{0} } },				/* 52: */
+	{{{1, 0x3500000, 0x3500400, 0x1ac000} } },/* 53: RPMX0 */
+	{{{1, 0x3600000, 0x3600400, 0x1ae000} } },/* 54: RPMX8 */
+	{{{1, 0x3700000, 0x3700400, 0x1ae400} } },/* 55: RPMX9 */
+	{{{1, 0x3800000, 0x3804000, 0x1d0000} } },/* 56: OCM0 */
+	{{{1, 0x3900000, 0x3904000, 0x1b4000} } },/* 57: CRYPTO */
+	{{{1, 0x3a00000, 0x3a04000, 0x1d8000} } },/* 58: SMB */
+	{{{0} } },				/* 59: I2C0 */
+	{{{0} } },				/* 60: I2C1 */
+	{{{1, 0x3d00000, 0x3d04000, 0x1d8000} } },/* 61: LPC */
+	{{{1, 0x3e00000, 0x3e01000, 0x167000} } },/* 62: P2NC */
+	{{{1, 0x3f00000, 0x3f01000, 0x168000} } }	/* 63: P2NR0 */
 };
 
-static u64 ctx_addr_sig_regs[][3] = {
-	{NETXEN_NIC_REG(0x188), NETXEN_NIC_REG(0x18c), NETXEN_NIC_REG(0x1c0)},
-	{NETXEN_NIC_REG(0x190), NETXEN_NIC_REG(0x194), NETXEN_NIC_REG(0x1c4)},
-	{NETXEN_NIC_REG(0x198), NETXEN_NIC_REG(0x19c), NETXEN_NIC_REG(0x1c8)},
-	{NETXEN_NIC_REG(0x1a0), NETXEN_NIC_REG(0x1a4), NETXEN_NIC_REG(0x1cc)}
+/*
+ * top 12 bits of crb internal address (hub, agent)
+ */
+static unsigned crb_hub_agt[64] =
+{
+	0,
+	NETXEN_HW_CRB_HUB_AGT_ADR_PS,
+	NETXEN_HW_CRB_HUB_AGT_ADR_MN,
+	NETXEN_HW_CRB_HUB_AGT_ADR_MS,
+	0,
+	NETXEN_HW_CRB_HUB_AGT_ADR_SRE,
+	NETXEN_HW_CRB_HUB_AGT_ADR_NIU,
+	NETXEN_HW_CRB_HUB_AGT_ADR_QMN,
+	NETXEN_HW_CRB_HUB_AGT_ADR_SQN0,
+	NETXEN_HW_CRB_HUB_AGT_ADR_SQN1,
+	NETXEN_HW_CRB_HUB_AGT_ADR_SQN2,
+	NETXEN_HW_CRB_HUB_AGT_ADR_SQN3,
+	NETXEN_HW_CRB_HUB_AGT_ADR_I2Q,
+	NETXEN_HW_CRB_HUB_AGT_ADR_TIMR,
+	NETXEN_HW_CRB_HUB_AGT_ADR_ROMUSB,
+	NETXEN_HW_CRB_HUB_AGT_ADR_PGN4,
+	NETXEN_HW_CRB_HUB_AGT_ADR_XDMA,
+	NETXEN_HW_CRB_HUB_AGT_ADR_PGN0,
+	NETXEN_HW_CRB_HUB_AGT_ADR_PGN1,
+	NETXEN_HW_CRB_HUB_AGT_ADR_PGN2,
+	NETXEN_HW_CRB_HUB_AGT_ADR_PGN3,
+	NETXEN_HW_CRB_HUB_AGT_ADR_PGND,
+	NETXEN_HW_CRB_HUB_AGT_ADR_PGNI,
+	NETXEN_HW_CRB_HUB_AGT_ADR_PGS0,
+	NETXEN_HW_CRB_HUB_AGT_ADR_PGS1,
+	NETXEN_HW_CRB_HUB_AGT_ADR_PGS2,
+	NETXEN_HW_CRB_HUB_AGT_ADR_PGS3,
+	0,
+	NETXEN_HW_CRB_HUB_AGT_ADR_PGSI,
+	NETXEN_HW_CRB_HUB_AGT_ADR_SN,
+	0,
+	NETXEN_HW_CRB_HUB_AGT_ADR_EG,
+	0,
+	NETXEN_HW_CRB_HUB_AGT_ADR_PS,
+	NETXEN_HW_CRB_HUB_AGT_ADR_CAM,
+	0,
+	0,
+	0,
+	0,
+	0,
+	NETXEN_HW_CRB_HUB_AGT_ADR_TIMR,
+	0,
+	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX1,
+	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX2,
+	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX3,
+	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX4,
+	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX5,
+	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX6,
+	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX7,
+	NETXEN_HW_CRB_HUB_AGT_ADR_XDMA,
+	NETXEN_HW_CRB_HUB_AGT_ADR_I2Q,
+	NETXEN_HW_CRB_HUB_AGT_ADR_ROMUSB,
+	0,
+	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX0,
+	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX8,
+	NETXEN_HW_CRB_HUB_AGT_ADR_RPMX9,
+	NETXEN_HW_CRB_HUB_AGT_ADR_OCM0,
+	0,
+	NETXEN_HW_CRB_HUB_AGT_ADR_SMB,
+	NETXEN_HW_CRB_HUB_AGT_ADR_I2C0,
+	NETXEN_HW_CRB_HUB_AGT_ADR_I2C1,
+	0,
+	NETXEN_HW_CRB_HUB_AGT_ADR_PGNC,
+	0,
 };
-#define CRB_CTX_ADDR_REG_LO(FUNC_ID)		(ctx_addr_sig_regs[FUNC_ID][0])
-#define CRB_CTX_ADDR_REG_HI(FUNC_ID)		(ctx_addr_sig_regs[FUNC_ID][2])
-#define CRB_CTX_SIGNATURE_REG(FUNC_ID)		(ctx_addr_sig_regs[FUNC_ID][1])
-
 
 /*  PCI Windowing for DDR regions.  */
 
 #define ADDR_IN_RANGE(addr, low, high)	\
 	(((addr) <= (high)) && ((addr) >= (low)))
 
-#define NETXEN_FLASH_BASE	(NETXEN_BOOTLD_START)
-#define NETXEN_PHANTOM_MEM_BASE	(NETXEN_FLASH_BASE)
 #define NETXEN_MAX_MTU		8000 + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE
 #define NETXEN_MIN_MTU		64
 #define NETXEN_ETH_FCS_SIZE     4
 #define NETXEN_ENET_HEADER_SIZE 14
-#define NETXEN_WINDOW_ONE 	0x2000000	/*CRB Window: bit 25 of CRB address */
+#define NETXEN_WINDOW_ONE 	0x2000000 /*CRB Window: bit 25 of CRB address */
 #define NETXEN_FIRMWARE_LEN 	((16 * 1024) / 4)
 #define NETXEN_NIU_HDRSIZE	(0x1 << 6)
 #define NETXEN_NIU_TLRSIZE	(0x1 << 5)
 
-#define lower32(x)		((u32)((x) & 0xffffffff))
-#define upper32(x)			\
-	((u32)(((unsigned long long)(x) >> 32) & 0xffffffff))
-
 #define NETXEN_NIC_ZERO_PAUSE_ADDR     0ULL
 #define NETXEN_NIC_UNIT_PAUSE_ADDR     0x200ULL
 #define NETXEN_NIC_EPG_PAUSE_ADDR1     0x2200010000c28001ULL
@@ -281,10 +301,6 @@
 
 #define NETXEN_NIC_WINDOW_MARGIN 0x100000
 
-static unsigned long netxen_nic_pci_set_window(struct netxen_adapter *adapter,
-					       unsigned long long addr);
-void netxen_free_hw_resources(struct netxen_adapter *adapter);
-
 int netxen_nic_set_mac(struct net_device *netdev, void *p)
 {
 	struct netxen_adapter *adapter = netdev_priv(netdev);
@@ -296,47 +312,356 @@
 	if (!is_valid_ether_addr(addr->sa_data))
 		return -EADDRNOTAVAIL;
 
-	DPRINTK(INFO, "valid ether addr\n");
 	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
 
-	if (adapter->macaddr_set)
-		adapter->macaddr_set(adapter, addr->sa_data);
+	/* For P3, MAC addr is not set in NIU */
+	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+		if (adapter->macaddr_set)
+			adapter->macaddr_set(adapter, addr->sa_data);
 
 	return 0;
 }
 
-/*
- * netxen_nic_set_multi - Multicast
- */
-void netxen_nic_set_multi(struct net_device *netdev)
+#define NETXEN_UNICAST_ADDR(port, index) \
+	(NETXEN_UNICAST_ADDR_BASE+(port*32)+(index*8))
+#define NETXEN_MCAST_ADDR(port, index) \
+	(NETXEN_MULTICAST_ADDR_BASE+(port*0x80)+(index*8))
+#define MAC_HI(addr) \
+	((addr[2] << 16) | (addr[1] << 8) | (addr[0]))
+#define MAC_LO(addr) \
+	((addr[5] << 16) | (addr[4] << 8) | (addr[3]))
+
+static int
+netxen_nic_enable_mcast_filter(struct netxen_adapter *adapter)
+{
+	u32	val = 0;
+	u16 port = adapter->physical_port;
+	u8 *addr = adapter->netdev->dev_addr;
+
+	if (adapter->mc_enabled)
+		return 0;
+
+	adapter->hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
+	val |= (1UL << (28+port));
+	adapter->hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
+
+	/* add broadcast addr to filter */
+	val = 0xffffff;
+	netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val);
+	netxen_crb_writelit_adapter(adapter,
+			NETXEN_UNICAST_ADDR(port, 0)+4, val);
+
+	/* add station addr to filter */
+	val = MAC_HI(addr);
+	netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1), val);
+	val = MAC_LO(addr);
+	netxen_crb_writelit_adapter(adapter,
+			NETXEN_UNICAST_ADDR(port, 1)+4, val);
+
+	adapter->mc_enabled = 1;
+	return 0;
+}
+
+static int
+netxen_nic_disable_mcast_filter(struct netxen_adapter *adapter)
+{
+	u32	val = 0;
+	u16 port = adapter->physical_port;
+	u8 *addr = adapter->netdev->dev_addr;
+
+	if (!adapter->mc_enabled)
+		return 0;
+
+	adapter->hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
+	val &= ~(1UL << (28+port));
+	adapter->hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
+
+	val = MAC_HI(addr);
+	netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val);
+	val = MAC_LO(addr);
+	netxen_crb_writelit_adapter(adapter,
+			NETXEN_UNICAST_ADDR(port, 0)+4, val);
+
+	netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1), 0);
+	netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, 0);
+
+	adapter->mc_enabled = 0;
+	return 0;
+}
+
+static int
+netxen_nic_set_mcast_addr(struct netxen_adapter *adapter,
+		int index, u8 *addr)
+{
+	u32 hi = 0, lo = 0;
+	u16 port = adapter->physical_port;
+
+	lo = MAC_LO(addr);
+	hi = MAC_HI(addr);
+
+	netxen_crb_writelit_adapter(adapter,
+			NETXEN_MCAST_ADDR(port, index), hi);
+	netxen_crb_writelit_adapter(adapter,
+			NETXEN_MCAST_ADDR(port, index)+4, lo);
+
+	return 0;
+}
+
+void netxen_p2_nic_set_multi(struct net_device *netdev)
 {
 	struct netxen_adapter *adapter = netdev_priv(netdev);
 	struct dev_mc_list *mc_ptr;
+	u8 null_addr[6];
+	int index = 0;
 
-	mc_ptr = netdev->mc_list;
+	memset(null_addr, 0, 6);
+
 	if (netdev->flags & IFF_PROMISC) {
-		if (adapter->set_promisc)
-			adapter->set_promisc(adapter,
-					     NETXEN_NIU_PROMISC_MODE);
-	} else {
-		if (adapter->unset_promisc)
-			adapter->unset_promisc(adapter,
-					       NETXEN_NIU_NON_PROMISC_MODE);
+
+		adapter->set_promisc(adapter,
+				NETXEN_NIU_PROMISC_MODE);
+
+		/* Full promiscuous mode */
+		netxen_nic_disable_mcast_filter(adapter);
+
+		return;
 	}
+
+	if (netdev->mc_count == 0) {
+		adapter->set_promisc(adapter,
+				NETXEN_NIU_NON_PROMISC_MODE);
+		netxen_nic_disable_mcast_filter(adapter);
+		return;
+	}
+
+	adapter->set_promisc(adapter, NETXEN_NIU_ALLMULTI_MODE);
+	if (netdev->flags & IFF_ALLMULTI ||
+			netdev->mc_count > adapter->max_mc_count) {
+		netxen_nic_disable_mcast_filter(adapter);
+		return;
+	}
+
+	netxen_nic_enable_mcast_filter(adapter);
+
+	for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next, index++)
+		netxen_nic_set_mcast_addr(adapter, index, mc_ptr->dmi_addr);
+
+	if (index != netdev->mc_count)
+		printk(KERN_WARNING "%s: %s multicast address count mismatch\n",
+			netxen_nic_driver_name, netdev->name);
+
+	/* Clear out remaining addresses */
+	for (; index < adapter->max_mc_count; index++)
+		netxen_nic_set_mcast_addr(adapter, index, null_addr);
+}
+
+static int nx_p3_nic_add_mac(struct netxen_adapter *adapter,
+		u8 *addr, nx_mac_list_t **add_list, nx_mac_list_t **del_list)
+{
+	nx_mac_list_t *cur, *prev;
+
+	/* if in del_list, move it to adapter->mac_list */
+	for (cur = *del_list, prev = NULL; cur;) {
+		if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) {
+			if (prev == NULL)
+				*del_list = cur->next;
+			else
+				prev->next = cur->next;
+			cur->next = adapter->mac_list;
+			adapter->mac_list = cur;
+			return 0;
+		}
+		prev = cur;
+		cur = cur->next;
+	}
+
+	/* make sure to add each mac address only once */
+	for (cur = adapter->mac_list; cur; cur = cur->next) {
+		if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0)
+			return 0;
+	}
+	/* not in del_list, create new entry and add to add_list */
+	cur = kmalloc(sizeof(*cur), in_atomic()? GFP_ATOMIC : GFP_KERNEL);
+	if (cur == NULL) {
+		printk(KERN_ERR "%s: cannot allocate memory. MAC filtering may"
+				"not work properly from now.\n", __func__);
+		return -1;
+	}
+
+	memcpy(cur->mac_addr, addr, ETH_ALEN);
+	cur->next = *add_list;
+	*add_list = cur;
+	return 0;
+}
+
+static int
+netxen_send_cmd_descs(struct netxen_adapter *adapter,
+		struct cmd_desc_type0 *cmd_desc_arr, int nr_elements)
+{
+	uint32_t i, producer;
+	struct netxen_cmd_buffer *pbuf;
+	struct cmd_desc_type0 *cmd_desc;
+
+	if (nr_elements > MAX_PENDING_DESC_BLOCK_SIZE || nr_elements == 0) {
+		printk(KERN_WARNING "%s: Too many command descriptors in a "
+			      "request\n", __func__);
+		return -EINVAL;
+	}
+
+	i = 0;
+
+	producer = adapter->cmd_producer;
+	do {
+		cmd_desc = &cmd_desc_arr[i];
+
+		pbuf = &adapter->cmd_buf_arr[producer];
+		pbuf->mss = 0;
+		pbuf->total_length = 0;
+		pbuf->skb = NULL;
+		pbuf->cmd = 0;
+		pbuf->frag_count = 0;
+		pbuf->port = 0;
+
+		/* adapter->ahw.cmd_desc_head[producer] = *cmd_desc; */
+		memcpy(&adapter->ahw.cmd_desc_head[producer],
+			&cmd_desc_arr[i], sizeof(struct cmd_desc_type0));
+
+		producer = get_next_index(producer,
+				adapter->max_tx_desc_count);
+		i++;
+
+	} while (i != nr_elements);
+
+	adapter->cmd_producer = producer;
+
+	/* write producer index to start the xmit */
+
+	netxen_nic_update_cmd_producer(adapter, adapter->cmd_producer);
+
+	return 0;
+}
+
+#define NIC_REQUEST		0x14
+#define NETXEN_MAC_EVENT	0x1
+
+static int nx_p3_sre_macaddr_change(struct net_device *dev,
+		u8 *addr, unsigned op)
+{
+	struct netxen_adapter *adapter = (struct netxen_adapter *)dev->priv;
+	nx_nic_req_t req;
+	nx_mac_req_t mac_req;
+	int rv;
+
+	memset(&req, 0, sizeof(nx_nic_req_t));
+	req.qhdr |= (NIC_REQUEST << 23);
+	req.req_hdr |= NETXEN_MAC_EVENT;
+	req.req_hdr |= ((u64)adapter->portnum << 16);
+	mac_req.op = op;
+	memcpy(&mac_req.mac_addr, addr, 6);
+	req.words[0] = cpu_to_le64(*(u64 *)&mac_req);
+
+	rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+	if (rv != 0) {
+		printk(KERN_ERR "ERROR. Could not send mac update\n");
+		return rv;
+	}
+
+	return 0;
+}
+
+void netxen_p3_nic_set_multi(struct net_device *netdev)
+{
+	struct netxen_adapter *adapter = netdev_priv(netdev);
+	nx_mac_list_t *cur, *next, *del_list, *add_list = NULL;
+	struct dev_mc_list *mc_ptr;
+	u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+	adapter->set_promisc(adapter, NETXEN_NIU_PROMISC_MODE);
+
+	/*
+	 * Programming mac addresses will automaticly enabling L2 filtering.
+	 * HW will replace timestamp with L2 conid when L2 filtering is
+	 * enabled. This causes problem for LSA. Do not enabling L2 filtering
+	 * until that problem is fixed.
+	 */
+	if ((netdev->flags & IFF_PROMISC) ||
+			(netdev->mc_count > adapter->max_mc_count))
+		return;
+
+	del_list = adapter->mac_list;
+	adapter->mac_list = NULL;
+
+	nx_p3_nic_add_mac(adapter, netdev->dev_addr, &add_list, &del_list);
+	if (netdev->mc_count > 0) {
+		nx_p3_nic_add_mac(adapter, bcast_addr, &add_list, &del_list);
+		for (mc_ptr = netdev->mc_list; mc_ptr;
+		     mc_ptr = mc_ptr->next) {
+			nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr,
+					  &add_list, &del_list);
+		}
+	}
+	for (cur = del_list; cur;) {
+		nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_DEL);
+		next = cur->next;
+		kfree(cur);
+		cur = next;
+	}
+	for (cur = add_list; cur;) {
+		nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_ADD);
+		next = cur->next;
+		cur->next = adapter->mac_list;
+		adapter->mac_list = cur;
+		cur = next;
+	}
+}
+
+#define	NETXEN_CONFIG_INTR_COALESCE	3
+
+/*
+ * Send the interrupt coalescing parameter set by ethtool to the card.
+ */
+int netxen_config_intr_coalesce(struct netxen_adapter *adapter)
+{
+	nx_nic_req_t req;
+	int rv;
+
+	memset(&req, 0, sizeof(nx_nic_req_t));
+
+	req.qhdr |= (NIC_REQUEST << 23);
+	req.req_hdr |= NETXEN_CONFIG_INTR_COALESCE;
+	req.req_hdr |= ((u64)adapter->portnum << 16);
+
+	memcpy(&req.words[0], &adapter->coal, sizeof(adapter->coal));
+
+	rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+	if (rv != 0) {
+		printk(KERN_ERR "ERROR. Could not send "
+			"interrupt coalescing parameters\n");
+	}
+
+	return rv;
 }
 
 /*
  * netxen_nic_change_mtu - Change the Maximum Transfer Unit
  * @returns 0 on success, negative on failure
  */
+
+#define MTU_FUDGE_FACTOR	100
+
 int netxen_nic_change_mtu(struct net_device *netdev, int mtu)
 {
 	struct netxen_adapter *adapter = netdev_priv(netdev);
-	int eff_mtu = mtu + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE;
+	int max_mtu;
 
-	if ((eff_mtu > NETXEN_MAX_MTU) || (eff_mtu < NETXEN_MIN_MTU)) {
-		printk(KERN_ERR "%s: %s %d is not supported.\n",
-		       netxen_nic_driver_name, netdev->name, mtu);
+	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+		max_mtu = P3_MAX_MTU;
+	else
+		max_mtu = P2_MAX_MTU;
+
+	if (mtu > max_mtu) {
+		printk(KERN_ERR "%s: mtu > %d bytes unsupported\n",
+				netdev->name, max_mtu);
 		return -EINVAL;
 	}
 
@@ -344,220 +669,15 @@
 		adapter->set_mtu(adapter, mtu);
 	netdev->mtu = mtu;
 
+	mtu += MTU_FUDGE_FACTOR;
+	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+		nx_fw_cmd_set_mtu(adapter, mtu);
+	else if (adapter->set_mtu)
+		adapter->set_mtu(adapter, mtu);
+
 	return 0;
 }
 
-/*
- * check if the firmware has been downloaded and ready to run  and
- * setup the address for the descriptors in the adapter
- */
-int netxen_nic_hw_resources(struct netxen_adapter *adapter)
-{
-	struct netxen_hardware_context *hw = &adapter->ahw;
-	u32 state = 0;
-	void *addr;
-	int loops = 0, err = 0;
-	int ctx, ring;
-	struct netxen_recv_context *recv_ctx;
-	struct netxen_rcv_desc_ctx *rcv_desc;
-	int func_id = adapter->portnum;
-
-	DPRINTK(INFO, "crb_base: %lx %x", NETXEN_PCI_CRBSPACE,
-		PCI_OFFSET_SECOND_RANGE(adapter, NETXEN_PCI_CRBSPACE));
-	DPRINTK(INFO, "cam base: %lx %x", NETXEN_CRB_CAM,
-		pci_base_offset(adapter, NETXEN_CRB_CAM));
-	DPRINTK(INFO, "cam RAM: %lx %x", NETXEN_CAM_RAM_BASE,
-		pci_base_offset(adapter, NETXEN_CAM_RAM_BASE));
-
-
-	for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
-		DPRINTK(INFO, "Command Peg ready..waiting for rcv peg\n");
-		loops = 0;
-		state = 0;
-		/* Window 1 call */
-		state = readl(NETXEN_CRB_NORMALIZE(adapter,
-						   recv_crb_registers[ctx].
-						   crb_rcvpeg_state));
-		while (state != PHAN_PEG_RCV_INITIALIZED && loops < 20) {
-			msleep(1);
-			/* Window 1 call */
-			state = readl(NETXEN_CRB_NORMALIZE(adapter,
-							   recv_crb_registers
-							   [ctx].
-							   crb_rcvpeg_state));
-			loops++;
-		}
-		if (loops >= 20) {
-			printk(KERN_ERR "Rcv Peg initialization not complete:"
-			       "%x.\n", state);
-			err = -EIO;
-			return err;
-		}
-	}
-	adapter->intr_scheme = readl(
-		NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_FW));
-	adapter->msi_mode = readl(
-		NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_MSI_MODE_FW));
-
-	addr = netxen_alloc(adapter->ahw.pdev,
-			    sizeof(struct netxen_ring_ctx) +
-			    sizeof(uint32_t),
-			    (dma_addr_t *) & adapter->ctx_desc_phys_addr,
-			    &adapter->ctx_desc_pdev);
-
-	if (addr == NULL) {
-		DPRINTK(ERR, "bad return from pci_alloc_consistent\n");
-		err = -ENOMEM;
-		return err;
-	}
-	memset(addr, 0, sizeof(struct netxen_ring_ctx));
-	adapter->ctx_desc = (struct netxen_ring_ctx *)addr;
-	adapter->ctx_desc->ctx_id = cpu_to_le32(adapter->portnum);
-	adapter->ctx_desc->cmd_consumer_offset =
-	    cpu_to_le64(adapter->ctx_desc_phys_addr +
-			sizeof(struct netxen_ring_ctx));
-	adapter->cmd_consumer = (__le32 *) (((char *)addr) +
-					      sizeof(struct netxen_ring_ctx));
-
-	addr = netxen_alloc(adapter->ahw.pdev,
-			    sizeof(struct cmd_desc_type0) *
-			    adapter->max_tx_desc_count,
-			    (dma_addr_t *) & hw->cmd_desc_phys_addr,
-			    &adapter->ahw.cmd_desc_pdev);
-
-	if (addr == NULL) {
-		DPRINTK(ERR, "bad return from pci_alloc_consistent\n");
-		netxen_free_hw_resources(adapter);
-		return -ENOMEM;
-	}
-
-	adapter->ctx_desc->cmd_ring_addr =
-		cpu_to_le64(hw->cmd_desc_phys_addr);
-	adapter->ctx_desc->cmd_ring_size =
-		cpu_to_le32(adapter->max_tx_desc_count);
-
-	hw->cmd_desc_head = (struct cmd_desc_type0 *)addr;
-
-	for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
-		recv_ctx = &adapter->recv_ctx[ctx];
-
-		for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
-			rcv_desc = &recv_ctx->rcv_desc[ring];
-			addr = netxen_alloc(adapter->ahw.pdev,
-					    RCV_DESC_RINGSIZE,
-					    &rcv_desc->phys_addr,
-					    &rcv_desc->phys_pdev);
-			if (addr == NULL) {
-				DPRINTK(ERR, "bad return from "
-					"pci_alloc_consistent\n");
-				netxen_free_hw_resources(adapter);
-				err = -ENOMEM;
-				return err;
-			}
-			rcv_desc->desc_head = (struct rcv_desc *)addr;
-			adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr =
-			    cpu_to_le64(rcv_desc->phys_addr);
-			adapter->ctx_desc->rcv_ctx[ring].rcv_ring_size =
-			    cpu_to_le32(rcv_desc->max_rx_desc_count);
-		}
-
-		addr = netxen_alloc(adapter->ahw.pdev, STATUS_DESC_RINGSIZE,
-				    &recv_ctx->rcv_status_desc_phys_addr,
-				    &recv_ctx->rcv_status_desc_pdev);
-		if (addr == NULL) {
-			DPRINTK(ERR, "bad return from"
-				" pci_alloc_consistent\n");
-			netxen_free_hw_resources(adapter);
-			err = -ENOMEM;
-			return err;
-		}
-		recv_ctx->rcv_status_desc_head = (struct status_desc *)addr;
-		adapter->ctx_desc->sts_ring_addr =
-		    cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr);
-		adapter->ctx_desc->sts_ring_size =
-		    cpu_to_le32(adapter->max_rx_desc_count);
-
-	}
-	/* Window = 1 */
-
-	writel(lower32(adapter->ctx_desc_phys_addr),
-	       NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_ADDR_REG_LO(func_id)));
-	writel(upper32(adapter->ctx_desc_phys_addr),
-	       NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_ADDR_REG_HI(func_id)));
-	writel(NETXEN_CTX_SIGNATURE | func_id,
-	       NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_SIGNATURE_REG(func_id)));
-	return err;
-}
-
-void netxen_free_hw_resources(struct netxen_adapter *adapter)
-{
-	struct netxen_recv_context *recv_ctx;
-	struct netxen_rcv_desc_ctx *rcv_desc;
-	int ctx, ring;
-
-	if (adapter->ctx_desc != NULL) {
-		pci_free_consistent(adapter->ctx_desc_pdev,
-				    sizeof(struct netxen_ring_ctx) +
-				    sizeof(uint32_t),
-				    adapter->ctx_desc,
-				    adapter->ctx_desc_phys_addr);
-		adapter->ctx_desc = NULL;
-	}
-
-	if (adapter->ahw.cmd_desc_head != NULL) {
-		pci_free_consistent(adapter->ahw.cmd_desc_pdev,
-				    sizeof(struct cmd_desc_type0) *
-				    adapter->max_tx_desc_count,
-				    adapter->ahw.cmd_desc_head,
-				    adapter->ahw.cmd_desc_phys_addr);
-		adapter->ahw.cmd_desc_head = NULL;
-	}
-
-	for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
-		recv_ctx = &adapter->recv_ctx[ctx];
-		for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
-			rcv_desc = &recv_ctx->rcv_desc[ring];
-
-			if (rcv_desc->desc_head != NULL) {
-				pci_free_consistent(rcv_desc->phys_pdev,
-						    RCV_DESC_RINGSIZE,
-						    rcv_desc->desc_head,
-						    rcv_desc->phys_addr);
-				rcv_desc->desc_head = NULL;
-			}
-		}
-
-		if (recv_ctx->rcv_status_desc_head != NULL) {
-			pci_free_consistent(recv_ctx->rcv_status_desc_pdev,
-					    STATUS_DESC_RINGSIZE,
-					    recv_ctx->rcv_status_desc_head,
-					    recv_ctx->
-					    rcv_status_desc_phys_addr);
-			recv_ctx->rcv_status_desc_head = NULL;
-		}
-	}
-}
-
-void netxen_tso_check(struct netxen_adapter *adapter,
-		      struct cmd_desc_type0 *desc, struct sk_buff *skb)
-{
-	if (desc->mss) {
-		desc->total_hdr_length = (sizeof(struct ethhdr) +
-					  ip_hdrlen(skb) + tcp_hdrlen(skb));
-		netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO);
-	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
-		if (ip_hdr(skb)->protocol == IPPROTO_TCP) {
-			netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT);
-		} else if (ip_hdr(skb)->protocol == IPPROTO_UDP) {
-			netxen_set_cmd_desc_opcode(desc, TX_UDP_PKT);
-		} else {
-			return;
-		}
-	}
-	desc->tcp_hdr_offset = skb_transport_offset(skb);
-	desc->ip_hdr_offset = skb_network_offset(skb);
-}
-
 int netxen_is_flash_supported(struct netxen_adapter *adapter)
 {
 	const int locs[] = { 0, 0x4, 0x100, 0x4000, 0x4128 };
@@ -632,41 +752,49 @@
 	return 0;
 }
 
+#define CRB_WIN_LOCK_TIMEOUT 100000000
+
+static int crb_win_lock(struct netxen_adapter *adapter)
+{
+	int done = 0, timeout = 0;
+
+	while (!done) {
+		/* acquire semaphore3 from PCI HW block */
+		adapter->hw_read_wx(adapter,
+				NETXEN_PCIE_REG(PCIE_SEM7_LOCK), &done, 4);
+		if (done == 1)
+			break;
+		if (timeout >= CRB_WIN_LOCK_TIMEOUT)
+			return -1;
+		timeout++;
+		udelay(1);
+	}
+	netxen_crb_writelit_adapter(adapter,
+			NETXEN_CRB_WIN_LOCK_ID, adapter->portnum);
+	return 0;
+}
+
+static void crb_win_unlock(struct netxen_adapter *adapter)
+{
+	int val;
+
+	adapter->hw_read_wx(adapter,
+			NETXEN_PCIE_REG(PCIE_SEM7_UNLOCK), &val, 4);
+}
+
 /*
  * Changes the CRB window to the specified window.
  */
-void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw)
+void
+netxen_nic_pci_change_crbwindow_128M(struct netxen_adapter *adapter, u32 wndw)
 {
 	void __iomem *offset;
 	u32 tmp;
 	int count = 0;
+	uint8_t func = adapter->ahw.pci_func;
 
 	if (adapter->curr_window == wndw)
 		return;
-	switch(adapter->ahw.pci_func) {
-		case 0:
-			offset = PCI_OFFSET_SECOND_RANGE(adapter,
-					NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW));
-			break;
-		case 1:
-			offset = PCI_OFFSET_SECOND_RANGE(adapter,
-					NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW_F1));
-			break;
-		case 2:
-			offset = PCI_OFFSET_SECOND_RANGE(adapter,
-					NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW_F2));
-			break;
-		case 3:
-			offset = PCI_OFFSET_SECOND_RANGE(adapter,
-					NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW_F3));
-			break;
-		default:
-			printk(KERN_INFO "Changing the window for PCI function "
-					"%d\n",	adapter->ahw.pci_func);
-			offset = PCI_OFFSET_SECOND_RANGE(adapter,
-					NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW));
-			break;
-	}
 	/*
 	 * Move the CRB window.
 	 * We need to write to the "direct access" region of PCI
@@ -675,6 +803,8 @@
 	 * register address is received by PCI. The direct region bypasses
 	 * the CRB bus.
 	 */
+	offset = PCI_OFFSET_SECOND_RANGE(adapter,
+			NETXEN_PCIX_PH_REG(PCIE_CRB_WINDOW_REG(func)));
 
 	if (wndw & 0x1)
 		wndw = NETXEN_WINDOW_ONE;
@@ -685,7 +815,7 @@
 	while ((tmp = readl(offset)) != wndw) {
 		printk(KERN_WARNING "%s: %s WARNING: CRB window value not "
 		       "registered properly: 0x%08x.\n",
-		       netxen_nic_driver_name, __FUNCTION__, tmp);
+		       netxen_nic_driver_name, __func__, tmp);
 		mdelay(1);
 		if (count >= 10)
 			break;
@@ -698,51 +828,119 @@
 		adapter->curr_window = 0;
 }
 
+/*
+ * Return -1 if off is not valid,
+ *	 1 if window access is needed. 'off' is set to offset from
+ *	   CRB space in 128M pci map
+ *	 0 if no window access is needed. 'off' is set to 2M addr
+ * In: 'off' is offset from base in 128M pci map
+ */
+static int
+netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter,
+		ulong *off, int len)
+{
+	unsigned long end = *off + len;
+	crb_128M_2M_sub_block_map_t *m;
+
+
+	if (*off >= NETXEN_CRB_MAX)
+		return -1;
+
+	if (*off >= NETXEN_PCI_CAMQM && (end <= NETXEN_PCI_CAMQM_2M_END)) {
+		*off = (*off - NETXEN_PCI_CAMQM) + NETXEN_PCI_CAMQM_2M_BASE +
+			(ulong)adapter->ahw.pci_base0;
+		return 0;
+	}
+
+	if (*off < NETXEN_PCI_CRBSPACE)
+		return -1;
+
+	*off -= NETXEN_PCI_CRBSPACE;
+	end = *off + len;
+
+	/*
+	 * Try direct map
+	 */
+	m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)];
+
+	if (m->valid && (m->start_128M <= *off) && (m->end_128M >= end)) {
+		*off = *off + m->start_2M - m->start_128M +
+			(ulong)adapter->ahw.pci_base0;
+		return 0;
+	}
+
+	/*
+	 * Not in direct map, use crb window
+	 */
+	return 1;
+}
+
+/*
+ * In: 'off' is offset from CRB space in 128M pci map
+ * Out: 'off' is 2M pci map addr
+ * side effect: lock crb window
+ */
+static void
+netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong *off)
+{
+	u32 win_read;
+
+	adapter->crb_win = CRB_HI(*off);
+	writel(adapter->crb_win, (void *)(CRB_WINDOW_2M +
+		adapter->ahw.pci_base0));
+	/*
+	 * Read back value to make sure write has gone through before trying
+	 * to use it.
+	 */
+	win_read = readl((void *)(CRB_WINDOW_2M + adapter->ahw.pci_base0));
+	if (win_read != adapter->crb_win) {
+		printk(KERN_ERR "%s: Written crbwin (0x%x) != "
+				"Read crbwin (0x%x), off=0x%lx\n",
+				__func__, adapter->crb_win, win_read, *off);
+	}
+	*off = (*off & MASK(16)) + CRB_INDIRECT_2M +
+		(ulong)adapter->ahw.pci_base0;
+}
+
 int netxen_load_firmware(struct netxen_adapter *adapter)
 {
 	int i;
 	u32 data, size = 0;
-	u32 flashaddr = NETXEN_FLASH_BASE, memaddr = NETXEN_PHANTOM_MEM_BASE;
-	u64 off;
-	void __iomem *addr;
+	u32 flashaddr = NETXEN_BOOTLD_START, memaddr = NETXEN_BOOTLD_START;
 
-	size = NETXEN_FIRMWARE_LEN;
-	writel(1, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
+	size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START)/4;
+
+	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+		adapter->pci_write_normalize(adapter,
+				NETXEN_ROMUSB_GLB_CAS_RST, 1);
 
 	for (i = 0; i < size; i++) {
-		int retries = 10;
 		if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0)
 			return -EIO;
 
-		off = netxen_nic_pci_set_window(adapter, memaddr);
-		addr = pci_base_offset(adapter, off);
-		writel(data, addr);
-		do {
-			if (readl(addr) == data)
-				break;
-			msleep(100);
-			writel(data, addr);
-		} while (--retries);
-		if (!retries) {
-			printk(KERN_ERR "%s: firmware load aborted, write failed at 0x%x\n",
-					netxen_nic_driver_name, memaddr);
-			return -EIO;
-		}
+		adapter->pci_mem_write(adapter, memaddr, &data, 4);
 		flashaddr += 4;
 		memaddr += 4;
+		cond_resched();
 	}
-	udelay(100);
-	/* make sure Casper is powered on */
-	writel(0x3fff,
-	       NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL));
-	writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
+	msleep(1);
+
+	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+		adapter->pci_write_normalize(adapter,
+				NETXEN_ROMUSB_GLB_SW_RESET, 0x80001d);
+	else {
+		adapter->pci_write_normalize(adapter,
+				NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL, 0x3fff);
+		adapter->pci_write_normalize(adapter,
+				NETXEN_ROMUSB_GLB_CAS_RST, 0);
+	}
 
 	return 0;
 }
 
 int
-netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
-		       int len)
+netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter,
+		ulong off, void *data, int len)
 {
 	void __iomem *addr;
 
@@ -750,7 +948,7 @@
 		addr = NETXEN_CRB_NORMALIZE(adapter, off);
 	} else {		/* Window 0 */
 		addr = pci_base_offset(adapter, off);
-		netxen_nic_pci_change_crbwindow(adapter, 0);
+		netxen_nic_pci_change_crbwindow_128M(adapter, 0);
 	}
 
 	DPRINTK(INFO, "writing to base %lx offset %llx addr %p"
@@ -758,7 +956,7 @@
 		pci_base(adapter, off), off, addr,
 		*(unsigned long long *)data, len);
 	if (!addr) {
-		netxen_nic_pci_change_crbwindow(adapter, 1);
+		netxen_nic_pci_change_crbwindow_128M(adapter, 1);
 		return 1;
 	}
 
@@ -785,14 +983,14 @@
 		break;
 	}
 	if (!ADDR_IN_WINDOW1(off))
-		netxen_nic_pci_change_crbwindow(adapter, 1);
+		netxen_nic_pci_change_crbwindow_128M(adapter, 1);
 
 	return 0;
 }
 
 int
-netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data,
-		      int len)
+netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter,
+		ulong off, void *data, int len)
 {
 	void __iomem *addr;
 
@@ -800,13 +998,13 @@
 		addr = NETXEN_CRB_NORMALIZE(adapter, off);
 	} else {		/* Window 0 */
 		addr = pci_base_offset(adapter, off);
-		netxen_nic_pci_change_crbwindow(adapter, 0);
+		netxen_nic_pci_change_crbwindow_128M(adapter, 0);
 	}
 
 	DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n",
 		pci_base(adapter, off), off, addr);
 	if (!addr) {
-		netxen_nic_pci_change_crbwindow(adapter, 1);
+		netxen_nic_pci_change_crbwindow_128M(adapter, 1);
 		return 1;
 	}
 	switch (len) {
@@ -830,81 +1028,195 @@
 	DPRINTK(INFO, "read %lx\n", *(unsigned long *)data);
 
 	if (!ADDR_IN_WINDOW1(off))
-		netxen_nic_pci_change_crbwindow(adapter, 1);
+		netxen_nic_pci_change_crbwindow_128M(adapter, 1);
+
+	return 0;
+}
+
+int
+netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter,
+		ulong off, void *data, int len)
+{
+	unsigned long flags = 0;
+	int rv;
+
+	rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, len);
+
+	if (rv == -1) {
+		printk(KERN_ERR "%s: invalid offset: 0x%016lx\n",
+				__func__, off);
+		dump_stack();
+		return -1;
+	}
+
+	if (rv == 1) {
+		write_lock_irqsave(&adapter->adapter_lock, flags);
+		crb_win_lock(adapter);
+		netxen_nic_pci_set_crbwindow_2M(adapter, &off);
+	}
+
+	DPRINTK(1, INFO, "write data %lx to offset %llx, len=%d\n",
+			*(unsigned long *)data, off, len);
+
+	switch (len) {
+	case 1:
+		writeb(*(uint8_t *)data, (void *)off);
+		break;
+	case 2:
+		writew(*(uint16_t *)data, (void *)off);
+		break;
+	case 4:
+		writel(*(uint32_t *)data, (void *)off);
+		break;
+	case 8:
+		writeq(*(uint64_t *)data, (void *)off);
+		break;
+	default:
+		DPRINTK(1, INFO,
+			"writing data %lx to offset %llx, num words=%d\n",
+			*(unsigned long *)data, off, (len>>3));
+		break;
+	}
+	if (rv == 1) {
+		crb_win_unlock(adapter);
+		write_unlock_irqrestore(&adapter->adapter_lock, flags);
+	}
+
+	return 0;
+}
+
+int
+netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter,
+		ulong off, void *data, int len)
+{
+	unsigned long flags = 0;
+	int rv;
+
+	rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, len);
+
+	if (rv == -1) {
+		printk(KERN_ERR "%s: invalid offset: 0x%016lx\n",
+				__func__, off);
+		dump_stack();
+		return -1;
+	}
+
+	if (rv == 1) {
+		write_lock_irqsave(&adapter->adapter_lock, flags);
+		crb_win_lock(adapter);
+		netxen_nic_pci_set_crbwindow_2M(adapter, &off);
+	}
+
+	DPRINTK(1, INFO, "read from offset %lx, len=%d\n", off, len);
+
+	switch (len) {
+	case 1:
+		*(uint8_t *)data = readb((void *)off);
+		break;
+	case 2:
+		*(uint16_t *)data = readw((void *)off);
+		break;
+	case 4:
+		*(uint32_t *)data = readl((void *)off);
+		break;
+	case 8:
+		*(uint64_t *)data = readq((void *)off);
+		break;
+	default:
+		break;
+	}
+
+	DPRINTK(1, INFO, "read %lx\n", *(unsigned long *)data);
+
+	if (rv == 1) {
+		crb_win_unlock(adapter);
+		write_unlock_irqrestore(&adapter->adapter_lock, flags);
+	}
 
 	return 0;
 }
 
 void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val)
-{				/* Only for window 1 */
-	void __iomem *addr;
-
-	addr = NETXEN_CRB_NORMALIZE(adapter, off);
-	DPRINTK(INFO, "writing to base %lx offset %llx addr %p data %x\n",
-		pci_base(adapter, off), off, addr, val);
-	writel(val, addr);
-
+{
+	adapter->hw_write_wx(adapter, off, &val, 4);
 }
 
 int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off)
-{				/* Only for window 1 */
-	void __iomem *addr;
+{
 	int val;
-
-	addr = NETXEN_CRB_NORMALIZE(adapter, off);
-	DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n",
-		pci_base(adapter, off), off, addr);
-	val = readl(addr);
-	writel(val, addr);
-
+	adapter->hw_read_wx(adapter, off, &val, 4);
 	return val;
 }
 
 /* Change the window to 0, write and change back to window 1. */
 void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value)
 {
-	void __iomem *addr;
-
-	netxen_nic_pci_change_crbwindow(adapter, 0);
-	addr = pci_base_offset(adapter, index);
-	writel(value, addr);
-	netxen_nic_pci_change_crbwindow(adapter, 1);
+	adapter->hw_write_wx(adapter, index, &value, 4);
 }
 
 /* Change the window to 0, read and change back to window 1. */
-void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 * value)
+void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 *value)
 {
-	void __iomem *addr;
+	adapter->hw_read_wx(adapter, index, value, 4);
+}
 
-	addr = pci_base_offset(adapter, index);
+void netxen_nic_write_w1(struct netxen_adapter *adapter, u32 index, u32 value)
+{
+	adapter->hw_write_wx(adapter, index, &value, 4);
+}
 
-	netxen_nic_pci_change_crbwindow(adapter, 0);
-	*value = readl(addr);
-	netxen_nic_pci_change_crbwindow(adapter, 1);
+void netxen_nic_read_w1(struct netxen_adapter *adapter, u32 index, u32 *value)
+{
+	adapter->hw_read_wx(adapter, index, value, 4);
+}
+
+/*
+ * check memory access boundary.
+ * used by test agent. support ddr access only for now
+ */
+static unsigned long
+netxen_nic_pci_mem_bound_check(struct netxen_adapter *adapter,
+		unsigned long long addr, int size)
+{
+	if (!ADDR_IN_RANGE(addr,
+			NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX) ||
+		!ADDR_IN_RANGE(addr+size-1,
+			NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX) ||
+		((size != 1) && (size != 2) && (size != 4) && (size != 8))) {
+		return 0;
+	}
+
+	return 1;
 }
 
 static int netxen_pci_set_window_warning_count;
 
-static  unsigned long netxen_nic_pci_set_window(struct netxen_adapter *adapter,
-						unsigned long long addr)
+unsigned long
+netxen_nic_pci_set_window_128M(struct netxen_adapter *adapter,
+		unsigned long long addr)
 {
-	static int ddr_mn_window = -1;
-	static int qdr_sn_window = -1;
+	void __iomem *offset;
 	int window;
+	unsigned long long	qdr_max;
+	uint8_t func = adapter->ahw.pci_func;
+
+	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+		qdr_max = NETXEN_ADDR_QDR_NET_MAX_P2;
+	} else {
+		qdr_max = NETXEN_ADDR_QDR_NET_MAX_P3;
+	}
 
 	if (ADDR_IN_RANGE(addr, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
 		/* DDR network side */
 		addr -= NETXEN_ADDR_DDR_NET;
 		window = (addr >> 25) & 0x3ff;
-		if (ddr_mn_window != window) {
-			ddr_mn_window = window;
-			writel(window, PCI_OFFSET_SECOND_RANGE(adapter,
-							       NETXEN_PCIX_PH_REG
-							       (PCIX_MN_WINDOW(adapter->ahw.pci_func))));
+		if (adapter->ahw.ddr_mn_window != window) {
+			adapter->ahw.ddr_mn_window = window;
+			offset = PCI_OFFSET_SECOND_RANGE(adapter,
+				NETXEN_PCIX_PH_REG(PCIE_MN_WINDOW_REG(func)));
+			writel(window, offset);
 			/* MUST make sure window is set before we forge on... */
-			readl(PCI_OFFSET_SECOND_RANGE(adapter,
-						      NETXEN_PCIX_PH_REG
-						      (PCIX_MN_WINDOW(adapter->ahw.pci_func))));
+			readl(offset);
 		}
 		addr -= (window * NETXEN_WINDOW_ONE);
 		addr += NETXEN_PCI_DDR_NET;
@@ -914,22 +1226,17 @@
 	} else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) {
 		addr -= NETXEN_ADDR_OCM1;
 		addr += NETXEN_PCI_OCM1;
-	} else
-	    if (ADDR_IN_RANGE
-		(addr, NETXEN_ADDR_QDR_NET, NETXEN_ADDR_QDR_NET_MAX)) {
+	} else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_QDR_NET, qdr_max)) {
 		/* QDR network side */
 		addr -= NETXEN_ADDR_QDR_NET;
 		window = (addr >> 22) & 0x3f;
-		if (qdr_sn_window != window) {
-			qdr_sn_window = window;
-			writel((window << 22),
-			       PCI_OFFSET_SECOND_RANGE(adapter,
-						       NETXEN_PCIX_PH_REG
-						       (PCIX_SN_WINDOW(adapter->ahw.pci_func))));
+		if (adapter->ahw.qdr_sn_window != window) {
+			adapter->ahw.qdr_sn_window = window;
+			offset = PCI_OFFSET_SECOND_RANGE(adapter,
+				NETXEN_PCIX_PH_REG(PCIE_SN_WINDOW_REG(func)));
+			writel((window << 22), offset);
 			/* MUST make sure window is set before we forge on... */
-			readl(PCI_OFFSET_SECOND_RANGE(adapter,
-						      NETXEN_PCIX_PH_REG
-						      (PCIX_SN_WINDOW(adapter->ahw.pci_func))));
+			readl(offset);
 		}
 		addr -= (window * 0x400000);
 		addr += NETXEN_PCI_QDR_NET;
@@ -943,11 +1250,711 @@
 			printk("%s: Warning:netxen_nic_pci_set_window()"
 			       " Unknown address range!\n",
 			       netxen_nic_driver_name);
-
+		addr = -1UL;
 	}
 	return addr;
 }
 
+/*
+ * Note : only 32-bit writes!
+ */
+int netxen_nic_pci_write_immediate_128M(struct netxen_adapter *adapter,
+		u64 off, u32 data)
+{
+	writel(data, (void __iomem *)(PCI_OFFSET_SECOND_RANGE(adapter, off)));
+	return 0;
+}
+
+u32 netxen_nic_pci_read_immediate_128M(struct netxen_adapter *adapter, u64 off)
+{
+	return readl((void __iomem *)(pci_base_offset(adapter, off)));
+}
+
+void netxen_nic_pci_write_normalize_128M(struct netxen_adapter *adapter,
+		u64 off, u32 data)
+{
+	writel(data, NETXEN_CRB_NORMALIZE(adapter, off));
+}
+
+u32 netxen_nic_pci_read_normalize_128M(struct netxen_adapter *adapter, u64 off)
+{
+	return readl(NETXEN_CRB_NORMALIZE(adapter, off));
+}
+
+unsigned long
+netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter,
+		unsigned long long addr)
+{
+	int window;
+	u32 win_read;
+
+	if (ADDR_IN_RANGE(addr, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
+		/* DDR network side */
+		window = MN_WIN(addr);
+		adapter->ahw.ddr_mn_window = window;
+		adapter->hw_write_wx(adapter,
+				adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
+				&window, 4);
+		adapter->hw_read_wx(adapter,
+				adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
+				&win_read, 4);
+		if ((win_read << 17) != window) {
+			printk(KERN_INFO "Written MNwin (0x%x) != "
+				"Read MNwin (0x%x)\n", window, win_read);
+		}
+		addr = GET_MEM_OFFS_2M(addr) + NETXEN_PCI_DDR_NET;
+	} else if (ADDR_IN_RANGE(addr,
+				NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) {
+		if ((addr & 0x00ff800) == 0xff800) {
+			printk("%s: QM access not handled.\n", __func__);
+			addr = -1UL;
+		}
+
+		window = OCM_WIN(addr);
+		adapter->ahw.ddr_mn_window = window;
+		adapter->hw_write_wx(adapter,
+				adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
+				&window, 4);
+		adapter->hw_read_wx(adapter,
+				adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
+				&win_read, 4);
+		if ((win_read >> 7) != window) {
+			printk(KERN_INFO "%s: Written OCMwin (0x%x) != "
+					"Read OCMwin (0x%x)\n",
+					__func__, window, win_read);
+		}
+		addr = GET_MEM_OFFS_2M(addr) + NETXEN_PCI_OCM0_2M;
+
+	} else if (ADDR_IN_RANGE(addr,
+			NETXEN_ADDR_QDR_NET, NETXEN_ADDR_QDR_NET_MAX_P3)) {
+		/* QDR network side */
+		window = MS_WIN(addr);
+		adapter->ahw.qdr_sn_window = window;
+		adapter->hw_write_wx(adapter,
+				adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE,
+				&window, 4);
+		adapter->hw_read_wx(adapter,
+				adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE,
+				&win_read, 4);
+		if (win_read != window) {
+			printk(KERN_INFO "%s: Written MSwin (0x%x) != "
+					"Read MSwin (0x%x)\n",
+					__func__, window, win_read);
+		}
+		addr = GET_MEM_OFFS_2M(addr) + NETXEN_PCI_QDR_NET;
+
+	} else {
+		/*
+		 * peg gdb frequently accesses memory that doesn't exist,
+		 * this limits the chit chat so debugging isn't slowed down.
+		 */
+		if ((netxen_pci_set_window_warning_count++ < 8)
+			|| (netxen_pci_set_window_warning_count%64 == 0)) {
+			printk("%s: Warning:%s Unknown address range!\n",
+					__func__, netxen_nic_driver_name);
+}
+		addr = -1UL;
+	}
+	return addr;
+}
+
+static int netxen_nic_pci_is_same_window(struct netxen_adapter *adapter,
+				      unsigned long long addr)
+{
+	int window;
+	unsigned long long qdr_max;
+
+	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+		qdr_max = NETXEN_ADDR_QDR_NET_MAX_P2;
+	else
+		qdr_max = NETXEN_ADDR_QDR_NET_MAX_P3;
+
+	if (ADDR_IN_RANGE(addr,
+			NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
+		/* DDR network side */
+		BUG();	/* MN access can not come here */
+	} else if (ADDR_IN_RANGE(addr,
+			NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) {
+		return 1;
+	} else if (ADDR_IN_RANGE(addr,
+				NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) {
+		return 1;
+	} else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_QDR_NET, qdr_max)) {
+		/* QDR network side */
+		window = ((addr - NETXEN_ADDR_QDR_NET) >> 22) & 0x3f;
+		if (adapter->ahw.qdr_sn_window == window)
+			return 1;
+	}
+
+	return 0;
+}
+
+static int netxen_nic_pci_mem_read_direct(struct netxen_adapter *adapter,
+			u64 off, void *data, int size)
+{
+	unsigned long flags;
+	void *addr;
+	int ret = 0;
+	u64 start;
+	uint8_t *mem_ptr = NULL;
+	unsigned long mem_base;
+	unsigned long mem_page;
+
+	write_lock_irqsave(&adapter->adapter_lock, flags);
+
+	/*
+	 * If attempting to access unknown address or straddle hw windows,
+	 * do not access.
+	 */
+	start = adapter->pci_set_window(adapter, off);
+	if ((start == -1UL) ||
+		(netxen_nic_pci_is_same_window(adapter, off+size-1) == 0)) {
+		write_unlock_irqrestore(&adapter->adapter_lock, flags);
+		printk(KERN_ERR "%s out of bound pci memory access. "
+			"offset is 0x%llx\n", netxen_nic_driver_name, off);
+		return -1;
+	}
+
+	addr = (void *)(pci_base_offset(adapter, start));
+	if (!addr) {
+		write_unlock_irqrestore(&adapter->adapter_lock, flags);
+		mem_base = pci_resource_start(adapter->pdev, 0);
+		mem_page = start & PAGE_MASK;
+		/* Map two pages whenever user tries to access addresses in two
+		consecutive pages.
+		*/
+		if (mem_page != ((start + size - 1) & PAGE_MASK))
+			mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2);
+		else
+			mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE);
+		if (mem_ptr == 0UL) {
+			*(uint8_t  *)data = 0;
+			return -1;
+		}
+		addr = mem_ptr;
+		addr += start & (PAGE_SIZE - 1);
+		write_lock_irqsave(&adapter->adapter_lock, flags);
+	}
+
+	switch (size) {
+	case 1:
+		*(uint8_t  *)data = readb(addr);
+		break;
+	case 2:
+		*(uint16_t *)data = readw(addr);
+		break;
+	case 4:
+		*(uint32_t *)data = readl(addr);
+		break;
+	case 8:
+		*(uint64_t *)data = readq(addr);
+		break;
+	default:
+		ret = -1;
+		break;
+	}
+	write_unlock_irqrestore(&adapter->adapter_lock, flags);
+	DPRINTK(1, INFO, "read %llx\n", *(unsigned long long *)data);
+
+	if (mem_ptr)
+		iounmap(mem_ptr);
+	return ret;
+}
+
+static int
+netxen_nic_pci_mem_write_direct(struct netxen_adapter *adapter, u64 off,
+		void *data, int size)
+{
+	unsigned long flags;
+	void *addr;
+	int ret = 0;
+	u64 start;
+	uint8_t *mem_ptr = NULL;
+	unsigned long mem_base;
+	unsigned long mem_page;
+
+	write_lock_irqsave(&adapter->adapter_lock, flags);
+
+	/*
+	 * If attempting to access unknown address or straddle hw windows,
+	 * do not access.
+	 */
+	start = adapter->pci_set_window(adapter, off);
+	if ((start == -1UL) ||
+		(netxen_nic_pci_is_same_window(adapter, off+size-1) == 0)) {
+		write_unlock_irqrestore(&adapter->adapter_lock, flags);
+		printk(KERN_ERR "%s out of bound pci memory access. "
+			"offset is 0x%llx\n", netxen_nic_driver_name, off);
+		return -1;
+	}
+
+	addr = (void *)(pci_base_offset(adapter, start));
+	if (!addr) {
+		write_unlock_irqrestore(&adapter->adapter_lock, flags);
+		mem_base = pci_resource_start(adapter->pdev, 0);
+		mem_page = start & PAGE_MASK;
+		/* Map two pages whenever user tries to access addresses in two
+		 * consecutive pages.
+		 */
+		if (mem_page != ((start + size - 1) & PAGE_MASK))
+			mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE*2);
+		else
+			mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE);
+		if (mem_ptr == 0UL)
+			return -1;
+		addr = mem_ptr;
+		addr += start & (PAGE_SIZE - 1);
+		write_lock_irqsave(&adapter->adapter_lock, flags);
+	}
+
+	switch (size) {
+	case 1:
+		writeb(*(uint8_t *)data, addr);
+		break;
+	case 2:
+		writew(*(uint16_t *)data, addr);
+		break;
+	case 4:
+		writel(*(uint32_t *)data, addr);
+		break;
+	case 8:
+		writeq(*(uint64_t *)data, addr);
+		break;
+	default:
+		ret = -1;
+		break;
+	}
+	write_unlock_irqrestore(&adapter->adapter_lock, flags);
+	DPRINTK(1, INFO, "writing data %llx to offset %llx\n",
+			*(unsigned long long *)data, start);
+	if (mem_ptr)
+		iounmap(mem_ptr);
+	return ret;
+}
+
+#define MAX_CTL_CHECK   1000
+
+int
+netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter,
+		u64 off, void *data, int size)
+{
+	unsigned long   flags, mem_crb;
+	int	     i, j, ret = 0, loop, sz[2], off0;
+	uint32_t      temp;
+	uint64_t      off8, tmpw, word[2] = {0, 0};
+
+	/*
+	 * If not MN, go check for MS or invalid.
+	 */
+	if (netxen_nic_pci_mem_bound_check(adapter, off, size) == 0)
+		return netxen_nic_pci_mem_write_direct(adapter,
+				off, data, size);
+
+	off8 = off & 0xfffffff8;
+	off0 = off & 0x7;
+	sz[0] = (size < (8 - off0)) ? size : (8 - off0);
+	sz[1] = size - sz[0];
+	loop = ((off0 + size - 1) >> 3) + 1;
+	mem_crb = (unsigned long)pci_base_offset(adapter, NETXEN_CRB_DDR_NET);
+
+	if ((size != 8) || (off0 != 0))  {
+		for (i = 0; i < loop; i++) {
+			if (adapter->pci_mem_read(adapter,
+				off8 + (i << 3), &word[i], 8))
+				return -1;
+		}
+	}
+
+	switch (size) {
+	case 1:
+		tmpw = *((uint8_t *)data);
+		break;
+	case 2:
+		tmpw = *((uint16_t *)data);
+		break;
+	case 4:
+		tmpw = *((uint32_t *)data);
+		break;
+	case 8:
+	default:
+		tmpw = *((uint64_t *)data);
+		break;
+	}
+	word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
+	word[0] |= tmpw << (off0 * 8);
+
+	if (loop == 2) {
+		word[1] &= ~(~0ULL << (sz[1] * 8));
+		word[1] |= tmpw >> (sz[0] * 8);
+	}
+
+	write_lock_irqsave(&adapter->adapter_lock, flags);
+	netxen_nic_pci_change_crbwindow_128M(adapter, 0);
+
+	for (i = 0; i < loop; i++) {
+		writel((uint32_t)(off8 + (i << 3)),
+			(void *)(mem_crb+MIU_TEST_AGT_ADDR_LO));
+		writel(0,
+			(void *)(mem_crb+MIU_TEST_AGT_ADDR_HI));
+		writel(word[i] & 0xffffffff,
+			(void *)(mem_crb+MIU_TEST_AGT_WRDATA_LO));
+		writel((word[i] >> 32) & 0xffffffff,
+			(void *)(mem_crb+MIU_TEST_AGT_WRDATA_HI));
+		writel(MIU_TA_CTL_ENABLE|MIU_TA_CTL_WRITE,
+			(void *)(mem_crb+MIU_TEST_AGT_CTRL));
+		writel(MIU_TA_CTL_START|MIU_TA_CTL_ENABLE|MIU_TA_CTL_WRITE,
+			(void *)(mem_crb+MIU_TEST_AGT_CTRL));
+
+		for (j = 0; j < MAX_CTL_CHECK; j++) {
+			temp = readl(
+			     (void *)(mem_crb+MIU_TEST_AGT_CTRL));
+			if ((temp & MIU_TA_CTL_BUSY) == 0)
+				break;
+		}
+
+		if (j >= MAX_CTL_CHECK) {
+			printk("%s: %s Fail to write through agent\n",
+					__func__, netxen_nic_driver_name);
+			ret = -1;
+			break;
+		}
+	}
+
+	netxen_nic_pci_change_crbwindow_128M(adapter, 1);
+	write_unlock_irqrestore(&adapter->adapter_lock, flags);
+	return ret;
+}
+
+int
+netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter,
+		u64 off, void *data, int size)
+{
+	unsigned long   flags, mem_crb;
+	int	     i, j = 0, k, start, end, loop, sz[2], off0[2];
+	uint32_t      temp;
+	uint64_t      off8, val, word[2] = {0, 0};
+
+
+	/*
+	 * If not MN, go check for MS or invalid.
+	 */
+	if (netxen_nic_pci_mem_bound_check(adapter, off, size) == 0)
+		return netxen_nic_pci_mem_read_direct(adapter, off, data, size);
+
+	off8 = off & 0xfffffff8;
+	off0[0] = off & 0x7;
+	off0[1] = 0;
+	sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]);
+	sz[1] = size - sz[0];
+	loop = ((off0[0] + size - 1) >> 3) + 1;
+	mem_crb = (unsigned long)pci_base_offset(adapter, NETXEN_CRB_DDR_NET);
+
+	write_lock_irqsave(&adapter->adapter_lock, flags);
+	netxen_nic_pci_change_crbwindow_128M(adapter, 0);
+
+	for (i = 0; i < loop; i++) {
+		writel((uint32_t)(off8 + (i << 3)),
+			(void *)(mem_crb+MIU_TEST_AGT_ADDR_LO));
+		writel(0,
+			(void *)(mem_crb+MIU_TEST_AGT_ADDR_HI));
+		writel(MIU_TA_CTL_ENABLE,
+			(void *)(mem_crb+MIU_TEST_AGT_CTRL));
+		writel(MIU_TA_CTL_START|MIU_TA_CTL_ENABLE,
+			(void *)(mem_crb+MIU_TEST_AGT_CTRL));
+
+		for (j = 0; j < MAX_CTL_CHECK; j++) {
+			temp = readl(
+			      (void *)(mem_crb+MIU_TEST_AGT_CTRL));
+			if ((temp & MIU_TA_CTL_BUSY) == 0)
+				break;
+		}
+
+		if (j >= MAX_CTL_CHECK) {
+			printk(KERN_ERR "%s: %s Fail to read through agent\n",
+					__func__, netxen_nic_driver_name);
+			break;
+		}
+
+		start = off0[i] >> 2;
+		end   = (off0[i] + sz[i] - 1) >> 2;
+		for (k = start; k <= end; k++) {
+			word[i] |= ((uint64_t) readl(
+				    (void *)(mem_crb +
+				    MIU_TEST_AGT_RDDATA(k))) << (32*k));
+		}
+	}
+
+	netxen_nic_pci_change_crbwindow_128M(adapter, 1);
+	write_unlock_irqrestore(&adapter->adapter_lock, flags);
+
+	if (j >= MAX_CTL_CHECK)
+		return -1;
+
+	if (sz[0] == 8) {
+		val = word[0];
+	} else {
+		val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) |
+			((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8));
+	}
+
+	switch (size) {
+	case 1:
+		*(uint8_t  *)data = val;
+		break;
+	case 2:
+		*(uint16_t *)data = val;
+		break;
+	case 4:
+		*(uint32_t *)data = val;
+		break;
+	case 8:
+		*(uint64_t *)data = val;
+		break;
+	}
+	DPRINTK(1, INFO, "read %llx\n", *(unsigned long long *)data);
+	return 0;
+}
+
+int
+netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter,
+		u64 off, void *data, int size)
+{
+	int i, j, ret = 0, loop, sz[2], off0;
+	uint32_t temp;
+	uint64_t off8, mem_crb, tmpw, word[2] = {0, 0};
+
+	/*
+	 * If not MN, go check for MS or invalid.
+	 */
+	if (off >= NETXEN_ADDR_QDR_NET && off <= NETXEN_ADDR_QDR_NET_MAX_P3)
+		mem_crb = NETXEN_CRB_QDR_NET;
+	else {
+		mem_crb = NETXEN_CRB_DDR_NET;
+		if (netxen_nic_pci_mem_bound_check(adapter, off, size) == 0)
+			return netxen_nic_pci_mem_write_direct(adapter,
+					off, data, size);
+	}
+
+	off8 = off & 0xfffffff8;
+	off0 = off & 0x7;
+	sz[0] = (size < (8 - off0)) ? size : (8 - off0);
+	sz[1] = size - sz[0];
+	loop = ((off0 + size - 1) >> 3) + 1;
+
+	if ((size != 8) || (off0 != 0)) {
+		for (i = 0; i < loop; i++) {
+			if (adapter->pci_mem_read(adapter, off8 + (i << 3),
+						&word[i], 8))
+				return -1;
+		}
+	}
+
+	switch (size) {
+	case 1:
+		tmpw = *((uint8_t *)data);
+		break;
+	case 2:
+		tmpw = *((uint16_t *)data);
+		break;
+	case 4:
+		tmpw = *((uint32_t *)data);
+		break;
+	case 8:
+	default:
+		tmpw = *((uint64_t *)data);
+	break;
+	}
+
+	word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
+	word[0] |= tmpw << (off0 * 8);
+
+	if (loop == 2) {
+		word[1] &= ~(~0ULL << (sz[1] * 8));
+		word[1] |= tmpw >> (sz[0] * 8);
+	}
+
+	/*
+	 * don't lock here - write_wx gets the lock if each time
+	 * write_lock_irqsave(&adapter->adapter_lock, flags);
+	 * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
+	 */
+
+	for (i = 0; i < loop; i++) {
+		temp = off8 + (i << 3);
+		adapter->hw_write_wx(adapter,
+				mem_crb+MIU_TEST_AGT_ADDR_LO, &temp, 4);
+		temp = 0;
+		adapter->hw_write_wx(adapter,
+				mem_crb+MIU_TEST_AGT_ADDR_HI, &temp, 4);
+		temp = word[i] & 0xffffffff;
+		adapter->hw_write_wx(adapter,
+				mem_crb+MIU_TEST_AGT_WRDATA_LO, &temp, 4);
+		temp = (word[i] >> 32) & 0xffffffff;
+		adapter->hw_write_wx(adapter,
+				mem_crb+MIU_TEST_AGT_WRDATA_HI, &temp, 4);
+		temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
+		adapter->hw_write_wx(adapter,
+				mem_crb+MIU_TEST_AGT_CTRL, &temp, 4);
+		temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
+		adapter->hw_write_wx(adapter,
+				mem_crb+MIU_TEST_AGT_CTRL, &temp, 4);
+
+		for (j = 0; j < MAX_CTL_CHECK; j++) {
+			adapter->hw_read_wx(adapter,
+					mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+			if ((temp & MIU_TA_CTL_BUSY) == 0)
+				break;
+		}
+
+		if (j >= MAX_CTL_CHECK) {
+			printk(KERN_ERR "%s: Fail to write through agent\n",
+					netxen_nic_driver_name);
+			ret = -1;
+			break;
+		}
+	}
+
+	/*
+	 * netxen_nic_pci_change_crbwindow_128M(adapter, 1);
+	 * write_unlock_irqrestore(&adapter->adapter_lock, flags);
+	 */
+	return ret;
+}
+
+int
+netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter,
+		u64 off, void *data, int size)
+{
+	int i, j = 0, k, start, end, loop, sz[2], off0[2];
+	uint32_t      temp;
+	uint64_t      off8, val, mem_crb, word[2] = {0, 0};
+
+	/*
+	 * If not MN, go check for MS or invalid.
+	 */
+
+	if (off >= NETXEN_ADDR_QDR_NET && off <= NETXEN_ADDR_QDR_NET_MAX_P3)
+		mem_crb = NETXEN_CRB_QDR_NET;
+	else {
+		mem_crb = NETXEN_CRB_DDR_NET;
+		if (netxen_nic_pci_mem_bound_check(adapter, off, size) == 0)
+			return netxen_nic_pci_mem_read_direct(adapter,
+					off, data, size);
+	}
+
+	off8 = off & 0xfffffff8;
+	off0[0] = off & 0x7;
+	off0[1] = 0;
+	sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]);
+	sz[1] = size - sz[0];
+	loop = ((off0[0] + size - 1) >> 3) + 1;
+
+	/*
+	 * don't lock here - write_wx gets the lock if each time
+	 * write_lock_irqsave(&adapter->adapter_lock, flags);
+	 * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
+	 */
+
+	for (i = 0; i < loop; i++) {
+		temp = off8 + (i << 3);
+		adapter->hw_write_wx(adapter,
+				mem_crb + MIU_TEST_AGT_ADDR_LO, &temp, 4);
+		temp = 0;
+		adapter->hw_write_wx(adapter,
+				mem_crb + MIU_TEST_AGT_ADDR_HI, &temp, 4);
+		temp = MIU_TA_CTL_ENABLE;
+		adapter->hw_write_wx(adapter,
+				mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+		temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE;
+		adapter->hw_write_wx(adapter,
+				mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+
+		for (j = 0; j < MAX_CTL_CHECK; j++) {
+			adapter->hw_read_wx(adapter,
+					mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+			if ((temp & MIU_TA_CTL_BUSY) == 0)
+				break;
+		}
+
+		if (j >= MAX_CTL_CHECK) {
+			printk(KERN_ERR "%s: Fail to read through agent\n",
+					netxen_nic_driver_name);
+			break;
+		}
+
+		start = off0[i] >> 2;
+		end   = (off0[i] + sz[i] - 1) >> 2;
+		for (k = start; k <= end; k++) {
+			adapter->hw_read_wx(adapter,
+				mem_crb + MIU_TEST_AGT_RDDATA(k), &temp, 4);
+			word[i] |= ((uint64_t)temp << (32 * k));
+		}
+	}
+
+	/*
+	 * netxen_nic_pci_change_crbwindow_128M(adapter, 1);
+	 * write_unlock_irqrestore(&adapter->adapter_lock, flags);
+	 */
+
+	if (j >= MAX_CTL_CHECK)
+		return -1;
+
+	if (sz[0] == 8) {
+		val = word[0];
+	} else {
+		val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) |
+		((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8));
+	}
+
+	switch (size) {
+	case 1:
+		*(uint8_t  *)data = val;
+		break;
+	case 2:
+		*(uint16_t *)data = val;
+		break;
+	case 4:
+		*(uint32_t *)data = val;
+		break;
+	case 8:
+		*(uint64_t *)data = val;
+		break;
+	}
+	DPRINTK(1, INFO, "read %llx\n", *(unsigned long long *)data);
+	return 0;
+}
+
+/*
+ * Note : only 32-bit writes!
+ */
+int netxen_nic_pci_write_immediate_2M(struct netxen_adapter *adapter,
+		u64 off, u32 data)
+{
+	adapter->hw_write_wx(adapter, off, &data, 4);
+
+	return 0;
+}
+
+u32 netxen_nic_pci_read_immediate_2M(struct netxen_adapter *adapter, u64 off)
+{
+	u32 temp;
+	adapter->hw_read_wx(adapter, off, &temp, 4);
+	return temp;
+}
+
+void netxen_nic_pci_write_normalize_2M(struct netxen_adapter *adapter,
+		u64 off, u32 data)
+{
+	adapter->hw_write_wx(adapter, off, &data, 4);
+}
+
+u32 netxen_nic_pci_read_normalize_2M(struct netxen_adapter *adapter, u64 off)
+{
+	u32 temp;
+	adapter->hw_read_wx(adapter, off, &temp, 4);
+	return temp;
+}
+
 #if 0
 int
 netxen_nic_erase_pxe(struct netxen_adapter *adapter)
@@ -1003,12 +2010,25 @@
 	case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
 	case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
 	case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
+	case NETXEN_BRDTYPE_P3_HMEZ:
+	case NETXEN_BRDTYPE_P3_XG_LOM:
+	case NETXEN_BRDTYPE_P3_10G_CX4:
+	case NETXEN_BRDTYPE_P3_10G_CX4_LP:
+	case NETXEN_BRDTYPE_P3_IMEZ:
+	case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
+	case NETXEN_BRDTYPE_P3_10G_XFP:
+	case NETXEN_BRDTYPE_P3_10000_BASE_T:
+
 		adapter->ahw.board_type = NETXEN_NIC_XGBE;
 		break;
 	case NETXEN_BRDTYPE_P1_BD:
 	case NETXEN_BRDTYPE_P1_SB:
 	case NETXEN_BRDTYPE_P1_SMAX:
 	case NETXEN_BRDTYPE_P1_SOCK:
+	case NETXEN_BRDTYPE_P3_REF_QG:
+	case NETXEN_BRDTYPE_P3_4_GB:
+	case NETXEN_BRDTYPE_P3_4_GB_MM:
+
 		adapter->ahw.board_type = NETXEN_NIC_GBE;
 		break;
 	default:
@@ -1042,25 +2062,11 @@
 	return 0;
 }
 
-void netxen_nic_init_niu_gb(struct netxen_adapter *adapter)
-{
-	netxen_niu_gbe_init_port(adapter, adapter->physical_port);
-}
-
 void
-netxen_crb_writelit_adapter(struct netxen_adapter *adapter, unsigned long off,
-			    int data)
+netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
+		unsigned long off, int data)
 {
-	void __iomem *addr;
-
-	if (ADDR_IN_WINDOW1(off)) {
-		writel(data, NETXEN_CRB_NORMALIZE(adapter, off));
-	} else {
-		netxen_nic_pci_change_crbwindow(adapter, 0);
-		addr = pci_base_offset(adapter, off);
-		writel(data, addr);
-		netxen_nic_pci_change_crbwindow(adapter, 1);
-	}
+	adapter->hw_write_wx(adapter, off, &data, 4);
 }
 
 void netxen_nic_set_link_parameters(struct netxen_adapter *adapter)
@@ -1147,12 +2153,11 @@
 		addr += sizeof(u32);
 	}
 
-	fw_major = readl(NETXEN_CRB_NORMALIZE(adapter,
-					      NETXEN_FW_VERSION_MAJOR));
-	fw_minor = readl(NETXEN_CRB_NORMALIZE(adapter,
-					      NETXEN_FW_VERSION_MINOR));
-	fw_build =
-	    readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_FW_VERSION_SUB));
+	adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MAJOR, &fw_major, 4);
+	adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MINOR, &fw_minor, 4);
+	adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_SUB, &fw_build, 4);
+
+	adapter->fw_major = fw_major;
 
 	if (adapter->portnum == 0) {
 		get_brd_name_by_type(board_info->board_type, brd_name);
@@ -1163,28 +2168,13 @@
 				fw_minor, fw_build);
 	}
 
-	if (fw_major != _NETXEN_NIC_LINUX_MAJOR) {
+	if (NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build) <
+			NETXEN_VERSION_CODE(3, 4, 216)) {
 		adapter->driver_mismatch = 1;
-	}
-	if (fw_minor != _NETXEN_NIC_LINUX_MINOR &&
-			fw_minor != (_NETXEN_NIC_LINUX_MINOR + 1)) {
-		adapter->driver_mismatch = 1;
-	}
-	if (adapter->driver_mismatch) {
-		printk(KERN_ERR "%s: driver and firmware version mismatch\n",
-				adapter->netdev->name);
+		printk(KERN_ERR "%s: firmware version %d.%d.%d unsupported\n",
+				netxen_nic_driver_name,
+				fw_major, fw_minor, fw_build);
 		return;
 	}
-
-	switch (adapter->ahw.board_type) {
-	case NETXEN_NIC_GBE:
-		dev_info(&adapter->pdev->dev, "%s: GbE port initialized\n",
-				adapter->netdev->name);
-		break;
-	case NETXEN_NIC_XGBE:
-		dev_info(&adapter->pdev->dev, "%s: XGbE port initialized\n",
-				adapter->netdev->name);
-		break;
-	}
 }
 
diff --git a/drivers/net/netxen/netxen_nic_hw.h b/drivers/net/netxen/netxen_nic_hw.h
index a3ea1dd..b8e0030 100644
--- a/drivers/net/netxen/netxen_nic_hw.h
+++ b/drivers/net/netxen/netxen_nic_hw.h
@@ -82,19 +82,9 @@
 
 #define NETXEN_PCI_MAPSIZE_BYTES  (NETXEN_PCI_MAPSIZE << 20)
 
-#define NETXEN_NIC_LOCKED_READ_REG(X, Y)	\
-	addr = pci_base_offset(adapter, X);	\
-	*(u32 *)Y = readl((void __iomem*) addr);
-
 struct netxen_port;
 void netxen_nic_set_link_parameters(struct netxen_adapter *adapter);
 void netxen_nic_flash_print(struct netxen_adapter *adapter);
-int netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off,
-			   void *data, int len);
-void netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
-				 unsigned long off, int data);
-int netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off,
-			  void *data, int len);
 
 typedef u8 netxen_ethernet_macaddr_t[6];
 
@@ -432,7 +422,8 @@
 /* Promiscous mode options (GbE mode only) */
 typedef enum {
 	NETXEN_NIU_PROMISC_MODE = 0,
-	NETXEN_NIU_NON_PROMISC_MODE
+	NETXEN_NIU_NON_PROMISC_MODE,
+	NETXEN_NIU_ALLMULTI_MODE
 } netxen_niu_prom_mode_t;
 
 /*
@@ -478,42 +469,6 @@
 #define netxen_xg_soft_reset(config_word)	\
 		((config_word) |= 1 << 4)
 
-/*
- * MAC Control Register
- *
- * Bit 0-1   : id_pool0
- * Bit 2     : enable_xtnd0
- * Bit 4-5   : id_pool1
- * Bit 6     : enable_xtnd1
- * Bit 8-9   : id_pool2
- * Bit 10    : enable_xtnd2
- * Bit 12-13 : id_pool3
- * Bit 14    : enable_xtnd3
- * Bit 24-25 : mode_select
- * Bit 28-31 : enable_pool
- */
-
-#define netxen_nic_mcr_set_id_pool0(config, val)	\
-		((config) |= ((val) &0x03))
-#define netxen_nic_mcr_set_enable_xtnd0(config)	\
-		((config) |= 1 << 3)
-#define netxen_nic_mcr_set_id_pool1(config, val)	\
-		((config) |= (((val) & 0x03) << 4))
-#define netxen_nic_mcr_set_enable_xtnd1(config)	\
-		((config) |= 1 << 6)
-#define netxen_nic_mcr_set_id_pool2(config, val)	\
-		((config) |= (((val) & 0x03) << 8))
-#define netxen_nic_mcr_set_enable_xtnd2(config)	\
-		((config) |= 1 << 10)
-#define netxen_nic_mcr_set_id_pool3(config, val)	\
-		((config) |= (((val) & 0x03) << 12))
-#define netxen_nic_mcr_set_enable_xtnd3(config)	\
-		((config) |= 1 << 14)
-#define netxen_nic_mcr_set_mode_select(config, val)	\
-		((config) |= (((val) & 0x03) << 24))
-#define netxen_nic_mcr_set_enable_pool(config, val)	\
-		((config) |= (((val) & 0x0f) << 28))
-
 /* Set promiscuous mode for a GbE interface */
 int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter,
 				    netxen_niu_prom_mode_t mode);
@@ -538,4 +493,15 @@
 
 int netxen_niu_disable_xg_port(struct netxen_adapter *adapter);
 
+typedef struct {
+	unsigned valid;
+	unsigned start_128M;
+	unsigned end_128M;
+	unsigned start_2M;
+} crb_128M_2M_sub_block_map_t;
+
+typedef struct {
+	crb_128M_2M_sub_block_map_t sub_block[16];
+} crb_128M_2M_block_map_t;
+
 #endif				/* __NETXEN_NIC_HW_H_ */
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 70d1b22..01ab31b3 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -42,8 +42,6 @@
 	u32 data;
 };
 
-unsigned long last_schedule_time;
-
 #define NETXEN_MAX_CRB_XFORM 60
 static unsigned int crb_addr_xform[NETXEN_MAX_CRB_XFORM];
 #define NETXEN_ADDR_ERROR (0xffffffff)
@@ -117,6 +115,8 @@
 	crb_addr_transform(C2C1);
 	crb_addr_transform(C2C0);
 	crb_addr_transform(SMB);
+	crb_addr_transform(OCM0);
+	crb_addr_transform(I2C0);
 }
 
 int netxen_init_firmware(struct netxen_adapter *adapter)
@@ -124,15 +124,15 @@
 	u32 state = 0, loops = 0, err = 0;
 
 	/* Window 1 call */
-	state = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+	state = adapter->pci_read_normalize(adapter, CRB_CMDPEG_STATE);
 
 	if (state == PHAN_INITIALIZE_ACK)
 		return 0;
 
 	while (state != PHAN_INITIALIZE_COMPLETE && loops < 2000) {
-		udelay(100);
+		msleep(1);
 		/* Window 1 call */
-		state = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+		state = adapter->pci_read_normalize(adapter, CRB_CMDPEG_STATE);
 
 		loops++;
 	}
@@ -143,64 +143,193 @@
 		return err;
 	}
 	/* Window 1 call */
-	writel(INTR_SCHEME_PERPORT,
-	       NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_HOST));
-	writel(MSI_MODE_MULTIFUNC,
-	       NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_MSI_MODE_HOST));
-	writel(MPORT_MULTI_FUNCTION_MODE,
-	       NETXEN_CRB_NORMALIZE(adapter, CRB_MPORT_MODE));
-	writel(PHAN_INITIALIZE_ACK,
-	       NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+	adapter->pci_write_normalize(adapter,
+			CRB_NIC_CAPABILITIES_HOST, INTR_SCHEME_PERPORT);
+	adapter->pci_write_normalize(adapter,
+			CRB_NIC_MSI_MODE_HOST, MSI_MODE_MULTIFUNC);
+	adapter->pci_write_normalize(adapter,
+			CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE);
+	adapter->pci_write_normalize(adapter,
+			CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
 
 	return err;
 }
 
-#define NETXEN_ADDR_LIMIT 0xffffffffULL
-
-void *netxen_alloc(struct pci_dev *pdev, size_t sz, dma_addr_t * ptr,
-		   struct pci_dev **used_dev)
+void netxen_release_rx_buffers(struct netxen_adapter *adapter)
 {
-	void *addr;
+	struct netxen_recv_context *recv_ctx;
+	struct nx_host_rds_ring *rds_ring;
+	struct netxen_rx_buffer *rx_buf;
+	int i, ctxid, ring;
 
-	addr = pci_alloc_consistent(pdev, sz, ptr);
-	if ((unsigned long long)(*ptr) < NETXEN_ADDR_LIMIT) {
-		*used_dev = pdev;
-		return addr;
+	for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) {
+		recv_ctx = &adapter->recv_ctx[ctxid];
+		for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+			rds_ring = &recv_ctx->rds_rings[ring];
+			for (i = 0; i < rds_ring->max_rx_desc_count; ++i) {
+				rx_buf = &(rds_ring->rx_buf_arr[i]);
+				if (rx_buf->state == NETXEN_BUFFER_FREE)
+					continue;
+				pci_unmap_single(adapter->pdev,
+						rx_buf->dma,
+						rds_ring->dma_size,
+						PCI_DMA_FROMDEVICE);
+				if (rx_buf->skb != NULL)
+					dev_kfree_skb_any(rx_buf->skb);
+			}
+		}
 	}
-	pci_free_consistent(pdev, sz, addr, *ptr);
-	addr = pci_alloc_consistent(NULL, sz, ptr);
-	*used_dev = NULL;
-	return addr;
 }
 
-void netxen_initialize_adapter_sw(struct netxen_adapter *adapter)
+void netxen_release_tx_buffers(struct netxen_adapter *adapter)
 {
-	int ctxid, ring;
-	u32 i;
-	u32 num_rx_bufs = 0;
-	struct netxen_rcv_desc_ctx *rcv_desc;
+	struct netxen_cmd_buffer *cmd_buf;
+	struct netxen_skb_frag *buffrag;
+	int i, j;
 
-	DPRINTK(INFO, "initializing some queues: %p\n", adapter);
-	for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) {
-		for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
-			struct netxen_rx_buffer *rx_buf;
-			rcv_desc = &adapter->recv_ctx[ctxid].rcv_desc[ring];
-			rcv_desc->begin_alloc = 0;
-			rx_buf = rcv_desc->rx_buf_arr;
-			num_rx_bufs = rcv_desc->max_rx_desc_count;
+	cmd_buf = adapter->cmd_buf_arr;
+	for (i = 0; i < adapter->max_tx_desc_count; i++) {
+		buffrag = cmd_buf->frag_array;
+		if (buffrag->dma) {
+			pci_unmap_single(adapter->pdev, buffrag->dma,
+					 buffrag->length, PCI_DMA_TODEVICE);
+			buffrag->dma = 0ULL;
+		}
+		for (j = 0; j < cmd_buf->frag_count; j++) {
+			buffrag++;
+			if (buffrag->dma) {
+				pci_unmap_page(adapter->pdev, buffrag->dma,
+					       buffrag->length,
+					       PCI_DMA_TODEVICE);
+				buffrag->dma = 0ULL;
+			}
+		}
+		/* Free the skb we received in netxen_nic_xmit_frame */
+		if (cmd_buf->skb) {
+			dev_kfree_skb_any(cmd_buf->skb);
+			cmd_buf->skb = NULL;
+		}
+		cmd_buf++;
+	}
+}
+
+void netxen_free_sw_resources(struct netxen_adapter *adapter)
+{
+	struct netxen_recv_context *recv_ctx;
+	struct nx_host_rds_ring *rds_ring;
+	int ctx, ring;
+
+	for (ctx = 0; ctx < MAX_RCV_CTX; ctx++) {
+		recv_ctx = &adapter->recv_ctx[ctx];
+		for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+			rds_ring = &recv_ctx->rds_rings[ring];
+			if (rds_ring->rx_buf_arr) {
+				vfree(rds_ring->rx_buf_arr);
+				rds_ring->rx_buf_arr = NULL;
+			}
+		}
+	}
+	if (adapter->cmd_buf_arr)
+		vfree(adapter->cmd_buf_arr);
+	return;
+}
+
+int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
+{
+	struct netxen_recv_context *recv_ctx;
+	struct nx_host_rds_ring *rds_ring;
+	struct netxen_rx_buffer *rx_buf;
+	int ctx, ring, i, num_rx_bufs;
+
+	struct netxen_cmd_buffer *cmd_buf_arr;
+	struct net_device *netdev = adapter->netdev;
+
+	cmd_buf_arr = (struct netxen_cmd_buffer *)vmalloc(TX_RINGSIZE);
+	if (cmd_buf_arr == NULL) {
+		printk(KERN_ERR "%s: Failed to allocate cmd buffer ring\n",
+		       netdev->name);
+		return -ENOMEM;
+	}
+	memset(cmd_buf_arr, 0, TX_RINGSIZE);
+	adapter->cmd_buf_arr = cmd_buf_arr;
+
+	for (ctx = 0; ctx < MAX_RCV_CTX; ctx++) {
+		recv_ctx = &adapter->recv_ctx[ctx];
+		for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+			rds_ring = &recv_ctx->rds_rings[ring];
+			switch (RCV_DESC_TYPE(ring)) {
+			case RCV_DESC_NORMAL:
+				rds_ring->max_rx_desc_count =
+					adapter->max_rx_desc_count;
+				rds_ring->flags = RCV_DESC_NORMAL;
+				if (adapter->ahw.cut_through) {
+					rds_ring->dma_size =
+						NX_CT_DEFAULT_RX_BUF_LEN;
+					rds_ring->skb_size =
+						NX_CT_DEFAULT_RX_BUF_LEN;
+				} else {
+					rds_ring->dma_size = RX_DMA_MAP_LEN;
+					rds_ring->skb_size =
+						MAX_RX_BUFFER_LENGTH;
+				}
+				break;
+
+			case RCV_DESC_JUMBO:
+				rds_ring->max_rx_desc_count =
+					adapter->max_jumbo_rx_desc_count;
+				rds_ring->flags = RCV_DESC_JUMBO;
+				if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+					rds_ring->dma_size =
+						NX_P3_RX_JUMBO_BUF_MAX_LEN;
+				else
+					rds_ring->dma_size =
+						NX_P2_RX_JUMBO_BUF_MAX_LEN;
+				rds_ring->skb_size =
+					rds_ring->dma_size + NET_IP_ALIGN;
+				break;
+
+			case RCV_RING_LRO:
+				rds_ring->max_rx_desc_count =
+					adapter->max_lro_rx_desc_count;
+				rds_ring->flags = RCV_DESC_LRO;
+				rds_ring->dma_size = RX_LRO_DMA_MAP_LEN;
+				rds_ring->skb_size = MAX_RX_LRO_BUFFER_LENGTH;
+				break;
+
+			}
+			rds_ring->rx_buf_arr = (struct netxen_rx_buffer *)
+				vmalloc(RCV_BUFFSIZE);
+			if (rds_ring->rx_buf_arr == NULL) {
+				printk(KERN_ERR "%s: Failed to allocate "
+					"rx buffer ring %d\n",
+					netdev->name, ring);
+				/* free whatever was already allocated */
+				goto err_out;
+			}
+			memset(rds_ring->rx_buf_arr, 0, RCV_BUFFSIZE);
+			INIT_LIST_HEAD(&rds_ring->free_list);
+			rds_ring->begin_alloc = 0;
 			/*
 			 * Now go through all of them, set reference handles
 			 * and put them in the queues.
 			 */
+			num_rx_bufs = rds_ring->max_rx_desc_count;
+			rx_buf = rds_ring->rx_buf_arr;
 			for (i = 0; i < num_rx_bufs; i++) {
+				list_add_tail(&rx_buf->list,
+						&rds_ring->free_list);
 				rx_buf->ref_handle = i;
 				rx_buf->state = NETXEN_BUFFER_FREE;
-				DPRINTK(INFO, "Rx buf:ctx%d i(%d) rx_buf:"
-					"%p\n", ctxid, i, rx_buf);
 				rx_buf++;
 			}
 		}
 	}
+
+	return 0;
+
+err_out:
+	netxen_free_sw_resources(adapter);
+	return -ENOMEM;
 }
 
 void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
@@ -211,14 +340,12 @@
 		    netxen_niu_gbe_enable_phy_interrupts;
 		adapter->disable_phy_interrupts =
 		    netxen_niu_gbe_disable_phy_interrupts;
-		adapter->handle_phy_intr = netxen_nic_gbe_handle_phy_intr;
 		adapter->macaddr_set = netxen_niu_macaddr_set;
 		adapter->set_mtu = netxen_nic_set_mtu_gb;
 		adapter->set_promisc = netxen_niu_set_promiscuous_mode;
-		adapter->unset_promisc = netxen_niu_set_promiscuous_mode;
 		adapter->phy_read = netxen_niu_gbe_phy_read;
 		adapter->phy_write = netxen_niu_gbe_phy_write;
-		adapter->init_niu = netxen_nic_init_niu_gb;
+		adapter->init_port = netxen_niu_gbe_init_port;
 		adapter->stop_port = netxen_niu_disable_gbe_port;
 		break;
 
@@ -227,12 +354,10 @@
 		    netxen_niu_xgbe_enable_phy_interrupts;
 		adapter->disable_phy_interrupts =
 		    netxen_niu_xgbe_disable_phy_interrupts;
-		adapter->handle_phy_intr = netxen_nic_xgbe_handle_phy_intr;
 		adapter->macaddr_set = netxen_niu_xg_macaddr_set;
 		adapter->set_mtu = netxen_nic_set_mtu_xgb;
 		adapter->init_port = netxen_niu_xg_init_port;
 		adapter->set_promisc = netxen_niu_xg_set_promiscuous_mode;
-		adapter->unset_promisc = netxen_niu_xg_set_promiscuous_mode;
 		adapter->stop_port = netxen_niu_disable_xg_port;
 		break;
 
@@ -270,7 +395,9 @@
 
 static long rom_max_timeout = 100;
 static long rom_lock_timeout = 10000;
+#if 0
 static long rom_write_timeout = 700;
+#endif
 
 static int rom_lock(struct netxen_adapter *adapter)
 {
@@ -319,6 +446,7 @@
 	return 0;
 }
 
+#if 0
 static int netxen_rom_wren(struct netxen_adapter *adapter)
 {
 	/* Set write enable latch in ROM status register */
@@ -348,6 +476,7 @@
 	}
 	return netxen_rdcrbreg(adapter, NETXEN_ROMUSB_ROM_RDATA);
 }
+#endif
 
 static void netxen_rom_unlock(struct netxen_adapter *adapter)
 {
@@ -358,6 +487,7 @@
 
 }
 
+#if 0
 static int netxen_rom_wip_poll(struct netxen_adapter *adapter)
 {
 	long timeout = 0;
@@ -393,6 +523,7 @@
 
 	return netxen_rom_wip_poll(adapter);
 }
+#endif
 
 static int do_rom_fast_read(struct netxen_adapter *adapter,
 			    int addr, int *valp)
@@ -475,7 +606,6 @@
 	netxen_rom_unlock(adapter);
 	return ret;
 }
-#endif  /*  0  */
 
 static int do_rom_fast_write_words(struct netxen_adapter *adapter,
 				   int addr, u8 *bytes, size_t size)
@@ -740,28 +870,25 @@
 
 	return ret;
 }
+#endif  /*  0  */
 
 #define NETXEN_BOARDTYPE		0x4008
 #define NETXEN_BOARDNUM 		0x400c
 #define NETXEN_CHIPNUM			0x4010
-#define NETXEN_ROMBUS_RESET		0xFFFFFFFF
-#define NETXEN_ROM_FIRST_BARRIER	0x800000000ULL
-#define NETXEN_ROM_FOUND_INIT		0x400
 
 int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
 {
 	int addr, val;
-	int n, i;
-	int init_delay = 0;
+	int i, init_delay = 0;
 	struct crb_addr_pair *buf;
+	unsigned offset, n;
 	u32 off;
 
 	/* resetall */
 	netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET,
-				    NETXEN_ROMBUS_RESET);
+				    0xffffffff);
 
 	if (verbose) {
-		int val;
 		if (netxen_rom_fast_read(adapter, NETXEN_BOARDTYPE, &val) == 0)
 			printk("P2 ROM board type: 0x%08x\n", val);
 		else
@@ -776,117 +903,141 @@
 			printk("Could not read chip number\n");
 	}
 
-	if (netxen_rom_fast_read(adapter, 0, &n) == 0
-	    && (n & NETXEN_ROM_FIRST_BARRIER)) {
-		n &= ~NETXEN_ROM_ROUNDUP;
-		if (n < NETXEN_ROM_FOUND_INIT) {
-			if (verbose)
-				printk("%s: %d CRB init values found"
-				       " in ROM.\n", netxen_nic_driver_name, n);
-		} else {
-			printk("%s:n=0x%x Error! NetXen card flash not"
-			       " initialized.\n", __FUNCTION__, n);
+	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+		if (netxen_rom_fast_read(adapter, 0, &n) != 0 ||
+			(n != 0xcafecafeUL) ||
+			netxen_rom_fast_read(adapter, 4, &n) != 0) {
+			printk(KERN_ERR "%s: ERROR Reading crb_init area: "
+					"n: %08x\n", netxen_nic_driver_name, n);
 			return -EIO;
 		}
-		buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL);
-		if (buf == NULL) {
-			printk("%s: netxen_pinit_from_rom: Unable to calloc "
-			       "memory.\n", netxen_nic_driver_name);
-			return -ENOMEM;
+		offset = n & 0xffffU;
+		n = (n >> 16) & 0xffffU;
+	} else {
+		if (netxen_rom_fast_read(adapter, 0, &n) != 0 ||
+			!(n & 0x80000000)) {
+			printk(KERN_ERR "%s: ERROR Reading crb_init area: "
+					"n: %08x\n", netxen_nic_driver_name, n);
+			return -EIO;
 		}
-		for (i = 0; i < n; i++) {
-			if (netxen_rom_fast_read(adapter, 8 * i + 4, &val) != 0
-			    || netxen_rom_fast_read(adapter, 8 * i + 8,
-						    &addr) != 0)
-				return -EIO;
+		offset = 1;
+		n &= ~0x80000000;
+	}
 
-			buf[i].addr = addr;
-			buf[i].data = val;
+	if (n < 1024) {
+		if (verbose)
+			printk(KERN_DEBUG "%s: %d CRB init values found"
+			       " in ROM.\n", netxen_nic_driver_name, n);
+	} else {
+		printk(KERN_ERR "%s:n=0x%x Error! NetXen card flash not"
+		       " initialized.\n", __func__, n);
+		return -EIO;
+	}
 
-			if (verbose)
-				printk("%s: PCI:     0x%08x == 0x%08x\n",
-				       netxen_nic_driver_name, (unsigned int)
-				       netxen_decode_crb_addr(addr), val);
-		}
-		for (i = 0; i < n; i++) {
+	buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL);
+	if (buf == NULL) {
+		printk("%s: netxen_pinit_from_rom: Unable to calloc memory.\n",
+				netxen_nic_driver_name);
+		return -ENOMEM;
+	}
+	for (i = 0; i < n; i++) {
+		if (netxen_rom_fast_read(adapter, 8*i + 4*offset, &val) != 0 ||
+		netxen_rom_fast_read(adapter, 8*i + 4*offset + 4, &addr) != 0)
+			return -EIO;
 
-			off = netxen_decode_crb_addr(buf[i].addr);
-			if (off == NETXEN_ADDR_ERROR) {
-				printk(KERN_ERR"CRB init value out of range %x\n",
+		buf[i].addr = addr;
+		buf[i].data = val;
+
+		if (verbose)
+			printk(KERN_DEBUG "%s: PCI:     0x%08x == 0x%08x\n",
+				netxen_nic_driver_name,
+				(u32)netxen_decode_crb_addr(addr), val);
+	}
+	for (i = 0; i < n; i++) {
+
+		off = netxen_decode_crb_addr(buf[i].addr);
+		if (off == NETXEN_ADDR_ERROR) {
+			printk(KERN_ERR"CRB init value out of range %x\n",
 					buf[i].addr);
-				continue;
-			}
-			off += NETXEN_PCI_CRBSPACE;
-			/* skipping cold reboot MAGIC */
-			if (off == NETXEN_CAM_RAM(0x1fc))
-				continue;
+			continue;
+		}
+		off += NETXEN_PCI_CRBSPACE;
+		/* skipping cold reboot MAGIC */
+		if (off == NETXEN_CAM_RAM(0x1fc))
+			continue;
 
-			/* After writing this register, HW needs time for CRB */
-			/* to quiet down (else crb_window returns 0xffffffff) */
-			if (off == NETXEN_ROMUSB_GLB_SW_RESET) {
-				init_delay = 1;
+		if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+			/* do not reset PCI */
+			if (off == (ROMUSB_GLB + 0xbc))
+				continue;
+			if (off == (NETXEN_CRB_PEG_NET_1 + 0x18))
+				buf[i].data = 0x1020;
+			/* skip the function enable register */
+			if (off == NETXEN_PCIE_REG(PCIE_SETUP_FUNCTION))
+				continue;
+			if (off == NETXEN_PCIE_REG(PCIE_SETUP_FUNCTION2))
+				continue;
+			if ((off & 0x0ff00000) == NETXEN_CRB_SMB)
+				continue;
+		}
+
+		if (off == NETXEN_ADDR_ERROR) {
+			printk(KERN_ERR "%s: Err: Unknown addr: 0x%08x\n",
+					netxen_nic_driver_name, buf[i].addr);
+			continue;
+		}
+
+		/* After writing this register, HW needs time for CRB */
+		/* to quiet down (else crb_window returns 0xffffffff) */
+		if (off == NETXEN_ROMUSB_GLB_SW_RESET) {
+			init_delay = 1;
+			if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
 				/* hold xdma in reset also */
 				buf[i].data = NETXEN_NIC_XDMA_RESET;
 			}
-
-			if (ADDR_IN_WINDOW1(off)) {
-				writel(buf[i].data,
-				       NETXEN_CRB_NORMALIZE(adapter, off));
-			} else {
-				netxen_nic_pci_change_crbwindow(adapter, 0);
-				writel(buf[i].data,
-				       pci_base_offset(adapter, off));
-
-				netxen_nic_pci_change_crbwindow(adapter, 1);
-			}
-			if (init_delay == 1) {
-				msleep(1000);
-				init_delay = 0;
-			}
-			msleep(1);
 		}
-		kfree(buf);
 
-		/* disable_peg_cache_all */
+		adapter->hw_write_wx(adapter, off, &buf[i].data, 4);
 
-		/* unreset_net_cache */
-		netxen_nic_hw_read_wx(adapter, NETXEN_ROMUSB_GLB_SW_RESET, &val,
-				      4);
-		netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET,
-					    (val & 0xffffff0f));
-		/* p2dn replyCount */
-		netxen_crb_writelit_adapter(adapter,
-					    NETXEN_CRB_PEG_NET_D + 0xec, 0x1e);
-		/* disable_peg_cache 0 */
-		netxen_crb_writelit_adapter(adapter,
-					    NETXEN_CRB_PEG_NET_D + 0x4c, 8);
-		/* disable_peg_cache 1 */
-		netxen_crb_writelit_adapter(adapter,
-					    NETXEN_CRB_PEG_NET_I + 0x4c, 8);
-
-		/* peg_clr_all */
-
-		/* peg_clr 0 */
-		netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0x8,
-					    0);
-		netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0xc,
-					    0);
-		/* peg_clr 1 */
-		netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0x8,
-					    0);
-		netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0xc,
-					    0);
-		/* peg_clr 2 */
-		netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0x8,
-					    0);
-		netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0xc,
-					    0);
-		/* peg_clr 3 */
-		netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0x8,
-					    0);
-		netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0xc,
-					    0);
+		if (init_delay == 1) {
+			msleep(1000);
+			init_delay = 0;
+		}
+		msleep(1);
 	}
+	kfree(buf);
+
+	/* disable_peg_cache_all */
+
+	/* unreset_net_cache */
+	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+		adapter->hw_read_wx(adapter,
+				NETXEN_ROMUSB_GLB_SW_RESET, &val, 4);
+		netxen_crb_writelit_adapter(adapter,
+				NETXEN_ROMUSB_GLB_SW_RESET, (val & 0xffffff0f));
+	}
+
+	/* p2dn replyCount */
+	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_D + 0xec, 0x1e);
+	/* disable_peg_cache 0 */
+	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_D + 0x4c, 8);
+	/* disable_peg_cache 1 */
+	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_I + 0x4c, 8);
+
+	/* peg_clr_all */
+
+	/* peg_clr 0 */
+	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0x8, 0);
+	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0xc, 0);
+	/* peg_clr 1 */
+	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0x8, 0);
+	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0xc, 0);
+	/* peg_clr 2 */
+	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0x8, 0);
+	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0xc, 0);
+	/* peg_clr 3 */
+	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0x8, 0);
+	netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0xc, 0);
 	return 0;
 }
 
@@ -897,12 +1048,12 @@
 	uint32_t lo;
 
 	adapter->dummy_dma.addr =
-	    pci_alloc_consistent(adapter->ahw.pdev,
+	    pci_alloc_consistent(adapter->pdev,
 				 NETXEN_HOST_DUMMY_DMA_SIZE,
 				 &adapter->dummy_dma.phys_addr);
 	if (adapter->dummy_dma.addr == NULL) {
 		printk("%s: ERROR: Could not allocate dummy DMA memory\n",
-		       __FUNCTION__);
+		       __func__);
 		return -ENOMEM;
 	}
 
@@ -910,8 +1061,13 @@
 	hi = (addr >> 32) & 0xffffffff;
 	lo = addr & 0xffffffff;
 
-	writel(hi, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI));
-	writel(lo, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO));
+	adapter->pci_write_normalize(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI, hi);
+	adapter->pci_write_normalize(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO, lo);
+
+	if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+		uint32_t temp = 0;
+		adapter->hw_write_wx(adapter, CRB_HOST_DUMMY_BUF, &temp, 4);
+	}
 
 	return 0;
 }
@@ -931,7 +1087,7 @@
 		} while (--i);
 
 		if (i) {
-			pci_free_consistent(adapter->ahw.pdev,
+			pci_free_consistent(adapter->pdev,
 				    NETXEN_HOST_DUMMY_DMA_SIZE,
 				    adapter->dummy_dma.addr,
 				    adapter->dummy_dma.phys_addr);
@@ -946,22 +1102,24 @@
 int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
 {
 	u32 val = 0;
-	int retries = 30;
+	int retries = 60;
 
 	if (!pegtune_val) {
 		do {
-			val = readl(NETXEN_CRB_NORMALIZE
-				  (adapter, CRB_CMDPEG_STATE));
-			pegtune_val = readl(NETXEN_CRB_NORMALIZE
-				  (adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE));
+			val = adapter->pci_read_normalize(adapter,
+					CRB_CMDPEG_STATE);
 
 			if (val == PHAN_INITIALIZE_COMPLETE ||
 				val == PHAN_INITIALIZE_ACK)
 				return 0;
 
-			msleep(1000);
+			msleep(500);
+
 		} while (--retries);
+
 		if (!retries) {
+			pegtune_val = adapter->pci_read_normalize(adapter,
+					NETXEN_ROMUSB_GLB_PEGTUNE_DONE);
 			printk(KERN_WARNING "netxen_phantom_init: init failed, "
 					"pegtune_val=%x\n", pegtune_val);
 			return -1;
@@ -971,58 +1129,61 @@
 	return 0;
 }
 
-static int netxen_nic_check_temp(struct netxen_adapter *adapter)
+int netxen_receive_peg_ready(struct netxen_adapter *adapter)
 {
-	struct net_device *netdev = adapter->netdev;
-	uint32_t temp, temp_state, temp_val;
-	int rv = 0;
+	u32 val = 0;
+	int retries = 2000;
 
-	temp = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_TEMP_STATE));
+	do {
+		val = adapter->pci_read_normalize(adapter, CRB_RCVPEG_STATE);
 
-	temp_state = nx_get_temp_state(temp);
-	temp_val = nx_get_temp_val(temp);
+		if (val == PHAN_PEG_RCV_INITIALIZED)
+			return 0;
 
-	if (temp_state == NX_TEMP_PANIC) {
-		printk(KERN_ALERT
-		       "%s: Device temperature %d degrees C exceeds"
-		       " maximum allowed. Hardware has been shut down.\n",
-		       netxen_nic_driver_name, temp_val);
+		msleep(10);
 
-		netif_carrier_off(netdev);
-		netif_stop_queue(netdev);
-		rv = 1;
-	} else if (temp_state == NX_TEMP_WARN) {
-		if (adapter->temp == NX_TEMP_NORMAL) {
-			printk(KERN_ALERT
-			       "%s: Device temperature %d degrees C "
-			       "exceeds operating range."
-			       " Immediate action needed.\n",
-			       netxen_nic_driver_name, temp_val);
-		}
-	} else {
-		if (adapter->temp == NX_TEMP_WARN) {
-			printk(KERN_INFO
-			       "%s: Device temperature is now %d degrees C"
-			       " in normal range.\n", netxen_nic_driver_name,
-			       temp_val);
-		}
+	} while (--retries);
+
+	if (!retries) {
+		printk(KERN_ERR "Receive Peg initialization not "
+			      "complete, state: 0x%x.\n", val);
+		return -EIO;
 	}
-	adapter->temp = temp_state;
-	return rv;
+
+	return 0;
 }
 
-void netxen_watchdog_task(struct work_struct *work)
+static struct sk_buff *netxen_process_rxbuf(struct netxen_adapter *adapter,
+		struct nx_host_rds_ring *rds_ring, u16 index, u16 cksum)
 {
-	struct netxen_adapter *adapter =
-		container_of(work, struct netxen_adapter, watchdog_task);
+	struct netxen_rx_buffer *buffer;
+	struct sk_buff *skb;
 
-	if ((adapter->portnum  == 0) && netxen_nic_check_temp(adapter))
-		return;
+	buffer = &rds_ring->rx_buf_arr[index];
 
-	if (adapter->handle_phy_intr)
-		adapter->handle_phy_intr(adapter);
+	pci_unmap_single(adapter->pdev, buffer->dma, rds_ring->dma_size,
+			PCI_DMA_FROMDEVICE);
 
-	mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+	skb = buffer->skb;
+	if (!skb)
+		goto no_skb;
+
+	if (likely(adapter->rx_csum && cksum == STATUS_CKSUM_OK)) {
+		adapter->stats.csummed++;
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+	} else
+		skb->ip_summed = CHECKSUM_NONE;
+
+	skb->dev = adapter->netdev;
+
+	buffer->skb = NULL;
+
+no_skb:
+	buffer->state = NETXEN_BUFFER_FREE;
+	buffer->lro_current_frags = 0;
+	buffer->lro_expected_frags = 0;
+	list_add_tail(&buffer->list, &rds_ring->free_list);
+	return skb;
 }
 
 /*
@@ -1031,9 +1192,8 @@
  * invoke the routine to send more rx buffers to the Phantom...
  */
 static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
-			       struct status_desc *desc)
+		struct status_desc *desc, struct status_desc *frag_desc)
 {
-	struct pci_dev *pdev = adapter->pdev;
 	struct net_device *netdev = adapter->netdev;
 	u64 sts_data = le64_to_cpu(desc->status_desc_data);
 	int index = netxen_get_sts_refhandle(sts_data);
@@ -1042,8 +1202,8 @@
 	struct sk_buff *skb;
 	u32 length = netxen_get_sts_totallength(sts_data);
 	u32 desc_ctx;
-	struct netxen_rcv_desc_ctx *rcv_desc;
-	int ret;
+	u16 pkt_offset = 0, cksum;
+	struct nx_host_rds_ring *rds_ring;
 
 	desc_ctx = netxen_get_sts_type(sts_data);
 	if (unlikely(desc_ctx >= NUM_RCV_DESC_RINGS)) {
@@ -1052,13 +1212,13 @@
 		return;
 	}
 
-	rcv_desc = &recv_ctx->rcv_desc[desc_ctx];
-	if (unlikely(index > rcv_desc->max_rx_desc_count)) {
+	rds_ring = &recv_ctx->rds_rings[desc_ctx];
+	if (unlikely(index > rds_ring->max_rx_desc_count)) {
 		DPRINTK(ERR, "Got a buffer index:%x Max is %x\n",
-			index, rcv_desc->max_rx_desc_count);
+			index, rds_ring->max_rx_desc_count);
 		return;
 	}
-	buffer = &rcv_desc->rx_buf_arr[index];
+	buffer = &rds_ring->rx_buf_arr[index];
 	if (desc_ctx == RCV_DESC_LRO_CTXID) {
 		buffer->lro_current_frags++;
 		if (netxen_get_sts_desc_lro_last_frag(desc)) {
@@ -1079,43 +1239,52 @@
 		}
 	}
 
-	pci_unmap_single(pdev, buffer->dma, rcv_desc->dma_size,
-			 PCI_DMA_FROMDEVICE);
+	cksum = netxen_get_sts_status(sts_data);
 
-	skb = (struct sk_buff *)buffer->skb;
+	skb = netxen_process_rxbuf(adapter, rds_ring, index, cksum);
+	if (!skb)
+		return;
 
-	if (likely(adapter->rx_csum &&
-			netxen_get_sts_status(sts_data) == STATUS_CKSUM_OK)) {
-		adapter->stats.csummed++;
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-	} else
-		skb->ip_summed = CHECKSUM_NONE;
-
-	skb->dev = netdev;
 	if (desc_ctx == RCV_DESC_LRO_CTXID) {
 		/* True length was only available on the last pkt */
 		skb_put(skb, buffer->lro_length);
 	} else {
-		skb_put(skb, length);
+		if (length > rds_ring->skb_size)
+			skb_put(skb, rds_ring->skb_size);
+		else
+			skb_put(skb, length);
+
+		pkt_offset = netxen_get_sts_pkt_offset(sts_data);
+		if (pkt_offset)
+			skb_pull(skb, pkt_offset);
 	}
 
 	skb->protocol = eth_type_trans(skb, netdev);
 
-	ret = netif_receive_skb(skb);
-	netdev->last_rx = jiffies;
-
-	rcv_desc->rcv_pending--;
-
 	/*
-	 * We just consumed one buffer so post a buffer.
+	 * rx buffer chaining is disabled, walk and free
+	 * any spurious rx buffer chain.
 	 */
-	buffer->skb = NULL;
-	buffer->state = NETXEN_BUFFER_FREE;
-	buffer->lro_current_frags = 0;
-	buffer->lro_expected_frags = 0;
+	if (frag_desc) {
+		u16 i, nr_frags = desc->nr_frags;
 
-	adapter->stats.no_rcv++;
-	adapter->stats.rxbytes += length;
+		dev_kfree_skb_any(skb);
+		for (i = 0; i < nr_frags; i++) {
+			index = frag_desc->frag_handles[i];
+			skb = netxen_process_rxbuf(adapter,
+					rds_ring, index, cksum);
+			if (skb)
+				dev_kfree_skb_any(skb);
+		}
+		adapter->stats.rxdropped++;
+	} else {
+
+		netif_receive_skb(skb);
+		netdev->last_rx = jiffies;
+
+		adapter->stats.no_rcv++;
+		adapter->stats.rxbytes += length;
+	}
 }
 
 /* Process Receive status ring */
@@ -1123,10 +1292,11 @@
 {
 	struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctxid]);
 	struct status_desc *desc_head = recv_ctx->rcv_status_desc_head;
-	struct status_desc *desc;	/* used to read status desc here */
+	struct status_desc *desc, *frag_desc;
 	u32 consumer = recv_ctx->status_rx_consumer;
-	u32 producer = 0;
 	int count = 0, ring;
+	u64 sts_data;
+	u16 opcode;
 
 	while (count < max) {
 		desc = &desc_head[consumer];
@@ -1135,24 +1305,38 @@
 				netxen_get_sts_owner(desc));
 			break;
 		}
-		netxen_process_rcv(adapter, ctxid, desc);
+
+		sts_data = le64_to_cpu(desc->status_desc_data);
+		opcode = netxen_get_sts_opcode(sts_data);
+		frag_desc = NULL;
+		if (opcode == NETXEN_NIC_RXPKT_DESC) {
+			if (desc->nr_frags) {
+				consumer = get_next_index(consumer,
+						adapter->max_rx_desc_count);
+				frag_desc = &desc_head[consumer];
+				netxen_set_sts_owner(frag_desc,
+						STATUS_OWNER_PHANTOM);
+			}
+		}
+
+		netxen_process_rcv(adapter, ctxid, desc, frag_desc);
+
 		netxen_set_sts_owner(desc, STATUS_OWNER_PHANTOM);
-		consumer = (consumer + 1) & (adapter->max_rx_desc_count - 1);
+
+		consumer = get_next_index(consumer,
+				adapter->max_rx_desc_count);
 		count++;
 	}
-	for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++)
+	for (ring = 0; ring < adapter->max_rds_rings; ring++)
 		netxen_post_rx_buffers_nodb(adapter, ctxid, ring);
 
 	/* update the consumer index in phantom */
 	if (count) {
 		recv_ctx->status_rx_consumer = consumer;
-		recv_ctx->status_rx_producer = producer;
 
 		/* Window = 1 */
-		writel(consumer,
-		       NETXEN_CRB_NORMALIZE(adapter,
-				    recv_crb_registers[adapter->portnum].
-					    crb_rcv_status_consumer));
+		adapter->pci_write_normalize(adapter,
+				recv_ctx->crb_sts_consumer, consumer);
 	}
 
 	return count;
@@ -1231,10 +1415,10 @@
  */
 void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
 {
-	struct pci_dev *pdev = adapter->ahw.pdev;
+	struct pci_dev *pdev = adapter->pdev;
 	struct sk_buff *skb;
 	struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]);
-	struct netxen_rcv_desc_ctx *rcv_desc = NULL;
+	struct nx_host_rds_ring *rds_ring = NULL;
 	uint producer;
 	struct rcv_desc *pdesc;
 	struct netxen_rx_buffer *buffer;
@@ -1242,41 +1426,36 @@
 	int index = 0;
 	netxen_ctx_msg msg = 0;
 	dma_addr_t dma;
+	struct list_head *head;
 
-	rcv_desc = &recv_ctx->rcv_desc[ringid];
+	rds_ring = &recv_ctx->rds_rings[ringid];
 
-	producer = rcv_desc->producer;
-	index = rcv_desc->begin_alloc;
-	buffer = &rcv_desc->rx_buf_arr[index];
+	producer = rds_ring->producer;
+	index = rds_ring->begin_alloc;
+	head = &rds_ring->free_list;
+
 	/* We can start writing rx descriptors into the phantom memory. */
-	while (buffer->state == NETXEN_BUFFER_FREE) {
-		skb = dev_alloc_skb(rcv_desc->skb_size);
+	while (!list_empty(head)) {
+
+		skb = dev_alloc_skb(rds_ring->skb_size);
 		if (unlikely(!skb)) {
-			/*
-			 * TODO
-			 * We need to schedule the posting of buffers to the pegs.
-			 */
-			rcv_desc->begin_alloc = index;
-			DPRINTK(ERR, "netxen_post_rx_buffers: "
-				" allocated only %d buffers\n", count);
+			rds_ring->begin_alloc = index;
 			break;
 		}
 
-		count++;	/* now there should be no failure */
-		pdesc = &rcv_desc->desc_head[producer];
+		buffer = list_entry(head->next, struct netxen_rx_buffer, list);
+		list_del(&buffer->list);
 
-#if defined(XGB_DEBUG)
-		*(unsigned long *)(skb->head) = 0xc0debabe;
-		if (skb_is_nonlinear(skb)) {
-			printk("Allocated SKB @%p is nonlinear\n");
-		}
-#endif
-		skb_reserve(skb, 2);
+		count++;	/* now there should be no failure */
+		pdesc = &rds_ring->desc_head[producer];
+
+		if (!adapter->ahw.cut_through)
+			skb_reserve(skb, 2);
 		/* This will be setup when we receive the
 		 * buffer after it has been filled  FSL  TBD TBD
 		 * skb->dev = netdev;
 		 */
-		dma = pci_map_single(pdev, skb->data, rcv_desc->dma_size,
+		dma = pci_map_single(pdev, skb->data, rds_ring->dma_size,
 				     PCI_DMA_FROMDEVICE);
 		pdesc->addr_buffer = cpu_to_le64(dma);
 		buffer->skb = skb;
@@ -1284,112 +1463,101 @@
 		buffer->dma = dma;
 		/* make a rcv descriptor  */
 		pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
-		pdesc->buffer_length = cpu_to_le32(rcv_desc->dma_size);
+		pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
 		DPRINTK(INFO, "done writing descripter\n");
 		producer =
-		    get_next_index(producer, rcv_desc->max_rx_desc_count);
-		index = get_next_index(index, rcv_desc->max_rx_desc_count);
-		buffer = &rcv_desc->rx_buf_arr[index];
+		    get_next_index(producer, rds_ring->max_rx_desc_count);
+		index = get_next_index(index, rds_ring->max_rx_desc_count);
 	}
 	/* if we did allocate buffers, then write the count to Phantom */
 	if (count) {
-		rcv_desc->begin_alloc = index;
-		rcv_desc->rcv_pending += count;
-		rcv_desc->producer = producer;
+		rds_ring->begin_alloc = index;
+		rds_ring->producer = producer;
 			/* Window = 1 */
-			writel((producer - 1) &
-			       (rcv_desc->max_rx_desc_count - 1),
-			       NETXEN_CRB_NORMALIZE(adapter,
-						    recv_crb_registers[
-						    adapter->portnum].
-						    rcv_desc_crb[ringid].
-						    crb_rcv_producer_offset));
+		adapter->pci_write_normalize(adapter,
+				rds_ring->crb_rcv_producer,
+				(producer-1) & (rds_ring->max_rx_desc_count-1));
+
+		if (adapter->fw_major < 4) {
 			/*
 			 * Write a doorbell msg to tell phanmon of change in
 			 * receive ring producer
+			 * Only for firmware version < 4.0.0
 			 */
 			netxen_set_msg_peg_id(msg, NETXEN_RCV_PEG_DB_ID);
 			netxen_set_msg_privid(msg);
 			netxen_set_msg_count(msg,
 					     ((producer -
-					       1) & (rcv_desc->
+					       1) & (rds_ring->
 						     max_rx_desc_count - 1)));
 			netxen_set_msg_ctxid(msg, adapter->portnum);
 			netxen_set_msg_opcode(msg, NETXEN_RCV_PRODUCER(ringid));
 			writel(msg,
 			       DB_NORMALIZE(adapter,
 					    NETXEN_RCV_PRODUCER_OFFSET));
+		}
 	}
 }
 
 static void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
 					uint32_t ctx, uint32_t ringid)
 {
-	struct pci_dev *pdev = adapter->ahw.pdev;
+	struct pci_dev *pdev = adapter->pdev;
 	struct sk_buff *skb;
 	struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]);
-	struct netxen_rcv_desc_ctx *rcv_desc = NULL;
+	struct nx_host_rds_ring *rds_ring = NULL;
 	u32 producer;
 	struct rcv_desc *pdesc;
 	struct netxen_rx_buffer *buffer;
 	int count = 0;
 	int index = 0;
+	struct list_head *head;
 
-	rcv_desc = &recv_ctx->rcv_desc[ringid];
+	rds_ring = &recv_ctx->rds_rings[ringid];
 
-	producer = rcv_desc->producer;
-	index = rcv_desc->begin_alloc;
-	buffer = &rcv_desc->rx_buf_arr[index];
+	producer = rds_ring->producer;
+	index = rds_ring->begin_alloc;
+	head = &rds_ring->free_list;
 	/* We can start writing rx descriptors into the phantom memory. */
-	while (buffer->state == NETXEN_BUFFER_FREE) {
-		skb = dev_alloc_skb(rcv_desc->skb_size);
+	while (!list_empty(head)) {
+
+		skb = dev_alloc_skb(rds_ring->skb_size);
 		if (unlikely(!skb)) {
-			/*
-			 * We need to schedule the posting of buffers to the pegs.
-			 */
-			rcv_desc->begin_alloc = index;
-			DPRINTK(ERR, "netxen_post_rx_buffers_nodb: "
-				" allocated only %d buffers\n", count);
+			rds_ring->begin_alloc = index;
 			break;
 		}
+
+		buffer = list_entry(head->next, struct netxen_rx_buffer, list);
+		list_del(&buffer->list);
+
 		count++;	/* now there should be no failure */
-		pdesc = &rcv_desc->desc_head[producer];
-		skb_reserve(skb, 2);
-		/*
-		 * This will be setup when we receive the
-		 * buffer after it has been filled
-		 * skb->dev = netdev;
-		 */
+		pdesc = &rds_ring->desc_head[producer];
+		if (!adapter->ahw.cut_through)
+			skb_reserve(skb, 2);
 		buffer->skb = skb;
 		buffer->state = NETXEN_BUFFER_BUSY;
 		buffer->dma = pci_map_single(pdev, skb->data,
-					     rcv_desc->dma_size,
+					     rds_ring->dma_size,
 					     PCI_DMA_FROMDEVICE);
 
 		/* make a rcv descriptor  */
 		pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
-		pdesc->buffer_length = cpu_to_le32(rcv_desc->dma_size);
+		pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
 		pdesc->addr_buffer = cpu_to_le64(buffer->dma);
-		DPRINTK(INFO, "done writing descripter\n");
 		producer =
-		    get_next_index(producer, rcv_desc->max_rx_desc_count);
-		index = get_next_index(index, rcv_desc->max_rx_desc_count);
-		buffer = &rcv_desc->rx_buf_arr[index];
+		    get_next_index(producer, rds_ring->max_rx_desc_count);
+		index = get_next_index(index, rds_ring->max_rx_desc_count);
+		buffer = &rds_ring->rx_buf_arr[index];
 	}
 
 	/* if we did allocate buffers, then write the count to Phantom */
 	if (count) {
-		rcv_desc->begin_alloc = index;
-		rcv_desc->rcv_pending += count;
-		rcv_desc->producer = producer;
+		rds_ring->begin_alloc = index;
+		rds_ring->producer = producer;
 			/* Window = 1 */
-			writel((producer - 1) &
-			       (rcv_desc->max_rx_desc_count - 1),
-			       NETXEN_CRB_NORMALIZE(adapter,
-						    recv_crb_registers[
-						    adapter->portnum].
-						    rcv_desc_crb[ringid].
-						    crb_rcv_producer_offset));
+		adapter->pci_write_normalize(adapter,
+			rds_ring->crb_rcv_producer,
+				(producer-1) & (rds_ring->max_rx_desc_count-1));
 			wmb();
 	}
 }
diff --git a/drivers/net/netxen/netxen_nic_isr.c b/drivers/net/netxen/netxen_nic_isr.c
deleted file mode 100644
index 96cec41..0000000
--- a/drivers/net/netxen/netxen_nic_isr.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (C) 2003 - 2006 NetXen, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  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.
- *
- * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.
- *
- * Contact Information:
- *    info@netxen.com
- * NetXen,
- * 3965 Freedom Circle, Fourth floor,
- * Santa Clara, CA 95054
- */
-
-#include <linux/netdevice.h>
-#include <linux/delay.h>
-
-#include "netxen_nic.h"
-#include "netxen_nic_hw.h"
-#include "netxen_nic_phan_reg.h"
-
-/*
- * netxen_nic_get_stats - Get System Network Statistics
- * @netdev: network interface device structure
- */
-struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
-{
-	struct netxen_adapter *adapter = netdev_priv(netdev);
-	struct net_device_stats *stats = &adapter->net_stats;
-
-	memset(stats, 0, sizeof(*stats));
-
-	/* total packets received   */
-	stats->rx_packets = adapter->stats.no_rcv;
-	/* total packets transmitted    */
-	stats->tx_packets = adapter->stats.xmitedframes +
-		adapter->stats.xmitfinished;
-	/* total bytes received     */
-	stats->rx_bytes = adapter->stats.rxbytes;
-	/* total bytes transmitted  */
-	stats->tx_bytes = adapter->stats.txbytes;
-	/* bad packets received     */
-	stats->rx_errors = adapter->stats.rcvdbadskb;
-	/* packet transmit problems */
-	stats->tx_errors = adapter->stats.nocmddescriptor;
-	/* no space in linux buffers    */
-	stats->rx_dropped = adapter->stats.rxdropped;
-	/* no space available in linux  */
-	stats->tx_dropped = adapter->stats.txdropped;
-
-	return stats;
-}
-
-static void netxen_indicate_link_status(struct netxen_adapter *adapter,
-					u32 link)
-{
-	struct net_device *netdev = adapter->netdev;
-
-	if (link)
-		netif_carrier_on(netdev);
-	else
-		netif_carrier_off(netdev);
-}
-
-#if 0
-void netxen_handle_port_int(struct netxen_adapter *adapter, u32 enable)
-{
-	__u32 int_src;
-
-	/*  This should clear the interrupt source */
-	if (adapter->phy_read)
-		adapter->phy_read(adapter,
-				  NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS,
-				  &int_src);
-	if (int_src == 0) {
-		DPRINTK(INFO, "No phy interrupts for port #%d\n", portno);
-		return;
-	}
-	if (adapter->disable_phy_interrupts)
-		adapter->disable_phy_interrupts(adapter);
-
-	if (netxen_get_phy_int_jabber(int_src))
-		DPRINTK(INFO, "Jabber interrupt \n");
-
-	if (netxen_get_phy_int_polarity_changed(int_src))
-		DPRINTK(INFO, "POLARITY CHANGED int \n");
-
-	if (netxen_get_phy_int_energy_detect(int_src))
-		DPRINTK(INFO, "ENERGY DETECT INT \n");
-
-	if (netxen_get_phy_int_downshift(int_src))
-		DPRINTK(INFO, "DOWNSHIFT INT \n");
-	/* write it down later.. */
-	if ((netxen_get_phy_int_speed_changed(int_src))
-	    || (netxen_get_phy_int_link_status_changed(int_src))) {
-		__u32 status;
-
-		DPRINTK(INFO, "SPEED CHANGED OR LINK STATUS CHANGED \n");
-
-		if (adapter->phy_read
-		    && adapter->phy_read(adapter,
-					 NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
-					 &status) == 0) {
-			if (netxen_get_phy_int_link_status_changed(int_src)) {
-				if (netxen_get_phy_link(status)) {
-					printk(KERN_INFO "%s: %s Link UP\n",
-					       netxen_nic_driver_name,
-					       adapter->netdev->name);
-
-				} else {
-					printk(KERN_INFO "%s: %s Link DOWN\n",
-					       netxen_nic_driver_name,
-					       adapter->netdev->name);
-				}
-				netxen_indicate_link_status(adapter,
-							    netxen_get_phy_link
-							    (status));
-			}
-		}
-	}
-	if (adapter->enable_phy_interrupts)
-		adapter->enable_phy_interrupts(adapter);
-}
-#endif  /*  0  */
-
-static void netxen_nic_isr_other(struct netxen_adapter *adapter)
-{
-	int portno = adapter->portnum;
-	u32 val, linkup, qg_linksup;
-
-	/* verify the offset */
-	val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE));
-	val = val >> adapter->physical_port;
-	if (val == adapter->ahw.qg_linksup)
-		return;
-
-	qg_linksup = adapter->ahw.qg_linksup;
-	adapter->ahw.qg_linksup = val;
-	DPRINTK(INFO, "link update 0x%08x\n", val);
-
-	linkup = val & 1;
-
-	if (linkup != (qg_linksup & 1)) {
-		printk(KERN_INFO "%s: %s PORT %d link %s\n",
-		       adapter->netdev->name,
-		       netxen_nic_driver_name, portno,
-		       ((linkup == 0) ? "down" : "up"));
-		netxen_indicate_link_status(adapter, linkup);
-		if (linkup)
-			netxen_nic_set_link_parameters(adapter);
-
-	}
-}
-
-void netxen_nic_gbe_handle_phy_intr(struct netxen_adapter *adapter)
-{
-	netxen_nic_isr_other(adapter);
-}
-
-#if 0
-int netxen_nic_link_ok(struct netxen_adapter *adapter)
-{
-	switch (adapter->ahw.board_type) {
-	case NETXEN_NIC_GBE:
-		return ((adapter->ahw.qg_linksup) & 1);
-
-	case NETXEN_NIC_XGBE:
-		return ((adapter->ahw.xg_linkup) & 1);
-
-	default:
-		printk(KERN_ERR"%s: Function: %s, Unknown board type\n",
-			netxen_nic_driver_name, __FUNCTION__);
-		break;
-	}
-
-	return 0;
-}
-#endif  /*  0  */
-
-void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter)
-{
-	struct net_device *netdev = adapter->netdev;
-	u32 val;
-
-	/* WINDOW = 1 */
-	val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE));
-	val >>= (adapter->physical_port * 8);
-	val &= 0xff;
-
-	if (adapter->ahw.xg_linkup == 1 && val != XG_LINK_UP) {
-		printk(KERN_INFO "%s: %s NIC Link is down\n",
-		       netxen_nic_driver_name, netdev->name);
-		adapter->ahw.xg_linkup = 0;
-		if (netif_running(netdev)) {
-			netif_carrier_off(netdev);
-			netif_stop_queue(netdev);
-		}
-	} else if (adapter->ahw.xg_linkup == 0 && val == XG_LINK_UP) {
-		printk(KERN_INFO "%s: %s NIC Link is up\n",
-		       netxen_nic_driver_name, netdev->name);
-		adapter->ahw.xg_linkup = 1;
-		netif_carrier_on(netdev);
-		netif_wake_queue(netdev);
-	}
-}
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 63cd67b..91d209a 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -49,13 +49,18 @@
 static char netxen_nic_driver_string[] = "NetXen Network Driver version "
     NETXEN_NIC_LINUX_VERSIONID;
 
-#define NETXEN_NETDEV_WEIGHT 120
-#define NETXEN_ADAPTER_UP_MAGIC 777
-#define NETXEN_NIC_PEG_TUNE 0
+static int port_mode = NETXEN_PORT_MODE_AUTO_NEG;
+
+/* Default to restricted 1G auto-neg mode */
+static int wol_port_mode = 5;
+
+static int use_msi = 1;
+
+static int use_msi_x = 1;
 
 /* Local functions to NetXen NIC driver */
 static int __devinit netxen_nic_probe(struct pci_dev *pdev,
-				      const struct pci_device_id *ent);
+		const struct pci_device_id *ent);
 static void __devexit netxen_nic_remove(struct pci_dev *pdev);
 static int netxen_nic_open(struct net_device *netdev);
 static int netxen_nic_close(struct net_device *netdev);
@@ -83,6 +88,7 @@
 	ENTRY(0x0005),
 	ENTRY(0x0024),
 	ENTRY(0x0025),
+	ENTRY(0x0100),
 	{0,}
 };
 
@@ -108,95 +114,61 @@
 
 static void netxen_watchdog(unsigned long);
 
-static void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
-					   uint32_t crb_producer)
+static uint32_t crb_cmd_producer[4] = {
+	CRB_CMD_PRODUCER_OFFSET, CRB_CMD_PRODUCER_OFFSET_1,
+	CRB_CMD_PRODUCER_OFFSET_2, CRB_CMD_PRODUCER_OFFSET_3
+};
+
+void
+netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
+		uint32_t crb_producer)
 {
-	switch (adapter->portnum) {
-		case 0:
-			writel(crb_producer, NETXEN_CRB_NORMALIZE
-					(adapter, CRB_CMD_PRODUCER_OFFSET));
-			return;
-		case 1:
-			writel(crb_producer, NETXEN_CRB_NORMALIZE
-					(adapter, CRB_CMD_PRODUCER_OFFSET_1));
-			return;
-		case 2:
-			writel(crb_producer, NETXEN_CRB_NORMALIZE
-					(adapter, CRB_CMD_PRODUCER_OFFSET_2));
-			return;
-		case 3:
-			writel(crb_producer, NETXEN_CRB_NORMALIZE
-					(adapter, CRB_CMD_PRODUCER_OFFSET_3));
-			return;
-		default:
-			printk(KERN_WARNING "We tried to update "
-					"CRB_CMD_PRODUCER_OFFSET for invalid "
-					"PCI function id %d\n",
-					adapter->portnum);
-			return;
-	}
+	adapter->pci_write_normalize(adapter,
+			adapter->crb_addr_cmd_producer, crb_producer);
 }
 
-static void netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter,
-					   u32 crb_consumer)
+static uint32_t crb_cmd_consumer[4] = {
+	CRB_CMD_CONSUMER_OFFSET, CRB_CMD_CONSUMER_OFFSET_1,
+	CRB_CMD_CONSUMER_OFFSET_2, CRB_CMD_CONSUMER_OFFSET_3
+};
+
+static inline void
+netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter,
+		u32 crb_consumer)
 {
-	switch (adapter->portnum) {
-		case 0:
-			writel(crb_consumer, NETXEN_CRB_NORMALIZE
-				(adapter, CRB_CMD_CONSUMER_OFFSET));
-			return;
-		case 1:
-			writel(crb_consumer, NETXEN_CRB_NORMALIZE
-				(adapter, CRB_CMD_CONSUMER_OFFSET_1));
-			return;
-		case 2:
-			writel(crb_consumer, NETXEN_CRB_NORMALIZE
-				(adapter, CRB_CMD_CONSUMER_OFFSET_2));
-			return;
-		case 3:
-			writel(crb_consumer, NETXEN_CRB_NORMALIZE
-				(adapter, CRB_CMD_CONSUMER_OFFSET_3));
-			return;
-		default:
-			printk(KERN_WARNING "We tried to update "
-					"CRB_CMD_PRODUCER_OFFSET for invalid "
-					"PCI function id %d\n",
-					adapter->portnum);
-			return;
-	}
+	adapter->pci_write_normalize(adapter,
+			adapter->crb_addr_cmd_consumer, crb_consumer);
 }
 
-#define	ADAPTER_LIST_SIZE 12
-
-static uint32_t msi_tgt_status[4] = {
+static uint32_t msi_tgt_status[8] = {
 	ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1,
-	ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3
+	ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3,
+	ISR_INT_TARGET_STATUS_F4, ISR_INT_TARGET_STATUS_F5,
+	ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7
 };
 
-static uint32_t sw_int_mask[4] = {
-	CRB_SW_INT_MASK_0, CRB_SW_INT_MASK_1,
-	CRB_SW_INT_MASK_2, CRB_SW_INT_MASK_3
-};
+static struct netxen_legacy_intr_set legacy_intr[] = NX_LEGACY_INTR_CONFIG;
 
 static void netxen_nic_disable_int(struct netxen_adapter *adapter)
 {
 	u32 mask = 0x7ff;
 	int retries = 32;
-	int port = adapter->portnum;
 	int pci_fn = adapter->ahw.pci_func;
 
 	if (adapter->msi_mode != MSI_MODE_MULTIFUNC)
-		writel(0x0, NETXEN_CRB_NORMALIZE(adapter, sw_int_mask[port]));
+		adapter->pci_write_normalize(adapter,
+				adapter->crb_intr_mask, 0);
 
 	if (adapter->intr_scheme != -1 &&
 	    adapter->intr_scheme != INTR_SCHEME_PERPORT)
-		writel(mask,PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
+		adapter->pci_write_immediate(adapter, ISR_INT_MASK, mask);
 
-	if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+	if (!NETXEN_IS_MSI_FAMILY(adapter)) {
 		do {
-			writel(0xffffffff,
-			       PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_STATUS));
-			mask = readl(pci_base_offset(adapter, ISR_INT_VECTOR));
+			adapter->pci_write_immediate(adapter,
+					ISR_INT_TARGET_STATUS, 0xffffffff);
+			mask = adapter->pci_read_immediate(adapter,
+					ISR_INT_VECTOR);
 			if (!(mask & 0x80))
 				break;
 			udelay(10);
@@ -208,8 +180,8 @@
 		}
 	} else {
 		if (adapter->msi_mode == MSI_MODE_MULTIFUNC) {
-			writel(0xffffffff, PCI_OFFSET_SECOND_RANGE(adapter,
-						msi_tgt_status[pci_fn]));
+			adapter->pci_write_immediate(adapter,
+					msi_tgt_status[pci_fn], 0xffffffff);
 		}
 	}
 }
@@ -217,7 +189,6 @@
 static void netxen_nic_enable_int(struct netxen_adapter *adapter)
 {
 	u32 mask;
-	int port = adapter->portnum;
 
 	DPRINTK(1, INFO, "Entered ISR Enable \n");
 
@@ -235,24 +206,299 @@
 			break;
 		}
 
-		writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
+		adapter->pci_write_immediate(adapter, ISR_INT_MASK, mask);
 	}
 
-	writel(0x1, NETXEN_CRB_NORMALIZE(adapter, sw_int_mask[port]));
+	adapter->pci_write_normalize(adapter, adapter->crb_intr_mask, 0x1);
 
-	if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+	if (!NETXEN_IS_MSI_FAMILY(adapter)) {
 		mask = 0xbff;
 		if (adapter->intr_scheme != -1 &&
 			adapter->intr_scheme != INTR_SCHEME_PERPORT) {
-			writel(0X0, NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
+			adapter->pci_write_normalize(adapter,
+					CRB_INT_VECTOR, 0);
 		}
-		writel(mask,
-		       PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_MASK));
+		adapter->pci_write_immediate(adapter,
+				ISR_INT_TARGET_MASK, mask);
 	}
 
 	DPRINTK(1, INFO, "Done with enable Int\n");
 }
 
+static int nx_set_dma_mask(struct netxen_adapter *adapter, uint8_t revision_id)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	int err;
+	uint64_t mask;
+
+#ifdef CONFIG_IA64
+	adapter->dma_mask = DMA_32BIT_MASK;
+#else
+	if (revision_id >= NX_P3_B0) {
+		/* should go to DMA_64BIT_MASK */
+		adapter->dma_mask = DMA_39BIT_MASK;
+		mask = DMA_39BIT_MASK;
+	} else if (revision_id == NX_P3_A2) {
+		adapter->dma_mask = DMA_39BIT_MASK;
+		mask = DMA_39BIT_MASK;
+	} else if (revision_id == NX_P2_C1) {
+		adapter->dma_mask = DMA_35BIT_MASK;
+		mask = DMA_35BIT_MASK;
+	} else {
+		adapter->dma_mask = DMA_32BIT_MASK;
+		mask = DMA_32BIT_MASK;
+		goto set_32_bit_mask;
+	}
+
+	/*
+	 * Consistent DMA mask is set to 32 bit because it cannot be set to
+	 * 35 bits. For P3 also leave it at 32 bits for now. Only the rings
+	 * come off this pool.
+	 */
+	if (pci_set_dma_mask(pdev, mask) == 0 &&
+		pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK) == 0) {
+		adapter->pci_using_dac = 1;
+		return 0;
+	}
+#endif /* CONFIG_IA64 */
+
+set_32_bit_mask:
+	err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+	if (!err)
+		err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+	if (err) {
+		DPRINTK(ERR, "No usable DMA configuration, aborting:%d\n", err);
+		return err;
+	}
+
+	adapter->pci_using_dac = 0;
+	return 0;
+}
+
+static void netxen_check_options(struct netxen_adapter *adapter)
+{
+	switch (adapter->ahw.boardcfg.board_type) {
+	case NETXEN_BRDTYPE_P3_HMEZ:
+	case NETXEN_BRDTYPE_P3_XG_LOM:
+	case NETXEN_BRDTYPE_P3_10G_CX4:
+	case NETXEN_BRDTYPE_P3_10G_CX4_LP:
+	case NETXEN_BRDTYPE_P3_IMEZ:
+	case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
+	case NETXEN_BRDTYPE_P3_10G_XFP:
+	case NETXEN_BRDTYPE_P3_10000_BASE_T:
+		adapter->msix_supported = !!use_msi_x;
+		adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G;
+		break;
+
+	case NETXEN_BRDTYPE_P2_SB31_10G:
+	case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
+	case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
+	case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
+		adapter->msix_supported = 0;
+		adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G;
+		break;
+
+	case NETXEN_BRDTYPE_P3_REF_QG:
+	case NETXEN_BRDTYPE_P3_4_GB:
+	case NETXEN_BRDTYPE_P3_4_GB_MM:
+	case NETXEN_BRDTYPE_P2_SB35_4G:
+	case NETXEN_BRDTYPE_P2_SB31_2G:
+		adapter->msix_supported = 0;
+		adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
+		break;
+
+	default:
+		adapter->msix_supported = 0;
+		adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
+
+		printk(KERN_WARNING "Unknown board type(0x%x)\n",
+				adapter->ahw.boardcfg.board_type);
+		break;
+	}
+
+	adapter->max_tx_desc_count = MAX_CMD_DESCRIPTORS_HOST;
+	adapter->max_jumbo_rx_desc_count = MAX_JUMBO_RCV_DESCRIPTORS;
+	adapter->max_lro_rx_desc_count = MAX_LRO_RCV_DESCRIPTORS;
+
+	adapter->max_possible_rss_rings = 1;
+	return;
+}
+
+static int
+netxen_check_hw_init(struct netxen_adapter *adapter, int first_boot)
+{
+	int ret = 0;
+
+	if (first_boot == 0x55555555) {
+		/* This is the first boot after power up */
+
+		/* PCI bus master workaround */
+		adapter->hw_read_wx(adapter,
+			NETXEN_PCIE_REG(0x4), &first_boot, 4);
+		if (!(first_boot & 0x4)) {
+			first_boot |= 0x4;
+			adapter->hw_write_wx(adapter,
+				NETXEN_PCIE_REG(0x4), &first_boot, 4);
+			adapter->hw_read_wx(adapter,
+				NETXEN_PCIE_REG(0x4), &first_boot, 4);
+		}
+
+		/* This is the first boot after power up */
+		adapter->hw_read_wx(adapter,
+			NETXEN_ROMUSB_GLB_SW_RESET, &first_boot, 4);
+		if (first_boot != 0x80000f) {
+			/* clear the register for future unloads/loads */
+			adapter->pci_write_normalize(adapter,
+					NETXEN_CAM_RAM(0x1fc), 0);
+			ret = -1;
+		}
+
+		if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+			/* Start P2 boot loader */
+			adapter->pci_write_normalize(adapter,
+				NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC);
+			adapter->pci_write_normalize(adapter,
+					NETXEN_ROMUSB_GLB_PEGTUNE_DONE, 1);
+		}
+	}
+	return ret;
+}
+
+static void netxen_set_port_mode(struct netxen_adapter *adapter)
+{
+	u32 val, data;
+
+	val = adapter->ahw.boardcfg.board_type;
+	if ((val == NETXEN_BRDTYPE_P3_HMEZ) ||
+		(val == NETXEN_BRDTYPE_P3_XG_LOM)) {
+		if (port_mode == NETXEN_PORT_MODE_802_3_AP) {
+			data = NETXEN_PORT_MODE_802_3_AP;
+			adapter->hw_write_wx(adapter,
+				NETXEN_PORT_MODE_ADDR, &data, 4);
+		} else if (port_mode == NETXEN_PORT_MODE_XG) {
+			data = NETXEN_PORT_MODE_XG;
+			adapter->hw_write_wx(adapter,
+				NETXEN_PORT_MODE_ADDR, &data, 4);
+		} else if (port_mode == NETXEN_PORT_MODE_AUTO_NEG_1G) {
+			data = NETXEN_PORT_MODE_AUTO_NEG_1G;
+			adapter->hw_write_wx(adapter,
+				NETXEN_PORT_MODE_ADDR, &data, 4);
+		} else if (port_mode == NETXEN_PORT_MODE_AUTO_NEG_XG) {
+			data = NETXEN_PORT_MODE_AUTO_NEG_XG;
+			adapter->hw_write_wx(adapter,
+				NETXEN_PORT_MODE_ADDR, &data, 4);
+		} else {
+			data = NETXEN_PORT_MODE_AUTO_NEG;
+			adapter->hw_write_wx(adapter,
+				NETXEN_PORT_MODE_ADDR, &data, 4);
+		}
+
+		if ((wol_port_mode != NETXEN_PORT_MODE_802_3_AP) &&
+			(wol_port_mode != NETXEN_PORT_MODE_XG) &&
+			(wol_port_mode != NETXEN_PORT_MODE_AUTO_NEG_1G) &&
+			(wol_port_mode != NETXEN_PORT_MODE_AUTO_NEG_XG)) {
+			wol_port_mode = NETXEN_PORT_MODE_AUTO_NEG;
+		}
+		adapter->hw_write_wx(adapter, NETXEN_WOL_PORT_MODE,
+			&wol_port_mode, 4);
+	}
+}
+
+#define PCI_CAP_ID_GEN  0x10
+
+static void netxen_pcie_strap_init(struct netxen_adapter *adapter)
+{
+	u32 pdevfuncsave;
+	u32 c8c9value = 0;
+	u32 chicken = 0;
+	u32 control = 0;
+	int i, pos;
+	struct pci_dev *pdev;
+
+	pdev = pci_get_device(0x1166, 0x0140, NULL);
+	if (pdev) {
+		pci_dev_put(pdev);
+		adapter->hw_read_wx(adapter,
+			NETXEN_PCIE_REG(PCIE_TGT_SPLIT_CHICKEN), &chicken, 4);
+		chicken |= 0x4000;
+		adapter->hw_write_wx(adapter,
+			NETXEN_PCIE_REG(PCIE_TGT_SPLIT_CHICKEN), &chicken, 4);
+	}
+
+	pdev = adapter->pdev;
+
+	adapter->hw_read_wx(adapter,
+		NETXEN_PCIE_REG(PCIE_CHICKEN3), &chicken, 4);
+	/* clear chicken3.25:24 */
+	chicken &= 0xFCFFFFFF;
+	/*
+	 * if gen1 and B0, set F1020 - if gen 2, do nothing
+	 * if gen2 set to F1000
+	 */
+	pos = pci_find_capability(pdev, PCI_CAP_ID_GEN);
+	if (pos == 0xC0) {
+		pci_read_config_dword(pdev, pos + 0x10, &control);
+		if ((control & 0x000F0000) != 0x00020000) {
+			/*  set chicken3.24 if gen1 */
+			chicken |= 0x01000000;
+		}
+		printk(KERN_INFO "%s Gen2 strapping detected\n",
+				netxen_nic_driver_name);
+		c8c9value = 0xF1000;
+	} else {
+		/* set chicken3.24 if gen1 */
+		chicken |= 0x01000000;
+		printk(KERN_INFO "%s Gen1 strapping detected\n",
+				netxen_nic_driver_name);
+		if (adapter->ahw.revision_id == NX_P3_B0)
+			c8c9value = 0xF1020;
+		else
+			c8c9value = 0;
+
+	}
+	adapter->hw_write_wx(adapter,
+		NETXEN_PCIE_REG(PCIE_CHICKEN3), &chicken, 4);
+
+	if (!c8c9value)
+		return;
+
+	pdevfuncsave = pdev->devfn;
+	if (pdevfuncsave & 0x07)
+		return;
+
+	for (i = 0; i < 8; i++) {
+		pci_read_config_dword(pdev, pos + 8, &control);
+		pci_read_config_dword(pdev, pos + 8, &control);
+		pci_write_config_dword(pdev, pos + 8, c8c9value);
+		pdev->devfn++;
+	}
+	pdev->devfn = pdevfuncsave;
+}
+
+static void netxen_set_msix_bit(struct pci_dev *pdev, int enable)
+{
+	u32 control;
+	int pos;
+
+	pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
+	if (pos) {
+		pci_read_config_dword(pdev, pos, &control);
+		if (enable)
+			control |= PCI_MSIX_FLAGS_ENABLE;
+		else
+			control = 0;
+		pci_write_config_dword(pdev, pos, control);
+	}
+}
+
+static void netxen_init_msix_entries(struct netxen_adapter *adapter)
+{
+	int i;
+
+	for (i = 0; i < MSIX_ENTRIES_PER_ADAPTER; i++)
+		adapter->msix_entries[i].entry = i;
+}
+
 /*
  * netxen_nic_probe()
  *
@@ -278,28 +524,28 @@
 
 
 	u8 __iomem *db_ptr = NULL;
-	unsigned long mem_base, mem_len, db_base, db_len;
-	int pci_using_dac, i = 0, err;
-	int ring;
-	struct netxen_recv_context *recv_ctx = NULL;
-	struct netxen_rcv_desc_ctx *rcv_desc = NULL;
-	struct netxen_cmd_buffer *cmd_buf_arr = NULL;
+	unsigned long mem_base, mem_len, db_base, db_len, pci_len0 = 0;
+	int i = 0, err;
+	int first_driver, first_boot;
 	__le64 mac_addr[FLASH_NUM_PORTS + 1];
-	int valid_mac = 0;
 	u32 val;
 	int pci_func_id = PCI_FUNC(pdev->devfn);
 	DECLARE_MAC_BUF(mac);
+	struct netxen_legacy_intr_set *legacy_intrp;
+	uint8_t revision_id;
 
 	if (pci_func_id == 0)
-		printk(KERN_INFO "%s \n", netxen_nic_driver_string);
+		printk(KERN_INFO "%s\n", netxen_nic_driver_string);
 
 	if (pdev->class != 0x020000) {
 		printk(KERN_DEBUG "NetXen function %d, class %x will not "
 				"be enabled.\n",pci_func_id, pdev->class);
 		return -ENODEV;
 	}
+
 	if ((err = pci_enable_device(pdev)))
 		return err;
+
 	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
 		err = -ENODEV;
 		goto err_out_disable_pdev;
@@ -309,18 +555,6 @@
 		goto err_out_disable_pdev;
 
 	pci_set_master(pdev);
-	if (pdev->revision == NX_P2_C1 &&
-	    (pci_set_dma_mask(pdev, DMA_35BIT_MASK) == 0) &&
-	    (pci_set_consistent_dma_mask(pdev, DMA_35BIT_MASK) == 0)) {
-		pci_using_dac = 1;
-	} else {
-		if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) ||
-		    (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)))
-			goto err_out_free_res;
-
-		pci_using_dac = 0;
-	}
-
 
 	netdev = alloc_etherdev(sizeof(struct netxen_adapter));
 	if(!netdev) {
@@ -333,13 +567,35 @@
 	SET_NETDEV_DEV(netdev, &pdev->dev);
 
 	adapter = netdev->priv;
-
-	adapter->ahw.pdev = pdev;
+	adapter->netdev  = netdev;
+	adapter->pdev    = pdev;
 	adapter->ahw.pci_func  = pci_func_id;
 
+	revision_id = pdev->revision;
+	adapter->ahw.revision_id = revision_id;
+
+	err = nx_set_dma_mask(adapter, revision_id);
+	if (err)
+		goto err_out_free_netdev;
+
+	rwlock_init(&adapter->adapter_lock);
+	adapter->ahw.qdr_sn_window = -1;
+	adapter->ahw.ddr_mn_window = -1;
+
 	/* remap phys address */
 	mem_base = pci_resource_start(pdev, 0);	/* 0 is for BAR 0 */
 	mem_len = pci_resource_len(pdev, 0);
+	pci_len0 = 0;
+
+	adapter->hw_write_wx = netxen_nic_hw_write_wx_128M;
+	adapter->hw_read_wx = netxen_nic_hw_read_wx_128M;
+	adapter->pci_read_immediate = netxen_nic_pci_read_immediate_128M;
+	adapter->pci_write_immediate = netxen_nic_pci_write_immediate_128M;
+	adapter->pci_read_normalize = netxen_nic_pci_read_normalize_128M;
+	adapter->pci_write_normalize = netxen_nic_pci_write_normalize_128M;
+	adapter->pci_set_window = netxen_nic_pci_set_window_128M;
+	adapter->pci_mem_read = netxen_nic_pci_mem_read_128M;
+	adapter->pci_mem_write = netxen_nic_pci_mem_write_128M;
 
 	/* 128 Meg of memory */
 	if (mem_len == NETXEN_PCI_128MB_SIZE) {
@@ -356,27 +612,48 @@
 			SECOND_PAGE_GROUP_START, THIRD_PAGE_GROUP_SIZE);
 		first_page_group_start = 0;
 		first_page_group_end   = 0;
+	} else if (mem_len == NETXEN_PCI_2MB_SIZE) {
+		adapter->hw_write_wx = netxen_nic_hw_write_wx_2M;
+		adapter->hw_read_wx = netxen_nic_hw_read_wx_2M;
+		adapter->pci_read_immediate = netxen_nic_pci_read_immediate_2M;
+		adapter->pci_write_immediate =
+			netxen_nic_pci_write_immediate_2M;
+		adapter->pci_read_normalize = netxen_nic_pci_read_normalize_2M;
+		adapter->pci_write_normalize =
+			netxen_nic_pci_write_normalize_2M;
+		adapter->pci_set_window = netxen_nic_pci_set_window_2M;
+		adapter->pci_mem_read = netxen_nic_pci_mem_read_2M;
+		adapter->pci_mem_write = netxen_nic_pci_mem_write_2M;
+
+		mem_ptr0 = ioremap(mem_base, mem_len);
+		pci_len0 = mem_len;
+		first_page_group_start = 0;
+		first_page_group_end   = 0;
+
+		adapter->ahw.ddr_mn_window = 0;
+		adapter->ahw.qdr_sn_window = 0;
+
+		adapter->ahw.mn_win_crb = 0x100000 + PCIX_MN_WINDOW +
+			(pci_func_id * 0x20);
+		adapter->ahw.ms_win_crb = 0x100000 + PCIX_SN_WINDOW;
+		if (pci_func_id < 4)
+			adapter->ahw.ms_win_crb += (pci_func_id * 0x20);
+		else
+			adapter->ahw.ms_win_crb +=
+					0xA0 + ((pci_func_id - 4) * 0x10);
 	} else {
 		err = -EIO;
 		goto err_out_free_netdev;
 	}
 
-	if ((!mem_ptr0 && mem_len == NETXEN_PCI_128MB_SIZE) ||
-			!mem_ptr1 || !mem_ptr2) {
-		DPRINTK(ERR,
-			"Cannot remap adapter memory aborting.:"
-			"0 -> %p, 1 -> %p, 2 -> %p\n",
-			mem_ptr0, mem_ptr1, mem_ptr2);
+	dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20));
 
-		err = -EIO;
-		goto err_out_iounmap;
-	}
 	db_base = pci_resource_start(pdev, 4);	/* doorbell is on bar 4 */
 	db_len = pci_resource_len(pdev, 4);
 
 	if (db_len == 0) {
 		printk(KERN_ERR "%s: doorbell is disabled\n",
-		       netxen_nic_driver_name);
+				netxen_nic_driver_name);
 		err = -EIO;
 		goto err_out_iounmap;
 	}
@@ -386,13 +663,14 @@
 	db_ptr = ioremap(db_base, NETXEN_DB_MAPSIZE_BYTES);
 	if (!db_ptr) {
 		printk(KERN_ERR "%s: Failed to allocate doorbell map.",
-		       netxen_nic_driver_name);
+				netxen_nic_driver_name);
 		err = -EIO;
 		goto err_out_iounmap;
 	}
 	DPRINTK(INFO, "doorbell ioremaped at %p\n", db_ptr);
 
 	adapter->ahw.pci_base0 = mem_ptr0;
+	adapter->ahw.pci_len0 = pci_len0;
 	adapter->ahw.first_page_group_start = first_page_group_start;
 	adapter->ahw.first_page_group_end   = first_page_group_end;
 	adapter->ahw.pci_base1 = mem_ptr1;
@@ -400,11 +678,18 @@
 	adapter->ahw.db_base = db_ptr;
 	adapter->ahw.db_len = db_len;
 
-	adapter->netdev  = netdev;
-	adapter->pdev    = pdev;
-
 	netif_napi_add(netdev, &adapter->napi,
-		       netxen_nic_poll, NETXEN_NETDEV_WEIGHT);
+			netxen_nic_poll, NETXEN_NETDEV_WEIGHT);
+
+	if (revision_id >= NX_P3_B0)
+		legacy_intrp = &legacy_intr[pci_func_id];
+	else
+		legacy_intrp = &legacy_intr[0];
+
+	adapter->legacy_intr.int_vec_bit = legacy_intrp->int_vec_bit;
+	adapter->legacy_intr.tgt_status_reg = legacy_intrp->tgt_status_reg;
+	adapter->legacy_intr.tgt_mask_reg = legacy_intrp->tgt_mask_reg;
+	adapter->legacy_intr.pci_int_reg = legacy_intrp->pci_int_reg;
 
 	/* this will be read from FW later */
 	adapter->intr_scheme = -1;
@@ -414,12 +699,23 @@
 	adapter->portnum = pci_func_id;
 	adapter->status   &= ~NETXEN_NETDEV_STATUS;
 	adapter->rx_csum = 1;
+	adapter->mc_enabled = 0;
+	if (NX_IS_REVISION_P3(revision_id)) {
+		adapter->max_mc_count = 38;
+		adapter->max_rds_rings = 2;
+	} else {
+		adapter->max_mc_count = 16;
+		adapter->max_rds_rings = 3;
+	}
 
 	netdev->open		   = netxen_nic_open;
 	netdev->stop		   = netxen_nic_close;
 	netdev->hard_start_xmit    = netxen_nic_xmit_frame;
 	netdev->get_stats	   = netxen_nic_get_stats;
-	netdev->set_multicast_list = netxen_nic_set_multi;
+	if (NX_IS_REVISION_P3(revision_id))
+		netdev->set_multicast_list = netxen_p3_nic_set_multi;
+	else
+		netdev->set_multicast_list = netxen_p2_nic_set_multi;
 	netdev->set_mac_address    = netxen_nic_set_mac;
 	netdev->change_mtu	   = netxen_nic_change_mtu;
 	netdev->tx_timeout	   = netxen_tx_timeout;
@@ -435,18 +731,14 @@
 	netdev->features = NETIF_F_SG;
 	netdev->features |= NETIF_F_IP_CSUM;
 	netdev->features |= NETIF_F_TSO;
+	if (NX_IS_REVISION_P3(revision_id)) {
+		netdev->features |= NETIF_F_IPV6_CSUM;
+		netdev->features |= NETIF_F_TSO6;
+	}
 
-	if (pci_using_dac)
+	if (adapter->pci_using_dac)
 		netdev->features |= NETIF_F_HIGHDMA;
 
-	if (pci_enable_msi(pdev))
-		adapter->flags &= ~NETXEN_NIC_MSI_ENABLED;
-	else
-		adapter->flags |= NETXEN_NIC_MSI_ENABLED;
-
-	netdev->irq = pdev->irq;
-	INIT_WORK(&adapter->tx_timeout_task, netxen_tx_timeout_task);
-
 	/*
 	 * Set the CRB window to invalid. If any register in window 0 is
 	 * accessed it should set the window to 0 and then reset it to 1.
@@ -455,87 +747,13 @@
 
 	if (netxen_nic_get_board_info(adapter) != 0) {
 		printk("%s: Error getting board config info.\n",
-		       netxen_nic_driver_name);
+				netxen_nic_driver_name);
 		err = -EIO;
 		goto err_out_iounmap;
 	}
 
-	/*
-	 *  Adapter in our case is quad port so initialize it before
-	 *  initializing the ports
-	 */
-
 	netxen_initialize_adapter_ops(adapter);
 
-	adapter->max_tx_desc_count = MAX_CMD_DESCRIPTORS_HOST;
-	if ((adapter->ahw.boardcfg.board_type == NETXEN_BRDTYPE_P2_SB35_4G) ||
-			(adapter->ahw.boardcfg.board_type ==
-			 NETXEN_BRDTYPE_P2_SB31_2G))
-		adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
-	else
-		adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS;
-	adapter->max_jumbo_rx_desc_count = MAX_JUMBO_RCV_DESCRIPTORS;
-	adapter->max_lro_rx_desc_count = MAX_LRO_RCV_DESCRIPTORS;
-
-	cmd_buf_arr = (struct netxen_cmd_buffer *)vmalloc(TX_RINGSIZE);
-	if (cmd_buf_arr == NULL) {
-		printk(KERN_ERR
-		       "%s: Could not allocate cmd_buf_arr memory:%d\n",
-		       netxen_nic_driver_name, (int)TX_RINGSIZE);
-		err = -ENOMEM;
-		goto err_out_free_adapter;
-	}
-	memset(cmd_buf_arr, 0, TX_RINGSIZE);
-	adapter->cmd_buf_arr = cmd_buf_arr;
-
-	for (i = 0; i < MAX_RCV_CTX; ++i) {
-		recv_ctx = &adapter->recv_ctx[i];
-		for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
-			rcv_desc = &recv_ctx->rcv_desc[ring];
-			switch (RCV_DESC_TYPE(ring)) {
-			case RCV_DESC_NORMAL:
-				rcv_desc->max_rx_desc_count =
-				    adapter->max_rx_desc_count;
-				rcv_desc->flags = RCV_DESC_NORMAL;
-				rcv_desc->dma_size = RX_DMA_MAP_LEN;
-				rcv_desc->skb_size = MAX_RX_BUFFER_LENGTH;
-				break;
-
-			case RCV_DESC_JUMBO:
-				rcv_desc->max_rx_desc_count =
-				    adapter->max_jumbo_rx_desc_count;
-				rcv_desc->flags = RCV_DESC_JUMBO;
-				rcv_desc->dma_size = RX_JUMBO_DMA_MAP_LEN;
-				rcv_desc->skb_size = MAX_RX_JUMBO_BUFFER_LENGTH;
-				break;
-
-			case RCV_RING_LRO:
-				rcv_desc->max_rx_desc_count =
-				    adapter->max_lro_rx_desc_count;
-				rcv_desc->flags = RCV_DESC_LRO;
-				rcv_desc->dma_size = RX_LRO_DMA_MAP_LEN;
-				rcv_desc->skb_size = MAX_RX_LRO_BUFFER_LENGTH;
-				break;
-
-			}
-			rcv_desc->rx_buf_arr = (struct netxen_rx_buffer *)
-			    vmalloc(RCV_BUFFSIZE);
-
-			if (rcv_desc->rx_buf_arr == NULL) {
-				printk(KERN_ERR "%s: Could not allocate "
-				       "rcv_desc->rx_buf_arr memory:%d\n",
-				       netxen_nic_driver_name,
-				       (int)RCV_BUFFSIZE);
-				err = -ENOMEM;
-				goto err_out_free_rx_buffer;
-			}
-			memset(rcv_desc->rx_buf_arr, 0, RCV_BUFFSIZE);
-		}
-
-	}
-
-	netxen_initialize_adapter_sw(adapter);	/* initialize the buffers in adapter */
-
 	/* Mezz cards have PCI function 0,2,3 enabled */
 	switch (adapter->ahw.boardcfg.board_type) {
 	case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
@@ -547,29 +765,155 @@
 		break;
 	}
 
+	/*
+	 * This call will setup various max rx/tx counts.
+	 * It must be done before any buffer/ring allocations.
+	 */
+	netxen_check_options(adapter);
+
+	first_driver = 0;
+	if (NX_IS_REVISION_P3(revision_id)) {
+		if (adapter->ahw.pci_func == 0)
+			first_driver = 1;
+	} else {
+		if (adapter->portnum == 0)
+			first_driver = 1;
+	}
+	adapter->crb_addr_cmd_producer = crb_cmd_producer[adapter->portnum];
+	adapter->crb_addr_cmd_consumer = crb_cmd_consumer[adapter->portnum];
+	netxen_nic_update_cmd_producer(adapter, 0);
+	netxen_nic_update_cmd_consumer(adapter, 0);
+
+	if (first_driver) {
+		first_boot = adapter->pci_read_normalize(adapter,
+				NETXEN_CAM_RAM(0x1fc));
+
+		err = netxen_check_hw_init(adapter, first_boot);
+		if (err) {
+			printk(KERN_ERR "%s: error in init HW init sequence\n",
+					netxen_nic_driver_name);
+			goto err_out_iounmap;
+		}
+
+		if (NX_IS_REVISION_P3(revision_id))
+			netxen_set_port_mode(adapter);
+
+		if (first_boot != 0x55555555) {
+			adapter->pci_write_normalize(adapter,
+						CRB_CMDPEG_STATE, 0);
+			netxen_pinit_from_rom(adapter, 0);
+			msleep(1);
+			netxen_load_firmware(adapter);
+		}
+
+		if (NX_IS_REVISION_P3(revision_id))
+			netxen_pcie_strap_init(adapter);
+
+		if (NX_IS_REVISION_P2(revision_id)) {
+
+			/* Initialize multicast addr pool owners */
+			val = 0x7654;
+			if (adapter->ahw.board_type == NETXEN_NIC_XGBE)
+				val |= 0x0f000000;
+			netxen_crb_writelit_adapter(adapter,
+					NETXEN_MAC_ADDR_CNTL_REG, val);
+
+		}
+
+		if ((first_boot == 0x55555555) &&
+			(NX_IS_REVISION_P2(revision_id))) {
+			/* Unlock the HW, prompting the boot sequence */
+			adapter->pci_write_normalize(adapter,
+					NETXEN_ROMUSB_GLB_PEGTUNE_DONE, 1);
+		}
+
+		err = netxen_initialize_adapter_offload(adapter);
+		if (err)
+			goto err_out_iounmap;
+
+		/*
+		 * Tell the hardware our version number.
+		 */
+		i = (_NETXEN_NIC_LINUX_MAJOR << 16)
+			| ((_NETXEN_NIC_LINUX_MINOR << 8))
+			| (_NETXEN_NIC_LINUX_SUBVERSION);
+		adapter->pci_write_normalize(adapter, CRB_DRIVER_VERSION, i);
+
+		/* Handshake with the card before we register the devices. */
+		netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
+
+	}	/* first_driver */
+
+	netxen_nic_flash_print(adapter);
+
+	if (NX_IS_REVISION_P3(revision_id)) {
+		adapter->hw_read_wx(adapter,
+				NETXEN_MIU_MN_CONTROL, &val, 4);
+		adapter->ahw.cut_through = (val & 0x4) ? 1 : 0;
+		dev_info(&pdev->dev, "firmware running in %s mode\n",
+		adapter->ahw.cut_through ? "cut through" : "legacy");
+	}
+
+	/*
+	 * See if the firmware gave us a virtual-physical port mapping.
+	 */
+	adapter->physical_port = adapter->portnum;
+	i = adapter->pci_read_normalize(adapter, CRB_V2P(adapter->portnum));
+	if (i != 0x55555555)
+		adapter->physical_port = i;
+
+	adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED);
+
+	netxen_set_msix_bit(pdev, 0);
+
+	if (NX_IS_REVISION_P3(revision_id)) {
+		if ((mem_len != NETXEN_PCI_128MB_SIZE) &&
+			mem_len != NETXEN_PCI_2MB_SIZE)
+			adapter->msix_supported = 0;
+	}
+
+	if (adapter->msix_supported) {
+
+		netxen_init_msix_entries(adapter);
+
+		if (pci_enable_msix(pdev, adapter->msix_entries,
+					MSIX_ENTRIES_PER_ADAPTER))
+			goto request_msi;
+
+		adapter->flags |= NETXEN_NIC_MSIX_ENABLED;
+		netxen_set_msix_bit(pdev, 1);
+		dev_info(&pdev->dev, "using msi-x interrupts\n");
+
+	} else {
+request_msi:
+		if (use_msi && !pci_enable_msi(pdev)) {
+			adapter->flags |= NETXEN_NIC_MSI_ENABLED;
+			dev_info(&pdev->dev, "using msi interrupts\n");
+		} else
+			dev_info(&pdev->dev, "using legacy interrupts\n");
+	}
+
+	if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
+		netdev->irq = adapter->msix_entries[0].vector;
+	else
+		netdev->irq = pdev->irq;
+
+	err = netxen_receive_peg_ready(adapter);
+	if (err)
+		goto err_out_disable_msi;
+
 	init_timer(&adapter->watchdog_timer);
-	adapter->ahw.xg_linkup = 0;
+	adapter->ahw.linkup = 0;
 	adapter->watchdog_timer.function = &netxen_watchdog;
 	adapter->watchdog_timer.data = (unsigned long)adapter;
 	INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task);
-	adapter->ahw.pdev = pdev;
-	adapter->ahw.revision_id = pdev->revision;
-
-	/* make sure Window == 1 */
-	netxen_nic_pci_change_crbwindow(adapter, 1);
-
-	netxen_nic_update_cmd_producer(adapter, 0);
-	netxen_nic_update_cmd_consumer(adapter, 0);
-	writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_LO));
+	INIT_WORK(&adapter->tx_timeout_task, netxen_tx_timeout_task);
 
 	if (netxen_is_flash_supported(adapter) == 0 &&
-	    netxen_get_flash_mac_addr(adapter, mac_addr) == 0)
-		valid_mac = 1;
-	else
-		valid_mac = 0;
+			netxen_get_flash_mac_addr(adapter, mac_addr) == 0) {
+		unsigned char *p;
 
-	if (valid_mac) {
-		unsigned char *p = (unsigned char *)&mac_addr[adapter->portnum];
+		p = (unsigned char *)&mac_addr[adapter->portnum];
 		netdev->dev_addr[0] = *(p + 5);
 		netdev->dev_addr[1] = *(p + 4);
 		netdev->dev_addr[2] = *(p + 3);
@@ -581,81 +925,13 @@
 			netdev->addr_len);
 		if (!is_valid_ether_addr(netdev->perm_addr)) {
 			printk(KERN_ERR "%s: Bad MAC address %s.\n",
-			       netxen_nic_driver_name,
-			       print_mac(mac, netdev->dev_addr));
+					netxen_nic_driver_name,
+					print_mac(mac, netdev->dev_addr));
 		} else {
-			if (adapter->macaddr_set)
-				adapter->macaddr_set(adapter,
-							netdev->dev_addr);
+			adapter->macaddr_set(adapter, netdev->dev_addr);
 		}
 	}
 
-	if (adapter->portnum == 0) {
-		err = netxen_initialize_adapter_offload(adapter);
-		if (err)
-			goto err_out_free_rx_buffer;
-		val = readl(NETXEN_CRB_NORMALIZE(adapter,
-					NETXEN_CAM_RAM(0x1fc)));
-		if (val == 0x55555555) {
-		    /* This is the first boot after power up */
-		    netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(0x4), &val);
-			if (!(val & 0x4)) {
-				val |= 0x4;
-				netxen_nic_write_w0(adapter, NETXEN_PCIE_REG(0x4), val);
-				netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(0x4), &val);
-				if (!(val & 0x4))
-					printk(KERN_ERR "%s: failed to set MSI bit in PCI-e reg\n",
-							netxen_nic_driver_name);
-			}
-		    val = readl(NETXEN_CRB_NORMALIZE(adapter,
-					NETXEN_ROMUSB_GLB_SW_RESET));
-		    printk(KERN_INFO"NetXen: read 0x%08x for reset reg.\n",val);
-		    if (val != 0x80000f) {
-			/* clear the register for future unloads/loads */
-				writel(0, NETXEN_CRB_NORMALIZE(adapter,
-							NETXEN_CAM_RAM(0x1fc)));
-				printk(KERN_ERR "ERROR in NetXen HW init sequence.\n");
-				err = -ENODEV;
-				goto err_out_free_dev;
-		    }
-		} else {
-			writel(0, NETXEN_CRB_NORMALIZE(adapter,
-						CRB_CMDPEG_STATE));
-			netxen_pinit_from_rom(adapter, 0);
-			msleep(1);
-			netxen_load_firmware(adapter);
-			netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
-		}
-
-		/* clear the register for future unloads/loads */
-		writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_CAM_RAM(0x1fc)));
-		dev_info(&pdev->dev, "cmdpeg state: 0x%0x\n",
-			readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)));
-
-		/*
-		 * Tell the hardware our version number.
-		 */
-		i = (_NETXEN_NIC_LINUX_MAJOR << 16)
-			| ((_NETXEN_NIC_LINUX_MINOR << 8))
-			| (_NETXEN_NIC_LINUX_SUBVERSION);
-		writel(i, NETXEN_CRB_NORMALIZE(adapter, CRB_DRIVER_VERSION));
-
-		/* Unlock the HW, prompting the boot sequence */
-		writel(1,
-			NETXEN_CRB_NORMALIZE(adapter,
-				NETXEN_ROMUSB_GLB_PEGTUNE_DONE));
-		/* Handshake with the card before we register the devices. */
-		netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
-	}
-
-	/*
-	 * See if the firmware gave us a virtual-physical port mapping.
-	 */
-	adapter->physical_port = adapter->portnum;
-	i = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_V2P(adapter->portnum)));
-	if (i != 0x55555555)
-		adapter->physical_port = i;
-
 	netif_carrier_off(netdev);
 	netif_stop_queue(netdev);
 
@@ -664,41 +940,37 @@
 			       " aborting\n", netxen_nic_driver_name,
 			       adapter->portnum);
 		err = -EIO;
-		goto err_out_free_dev;
+		goto err_out_disable_msi;
 	}
 
-	netxen_nic_flash_print(adapter);
 	pci_set_drvdata(pdev, adapter);
 
+	switch (adapter->ahw.board_type) {
+	case NETXEN_NIC_GBE:
+		dev_info(&adapter->pdev->dev, "%s: GbE port initialized\n",
+				adapter->netdev->name);
+		break;
+	case NETXEN_NIC_XGBE:
+		dev_info(&adapter->pdev->dev, "%s: XGbE port initialized\n",
+				adapter->netdev->name);
+		break;
+	}
+
 	return 0;
 
-err_out_free_dev:
-	if (adapter->portnum == 0)
-		netxen_free_adapter_offload(adapter);
-
-err_out_free_rx_buffer:
-	for (i = 0; i < MAX_RCV_CTX; ++i) {
-		recv_ctx = &adapter->recv_ctx[i];
-		for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
-			rcv_desc = &recv_ctx->rcv_desc[ring];
-			if (rcv_desc->rx_buf_arr != NULL) {
-				vfree(rcv_desc->rx_buf_arr);
-				rcv_desc->rx_buf_arr = NULL;
-			}
-		}
-	}
-	vfree(cmd_buf_arr);
-
-err_out_free_adapter:
+err_out_disable_msi:
+	if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
+		pci_disable_msix(pdev);
 	if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
 		pci_disable_msi(pdev);
 
-	pci_set_drvdata(pdev, NULL);
+	if (first_driver)
+		netxen_free_adapter_offload(adapter);
 
+err_out_iounmap:
 	if (db_ptr)
 		iounmap(db_ptr);
 
-err_out_iounmap:
 	if (mem_ptr0)
 		iounmap(mem_ptr0);
 	if (mem_ptr1)
@@ -713,6 +985,7 @@
 	pci_release_regions(pdev);
 
 err_out_disable_pdev:
+	pci_set_drvdata(pdev, NULL);
 	pci_disable_device(pdev);
 	return err;
 }
@@ -721,11 +994,6 @@
 {
 	struct netxen_adapter *adapter;
 	struct net_device *netdev;
-	struct netxen_rx_buffer *buffer;
-	struct netxen_recv_context *recv_ctx;
-	struct netxen_rcv_desc_ctx *rcv_desc;
-	int i, ctxid, ring;
-	static int init_firmware_done = 0;
 
 	adapter = pci_get_drvdata(pdev);
 	if (adapter == NULL)
@@ -736,36 +1004,18 @@
 	unregister_netdev(netdev);
 
 	if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
-		init_firmware_done++;
 		netxen_free_hw_resources(adapter);
+		netxen_free_sw_resources(adapter);
 	}
 
-	for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) {
-		recv_ctx = &adapter->recv_ctx[ctxid];
-		for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
-			rcv_desc = &recv_ctx->rcv_desc[ring];
-			for (i = 0; i < rcv_desc->max_rx_desc_count; ++i) {
-				buffer = &(rcv_desc->rx_buf_arr[i]);
-				if (buffer->state == NETXEN_BUFFER_FREE)
-					continue;
-				pci_unmap_single(pdev, buffer->dma,
-						 rcv_desc->dma_size,
-						 PCI_DMA_FROMDEVICE);
-				if (buffer->skb != NULL)
-					dev_kfree_skb_any(buffer->skb);
-			}
-			vfree(rcv_desc->rx_buf_arr);
-		}
-	}
-
-	vfree(adapter->cmd_buf_arr);
-
 	if (adapter->portnum == 0)
 		netxen_free_adapter_offload(adapter);
 
 	if (adapter->irq)
 		free_irq(adapter->irq, adapter);
 
+	if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
+		pci_disable_msix(pdev);
 	if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
 		pci_disable_msi(pdev);
 
@@ -803,51 +1053,69 @@
 			return -EIO;
 		}
 
-		/* setup all the resources for the Phantom... */
-		/* this include the descriptors for rcv, tx, and status */
-		netxen_nic_clear_stats(adapter);
-		err = netxen_nic_hw_resources(adapter);
+		err = netxen_alloc_sw_resources(adapter);
 		if (err) {
-			printk(KERN_ERR "Error in setting hw resources:%d\n",
-			       err);
+			printk(KERN_ERR "%s: Error in setting sw resources\n",
+					netdev->name);
 			return err;
 		}
+
+		netxen_nic_clear_stats(adapter);
+
+		err = netxen_alloc_hw_resources(adapter);
+		if (err) {
+			printk(KERN_ERR "%s: Error in setting hw resources\n",
+					netdev->name);
+			goto err_out_free_sw;
+		}
+
+		if (adapter->fw_major < 4) {
+			adapter->crb_addr_cmd_producer =
+				crb_cmd_producer[adapter->portnum];
+			adapter->crb_addr_cmd_consumer =
+				crb_cmd_consumer[adapter->portnum];
+		}
+
+		netxen_nic_update_cmd_producer(adapter, 0);
+		netxen_nic_update_cmd_consumer(adapter, 0);
+
 		for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
-			for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++)
+			for (ring = 0; ring < adapter->max_rds_rings; ring++)
 				netxen_post_rx_buffers(adapter, ctx, ring);
 		}
-		adapter->irq = adapter->ahw.pdev->irq;
-		if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
+		if (NETXEN_IS_MSI_FAMILY(adapter))
 			handler = netxen_msi_intr;
 		else {
 			flags |= IRQF_SHARED;
 			handler = netxen_intr;
 		}
+		adapter->irq = netdev->irq;
 		err = request_irq(adapter->irq, handler,
 				  flags, netdev->name, adapter);
 		if (err) {
 			printk(KERN_ERR "request_irq failed with: %d\n", err);
-			netxen_free_hw_resources(adapter);
-			return err;
+			goto err_out_free_hw;
 		}
 
 		adapter->is_up = NETXEN_ADAPTER_UP_MAGIC;
 	}
+
 	/* Done here again so that even if phantom sw overwrote it,
 	 * we set it */
-	if (adapter->init_port
-	    && adapter->init_port(adapter, adapter->portnum) != 0) {
+	err = adapter->init_port(adapter, adapter->physical_port);
+	if (err) {
 		printk(KERN_ERR "%s: Failed to initialize port %d\n",
 				netxen_nic_driver_name, adapter->portnum);
-		return -EIO;
+		goto err_out_free_irq;
 	}
-	if (adapter->macaddr_set)
-		adapter->macaddr_set(adapter, netdev->dev_addr);
+	adapter->macaddr_set(adapter, netdev->dev_addr);
 
 	netxen_nic_set_link_parameters(adapter);
 
-	netxen_nic_set_multi(netdev);
-	if (adapter->set_mtu)
+	netdev->set_multicast_list(netdev);
+	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+		nx_fw_cmd_set_mtu(adapter, netdev->mtu);
+	else
 		adapter->set_mtu(adapter, netdev->mtu);
 
 	mod_timer(&adapter->watchdog_timer, jiffies);
@@ -858,6 +1126,14 @@
 	netif_start_queue(netdev);
 
 	return 0;
+
+err_out_free_irq:
+	free_irq(adapter->irq, adapter);
+err_out_free_hw:
+	netxen_free_hw_resources(adapter);
+err_out_free_sw:
+	netxen_free_sw_resources(adapter);
+	return err;
 }
 
 /*
@@ -866,9 +1142,6 @@
 static int netxen_nic_close(struct net_device *netdev)
 {
 	struct netxen_adapter *adapter = netdev_priv(netdev);
-	int i, j;
-	struct netxen_cmd_buffer *cmd_buff;
-	struct netxen_skb_frag *buffrag;
 
 	netif_carrier_off(netdev);
 	netif_stop_queue(netdev);
@@ -879,30 +1152,8 @@
 
 	netxen_nic_disable_int(adapter);
 
-	cmd_buff = adapter->cmd_buf_arr;
-	for (i = 0; i < adapter->max_tx_desc_count; i++) {
-		buffrag = cmd_buff->frag_array;
-		if (buffrag->dma) {
-			pci_unmap_single(adapter->pdev, buffrag->dma,
-					 buffrag->length, PCI_DMA_TODEVICE);
-			buffrag->dma = 0ULL;
-		}
-		for (j = 0; j < cmd_buff->frag_count; j++) {
-			buffrag++;
-			if (buffrag->dma) {
-				pci_unmap_page(adapter->pdev, buffrag->dma,
-					       buffrag->length,
-					       PCI_DMA_TODEVICE);
-				buffrag->dma = 0ULL;
-			}
-		}
-		/* Free the skb we received in netxen_nic_xmit_frame */
-		if (cmd_buff->skb) {
-			dev_kfree_skb_any(cmd_buff->skb);
-			cmd_buff->skb = NULL;
-		}
-		cmd_buff++;
-	}
+	netxen_release_tx_buffers(adapter);
+
 	if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
 		FLUSH_SCHEDULED_WORK();
 		del_timer_sync(&adapter->watchdog_timer);
@@ -911,6 +1162,31 @@
 	return 0;
 }
 
+void netxen_tso_check(struct netxen_adapter *adapter,
+		      struct cmd_desc_type0 *desc, struct sk_buff *skb)
+{
+	if (desc->mss) {
+		desc->total_hdr_length = (sizeof(struct ethhdr) +
+					  ip_hdrlen(skb) + tcp_hdrlen(skb));
+
+		if ((NX_IS_REVISION_P3(adapter->ahw.revision_id)) &&
+				(skb->protocol == htons(ETH_P_IPV6)))
+			netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO6);
+		else
+			netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO);
+
+	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		if (ip_hdr(skb)->protocol == IPPROTO_TCP)
+			netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT);
+		else if (ip_hdr(skb)->protocol == IPPROTO_UDP)
+			netxen_set_cmd_desc_opcode(desc, TX_UDP_PKT);
+		else
+			return;
+	}
+	desc->tcp_hdr_offset = skb_transport_offset(skb);
+	desc->ip_hdr_offset = skb_network_offset(skb);
+}
+
 static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 {
 	struct netxen_adapter *adapter = netdev_priv(netdev);
@@ -932,7 +1208,7 @@
 
 	/* There 4 fragments per descriptor */
 	no_of_desc = (frag_count + 3) >> 2;
-	if (netdev->features & NETIF_F_TSO) {
+	if (netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) {
 		if (skb_shinfo(skb)->gso_size > 0) {
 
 			no_of_desc++;
@@ -959,7 +1235,8 @@
 	memset(hwdesc, 0, sizeof(struct cmd_desc_type0));
 	/* Take skb->data itself */
 	pbuf = &adapter->cmd_buf_arr[producer];
-	if ((netdev->features & NETIF_F_TSO) && skb_shinfo(skb)->gso_size > 0) {
+	if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
+			skb_shinfo(skb)->gso_size > 0) {
 		pbuf->mss = skb_shinfo(skb)->gso_size;
 		hwdesc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
 	} else {
@@ -1086,6 +1363,89 @@
 	return NETDEV_TX_OK;
 }
 
+static int netxen_nic_check_temp(struct netxen_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	uint32_t temp, temp_state, temp_val;
+	int rv = 0;
+
+	temp = adapter->pci_read_normalize(adapter, CRB_TEMP_STATE);
+
+	temp_state = nx_get_temp_state(temp);
+	temp_val = nx_get_temp_val(temp);
+
+	if (temp_state == NX_TEMP_PANIC) {
+		printk(KERN_ALERT
+		       "%s: Device temperature %d degrees C exceeds"
+		       " maximum allowed. Hardware has been shut down.\n",
+		       netxen_nic_driver_name, temp_val);
+
+		netif_carrier_off(netdev);
+		netif_stop_queue(netdev);
+		rv = 1;
+	} else if (temp_state == NX_TEMP_WARN) {
+		if (adapter->temp == NX_TEMP_NORMAL) {
+			printk(KERN_ALERT
+			       "%s: Device temperature %d degrees C "
+			       "exceeds operating range."
+			       " Immediate action needed.\n",
+			       netxen_nic_driver_name, temp_val);
+		}
+	} else {
+		if (adapter->temp == NX_TEMP_WARN) {
+			printk(KERN_INFO
+			       "%s: Device temperature is now %d degrees C"
+			       " in normal range.\n", netxen_nic_driver_name,
+			       temp_val);
+		}
+	}
+	adapter->temp = temp_state;
+	return rv;
+}
+
+static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	u32 val, port, linkup;
+
+	port = adapter->physical_port;
+
+	if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
+		val = adapter->pci_read_normalize(adapter, CRB_XG_STATE);
+		linkup = (val >> port) & 1;
+	} else {
+		if (adapter->fw_major < 4) {
+			val = adapter->pci_read_normalize(adapter,
+					CRB_XG_STATE);
+			val = (val >> port*8) & 0xff;
+			linkup = (val == XG_LINK_UP);
+		} else {
+			val = adapter->pci_read_normalize(adapter,
+				CRB_XG_STATE_P3);
+			val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val);
+			linkup = (val == XG_LINK_UP_P3);
+		}
+	}
+
+	if (adapter->ahw.linkup && !linkup) {
+		printk(KERN_INFO "%s: %s NIC Link is down\n",
+		       netxen_nic_driver_name, netdev->name);
+		adapter->ahw.linkup = 0;
+		if (netif_running(netdev)) {
+			netif_carrier_off(netdev);
+			netif_stop_queue(netdev);
+		}
+	} else if (!adapter->ahw.linkup && linkup) {
+		printk(KERN_INFO "%s: %s NIC Link is up\n",
+		       netxen_nic_driver_name, netdev->name);
+		adapter->ahw.linkup = 1;
+		if (netif_running(netdev)) {
+			netif_carrier_on(netdev);
+			netif_wake_queue(netdev);
+		}
+	}
+}
+
 static void netxen_watchdog(unsigned long v)
 {
 	struct netxen_adapter *adapter = (struct netxen_adapter *)v;
@@ -1093,6 +1453,19 @@
 	SCHEDULE_WORK(&adapter->watchdog_task);
 }
 
+void netxen_watchdog_task(struct work_struct *work)
+{
+	struct netxen_adapter *adapter =
+		container_of(work, struct netxen_adapter, watchdog_task);
+
+	if ((adapter->portnum  == 0) && netxen_nic_check_temp(adapter))
+		return;
+
+	netxen_nic_handle_phy_intr(adapter);
+
+	mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+}
+
 static void netxen_tx_timeout(struct net_device *netdev)
 {
 	struct netxen_adapter *adapter = (struct netxen_adapter *)
@@ -1118,6 +1491,38 @@
 	netif_wake_queue(adapter->netdev);
 }
 
+/*
+ * netxen_nic_get_stats - Get System Network Statistics
+ * @netdev: network interface device structure
+ */
+struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
+{
+	struct netxen_adapter *adapter = netdev_priv(netdev);
+	struct net_device_stats *stats = &adapter->net_stats;
+
+	memset(stats, 0, sizeof(*stats));
+
+	/* total packets received   */
+	stats->rx_packets = adapter->stats.no_rcv;
+	/* total packets transmitted    */
+	stats->tx_packets = adapter->stats.xmitedframes +
+		adapter->stats.xmitfinished;
+	/* total bytes received     */
+	stats->rx_bytes = adapter->stats.rxbytes;
+	/* total bytes transmitted  */
+	stats->tx_bytes = adapter->stats.txbytes;
+	/* bad packets received     */
+	stats->rx_errors = adapter->stats.rcvdbadskb;
+	/* packet transmit problems */
+	stats->tx_errors = adapter->stats.nocmddescriptor;
+	/* no space in linux buffers    */
+	stats->rx_dropped = adapter->stats.rxdropped;
+	/* no space available in linux  */
+	stats->tx_dropped = adapter->stats.txdropped;
+
+	return stats;
+}
+
 static inline void
 netxen_handle_int(struct netxen_adapter *adapter)
 {
@@ -1125,20 +1530,20 @@
 	napi_schedule(&adapter->napi);
 }
 
-irqreturn_t netxen_intr(int irq, void *data)
+static irqreturn_t netxen_intr(int irq, void *data)
 {
 	struct netxen_adapter *adapter = data;
 	u32 our_int = 0;
 
-	our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
+	our_int = adapter->pci_read_normalize(adapter, CRB_INT_VECTOR);
 	/* not our interrupt */
 	if ((our_int & (0x80 << adapter->portnum)) == 0)
 		return IRQ_NONE;
 
 	if (adapter->intr_scheme == INTR_SCHEME_PERPORT) {
 		/* claim interrupt */
-		writel(our_int & ~((u32)(0x80 << adapter->portnum)),
-			NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
+		adapter->pci_write_normalize(adapter, CRB_INT_VECTOR,
+				our_int & ~((u32)(0x80 << adapter->portnum)));
 	}
 
 	netxen_handle_int(adapter);
@@ -1146,7 +1551,7 @@
 	return IRQ_HANDLED;
 }
 
-irqreturn_t netxen_msi_intr(int irq, void *data)
+static irqreturn_t netxen_msi_intr(int irq, void *data)
 {
 	struct netxen_adapter *adapter = data;
 
@@ -1220,10 +1625,6 @@
 
 static void __exit netxen_exit_module(void)
 {
-	/*
-	 * Wait for some time to allow the dma to drain, if any.
-	 */
-	msleep(100);
 	pci_unregister_driver(&netxen_driver);
 	destroy_workqueue(netxen_workq);
 }
diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c
index a3bc7cc..4cb8f4a 100644
--- a/drivers/net/netxen/netxen_nic_niu.c
+++ b/drivers/net/netxen/netxen_nic_niu.c
@@ -46,9 +46,8 @@
 	int done = 0, timeout = 0;
 
 	while (!done) {
-		done =
-		    readl(pci_base_offset
-			  (adapter, NETXEN_PCIE_REG(PCIE_SEM3_LOCK)));
+		done = netxen_nic_reg_read(adapter,
+				NETXEN_PCIE_REG(PCIE_SEM3_LOCK));
 		if (done == 1)
 			break;
 		if (timeout >= phy_lock_timeout) {
@@ -63,14 +62,14 @@
 		}
 	}
 
-	writel(PHY_LOCK_DRIVER,
-	       NETXEN_CRB_NORMALIZE(adapter, NETXEN_PHY_LOCK_ID));
+	netxen_crb_writelit_adapter(adapter,
+			NETXEN_PHY_LOCK_ID, PHY_LOCK_DRIVER);
 	return 0;
 }
 
 static int phy_unlock(struct netxen_adapter *adapter)
 {
-	readl(pci_base_offset(adapter, NETXEN_PCIE_REG(PCIE_SEM3_UNLOCK)));
+	adapter->pci_read_immediate(adapter, NETXEN_PCIE_REG(PCIE_SEM3_UNLOCK));
 
 	return 0;
 }
@@ -109,7 +108,7 @@
 	 * so it cannot be in reset
 	 */
 
-	if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
+	if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
 				  &mac_cfg0, 4))
 		return -EIO;
 	if (netxen_gb_get_soft_reset(mac_cfg0)) {
@@ -119,7 +118,7 @@
 		netxen_gb_rx_reset_pb(temp);
 		netxen_gb_tx_reset_mac(temp);
 		netxen_gb_rx_reset_mac(temp);
-		if (netxen_nic_hw_write_wx(adapter,
+		if (adapter->hw_write_wx(adapter,
 					   NETXEN_NIU_GB_MAC_CONFIG_0(0),
 					   &temp, 4))
 			return -EIO;
@@ -129,22 +128,22 @@
 	address = 0;
 	netxen_gb_mii_mgmt_reg_addr(address, reg);
 	netxen_gb_mii_mgmt_phy_addr(address, phy);
-	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
+	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
 				   &address, 4))
 		return -EIO;
 	command = 0;		/* turn off any prior activity */
-	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
+	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
 				   &command, 4))
 		return -EIO;
 	/* send read command */
 	netxen_gb_mii_mgmt_set_read_cycle(command);
-	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
+	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
 				   &command, 4))
 		return -EIO;
 
 	status = 0;
 	do {
-		if (netxen_nic_hw_read_wx(adapter,
+		if (adapter->hw_read_wx(adapter,
 					  NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
 					  &status, 4))
 			return -EIO;
@@ -154,7 +153,7 @@
 		 && (timeout++ < NETXEN_NIU_PHY_WAITMAX));
 
 	if (timeout < NETXEN_NIU_PHY_WAITMAX) {
-		if (netxen_nic_hw_read_wx(adapter,
+		if (adapter->hw_read_wx(adapter,
 					  NETXEN_NIU_GB_MII_MGMT_STATUS(0),
 					  readval, 4))
 			return -EIO;
@@ -163,7 +162,7 @@
 		result = -1;
 
 	if (restore)
-		if (netxen_nic_hw_write_wx(adapter,
+		if (adapter->hw_write_wx(adapter,
 					   NETXEN_NIU_GB_MAC_CONFIG_0(0),
 					   &mac_cfg0, 4))
 			return -EIO;
@@ -201,7 +200,7 @@
 	 * cannot be in reset
 	 */
 
-	if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
+	if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
 				  &mac_cfg0, 4))
 		return -EIO;
 	if (netxen_gb_get_soft_reset(mac_cfg0)) {
@@ -212,7 +211,7 @@
 		netxen_gb_tx_reset_mac(temp);
 		netxen_gb_rx_reset_mac(temp);
 
-		if (netxen_nic_hw_write_wx(adapter,
+		if (adapter->hw_write_wx(adapter,
 					   NETXEN_NIU_GB_MAC_CONFIG_0(0),
 					   &temp, 4))
 			return -EIO;
@@ -220,24 +219,24 @@
 	}
 
 	command = 0;		/* turn off any prior activity */
-	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
+	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
 				   &command, 4))
 		return -EIO;
 
 	address = 0;
 	netxen_gb_mii_mgmt_reg_addr(address, reg);
 	netxen_gb_mii_mgmt_phy_addr(address, phy);
-	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
+	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
 				   &address, 4))
 		return -EIO;
 
-	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0),
+	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0),
 				   &val, 4))
 		return -EIO;
 
 	status = 0;
 	do {
-		if (netxen_nic_hw_read_wx(adapter,
+		if (adapter->hw_read_wx(adapter,
 					  NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
 					  &status, 4))
 			return -EIO;
@@ -252,7 +251,7 @@
 
 	/* restore the state of port 0 MAC in case we tampered with it */
 	if (restore)
-		if (netxen_nic_hw_write_wx(adapter,
+		if (adapter->hw_write_wx(adapter,
 					   NETXEN_NIU_GB_MAC_CONFIG_0(0),
 					   &mac_cfg0, 4))
 			return -EIO;
@@ -401,14 +400,16 @@
 {
 	int result = 0;
 	__u32 status;
+
+	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+		return 0;
+
 	if (adapter->disable_phy_interrupts)
 		adapter->disable_phy_interrupts(adapter);
 	mdelay(2);
 
-	if (0 ==
-	    netxen_niu_gbe_phy_read(adapter,
-				    NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
-				    &status)) {
+	if (0 == netxen_niu_gbe_phy_read(adapter,
+			NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, &status)) {
 		if (netxen_get_phy_link(status)) {
 			if (netxen_get_phy_speed(status) == 2) {
 				netxen_niu_gbe_set_gmii_mode(adapter, port, 1);
@@ -456,12 +457,12 @@
 
 int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)
 {
-	u32 portnum = adapter->physical_port;
-
-	netxen_crb_writelit_adapter(adapter,
-		NETXEN_NIU_XGE_CONFIG_1+(0x10000*portnum), 0x1447);
-	netxen_crb_writelit_adapter(adapter,
-		NETXEN_NIU_XGE_CONFIG_0+(0x10000*portnum), 0x5);
+	if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+		netxen_crb_writelit_adapter(adapter,
+			NETXEN_NIU_XGE_CONFIG_1+(0x10000*port), 0x1447);
+		netxen_crb_writelit_adapter(adapter,
+			NETXEN_NIU_XGE_CONFIG_0+(0x10000*port), 0x5);
+	}
 
 	return 0;
 }
@@ -581,10 +582,10 @@
 	if ((phy < 0) || (phy > 3))
 		return -EINVAL;
 
-	if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy),
+	if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy),
 				  &stationhigh, 4))
 		return -EIO;
-	if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy),
+	if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy),
 				  &stationlow, 4))
 		return -EIO;
 	((__le32 *)val)[1] = cpu_to_le32(stationhigh);
@@ -613,14 +614,14 @@
 		temp[0] = temp[1] = 0;
 		memcpy(temp + 2, addr, 2);
 		val = le32_to_cpu(*(__le32 *)temp);
-		if (netxen_nic_hw_write_wx
-		    (adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy), &val, 4))
+		if (adapter->hw_write_wx(adapter,
+				NETXEN_NIU_GB_STATION_ADDR_1(phy), &val, 4))
 			return -EIO;
 
 		memcpy(temp, ((u8 *) addr) + 2, sizeof(__le32));
 		val = le32_to_cpu(*(__le32 *)temp);
-		if (netxen_nic_hw_write_wx
-		    (adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy), &val, 4))
+		if (adapter->hw_write_wx(adapter,
+				NETXEN_NIU_GB_STATION_ADDR_0(phy), &val, 4))
 			return -2;
 
 		netxen_niu_macaddr_get(adapter,
@@ -654,7 +655,7 @@
 
 	mac_cfg0 = 0;
 	netxen_gb_soft_reset(mac_cfg0);
-	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
 				   &mac_cfg0, 4))
 		return -EIO;
 	mac_cfg0 = 0;
@@ -666,7 +667,7 @@
 	netxen_gb_tx_reset_mac(mac_cfg0);
 	netxen_gb_rx_reset_mac(mac_cfg0);
 
-	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
 				   &mac_cfg0, 4))
 		return -EIO;
 	mac_cfg1 = 0;
@@ -679,7 +680,7 @@
 
 	if (mode == NETXEN_NIU_10_100_MB) {
 		netxen_gb_set_intfmode(mac_cfg1, 1);
-		if (netxen_nic_hw_write_wx(adapter,
+		if (adapter->hw_write_wx(adapter,
 					   NETXEN_NIU_GB_MAC_CONFIG_1(port),
 					   &mac_cfg1, 4))
 			return -EIO;
@@ -692,7 +693,7 @@
 
 	} else if (mode == NETXEN_NIU_1000_MB) {
 		netxen_gb_set_intfmode(mac_cfg1, 2);
-		if (netxen_nic_hw_write_wx(adapter,
+		if (adapter->hw_write_wx(adapter,
 					   NETXEN_NIU_GB_MAC_CONFIG_1(port),
 					   &mac_cfg1, 4))
 			return -EIO;
@@ -704,7 +705,7 @@
 	}
 	mii_cfg = 0;
 	netxen_gb_set_mii_mgmt_clockselect(mii_cfg, 7);
-	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port),
+	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port),
 				   &mii_cfg, 4))
 		return -EIO;
 	mac_cfg0 = 0;
@@ -713,7 +714,7 @@
 	netxen_gb_unset_rx_flowctl(mac_cfg0);
 	netxen_gb_unset_tx_flowctl(mac_cfg0);
 
-	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
 				   &mac_cfg0, 4))
 		return -EIO;
 	return 0;
@@ -730,7 +731,7 @@
 		return -EINVAL;
 	mac_cfg0 = 0;
 	netxen_gb_soft_reset(mac_cfg0);
-	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
 				   &mac_cfg0, 4))
 		return -EIO;
 	return 0;
@@ -746,7 +747,7 @@
 		return -EINVAL;
 
 	mac_cfg = 0;
-	if (netxen_nic_hw_write_wx(adapter,
+	if (adapter->hw_write_wx(adapter,
 		NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), &mac_cfg, 4))
 		return -EIO;
 	return 0;
@@ -763,7 +764,7 @@
 		return -EINVAL;
 
 	/* save previous contents */
-	if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
+	if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
 				  &reg, 4))
 		return -EIO;
 	if (mode == NETXEN_NIU_PROMISC_MODE) {
@@ -801,7 +802,7 @@
 			return -EIO;
 		}
 	}
-	if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
+	if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
 				   &reg, 4))
 		return -EIO;
 	return 0;
@@ -826,13 +827,13 @@
 	case 0:
 	    memcpy(temp + 2, addr, 2);
 	    val = le32_to_cpu(*(__le32 *)temp);
-	    if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
+	    if (adapter->hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
 				&val, 4))
 		return -EIO;
 
 	    memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
 	    val = le32_to_cpu(*(__le32 *)temp);
-	    if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
+	    if (adapter->hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
 				&val, 4))
 		return -EIO;
 	    break;
@@ -840,13 +841,13 @@
 	case 1:
 	    memcpy(temp + 2, addr, 2);
 	    val = le32_to_cpu(*(__le32 *)temp);
-	    if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_1,
+	    if (adapter->hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_1,
 				&val, 4))
 		return -EIO;
 
 	    memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
 	    val = le32_to_cpu(*(__le32 *)temp);
-	    if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_HI,
+	    if (adapter->hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_HI,
 				&val, 4))
 		return -EIO;
 	    break;
@@ -877,10 +878,10 @@
 	if (phy != 0)
 		return -EINVAL;
 
-	if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
+	if (adapter->hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
 				  &stationhigh, 4))
 		return -EIO;
-	if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
+	if (adapter->hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
 				  &stationlow, 4))
 		return -EIO;
 	((__le32 *)val)[1] = cpu_to_le32(stationhigh);
@@ -901,7 +902,7 @@
 	if (port > NETXEN_NIU_MAX_XG_PORTS)
 		return -EINVAL;
 
-	if (netxen_nic_hw_read_wx(adapter,
+	if (adapter->hw_read_wx(adapter,
 		NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), &reg, 4))
 			return -EIO;
 	if (mode == NETXEN_NIU_PROMISC_MODE)
@@ -909,6 +910,11 @@
 	else
 		reg = (reg & ~0x2000UL);
 
+	if (mode == NETXEN_NIU_ALLMULTI_MODE)
+		reg = (reg | 0x1000UL);
+	else
+		reg = (reg & ~0x1000UL);
+
 	netxen_crb_writelit_adapter(adapter,
 		NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), reg);
 
diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h
index a566b50..3bfa51b 100644
--- a/drivers/net/netxen/netxen_nic_phan_reg.h
+++ b/drivers/net/netxen/netxen_nic_phan_reg.h
@@ -42,8 +42,11 @@
 #define CRB_CMD_CONSUMER_OFFSET     NETXEN_NIC_REG(0x0c)
 #define CRB_PAUSE_ADDR_LO           NETXEN_NIC_REG(0x10)	/* C0 EPG BUG  */
 #define CRB_PAUSE_ADDR_HI           NETXEN_NIC_REG(0x14)
-#define CRB_HOST_CMD_ADDR_HI        NETXEN_NIC_REG(0x18)	/* host add:cmd ring */
-#define CRB_HOST_CMD_ADDR_LO        NETXEN_NIC_REG(0x1c)
+#define NX_CDRP_CRB_OFFSET          NETXEN_NIC_REG(0x18)
+#define NX_ARG1_CRB_OFFSET          NETXEN_NIC_REG(0x1c)
+#define NX_ARG2_CRB_OFFSET          NETXEN_NIC_REG(0x20)
+#define NX_ARG3_CRB_OFFSET          NETXEN_NIC_REG(0x24)
+#define NX_SIGN_CRB_OFFSET          NETXEN_NIC_REG(0x28)
 #define CRB_CMD_INTR_LOOP           NETXEN_NIC_REG(0x20)	/* 4 regs for perf */
 #define CRB_CMD_DMA_LOOP            NETXEN_NIC_REG(0x24)
 #define CRB_RCV_INTR_LOOP           NETXEN_NIC_REG(0x28)
@@ -73,8 +76,8 @@
 #define CRB_RX_LRO_MID_TIMER        NETXEN_NIC_REG(0x88)
 #define CRB_DMA_MAX_RCV_BUFS        NETXEN_NIC_REG(0x8c)
 #define CRB_MAX_DMA_ENTRIES         NETXEN_NIC_REG(0x90)
-#define CRB_XG_STATE                NETXEN_NIC_REG(0x94)	/* XG Link status */
-#define CRB_AGENT_GO                NETXEN_NIC_REG(0x98)	/* NIC pkt gen agent */
+#define CRB_XG_STATE                NETXEN_NIC_REG(0x94) /* XG Link status */
+#define CRB_XG_STATE_P3             NETXEN_NIC_REG(0x98) /* XG PF Link status */
 #define CRB_AGENT_TX_SIZE           NETXEN_NIC_REG(0x9c)
 #define CRB_AGENT_TX_TYPE           NETXEN_NIC_REG(0xa0)
 #define CRB_AGENT_TX_ADDR           NETXEN_NIC_REG(0xa4)
@@ -97,7 +100,9 @@
 #define CRB_HOST_BUFFER_CONS        NETXEN_NIC_REG(0xf0)
 #define CRB_JUMBO_BUFFER_PROD       NETXEN_NIC_REG(0xf4)
 #define CRB_JUMBO_BUFFER_CONS       NETXEN_NIC_REG(0xf8)
+#define CRB_HOST_DUMMY_BUF          NETXEN_NIC_REG(0xfc)
 
+#define CRB_RCVPEG_STATE            NETXEN_NIC_REG(0x13c)
 #define CRB_CMD_PRODUCER_OFFSET_1   NETXEN_NIC_REG(0x1ac)
 #define CRB_CMD_CONSUMER_OFFSET_1   NETXEN_NIC_REG(0x1b0)
 #define CRB_CMD_PRODUCER_OFFSET_2   NETXEN_NIC_REG(0x1b8)
@@ -147,29 +152,15 @@
 #define nx_get_temp_state(x)		((x) & 0xffff)
 #define nx_encode_temp(val, state)	(((val) << 16) | (state))
 
-/* CRB registers per Rcv Descriptor ring */
-struct netxen_rcv_desc_crb {
-	u32 crb_rcv_producer_offset __attribute__ ((aligned(512)));
-	u32 crb_rcv_consumer_offset;
-	u32 crb_globalrcv_ring;
-	u32 crb_rcv_ring_size;
-};
-
 /*
  * CRB registers used by the receive peg logic.
  */
 
 struct netxen_recv_crb {
-	struct netxen_rcv_desc_crb rcv_desc_crb[NUM_RCV_DESC_RINGS];
-	u32 crb_rcvstatus_ring;
-	u32 crb_rcv_status_producer;
-	u32 crb_rcv_status_consumer;
-	u32 crb_rcvpeg_state;
-	u32 crb_status_ring_size;
+	u32 crb_rcv_producer[NUM_RCV_DESC_RINGS];
+	u32 crb_sts_consumer;
 };
 
-extern struct netxen_recv_crb recv_crb_registers[];
-
 /*
  * Temperature control.
  */
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 32a8503..4aa5479 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -158,11 +158,10 @@
 {
 	int err;
 	int temp;
-	int mode;
 
 	/* Enable Fiber/Copper auto selection */
 	temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
-	temp |= MII_M1111_HWCFG_FIBER_COPPER_AUTO;
+	temp &= ~MII_M1111_HWCFG_FIBER_COPPER_AUTO;
 	phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
 
 	temp = phy_read(phydev, MII_BMCR);
@@ -198,9 +197,7 @@
 
 		temp &= ~(MII_M1111_HWCFG_MODE_MASK);
 
-		mode = phy_read(phydev, MII_M1111_PHY_EXT_CR);
-
-		if (mode & MII_M1111_HWCFG_FIBER_COPPER_RES)
+		if (temp & MII_M1111_HWCFG_FIBER_COPPER_RES)
 			temp |= MII_M1111_HWCFG_MODE_FIBER_RGMII;
 		else
 			temp |= MII_M1111_HWCFG_MODE_COPPER_RGMII;
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 6b1d7a8..739b3ab 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -866,7 +866,8 @@
 			err = PTR_ERR(ppp_class);
 			goto out_chrdev;
 		}
-		device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), "ppp");
+		device_create_drvdata(ppp_class, NULL, MKDEV(PPP_MAJOR, 0),
+				      NULL, "ppp");
 	}
 
 out:
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c
index 504a48f..6531ff5 100644
--- a/drivers/net/r6040.c
+++ b/drivers/net/r6040.c
@@ -50,8 +50,8 @@
 #include <asm/processor.h>
 
 #define DRV_NAME	"r6040"
-#define DRV_VERSION	"0.16"
-#define DRV_RELDATE	"10Nov2007"
+#define DRV_VERSION	"0.18"
+#define DRV_RELDATE	"13Jul2008"
 
 /* PHY CHIP Address */
 #define PHY1_ADDR	1	/* For MAC1 */
@@ -91,6 +91,14 @@
 #define MISR		0x3C	/* Status register */
 #define MIER		0x40	/* INT enable register */
 #define  MSK_INT	0x0000	/* Mask off interrupts */
+#define  RX_FINISH	0x0001  /* RX finished */
+#define  RX_NO_DESC	0x0002  /* No RX descriptor available */
+#define  RX_FIFO_FULL	0x0004  /* RX FIFO full */
+#define  RX_EARLY	0x0008  /* RX early */
+#define  TX_FINISH	0x0010  /* TX finished */
+#define  TX_EARLY	0x0080  /* TX early */
+#define  EVENT_OVRFL	0x0100  /* Event counter overflow */
+#define  LINK_CHANGED	0x0200  /* PHY link changed */
 #define ME_CISR		0x44	/* Event counter INT status */
 #define ME_CIER		0x48	/* Event counter INT enable  */
 #define MR_CNT		0x50	/* Successfully received packet counter */
@@ -130,6 +138,21 @@
 #define MBCR_DEFAULT	0x012A	/* MAC Bus Control Register */
 #define MCAST_MAX	4	/* Max number multicast addresses to filter */
 
+/* Descriptor status */
+#define DSC_OWNER_MAC	0x8000	/* MAC is the owner of this descriptor */
+#define DSC_RX_OK	0x4000	/* RX was successful */
+#define DSC_RX_ERR	0x0800	/* RX PHY error */
+#define DSC_RX_ERR_DRI	0x0400	/* RX dribble packet */
+#define DSC_RX_ERR_BUF	0x0200	/* RX length exceeds buffer size */
+#define DSC_RX_ERR_LONG	0x0100	/* RX length > maximum packet length */
+#define DSC_RX_ERR_RUNT	0x0080	/* RX packet length < 64 byte */
+#define DSC_RX_ERR_CRC	0x0040	/* RX CRC error */
+#define DSC_RX_BCAST	0x0020	/* RX broadcast (no error) */
+#define DSC_RX_MCAST	0x0010	/* RX multicast (no error) */
+#define DSC_RX_MCH_HIT	0x0008	/* RX multicast hit in hash table (no error) */
+#define DSC_RX_MIDH_HIT	0x0004	/* RX MID table hit (no error) */
+#define DSC_RX_IDX_MID_MASK 3	/* RX mask for the index of matched MIDx */
+
 /* PHY settings */
 #define ICPLUS_PHY_ID	0x0243
 
@@ -139,10 +162,10 @@
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("RDC R6040 NAPI PCI FastEthernet driver");
 
-#define RX_INT                         0x0001
-#define TX_INT                         0x0010
-#define RX_NO_DESC_INT                 0x0002
-#define INT_MASK                 (RX_INT | TX_INT)
+/* RX and TX interrupts that we handle */
+#define RX_INTS			(RX_FIFO_FULL | RX_NO_DESC | RX_FINISH)
+#define TX_INTS			(TX_FINISH)
+#define INT_MASK		(RX_INTS | TX_INTS)
 
 struct r6040_descriptor {
 	u16	status, len;		/* 0-3 */
@@ -167,7 +190,7 @@
 	struct r6040_descriptor *tx_ring;
 	dma_addr_t rx_ring_dma;
 	dma_addr_t tx_ring_dma;
-	u16	tx_free_desc, rx_free_desc, phy_addr, phy_mode;
+	u16	tx_free_desc, phy_addr, phy_mode;
 	u16	mcr0, mcr1;
 	u16	switch_sig;
 	struct net_device *dev;
@@ -183,7 +206,7 @@
 static int phy_table[] = { PHY1_ADDR, PHY2_ADDR };
 
 /* Read a word data from PHY Chip */
-static int phy_read(void __iomem *ioaddr, int phy_addr, int reg)
+static int r6040_phy_read(void __iomem *ioaddr, int phy_addr, int reg)
 {
 	int limit = 2048;
 	u16 cmd;
@@ -200,7 +223,7 @@
 }
 
 /* Write a word data from PHY Chip */
-static void phy_write(void __iomem *ioaddr, int phy_addr, int reg, u16 val)
+static void r6040_phy_write(void __iomem *ioaddr, int phy_addr, int reg, u16 val)
 {
 	int limit = 2048;
 	u16 cmd;
@@ -216,20 +239,20 @@
 	}
 }
 
-static int mdio_read(struct net_device *dev, int mii_id, int reg)
+static int r6040_mdio_read(struct net_device *dev, int mii_id, int reg)
 {
 	struct r6040_private *lp = netdev_priv(dev);
 	void __iomem *ioaddr = lp->base;
 
-	return (phy_read(ioaddr, lp->phy_addr, reg));
+	return (r6040_phy_read(ioaddr, lp->phy_addr, reg));
 }
 
-static void mdio_write(struct net_device *dev, int mii_id, int reg, int val)
+static void r6040_mdio_write(struct net_device *dev, int mii_id, int reg, int val)
 {
 	struct r6040_private *lp = netdev_priv(dev);
 	void __iomem *ioaddr = lp->base;
 
-	phy_write(ioaddr, lp->phy_addr, reg, val);
+	r6040_phy_write(ioaddr, lp->phy_addr, reg, val);
 }
 
 static void r6040_free_txbufs(struct net_device *dev)
@@ -283,58 +306,101 @@
 	desc->vndescp = desc_ring;
 }
 
-/* Allocate skb buffer for rx descriptor */
-static void rx_buf_alloc(struct r6040_private *lp, struct net_device *dev)
-{
-	struct r6040_descriptor *descptr;
-	void __iomem *ioaddr = lp->base;
-
-	descptr = lp->rx_insert_ptr;
-	while (lp->rx_free_desc < RX_DCNT) {
-		descptr->skb_ptr = netdev_alloc_skb(dev, MAX_BUF_SIZE);
-
-		if (!descptr->skb_ptr)
-			break;
-		descptr->buf = cpu_to_le32(pci_map_single(lp->pdev,
-			descptr->skb_ptr->data,
-			MAX_BUF_SIZE, PCI_DMA_FROMDEVICE));
-		descptr->status = 0x8000;
-		descptr = descptr->vndescp;
-		lp->rx_free_desc++;
-		/* Trigger RX DMA */
-		iowrite16(lp->mcr0 | 0x0002, ioaddr);
-	}
-	lp->rx_insert_ptr = descptr;
-}
-
-static void r6040_alloc_txbufs(struct net_device *dev)
+static void r6040_init_txbufs(struct net_device *dev)
 {
 	struct r6040_private *lp = netdev_priv(dev);
-	void __iomem *ioaddr = lp->base;
 
 	lp->tx_free_desc = TX_DCNT;
 
 	lp->tx_remove_ptr = lp->tx_insert_ptr = lp->tx_ring;
 	r6040_init_ring_desc(lp->tx_ring, lp->tx_ring_dma, TX_DCNT);
-
-	iowrite16(lp->tx_ring_dma, ioaddr + MTD_SA0);
-	iowrite16(lp->tx_ring_dma >> 16, ioaddr + MTD_SA1);
 }
 
-static void r6040_alloc_rxbufs(struct net_device *dev)
+static int r6040_alloc_rxbufs(struct net_device *dev)
 {
 	struct r6040_private *lp = netdev_priv(dev);
-	void __iomem *ioaddr = lp->base;
-
-	lp->rx_free_desc = 0;
+	struct r6040_descriptor *desc;
+	struct sk_buff *skb;
+	int rc;
 
 	lp->rx_remove_ptr = lp->rx_insert_ptr = lp->rx_ring;
 	r6040_init_ring_desc(lp->rx_ring, lp->rx_ring_dma, RX_DCNT);
 
-	rx_buf_alloc(lp, dev);
+	/* Allocate skbs for the rx descriptors */
+	desc = lp->rx_ring;
+	do {
+		skb = netdev_alloc_skb(dev, MAX_BUF_SIZE);
+		if (!skb) {
+			printk(KERN_ERR "%s: failed to alloc skb for rx\n", dev->name);
+			rc = -ENOMEM;
+			goto err_exit;
+		}
+		desc->skb_ptr = skb;
+		desc->buf = cpu_to_le32(pci_map_single(lp->pdev,
+						desc->skb_ptr->data,
+						MAX_BUF_SIZE, PCI_DMA_FROMDEVICE));
+		desc->status = DSC_OWNER_MAC;
+		desc = desc->vndescp;
+	} while (desc != lp->rx_ring);
 
+	return 0;
+
+err_exit:
+	/* Deallocate all previously allocated skbs */
+	r6040_free_rxbufs(dev);
+	return rc;
+}
+
+static void r6040_init_mac_regs(struct net_device *dev)
+{
+	struct r6040_private *lp = netdev_priv(dev);
+	void __iomem *ioaddr = lp->base;
+	int limit = 2048;
+	u16 cmd;
+
+	/* Mask Off Interrupt */
+	iowrite16(MSK_INT, ioaddr + MIER);
+
+	/* Reset RDC MAC */
+	iowrite16(MAC_RST, ioaddr + MCR1);
+	while (limit--) {
+		cmd = ioread16(ioaddr + MCR1);
+		if (cmd & 0x1)
+			break;
+	}
+	/* Reset internal state machine */
+	iowrite16(2, ioaddr + MAC_SM);
+	iowrite16(0, ioaddr + MAC_SM);
+	udelay(5000);
+
+	/* MAC Bus Control Register */
+	iowrite16(MBCR_DEFAULT, ioaddr + MBCR);
+
+	/* Buffer Size Register */
+	iowrite16(MAX_BUF_SIZE, ioaddr + MR_BSR);
+
+	/* Write TX ring start address */
+	iowrite16(lp->tx_ring_dma, ioaddr + MTD_SA0);
+	iowrite16(lp->tx_ring_dma >> 16, ioaddr + MTD_SA1);
+
+	/* Write RX ring start address */
 	iowrite16(lp->rx_ring_dma, ioaddr + MRD_SA0);
 	iowrite16(lp->rx_ring_dma >> 16, ioaddr + MRD_SA1);
+
+	/* Set interrupt waiting time and packet numbers */
+	iowrite16(0, ioaddr + MT_ICR);
+	iowrite16(0, ioaddr + MR_ICR);
+
+	/* Enable interrupts */
+	iowrite16(INT_MASK, ioaddr + MIER);
+
+	/* Enable TX and RX */
+	iowrite16(lp->mcr0 | 0x0002, ioaddr);
+
+	/* Let TX poll the descriptors
+	 * we may got called by r6040_tx_timeout which has left
+	 * some unsent tx buffers */
+	iowrite16(0x01, ioaddr + MTPR);
 }
 
 static void r6040_tx_timeout(struct net_device *dev)
@@ -342,27 +408,16 @@
 	struct r6040_private *priv = netdev_priv(dev);
 	void __iomem *ioaddr = priv->base;
 
-	printk(KERN_WARNING "%s: transmit timed out, status %4.4x, PHY status "
-		"%4.4x\n",
+	printk(KERN_WARNING "%s: transmit timed out, int enable %4.4x "
+		"status %4.4x, PHY status %4.4x\n",
 		dev->name, ioread16(ioaddr + MIER),
-		mdio_read(dev, priv->mii_if.phy_id, MII_BMSR));
-
-	disable_irq(dev->irq);
-	napi_disable(&priv->napi);
-	spin_lock(&priv->lock);
-	/* Clear all descriptors */
-	r6040_free_txbufs(dev);
-	r6040_free_rxbufs(dev);
-	r6040_alloc_txbufs(dev);
-	r6040_alloc_rxbufs(dev);
-
-	/* Reset MAC */
-	iowrite16(MAC_RST, ioaddr + MCR1);
-	spin_unlock(&priv->lock);
-	enable_irq(dev->irq);
+		ioread16(ioaddr + MISR),
+		r6040_mdio_read(dev, priv->mii_if.phy_id, MII_BMSR));
 
 	dev->stats.tx_errors++;
-	netif_wake_queue(dev);
+
+	/* Reset MAC and re-init all registers */
+	r6040_init_mac_regs(dev);
 }
 
 static struct net_device_stats *r6040_get_stats(struct net_device *dev)
@@ -424,6 +479,7 @@
 	del_timer_sync(&lp->timer);
 
 	spin_lock_irq(&lp->lock);
+	napi_disable(&lp->napi);
 	netif_stop_queue(dev);
 	r6040_down(dev);
 	spin_unlock_irq(&lp->lock);
@@ -432,23 +488,23 @@
 }
 
 /* Status of PHY CHIP */
-static int phy_mode_chk(struct net_device *dev)
+static int r6040_phy_mode_chk(struct net_device *dev)
 {
 	struct r6040_private *lp = netdev_priv(dev);
 	void __iomem *ioaddr = lp->base;
 	int phy_dat;
 
 	/* PHY Link Status Check */
-	phy_dat = phy_read(ioaddr, lp->phy_addr, 1);
+	phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 1);
 	if (!(phy_dat & 0x4))
 		phy_dat = 0x8000;	/* Link Failed, full duplex */
 
 	/* PHY Chip Auto-Negotiation Status */
-	phy_dat = phy_read(ioaddr, lp->phy_addr, 1);
+	phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 1);
 	if (phy_dat & 0x0020) {
 		/* Auto Negotiation Mode */
-		phy_dat = phy_read(ioaddr, lp->phy_addr, 5);
-		phy_dat &= phy_read(ioaddr, lp->phy_addr, 4);
+		phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 5);
+		phy_dat &= r6040_phy_read(ioaddr, lp->phy_addr, 4);
 		if (phy_dat & 0x140)
 			/* Force full duplex */
 			phy_dat = 0x8000;
@@ -456,7 +512,7 @@
 			phy_dat = 0;
 	} else {
 		/* Force Mode */
-		phy_dat = phy_read(ioaddr, lp->phy_addr, 0);
+		phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 0);
 		if (phy_dat & 0x100)
 			phy_dat = 0x8000;
 		else
@@ -468,12 +524,12 @@
 
 static void r6040_set_carrier(struct mii_if_info *mii)
 {
-	if (phy_mode_chk(mii->dev)) {
+	if (r6040_phy_mode_chk(mii->dev)) {
 		/* autoneg is off: Link is always assumed to be up */
 		if (!netif_carrier_ok(mii->dev))
 			netif_carrier_on(mii->dev);
 	} else
-		phy_mode_chk(mii->dev);
+		r6040_phy_mode_chk(mii->dev);
 }
 
 static int r6040_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -494,73 +550,72 @@
 static int r6040_rx(struct net_device *dev, int limit)
 {
 	struct r6040_private *priv = netdev_priv(dev);
-	int count;
-	void __iomem *ioaddr = priv->base;
+	struct r6040_descriptor *descptr = priv->rx_remove_ptr;
+	struct sk_buff *skb_ptr, *new_skb;
+	int count = 0;
 	u16 err;
 
-	for (count = 0; count < limit; ++count) {
-		struct r6040_descriptor *descptr = priv->rx_remove_ptr;
-		struct sk_buff *skb_ptr;
-
-		/* Disable RX interrupt */
-		iowrite16(ioread16(ioaddr + MIER) & (~RX_INT), ioaddr + MIER);
-		descptr = priv->rx_remove_ptr;
-
-		/* Check for errors */
-		err = ioread16(ioaddr + MLSR);
-		if (err & 0x0400)
-			dev->stats.rx_errors++;
-		/* RX FIFO over-run */
-		if (err & 0x8000)
-			dev->stats.rx_fifo_errors++;
-		/* RX descriptor unavailable */
-		if (err & 0x0080)
-			dev->stats.rx_frame_errors++;
-		/* Received packet with length over buffer lenght */
-		if (err & 0x0020)
-			dev->stats.rx_over_errors++;
-		/* Received packet with too long or short */
-		if (err & (0x0010 | 0x0008))
-			dev->stats.rx_length_errors++;
-		/* Received packet with CRC errors */
-		if (err & 0x0004) {
-			spin_lock(&priv->lock);
-			dev->stats.rx_crc_errors++;
-			spin_unlock(&priv->lock);
-		}
-
-		while (priv->rx_free_desc) {
-			/* No RX packet */
-			if (descptr->status & 0x8000)
-				break;
-			skb_ptr = descptr->skb_ptr;
-			if (!skb_ptr) {
-				printk(KERN_ERR "%s: Inconsistent RX"
-					"descriptor chain\n",
-					dev->name);
-				break;
+	/* Limit not reached and the descriptor belongs to the CPU */
+	while (count < limit && !(descptr->status & DSC_OWNER_MAC)) {
+		/* Read the descriptor status */
+		err = descptr->status;
+		/* Global error status set */
+		if (err & DSC_RX_ERR) {
+			/* RX dribble */
+			if (err & DSC_RX_ERR_DRI)
+				dev->stats.rx_frame_errors++;
+			/* Buffer lenght exceeded */
+			if (err & DSC_RX_ERR_BUF)
+				dev->stats.rx_length_errors++;
+			/* Packet too long */
+			if (err & DSC_RX_ERR_LONG)
+				dev->stats.rx_length_errors++;
+			/* Packet < 64 bytes */
+			if (err & DSC_RX_ERR_RUNT)
+				dev->stats.rx_length_errors++;
+			/* CRC error */
+			if (err & DSC_RX_ERR_CRC) {
+				spin_lock(&priv->lock);
+				dev->stats.rx_crc_errors++;
+				spin_unlock(&priv->lock);
 			}
-			descptr->skb_ptr = NULL;
-			skb_ptr->dev = priv->dev;
-			/* Do not count the CRC */
-			skb_put(skb_ptr, descptr->len - 4);
-			pci_unmap_single(priv->pdev, le32_to_cpu(descptr->buf),
-				MAX_BUF_SIZE, PCI_DMA_FROMDEVICE);
-			skb_ptr->protocol = eth_type_trans(skb_ptr, priv->dev);
-			/* Send to upper layer */
-			netif_receive_skb(skb_ptr);
-			dev->last_rx = jiffies;
-			dev->stats.rx_packets++;
-			dev->stats.rx_bytes += descptr->len;
-			/* To next descriptor */
-			descptr = descptr->vndescp;
-			priv->rx_free_desc--;
+			goto next_descr;
 		}
-		priv->rx_remove_ptr = descptr;
+		
+		/* Packet successfully received */
+		new_skb = netdev_alloc_skb(dev, MAX_BUF_SIZE);
+		if (!new_skb) {
+			dev->stats.rx_dropped++;
+			goto next_descr;
+		}
+		skb_ptr = descptr->skb_ptr;
+		skb_ptr->dev = priv->dev;
+		
+		/* Do not count the CRC */
+		skb_put(skb_ptr, descptr->len - 4);
+		pci_unmap_single(priv->pdev, le32_to_cpu(descptr->buf),
+					MAX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+		skb_ptr->protocol = eth_type_trans(skb_ptr, priv->dev);
+		
+		/* Send to upper layer */
+		netif_receive_skb(skb_ptr);
+		dev->last_rx = jiffies;
+		dev->stats.rx_packets++;
+		dev->stats.rx_bytes += descptr->len - 4;
+
+		/* put new skb into descriptor */
+		descptr->skb_ptr = new_skb;
+		descptr->buf = cpu_to_le32(pci_map_single(priv->pdev,
+						descptr->skb_ptr->data,
+					MAX_BUF_SIZE, PCI_DMA_FROMDEVICE));
+
+next_descr:
+		/* put the descriptor back to the MAC */
+		descptr->status = DSC_OWNER_MAC;
+		descptr = descptr->vndescp;
+		count++;
 	}
-	/* Allocate new RX buffer */
-	if (priv->rx_free_desc < RX_DCNT)
-		rx_buf_alloc(priv, priv->dev);
+	priv->rx_remove_ptr = descptr;
 
 	return count;
 }
@@ -584,7 +639,7 @@
 		if (err & (0x2000 | 0x4000))
 			dev->stats.tx_carrier_errors++;
 
-		if (descptr->status & 0x8000)
+		if (descptr->status & DSC_OWNER_MAC)
 			break; /* Not complete */
 		skb_ptr = descptr->skb_ptr;
 		pci_unmap_single(priv->pdev, le32_to_cpu(descptr->buf),
@@ -616,7 +671,7 @@
 	if (work_done < budget) {
 		netif_rx_complete(dev, napi);
 		/* Enable RX interrupt */
-		iowrite16(ioread16(ioaddr + MIER) | RX_INT, ioaddr + MIER);
+		iowrite16(ioread16(ioaddr + MIER) | RX_INTS, ioaddr + MIER);
 	}
 	return work_done;
 }
@@ -638,13 +693,22 @@
 		return IRQ_NONE;
 
 	/* RX interrupt request */
-	if (status & 0x01) {
+	if (status & RX_INTS) {
+		if (status & RX_NO_DESC) {
+			/* RX descriptor unavailable */
+			dev->stats.rx_dropped++;
+			dev->stats.rx_missed_errors++;
+		}
+		if (status & RX_FIFO_FULL)
+			dev->stats.rx_fifo_errors++;
+
+		/* Mask off RX interrupt */
+		iowrite16(ioread16(ioaddr + MIER) & ~RX_INTS, ioaddr + MIER);
 		netif_rx_schedule(dev, &lp->napi);
-		iowrite16(TX_INT, ioaddr + MIER);
 	}
 
 	/* TX interrupt request */
-	if (status & 0x10)
+	if (status & TX_INTS)
 		r6040_tx(dev);
 
 	return IRQ_HANDLED;
@@ -660,52 +724,48 @@
 #endif
 
 /* Init RDC MAC */
-static void r6040_up(struct net_device *dev)
+static int r6040_up(struct net_device *dev)
 {
 	struct r6040_private *lp = netdev_priv(dev);
 	void __iomem *ioaddr = lp->base;
+	int ret;
 
 	/* Initialise and alloc RX/TX buffers */
-	r6040_alloc_txbufs(dev);
-	r6040_alloc_rxbufs(dev);
+	r6040_init_txbufs(dev);
+	ret = r6040_alloc_rxbufs(dev);
+	if (ret)
+		return ret;
 
-	/* Buffer Size Register */
-	iowrite16(MAX_BUF_SIZE, ioaddr + MR_BSR);
 	/* Read the PHY ID */
-	lp->switch_sig = phy_read(ioaddr, 0, 2);
+	lp->switch_sig = r6040_phy_read(ioaddr, 0, 2);
 
 	if (lp->switch_sig  == ICPLUS_PHY_ID) {
-		phy_write(ioaddr, 29, 31, 0x175C); /* Enable registers */
+		r6040_phy_write(ioaddr, 29, 31, 0x175C); /* Enable registers */
 		lp->phy_mode = 0x8000;
 	} else {
 		/* PHY Mode Check */
-		phy_write(ioaddr, lp->phy_addr, 4, PHY_CAP);
-		phy_write(ioaddr, lp->phy_addr, 0, PHY_MODE);
+		r6040_phy_write(ioaddr, lp->phy_addr, 4, PHY_CAP);
+		r6040_phy_write(ioaddr, lp->phy_addr, 0, PHY_MODE);
 
 		if (PHY_MODE == 0x3100)
-			lp->phy_mode = phy_mode_chk(dev);
+			lp->phy_mode = r6040_phy_mode_chk(dev);
 		else
 			lp->phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0;
 	}
-	/* MAC Bus Control Register */
-	iowrite16(MBCR_DEFAULT, ioaddr + MBCR);
 
-	/* MAC TX/RX Enable */
+	/* Set duplex mode */
 	lp->mcr0 |= lp->phy_mode;
-	iowrite16(lp->mcr0, ioaddr);
-
-	/* set interrupt waiting time and packet numbers */
-	iowrite16(0x0F06, ioaddr + MT_ICR);
-	iowrite16(0x0F06, ioaddr + MR_ICR);
 
 	/* improve performance (by RDC guys) */
-	phy_write(ioaddr, 30, 17, (phy_read(ioaddr, 30, 17) | 0x4000));
-	phy_write(ioaddr, 30, 17, ~((~phy_read(ioaddr, 30, 17)) | 0x2000));
-	phy_write(ioaddr, 0, 19, 0x0000);
-	phy_write(ioaddr, 0, 30, 0x01F0);
+	r6040_phy_write(ioaddr, 30, 17, (r6040_phy_read(ioaddr, 30, 17) | 0x4000));
+	r6040_phy_write(ioaddr, 30, 17, ~((~r6040_phy_read(ioaddr, 30, 17)) | 0x2000));
+	r6040_phy_write(ioaddr, 0, 19, 0x0000);
+	r6040_phy_write(ioaddr, 0, 30, 0x01F0);
 
-	/* Interrupt Mask Register */
-	iowrite16(INT_MASK, ioaddr + MIER);
+	/* Initialize all MAC registers */
+	r6040_init_mac_regs(dev);
+
+	return 0;
 }
 
 /*
@@ -721,7 +781,7 @@
 
 	/* Polling PHY Chip Status */
 	if (PHY_MODE == 0x3100)
-		phy_mode = phy_mode_chk(dev);
+		phy_mode = r6040_phy_mode_chk(dev);
 	else
 		phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0;
 
@@ -784,7 +844,14 @@
 		return -ENOMEM;
 	}
 
-	r6040_up(dev);
+	ret = r6040_up(dev);
+	if (ret) {
+		pci_free_consistent(lp->pdev, TX_DESC_SIZE, lp->tx_ring,
+							lp->tx_ring_dma);
+		pci_free_consistent(lp->pdev, RX_DESC_SIZE, lp->rx_ring,
+							lp->rx_ring_dma);
+		return ret;
+	}
 
 	napi_enable(&lp->napi);
 	netif_start_queue(dev);
@@ -830,7 +897,7 @@
 	descptr->skb_ptr = skb;
 	descptr->buf = cpu_to_le32(pci_map_single(lp->pdev,
 		skb->data, skb->len, PCI_DMA_TODEVICE));
-	descptr->status = 0x8000;
+	descptr->status = DSC_OWNER_MAC;
 	/* Trigger the MAC to check the TX descriptor */
 	iowrite16(0x01, ioaddr + MTPR);
 	lp->tx_insert_ptr = descptr->vndescp;
@@ -987,24 +1054,27 @@
 
 	err = pci_enable_device(pdev);
 	if (err)
-		return err;
+		goto err_out;
 
 	/* this should always be supported */
-	if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+	err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+	if (err) {
 		printk(KERN_ERR DRV_NAME "32-bit PCI DMA addresses"
 				"not supported by the card\n");
-		return -ENODEV;
+		goto err_out;
 	}
-	if (pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
+	err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+	if (err) {
 		printk(KERN_ERR DRV_NAME "32-bit PCI DMA addresses"
 				"not supported by the card\n");
-		return -ENODEV;
+		goto err_out;
 	}
 
 	/* IO Size check */
 	if (pci_resource_len(pdev, 0) < io_size) {
-		printk(KERN_ERR "Insufficient PCI resources, aborting\n");
-		return -EIO;
+		printk(KERN_ERR DRV_NAME "Insufficient PCI resources, aborting\n");
+		err = -EIO;
+		goto err_out;
 	}
 
 	pioaddr = pci_resource_start(pdev, 0);	/* IO map base address */
@@ -1012,24 +1082,26 @@
 
 	dev = alloc_etherdev(sizeof(struct r6040_private));
 	if (!dev) {
-		printk(KERN_ERR "Failed to allocate etherdev\n");
-		return -ENOMEM;
+		printk(KERN_ERR DRV_NAME "Failed to allocate etherdev\n");
+		err = -ENOMEM;
+		goto err_out;
 	}
 	SET_NETDEV_DEV(dev, &pdev->dev);
 	lp = netdev_priv(dev);
-	lp->pdev = pdev;
 
-	if (pci_request_regions(pdev, DRV_NAME)) {
+	err = pci_request_regions(pdev, DRV_NAME);
+
+	if (err) {
 		printk(KERN_ERR DRV_NAME ": Failed to request PCI regions\n");
-		err = -ENODEV;
-		goto err_out_disable;
+		goto err_out_free_dev;
 	}
 
 	ioaddr = pci_iomap(pdev, bar, io_size);
 	if (!ioaddr) {
 		printk(KERN_ERR "ioremap failed for device %s\n",
 			pci_name(pdev));
-		return -EIO;
+		err = -EIO;
+		goto err_out_free_res;
 	}
 
 	/* Init system & device */
@@ -1049,6 +1121,7 @@
 
 	/* Link new device into r6040_root_dev */
 	lp->pdev = pdev;
+	lp->dev = dev;
 
 	/* Init RDC private data */
 	lp->mcr0 = 0x1002;
@@ -1070,8 +1143,8 @@
 #endif
 	netif_napi_add(dev, &lp->napi, r6040_poll, 64);
 	lp->mii_if.dev = dev;
-	lp->mii_if.mdio_read = mdio_read;
-	lp->mii_if.mdio_write = mdio_write;
+	lp->mii_if.mdio_read = r6040_mdio_read;
+	lp->mii_if.mdio_write = r6040_mdio_write;
 	lp->mii_if.phy_id = lp->phy_addr;
 	lp->mii_if.phy_id_mask = 0x1f;
 	lp->mii_if.reg_num_mask = 0x1f;
@@ -1080,17 +1153,17 @@
 	err = register_netdev(dev);
 	if (err) {
 		printk(KERN_ERR DRV_NAME ": Failed to register net device\n");
-		goto err_out_res;
+		goto err_out_unmap;
 	}
 	return 0;
 
-err_out_res:
+err_out_unmap:
+	pci_iounmap(pdev, ioaddr);
+err_out_free_res:
 	pci_release_regions(pdev);
-err_out_disable:
-	pci_disable_device(pdev);
-	pci_set_drvdata(pdev, NULL);
+err_out_free_dev:
 	free_netdev(dev);
-
+err_out:
 	return err;
 }
 
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index cfe8829..a3e3895 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -1418,8 +1418,10 @@
 
 	rtl_hw_phy_config(dev);
 
-	dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
-	RTL_W8(0x82, 0x01);
+	if (tp->mac_version <= RTL_GIGA_MAC_VER_06) {
+		dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
+		RTL_W8(0x82, 0x01);
+	}
 
 	pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
 
@@ -3032,13 +3034,7 @@
 	tmp = rtl8169_rx_config | rx_mode |
 	      (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
 
-	if ((tp->mac_version == RTL_GIGA_MAC_VER_11) ||
-	    (tp->mac_version == RTL_GIGA_MAC_VER_12) ||
-	    (tp->mac_version == RTL_GIGA_MAC_VER_13) ||
-	    (tp->mac_version == RTL_GIGA_MAC_VER_14) ||
-	    (tp->mac_version == RTL_GIGA_MAC_VER_15) ||
-	    (tp->mac_version == RTL_GIGA_MAC_VER_16) ||
-	    (tp->mac_version == RTL_GIGA_MAC_VER_17)) {
+	if (tp->mac_version > RTL_GIGA_MAC_VER_06) {
 		u32 data = mc_filter[0];
 
 		mc_filter[0] = swab32(mc_filter[1]);
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 7b2015f..45c72ee 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -19,6 +19,7 @@
 #include <linux/in.h>
 #include <linux/crc32.h>
 #include <linux/ethtool.h>
+#include <linux/topology.h>
 #include "net_driver.h"
 #include "gmii.h"
 #include "ethtool.h"
@@ -832,7 +833,23 @@
 	if (efx->interrupt_mode == EFX_INT_MODE_MSIX) {
 		BUG_ON(!pci_find_capability(efx->pci_dev, PCI_CAP_ID_MSIX));
 
-		efx->rss_queues = rss_cpus ? rss_cpus : num_online_cpus();
+		if (rss_cpus == 0) {
+			cpumask_t core_mask;
+			int cpu;
+
+			cpus_clear(core_mask);
+			efx->rss_queues = 0;
+			for_each_online_cpu(cpu) {
+				if (!cpu_isset(cpu, core_mask)) {
+					++efx->rss_queues;
+					cpus_or(core_mask, core_mask,
+						topology_core_siblings(cpu));
+				}
+			}
+		} else {
+			efx->rss_queues = rss_cpus;
+		}
+
 		efx->rss_queues = min(efx->rss_queues, max_channel + 1);
 		efx->rss_queues = min(efx->rss_queues, EFX_MAX_CHANNELS);
 
@@ -1762,7 +1779,7 @@
 
 	efx->reset_pending = method;
 
-	queue_work(efx->workqueue, &efx->reset_work);
+	queue_work(efx->reset_workqueue, &efx->reset_work);
 }
 
 /**************************************************************************
@@ -1907,14 +1924,28 @@
 		goto fail1;
 	}
 
+	efx->reset_workqueue = create_singlethread_workqueue("sfc_reset");
+	if (!efx->reset_workqueue) {
+		rc = -ENOMEM;
+		goto fail2;
+	}
+
 	return 0;
 
+ fail2:
+	destroy_workqueue(efx->workqueue);
+	efx->workqueue = NULL;
+
  fail1:
 	return rc;
 }
 
 static void efx_fini_struct(struct efx_nic *efx)
 {
+	if (efx->reset_workqueue) {
+		destroy_workqueue(efx->reset_workqueue);
+		efx->reset_workqueue = NULL;
+	}
 	if (efx->workqueue) {
 		destroy_workqueue(efx->workqueue);
 		efx->workqueue = NULL;
@@ -1977,7 +2008,7 @@
 	 * scheduled from this point because efx_stop_all() has been
 	 * called, we are no longer registered with driverlink, and
 	 * the net_device's have been removed. */
-	flush_workqueue(efx->workqueue);
+	flush_workqueue(efx->reset_workqueue);
 
 	efx_pci_remove_main(efx);
 
@@ -2098,7 +2129,7 @@
 		 * scheduled since efx_stop_all() has been called, and we
 		 * have not and never have been registered with either
 		 * the rtnetlink or driverlink layers. */
-		cancel_work_sync(&efx->reset_work);
+		flush_workqueue(efx->reset_workqueue);
 
 		/* Retry if a recoverably reset event has been scheduled */
 		if ((efx->reset_pending != RESET_TYPE_INVISIBLE) &&
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index 630406e..9138ee5 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -223,13 +223,8 @@
 	.getsda		= falcon_getsda,
 	.getscl		= falcon_getscl,
 	.udelay		= 5,
-	/*
-	 * This is the number of system clock ticks after which
-	 * i2c-algo-bit gives up waiting for SCL to become high.
-	 * It must be at least 2 since the first tick can happen
-	 * immediately after it starts waiting.
-	 */
-	.timeout	= 2,
+	/* Wait up to 50 ms for slave to let us pull SCL high */
+	.timeout	= DIV_ROUND_UP(HZ, 20),
 };
 
 /**************************************************************************
@@ -2479,12 +2474,11 @@
 
 	/* Initialise I2C adapter */
  	efx->i2c_adap.owner = THIS_MODULE;
- 	efx->i2c_adap.class = I2C_CLASS_HWMON;
 	nic_data->i2c_data = falcon_i2c_bit_operations;
 	nic_data->i2c_data.data = efx;
  	efx->i2c_adap.algo_data = &nic_data->i2c_data;
 	efx->i2c_adap.dev.parent = &efx->pci_dev->dev;
-	strcpy(efx->i2c_adap.name, "SFC4000 GPIO");
+	strlcpy(efx->i2c_adap.name, "SFC4000 GPIO", sizeof(efx->i2c_adap.name));
 	rc = i2c_bit_add_bus(&efx->i2c_adap);
 	if (rc)
 		goto fail5;
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index d803b86..219c74a 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -616,7 +616,9 @@
  * @pci_dev: The PCI device
  * @type: Controller type attributes
  * @legacy_irq: IRQ number
- * @workqueue: Workqueue for resets, port reconfigures and the HW monitor
+ * @workqueue: Workqueue for port reconfigures and the HW monitor.
+ *	Work items do not hold and must not acquire RTNL.
+ * @reset_workqueue: Workqueue for resets.  Work item will acquire RTNL.
  * @reset_work: Scheduled reset workitem
  * @monitor_work: Hardware monitor workitem
  * @membase_phys: Memory BAR value as physical address
@@ -684,6 +686,7 @@
 	const struct efx_nic_type *type;
 	int legacy_irq;
 	struct workqueue_struct *workqueue;
+	struct workqueue_struct *reset_workqueue;
 	struct work_struct reset_work;
 	struct delayed_work monitor_work;
 	resource_size_t membase_phys;
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index a4bc812..c69ba13 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -642,17 +642,12 @@
 					| ECMR_DM, ioaddr + ECMR);
 			new_state = 1;
 			mdp->link = phydev->link;
-			netif_tx_schedule_all(ndev);
-			netif_carrier_on(ndev);
-			netif_start_queue(ndev);
 		}
 	} else if (mdp->link) {
 		new_state = 1;
 		mdp->link = PHY_DOWN;
 		mdp->speed = 0;
 		mdp->duplex = -1;
-		netif_stop_queue(ndev);
-		netif_carrier_off(ndev);
 	}
 
 	if (new_state)
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index f2051b2..2040965 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -308,7 +308,7 @@
 	 * can't handle it then there will be no recovery except for
 	 * a hard reset or power cycle
 	 */
-	if (nowait)
+	if (lp->cfg.flags & SMC91X_NOWAIT)
 		cfg |= CONFIG_NO_WAIT;
 
 	/*
@@ -1939,8 +1939,11 @@
       	if (retval)
       		goto err_out;
 
-#ifdef SMC_USE_PXA_DMA
-	{
+#ifdef CONFIG_ARCH_PXA
+#  ifdef SMC_USE_PXA_DMA
+	lp->cfg.flags |= SMC91X_USE_DMA;
+#  endif
+	if (lp->cfg.flags & SMC91X_USE_DMA) {
 		int dma = pxa_request_dma(dev->name, DMA_PRIO_LOW,
 					  smc_pxa_dma_irq, NULL);
 		if (dma >= 0)
@@ -1980,7 +1983,7 @@
 	}
 
 err_out:
-#ifdef SMC_USE_PXA_DMA
+#ifdef CONFIG_ARCH_PXA
 	if (retval && dev->dma != (unsigned char)-1)
 		pxa_free_dma(dev->dma);
 #endif
@@ -2050,9 +2053,11 @@
 	return 0;
 }
 
-static int smc_request_attrib(struct platform_device *pdev)
+static int smc_request_attrib(struct platform_device *pdev,
+			      struct net_device *ndev)
 {
 	struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+	struct smc_local *lp = netdev_priv(ndev);
 
 	if (!res)
 		return 0;
@@ -2063,9 +2068,11 @@
 	return 0;
 }
 
-static void smc_release_attrib(struct platform_device *pdev)
+static void smc_release_attrib(struct platform_device *pdev,
+			       struct net_device *ndev)
 {
 	struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+	struct smc_local *lp = netdev_priv(ndev);
 
 	if (res)
 		release_mem_region(res->start, ATTRIB_SIZE);
@@ -2123,27 +2130,14 @@
 	struct net_device *ndev;
 	struct resource *res, *ires;
 	unsigned int __iomem *addr;
+	unsigned long irq_flags = SMC_IRQ_FLAGS;
 	int ret;
 
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
-	if (!res)
-		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		ret = -ENODEV;
-		goto out;
-	}
-
-
-	if (!request_mem_region(res->start, SMC_IO_EXTENT, CARDNAME)) {
-		ret = -EBUSY;
-		goto out;
-	}
-
 	ndev = alloc_etherdev(sizeof(struct smc_local));
 	if (!ndev) {
 		printk("%s: could not allocate device.\n", CARDNAME);
 		ret = -ENOMEM;
-		goto out_release_io;
+		goto out;
 	}
 	SET_NETDEV_DEV(ndev, &pdev->dev);
 
@@ -2152,37 +2146,47 @@
 	 */
 
 	lp = netdev_priv(ndev);
-	lp->cfg.irq_flags = SMC_IRQ_FLAGS;
 
-#ifdef SMC_DYNAMIC_BUS_CONFIG
-	if (pd)
+	if (pd) {
 		memcpy(&lp->cfg, pd, sizeof(lp->cfg));
-	else {
-		lp->cfg.flags = SMC91X_USE_8BIT;
-		lp->cfg.flags |= SMC91X_USE_16BIT;
-		lp->cfg.flags |= SMC91X_USE_32BIT;
+		lp->io_shift = SMC91X_IO_SHIFT(lp->cfg.flags);
+	} else {
+		lp->cfg.flags |= (SMC_CAN_USE_8BIT)  ? SMC91X_USE_8BIT  : 0;
+		lp->cfg.flags |= (SMC_CAN_USE_16BIT) ? SMC91X_USE_16BIT : 0;
+		lp->cfg.flags |= (SMC_CAN_USE_32BIT) ? SMC91X_USE_32BIT : 0;
+		lp->cfg.flags |= (nowait) ? SMC91X_NOWAIT : 0;
 	}
 
-	lp->cfg.flags &= ~(SMC_CAN_USE_8BIT ? 0 : SMC91X_USE_8BIT);
-	lp->cfg.flags &= ~(SMC_CAN_USE_16BIT ? 0 : SMC91X_USE_16BIT);
-	lp->cfg.flags &= ~(SMC_CAN_USE_32BIT ? 0 : SMC91X_USE_32BIT);
-#endif
-
 	ndev->dma = (unsigned char)-1;
 
-	ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!ires) {
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
+	if (!res)
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
 		ret = -ENODEV;
 		goto out_free_netdev;
 	}
 
-	ndev->irq = ires->start;
-	if (SMC_IRQ_FLAGS == -1)
-		lp->cfg.irq_flags = ires->flags & IRQF_TRIGGER_MASK;
 
-	ret = smc_request_attrib(pdev);
-	if (ret)
+	if (!request_mem_region(res->start, SMC_IO_EXTENT, CARDNAME)) {
+		ret = -EBUSY;
 		goto out_free_netdev;
+	}
+
+	ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!ires) {
+		ret = -ENODEV;
+		goto out_release_io;
+	}
+
+	ndev->irq = ires->start;
+
+	if (ires->flags & IRQF_TRIGGER_MASK)
+		irq_flags = ires->flags & IRQF_TRIGGER_MASK;
+
+	ret = smc_request_attrib(pdev, ndev);
+	if (ret)
+		goto out_release_io;
 #if defined(CONFIG_SA1100_ASSABET)
 	NCR_0 |= NCR_ENET_OSC_EN;
 #endif
@@ -2197,7 +2201,7 @@
 		goto out_release_attrib;
 	}
 
-#ifdef SMC_USE_PXA_DMA
+#ifdef CONFIG_ARCH_PXA
 	{
 		struct smc_local *lp = netdev_priv(ndev);
 		lp->device = &pdev->dev;
@@ -2205,7 +2209,7 @@
 	}
 #endif
 
-	ret = smc_probe(ndev, addr, lp->cfg.irq_flags);
+	ret = smc_probe(ndev, addr, irq_flags);
 	if (ret != 0)
 		goto out_iounmap;
 
@@ -2217,11 +2221,11 @@
 	platform_set_drvdata(pdev, NULL);
 	iounmap(addr);
  out_release_attrib:
-	smc_release_attrib(pdev);
- out_free_netdev:
-	free_netdev(ndev);
+	smc_release_attrib(pdev, ndev);
  out_release_io:
 	release_mem_region(res->start, SMC_IO_EXTENT);
+ out_free_netdev:
+	free_netdev(ndev);
  out:
 	printk("%s: not found (%d).\n", CARDNAME, ret);
 
@@ -2240,14 +2244,14 @@
 
 	free_irq(ndev->irq, ndev);
 
-#ifdef SMC_USE_PXA_DMA
+#ifdef CONFIG_ARCH_PXA
 	if (ndev->dma != (unsigned char)-1)
 		pxa_free_dma(ndev->dma);
 #endif
 	iounmap(lp->base);
 
 	smc_release_datacs(pdev,ndev);
-	smc_release_attrib(pdev);
+	smc_release_attrib(pdev,ndev);
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
 	if (!res)
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index 86068186..22209b6 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -40,23 +40,46 @@
  * Define your architecture specific bus configuration parameters here.
  */
 
-#if	defined(CONFIG_ARCH_LUBBOCK)
+#if defined(CONFIG_ARCH_LUBBOCK) ||\
+    defined(CONFIG_MACH_MAINSTONE) ||\
+    defined(CONFIG_MACH_ZYLONITE) ||\
+    defined(CONFIG_MACH_LITTLETON)
 
-/* We can only do 16-bit reads and writes in the static memory space. */
-#define SMC_CAN_USE_8BIT	0
+#include <asm/mach-types.h>
+
+/* Now the bus width is specified in the platform data
+ * pretend here to support all I/O access types
+ */
+#define SMC_CAN_USE_8BIT	1
 #define SMC_CAN_USE_16BIT	1
-#define SMC_CAN_USE_32BIT	0
+#define SMC_CAN_USE_32BIT	1
 #define SMC_NOWAIT		1
 
-/* The first two address lines aren't connected... */
-#define SMC_IO_SHIFT		2
+#define SMC_IO_SHIFT		(lp->io_shift)
 
+#define SMC_inb(a, r)		readb((a) + (r))
 #define SMC_inw(a, r)		readw((a) + (r))
-#define SMC_outw(v, a, r)	writew(v, (a) + (r))
+#define SMC_inl(a, r)		readl((a) + (r))
+#define SMC_outb(v, a, r)	writeb(v, (a) + (r))
+#define SMC_outl(v, a, r)	writel(v, (a) + (r))
 #define SMC_insw(a, r, p, l)	readsw((a) + (r), p, l)
 #define SMC_outsw(a, r, p, l)	writesw((a) + (r), p, l)
+#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		(-1)	/* from resource */
 
+/* We actually can't write halfwords properly if not word aligned */
+static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg)
+{
+	if (machine_is_mainstone() && reg & 2) {
+		unsigned int v = val << 16;
+		v |= readl(ioaddr + (reg & ~2)) & 0xffff;
+		writel(v, ioaddr + (reg & ~2));
+	} else {
+		writew(val, ioaddr + reg);
+	}
+}
+
 #elif defined(CONFIG_BLACKFIN)
 
 #define SMC_IRQ_FLAGS		IRQF_TRIGGER_HIGH
@@ -195,7 +218,6 @@
 #define SMC_outsw(a, r, p, l)	writesw((a) + (r), p, l)
 
 #elif	defined(CONFIG_ARCH_INNOKOM) || \
-	defined(CONFIG_MACH_MAINSTONE) || \
 	defined(CONFIG_ARCH_PXA_IDP) || \
 	defined(CONFIG_ARCH_RAMSES) || \
 	defined(CONFIG_ARCH_PCM027)
@@ -229,22 +251,6 @@
 	}
 }
 
-#elif defined(CONFIG_MACH_ZYLONITE)
-
-#define SMC_CAN_USE_8BIT        1
-#define SMC_CAN_USE_16BIT       1
-#define SMC_CAN_USE_32BIT       0
-#define SMC_IO_SHIFT            0
-#define SMC_NOWAIT              1
-#define SMC_USE_PXA_DMA		1
-#define SMC_inb(a, r)           readb((a) + (r))
-#define SMC_inw(a, r)           readw((a) + (r))
-#define SMC_insw(a, r, p, l)    insw((a) + (r), p, l)
-#define SMC_outsw(a, r, p, l)   outsw((a) + (r), p, l)
-#define SMC_outb(v, a, r)       writeb(v, (a) + (r))
-#define SMC_outw(v, a, r)       writew(v, (a) + (r))
-#define SMC_IRQ_FLAGS		(-1)	/* from resource */
-
 #elif	defined(CONFIG_ARCH_OMAP)
 
 /* We can only do 16-bit reads and writes in the static memory space. */
@@ -454,7 +460,6 @@
 #define RPC_LSA_DEFAULT		RPC_LED_100_10
 #define RPC_LSB_DEFAULT		RPC_LED_TX_RX
 
-#define SMC_DYNAMIC_BUS_CONFIG
 #endif
 
 
@@ -493,7 +498,7 @@
 
 	spinlock_t lock;
 
-#ifdef SMC_USE_PXA_DMA
+#ifdef CONFIG_ARCH_PXA
 	/* DMA needs the physical address of the chip */
 	u_long physaddr;
 	struct device *device;
@@ -501,20 +506,17 @@
 	void __iomem *base;
 	void __iomem *datacs;
 
+	/* the low address lines on some platforms aren't connected... */
+	int	io_shift;
+
 	struct smc91x_platdata cfg;
 };
 
-#ifdef SMC_DYNAMIC_BUS_CONFIG
-#define SMC_8BIT(p) (((p)->cfg.flags & SMC91X_USE_8BIT) && SMC_CAN_USE_8BIT)
-#define SMC_16BIT(p) (((p)->cfg.flags & SMC91X_USE_16BIT) && SMC_CAN_USE_16BIT)
-#define SMC_32BIT(p) (((p)->cfg.flags & SMC91X_USE_32BIT) && SMC_CAN_USE_32BIT)
-#else
-#define SMC_8BIT(p) SMC_CAN_USE_8BIT
-#define SMC_16BIT(p) SMC_CAN_USE_16BIT
-#define SMC_32BIT(p) SMC_CAN_USE_32BIT
-#endif
+#define SMC_8BIT(p)	((p)->cfg.flags & SMC91X_USE_8BIT)
+#define SMC_16BIT(p)	((p)->cfg.flags & SMC91X_USE_16BIT)
+#define SMC_32BIT(p)	((p)->cfg.flags & SMC91X_USE_32BIT)
 
-#ifdef SMC_USE_PXA_DMA
+#ifdef CONFIG_ARCH_PXA
 /*
  * Let's use the DMA engine on the XScale PXA2xx for RX packets. This is
  * always happening in irq context so no need to worry about races.  TX is
@@ -608,7 +610,7 @@
 {
 	DCSR(dma) = 0;
 }
-#endif  /* SMC_USE_PXA_DMA */
+#endif  /* CONFIG_ARCH_PXA */
 
 
 /*
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index 1aa425b..b79d5f0 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -2377,8 +2377,6 @@
 
 	spin_lock_irq(&hp->happy_lock);
 
-	netif_stop_queue(dev);
-
 	if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) {
 		hme_write32(hp, bregs + BMAC_HTABLE0, 0xffff);
 		hme_write32(hp, bregs + BMAC_HTABLE1, 0xffff);
@@ -2410,8 +2408,6 @@
 		hme_write32(hp, bregs + BMAC_HTABLE3, hash_table[3]);
 	}
 
-	netif_wake_queue(dev);
-
 	spin_unlock_irq(&hp->happy_lock);
 }
 
diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c
index 41d3ac4..a645e50 100644
--- a/drivers/net/tc35815.c
+++ b/drivers/net/tc35815.c
@@ -672,7 +672,6 @@
 			if (dev->flags & IFF_PROMISC)
 				tc35815_set_multicast_list(dev);
 #endif
-			netif_tx_schedule_all(dev);
 		} else {
 			lp->speed = 0;
 			lp->duplex = -1;
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index bc30c6e..617ef41 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -5514,22 +5514,6 @@
 	netif_wake_queue(dev);                      /* Unlock the TX ring */
 	break;
 
-    case DE4X5_SET_PROM:             /* Set Promiscuous Mode */
-	if (!capable(CAP_NET_ADMIN)) return -EPERM;
-	omr = inl(DE4X5_OMR);
-	omr |= OMR_PR;
-	outl(omr, DE4X5_OMR);
-	dev->flags |= IFF_PROMISC;
-	break;
-
-    case DE4X5_CLR_PROM:             /* Clear Promiscuous Mode */
-	if (!capable(CAP_NET_ADMIN)) return -EPERM;
-	omr = inl(DE4X5_OMR);
-	omr &= ~OMR_PR;
-	outl(omr, DE4X5_OMR);
-	dev->flags &= ~IFF_PROMISC;
-	break;
-
     case DE4X5_SAY_BOO:              /* Say "Boo!" to the kernel log file */
 	if (!capable(CAP_NET_ADMIN)) return -EPERM;
 	printk("%s: Boo!\n", dev->name);
diff --git a/drivers/net/tulip/de4x5.h b/drivers/net/tulip/de4x5.h
index f5f33b3..9f28774 100644
--- a/drivers/net/tulip/de4x5.h
+++ b/drivers/net/tulip/de4x5.h
@@ -1004,8 +1004,7 @@
 */
 #define DE4X5_GET_HWADDR	0x01 /* Get the hardware address */
 #define DE4X5_SET_HWADDR	0x02 /* Set the hardware address */
-#define DE4X5_SET_PROM  	0x03 /* Set Promiscuous Mode */
-#define DE4X5_CLR_PROM  	0x04 /* Clear Promiscuous Mode */
+/* 0x03 and 0x04 were used before and are obsoleted now. Don't use them. */
 #define DE4X5_SAY_BOO	        0x05 /* Say "Boo!" to the kernel log file */
 #define DE4X5_GET_MCA   	0x06 /* Get a multicast address */
 #define DE4X5_SET_MCA   	0x07 /* Set a multicast address */
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index a82b32b..e6bbc63 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -900,7 +900,7 @@
 		if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
 			return -EINVAL;
 		rtnl_lock();
-		ret = update_filter(&tun->txflt, (void *) __user arg);
+		ret = update_filter(&tun->txflt, (void __user *)arg);
 		rtnl_unlock();
 		return ret;
 
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 756ba10..8f944e5 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -1588,7 +1588,6 @@
 		if (!ugeth->oldlink) {
 			new_state = 1;
 			ugeth->oldlink = 1;
-			netif_tx_schedule_all(dev);
 		}
 	} else if (ugeth->oldlink) {
 			new_state = 1;
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index a934428..0e061df 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -50,10 +50,18 @@
 		&& desc->bInterfaceProtocol == 1;
 }
 
+static int is_wireless_rndis(struct usb_interface_descriptor *desc)
+{
+	return desc->bInterfaceClass == USB_CLASS_WIRELESS_CONTROLLER
+		&& desc->bInterfaceSubClass == 1
+		&& desc->bInterfaceProtocol == 3;
+}
+
 #else
 
 #define is_rndis(desc)		0
 #define is_activesync(desc)	0
+#define is_wireless_rndis(desc)	0
 
 #endif
 
@@ -110,7 +118,8 @@
 	 * of cdc-acm, it'll fail RNDIS requests cleanly.
 	 */
 	rndis = is_rndis(&intf->cur_altsetting->desc)
-		|| is_activesync(&intf->cur_altsetting->desc);
+		|| is_activesync(&intf->cur_altsetting->desc)
+		|| is_wireless_rndis(&intf->cur_altsetting->desc);
 
 	memset(info, 0, sizeof *info);
 	info->control = intf;
diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c
index 61c98be..bcd858c 100644
--- a/drivers/net/usb/rndis_host.c
+++ b/drivers/net/usb/rndis_host.c
@@ -576,6 +576,10 @@
 	/* "ActiveSync" is an undocumented variant of RNDIS, used in WM5 */
 	USB_INTERFACE_INFO(USB_CLASS_MISC, 1, 1),
 	.driver_info = (unsigned long) &rndis_info,
+}, {
+	/* RNDIS for tethering */
+	USB_INTERFACE_INFO(USB_CLASS_WIRELESS_CONTROLLER, 1, 3),
+	.driver_info = (unsigned long) &rndis_info,
 },
 	{ },		// END
 };
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 5827324..f7d3349 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -397,9 +397,9 @@
 		err = PTR_ERR(cosa_class);
 		goto out_chrdev;
 	}
-	for (i=0; i<nr_cards; i++) {
-		device_create(cosa_class, NULL, MKDEV(cosa_major, i), "cosa%d", i);
-	}
+	for (i = 0; i < nr_cards; i++)
+		device_create_drvdata(cosa_class, NULL, MKDEV(cosa_major, i),
+				      NULL, "cosa%d", i);
 	err = 0;
 	goto out;
 	
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index 13d5882..3153fe9 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -3101,6 +3101,7 @@
  * This is a natural nesting, which needs a split lock type.
  */
 static struct lock_class_key hostap_netdev_xmit_lock_key;
+static struct lock_class_key hostap_netdev_addr_lock_key;
 
 static void prism2_set_lockdep_class_one(struct net_device *dev,
 					 struct netdev_queue *txq,
@@ -3112,6 +3113,8 @@
 
 static void prism2_set_lockdep_class(struct net_device *dev)
 {
+	lockdep_set_class(&dev->addr_list_lock,
+			  &hostap_netdev_addr_lock_key);
 	netdev_for_each_tx_queue(dev, prism2_set_lockdep_class_one, NULL);
 }
 
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 6e70460..1acfbcd 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -4972,8 +4972,7 @@
 	}
       done:
 	if ((ipw_tx_queue_space(q) > q->low_mark) &&
-	    (qindex >= 0) &&
-	    (priv->status & STATUS_ASSOCIATED) && netif_running(priv->net_dev))
+	    (qindex >= 0))
 		netif_wake_queue(priv->net_dev);
 	used = q->first_empty - q->last_used;
 	if (used < 0)
@@ -10154,14 +10153,8 @@
 
 static int ipw_net_open(struct net_device *dev)
 {
-	struct ipw_priv *priv = ieee80211_priv(dev);
 	IPW_DEBUG_INFO("dev->open\n");
-	/* we should be verifying the device is ready to be opened */
-	mutex_lock(&priv->mutex);
-	if (!(priv->status & STATUS_RF_KILL_MASK) &&
-	    (priv->status & STATUS_ASSOCIATED))
-		netif_start_queue(dev);
-	mutex_unlock(&priv->mutex);
+	netif_start_queue(dev);
 	return 0;
 }
 
@@ -10481,13 +10474,6 @@
 	IPW_DEBUG_TX("dev->xmit(%d bytes)\n", txb->payload_size);
 	spin_lock_irqsave(&priv->lock, flags);
 
-	if (!(priv->status & STATUS_ASSOCIATED)) {
-		IPW_DEBUG_INFO("Tx attempt while not associated.\n");
-		priv->ieee->stats.tx_carrier_errors++;
-		netif_stop_queue(dev);
-		goto fail_unlock;
-	}
-
 #ifdef CONFIG_IPW2200_PROMISCUOUS
 	if (rtap_iface && netif_running(priv->prom_net_dev))
 		ipw_handle_promiscuous_tx(priv, txb);
@@ -10499,10 +10485,6 @@
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return ret;
-
-      fail_unlock:
-	spin_unlock_irqrestore(&priv->lock, flags);
-	return 1;
 }
 
 static struct net_device_stats *ipw_net_get_stats(struct net_device *dev)
@@ -10703,13 +10685,6 @@
 	priv->last_packet_time = 0;
 
 	netif_carrier_on(priv->net_dev);
-	if (netif_queue_stopped(priv->net_dev)) {
-		IPW_DEBUG_NOTIF("waking queue\n");
-		netif_wake_queue(priv->net_dev);
-	} else {
-		IPW_DEBUG_NOTIF("starting queue\n");
-		netif_start_queue(priv->net_dev);
-	}
 
 	cancel_delayed_work(&priv->request_scan);
 	cancel_delayed_work(&priv->request_direct_scan);
@@ -10739,7 +10714,6 @@
 {
 	ipw_led_link_down(priv);
 	netif_carrier_off(priv->net_dev);
-	netif_stop_queue(priv->net_dev);
 	notify_wx_assoc_event(priv);
 
 	/* Cancel any queued work ... */
@@ -11419,7 +11393,6 @@
 	/* Clear all bits but the RF Kill */
 	priv->status &= STATUS_RF_KILL_MASK | STATUS_EXIT_PENDING;
 	netif_carrier_off(priv->net_dev);
-	netif_stop_queue(priv->net_dev);
 
 	ipw_stop_nic(priv);
 
@@ -11522,7 +11495,6 @@
 
 	IPW_DEBUG_INFO("prom dev->open\n");
 	netif_carrier_off(dev);
-	netif_stop_queue(dev);
 
 	if (priv->ieee->iw_mode != IW_MODE_MONITOR) {
 		priv->sys_config.accept_all_data_frames = 1;
@@ -11558,7 +11530,6 @@
 static int ipw_prom_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	IPW_DEBUG_INFO("prom dev->xmit\n");
-	netif_stop_queue(dev);
 	return -EOPNOTSUPP;
 }
 
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 913dc9f..5816230 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -364,8 +364,7 @@
 			struct mac80211_hwsim_data *data;
 			data = hwsim_radios[i]->priv;
 			ieee80211_unregister_hw(hwsim_radios[i]);
-			if (!IS_ERR(data->dev))
-				device_unregister(data->dev);
+			device_unregister(data->dev);
 			ieee80211_free_hw(hwsim_radios[i]);
 		}
 	}
@@ -437,7 +436,7 @@
 			       "mac80211_hwsim: device_create_drvdata "
 			       "failed (%ld)\n", PTR_ERR(data->dev));
 			err = -ENOMEM;
-			goto failed;
+			goto failed_drvdata;
 		}
 		data->dev->driver = &mac80211_hwsim_driver;
 
@@ -461,7 +460,7 @@
 		if (err < 0) {
 			printk(KERN_DEBUG "mac80211_hwsim: "
 			       "ieee80211_register_hw failed (%d)\n", err);
-			goto failed;
+			goto failed_hw;
 		}
 
 		printk(KERN_DEBUG "%s: hwaddr %s registered\n",
@@ -479,9 +478,9 @@
 	rtnl_lock();
 
 	err = dev_alloc_name(hwsim_mon, hwsim_mon->name);
-	if (err < 0) {
+	if (err < 0)
 		goto failed_mon;
-	}
+
 
 	err = register_netdevice(hwsim_mon);
 	if (err < 0)
@@ -494,7 +493,14 @@
 failed_mon:
 	rtnl_unlock();
 	free_netdev(hwsim_mon);
+	mac80211_hwsim_free();
+	return err;
 
+failed_hw:
+	device_unregister(data->dev);
+failed_drvdata:
+	ieee80211_free_hw(hw);
+	hwsim_radios[i] = 0;
 failed:
 	mac80211_hwsim_free();
 	return err;
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index ef671d1..902bbe7 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -92,7 +92,7 @@
 	 */
 	union skb_entry {
 		struct sk_buff *skb;
-		unsigned link;
+		unsigned long link;
 	} tx_skbs[NET_TX_RING_SIZE];
 	grant_ref_t gref_tx_head;
 	grant_ref_t grant_tx_ref[NET_TX_RING_SIZE];
@@ -125,6 +125,17 @@
 	struct xen_netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1];
 };
 
+static void skb_entry_set_link(union skb_entry *list, unsigned short id)
+{
+	list->link = id;
+}
+
+static int skb_entry_is_link(const union skb_entry *list)
+{
+	BUILD_BUG_ON(sizeof(list->skb) != sizeof(list->link));
+	return ((unsigned long)list->skb < PAGE_OFFSET);
+}
+
 /*
  * Access macros for acquiring freeing slots in tx_skbs[].
  */
@@ -132,7 +143,7 @@
 static void add_id_to_freelist(unsigned *head, union skb_entry *list,
 			       unsigned short id)
 {
-	list[id].link = *head;
+	skb_entry_set_link(&list[id], *head);
 	*head = id;
 }
 
@@ -993,7 +1004,7 @@
 
 	for (i = 0; i < NET_TX_RING_SIZE; i++) {
 		/* Skip over entries which are actually freelist references */
-		if ((unsigned long)np->tx_skbs[i].skb < PAGE_OFFSET)
+		if (skb_entry_is_link(&np->tx_skbs[i]))
 			continue;
 
 		skb = np->tx_skbs[i].skb;
@@ -1123,7 +1134,7 @@
 	/* Initialise tx_skbs as a free chain containing every entry. */
 	np->tx_skb_freelist = 0;
 	for (i = 0; i < NET_TX_RING_SIZE; i++) {
-		np->tx_skbs[i].link = i+1;
+		skb_entry_set_link(&np->tx_skbs[i], i+1);
 		np->grant_tx_ref[i] = GRANT_INVALID_REF;
 	}
 
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index eecf7cb..5a58b07 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -36,7 +36,7 @@
 #define _ACPIPHP_H
 
 #include <linux/acpi.h>
-#include <linux/kobject.h>	/* for KOBJ_NAME_LEN */
+#include <linux/kobject.h>
 #include <linux/mutex.h>
 #include <linux/pci_hotplug.h>
 
@@ -51,7 +51,7 @@
 #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
 
 /* name size which is used for entries in pcihpfs */
-#define SLOT_NAME_SIZE	KOBJ_NAME_LEN		/* {_SUN} */
+#define SLOT_NAME_SIZE	20		/* {_SUN} */
 
 struct acpiphp_bridge;
 struct acpiphp_slot;
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 3f7b81c..8d0e60a 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -37,7 +37,7 @@
 #include "intel-iommu.h"
 #include <asm/proto.h> /* force_iommu in this header in x86-64*/
 #include <asm/cacheflush.h>
-#include <asm/gart.h>
+#include <asm/iommu.h>
 #include "pci.h"
 
 #define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 44a46c9..d00f0e0 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1123,8 +1123,7 @@
 }
 
 /**
- * pci_prepare_to_sleep - prepare PCI device for system-wide transition into
- *                        a sleep state
+ * pci_prepare_to_sleep - prepare PCI device for system-wide transition into a sleep state
  * @dev: Device to handle.
  *
  * Choose the power state appropriate for the device depending on whether
@@ -1181,8 +1180,7 @@
 }
 
 /**
- * pci_back_from_sleep - turn PCI device on during system-wide transition into
- *                       the working state a sleep state
+ * pci_back_from_sleep - turn PCI device on during system-wide transition into working state
  * @dev: Device to handle.
  *
  * Disable device's sytem wake-up capability and put it into D0.
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index e45402a..e0f8840 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -219,7 +219,8 @@
 config PCMCIA_PXA2XX
 	tristate "PXA2xx support"
 	depends on ARM && ARCH_PXA && PCMCIA
-	depends on ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL || MACH_ARMCORE
+	depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \
+		    || MACH_ARMCORE || ARCH_PXA_PALM)
 	help
 	  Say Y here to include support for the PXA2xx PCMCIA controller
 
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index 85c6cc9..269a9e9 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -72,4 +72,5 @@
 pxa2xx_cs-$(CONFIG_MACH_MAINSTONE)		+= pxa2xx_mainstone.o
 pxa2xx_cs-$(CONFIG_PXA_SHARPSL)			+= pxa2xx_sharpsl.o
 pxa2xx_cs-$(CONFIG_MACH_ARMCORE)		+= pxa2xx_cm_x270.o
+pxa2xx_cs-$(CONFIG_MACH_PALMTX)		+= pxa2xx_palmtx.o
 
diff --git a/drivers/pcmcia/pxa2xx_cm_x270.c b/drivers/pcmcia/pxa2xx_cm_x270.c
index f123fce..bb95db7 100644
--- a/drivers/pcmcia/pxa2xx_cm_x270.c
+++ b/drivers/pcmcia/pxa2xx_cm_x270.c
@@ -5,83 +5,60 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * Compulab Ltd., 2003, 2007
+ * Compulab Ltd., 2003, 2007, 2008
  * Mike Rapoport <mike@compulab.co.il>
  *
  */
 
-#include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/platform_device.h>
 #include <linux/irq.h>
 #include <linux/delay.h>
+#include <linux/gpio.h>
 
-#include <pcmcia/ss.h>
-#include <asm/hardware.h>
 #include <asm/mach-types.h>
-
 #include <asm/arch/pxa-regs.h>
-#include <asm/arch/pxa2xx-gpio.h>
-#include <asm/arch/cm-x270.h>
 
 #include "soc_common.h"
 
+#define GPIO_PCMCIA_S0_CD_VALID	(84)
+#define GPIO_PCMCIA_S0_RDYINT	(82)
+#define GPIO_PCMCIA_RESET	(53)
+
+#define PCMCIA_S0_CD_VALID	IRQ_GPIO(GPIO_PCMCIA_S0_CD_VALID)
+#define PCMCIA_S0_RDYINT	IRQ_GPIO(GPIO_PCMCIA_S0_RDYINT)
+
+
 static struct pcmcia_irqs irqs[] = {
 	{ 0, PCMCIA_S0_CD_VALID, "PCMCIA0 CD" },
-	{ 1, PCMCIA_S1_CD_VALID, "PCMCIA1 CD" },
 };
 
 static int cmx270_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
-	GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) |
-		GPIO_bit(GPIO49_nPWE) |
-		GPIO_bit(GPIO50_nPIOR) |
-		GPIO_bit(GPIO51_nPIOW) |
-		GPIO_bit(GPIO85_nPCE_1) |
-		GPIO_bit(GPIO54_nPCE_2);
+	int ret = gpio_request(GPIO_PCMCIA_RESET, "PCCard reset");
+	if (ret)
+		return ret;
+	gpio_direction_output(GPIO_PCMCIA_RESET, 0);
 
-	pxa_gpio_mode(GPIO48_nPOE_MD);
-	pxa_gpio_mode(GPIO49_nPWE_MD);
-	pxa_gpio_mode(GPIO50_nPIOR_MD);
-	pxa_gpio_mode(GPIO51_nPIOW_MD);
-	pxa_gpio_mode(GPIO85_nPCE_1_MD);
-	pxa_gpio_mode(GPIO54_nPCE_2_MD);
-	pxa_gpio_mode(GPIO55_nPREG_MD);
-	pxa_gpio_mode(GPIO56_nPWAIT_MD);
-	pxa_gpio_mode(GPIO57_nIOIS16_MD);
+	skt->irq = PCMCIA_S0_RDYINT;
+	ret = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	if (!ret)
+		gpio_free(GPIO_PCMCIA_RESET);
 
-	/* Reset signal */
-	pxa_gpio_mode(GPIO53_nPCE_2 | GPIO_OUT);
-	GPCR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2);
-
-	set_irq_type(PCMCIA_S0_CD_VALID, IRQ_TYPE_EDGE_BOTH);
-	set_irq_type(PCMCIA_S1_CD_VALID, IRQ_TYPE_EDGE_BOTH);
-
-	/* irq's for slots: */
-	set_irq_type(PCMCIA_S0_RDYINT, IRQ_TYPE_EDGE_FALLING);
-	set_irq_type(PCMCIA_S1_RDYINT, IRQ_TYPE_EDGE_FALLING);
-
-	skt->irq = (skt->nr == 0) ? PCMCIA_S0_RDYINT : PCMCIA_S1_RDYINT;
-	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	return ret;
 }
 
 static void cmx270_pcmcia_shutdown(struct soc_pcmcia_socket *skt)
 {
 	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
-
-	set_irq_type(IRQ_TO_GPIO(PCMCIA_S0_CD_VALID), IRQ_TYPE_NONE);
-	set_irq_type(IRQ_TO_GPIO(PCMCIA_S1_CD_VALID), IRQ_TYPE_NONE);
-
-	set_irq_type(IRQ_TO_GPIO(PCMCIA_S0_RDYINT), IRQ_TYPE_NONE);
-	set_irq_type(IRQ_TO_GPIO(PCMCIA_S1_RDYINT), IRQ_TYPE_NONE);
+	gpio_free(GPIO_PCMCIA_RESET);
 }
 
 
 static void cmx270_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
 				       struct pcmcia_state *state)
 {
-	state->detect = (PCC_DETECT(skt->nr) == 0) ? 1 : 0;
-	state->ready  = (PCC_READY(skt->nr) == 0) ? 0 : 1;
+	state->detect = (gpio_get_value(GPIO_PCMCIA_S0_CD_VALID) == 0) ? 1 : 0;
+	state->ready  = (gpio_get_value(GPIO_PCMCIA_S0_RDYINT) == 0) ? 0 : 1;
 	state->bvd1   = 1;
 	state->bvd2   = 1;
 	state->vs_3v  = 0;
@@ -93,32 +70,16 @@
 static int cmx270_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
 					  const socket_state_t *state)
 {
-	GPSR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE);
-	pxa_gpio_mode(GPIO49_nPWE | GPIO_OUT);
-
 	switch (skt->nr) {
 	case 0:
 		if (state->flags & SS_RESET) {
-			GPCR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE);
-			GPSR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2);
+			gpio_set_value(GPIO_PCMCIA_RESET, 1);
 			udelay(10);
-			GPCR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2);
-			GPSR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE);
-		}
-		break;
-	case 1:
-		if (state->flags & SS_RESET) {
-			GPCR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE);
-			GPSR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2);
-			udelay(10);
-			GPCR(GPIO53_nPCE_2) = GPIO_bit(GPIO53_nPCE_2);
-			GPSR(GPIO49_nPWE) = GPIO_bit(GPIO49_nPWE);
+			gpio_set_value(GPIO_PCMCIA_RESET, 0);
 		}
 		break;
 	}
 
-	pxa_gpio_mode(GPIO49_nPWE_MD);
-
 	return 0;
 }
 
@@ -139,7 +100,7 @@
 	.configure_socket	= cmx270_pcmcia_configure_socket,
 	.socket_init		= cmx270_pcmcia_socket_init,
 	.socket_suspend		= cmx270_pcmcia_socket_suspend,
-	.nr			= 2,
+	.nr			= 1,
 };
 
 static struct platform_device *cmx270_pcmcia_device;
diff --git a/drivers/pcmcia/pxa2xx_palmtx.c b/drivers/pcmcia/pxa2xx_palmtx.c
new file mode 100644
index 0000000..4abde19
--- /dev/null
+++ b/drivers/pcmcia/pxa2xx_palmtx.c
@@ -0,0 +1,118 @@
+/*
+ * linux/drivers/pcmcia/pxa2xx_palmtx.c
+ *
+ * Driver for Palm T|X PCMCIA
+ *
+ * Copyright (C) 2007-2008 Marek Vasut <marek.vasut@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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/palmtx.h>
+
+#include "soc_common.h"
+
+static int palmtx_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+	skt->irq = IRQ_GPIO(GPIO_NR_PALMTX_PCMCIA_READY);
+	return 0;
+}
+
+static void palmtx_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
+{
+}
+
+static void palmtx_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
+					struct pcmcia_state *state)
+{
+	state->detect = 1; /* always inserted */
+	state->ready  = !!gpio_get_value(GPIO_NR_PALMTX_PCMCIA_READY);
+	state->bvd1   = 1;
+	state->bvd2   = 1;
+	state->wrprot = 0;
+	state->vs_3v  = 1;
+	state->vs_Xv  = 0;
+}
+
+static int
+palmtx_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
+				const socket_state_t *state)
+{
+	gpio_set_value(GPIO_NR_PALMTX_PCMCIA_POWER1, 1);
+	gpio_set_value(GPIO_NR_PALMTX_PCMCIA_POWER2, 1);
+	gpio_set_value(GPIO_NR_PALMTX_PCMCIA_RESET,
+			!!(state->flags & SS_RESET));
+
+	return 0;
+}
+
+static void palmtx_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
+{
+}
+
+static void palmtx_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
+{
+}
+
+static struct pcmcia_low_level palmtx_pcmcia_ops = {
+	.owner			= THIS_MODULE,
+
+	.first			= 0,
+	.nr			= 1,
+
+	.hw_init		= palmtx_pcmcia_hw_init,
+	.hw_shutdown		= palmtx_pcmcia_hw_shutdown,
+
+	.socket_state		= palmtx_pcmcia_socket_state,
+	.configure_socket	= palmtx_pcmcia_configure_socket,
+
+	.socket_init		= palmtx_pcmcia_socket_init,
+	.socket_suspend		= palmtx_pcmcia_socket_suspend,
+};
+
+static struct platform_device *palmtx_pcmcia_device;
+
+static int __init palmtx_pcmcia_init(void)
+{
+	int ret;
+
+	if (!machine_is_palmtx())
+		return -ENODEV;
+
+	palmtx_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
+	if (!palmtx_pcmcia_device)
+		return -ENOMEM;
+
+	ret = platform_device_add_data(palmtx_pcmcia_device, &palmtx_pcmcia_ops,
+					sizeof(palmtx_pcmcia_ops));
+
+	if (!ret)
+		ret = platform_device_add(palmtx_pcmcia_device);
+
+	if (ret)
+		platform_device_put(palmtx_pcmcia_device);
+
+	return ret;
+}
+
+static void __exit palmtx_pcmcia_exit(void)
+{
+	platform_device_unregister(palmtx_pcmcia_device);
+}
+
+fs_initcall(palmtx_pcmcia_init);
+module_exit(palmtx_pcmcia_exit);
+
+MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
+MODULE_DESCRIPTION("PCMCIA support for Palm T|X");
+MODULE_ALIAS("platform:pxa2xx-pcmcia");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 58c806e..4d17d38 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -49,4 +49,10 @@
 	help
 	  Say Y to enable support for the battery on the OLPC laptop.
 
+config BATTERY_PALMTX
+	tristate "Palm T|X battery"
+	depends on MACH_PALMTX
+	help
+	  Say Y to enable support for the battery in Palm T|X.
+
 endif # POWER_SUPPLY
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 6413ded..6f43a54 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -20,3 +20,4 @@
 obj-$(CONFIG_BATTERY_DS2760)	+= ds2760_battery.o
 obj-$(CONFIG_BATTERY_PMU)	+= pmu_battery.o
 obj-$(CONFIG_BATTERY_OLPC)	+= olpc_battery.o
+obj-$(CONFIG_BATTERY_PALMTX)	+= palmtx_battery.o
diff --git a/drivers/power/apm_power.c b/drivers/power/apm_power.c
index a489227..936bae5 100644
--- a/drivers/power/apm_power.c
+++ b/drivers/power/apm_power.c
@@ -78,7 +78,7 @@
 	main_battery = NULL;
 	bp.main = main_battery;
 
-	error = class_for_each_device(power_supply_class, &bp,
+	error = class_for_each_device(power_supply_class, NULL, &bp,
 				      __find_main_battery);
 	if (error) {
 		main_battery = bp.main;
diff --git a/drivers/power/palmtx_battery.c b/drivers/power/palmtx_battery.c
new file mode 100644
index 0000000..244bb27
--- /dev/null
+++ b/drivers/power/palmtx_battery.c
@@ -0,0 +1,198 @@
+/*
+ * linux/drivers/power/palmtx_battery.c
+ *
+ * Battery measurement code for Palm T|X Handheld computer
+ *
+ * based on tosa_battery.c
+ *
+ * Copyright (C) 2008 Marek Vasut <marek.vasut@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.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/power_supply.h>
+#include <linux/wm97xx.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+#include <asm/arch/palmtx.h>
+
+static DEFINE_MUTEX(bat_lock);
+static struct work_struct bat_work;
+struct mutex work_lock;
+int bat_status = POWER_SUPPLY_STATUS_DISCHARGING;
+
+static unsigned long palmtx_read_bat(struct power_supply *bat_ps)
+{
+	return wm97xx_read_aux_adc(bat_ps->dev->parent->driver_data,
+				    WM97XX_AUX_ID3) * 1000 / 414;
+}
+
+static unsigned long palmtx_read_temp(struct power_supply *bat_ps)
+{
+	return wm97xx_read_aux_adc(bat_ps->dev->parent->driver_data,
+				    WM97XX_AUX_ID2);
+}
+
+static int palmtx_bat_get_property(struct power_supply *bat_ps,
+			    enum power_supply_property psp,
+			    union power_supply_propval *val)
+{
+	switch (psp) {
+	case POWER_SUPPLY_PROP_STATUS:
+		val->intval = bat_status;
+		break;
+	case POWER_SUPPLY_PROP_TECHNOLOGY:
+		val->intval = POWER_SUPPLY_TECHNOLOGY_LIPO;
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		val->intval = palmtx_read_bat(bat_ps);
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+		val->intval = PALMTX_BAT_MAX_VOLTAGE;
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+		val->intval = PALMTX_BAT_MIN_VOLTAGE;
+		break;
+	case POWER_SUPPLY_PROP_TEMP:
+		val->intval = palmtx_read_temp(bat_ps);
+		break;
+	case POWER_SUPPLY_PROP_PRESENT:
+		val->intval = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void palmtx_bat_external_power_changed(struct power_supply *bat_ps)
+{
+	schedule_work(&bat_work);
+}
+
+static char *status_text[] = {
+	[POWER_SUPPLY_STATUS_UNKNOWN] =		"Unknown",
+	[POWER_SUPPLY_STATUS_CHARGING] =	"Charging",
+	[POWER_SUPPLY_STATUS_DISCHARGING] =	"Discharging",
+};
+
+static void palmtx_bat_update(struct power_supply *bat_ps)
+{
+	int old_status = bat_status;
+
+	mutex_lock(&work_lock);
+
+	bat_status = gpio_get_value(GPIO_NR_PALMTX_POWER_DETECT) ?
+				    POWER_SUPPLY_STATUS_CHARGING :
+				    POWER_SUPPLY_STATUS_DISCHARGING;
+
+	if (old_status != bat_status) {
+		pr_debug("%s %s -> %s\n", bat_ps->name,
+				status_text[old_status],
+				status_text[bat_status]);
+		power_supply_changed(bat_ps);
+	}
+
+	mutex_unlock(&work_lock);
+}
+
+static enum power_supply_property palmtx_bat_main_props[] = {
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_TECHNOLOGY,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_VOLTAGE_MAX,
+	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+	POWER_SUPPLY_PROP_TEMP,
+	POWER_SUPPLY_PROP_PRESENT,
+};
+
+struct power_supply bat_ps = {
+	.name			= "main-battery",
+	.type			= POWER_SUPPLY_TYPE_BATTERY,
+	.properties		= palmtx_bat_main_props,
+	.num_properties		= ARRAY_SIZE(palmtx_bat_main_props),
+	.get_property		= palmtx_bat_get_property,
+	.external_power_changed = palmtx_bat_external_power_changed,
+	.use_for_apm		= 1,
+};
+
+static void palmtx_bat_work(struct work_struct *work)
+{
+	palmtx_bat_update(&bat_ps);
+}
+
+#ifdef CONFIG_PM
+static int palmtx_bat_suspend(struct platform_device *dev, pm_message_t state)
+{
+	flush_scheduled_work();
+	return 0;
+}
+
+static int palmtx_bat_resume(struct platform_device *dev)
+{
+	schedule_work(&bat_work);
+	return 0;
+}
+#else
+#define palmtx_bat_suspend NULL
+#define palmtx_bat_resume NULL
+#endif
+
+static int __devinit palmtx_bat_probe(struct platform_device *dev)
+{
+	int ret = 0;
+
+	if (!machine_is_palmtx())
+		return -ENODEV;
+
+	mutex_init(&work_lock);
+
+	INIT_WORK(&bat_work, palmtx_bat_work);
+
+	ret = power_supply_register(&dev->dev, &bat_ps);
+	if (!ret)
+		schedule_work(&bat_work);
+
+	return ret;
+}
+
+static int __devexit palmtx_bat_remove(struct platform_device *dev)
+{
+	power_supply_unregister(&bat_ps);
+	return 0;
+}
+
+static struct platform_driver palmtx_bat_driver = {
+	.driver.name	= "wm97xx-battery",
+	.driver.owner	= THIS_MODULE,
+	.probe		= palmtx_bat_probe,
+	.remove		= __devexit_p(palmtx_bat_remove),
+	.suspend	= palmtx_bat_suspend,
+	.resume		= palmtx_bat_resume,
+};
+
+static int __init palmtx_bat_init(void)
+{
+	return platform_driver_register(&palmtx_bat_driver);
+}
+
+static void __exit palmtx_bat_exit(void)
+{
+	platform_driver_unregister(&palmtx_bat_driver);
+}
+
+module_init(palmtx_bat_init);
+module_exit(palmtx_bat_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
+MODULE_DESCRIPTION("Palm T|X battery driver");
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index af1633e..cb1ccb4 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -41,7 +41,7 @@
 
 	dev_dbg(psy->dev, "%s\n", __func__);
 
-	class_for_each_device(power_supply_class, psy,
+	class_for_each_device(power_supply_class, NULL, psy,
 			      __power_supply_changed_work);
 
 	power_supply_update_leds(psy);
@@ -79,7 +79,7 @@
 {
 	int error;
 
-	error = class_for_each_device(power_supply_class, psy,
+	error = class_for_each_device(power_supply_class, NULL, psy,
 				      __power_supply_am_i_supplied);
 
 	dev_dbg(psy->dev, "%s %d\n", __func__, error);
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 58b7336..d397fa5f 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -345,7 +345,7 @@
 	struct device *dev;
 	struct rtc_device *rtc = NULL;
 
-	dev = class_find_device(rtc_class, name, __rtc_match);
+	dev = class_find_device(rtc_class, NULL, name, __rtc_match);
 	if (dev)
 		rtc = to_rtc_device(dev);
 
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 81a96e0..c3dee90 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -1168,17 +1168,19 @@
 	if (rc)
 		goto out;
 
-	rp->clttydev = device_create(class3270, &rp->cdev->dev,
-				     MKDEV(IBM_TTY3270_MAJOR, rp->minor),
-				     "tty%s", rp->cdev->dev.bus_id);
+	rp->clttydev = device_create_drvdata(class3270, &rp->cdev->dev,
+					     MKDEV(IBM_TTY3270_MAJOR, rp->minor),
+					     NULL,
+					     "tty%s", rp->cdev->dev.bus_id);
 	if (IS_ERR(rp->clttydev)) {
 		rc = PTR_ERR(rp->clttydev);
 		goto out_ttydev;
 	}
 
-	rp->cltubdev = device_create(class3270, &rp->cdev->dev,
-				     MKDEV(IBM_FS3270_MAJOR, rp->minor),
-				     "tub%s", rp->cdev->dev.bus_id);
+	rp->cltubdev = device_create_drvdata(class3270, &rp->cdev->dev,
+					     MKDEV(IBM_FS3270_MAJOR, rp->minor),
+					     NULL,
+					     "tub%s", rp->cdev->dev.bus_id);
 	if (!IS_ERR(rp->cltubdev))
 		goto out;
 
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
index 6dfdb7c..12c2a5a 100644
--- a/drivers/s390/char/tape_class.c
+++ b/drivers/s390/char/tape_class.c
@@ -69,10 +69,9 @@
 	if (rc)
 		goto fail_with_cdev;
 
-	tcd->class_device = device_create(tape_class, device,
-					  tcd->char_device->dev,
-					  "%s", tcd->device_name
-			);
+	tcd->class_device = device_create_drvdata(tape_class, device,
+						  tcd->char_device->dev,
+						  NULL, "%s", tcd->device_name);
 	rc = IS_ERR(tcd->class_device) ? PTR_ERR(tcd->class_device) : 0;
 	if (rc)
 		goto fail_with_cdev;
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index b0ac44b..c1f352b 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -896,8 +896,9 @@
 		goto fail_free_cdev;
 	}
 
-	urd->device = device_create(vmur_class, NULL, urd->char_device->dev,
-					"%s", node_id);
+	urd->device = device_create_drvdata(vmur_class, NULL,
+					    urd->char_device->dev, NULL,
+					    "%s", node_id);
 	if (IS_ERR(urd->device)) {
 		rc = PTR_ERR(urd->device);
 		TRACE("ur_set_online: device_create rc=%d\n", rc);
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index c644669..a08b168 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -58,13 +58,13 @@
  *    1.10  Changes for Buffer allocation
  *    1.15  Changed for 2.6 Kernel  No longer compiles on 2.4 or lower
  *    1.25  Added Packing support
+ *    1.5
  */
 #include <asm/ccwdev.h>
 #include <asm/ccwgroup.h>
 #include <asm/debug.h>
 #include <asm/idals.h>
 #include <asm/io.h>
-
 #include <linux/bitops.h>
 #include <linux/ctype.h>
 #include <linux/delay.h>
@@ -90,36 +90,10 @@
 #include "cu3088.h"
 #include "claw.h"
 
-MODULE_AUTHOR("Andy Richter <richtera@us.ibm.com>");
-MODULE_DESCRIPTION("Linux for zSeries CLAW Driver\n" \
-			"Copyright 2000,2005 IBM Corporation\n");
-MODULE_LICENSE("GPL");
-
-/* Debugging is based on DEBUGMSG, IOTRACE, or FUNCTRACE  options:
-   DEBUGMSG  - Enables output of various debug messages in the code
-   IOTRACE   - Enables output of CCW and other IO related traces
-   FUNCTRACE - Enables output of function entry/exit trace
-   Define any combination of above options to enable tracing
-
-   CLAW also uses the s390dbf file system  see claw_trace and claw_setup
+/*
+   CLAW uses the s390dbf file system  see claw_trace and claw_setup
 */
 
-/* following enables tracing */
-//#define DEBUGMSG
-//#define IOTRACE
-//#define FUNCTRACE
-
-#ifdef DEBUGMSG
-#define DEBUG
-#endif
-
-#ifdef IOTRACE
-#define DEBUG
-#endif
-
-#ifdef FUNCTRACE
-#define DEBUG
-#endif
 
 static char debug_buffer[255];
 /**
@@ -146,7 +120,6 @@
 	claw_dbf_setup = debug_register("claw_setup", 2, 1, 8);
 	claw_dbf_trace = debug_register("claw_trace", 2, 2, 8);
 	if (claw_dbf_setup == NULL || claw_dbf_trace == NULL) {
-		printk(KERN_WARNING "Not enough memory for debug facility.\n");
 		claw_unregister_debug_facility();
 		return -ENOMEM;
 	}
@@ -232,9 +205,6 @@
 static struct net_device_stats *claw_stats(struct net_device *dev);
 static int pages_to_order_of_mag(int num_of_pages);
 static struct sk_buff *claw_pack_skb(struct claw_privbk *privptr);
-#ifdef DEBUG
-static void dumpit (char *buf, int len);
-#endif
 /* sysfs Functions */
 static ssize_t claw_hname_show(struct device *dev, struct device_attribute *attr, char *buf);
 static ssize_t claw_hname_write(struct device *dev, struct device_attribute *attr,
@@ -263,12 +233,12 @@
 static int claw_snd_sys_validate_rsp(struct net_device *dev,
         struct clawctl * p_ctl, __u32 return_code);
 static int claw_strt_conn_req(struct net_device *dev );
-static void claw_strt_read ( struct net_device *dev, int lock );
-static void claw_strt_out_IO( struct net_device *dev );
-static void claw_free_wrt_buf( struct net_device *dev );
+static void claw_strt_read(struct net_device *dev, int lock);
+static void claw_strt_out_IO(struct net_device *dev);
+static void claw_free_wrt_buf(struct net_device *dev);
 
 /* Functions for unpack reads   */
-static void unpack_read (struct net_device *dev );
+static void unpack_read(struct net_device *dev);
 
 /* ccwgroup table  */
 
@@ -284,7 +254,6 @@
 };
 
 /*
-*
 *       Key functions
 */
 
@@ -298,23 +267,14 @@
 	int  		rc;
 	struct claw_privbk *privptr=NULL;
 
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s Enter\n",__func__);
-#endif
-	CLAW_DBF_TEXT(2,setup,"probe");
+	CLAW_DBF_TEXT(2, setup, "probe");
 	if (!get_device(&cgdev->dev))
 		return -ENODEV;
-#ifdef DEBUGMSG
-        printk(KERN_INFO "claw: variable cgdev =\n");
-        dumpit((char *)cgdev, sizeof(struct ccwgroup_device));
-#endif
 	privptr = kzalloc(sizeof(struct claw_privbk), GFP_KERNEL);
 	if (privptr == NULL) {
 		probe_error(cgdev);
 		put_device(&cgdev->dev);
-		printk(KERN_WARNING "Out of memory %s %s Exit Line %d \n",
-			cgdev->cdev[0]->dev.bus_id,__func__,__LINE__);
-		CLAW_DBF_TEXT_(2,setup,"probex%d",-ENOMEM);
+		CLAW_DBF_TEXT_(2, setup, "probex%d", -ENOMEM);
 		return -ENOMEM;
 	}
 	privptr->p_mtc_envelope= kzalloc( MAX_ENVELOPE_SIZE, GFP_KERNEL);
@@ -322,9 +282,7 @@
         if ((privptr->p_mtc_envelope==NULL) || (privptr->p_env==NULL)) {
                 probe_error(cgdev);
 		put_device(&cgdev->dev);
-		printk(KERN_WARNING "Out of memory %s %s Exit Line %d \n",
-			cgdev->cdev[0]->dev.bus_id,__func__,__LINE__);
-		CLAW_DBF_TEXT_(2,setup,"probex%d",-ENOMEM);
+		CLAW_DBF_TEXT_(2, setup, "probex%d", -ENOMEM);
                 return -ENOMEM;
         }
 	memcpy(privptr->p_env->adapter_name,WS_NAME_NOT_DEF,8);
@@ -341,19 +299,14 @@
 		put_device(&cgdev->dev);
 		printk(KERN_WARNING "add_files failed %s %s Exit Line %d \n",
 			cgdev->cdev[0]->dev.bus_id,__func__,__LINE__);
-		CLAW_DBF_TEXT_(2,setup,"probex%d",rc);
+		CLAW_DBF_TEXT_(2, setup, "probex%d", rc);
 		return rc;
 	}
-	printk(KERN_INFO "claw: sysfs files added for %s\n",cgdev->cdev[0]->dev.bus_id);
 	privptr->p_env->p_priv = privptr;
         cgdev->cdev[0]->handler = claw_irq_handler;
 	cgdev->cdev[1]->handler = claw_irq_handler;
 	cgdev->dev.driver_data = privptr;
-#ifdef FUNCTRACE
-        printk(KERN_INFO "claw:%s exit on line %d, "
-		"rc = 0\n",__func__,__LINE__);
-#endif
-	CLAW_DBF_TEXT(2,setup,"prbext 0");
+	CLAW_DBF_TEXT(2, setup, "prbext 0");
 
         return 0;
 }  /*  end of claw_probe       */
@@ -370,37 +323,18 @@
 	unsigned long saveflags;
         struct chbk *p_ch;
 
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s enter\n",dev->name,__func__);
-#endif
-	CLAW_DBF_TEXT(4,trace,"claw_tx");
+	CLAW_DBF_TEXT(4, trace, "claw_tx");
         p_ch=&privptr->channel[WRITE];
         if (skb == NULL) {
-                printk(KERN_WARNING "%s: null pointer passed as sk_buffer\n",
-			dev->name);
                 privptr->stats.tx_dropped++;
-#ifdef FUNCTRACE
-                printk(KERN_INFO "%s: %s() exit on line %d, rc = EIO\n",
-			dev->name,__func__, __LINE__);
-#endif
-		CLAW_DBF_TEXT_(2,trace,"clawtx%d",-EIO);
+		privptr->stats.tx_errors++;
+		CLAW_DBF_TEXT_(2, trace, "clawtx%d", -EIO);
                 return -EIO;
         }
-
-#ifdef IOTRACE
-        printk(KERN_INFO "%s: variable sk_buff=\n",dev->name);
-        dumpit((char *) skb, sizeof(struct sk_buff));
-        printk(KERN_INFO "%s: variable dev=\n",dev->name);
-        dumpit((char *) dev, sizeof(struct net_device));
-#endif
         spin_lock_irqsave(get_ccwdev_lock(p_ch->cdev), saveflags);
         rc=claw_hw_tx( skb, dev, 1 );
         spin_unlock_irqrestore(get_ccwdev_lock(p_ch->cdev), saveflags);
-#ifdef FUNCTRACE
-        printk(KERN_INFO "%s:%s exit on line %d, rc = %d\n",
-		dev->name, __func__, __LINE__, rc);
-#endif
-	CLAW_DBF_TEXT_(4,trace,"clawtx%d",rc);
+	CLAW_DBF_TEXT_(4, trace, "clawtx%d", rc);
         return rc;
 }   /*  end of claw_tx */
 
@@ -419,7 +353,7 @@
 
 	new_skb = NULL;		/* assume no dice */
 	pkt_cnt = 0;
-	CLAW_DBF_TEXT(4,trace,"PackSKBe");
+	CLAW_DBF_TEXT(4, trace, "PackSKBe");
 	if (!skb_queue_empty(&p_ch->collect_queue)) {
 	/* some data */
 		held_skb = skb_dequeue(&p_ch->collect_queue);
@@ -457,13 +391,8 @@
 				skb_queue_head(&p_ch->collect_queue,held_skb);
 			}
 		}
-#ifdef IOTRACE
-		printk(KERN_INFO "%s: %s() Packed %d len %d\n",
-			p_env->ndev->name,
-			__func__,pkt_cnt,new_skb->len);
-#endif
 	}
-	CLAW_DBF_TEXT(4,trace,"PackSKBx");
+	CLAW_DBF_TEXT(4, trace, "PackSKBx");
 	return new_skb;
 }
 
@@ -477,29 +406,12 @@
 {
 	struct claw_privbk  *privptr=dev->priv;
 	int buff_size;
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Enter  \n",dev->name,__func__);
-#endif
-#ifdef DEBUGMSG
-        printk(KERN_INFO "variable dev =\n");
-        dumpit((char *) dev, sizeof(struct net_device));
-        printk(KERN_INFO "variable new_mtu = %d\n", new_mtu);
-#endif
-	CLAW_DBF_TEXT(4,trace,"setmtu");
+	CLAW_DBF_TEXT(4, trace, "setmtu");
 	buff_size = privptr->p_env->write_size;
         if ((new_mtu < 60) || (new_mtu > buff_size)) {
-#ifdef FUNCTRACE
-                printk(KERN_INFO "%s:%s Exit on line %d, rc=EINVAL\n",
-		dev->name,
-		__func__, __LINE__);
-#endif
                 return -EINVAL;
         }
         dev->mtu = new_mtu;
-#ifdef FUNCTRACE
-        printk(KERN_INFO "%s:%s Exit on line %d\n",dev->name,
-	__func__, __LINE__);
-#endif
         return 0;
 }  /*   end of claw_change_mtu */
 
@@ -521,24 +433,13 @@
         struct timer_list  timer;
         struct ccwbk *p_buf;
 
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Enter  \n",dev->name,__func__);
-#endif
-	CLAW_DBF_TEXT(4,trace,"open");
-	if (!dev || (dev->name[0] == 0x00)) {
-		CLAW_DBF_TEXT(2,trace,"BadDev");
-	 	printk(KERN_WARNING "claw: Bad device at open failing \n");
-		return -ENODEV;
-	}
+	CLAW_DBF_TEXT(4, trace, "open");
 	privptr = (struct claw_privbk *)dev->priv;
         /*   allocate and initialize CCW blocks */
 	if (privptr->buffs_alloc == 0) {
 	        rc=init_ccw_bk(dev);
         	if (rc) {
-                	printk(KERN_INFO "%s:%s Exit on line %d, rc=ENOMEM\n",
-			dev->name,
-			__func__, __LINE__);
-			CLAW_DBF_TEXT(2,trace,"openmem");
+			CLAW_DBF_TEXT(2, trace, "openmem");
                 	return -ENOMEM;
         	}
 	}
@@ -557,7 +458,7 @@
 	tasklet_init(&privptr->channel[READ].tasklet, claw_irq_tasklet,
         	(unsigned long) &privptr->channel[READ]);
         for ( i = 0; i < 2;  i++) {
-		CLAW_DBF_TEXT_(2,trace,"opn_ch%d",i);
+		CLAW_DBF_TEXT_(2, trace, "opn_ch%d", i);
                 init_waitqueue_head(&privptr->channel[i].wait);
 		/* skb_queue_head_init(&p_ch->io_queue); */
 		if (i == WRITE)
@@ -595,15 +496,8 @@
            ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) ||
            (((privptr->channel[READ].flag |
 	   	privptr->channel[WRITE].flag) & CLAW_TIMER) != 0x00)) {
-#ifdef DEBUGMSG
-                printk(KERN_INFO "%s: channel problems during open - read:"
-			" %02x -  write: %02x\n",
-                        dev->name,
-			privptr->channel[READ].last_dstat,
-			privptr->channel[WRITE].last_dstat);
-#endif
                 printk(KERN_INFO "%s: remote side is not ready\n", dev->name);
-		CLAW_DBF_TEXT(2,trace,"notrdy");
+		CLAW_DBF_TEXT(2, trace, "notrdy");
 
                 for ( i = 0; i < 2;  i++) {
                         spin_lock_irqsave(
@@ -659,23 +553,14 @@
                 privptr->p_buff_read=NULL;
                 privptr->p_buff_write=NULL;
                 claw_clear_busy(dev);
-#ifdef FUNCTRACE
-                printk(KERN_INFO "%s:%s Exit on line %d, rc=EIO\n",
-		dev->name,__func__,__LINE__);
-#endif
-		CLAW_DBF_TEXT(2,trace,"open EIO");
+		CLAW_DBF_TEXT(2, trace, "open EIO");
                 return -EIO;
         }
 
         /*   Send SystemValidate command */
 
         claw_clear_busy(dev);
-
-#ifdef FUNCTRACE
-        printk(KERN_INFO "%s:%s Exit on line %d, rc=0\n",
-		dev->name,__func__,__LINE__);
-#endif
-	CLAW_DBF_TEXT(4,trace,"openok");
+	CLAW_DBF_TEXT(4, trace, "openok");
         return 0;
 }    /*     end of claw_open    */
 
@@ -694,22 +579,14 @@
         struct claw_env  *p_env;
         struct chbk *p_ch_r=NULL;
 
-
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s enter  \n",__func__);
-#endif
-	CLAW_DBF_TEXT(4,trace,"clawirq");
+	CLAW_DBF_TEXT(4, trace, "clawirq");
         /* Bypass all 'unsolicited interrupts' */
 	if (!cdev->dev.driver_data) {
                 printk(KERN_WARNING "claw: unsolicited interrupt for device:"
 		 	"%s received c-%02x d-%02x\n",
 		       cdev->dev.bus_id, irb->scsw.cmd.cstat,
 		       irb->scsw.cmd.dstat);
-#ifdef FUNCTRACE
-                printk(KERN_INFO "claw: %s() "
-			"exit on line %d\n",__func__,__LINE__);
-#endif
-		CLAW_DBF_TEXT(2,trace,"badirq");
+		CLAW_DBF_TEXT(2, trace, "badirq");
                 return;
         }
 	privptr = (struct claw_privbk *)cdev->dev.driver_data;
@@ -722,41 +599,25 @@
 	else {
 		printk(KERN_WARNING "claw: Can't determine channel for "
 			"interrupt, device %s\n", cdev->dev.bus_id);
-		CLAW_DBF_TEXT(2,trace,"badchan");
+		CLAW_DBF_TEXT(2, trace, "badchan");
 		return;
 	}
-	CLAW_DBF_TEXT_(4,trace,"IRQCH=%d",p_ch->flag);
+	CLAW_DBF_TEXT_(4, trace, "IRQCH=%d", p_ch->flag);
 
 	dev = (struct net_device *) (p_ch->ndev);
         p_env=privptr->p_env;
 
-#ifdef IOTRACE
-        printk(KERN_INFO "%s: interrupt for device: %04x "
-		"received c-%02x d-%02x state-%02x\n",
-	       dev->name, p_ch->devno, irb->scsw.cmd.cstat,
-	       irb->scsw.cmd.dstat, p_ch->claw_state);
-#endif
-
 	/* Copy interruption response block. */
 	memcpy(p_ch->irb, irb, sizeof(struct irb));
 
-        /* Check for good subchannel return code, otherwise error message */
+	/* Check for good subchannel return code, otherwise info message */
 	if (irb->scsw.cmd.cstat && !(irb->scsw.cmd.cstat & SCHN_STAT_PCI)) {
                 printk(KERN_INFO "%s: subchannel check for device: %04x -"
 			" Sch Stat %02x  Dev Stat %02x CPA - %04x\n",
                         dev->name, p_ch->devno,
 			irb->scsw.cmd.cstat, irb->scsw.cmd.dstat,
 			irb->scsw.cmd.cpa);
-#ifdef IOTRACE
-		dumpit((char *)irb,sizeof(struct irb));
-		dumpit((char *)(unsigned long)irb->scsw.cmd.cpa,
-			sizeof(struct ccw1));
-#endif
-#ifdef FUNCTRACE
-		printk(KERN_INFO "%s:%s Exit on line %d\n",
-		dev->name,__func__,__LINE__);
-#endif
-		CLAW_DBF_TEXT(2,trace,"chanchk");
+		CLAW_DBF_TEXT(2, trace, "chanchk");
                 /* return; */
         }
 
@@ -768,233 +629,138 @@
 	p_ch->last_dstat = irb->scsw.cmd.dstat;
 
         switch (p_ch->claw_state) {
-                case CLAW_STOP:/* HALT_IO by claw_release (halt sequence) */
-#ifdef DEBUGMSG
-                        printk(KERN_INFO "%s: CLAW_STOP enter\n", dev->name);
-#endif
-			if (!((p_ch->irb->scsw.cmd.stctl &
-			       SCSW_STCTL_SEC_STATUS) ||
-			    (p_ch->irb->scsw.cmd.stctl ==
-				SCSW_STCTL_STATUS_PEND) ||
-			    (p_ch->irb->scsw.cmd.stctl ==
-				(SCSW_STCTL_ALERT_STATUS |
-				 SCSW_STCTL_STATUS_PEND)))) {
-#ifdef FUNCTRACE
-                                printk(KERN_INFO "%s:%s Exit on line %d\n",
-					dev->name,__func__,__LINE__);
-#endif
-                                return;
-                        }
-                        wake_up(&p_ch->wait);   /* wake up claw_release */
-
-#ifdef DEBUGMSG
-                        printk(KERN_INFO "%s: CLAW_STOP exit\n", dev->name);
-#endif
-#ifdef FUNCTRACE
-                        printk(KERN_INFO "%s:%s Exit on line %d\n",
-				dev->name,__func__,__LINE__);
-#endif
-			CLAW_DBF_TEXT(4,trace,"stop");
-                        return;
-
-                case CLAW_START_HALT_IO: /* HALT_IO issued by claw_open  */
-#ifdef DEBUGMSG
-                        printk(KERN_INFO "%s: process CLAW_STAT_HALT_IO\n",
-				dev->name);
-#endif
-			if (!((p_ch->irb->scsw.cmd.stctl &
-			       SCSW_STCTL_SEC_STATUS) ||
-			    (p_ch->irb->scsw.cmd.stctl ==
-			     SCSW_STCTL_STATUS_PEND) ||
-			    (p_ch->irb->scsw.cmd.stctl ==
-			     (SCSW_STCTL_ALERT_STATUS |
-			      SCSW_STCTL_STATUS_PEND)))) {
-#ifdef FUNCTRACE
-				printk(KERN_INFO "%s:%s Exit on line %d\n",
-					dev->name,__func__,__LINE__);
-#endif
-				CLAW_DBF_TEXT(4,trace,"haltio");
-                                return;
-                        }
-                        if (p_ch->flag == CLAW_READ) {
-                                p_ch->claw_state = CLAW_START_READ;
-                                wake_up(&p_ch->wait); /* wake claw_open (READ)*/
-                        }
+	case CLAW_STOP:/* HALT_IO by claw_release (halt sequence) */
+		if (!((p_ch->irb->scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS) ||
+		(p_ch->irb->scsw.cmd.stctl == SCSW_STCTL_STATUS_PEND) ||
+		(p_ch->irb->scsw.cmd.stctl ==
+		(SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND))))
+			return;
+		wake_up(&p_ch->wait);   /* wake up claw_release */
+		CLAW_DBF_TEXT(4, trace, "stop");
+		return;
+	case CLAW_START_HALT_IO: /* HALT_IO issued by claw_open  */
+		if (!((p_ch->irb->scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS) ||
+		(p_ch->irb->scsw.cmd.stctl == SCSW_STCTL_STATUS_PEND) ||
+		(p_ch->irb->scsw.cmd.stctl ==
+		(SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+			CLAW_DBF_TEXT(4, trace, "haltio");
+			return;
+		}
+		if (p_ch->flag == CLAW_READ) {
+			p_ch->claw_state = CLAW_START_READ;
+			wake_up(&p_ch->wait); /* wake claw_open (READ)*/
+		} else if (p_ch->flag == CLAW_WRITE) {
+			p_ch->claw_state = CLAW_START_WRITE;
+			/*	send SYSTEM_VALIDATE			*/
+			claw_strt_read(dev, LOCK_NO);
+			claw_send_control(dev,
+				SYSTEM_VALIDATE_REQUEST,
+				0, 0, 0,
+				p_env->host_name,
+				p_env->adapter_name);
+		} else {
+			printk(KERN_WARNING "claw: unsolicited "
+				"interrupt for device:"
+				"%s received c-%02x d-%02x\n",
+				cdev->dev.bus_id,
+				irb->scsw.cmd.cstat,
+				irb->scsw.cmd.dstat);
+			return;
+			}
+		CLAW_DBF_TEXT(4, trace, "haltio");
+		return;
+	case CLAW_START_READ:
+		CLAW_DBF_TEXT(4, trace, "ReadIRQ");
+		if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
+			clear_bit(0, (void *)&p_ch->IO_active);
+			if ((p_ch->irb->ecw[0] & 0x41) == 0x41 ||
+			    (p_ch->irb->ecw[0] & 0x40) == 0x40 ||
+			    (p_ch->irb->ecw[0])        == 0) {
+				privptr->stats.rx_errors++;
+				printk(KERN_INFO "%s: Restart is "
+					"required after remote "
+					"side recovers \n",
+					dev->name);
+			}
+			CLAW_DBF_TEXT(4, trace, "notrdy");
+			return;
+		}
+		if ((p_ch->irb->scsw.cmd.cstat & SCHN_STAT_PCI) &&
+			(p_ch->irb->scsw.cmd.dstat == 0)) {
+			if (test_and_set_bit(CLAW_BH_ACTIVE,
+				(void *)&p_ch->flag_a) == 0)
+				tasklet_schedule(&p_ch->tasklet);
 			else
-			   if (p_ch->flag == CLAW_WRITE) {
-                                p_ch->claw_state = CLAW_START_WRITE;
-                                /*      send SYSTEM_VALIDATE                    */
-                                claw_strt_read(dev, LOCK_NO);
-                               	claw_send_control(dev,
-					SYSTEM_VALIDATE_REQUEST,
-					0, 0, 0,
-					p_env->host_name,
-					p_env->adapter_name );
-                        } else {
-				printk(KERN_WARNING "claw: unsolicited "
-					"interrupt for device:"
-				 	"%s received c-%02x d-%02x\n",
-                		        cdev->dev.bus_id,
-					irb->scsw.cmd.cstat,
-					irb->scsw.cmd.dstat);
-				return;
-				}
-#ifdef DEBUGMSG
-                        printk(KERN_INFO "%s: process CLAW_STAT_HALT_IO exit\n",
-				dev->name);
-#endif
-#ifdef FUNCTRACE
-                        printk(KERN_INFO "%s:%s Exit on line %d\n",
-				dev->name,__func__,__LINE__);
-#endif
-			CLAW_DBF_TEXT(4,trace,"haltio");
-                        return;
-                case CLAW_START_READ:
-			CLAW_DBF_TEXT(4,trace,"ReadIRQ");
-			if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
-                                clear_bit(0, (void *)&p_ch->IO_active);
-                                if ((p_ch->irb->ecw[0] & 0x41) == 0x41 ||
-                                    (p_ch->irb->ecw[0] & 0x40) == 0x40 ||
-                                    (p_ch->irb->ecw[0])        == 0)
-                                {
-                                        privptr->stats.rx_errors++;
-                                        printk(KERN_INFO "%s: Restart is "
-						"required after remote "
-						"side recovers \n",
-						dev->name);
-                                }
-#ifdef FUNCTRACE
-				printk(KERN_INFO "%s:%s Exit on line %d\n",
-					dev->name,__func__,__LINE__);
-#endif
-					CLAW_DBF_TEXT(4,trace,"notrdy");
-                                        return;
-                        }
-			if ((p_ch->irb->scsw.cmd.cstat & SCHN_STAT_PCI) &&
-			    (p_ch->irb->scsw.cmd.dstat == 0)) {
-                                if (test_and_set_bit(CLAW_BH_ACTIVE,
-					(void *)&p_ch->flag_a) == 0) {
-					tasklet_schedule(&p_ch->tasklet);
-                                }
-				else {
-					CLAW_DBF_TEXT(4,trace,"PCINoBH");
-				}
-#ifdef FUNCTRACE
-				printk(KERN_INFO "%s:%s Exit on line %d\n",
-					dev->name,__func__,__LINE__);
-#endif
-				CLAW_DBF_TEXT(4,trace,"PCI_read");
-                                return;
-                        }
-			if (!((p_ch->irb->scsw.cmd.stctl &
-			       SCSW_STCTL_SEC_STATUS) ||
-			     (p_ch->irb->scsw.cmd.stctl ==
-			      SCSW_STCTL_STATUS_PEND) ||
-			     (p_ch->irb->scsw.cmd.stctl ==
-			      (SCSW_STCTL_ALERT_STATUS |
-			       SCSW_STCTL_STATUS_PEND)))) {
-#ifdef FUNCTRACE
-				printk(KERN_INFO "%s:%s Exit on line %d\n",
-					dev->name,__func__,__LINE__);
-#endif
-				CLAW_DBF_TEXT(4,trace,"SPend_rd");
-                                return;
-                        }
-                        clear_bit(0, (void *)&p_ch->IO_active);
-                        claw_clearbit_busy(TB_RETRY,dev);
-                        if (test_and_set_bit(CLAW_BH_ACTIVE,
-    				(void *)&p_ch->flag_a) == 0) {
-    				tasklet_schedule(&p_ch->tasklet);
-                         }
-    			else {
-    				CLAW_DBF_TEXT(4,trace,"RdBHAct");
-    			}
-
-#ifdef DEBUGMSG
-                        printk(KERN_INFO "%s: process CLAW_START_READ exit\n",
-				dev->name);
-#endif
-#ifdef FUNCTRACE
-			printk(KERN_INFO "%s:%s Exit on line %d\n",
-				dev->name,__func__,__LINE__);
-#endif
-			CLAW_DBF_TEXT(4,trace,"RdIRQXit");
-                        return;
-                case CLAW_START_WRITE:
-			if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
-                                printk(KERN_INFO "%s: Unit Check Occured in "
-					"write channel\n",dev->name);
-                                clear_bit(0, (void *)&p_ch->IO_active);
-                                if (p_ch->irb->ecw[0] & 0x80 ) {
-                                        printk(KERN_INFO "%s: Resetting Event "
-						"occurred:\n",dev->name);
-                                        init_timer(&p_ch->timer);
-                                        p_ch->timer.function =
-						(void *)claw_write_retry;
-                                        p_ch->timer.data = (unsigned long)p_ch;
-                                        p_ch->timer.expires = jiffies + 10*HZ;
-                                        add_timer(&p_ch->timer);
-                                        printk(KERN_INFO "%s: write connection "
-						"restarting\n",dev->name);
-                                }
-#ifdef FUNCTRACE
-				printk(KERN_INFO "%s:%s Exit on line %d\n",
-					dev->name,__func__,__LINE__);
-#endif
-				CLAW_DBF_TEXT(4,trace,"rstrtwrt");
-                                return;
-                        }
-			if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_EXCEP) {
-                                        clear_bit(0, (void *)&p_ch->IO_active);
-                                        printk(KERN_INFO "%s: Unit Exception "
-						"Occured in write channel\n",
-						dev->name);
-                        }
-			if (!((p_ch->irb->scsw.cmd.stctl &
-			       SCSW_STCTL_SEC_STATUS) ||
-			     (p_ch->irb->scsw.cmd.stctl ==
-			      SCSW_STCTL_STATUS_PEND) ||
-			     (p_ch->irb->scsw.cmd.stctl ==
-			      (SCSW_STCTL_ALERT_STATUS |
-			       SCSW_STCTL_STATUS_PEND)))) {
-#ifdef FUNCTRACE
-				printk(KERN_INFO "%s:%s Exit on line %d\n",
-					dev->name,__func__,__LINE__);
-#endif
-				CLAW_DBF_TEXT(4,trace,"writeUE");
-                                return;
-                        }
-                        clear_bit(0, (void *)&p_ch->IO_active);
-                        if (claw_test_and_setbit_busy(TB_TX,dev)==0) {
-                                claw_write_next(p_ch);
-                                claw_clearbit_busy(TB_TX,dev);
-                                claw_clear_busy(dev);
-                        }
-                        p_ch_r=(struct chbk *)&privptr->channel[READ];
-                        if (test_and_set_bit(CLAW_BH_ACTIVE,
- 					(void *)&p_ch_r->flag_a) == 0) {
-			 	tasklet_schedule(&p_ch_r->tasklet);
-                        }
-
-#ifdef DEBUGMSG
-                        printk(KERN_INFO "%s: process CLAW_START_WRITE exit\n",
-				 dev->name);
-#endif
-#ifdef FUNCTRACE
-			printk(KERN_INFO "%s:%s Exit on line %d\n",
-				dev->name,__func__,__LINE__);
-#endif
-			CLAW_DBF_TEXT(4,trace,"StWtExit");
-                        return;
-                default:
-                        printk(KERN_WARNING "%s: wrong selection code - irq "
-				"state=%d\n",dev->name,p_ch->claw_state);
-#ifdef FUNCTRACE
-			printk(KERN_INFO "%s:%s Exit on line %d\n",
-				dev->name,__func__,__LINE__);
-#endif
-			CLAW_DBF_TEXT(2,trace,"badIRQ");
-                        return;
+				CLAW_DBF_TEXT(4, trace, "PCINoBH");
+			CLAW_DBF_TEXT(4, trace, "PCI_read");
+			return;
+		}
+		if (!((p_ch->irb->scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS) ||
+		 (p_ch->irb->scsw.cmd.stctl == SCSW_STCTL_STATUS_PEND) ||
+		 (p_ch->irb->scsw.cmd.stctl ==
+		 (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+			CLAW_DBF_TEXT(4, trace, "SPend_rd");
+			return;
+		}
+		clear_bit(0, (void *)&p_ch->IO_active);
+		claw_clearbit_busy(TB_RETRY, dev);
+		if (test_and_set_bit(CLAW_BH_ACTIVE,
+			(void *)&p_ch->flag_a) == 0)
+			tasklet_schedule(&p_ch->tasklet);
+		else
+			CLAW_DBF_TEXT(4, trace, "RdBHAct");
+		CLAW_DBF_TEXT(4, trace, "RdIRQXit");
+		return;
+	case CLAW_START_WRITE:
+		if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
+			printk(KERN_INFO "%s: Unit Check Occured in "
+				"write channel\n", dev->name);
+			clear_bit(0, (void *)&p_ch->IO_active);
+			if (p_ch->irb->ecw[0] & 0x80) {
+				printk(KERN_INFO "%s: Resetting Event "
+					"occurred:\n", dev->name);
+				init_timer(&p_ch->timer);
+				p_ch->timer.function =
+					(void *)claw_write_retry;
+				p_ch->timer.data = (unsigned long)p_ch;
+				p_ch->timer.expires = jiffies + 10*HZ;
+				add_timer(&p_ch->timer);
+				printk(KERN_INFO "%s: write connection "
+					"restarting\n", dev->name);
+			}
+			CLAW_DBF_TEXT(4, trace, "rstrtwrt");
+			return;
+		}
+		if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_EXCEP) {
+			clear_bit(0, (void *)&p_ch->IO_active);
+			printk(KERN_INFO "%s: Unit Exception "
+			       "Occured in write channel\n",
+			       dev->name);
+		}
+		if (!((p_ch->irb->scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS) ||
+		(p_ch->irb->scsw.cmd.stctl == SCSW_STCTL_STATUS_PEND) ||
+		(p_ch->irb->scsw.cmd.stctl ==
+		(SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+			CLAW_DBF_TEXT(4, trace, "writeUE");
+			return;
+		}
+		clear_bit(0, (void *)&p_ch->IO_active);
+		if (claw_test_and_setbit_busy(TB_TX, dev) == 0) {
+			claw_write_next(p_ch);
+			claw_clearbit_busy(TB_TX, dev);
+			claw_clear_busy(dev);
+		}
+		p_ch_r = (struct chbk *)&privptr->channel[READ];
+		if (test_and_set_bit(CLAW_BH_ACTIVE,
+			(void *)&p_ch_r->flag_a) == 0)
+			tasklet_schedule(&p_ch_r->tasklet);
+		CLAW_DBF_TEXT(4, trace, "StWtExit");
+		return;
+	default:
+		printk(KERN_WARNING "%s: wrong selection code - irq "
+			"state=%d\n", dev->name, p_ch->claw_state);
+		CLAW_DBF_TEXT(2, trace, "badIRQ");
+		return;
         }
 
 }       /*   end of claw_irq_handler    */
@@ -1013,29 +779,11 @@
 
 	p_ch = (struct chbk *) data;
         dev = (struct net_device *)p_ch->ndev;
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Enter  \n",dev->name,__func__);
-#endif
-#ifdef DEBUGMSG
-        printk(KERN_INFO "%s: variable p_ch =\n",dev->name);
-        dumpit((char *) p_ch, sizeof(struct chbk));
-#endif
-	CLAW_DBF_TEXT(4,trace,"IRQtask");
-
+	CLAW_DBF_TEXT(4, trace, "IRQtask");
         privptr = (struct claw_privbk *) dev->priv;
-
-#ifdef DEBUGMSG
-        printk(KERN_INFO "%s: bh routine - state-%02x\n" ,
-		dev->name, p_ch->claw_state);
-#endif
-
         unpack_read(dev);
         clear_bit(CLAW_BH_ACTIVE, (void *)&p_ch->flag_a);
-	CLAW_DBF_TEXT(4,trace,"TskletXt");
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Exit on line %d\n",
-		dev->name,__func__,__LINE__);
-#endif
+	CLAW_DBF_TEXT(4, trace, "TskletXt");
         return;
 }       /*    end of claw_irq_bh    */
 
@@ -1060,16 +808,7 @@
         privptr = (struct claw_privbk *) dev->priv;
         if (!privptr)
                 return 0;
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Enter  \n",dev->name,__func__);
-#endif
-	CLAW_DBF_TEXT(4,trace,"release");
-#ifdef DEBUGMSG
-        printk(KERN_INFO "%s: variable dev =\n",dev->name);
-        dumpit((char *) dev, sizeof(struct net_device));
-	printk(KERN_INFO "Priv Buffalloc %d\n",privptr->buffs_alloc);
-	printk(KERN_INFO "Priv p_buff_ccw = %p\n",&privptr->p_buff_ccw);
-#endif
+	CLAW_DBF_TEXT(4, trace, "release");
         privptr->release_pend=1;
         claw_setbit_busy(TB_STOP,dev);
         for ( i = 1; i >=0 ;  i--) {
@@ -1101,19 +840,15 @@
 		privptr->pk_skb = NULL;
 	}
 	if(privptr->buffs_alloc != 1) {
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Exit on line %d\n",
-		dev->name,__func__,__LINE__);
-#endif
-		CLAW_DBF_TEXT(4,trace,"none2fre");
+		CLAW_DBF_TEXT(4, trace, "none2fre");
 		return 0;
 	}
-	CLAW_DBF_TEXT(4,trace,"freebufs");
+	CLAW_DBF_TEXT(4, trace, "freebufs");
 	if (privptr->p_buff_ccw != NULL) {
         	free_pages((unsigned long)privptr->p_buff_ccw,
 	        	(int)pages_to_order_of_mag(privptr->p_buff_ccw_num));
 	}
-	CLAW_DBF_TEXT(4,trace,"freeread");
+	CLAW_DBF_TEXT(4, trace, "freeread");
         if (privptr->p_env->read_size < PAGE_SIZE) {
 	    if (privptr->p_buff_read != NULL) {
                 free_pages((unsigned long)privptr->p_buff_read,
@@ -1129,7 +864,7 @@
                         p_buf=p_buf->next;
                 }
         }
-	 CLAW_DBF_TEXT(4,trace,"freewrit");
+	 CLAW_DBF_TEXT(4, trace, "freewrit");
         if (privptr->p_env->write_size < PAGE_SIZE ) {
                 free_pages((unsigned long)privptr->p_buff_write,
 		      (int)pages_to_order_of_mag(privptr->p_buff_write_num));
@@ -1143,7 +878,7 @@
                         p_buf=p_buf->next;
                 }
         }
-	 CLAW_DBF_TEXT(4,trace,"clearptr");
+	 CLAW_DBF_TEXT(4, trace, "clearptr");
 	privptr->buffs_alloc = 0;
         privptr->p_buff_ccw=NULL;
         privptr->p_buff_read=NULL;
@@ -1180,18 +915,12 @@
                 dev->name,
 		privptr->channel[READ].last_dstat,
 		privptr->channel[WRITE].last_dstat);
-		 CLAW_DBF_TEXT(2,trace,"badclose");
+		 CLAW_DBF_TEXT(2, trace, "badclose");
         }
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Exit on line %d\n",
-		dev->name,__func__,__LINE__);
-#endif
-	CLAW_DBF_TEXT(4,trace,"rlsexit");
+	CLAW_DBF_TEXT(4, trace, "rlsexit");
         return 0;
 }      /* end of claw_release     */
 
-
-
 /*-------------------------------------------------------------------*
 *       claw_write_retry                                             *
 *                                                                    *
@@ -1203,32 +932,12 @@
 
         struct net_device  *dev=p_ch->ndev;
 
-
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
-        printk(KERN_INFO "claw: variable p_ch =\n");
-        dumpit((char *) p_ch, sizeof(struct chbk));
-#endif
-	CLAW_DBF_TEXT(4,trace,"w_retry");
+	CLAW_DBF_TEXT(4, trace, "w_retry");
         if (p_ch->claw_state == CLAW_STOP) {
-#ifdef FUNCTRACE
-		printk(KERN_INFO "%s:%s Exit on line %d\n",
-			dev->name,__func__,__LINE__);
-#endif
         	return;
         }
-#ifdef DEBUGMSG
-        printk( KERN_INFO "%s:%s  state-%02x\n" ,
-		dev->name,
-		__func__,
-		p_ch->claw_state);
-#endif
 	claw_strt_out_IO( dev );
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Exit on line %d\n",
-		dev->name,__func__,__LINE__);
-#endif
-	CLAW_DBF_TEXT(4,trace,"rtry_xit");
+	CLAW_DBF_TEXT(4, trace, "rtry_xit");
         return;
 }      /* end of claw_write_retry      */
 
@@ -1247,12 +956,7 @@
 	struct sk_buff *pk_skb;
 	int	rc;
 
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Enter  \n",p_ch->ndev->name,__func__);
-        printk(KERN_INFO "%s: variable p_ch =\n",p_ch->ndev->name);
-        dumpit((char *) p_ch, sizeof(struct chbk));
-#endif
-	CLAW_DBF_TEXT(4,trace,"claw_wrt");
+	CLAW_DBF_TEXT(4, trace, "claw_wrt");
         if (p_ch->claw_state == CLAW_STOP)
                 return;
         dev = (struct net_device *) p_ch->ndev;
@@ -1272,11 +976,6 @@
         if (privptr->p_write_active_first!=NULL) {
                 claw_strt_out_IO(dev);
         }
-
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Exit on line %d\n",
-		dev->name,__func__,__LINE__);
-#endif
         return;
 }      /* end of claw_write_next      */
 
@@ -1288,22 +987,12 @@
 static void
 claw_timer ( struct chbk * p_ch )
 {
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Entry\n",p_ch->ndev->name,__func__);
-        printk(KERN_INFO "%s: variable p_ch =\n",p_ch->ndev->name);
-        dumpit((char *) p_ch, sizeof(struct chbk));
-#endif
-	CLAW_DBF_TEXT(4,trace,"timer");
+	CLAW_DBF_TEXT(4, trace, "timer");
         p_ch->flag |= CLAW_TIMER;
         wake_up(&p_ch->wait);
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Exit on line %d\n",
-		p_ch->ndev->name,__func__,__LINE__);
-#endif
         return;
 }      /* end of claw_timer  */
 
-
 /*
 *
 *       functions
@@ -1324,10 +1013,8 @@
 {
 	int	order_of_mag=1;		/* assume 2 pages */
 	int	nump=2;
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s Enter pages = %d \n",__func__,num_of_pages);
-#endif
-	CLAW_DBF_TEXT_(5,trace,"pages%d",num_of_pages);
+
+	CLAW_DBF_TEXT_(5, trace, "pages%d", num_of_pages);
 	if (num_of_pages == 1)   {return 0; }  /* magnitude of 0 = 1 page */
 	/* 512 pages = 2Meg on 4k page systems */
 	if (num_of_pages >= 512) {return 9; }
@@ -1338,11 +1025,7 @@
 	  order_of_mag +=1;
 	}
 	if (order_of_mag > 9) { order_of_mag = 9; }  /* I know it's paranoid */
-#ifdef FUNCTRACE
-        printk(KERN_INFO "%s Exit on line %d, order = %d\n",
-	__func__,__LINE__, order_of_mag);
-#endif
-	CLAW_DBF_TEXT_(5,trace,"mag%d",order_of_mag);
+	CLAW_DBF_TEXT_(5, trace, "mag%d", order_of_mag);
 	return order_of_mag;
 }
 
@@ -1358,21 +1041,7 @@
         struct claw_privbk *privptr;
         struct ccw1  temp_ccw;
         struct endccw * p_end;
-#ifdef IOTRACE
-        struct ccwbk*  p_buf;
-#endif
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Enter  \n",dev->name,__func__);
-#endif
-#ifdef DEBUGMSG
-        printk(KERN_INFO "dev\n");
-        dumpit((char *) dev, sizeof(struct net_device));
-        printk(KERN_INFO "p_first\n");
-        dumpit((char *) p_first, sizeof(struct ccwbk));
-        printk(KERN_INFO "p_last\n");
-        dumpit((char *) p_last, sizeof(struct ccwbk));
-#endif
-	CLAW_DBF_TEXT(4,trace,"addreads");
+	CLAW_DBF_TEXT(4, trace, "addreads");
         privptr = dev->priv;
         p_end = privptr->p_end_ccw;
 
@@ -1380,11 +1049,7 @@
         *       to apend the running channel programs
         */
         if ( p_first==NULL) {
-#ifdef FUNCTRACE
-		printk(KERN_INFO "%s:%s Exit on line %d\n",
-			dev->name,__func__,__LINE__);
-#endif
-		CLAW_DBF_TEXT(4,trace,"addexit");
+		CLAW_DBF_TEXT(4, trace, "addexit");
                 return 0;
         }
 
@@ -1411,21 +1076,11 @@
         }
 
         if ( privptr-> p_read_active_first ==NULL ) {
-#ifdef DEBUGMSG
-                printk(KERN_INFO "%s:%s p_read_active_first == NULL \n",
-			dev->name,__func__);
-                printk(KERN_INFO "%s:%s Read active first/last changed \n",
-			dev->name,__func__);
-#endif
                 privptr-> p_read_active_first= p_first;  /*    set new first */
                 privptr-> p_read_active_last = p_last;   /*    set new last  */
         }
         else {
 
-#ifdef DEBUGMSG
-                printk(KERN_INFO "%s:%s Read in progress \n",
-		dev->name,__func__);
-#endif
                 /* set up TIC ccw  */
                 temp_ccw.cda= (__u32)__pa(&p_first->read);
                 temp_ccw.count=0;
@@ -1462,27 +1117,7 @@
                 privptr->p_read_active_last->next = p_first;
                 privptr->p_read_active_last=p_last;
         } /* end of if ( privptr-> p_read_active_first ==NULL)  */
-#ifdef IOTRACE
-	printk(KERN_INFO "%s:%s  dump p_last CCW BK \n",dev->name,__func__);
-        dumpit((char *)p_last, sizeof(struct ccwbk));
-	printk(KERN_INFO "%s:%s  dump p_end CCW BK \n",dev->name,__func__);
-        dumpit((char *)p_end, sizeof(struct endccw));
-
-	printk(KERN_INFO "%s:%s dump p_first CCW BK \n",dev->name,__func__);
-        dumpit((char *)p_first, sizeof(struct ccwbk));
-        printk(KERN_INFO "%s:%s Dump Active CCW chain \n",
-		dev->name,__func__);
-        p_buf=privptr->p_read_active_first;
-        while (p_buf!=NULL) {
-                dumpit((char *)p_buf, sizeof(struct ccwbk));
-                p_buf=p_buf->next;
-        }
-#endif
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Exit on line %d\n",
-		dev->name,__func__,__LINE__);
-#endif
-	CLAW_DBF_TEXT(4,trace,"addexit");
+	CLAW_DBF_TEXT(4, trace, "addexit");
         return 0;
 }    /*     end of add_claw_reads   */
 
@@ -1494,44 +1129,29 @@
 static void
 ccw_check_return_code(struct ccw_device *cdev, int return_code)
 {
-#ifdef FUNCTRACE
-        printk(KERN_INFO "%s: %s() > enter  \n",
-		cdev->dev.bus_id,__func__);
-#endif
-	CLAW_DBF_TEXT(4,trace,"ccwret");
-#ifdef DEBUGMSG
-        printk(KERN_INFO "variable cdev =\n");
-        dumpit((char *) cdev, sizeof(struct ccw_device));
-        printk(KERN_INFO "variable return_code = %d\n",return_code);
-#endif
+	CLAW_DBF_TEXT(4, trace, "ccwret");
         if (return_code != 0) {
                 switch (return_code) {
-                        case -EBUSY:
-                                printk(KERN_INFO "%s: Busy !\n",
-					cdev->dev.bus_id);
-                                break;
-                        case -ENODEV:
-                                printk(KERN_EMERG "%s: Missing device called "
-					"for IO ENODEV\n", cdev->dev.bus_id);
-                                break;
-                        case -EIO:
-                                printk(KERN_EMERG "%s: Status pending... EIO \n",
-					cdev->dev.bus_id);
-                                break;
-			case -EINVAL:
-                                printk(KERN_EMERG "%s: Invalid Dev State EINVAL \n",
-					cdev->dev.bus_id);
-                                break;
-                        default:
-                                printk(KERN_EMERG "%s: Unknown error in "
+		case -EBUSY: /* BUSY is a transient state no action needed */
+			break;
+		case -ENODEV:
+			printk(KERN_EMERG "%s: Missing device called "
+				"for IO ENODEV\n", cdev->dev.bus_id);
+			break;
+		case -EIO:
+			printk(KERN_EMERG "%s: Status pending... EIO \n",
+				cdev->dev.bus_id);
+			break;
+		case -EINVAL:
+			printk(KERN_EMERG "%s: Invalid Dev State EINVAL \n",
+				cdev->dev.bus_id);
+			break;
+		default:
+			printk(KERN_EMERG "%s: Unknown error in "
 				 "Do_IO %d\n",cdev->dev.bus_id, return_code);
-                }
-        }
-#ifdef FUNCTRACE
-        printk(KERN_INFO "%s: %s() > exit on line %d\n",
-		cdev->dev.bus_id,__func__,__LINE__);
-#endif
-	CLAW_DBF_TEXT(4,trace,"ccwret");
+		}
+	}
+	CLAW_DBF_TEXT(4, trace, "ccwret");
 }    /*    end of ccw_check_return_code   */
 
 /*-------------------------------------------------------------------*
@@ -1541,173 +1161,46 @@
 static void
 ccw_check_unit_check(struct chbk * p_ch, unsigned char sense )
 {
-	struct net_device *dev = p_ch->ndev;
+	struct net_device *ndev = p_ch->ndev;
 
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s: %s() > enter\n",dev->name,__func__);
-#endif
-#ifdef DEBUGMSG
-        printk(KERN_INFO "%s: variable dev =\n",dev->name);
-        dumpit((char *)dev, sizeof(struct net_device));
-        printk(KERN_INFO "%s: variable sense =\n",dev->name);
-        dumpit((char *)&sense, 2);
-#endif
-	CLAW_DBF_TEXT(4,trace,"unitchek");
-
+	CLAW_DBF_TEXT(4, trace, "unitchek");
         printk(KERN_INFO "%s: Unit Check with sense byte:0x%04x\n",
-                dev->name, sense);
+	       ndev->name, sense);
 
         if (sense & 0x40) {
                 if (sense & 0x01) {
                         printk(KERN_WARNING "%s: Interface disconnect or "
 				"Selective reset "
-			       	"occurred (remote side)\n", dev->name);
+				"occurred (remote side)\n", ndev->name);
                 }
                 else {
                         printk(KERN_WARNING "%s: System reset occured"
-				" (remote side)\n", dev->name);
+				" (remote side)\n", ndev->name);
                 }
         }
         else if (sense & 0x20) {
                 if (sense & 0x04) {
                         printk(KERN_WARNING "%s: Data-streaming "
-				"timeout)\n", dev->name);
+				"timeout)\n", ndev->name);
                 }
                 else  {
                         printk(KERN_WARNING "%s: Data-transfer parity"
-				" error\n", dev->name);
+				" error\n", ndev->name);
                 }
         }
         else if (sense & 0x10) {
                 if (sense & 0x20) {
                         printk(KERN_WARNING "%s: Hardware malfunction "
-				"(remote side)\n", dev->name);
+				"(remote side)\n", ndev->name);
                 }
                 else {
                         printk(KERN_WARNING "%s: read-data parity error "
-				"(remote side)\n", dev->name);
+				"(remote side)\n", ndev->name);
                 }
         }
 
-#ifdef FUNCTRACE
-        printk(KERN_INFO "%s: %s() exit on line %d\n",
-		dev->name,__func__,__LINE__);
-#endif
 }   /*    end of ccw_check_unit_check    */
 
-
-
-/*-------------------------------------------------------------------*
-* Dump buffer format                                                 *
-*                                                                    *
-*--------------------------------------------------------------------*/
-#ifdef DEBUG
-static void
-dumpit(char* buf, int len)
-{
-
-        __u32      ct, sw, rm, dup;
-        char       *ptr, *rptr;
-        char       tbuf[82], tdup[82];
-#if (CONFIG_64BIT)
-        char       addr[22];
-#else
-        char       addr[12];
-#endif
-        char       boff[12];
-        char       bhex[82], duphex[82];
-        char       basc[40];
-
-        sw  = 0;
-        rptr =ptr=buf;
-        rm  = 16;
-        duphex[0]  = 0x00;
-        dup = 0;
-        for ( ct=0; ct < len; ct++, ptr++, rptr++ )  {
-                if (sw == 0) {
-#if (CONFIG_64BIT)
-                        sprintf(addr, "%16.16lX",(unsigned long)rptr);
-#else
-                        sprintf(addr, "%8.8X",(__u32)rptr);
-#endif
-                        sprintf(boff, "%4.4X", (__u32)ct);
-                        bhex[0] = '\0';
-                        basc[0] = '\0';
-                }
-                if ((sw == 4) || (sw == 12)) {
-                        strcat(bhex, " ");
-                }
-                if (sw == 8) {
-                        strcat(bhex, "  ");
-                }
-#if (CONFIG_64BIT)
-                sprintf(tbuf,"%2.2lX", (unsigned long)*ptr);
-#else
-                sprintf(tbuf,"%2.2X", (__u32)*ptr);
-#endif
-                tbuf[2] = '\0';
-                strcat(bhex, tbuf);
-                if ((0!=isprint(*ptr)) && (*ptr >= 0x20)) {
-                        basc[sw] = *ptr;
-                }
-                else {
-                        basc[sw] = '.';
-                }
-                basc[sw+1] = '\0';
-                sw++;
-                rm--;
-                if (sw==16) {
-                        if ((strcmp(duphex, bhex)) !=0) {
-                                if (dup !=0) {
-					sprintf(tdup,"Duplicate as above to"
-						" %s", addr);
-                                        printk( KERN_INFO "                 "
-						"   --- %s ---\n",tdup);
-                                }
-                                printk( KERN_INFO "   %s (+%s) : %s  [%s]\n",
-					 addr, boff, bhex, basc);
-                                dup = 0;
-                                strcpy(duphex, bhex);
-                        }
-                        else {
-                                dup++;
-                        }
-                        sw = 0;
-                        rm = 16;
-                }
-        }  /* endfor */
-
-        if (sw != 0) {
-                for ( ; rm > 0; rm--, sw++ ) {
-                        if ((sw==4) || (sw==12)) strcat(bhex, " ");
-                        if (sw==8)               strcat(bhex, "  ");
-                        strcat(bhex, "  ");
-                        strcat(basc, " ");
-                }
-                if (dup !=0) {
-                        sprintf(tdup,"Duplicate as above to %s", addr);
-                        printk( KERN_INFO "                    --- %s ---\n",
-				tdup);
-                }
-                printk( KERN_INFO "   %s (+%s) : %s  [%s]\n",
-			addr, boff, bhex, basc);
-        }
-        else {
-                if (dup >=1) {
-                        sprintf(tdup,"Duplicate as above to %s", addr);
-                        printk( KERN_INFO "                    --- %s ---\n",
-				tdup);
-                }
-                if (dup !=0) {
-                        printk( KERN_INFO "   %s (+%s) : %s  [%s]\n",
-				addr, boff, bhex, basc);
-                }
-        }
-        return;
-
-}   /*   end of dumpit  */
-#endif
-
 /*-------------------------------------------------------------------*
 *               find_link                                            *
 *--------------------------------------------------------------------*/
@@ -1718,16 +1211,7 @@
 	struct claw_env *p_env;
 	int    rc=0;
 
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s > enter  \n",dev->name,__func__);
-#endif
-	CLAW_DBF_TEXT(2,setup,"findlink");
-#ifdef DEBUGMSG
-        printk(KERN_INFO "%s: variable dev = \n",dev->name);
-        dumpit((char *) dev, sizeof(struct net_device));
-        printk(KERN_INFO "%s: variable host_name = %s\n",dev->name, host_name);
-        printk(KERN_INFO "%s: variable ws_name = %s\n",dev->name, ws_name);
-#endif
+	CLAW_DBF_TEXT(2, setup, "findlink");
         privptr=dev->priv;
         p_env=privptr->p_env;
 	switch (p_env->packing)
@@ -1750,10 +1234,6 @@
 			break;
 	}
 
-#ifdef FUNCTRACE
-        printk(KERN_INFO "%s:%s Exit on line %d\n",
-		dev->name,__func__,__LINE__);
-#endif
         return 0;
 }    /*    end of find_link    */
 
@@ -1782,27 +1262,11 @@
         int                             lock;
 	struct clawph			*pk_head;
 	struct chbk			*ch;
-#ifdef IOTRACE
-        struct ccwbk                   *p_buf;
-#endif
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s: %s() > enter\n",dev->name,__func__);
-#endif
-	CLAW_DBF_TEXT(4,trace,"hw_tx");
-#ifdef DEBUGMSG
-        printk(KERN_INFO "%s: variable dev skb =\n",dev->name);
-        dumpit((char *) skb, sizeof(struct sk_buff));
-        printk(KERN_INFO "%s: variable dev =\n",dev->name);
-        dumpit((char *) dev, sizeof(struct net_device));
-        printk(KERN_INFO "%s: variable linkid = %ld\n",dev->name,linkid);
-#endif
+
+	CLAW_DBF_TEXT(4, trace, "hw_tx");
         privptr = (struct claw_privbk *) (dev->priv);
         p_ch=(struct chbk *)&privptr->channel[WRITE];
 	p_env =privptr->p_env;
-#ifdef IOTRACE
-	printk(KERN_INFO "%s: %s() dump sk_buff  \n",dev->name,__func__);
-        dumpit((char *)skb ,sizeof(struct sk_buff));
-#endif
 	claw_free_wrt_buf(dev);	/* Clean up free chain if posible */
         /*  scan the write queue to free any completed write packets   */
         p_first_ccw=NULL;
@@ -1834,11 +1298,6 @@
                                 claw_strt_out_IO(dev );
                                 claw_free_wrt_buf( dev );
                                 if (privptr->write_free_count==0) {
-#ifdef IOTRACE
-                                	printk(KERN_INFO "%s: "
-					   "(claw_check_busy) no free write "
-					   "buffers\n", dev->name);
-#endif
 					ch = &privptr->channel[WRITE];
 					atomic_inc(&skb->users);
 					skb_queue_tail(&ch->collect_queue, skb);
@@ -1851,10 +1310,6 @@
                 }
                 /*  tx lock  */
                 if (claw_test_and_setbit_busy(TB_TX,dev)) { /* set to busy */
-#ifdef DEBUGMSG
-                        printk(KERN_INFO "%s:  busy  (claw_test_and_setbit_"
-				"busy)\n", dev->name);
-#endif
 			ch = &privptr->channel[WRITE];
 			atomic_inc(&skb->users);
 			skb_queue_tail(&ch->collect_queue, skb);
@@ -1871,28 +1326,16 @@
             privptr->p_write_free_chain == NULL ) {
 
                 claw_setbit_busy(TB_NOBUFFER,dev);
-
-#ifdef DEBUGMSG
-                printk(KERN_INFO "%s:  busy  (claw_setbit_busy"
-			"(TB_NOBUFFER))\n", dev->name);
-                printk(KERN_INFO "       free_count: %d, numBuffers : %d\n",
-			(int)privptr->write_free_count,(int) numBuffers );
-#endif
 		ch = &privptr->channel[WRITE];
 		atomic_inc(&skb->users);
 		skb_queue_tail(&ch->collect_queue, skb);
-		CLAW_DBF_TEXT(2,trace,"clawbusy");
+		CLAW_DBF_TEXT(2, trace, "clawbusy");
                 goto Done2;
         }
         pDataAddress=skb->data;
         len_of_data=skb->len;
 
         while (len_of_data > 0) {
-#ifdef DEBUGMSG
-                printk(KERN_INFO "%s: %s() length-of-data is %ld \n",
-			dev->name ,__func__,len_of_data);
-                dumpit((char *)pDataAddress ,64);
-#endif
                 p_this_ccw=privptr->p_write_free_chain;  /* get a block */
 		if (p_this_ccw == NULL) { /* lost the race */
 			ch = &privptr->channel[WRITE];
@@ -1924,12 +1367,6 @@
 				(__u32)__pa(&p_this_ccw->write);
                 }
                 p_last_ccw=p_this_ccw;      /* save new last block */
-#ifdef IOTRACE
-		printk(KERN_INFO "%s: %s() > CCW and Buffer %ld bytes long \n",
-			dev->name,__func__,bytesInThisBuffer);
-                dumpit((char *)p_this_ccw, sizeof(struct ccwbk));
-                dumpit((char *)p_this_ccw->p_buffer, 64);
-#endif
         }
 
         /*      FirstCCW and LastCCW now contain a new set of write channel
@@ -1962,13 +1399,11 @@
                         pEnd->write1_nop2.count=1;
                 }  /* end if if (pEnd->write1) */
 
-
                 if (privptr->p_write_active_first==NULL ) {
                         privptr->p_write_active_first=p_first_ccw;
                         privptr->p_write_active_last=p_last_ccw;
                 }
                 else {
-
                         /*      set up Tic CCWs         */
 
                         tempCCW.cda=(__u32)__pa(&p_first_ccw->write);
@@ -2007,19 +1442,6 @@
                 }
 
         } /* endif (p_first_ccw!=NULL)  */
-
-
-#ifdef IOTRACE
-        printk(KERN_INFO "%s: %s() >  Dump Active CCW chain \n",
-		dev->name,__func__);
-        p_buf=privptr->p_write_active_first;
-        while (p_buf!=NULL) {
-                dumpit((char *)p_buf, sizeof(struct ccwbk));
-                p_buf=p_buf->next;
-        }
-        p_buf=(struct ccwbk*)privptr->p_end_ccw;
-        dumpit((char *)p_buf, sizeof(struct endccw));
-#endif
         dev_kfree_skb_any(skb);
 	if (linkid==0) {
         	lock=LOCK_NO;
@@ -2029,21 +1451,12 @@
         }
         claw_strt_out_IO(dev );
         /*      if write free count is zero , set NOBUFFER       */
-#ifdef DEBUGMSG
-        printk(KERN_INFO "%s: %s() > free_count is %d\n",
-		dev->name,__func__,
-		(int) privptr->write_free_count );
-#endif
 	if (privptr->write_free_count==0) {
 		claw_setbit_busy(TB_NOBUFFER,dev);
         }
 Done2:
 	claw_clearbit_busy(TB_TX,dev);
 Done:
-#ifdef FUNCTRACE
-        printk(KERN_INFO "%s: %s() > exit on line %d, rc = %d \n",
-		dev->name,__func__,__LINE__, rc);
-#endif
 	return(rc);
 }    /*    end of claw_hw_tx    */
 
@@ -2075,14 +1488,7 @@
         struct clawh *pClawH=NULL;
         addr_t   real_TIC_address;
         int i,j;
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s: %s() enter  \n",dev->name,__func__);
-#endif
-	CLAW_DBF_TEXT(4,trace,"init_ccw");
-#ifdef DEBUGMSG
-        printk(KERN_INFO "%s: variable dev =\n",dev->name);
-        dumpit((char *) dev, sizeof(struct net_device));
-#endif
+	CLAW_DBF_TEXT(4, trace, "init_ccw");
 
         /*  initialize  statistics field */
         privptr->active_link_ID=0;
@@ -2107,20 +1513,6 @@
         */
         ccw_blocks_required =
 		privptr->p_env->read_buffers+privptr->p_env->write_buffers+1;
-#ifdef DEBUGMSG
-        printk(KERN_INFO "%s: %s() "
-		"ccw_blocks_required=%d\n",
-		dev->name,__func__,
-		ccw_blocks_required);
-        printk(KERN_INFO "%s: %s() "
-		"PAGE_SIZE=0x%x\n",
-		dev->name,__func__,
-		(unsigned int)PAGE_SIZE);
-        printk(KERN_INFO "%s: %s() > "
-		"PAGE_MASK=0x%x\n",
-		dev->name,__func__,
-		(unsigned int)PAGE_MASK);
-#endif
         /*
         * compute number of CCW blocks that will fit in a page
         */
@@ -2128,14 +1520,6 @@
         ccw_pages_required=
 		DIV_ROUND_UP(ccw_blocks_required, ccw_blocks_perpage);
 
-#ifdef DEBUGMSG
-        printk(KERN_INFO "%s: %s() > ccw_blocks_perpage=%d\n",
-		dev->name,__func__,
-		ccw_blocks_perpage);
-        printk(KERN_INFO "%s: %s() > ccw_pages_required=%d\n",
-		dev->name,__func__,
-		ccw_pages_required);
-#endif
         /*
          *  read and write sizes are set by 2 constants in claw.h
 	 *  4k and 32k.  Unpacked values other than 4k are not going to
@@ -2166,36 +1550,6 @@
 		claw_write_pages = privptr->p_env->write_buffers *
 					privptr->p_buff_pages_perwrite;
         }
-#ifdef DEBUGMSG
-        if (privptr->p_env->read_size < PAGE_SIZE) {
-            printk(KERN_INFO "%s: %s() reads_perpage=%d\n",
-		dev->name,__func__,
-		claw_reads_perpage);
-        }
-        else {
-            printk(KERN_INFO "%s: %s() pages_perread=%d\n",
-		dev->name,__func__,
-		privptr->p_buff_pages_perread);
-        }
-        printk(KERN_INFO "%s: %s() read_pages=%d\n",
-		dev->name,__func__,
-		claw_read_pages);
-        if (privptr->p_env->write_size < PAGE_SIZE) {
-            printk(KERN_INFO "%s: %s() writes_perpage=%d\n",
-		dev->name,__func__,
-		claw_writes_perpage);
-        }
-        else {
-            printk(KERN_INFO "%s: %s() pages_perwrite=%d\n",
-		dev->name,__func__,
-		privptr->p_buff_pages_perwrite);
-        }
-        printk(KERN_INFO "%s: %s() write_pages=%d\n",
-		dev->name,__func__,
-		claw_write_pages);
-#endif
-
-
         /*
         *               allocate ccw_pages_required
         */
@@ -2204,17 +1558,6 @@
 			(void *)__get_free_pages(__GFP_DMA,
 		        (int)pages_to_order_of_mag(ccw_pages_required ));
                 if (privptr->p_buff_ccw==NULL) {
-                        printk(KERN_INFO "%s: %s()  "
-				"__get_free_pages for CCWs failed : "
-				"pages is %d\n",
-				dev->name,__func__,
-				ccw_pages_required );
-#ifdef FUNCTRACE
-                        printk(KERN_INFO "%s: %s() > "
-				"exit on line %d, rc = ENOMEM\n",
-				dev->name,__func__,
-				 __LINE__);
-#endif
                         return -ENOMEM;
                 }
                 privptr->p_buff_ccw_num=ccw_pages_required;
@@ -2229,11 +1572,6 @@
         privptr->p_end_ccw = (struct endccw *)&privptr->end_ccw;
         real_address  = (__u32)__pa(privptr->p_end_ccw);
         /*                              Initialize ending CCW block       */
-#ifdef DEBUGMSG
-        printk(KERN_INFO "%s: %s() begin initialize ending CCW blocks\n",
-		dev->name,__func__);
-#endif
-
         p_endccw=privptr->p_end_ccw;
         p_endccw->real=real_address;
         p_endccw->write1=0x00;
@@ -2287,21 +1625,10 @@
         p_endccw->read2_nop2.count        = 1;
         p_endccw->read2_nop2.cda          = 0;
 
-#ifdef IOTRACE
-        printk(KERN_INFO "%s: %s() dump claw ending CCW BK \n",
-		dev->name,__func__);
-        dumpit((char *)p_endccw, sizeof(struct endccw));
-#endif
-
         /*
         *                               Build a chain of CCWs
         *
         */
-
-#ifdef DEBUGMSG
-        printk(KERN_INFO "%s: %s()  Begin build a chain of CCW buffer \n",
-		dev->name,__func__);
-#endif
         p_buff=privptr->p_buff_ccw;
 
         p_free_chain=NULL;
@@ -2316,26 +1643,10 @@
                 }
                 p_buff+=PAGE_SIZE;
         }
-#ifdef DEBUGMSG
-        printk(KERN_INFO "%s: %s() "
-		"End build a chain of CCW buffer \n",
-			dev->name,__func__);
-        p_buf=p_free_chain;
-        while (p_buf!=NULL) {
-                dumpit((char *)p_buf, sizeof(struct ccwbk));
-                p_buf=p_buf->next;
-        }
-#endif
-
         /*
         *                               Initialize ClawSignalBlock
         *
         */
-#ifdef DEBUGMSG
-        printk(KERN_INFO "%s: %s() "
-		"Begin initialize ClawSignalBlock \n",
-		dev->name,__func__);
-#endif
         if (privptr->p_claw_signal_blk==NULL) {
                 privptr->p_claw_signal_blk=p_free_chain;
                 p_free_chain=p_free_chain->next;
@@ -2344,12 +1655,6 @@
                 pClawH->opcode=0xff;
                 pClawH->flag=CLAW_BUSY;
         }
-#ifdef DEBUGMSG
-        printk(KERN_INFO "%s: %s() >  End initialize "
-	 	"ClawSignalBlock\n",
-		dev->name,__func__);
-        dumpit((char *)privptr->p_claw_signal_blk, sizeof(struct ccwbk));
-#endif
 
         /*
         *               allocate write_pages_required and add to free chain
@@ -2360,17 +1665,7 @@
 			(void *)__get_free_pages(__GFP_DMA,
 			(int)pages_to_order_of_mag(claw_write_pages ));
                 if (privptr->p_buff_write==NULL) {
-                        printk(KERN_INFO "%s: %s() __get_free_pages for write"
-				" bufs failed : get is for %d pages\n",
-				dev->name,__func__,claw_write_pages );
-                        free_pages((unsigned long)privptr->p_buff_ccw,
-			   (int)pages_to_order_of_mag(privptr->p_buff_ccw_num));
                         privptr->p_buff_ccw=NULL;
-#ifdef FUNCTRACE
-                        printk(KERN_INFO "%s: %s() > exit on line %d,"
-			 	"rc = ENOMEM\n",
-				dev->name,__func__,__LINE__);
-#endif
                         return -ENOMEM;
                 }
                 /*
@@ -2380,10 +1675,6 @@
 
                 memset(privptr->p_buff_write, 0x00,
 			ccw_pages_required * PAGE_SIZE);
-#ifdef DEBUGMSG
-                printk(KERN_INFO "%s: %s() Begin build claw write free "
-			"chain \n",dev->name,__func__);
-#endif
                 privptr->p_write_free_chain=NULL;
 
                 p_buff=privptr->p_buff_write;
@@ -2419,18 +1710,7 @@
                    p_buff=(void *)__get_free_pages(__GFP_DMA,
 		        (int)pages_to_order_of_mag(
 			privptr->p_buff_pages_perwrite) );
-#ifdef IOTRACE
-                   printk(KERN_INFO "%s:%s __get_free_pages "
-		    "for writes buf: get for %d pages\n",
-		    dev->name,__func__,
-		    privptr->p_buff_pages_perwrite);
-#endif
                    if (p_buff==NULL) {
-			printk(KERN_INFO "%s:%s __get_free_pages "
-			 	"for writes buf failed : get is for %d pages\n",
-				dev->name,
-				__func__,
-				privptr->p_buff_pages_perwrite );
                         free_pages((unsigned long)privptr->p_buff_ccw,
 			      (int)pages_to_order_of_mag(
 			      		privptr->p_buff_ccw_num));
@@ -2443,12 +1723,6 @@
 					privptr->p_buff_pages_perwrite));
                                 p_buf=p_buf->next;
                         }
-#ifdef FUNCTRACE
-                        printk(KERN_INFO "%s: %s exit on line %d, rc = ENOMEM\n",
-			dev->name,
-			__func__,
-			__LINE__);
-#endif
                         return -ENOMEM;
                    }  /* Error on get_pages   */
                    memset(p_buff, 0x00, privptr->p_env->write_size );
@@ -2477,15 +1751,6 @@
         privptr->write_free_count=privptr->p_env->write_buffers;
 
 
-#ifdef DEBUGMSG
-        printk(KERN_INFO "%s:%s  End build claw write free chain \n",
-	dev->name,__func__);
-        p_buf=privptr->p_write_free_chain;
-        while (p_buf!=NULL) {
-                dumpit((char *)p_buf, sizeof(struct ccwbk));
-                p_buf=p_buf->next;
-        }
-#endif
         /*
         *               allocate read_pages_required and chain to free chain
         */
@@ -2495,10 +1760,6 @@
 			(void *)__get_free_pages(__GFP_DMA,
 			(int)pages_to_order_of_mag(claw_read_pages) );
                 if (privptr->p_buff_read==NULL) {
-                        printk(KERN_INFO "%s: %s() "
-			 	"__get_free_pages for read buf failed : "
-			 	"get is for %d pages\n",
-				dev->name,__func__,claw_read_pages );
                         free_pages((unsigned long)privptr->p_buff_ccw,
 				(int)pages_to_order_of_mag(
 					privptr->p_buff_ccw_num));
@@ -2508,10 +1769,6 @@
 				privptr->p_buff_write_num));
                         privptr->p_buff_ccw=NULL;
                         privptr->p_buff_write=NULL;
-#ifdef FUNCTRACE
-                        printk(KERN_INFO "%s: %s() > exit on line %d, rc ="
-				" ENOMEM\n",dev->name,__func__,__LINE__);
-#endif
                         return -ENOMEM;
                 }
                 memset(privptr->p_buff_read, 0x00, claw_read_pages * PAGE_SIZE);
@@ -2520,10 +1777,6 @@
                 *                               Build CLAW read free chain
                 *
                 */
-#ifdef DEBUGMSG
-                printk(KERN_INFO "%s: %s() Begin build claw read free chain \n",
-			dev->name,__func__);
-#endif
                 p_buff=privptr->p_buff_read;
                 for (i=0 ; i< privptr->p_env->read_buffers ; i++) {
                         p_buf        = p_free_chain;
@@ -2600,19 +1853,10 @@
                 }   /* for read_buffers   */
           }         /* read_size < PAGE_SIZE  */
           else {  /* read Size >= PAGE_SIZE  */
-
-#ifdef DEBUGMSG
-        printk(KERN_INFO "%s: %s() Begin build claw read free chain \n",
-		dev->name,__func__);
-#endif
                 for (i=0 ; i< privptr->p_env->read_buffers ; i++) {
                         p_buff = (void *)__get_free_pages(__GFP_DMA,
 				(int)pages_to_order_of_mag(privptr->p_buff_pages_perread) );
                         if (p_buff==NULL) {
-                                printk(KERN_INFO "%s: %s() __get_free_pages for read "
-					"buf failed : get is for %d pages\n",
-					dev->name,__func__,
-                                        privptr->p_buff_pages_perread );
                                 free_pages((unsigned long)privptr->p_buff_ccw,
 					(int)pages_to_order_of_mag(privptr->p_buff_ccw_num));
 				/* free the write pages  */
@@ -2633,11 +1877,6 @@
                                 }
                                 privptr->p_buff_ccw=NULL;
                                 privptr->p_buff_write=NULL;
-#ifdef FUNCTRACE
-                                printk(KERN_INFO "%s: %s() exit on line %d, rc = ENOMEM\n",
-					dev->name,__func__,
-					__LINE__);
-#endif
                                 return -ENOMEM;
                         }
                         memset(p_buff, 0x00, privptr->p_env->read_size);
@@ -2706,22 +1945,9 @@
                 }    /* For read_buffers   */
           }     /*  read_size >= PAGE_SIZE   */
         }       /*  pBuffread = NULL */
-#ifdef DEBUGMSG
-        printk(KERN_INFO "%s: %s() >  End build claw read free chain \n",
-		dev->name,__func__);
-        p_buf=p_first_CCWB;
-        while (p_buf!=NULL) {
-                dumpit((char *)p_buf, sizeof(struct ccwbk));
-                p_buf=p_buf->next;
-        }
-
-#endif
         add_claw_reads( dev  ,p_first_CCWB , p_last_CCWB);
 	privptr->buffs_alloc = 1;
-#ifdef FUNCTRACE
-        printk(KERN_INFO "%s: %s() exit on line %d\n",
-		dev->name,__func__,__LINE__);
-#endif
+
         return 0;
 }    /*    end of init_ccw_bk */
 
@@ -2735,14 +1961,8 @@
 probe_error( struct ccwgroup_device *cgdev)
 {
   struct claw_privbk *privptr;
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s enter  \n",__func__);
-#endif
-	CLAW_DBF_TEXT(4,trace,"proberr");
-#ifdef DEBUGMSG
-	printk(KERN_INFO "%s variable cgdev =\n",__func__);
-        dumpit((char *) cgdev, sizeof(struct ccwgroup_device));
-#endif
+
+	CLAW_DBF_TEXT(4, trace, "proberr");
         privptr=(struct claw_privbk *)cgdev->dev.driver_data;
 	if (privptr!=NULL) {
 		kfree(privptr->p_env);
@@ -2752,16 +1972,9 @@
                 kfree(privptr);
                 privptr=NULL;
         }
-#ifdef FUNCTRACE
-        printk(KERN_INFO "%s > exit on line %d\n",
-		 __func__,__LINE__);
-#endif
-
         return;
 }    /*    probe_error    */
 
-
-
 /*-------------------------------------------------------------------*
 *    claw_process_control                                            *
 *                                                                    *
@@ -2783,32 +1996,19 @@
         struct conncmd *p_connect=NULL;
         int rc;
         struct chbk *p_ch = NULL;
-#ifdef FUNCTRACE
-        printk(KERN_INFO "%s: %s() > enter  \n",
-		dev->name,__func__);
-#endif
-	CLAW_DBF_TEXT(2,setup,"clw_cntl");
-#ifdef DEBUGMSG
-        printk(KERN_INFO "%s: variable dev =\n",dev->name);
-        dumpit((char *) dev, sizeof(struct net_device));
-        printk(KERN_INFO "%s: variable p_ccw =\n",dev->name);
-        dumpit((char *) p_ccw, sizeof(struct ccwbk *));
-#endif
+	struct device *tdev;
+	CLAW_DBF_TEXT(2, setup, "clw_cntl");
         udelay(1000);  /* Wait a ms for the control packets to
 			*catch up to each other */
         privptr=dev->priv;
         p_env=privptr->p_env;
+	tdev = &privptr->channel[READ].cdev->dev;
 	memcpy( &temp_host_name, p_env->host_name, 8);
         memcpy( &temp_ws_name, p_env->adapter_name , 8);
         printk(KERN_INFO "%s: CLAW device %.8s: "
 		"Received Control Packet\n",
 		dev->name, temp_ws_name);
         if (privptr->release_pend==1) {
-#ifdef FUNCTRACE
-                printk(KERN_INFO "%s: %s() > "
-			"exit on line %d, rc=0\n",
-			dev->name,__func__,__LINE__);
-#endif
                 return 0;
         }
         p_buf=p_ccw->p_buffer;
@@ -2818,261 +2018,246 @@
 	} else {
 		memcpy(p_ctlbk, p_buf, sizeof(struct clawctl));
 	}
-#ifdef IOTRACE
-        printk(KERN_INFO "%s: dump claw control data inbound\n",dev->name);
-        dumpit((char *)p_ctlbk, sizeof(struct clawctl));
-#endif
         switch (p_ctlbk->command)
         {
-                case SYSTEM_VALIDATE_REQUEST:
-                        if (p_ctlbk->version!=CLAW_VERSION_ID) {
-                                claw_snd_sys_validate_rsp(dev, p_ctlbk,
-					CLAW_RC_WRONG_VERSION );
-                                printk("%s: %d is wrong version id. "
-					"Expected %d\n",
-					dev->name, p_ctlbk->version,
-                                        CLAW_VERSION_ID);
-                        }
-                        p_sysval=(struct sysval *)&(p_ctlbk->data);
-			printk( "%s: Recv Sys Validate Request: "
-				"Vers=%d,link_id=%d,Corr=%d,WS name=%."
-				"8s,Host name=%.8s\n",
-                                dev->name, p_ctlbk->version,
-				p_ctlbk->linkid,
-				p_ctlbk->correlator,
-				p_sysval->WS_name,
-                                p_sysval->host_name);
-                        if (0!=memcmp(temp_host_name,p_sysval->host_name,8)) {
-                                claw_snd_sys_validate_rsp(dev, p_ctlbk,
-					CLAW_RC_NAME_MISMATCH );
-				CLAW_DBF_TEXT(2,setup,"HSTBAD");
-				CLAW_DBF_TEXT_(2,setup,"%s",p_sysval->host_name);
-				CLAW_DBF_TEXT_(2,setup,"%s",temp_host_name);
-                                printk(KERN_INFO "%s:  Host name mismatch\n",
-					dev->name);
-				printk(KERN_INFO "%s: Received :%s: "
-					"expected :%s: \n",
-					dev->name,
-					p_sysval->host_name,
-					temp_host_name);
-                        }
-                        if (0!=memcmp(temp_ws_name,p_sysval->WS_name,8)) {
-                                claw_snd_sys_validate_rsp(dev, p_ctlbk,
-					CLAW_RC_NAME_MISMATCH );
-				CLAW_DBF_TEXT(2,setup,"WSNBAD");
-                                CLAW_DBF_TEXT_(2,setup,"%s",p_sysval->WS_name);
-                                CLAW_DBF_TEXT_(2,setup,"%s",temp_ws_name);
-                                printk(KERN_INFO "%s: WS name mismatch\n",
-					dev->name);
-				 printk(KERN_INFO "%s: Received :%s: "
-                                        "expected :%s: \n",
-                                        dev->name,
-                                        p_sysval->WS_name,
-					temp_ws_name);
-                        }
-                        if (( p_sysval->write_frame_size < p_env->write_size) &&
-			   ( p_env->packing == 0)) {
-                                claw_snd_sys_validate_rsp(dev, p_ctlbk,
-					CLAW_RC_HOST_RCV_TOO_SMALL );
-                                printk(KERN_INFO "%s: host write size is too "
-					"small\n", dev->name);
-				CLAW_DBF_TEXT(2,setup,"wrtszbad");
-                        }
-                        if (( p_sysval->read_frame_size < p_env->read_size) &&
-			   ( p_env->packing == 0)) {
-                                claw_snd_sys_validate_rsp(dev, p_ctlbk,
-					CLAW_RC_HOST_RCV_TOO_SMALL );
-                                printk(KERN_INFO "%s: host read size is too "
-					"small\n", dev->name);
-				CLAW_DBF_TEXT(2,setup,"rdsizbad");
-                        }
-                        claw_snd_sys_validate_rsp(dev, p_ctlbk, 0 );
-                        printk("%s: CLAW device %.8s: System validate"
-				" completed.\n",dev->name, temp_ws_name);
-			printk("%s: sys Validate Rsize:%d Wsize:%d\n",dev->name,
-				p_sysval->read_frame_size,p_sysval->write_frame_size);
-                        privptr->system_validate_comp=1;
-                	if(strncmp(p_env->api_type,WS_APPL_NAME_PACKED,6) == 0) {
-				p_env->packing = PACKING_ASK;
-			}
-                        claw_strt_conn_req(dev);
-                        break;
+	case SYSTEM_VALIDATE_REQUEST:
+		if (p_ctlbk->version != CLAW_VERSION_ID) {
+			claw_snd_sys_validate_rsp(dev, p_ctlbk,
+				CLAW_RC_WRONG_VERSION);
+			printk("%s: %d is wrong version id. "
+			       "Expected %d\n",
+			       dev->name, p_ctlbk->version,
+			       CLAW_VERSION_ID);
+		}
+		p_sysval = (struct sysval *)&(p_ctlbk->data);
+		printk("%s: Recv Sys Validate Request: "
+		       "Vers=%d,link_id=%d,Corr=%d,WS name=%."
+		       "8s,Host name=%.8s\n",
+		       dev->name, p_ctlbk->version,
+		       p_ctlbk->linkid,
+		       p_ctlbk->correlator,
+		       p_sysval->WS_name,
+		       p_sysval->host_name);
+		if (memcmp(temp_host_name, p_sysval->host_name, 8)) {
+			claw_snd_sys_validate_rsp(dev, p_ctlbk,
+				CLAW_RC_NAME_MISMATCH);
+			CLAW_DBF_TEXT(2, setup, "HSTBAD");
+			CLAW_DBF_TEXT_(2, setup, "%s", p_sysval->host_name);
+			CLAW_DBF_TEXT_(2, setup, "%s", temp_host_name);
+			printk(KERN_INFO "%s:  Host name mismatch\n",
+				dev->name);
+			printk(KERN_INFO "%s: Received :%s: "
+				"expected :%s: \n",
+				dev->name,
+				p_sysval->host_name,
+				temp_host_name);
+		}
+		if (memcmp(temp_ws_name, p_sysval->WS_name, 8)) {
+			claw_snd_sys_validate_rsp(dev, p_ctlbk,
+				CLAW_RC_NAME_MISMATCH);
+			CLAW_DBF_TEXT(2, setup, "WSNBAD");
+			CLAW_DBF_TEXT_(2, setup, "%s", p_sysval->WS_name);
+			CLAW_DBF_TEXT_(2, setup, "%s", temp_ws_name);
+			printk(KERN_INFO "%s: WS name mismatch\n",
+				dev->name);
+			printk(KERN_INFO "%s: Received :%s: "
+			       "expected :%s: \n",
+			       dev->name,
+			       p_sysval->WS_name,
+			       temp_ws_name);
+		}
+		if ((p_sysval->write_frame_size < p_env->write_size) &&
+		    (p_env->packing == 0)) {
+			claw_snd_sys_validate_rsp(dev, p_ctlbk,
+				CLAW_RC_HOST_RCV_TOO_SMALL);
+			printk(KERN_INFO "%s: host write size is too "
+				"small\n", dev->name);
+			CLAW_DBF_TEXT(2, setup, "wrtszbad");
+		}
+		if ((p_sysval->read_frame_size < p_env->read_size) &&
+		    (p_env->packing == 0)) {
+			claw_snd_sys_validate_rsp(dev, p_ctlbk,
+				CLAW_RC_HOST_RCV_TOO_SMALL);
+			printk(KERN_INFO "%s: host read size is too "
+				"small\n", dev->name);
+			CLAW_DBF_TEXT(2, setup, "rdsizbad");
+		}
+		claw_snd_sys_validate_rsp(dev, p_ctlbk, 0);
+		printk(KERN_INFO "%s: CLAW device %.8s: System validate "
+			"completed.\n", dev->name, temp_ws_name);
+		printk("%s: sys Validate Rsize:%d Wsize:%d\n", dev->name,
+			p_sysval->read_frame_size, p_sysval->write_frame_size);
+		privptr->system_validate_comp = 1;
+		if (strncmp(p_env->api_type, WS_APPL_NAME_PACKED, 6) == 0)
+			p_env->packing = PACKING_ASK;
+		claw_strt_conn_req(dev);
+		break;
+	case SYSTEM_VALIDATE_RESPONSE:
+		p_sysval = (struct sysval *)&(p_ctlbk->data);
+		printk("%s: Recv Sys Validate Resp: Vers=%d,Corr=%d,RC=%d,"
+			"WS name=%.8s,Host name=%.8s\n",
+			dev->name,
+			p_ctlbk->version,
+			p_ctlbk->correlator,
+			p_ctlbk->rc,
+			p_sysval->WS_name,
+			p_sysval->host_name);
+		switch (p_ctlbk->rc) {
+		case 0:
+			printk(KERN_INFO "%s: CLAW device "
+				"%.8s: System validate "
+				"completed.\n",
+			       dev->name, temp_ws_name);
+			if (privptr->system_validate_comp == 0)
+				claw_strt_conn_req(dev);
+			privptr->system_validate_comp = 1;
+			break;
+		case CLAW_RC_NAME_MISMATCH:
+			printk(KERN_INFO "%s: Sys Validate "
+				"Resp : Host, WS name is "
+				"mismatch\n",
+			       dev->name);
+			break;
+		case CLAW_RC_WRONG_VERSION:
+			printk(KERN_INFO "%s: Sys Validate "
+				"Resp : Wrong version\n",
+				dev->name);
+			break;
+		case CLAW_RC_HOST_RCV_TOO_SMALL:
+			printk(KERN_INFO "%s: Sys Validate "
+				"Resp : bad frame size\n",
+				dev->name);
+			break;
+		default:
+			printk(KERN_INFO "%s: Sys Validate "
+				"error code=%d \n",
+				 dev->name, p_ctlbk->rc);
+			break;
+		}
+		break;
 
-                case SYSTEM_VALIDATE_RESPONSE:
-			p_sysval=(struct sysval *)&(p_ctlbk->data);
-			printk("%s: Recv Sys Validate Resp: Vers=%d,Corr=%d,RC=%d,"
-				"WS name=%.8s,Host name=%.8s\n",
-                        	dev->name,
-                        	p_ctlbk->version,
-                        	p_ctlbk->correlator,
-                        	p_ctlbk->rc,
-                        	p_sysval->WS_name,
-                        	p_sysval->host_name);
-                        switch (p_ctlbk->rc)
-                        {
-                                case 0:
-                                        printk(KERN_INFO "%s: CLAW device "
-						"%.8s: System validate "
-						"completed.\n",
-                                                dev->name, temp_ws_name);
-					if (privptr->system_validate_comp == 0)
-	                                        claw_strt_conn_req(dev);
-					privptr->system_validate_comp=1;
-                                        break;
-                                case CLAW_RC_NAME_MISMATCH:
-                                        printk(KERN_INFO "%s: Sys Validate "
-						"Resp : Host, WS name is "
-						"mismatch\n",
-                                                dev->name);
-                                        break;
-                                case CLAW_RC_WRONG_VERSION:
-                                        printk(KERN_INFO "%s: Sys Validate "
-						"Resp : Wrong version\n",
-						dev->name);
-                                        break;
-                                case CLAW_RC_HOST_RCV_TOO_SMALL:
-                                        printk(KERN_INFO "%s: Sys Validate "
-						"Resp : bad frame size\n",
-						dev->name);
-                                        break;
-                                default:
-                                        printk(KERN_INFO "%s: Sys Validate "
-						"error code=%d \n",
-						 dev->name, p_ctlbk->rc );
-                                        break;
-                        }
-                        break;
+	case CONNECTION_REQUEST:
+		p_connect = (struct conncmd *)&(p_ctlbk->data);
+		printk(KERN_INFO "%s: Recv Conn Req: Vers=%d,link_id=%d,"
+			"Corr=%d,HOST appl=%.8s,WS appl=%.8s\n",
+			dev->name,
+			p_ctlbk->version,
+			p_ctlbk->linkid,
+			p_ctlbk->correlator,
+			p_connect->host_name,
+			p_connect->WS_name);
+		if (privptr->active_link_ID != 0) {
+			claw_snd_disc(dev, p_ctlbk);
+			printk(KERN_INFO "%s: Conn Req error : "
+				"already logical link is active \n",
+				dev->name);
+		}
+		if (p_ctlbk->linkid != 1) {
+			claw_snd_disc(dev, p_ctlbk);
+			printk(KERN_INFO "%s: Conn Req error : "
+				"req logical link id is not 1\n",
+				dev->name);
+		}
+		rc = find_link(dev, p_connect->host_name, p_connect->WS_name);
+		if (rc != 0) {
+			claw_snd_disc(dev, p_ctlbk);
+			printk(KERN_INFO "%s: Conn Resp error: "
+				"req appl name does not match\n",
+				dev->name);
+		}
+		claw_send_control(dev,
+			CONNECTION_CONFIRM, p_ctlbk->linkid,
+			p_ctlbk->correlator,
+			0, p_connect->host_name,
+			p_connect->WS_name);
+		if (p_env->packing == PACKING_ASK) {
+			p_env->packing = PACK_SEND;
+			claw_snd_conn_req(dev, 0);
+		}
+		printk(KERN_INFO "%s: CLAW device %.8s: Connection "
+			"completed link_id=%d.\n",
+			dev->name, temp_ws_name,
+			p_ctlbk->linkid);
+			privptr->active_link_ID = p_ctlbk->linkid;
+			p_ch = &privptr->channel[WRITE];
+			wake_up(&p_ch->wait);  /* wake up claw_open ( WRITE) */
+		break;
+	case CONNECTION_RESPONSE:
+		p_connect = (struct conncmd *)&(p_ctlbk->data);
+		printk(KERN_INFO "%s: Revc Conn Resp: Vers=%d,link_id=%d,"
+			"Corr=%d,RC=%d,Host appl=%.8s, WS appl=%.8s\n",
+			dev->name,
+			p_ctlbk->version,
+			p_ctlbk->linkid,
+			p_ctlbk->correlator,
+			p_ctlbk->rc,
+			p_connect->host_name,
+			p_connect->WS_name);
 
-                case CONNECTION_REQUEST:
-                        p_connect=(struct conncmd *)&(p_ctlbk->data);
-                        printk(KERN_INFO "%s: Recv Conn Req: Vers=%d,link_id=%d,"
-				"Corr=%d,HOST appl=%.8s,WS appl=%.8s\n",
-                        	dev->name,
-	                        p_ctlbk->version,
-        	                p_ctlbk->linkid,
-                	        p_ctlbk->correlator,
-                        	p_connect->host_name,
-                      		p_connect->WS_name);
-                        if (privptr->active_link_ID!=0 ) {
-                                claw_snd_disc(dev, p_ctlbk);
-                                printk(KERN_INFO "%s: Conn Req error : "
-					"already logical link is active \n",
+		if (p_ctlbk->rc != 0) {
+			printk(KERN_INFO "%s: Conn Resp error: rc=%d \n",
+				dev->name, p_ctlbk->rc);
+			return 1;
+		}
+		rc = find_link(dev,
+			p_connect->host_name, p_connect->WS_name);
+		if (rc != 0) {
+			claw_snd_disc(dev, p_ctlbk);
+			printk(KERN_INFO "%s: Conn Resp error: "
+				"req appl name does not match\n",
+				 dev->name);
+		}
+		/* should be until CONNECTION_CONFIRM */
+		privptr->active_link_ID = -(p_ctlbk->linkid);
+		break;
+	case CONNECTION_CONFIRM:
+		p_connect = (struct conncmd *)&(p_ctlbk->data);
+		printk(KERN_INFO "%s: Recv Conn Confirm:Vers=%d,link_id=%d,"
+			"Corr=%d,Host appl=%.8s,WS appl=%.8s\n",
+			dev->name,
+			p_ctlbk->version,
+			p_ctlbk->linkid,
+			p_ctlbk->correlator,
+			p_connect->host_name,
+			p_connect->WS_name);
+		if (p_ctlbk->linkid == -(privptr->active_link_ID)) {
+			privptr->active_link_ID = p_ctlbk->linkid;
+			if (p_env->packing > PACKING_ASK) {
+				printk(KERN_INFO "%s: Confirmed Now packing\n",
 					dev->name);
-                        }
-                        if (p_ctlbk->linkid!=1 ) {
-                                claw_snd_disc(dev, p_ctlbk);
-                                printk(KERN_INFO "%s: Conn Req error : "
-					"req logical link id is not 1\n",
-					dev->name);
-                        }
-                        rc=find_link(dev,
-				p_connect->host_name, p_connect->WS_name);
-                        if (rc!=0) {
-                                claw_snd_disc(dev, p_ctlbk);
-                                printk(KERN_INFO "%s: Conn Req error : "
-					"req appl name does not match\n",
-					 dev->name);
-                        }
-                        claw_send_control(dev,
-				CONNECTION_CONFIRM, p_ctlbk->linkid,
-				p_ctlbk->correlator,
-				0, p_connect->host_name,
-                                p_connect->WS_name);
-			if (p_env->packing == PACKING_ASK) {
-				printk("%s: Now Pack ask\n",dev->name);
-				p_env->packing = PACK_SEND;
-				claw_snd_conn_req(dev,0);
-			}
-                        printk(KERN_INFO "%s: CLAW device %.8s: Connection "
-				"completed link_id=%d.\n",
-				dev->name, temp_ws_name,
-                                p_ctlbk->linkid);
-                        privptr->active_link_ID=p_ctlbk->linkid;
-                        p_ch=&privptr->channel[WRITE];
-                        wake_up(&p_ch->wait);  /* wake up claw_open ( WRITE) */
-                        break;
-                case CONNECTION_RESPONSE:
-                        p_connect=(struct conncmd *)&(p_ctlbk->data);
-                        printk(KERN_INFO "%s: Revc Conn Resp: Vers=%d,link_id=%d,"
-				"Corr=%d,RC=%d,Host appl=%.8s, WS appl=%.8s\n",
-                                dev->name,
-				p_ctlbk->version,
-				p_ctlbk->linkid,
-				p_ctlbk->correlator,
-				p_ctlbk->rc,
-				p_connect->host_name,
-                                p_connect->WS_name);
-
-                        if (p_ctlbk->rc !=0 ) {
-                                printk(KERN_INFO "%s: Conn Resp error: rc=%d \n",
-					dev->name, p_ctlbk->rc);
-                                return 1;
-                        }
-                        rc=find_link(dev,
-				p_connect->host_name, p_connect->WS_name);
-                        if (rc!=0) {
-                                claw_snd_disc(dev, p_ctlbk);
-                                printk(KERN_INFO "%s: Conn Resp error: "
-					"req appl name does not match\n",
-					 dev->name);
-                        }
-			/* should be until CONNECTION_CONFIRM */
-                        privptr->active_link_ID =  - (p_ctlbk->linkid);
-                        break;
-                case CONNECTION_CONFIRM:
-                        p_connect=(struct conncmd *)&(p_ctlbk->data);
-                        printk(KERN_INFO "%s: Recv Conn Confirm:Vers=%d,link_id=%d,"
-				"Corr=%d,Host appl=%.8s,WS appl=%.8s\n",
-                        dev->name,
-                        p_ctlbk->version,
-                        p_ctlbk->linkid,
-                        p_ctlbk->correlator,
-                        p_connect->host_name,
-                        p_connect->WS_name);
-                        if (p_ctlbk->linkid== -(privptr->active_link_ID)) {
-                                privptr->active_link_ID=p_ctlbk->linkid;
-				if (p_env->packing > PACKING_ASK) {
-					printk(KERN_INFO "%s: Confirmed Now packing\n",dev->name);
-					p_env->packing = DO_PACKED;
-					}
-				p_ch=&privptr->channel[WRITE];
-                                wake_up(&p_ch->wait);
-                        }
-                        else {
-                                printk(KERN_INFO "%s: Conn confirm: "
-					"unexpected linkid=%d \n",
-					dev->name, p_ctlbk->linkid);
-                                claw_snd_disc(dev, p_ctlbk);
-                        }
-                        break;
-                case DISCONNECT:
-                        printk(KERN_INFO "%s: Disconnect: "
-				"Vers=%d,link_id=%d,Corr=%d\n",
-				dev->name, p_ctlbk->version,
-                                p_ctlbk->linkid, p_ctlbk->correlator);
-			if ((p_ctlbk->linkid == 2) &&
-			    (p_env->packing == PACK_SEND)) {
-				privptr->active_link_ID = 1;
 				p_env->packing = DO_PACKED;
 			}
-			else
-	                        privptr->active_link_ID=0;
-                        break;
-                case CLAW_ERROR:
-                        printk(KERN_INFO "%s: CLAW ERROR detected\n",
-				dev->name);
-                        break;
-                default:
-                        printk(KERN_INFO "%s:  Unexpected command code=%d \n",
-				dev->name,  p_ctlbk->command);
-                        break;
+			p_ch = &privptr->channel[WRITE];
+			wake_up(&p_ch->wait);
+		} else {
+		       printk(KERN_INFO "%s: Conn confirm: "
+				"unexpected linkid=%d \n",
+				dev->name, p_ctlbk->linkid);
+			claw_snd_disc(dev, p_ctlbk);
+		}
+		break;
+	case DISCONNECT:
+		printk(KERN_INFO "%s: Disconnect: "
+			"Vers=%d,link_id=%d,Corr=%d\n",
+			dev->name, p_ctlbk->version,
+			p_ctlbk->linkid, p_ctlbk->correlator);
+		if ((p_ctlbk->linkid == 2) &&
+		    (p_env->packing == PACK_SEND)) {
+			privptr->active_link_ID = 1;
+			p_env->packing = DO_PACKED;
+		} else
+			privptr->active_link_ID = 0;
+		break;
+	case CLAW_ERROR:
+		printk(KERN_INFO "%s: CLAW ERROR detected\n",
+			dev->name);
+		break;
+	default:
+		printk(KERN_INFO "%s:  Unexpected command code=%d \n",
+			dev->name,  p_ctlbk->command);
+		break;
         }
 
-#ifdef FUNCTRACE
-        printk(KERN_INFO "%s: %s() exit on line %d, rc = 0\n",
-		dev->name,__func__,__LINE__);
-#endif
-
         return 0;
 }   /*    end of claw_process_control    */
 
@@ -3092,18 +2277,7 @@
         struct conncmd                  *p_connect;
         struct sk_buff 			*skb;
 
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s > enter  \n",dev->name,__func__);
-#endif
-	CLAW_DBF_TEXT(2,setup,"sndcntl");
-#ifdef DEBUGMSG
-	printk(KERN_INFO "%s: Sending Control Packet \n",dev->name);
-        printk(KERN_INFO "%s: variable type = 0x%X, link = "
-		"%d, correlator = %d, rc = %d\n",
-                dev->name,type, link, correlator, rc);
-        printk(KERN_INFO "%s: variable local_name = %s, "
-		"remote_name = %s\n",dev->name, local_name, remote_name);
-#endif
+	CLAW_DBF_TEXT(2, setup, "sndcntl");
         privptr=dev->priv;
         p_ctl=(struct clawctl *)&privptr->ctl_bk;
 
@@ -3125,7 +2299,7 @@
                         	p_sysval->read_frame_size=DEF_PACK_BUFSIZE;
 	                        p_sysval->write_frame_size=DEF_PACK_BUFSIZE;
 			} else {
-				/* how big is the piggest group of packets */
+				/* how big is the biggest group of packets */
 				p_sysval->read_frame_size=privptr->p_env->read_size;
 	                        p_sysval->write_frame_size=privptr->p_env->write_size;
 			}
@@ -3155,29 +2329,14 @@
 
         skb = dev_alloc_skb(sizeof(struct clawctl));
         if (!skb) {
-                printk(  "%s:%s low on mem, returning...\n",
-			dev->name,__func__);
-#ifdef DEBUG
-                printk(KERN_INFO "%s:%s Exit, rc = ENOMEM\n",
-			dev->name,__func__);
-#endif
                 return -ENOMEM;
         }
 	memcpy(skb_put(skb, sizeof(struct clawctl)),
 		p_ctl, sizeof(struct clawctl));
-#ifdef IOTRACE
-	 printk(KERN_INFO "%s: outbnd claw cntl data \n",dev->name);
-        dumpit((char *)p_ctl,sizeof(struct clawctl));
-#endif
 	if (privptr->p_env->packing >= PACK_SEND)
 		claw_hw_tx(skb, dev, 1);
 	else
         	claw_hw_tx(skb, dev, 0);
-#ifdef FUNCTRACE
-        printk(KERN_INFO "%s:%s Exit on line %d\n",
-		dev->name,__func__,__LINE__);
-#endif
-
         return 0;
 }  /*   end of claw_send_control  */
 
@@ -3192,22 +2351,11 @@
         struct claw_privbk *privptr=dev->priv;
         struct clawctl 	   *p_ctl;
 
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Enter  \n",dev->name,__func__);
-#endif
-	CLAW_DBF_TEXT(2,setup,"snd_conn");
-#ifdef  DEBUGMSG
-        printk(KERN_INFO "%s: variable link = %X, dev =\n",dev->name, link);
-        dumpit((char *) dev, sizeof(struct net_device));
-#endif
+	CLAW_DBF_TEXT(2, setup, "snd_conn");
 	rc = 1;
         p_ctl=(struct clawctl *)&privptr->ctl_bk;
 	p_ctl->linkid = link;
         if ( privptr->system_validate_comp==0x00 ) {
-#ifdef FUNCTRACE
-                printk(KERN_INFO "%s:%s Exit on line %d, rc = 1\n",
-			dev->name,__func__,__LINE__);
-#endif
                 return rc;
         }
 	if (privptr->p_env->packing == PACKING_ASK )
@@ -3220,10 +2368,6 @@
 	if (privptr->p_env->packing == 0)
         	rc=claw_send_control(dev, CONNECTION_REQUEST,0,0,0,
        			HOST_APPL_NAME, privptr->p_env->api_type);
-#ifdef FUNCTRACE
-        printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
-		dev->name,__func__,__LINE__, rc);
-#endif
         return rc;
 
 }  /*  end of claw_snd_conn_req */
@@ -3240,25 +2384,12 @@
         int rc;
         struct conncmd *  p_connect;
 
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
-#endif
-	CLAW_DBF_TEXT(2,setup,"snd_dsc");
-#ifdef  DEBUGMSG
-        printk(KERN_INFO "%s: variable dev =\n",dev->name);
-        dumpit((char *) dev, sizeof(struct net_device));
-        printk(KERN_INFO "%s: variable p_ctl",dev->name);
-        dumpit((char *) p_ctl, sizeof(struct clawctl));
-#endif
+	CLAW_DBF_TEXT(2, setup, "snd_dsc");
         p_connect=(struct conncmd *)&p_ctl->data;
 
         rc=claw_send_control(dev, DISCONNECT, p_ctl->linkid,
 		p_ctl->correlator, 0,
                 p_connect->host_name, p_connect->WS_name);
-#ifdef FUNCTRACE
-        printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
-		dev->name,__func__, __LINE__, rc);
-#endif
         return rc;
 }     /*   end of claw_snd_disc    */
 
@@ -3276,18 +2407,7 @@
         struct claw_privbk *privptr;
         int    rc;
 
-#ifdef FUNCTRACE
-        printk(KERN_INFO "%s:%s Enter\n",
-		dev->name,__func__);
-#endif
-	CLAW_DBF_TEXT(2,setup,"chkresp");
-#ifdef DEBUGMSG
-        printk(KERN_INFO "%s: variable return_code = %d, dev =\n",
-		dev->name, return_code);
-        dumpit((char *) dev, sizeof(struct net_device));
-        printk(KERN_INFO "%s: variable p_ctl =\n",dev->name);
-        dumpit((char *) p_ctl, sizeof(struct clawctl));
-#endif
+	CLAW_DBF_TEXT(2, setup, "chkresp");
         privptr = dev->priv;
         p_env=privptr->p_env;
         rc=claw_send_control(dev, SYSTEM_VALIDATE_RESPONSE,
@@ -3296,10 +2416,6 @@
                 return_code,
 		p_env->host_name,
 		p_env->adapter_name  );
-#ifdef FUNCTRACE
-        printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
-		dev->name,__func__,__LINE__, rc);
-#endif
         return rc;
 }     /*    end of claw_snd_sys_validate_rsp    */
 
@@ -3313,19 +2429,8 @@
 {
         int rc;
 
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
-#endif
-	CLAW_DBF_TEXT(2,setup,"conn_req");
-#ifdef DEBUGMSG
-        printk(KERN_INFO "%s: variable dev =\n",dev->name);
-        dumpit((char *) dev, sizeof(struct net_device));
-#endif
+	CLAW_DBF_TEXT(2, setup, "conn_req");
         rc=claw_snd_conn_req(dev, 1);
-#ifdef FUNCTRACE
-        printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
-		dev->name,__func__,__LINE__, rc);
-#endif
         return rc;
 }    /*   end of claw_strt_conn_req   */
 
@@ -3339,15 +2444,9 @@
 net_device_stats *claw_stats(struct net_device *dev)
 {
         struct claw_privbk *privptr;
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
-#endif
-	CLAW_DBF_TEXT(4,trace,"stats");
+
+	CLAW_DBF_TEXT(4, trace, "stats");
         privptr = dev->priv;
-#ifdef FUNCTRACE
-        printk(KERN_INFO "%s:%s Exit on line %d\n",
-		dev->name,__func__,__LINE__);
-#endif
         return &privptr->stats;
 }     /*   end of claw_stats   */
 
@@ -3368,36 +2467,28 @@
 	struct clawph 	*p_packh;
 	void		*p_packd;
 	struct clawctl 	*p_ctlrec=NULL;
+	struct device	*p_dev;
 
         __u32	len_of_data;
 	__u32	pack_off;
         __u8	link_num;
         __u8 	mtc_this_frm=0;
         __u32	bytes_to_mov;
-        struct chbk *p_ch = NULL;
         int	i=0;
 	int     p=0;
 
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s enter  \n",dev->name,__func__);
-#endif
-	CLAW_DBF_TEXT(4,trace,"unpkread");
+	CLAW_DBF_TEXT(4, trace, "unpkread");
         p_first_ccw=NULL;
         p_last_ccw=NULL;
 	p_packh=NULL;
 	p_packd=NULL;
         privptr=dev->priv;
+
+	p_dev = &privptr->channel[READ].cdev->dev;
 	p_env = privptr->p_env;
         p_this_ccw=privptr->p_read_active_first;
         i=0;
 	while (p_this_ccw!=NULL && p_this_ccw->header.flag!=CLAW_PENDING) {
-#ifdef IOTRACE
-		printk(KERN_INFO "%s p_this_ccw \n",dev->name);
-                dumpit((char*)p_this_ccw, sizeof(struct ccwbk));
-                printk(KERN_INFO "%s Inbound p_this_ccw->p_buffer(64)"
-			" pk=%d \n",dev->name,p_env->packing);
-                dumpit((char *)p_this_ccw->p_buffer, 64 );
-#endif
 		pack_off = 0;
 		p = 0;
 		p_this_ccw->header.flag=CLAW_PENDING;
@@ -3419,10 +2510,6 @@
 		else
 	                link_num=p_this_ccw->header.opcode / 8;
                 if ((p_this_ccw->header.opcode & MORE_to_COME_FLAG)!=0) {
-#ifdef DEBUGMSG
-                        printk(KERN_INFO "%s: %s > More_to_come is ON\n",
-			dev->name,__func__);
-#endif
                         mtc_this_frm=1;
                         if (p_this_ccw->header.length!=
 				privptr->p_env->read_size ) {
@@ -3445,22 +2532,12 @@
                                 privptr->mtc_skipping=0; /* Ok, the end */
                                 privptr->mtc_logical_link=-1;
                         }
-#ifdef DEBUGMSG
-                        printk(KERN_INFO "%s:%s goto next "
-				"frame from MoretoComeSkip \n",
-				dev->name,__func__);
-#endif
                         goto NextFrame;
                 }
 
                 if (link_num==0) {
                         claw_process_control(dev, p_this_ccw);
-#ifdef DEBUGMSG
-                        printk(KERN_INFO "%s:%s goto next "
-				"frame from claw_process_control \n",
-				dev->name,__func__);
-#endif
-			CLAW_DBF_TEXT(4,trace,"UnpkCntl");
+			CLAW_DBF_TEXT(4, trace, "UnpkCntl");
                         goto NextFrame;
                 }
 unpack_next:
@@ -3479,10 +2556,6 @@
                 	bytes_to_mov=p_this_ccw->header.length;
 		}
                 if (privptr->mtc_logical_link<0) {
-#ifdef DEBUGMSG
-                printk(KERN_INFO "%s: %s mtc_logical_link < 0  \n",
-			dev->name,__func__);
-#endif
 
                 /*
                 *  if More-To-Come is set in this frame then we don't know
@@ -3496,15 +2569,6 @@
 
                 if (bytes_to_mov > (MAX_ENVELOPE_SIZE- privptr->mtc_offset) ) {
                         /*      error     */
-#ifdef DEBUGMSG
-                        printk(KERN_INFO "%s: %s > goto next "
-				"frame from MoretoComeSkip \n",
-				dev->name,
-				__func__);
-                        printk(KERN_INFO "      bytes_to_mov %d > (MAX_ENVELOPE_"
-				"SIZE-privptr->mtc_offset %d)\n",
-				bytes_to_mov,(MAX_ENVELOPE_SIZE- privptr->mtc_offset));
-#endif
                         privptr->stats.rx_frame_errors++;
                         goto NextFrame;
                 }
@@ -3516,16 +2580,6 @@
                 	memcpy( privptr->p_mtc_envelope+ privptr->mtc_offset,
                         	p_this_ccw->p_buffer, bytes_to_mov);
 		}
-#ifdef DEBUGMSG
-                printk(KERN_INFO "%s: %s() received data \n",
-			dev->name,__func__);
-		if (p_env->packing == DO_PACKED)
-			dumpit((char *)p_packd+sizeof(struct clawph),32);
-		else
-	                dumpit((char *)p_this_ccw->p_buffer, 32);
-		printk(KERN_INFO "%s: %s() bytelength %d \n",
-			dev->name,__func__,bytes_to_mov);
-#endif
                 if (mtc_this_frm==0) {
                         len_of_data=privptr->mtc_offset+bytes_to_mov;
                         skb=dev_alloc_skb(len_of_data);
@@ -3540,11 +2594,6 @@
                                 privptr->stats.rx_packets++;
 				privptr->stats.rx_bytes+=len_of_data;
                                 netif_rx(skb);
-#ifdef DEBUGMSG
-                                printk(KERN_INFO "%s: %s() netif_"
-					"rx(skb) completed \n",
-					dev->name,__func__);
-#endif
                         }
                         else {
                                 privptr->stats.rx_dropped++;
@@ -3581,28 +2630,14 @@
                 *       chain to next block on active read queue
                 */
                 p_this_ccw = privptr->p_read_active_first;
-		CLAW_DBF_TEXT_(4,trace,"rxpkt %d",p);
+		CLAW_DBF_TEXT_(4, trace, "rxpkt %d", p);
         } /* end of while */
 
         /*      check validity                  */
 
-#ifdef IOTRACE
-        printk(KERN_INFO "%s:%s processed frame is %d \n",
-		dev->name,__func__,i);
-        printk(KERN_INFO "%s:%s  F:%lx L:%lx\n",
-		dev->name,
-		__func__,
-		(unsigned long)p_first_ccw,
-		(unsigned long)p_last_ccw);
-#endif
-	CLAW_DBF_TEXT_(4,trace,"rxfrm %d",i);
+	CLAW_DBF_TEXT_(4, trace, "rxfrm %d", i);
         add_claw_reads(dev, p_first_ccw, p_last_ccw);
-        p_ch=&privptr->channel[READ];
         claw_strt_read(dev, LOCK_YES);
-#ifdef FUNCTRACE
-        printk(KERN_INFO "%s: %s exit on line %d\n",
-		dev->name, __func__, __LINE__);
-#endif
         return;
 }     /*  end of unpack_read   */
 
@@ -3622,12 +2657,7 @@
         struct clawh *p_clawh;
         p_ch=&privptr->channel[READ];
 
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Enter  \n",dev->name,__func__);
-        printk(KERN_INFO "%s: variable lock = %d, dev =\n",dev->name, lock);
-        dumpit((char *) dev, sizeof(struct net_device));
-#endif
-	CLAW_DBF_TEXT(4,trace,"StRdNter");
+	CLAW_DBF_TEXT(4, trace, "StRdNter");
         p_clawh=(struct clawh *)privptr->p_claw_signal_blk;
         p_clawh->flag=CLAW_IDLE;    /* 0x00 */
 
@@ -3637,21 +2667,11 @@
              privptr->p_read_active_first->header.flag!=CLAW_PENDING )) {
                 p_clawh->flag=CLAW_BUSY;    /* 0xff */
         }
-#ifdef DEBUGMSG
-        printk(KERN_INFO "%s:%s state-%02x\n" ,
-		dev->name,__func__, p_ch->claw_state);
-#endif
         if (lock==LOCK_YES) {
                 spin_lock_irqsave(get_ccwdev_lock(p_ch->cdev), saveflags);
         }
         if (test_and_set_bit(0, (void *)&p_ch->IO_active) == 0) {
-#ifdef DEBUGMSG
-                printk(KERN_INFO "%s: HOT READ started in %s\n" ,
-			dev->name,__func__);
-                p_clawh=(struct clawh *)privptr->p_claw_signal_blk;
-                dumpit((char *)&p_clawh->flag , 1);
-#endif
-		CLAW_DBF_TEXT(4,trace,"HotRead");
+		CLAW_DBF_TEXT(4, trace, "HotRead");
                 p_ccwbk=privptr->p_read_active_first;
                 parm = (unsigned long) p_ch;
                 rc = ccw_device_start (p_ch->cdev, &p_ccwbk->read, parm,
@@ -3661,21 +2681,13 @@
                 }
         }
 	else {
-#ifdef DEBUGMSG
-		printk(KERN_INFO "%s: No READ started by %s() In progress\n" ,
-			dev->name,__func__);
-#endif
-		CLAW_DBF_TEXT(2,trace,"ReadAct");
+		CLAW_DBF_TEXT(2, trace, "ReadAct");
 	}
 
         if (lock==LOCK_YES) {
                 spin_unlock_irqrestore(get_ccwdev_lock(p_ch->cdev), saveflags);
         }
-#ifdef FUNCTRACE
-        printk(KERN_INFO "%s:%s Exit on line %d\n",
-		dev->name,__func__,__LINE__);
-#endif
-	CLAW_DBF_TEXT(4,trace,"StRdExit");
+	CLAW_DBF_TEXT(4, trace, "StRdExit");
         return;
 }       /*    end of claw_strt_read    */
 
@@ -3693,38 +2705,23 @@
         struct chbk     	*p_ch;
         struct ccwbk   	*p_first_ccw;
 
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
-#endif
 	if (!dev) {
 		return;
 	}
         privptr=(struct claw_privbk *)dev->priv;
         p_ch=&privptr->channel[WRITE];
 
-#ifdef DEBUGMSG
-        printk(KERN_INFO "%s:%s state-%02x\n" ,
-		dev->name,__func__,p_ch->claw_state);
-#endif
-        CLAW_DBF_TEXT(4,trace,"strt_io");
+	CLAW_DBF_TEXT(4, trace, "strt_io");
         p_first_ccw=privptr->p_write_active_first;
 
         if (p_ch->claw_state == CLAW_STOP)
                 return;
         if (p_first_ccw == NULL) {
-#ifdef FUNCTRACE
-                printk(KERN_INFO "%s:%s Exit on line %d\n",
-			dev->name,__func__,__LINE__);
-#endif
                 return;
         }
         if (test_and_set_bit(0, (void *)&p_ch->IO_active) == 0) {
                 parm = (unsigned long) p_ch;
-#ifdef DEBUGMSG
-		printk(KERN_INFO "%s:%s do_io \n" ,dev->name,__func__);
-                dumpit((char *)p_first_ccw, sizeof(struct ccwbk));
-#endif
-		CLAW_DBF_TEXT(2,trace,"StWrtIO");
+		CLAW_DBF_TEXT(2, trace, "StWrtIO");
                 rc = ccw_device_start (p_ch->cdev,&p_first_ccw->write, parm,
 				       0xff, 0);
                 if (rc != 0) {
@@ -3732,11 +2729,6 @@
                 }
         }
         dev->trans_start = jiffies;
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Exit on line %d\n",
-		dev->name,__func__,__LINE__);
-#endif
-
         return;
 }       /*    end of claw_strt_out_IO    */
 
@@ -3754,32 +2746,11 @@
 	struct ccwbk*p_last_ccw;
 	struct ccwbk*p_this_ccw;
 	struct ccwbk*p_next_ccw;
-#ifdef IOTRACE
-        struct ccwbk*p_buf;
-#endif
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
-        printk(KERN_INFO "%s: free count = %d  variable dev =\n",
-		dev->name,privptr->write_free_count);
-#endif
-	CLAW_DBF_TEXT(4,trace,"freewrtb");
+
+	CLAW_DBF_TEXT(4, trace, "freewrtb");
         /*  scan the write queue to free any completed write packets   */
         p_first_ccw=NULL;
         p_last_ccw=NULL;
-#ifdef IOTRACE
-        printk(KERN_INFO "%s:  Dump current CCW chain \n",dev->name  );
-        p_buf=privptr->p_write_active_first;
-        while (p_buf!=NULL) {
-                dumpit((char *)p_buf, sizeof(struct ccwbk));
-                p_buf=p_buf->next;
-        }
-        if (p_buf==NULL) {
-                printk(KERN_INFO "%s: privptr->p_write_"
-			"active_first==NULL\n",dev->name  );
-        }
-        p_buf=(struct ccwbk*)privptr->p_end_ccw;
-        dumpit((char *)p_buf, sizeof(struct endccw));
-#endif
         p_this_ccw=privptr->p_write_active_first;
         while ( (p_this_ccw!=NULL) && (p_this_ccw->header.flag!=CLAW_PENDING))
         {
@@ -3809,31 +2780,8 @@
         /*   whole chain removed?   */
         if (privptr->p_write_active_first==NULL) {
                 privptr->p_write_active_last=NULL;
-#ifdef DEBUGMSG
-                printk(KERN_INFO "%s:%s p_write_"
-			"active_first==NULL\n",dev->name,__func__);
-#endif
         }
-#ifdef IOTRACE
-        printk(KERN_INFO "%s: Dump arranged CCW chain \n",dev->name  );
-        p_buf=privptr->p_write_active_first;
-        while (p_buf!=NULL) {
-                dumpit((char *)p_buf, sizeof(struct ccwbk));
-                p_buf=p_buf->next;
-        }
-        if (p_buf==NULL) {
-                printk(KERN_INFO "%s: privptr->p_write_active_"
-			"first==NULL\n",dev->name  );
-        }
-        p_buf=(struct ccwbk*)privptr->p_end_ccw;
-        dumpit((char *)p_buf, sizeof(struct endccw));
-#endif
-
-	CLAW_DBF_TEXT_(4,trace,"FWC=%d",privptr->write_free_count);
-#ifdef FUNCTRACE
-        printk(KERN_INFO "%s:%s Exit on line %d free_count =%d\n",
-		dev->name,__func__, __LINE__,privptr->write_free_count);
-#endif
+	CLAW_DBF_TEXT_(4, trace, "FWC=%d", privptr->write_free_count);
         return;
 }
 
@@ -3845,14 +2793,11 @@
 claw_free_netdevice(struct net_device * dev, int free_dev)
 {
 	struct claw_privbk *privptr;
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
-#endif
-	CLAW_DBF_TEXT(2,setup,"free_dev");
 
+	CLAW_DBF_TEXT(2, setup, "free_dev");
 	if (!dev)
 		return;
-	CLAW_DBF_TEXT_(2,setup,"%s",dev->name);
+	CLAW_DBF_TEXT_(2, setup, "%s", dev->name);
 	privptr = dev->priv;
 	if (dev->flags & IFF_RUNNING)
 		claw_release(dev);
@@ -3865,10 +2810,7 @@
 		free_netdev(dev);
 	}
 #endif
-	CLAW_DBF_TEXT(2,setup,"feee_ok");
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Exit\n",dev->name,__func__);
-#endif
+	CLAW_DBF_TEXT(2, setup, "free_ok");
 }
 
 /**
@@ -3879,17 +2821,8 @@
 static void
 claw_init_netdevice(struct net_device * dev)
 {
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Enter\n",dev->name,__func__);
-#endif
-	CLAW_DBF_TEXT(2,setup,"init_dev");
-	CLAW_DBF_TEXT_(2,setup,"%s",dev->name);
-	if (!dev) {
-        printk(KERN_WARNING "claw:%s BAD Device exit line %d\n",
-		__func__,__LINE__);
-		CLAW_DBF_TEXT(2,setup,"baddev");
-		return;
-	}
+	CLAW_DBF_TEXT(2, setup, "init_dev");
+	CLAW_DBF_TEXT_(2, setup, "%s", dev->name);
 	dev->mtu = CLAW_DEFAULT_MTU_SIZE;
 	dev->hard_start_xmit = claw_tx;
 	dev->open = claw_open;
@@ -3901,10 +2834,7 @@
 	dev->type = ARPHRD_SLIP;
 	dev->tx_queue_len = 1300;
 	dev->flags = IFF_POINTOPOINT | IFF_NOARP;
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Exit\n",dev->name,__func__);
-#endif
-	CLAW_DBF_TEXT(2,setup,"initok");
+	CLAW_DBF_TEXT(2, setup, "initok");
 	return;
 }
 
@@ -3921,10 +2851,7 @@
 	struct chbk *p_ch;
 	struct ccw_dev_id dev_id;
 
-#ifdef FUNCTRACE
-	printk(KERN_INFO "%s:%s Enter\n",cdev->dev.bus_id,__func__);
-#endif
-	CLAW_DBF_TEXT_(2,setup,"%s",cdev->dev.bus_id);
+	CLAW_DBF_TEXT_(2, setup, "%s", cdev->dev.bus_id);
 	privptr->channel[i].flag  = i+1;   /* Read is 1 Write is 2 */
 	p_ch = &privptr->channel[i];
 	p_ch->cdev = cdev;
@@ -3932,18 +2859,8 @@
 	ccw_device_get_id(cdev, &dev_id);
 	p_ch->devno = dev_id.devno;
 	if ((p_ch->irb = kzalloc(sizeof (struct irb),GFP_KERNEL)) == NULL) {
-		printk(KERN_WARNING "%s Out of memory in %s for irb\n",
-			p_ch->id,__func__);
-#ifdef FUNCTRACE
-        	printk(KERN_INFO "%s:%s Exit on line %d\n",
-			p_ch->id,__func__,__LINE__);
-#endif
 		return -ENOMEM;
 	}
-#ifdef FUNCTRACE
-        	printk(KERN_INFO "%s:%s Exit on line %d\n",
-			cdev->dev.bus_id,__func__,__LINE__);
-#endif
 	return 0;
 }
 
@@ -3965,9 +2882,8 @@
 	int ret;
 	struct ccw_dev_id dev_id;
 
-	pr_debug("%s() called\n", __func__);
 	printk(KERN_INFO "claw: add for %s\n",cgdev->cdev[READ]->dev.bus_id);
-	CLAW_DBF_TEXT(2,setup,"new_dev");
+	CLAW_DBF_TEXT(2, setup, "new_dev");
 	privptr = cgdev->dev.driver_data;
 	cgdev->cdev[READ]->dev.driver_data = privptr;
 	cgdev->cdev[WRITE]->dev.driver_data = privptr;
@@ -3982,22 +2898,21 @@
 	if (ret == 0)
 		ret = add_channel(cgdev->cdev[1],1,privptr);
 	if (ret != 0) {
-			printk(KERN_WARNING
-		 	"add channel failed "
-				"with ret = %d\n", ret);
-			goto out;
+		printk(KERN_WARNING
+			"add channel failed with ret = %d\n", ret);
+		goto out;
 	}
 	ret = ccw_device_set_online(cgdev->cdev[READ]);
 	if (ret != 0) {
 		printk(KERN_WARNING
-		 "claw: ccw_device_set_online %s READ failed "
+			"claw: ccw_device_set_online %s READ failed "
 			"with ret = %d\n",cgdev->cdev[READ]->dev.bus_id,ret);
 		goto out;
 	}
 	ret = ccw_device_set_online(cgdev->cdev[WRITE]);
 	if (ret != 0) {
 		printk(KERN_WARNING
-		 "claw: ccw_device_set_online %s WRITE failed "
+			"claw: ccw_device_set_online %s WRITE failed "
 			"with ret = %d\n",cgdev->cdev[WRITE]->dev.bus_id, ret);
 		goto out;
 	}
@@ -4014,18 +2929,16 @@
         SET_NETDEV_DEV(dev, &cgdev->dev);
 	if (register_netdev(dev) != 0) {
 		claw_free_netdevice(dev, 1);
-		CLAW_DBF_TEXT(2,trace,"regfail");
+		CLAW_DBF_TEXT(2, trace, "regfail");
 		goto out;
 	}
 	dev->flags &=~IFF_RUNNING;
 	if (privptr->buffs_alloc == 0) {
 	        ret=init_ccw_bk(dev);
 		if (ret !=0) {
-			printk(KERN_WARNING
-			 "claw: init_ccw_bk failed with ret=%d\n", ret);
 			unregister_netdev(dev);
 			claw_free_netdevice(dev,1);
-			CLAW_DBF_TEXT(2,trace,"ccwmem");
+			CLAW_DBF_TEXT(2, trace, "ccwmem");
 			goto out;
 		}
 	}
@@ -4047,7 +2960,6 @@
 out:
 	ccw_device_set_offline(cgdev->cdev[1]);
 	ccw_device_set_offline(cgdev->cdev[0]);
-
 	return -ENODEV;
 }
 
@@ -4056,8 +2968,7 @@
 {
         struct sk_buff *skb;
 
-        CLAW_DBF_TEXT(4,trace,"purgque");
-
+	CLAW_DBF_TEXT(4, trace, "purgque");
         while ((skb = skb_dequeue(q))) {
                 atomic_dec(&skb->users);
                 dev_kfree_skb_any(skb);
@@ -4078,8 +2989,7 @@
 	struct net_device *ndev;
 	int	ret;
 
-	pr_debug("%s() called\n", __func__);
-	CLAW_DBF_TEXT_(2,setup,"%s",cgdev->dev.bus_id);
+	CLAW_DBF_TEXT_(2, setup, "%s", cgdev->dev.bus_id);
 	priv = cgdev->dev.driver_data;
 	if (!priv)
 		return -ENODEV;
@@ -4108,13 +3018,10 @@
 {
 	struct claw_privbk *priv;
 
-	pr_debug("%s() called\n", __func__);
-	CLAW_DBF_TEXT_(2,setup,"%s",cgdev->dev.bus_id);
+	BUG_ON(!cgdev);
+	CLAW_DBF_TEXT_(2, setup, "%s", cgdev->dev.bus_id);
 	priv = cgdev->dev.driver_data;
-	if (!priv) {
-		printk(KERN_WARNING "claw: %s() no Priv exiting\n",__func__);
-		return;
-	}
+	BUG_ON(!priv);
 	printk(KERN_INFO "claw: %s() called %s will be removed.\n",
 			__func__,cgdev->cdev[0]->dev.bus_id);
 	if (cgdev->state == CCWGROUP_ONLINE)
@@ -4133,6 +3040,8 @@
 	cgdev->cdev[READ]->dev.driver_data = NULL;
 	cgdev->cdev[WRITE]->dev.driver_data = NULL;
 	put_device(&cgdev->dev);
+
+	return;
 }
 
 
@@ -4168,8 +3077,8 @@
 	strncpy(p_env->host_name,buf, count);
 	p_env->host_name[count-1] = 0x20;  /* clear extra 0x0a */
 	p_env->host_name[MAX_NAME_LEN] = 0x00;
-	CLAW_DBF_TEXT(2,setup,"HstnSet");
-        CLAW_DBF_TEXT_(2,setup,"%s",p_env->host_name);
+	CLAW_DBF_TEXT(2, setup, "HstnSet");
+	CLAW_DBF_TEXT_(2, setup, "%s", p_env->host_name);
 
 	return count;
 }
@@ -4186,7 +3095,7 @@
 	if (!priv)
 		return -ENODEV;
 	p_env = priv->p_env;
-	return sprintf(buf, "%s\n",p_env->adapter_name);
+	return sprintf(buf, "%s\n", p_env->adapter_name);
 }
 
 static ssize_t
@@ -4205,8 +3114,8 @@
 	strncpy(p_env->adapter_name,buf, count);
 	p_env->adapter_name[count-1] = 0x20; /* clear extra 0x0a */
 	p_env->adapter_name[MAX_NAME_LEN] = 0x00;
-	CLAW_DBF_TEXT(2,setup,"AdnSet");
-	CLAW_DBF_TEXT_(2,setup,"%s",p_env->adapter_name);
+	CLAW_DBF_TEXT(2, setup, "AdnSet");
+	CLAW_DBF_TEXT_(2, setup, "%s", p_env->adapter_name);
 
 	return count;
 }
@@ -4247,15 +3156,15 @@
 		p_env->read_size=DEF_PACK_BUFSIZE;
 		p_env->write_size=DEF_PACK_BUFSIZE;
 		p_env->packing=PACKING_ASK;
-		CLAW_DBF_TEXT(2,setup,"PACKING");
+		CLAW_DBF_TEXT(2, setup, "PACKING");
 	}
 	else {
 		p_env->packing=0;
 		p_env->read_size=CLAW_FRAME_SIZE;
 		p_env->write_size=CLAW_FRAME_SIZE;
-		CLAW_DBF_TEXT(2,setup,"ApiSet");
+		CLAW_DBF_TEXT(2, setup, "ApiSet");
 	}
-	CLAW_DBF_TEXT_(2,setup,"%s",p_env->api_type);
+	CLAW_DBF_TEXT_(2, setup, "%s", p_env->api_type);
 	return count;
 }
 
@@ -4295,8 +3204,8 @@
 	if ((nnn > max ) || (nnn < 2))
 		return -EINVAL;
 	p_env->write_buffers = nnn;
-	CLAW_DBF_TEXT(2,setup,"Wbufset");
-        CLAW_DBF_TEXT_(2,setup,"WB=%d",p_env->write_buffers);
+	CLAW_DBF_TEXT(2, setup, "Wbufset");
+	CLAW_DBF_TEXT_(2, setup, "WB=%d", p_env->write_buffers);
 	return count;
 }
 
@@ -4336,8 +3245,8 @@
 	if ((nnn > max ) || (nnn < 2))
 		return -EINVAL;
 	p_env->read_buffers = nnn;
-	CLAW_DBF_TEXT(2,setup,"Rbufset");
-	CLAW_DBF_TEXT_(2,setup,"RB=%d",p_env->read_buffers);
+	CLAW_DBF_TEXT(2, setup, "Rbufset");
+	CLAW_DBF_TEXT_(2, setup, "RB=%d", p_env->read_buffers);
 	return count;
 }
 
@@ -4359,16 +3268,14 @@
 static int
 claw_add_files(struct device *dev)
 {
-	pr_debug("%s() called\n", __func__);
-	CLAW_DBF_TEXT(2,setup,"add_file");
+	CLAW_DBF_TEXT(2, setup, "add_file");
 	return sysfs_create_group(&dev->kobj, &claw_attr_group);
 }
 
 static void
 claw_remove_files(struct device *dev)
 {
-	pr_debug("%s() called\n", __func__);
-	CLAW_DBF_TEXT(2,setup,"rem_file");
+	CLAW_DBF_TEXT(2, setup, "rem_file");
 	sysfs_remove_group(&dev->kobj, &claw_attr_group);
 }
 
@@ -4397,35 +3304,27 @@
 	int ret = 0;
 	printk(KERN_INFO "claw: starting driver\n");
 
-#ifdef FUNCTRACE
-	printk(KERN_INFO "claw: %s() enter \n",__func__);
-#endif
 	ret = claw_register_debug_facility();
 	if (ret) {
 		printk(KERN_WARNING "claw: %s() debug_register failed %d\n",
 			__func__,ret);
 		return ret;
 	}
-	CLAW_DBF_TEXT(2,setup,"init_mod");
+	CLAW_DBF_TEXT(2, setup, "init_mod");
 	ret = register_cu3088_discipline(&claw_group_driver);
 	if (ret) {
+		CLAW_DBF_TEXT(2, setup, "init_bad");
 		claw_unregister_debug_facility();
 		printk(KERN_WARNING "claw; %s() cu3088 register failed %d\n",
 			__func__,ret);
 	}
-#ifdef FUNCTRACE
-	printk(KERN_INFO "claw: %s() exit \n",__func__);
-#endif
 	return ret;
 }
 
 module_init(claw_init);
 module_exit(claw_cleanup);
 
-
-
-/*--------------------------------------------------------------------*
-*    End of File                                                      *
-*---------------------------------------------------------------------*/
-
-
+MODULE_AUTHOR("Andy Richter <richtera@us.ibm.com>");
+MODULE_DESCRIPTION("Linux for System z CLAW Driver\n" \
+			"Copyright 2000,2008 IBM Corporation\n");
+MODULE_LICENSE("GPL");
diff --git a/drivers/s390/net/ctcm_dbug.c b/drivers/s390/net/ctcm_dbug.c
index 8eb25d0..1ca58f1 100644
--- a/drivers/s390/net/ctcm_dbug.c
+++ b/drivers/s390/net/ctcm_dbug.c
@@ -7,6 +7,7 @@
  */
 
 #include <linux/stddef.h>
+#include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
@@ -22,15 +23,13 @@
  * Debug Facility Stuff
  */
 
-DEFINE_PER_CPU(char[256], ctcm_dbf_txt_buf);
-
 struct ctcm_dbf_info ctcm_dbf[CTCM_DBF_INFOS] = {
-	[CTCM_DBF_SETUP]	= {"ctc_setup", 8, 1, 64, 5, NULL},
-	[CTCM_DBF_ERROR]	= {"ctc_error", 8, 1, 64, 3, NULL},
-	[CTCM_DBF_TRACE]	= {"ctc_trace", 8, 1, 64, 3, NULL},
-	[CTCM_DBF_MPC_SETUP]	= {"mpc_setup", 8, 1, 64, 5, NULL},
-	[CTCM_DBF_MPC_ERROR]	= {"mpc_error", 8, 1, 64, 3, NULL},
-	[CTCM_DBF_MPC_TRACE]	= {"mpc_trace", 8, 1, 64, 3, NULL},
+	[CTCM_DBF_SETUP]     = {"ctc_setup", 8, 1, 64, CTC_DBF_INFO, NULL},
+	[CTCM_DBF_ERROR]     = {"ctc_error", 8, 1, 64, CTC_DBF_ERROR, NULL},
+	[CTCM_DBF_TRACE]     = {"ctc_trace", 8, 1, 64, CTC_DBF_ERROR, NULL},
+	[CTCM_DBF_MPC_SETUP] = {"mpc_setup", 8, 1, 80, CTC_DBF_INFO, NULL},
+	[CTCM_DBF_MPC_ERROR] = {"mpc_error", 8, 1, 80, CTC_DBF_ERROR, NULL},
+	[CTCM_DBF_MPC_TRACE] = {"mpc_trace", 8, 1, 80, CTC_DBF_ERROR, NULL},
 };
 
 void ctcm_unregister_dbf_views(void)
@@ -65,3 +64,17 @@
 	return 0;
 }
 
+void ctcm_dbf_longtext(enum ctcm_dbf_names dbf_nix, int level, char *fmt, ...)
+{
+	char dbf_txt_buf[64];
+	va_list args;
+
+	if (level > (ctcm_dbf[dbf_nix].id)->level)
+		return;
+	va_start(args, fmt);
+	vsnprintf(dbf_txt_buf, sizeof(dbf_txt_buf), fmt, args);
+	va_end(args);
+
+	debug_text_event(ctcm_dbf[dbf_nix].id, level, dbf_txt_buf);
+}
+
diff --git a/drivers/s390/net/ctcm_dbug.h b/drivers/s390/net/ctcm_dbug.h
index fdff34f..26966d0 100644
--- a/drivers/s390/net/ctcm_dbug.h
+++ b/drivers/s390/net/ctcm_dbug.h
@@ -20,16 +20,17 @@
 #else
  #define do_debug 0
 #endif
+#ifdef DEBUGCCW
+ #define do_debug_ccw 1
+ #define DEBUGDATA 1
+#else
+ #define do_debug_ccw 0
+#endif
 #ifdef DEBUGDATA
  #define do_debug_data 1
 #else
  #define do_debug_data 0
 #endif
-#ifdef DEBUGCCW
- #define do_debug_ccw 1
-#else
- #define do_debug_ccw 0
-#endif
 
 /* define dbf debug levels similar to kernel msg levels */
 #define	CTC_DBF_ALWAYS	0	/* always print this 			*/
@@ -42,8 +43,6 @@
 #define	CTC_DBF_INFO	5	/* informational			*/
 #define	CTC_DBF_DEBUG	6	/* debug-level messages			*/
 
-DECLARE_PER_CPU(char[256], ctcm_dbf_txt_buf);
-
 enum ctcm_dbf_names {
 	CTCM_DBF_SETUP,
 	CTCM_DBF_ERROR,
@@ -67,6 +66,7 @@
 
 int ctcm_register_dbf_views(void);
 void ctcm_unregister_dbf_views(void);
+void ctcm_dbf_longtext(enum ctcm_dbf_names dbf_nix, int level, char *text, ...);
 
 static inline const char *strtail(const char *s, int n)
 {
@@ -74,12 +74,6 @@
 	return (l > n) ? s + (l - n) : s;
 }
 
-/* sort out levels early to avoid unnecessary sprintfs */
-static inline int ctcm_dbf_passes(debug_info_t *dbf_grp, int level)
-{
-	return (dbf_grp->level >= level);
-}
-
 #define CTCM_FUNTAIL strtail((char *)__func__, 16)
 
 #define CTCM_DBF_TEXT(name, level, text) \
@@ -94,16 +88,7 @@
 	} while (0)
 
 #define CTCM_DBF_TEXT_(name, level, text...) \
-	do { \
-		if (ctcm_dbf_passes(ctcm_dbf[CTCM_DBF_##name].id, level)) { \
-			char *ctcm_dbf_txt_buf = \
-					 get_cpu_var(ctcm_dbf_txt_buf); \
-			sprintf(ctcm_dbf_txt_buf, text); \
-			debug_text_event(ctcm_dbf[CTCM_DBF_##name].id, \
-					level, ctcm_dbf_txt_buf); \
-			put_cpu_var(ctcm_dbf_txt_buf); \
-		} \
-	} while (0)
+	ctcm_dbf_longtext(CTCM_DBF_##name, level, text)
 
 /*
  * cat : one of {setup, mpc_setup, trace, mpc_trace, error, mpc_error}.
@@ -112,13 +97,13 @@
  */
 #define CTCM_DBF_DEV_NAME(cat, dev, text) \
 	do { \
-		CTCM_DBF_TEXT_(cat, CTC_DBF_INFO, "%s(%s) : %s", \
+		CTCM_DBF_TEXT_(cat, CTC_DBF_INFO, "%s(%s) :- %s", \
 			CTCM_FUNTAIL, dev->name, text); \
 	} while (0)
 
 #define MPC_DBF_DEV_NAME(cat, dev, text) \
 	do { \
-		CTCM_DBF_TEXT_(MPC_##cat, CTC_DBF_INFO, "%s(%s) : %s", \
+		CTCM_DBF_TEXT_(MPC_##cat, CTC_DBF_INFO, "%s(%s) := %s", \
 			CTCM_FUNTAIL, dev->name, text); \
 	} while (0)
 
@@ -137,13 +122,13 @@
  */
 #define CTCM_DBF_DEV(cat, dev, text) \
 	do { \
-		CTCM_DBF_TEXT_(cat, CTC_DBF_INFO, "%s(%p) : %s", \
+		CTCM_DBF_TEXT_(cat, CTC_DBF_INFO, "%s(%p) :-: %s", \
 			CTCM_FUNTAIL, dev, text); \
 	} while (0)
 
 #define MPC_DBF_DEV(cat, dev, text) \
 	do { \
-		CTCM_DBF_TEXT_(MPC_##cat, CTC_DBF_INFO, "%s(%p) : %s", \
+		CTCM_DBF_TEXT_(MPC_##cat, CTC_DBF_INFO, "%s(%p) :=: %s", \
 			CTCM_FUNTAIL, dev, text); \
 	} while (0)
 
diff --git a/drivers/s390/net/ctcm_fsms.c b/drivers/s390/net/ctcm_fsms.c
index 7e6bd38..0b4e625 100644
--- a/drivers/s390/net/ctcm_fsms.c
+++ b/drivers/s390/net/ctcm_fsms.c
@@ -190,7 +190,8 @@
 void ctcm_ccw_check_rc(struct channel *ch, int rc, char *msg)
 {
 	CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
-			"ccw error %s (%s): %04x\n", ch->id, msg, rc);
+			"%s(%s): %s: %04x\n",
+				CTCM_FUNTAIL, ch->id, msg, rc);
 	switch (rc) {
 	case -EBUSY:
 		ctcm_pr_warn("%s (%s): Busy !\n", ch->id, msg);
@@ -212,7 +213,7 @@
 {
 	struct sk_buff *skb;
 
-	CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
+	CTCM_DBF_TEXT(TRACE, CTC_DBF_DEBUG, __func__);
 
 	while ((skb = skb_dequeue(q))) {
 		atomic_dec(&skb->users);
@@ -251,6 +252,8 @@
 	unsigned long duration;
 	struct timespec done_stamp = current_kernel_time(); /* xtime */
 
+	CTCM_PR_DEBUG("%s(%s): %s\n", __func__, ch->id, dev->name);
+
 	duration =
 	    (done_stamp.tv_sec - ch->prof.send_stamp.tv_sec) * 1000000 +
 	    (done_stamp.tv_nsec - ch->prof.send_stamp.tv_nsec) / 1000;
@@ -258,8 +261,9 @@
 		ch->prof.tx_time = duration;
 
 	if (ch->irb->scsw.cmd.count != 0)
-		ctcm_pr_debug("%s: TX not complete, remaining %d bytes\n",
-			     dev->name, ch->irb->scsw.cmd.count);
+		CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
+			"%s(%s): TX not complete, remaining %d bytes",
+			     CTCM_FUNTAIL, dev->name, ch->irb->scsw.cmd.count);
 	fsm_deltimer(&ch->timer);
 	while ((skb = skb_dequeue(&ch->io_queue))) {
 		priv->stats.tx_packets++;
@@ -334,7 +338,8 @@
 	struct net_device *dev = ch->netdev;
 	struct ctcm_priv *priv = dev->priv;
 
-	CTCM_DBF_TEXT(TRACE, 6, __FUNCTION__);
+	CTCM_PR_DEBUG("%s(%s): %s\n", __func__, ch->id, dev->name);
+
 	fsm_deltimer(&ch->timer);
 	fsm_newstate(fi, CTC_STATE_TXIDLE);
 	fsm_event(priv->fsm, DEV_EVENT_TXUP, ch->netdev);
@@ -361,15 +366,17 @@
 
 	fsm_deltimer(&ch->timer);
 	if (len < 8) {
-		ctcm_pr_debug("%s: got packet with length %d < 8\n",
-			     dev->name, len);
+		CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
+			"%s(%s): got packet with length %d < 8\n",
+					CTCM_FUNTAIL, dev->name, len);
 		priv->stats.rx_dropped++;
 		priv->stats.rx_length_errors++;
 						goto again;
 	}
 	if (len > ch->max_bufsize) {
-		ctcm_pr_debug("%s: got packet with length %d > %d\n",
-			     dev->name, len, ch->max_bufsize);
+		CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
+			"%s(%s): got packet with length %d > %d\n",
+				CTCM_FUNTAIL, dev->name, len, ch->max_bufsize);
 		priv->stats.rx_dropped++;
 		priv->stats.rx_length_errors++;
 						goto again;
@@ -388,8 +395,9 @@
 		break;
 	}
 	if ((len < block_len) || (len > check_len)) {
-		ctcm_pr_debug("%s: got block length %d != rx length %d\n",
-			     dev->name, block_len, len);
+		CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
+			"%s(%s): got block length %d != rx length %d\n",
+				CTCM_FUNTAIL, dev->name, block_len, len);
 		if (do_debug)
 			ctcmpc_dump_skb(skb, 0);
 
@@ -425,17 +433,23 @@
  */
 static void chx_firstio(fsm_instance *fi, int event, void *arg)
 {
-	struct channel *ch = arg;
 	int rc;
+	struct channel *ch = arg;
+	int fsmstate = fsm_getstate(fi);
 
-	CTCM_DBF_TEXT(TRACE, 6, __FUNCTION__);
+	CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
+		"%s(%s) : %02x",
+		CTCM_FUNTAIL, ch->id, fsmstate);
 
-	if (fsm_getstate(fi) == CTC_STATE_TXIDLE)
-		ctcm_pr_debug("%s: remote side issued READ?, init.\n", ch->id);
+	ch->sense_rc = 0;	/* reset unit check report control */
+	if (fsmstate == CTC_STATE_TXIDLE)
+		CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
+			"%s(%s): remote side issued READ?, init.\n",
+				CTCM_FUNTAIL, ch->id);
 	fsm_deltimer(&ch->timer);
 	if (ctcm_checkalloc_buffer(ch))
 		return;
-	if ((fsm_getstate(fi) == CTC_STATE_SETUPWAIT) &&
+	if ((fsmstate == CTC_STATE_SETUPWAIT) &&
 	    (ch->protocol == CTCM_PROTO_OS390)) {
 		/* OS/390 resp. z/OS */
 		if (CHANNEL_DIRECTION(ch->flags) == READ) {
@@ -451,7 +465,6 @@
 		}
 		return;
 	}
-
 	/*
 	 * Don't setup a timer for receiving the initial RX frame
 	 * if in compatibility mode, since VM TCP delays the initial
@@ -505,11 +518,10 @@
 	__u16 buflen;
 	int rc;
 
-	CTCM_DBF_TEXT(TRACE, 6, __FUNCTION__);
 	fsm_deltimer(&ch->timer);
 	buflen = *((__u16 *)ch->trans_skb->data);
-	if (do_debug)
-		ctcm_pr_debug("%s: Initial RX count %d\n", dev->name, buflen);
+	CTCM_PR_DEBUG("%s: %s: Initial RX count = %d\n",
+			__func__, dev->name, buflen);
 
 	if (buflen >= CTCM_INITIAL_BLOCKLEN) {
 		if (ctcm_checkalloc_buffer(ch))
@@ -524,9 +536,9 @@
 		} else
 			fsm_event(priv->fsm, DEV_EVENT_RXUP, dev);
 	} else {
-		if (do_debug)
-			ctcm_pr_debug("%s: Initial RX count %d not %d\n",
-				dev->name, buflen, CTCM_INITIAL_BLOCKLEN);
+		CTCM_PR_DEBUG("%s: %s: Initial RX count %d not %d\n",
+				__func__, dev->name,
+					buflen, CTCM_INITIAL_BLOCKLEN);
 		chx_firstio(fi, event, arg);
 	}
 }
@@ -548,14 +560,12 @@
 	fsm_deltimer(&ch->timer);
 	if (IS_MPC(ch)) {
 		timeout = 1500;
-		if (do_debug)
-			ctcm_pr_debug("ctcm enter: %s(): cp=%i ch=0x%p id=%s\n",
-				__FUNCTION__, smp_processor_id(), ch, ch->id);
+		CTCM_PR_DEBUG("enter %s: cp=%i ch=0x%p id=%s\n",
+				__func__, smp_processor_id(), ch, ch->id);
 	}
 	fsm_addtimer(&ch->timer, timeout, CTC_EVENT_TIMER, ch);
 	fsm_newstate(fi, CTC_STATE_SETUPWAIT);
-	if (do_debug_ccw && IS_MPC(ch))
-		ctcmpc_dumpit((char *)&ch->ccw[6], sizeof(struct ccw1) * 2);
+	CTCM_CCW_DUMP((char *)&ch->ccw[6], sizeof(struct ccw1) * 2);
 
 	if (event == CTC_EVENT_TIMER)	/* only for timer not yet locked */
 		spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
@@ -583,24 +593,12 @@
  */
 static void ctcm_chx_start(fsm_instance *fi, int event, void *arg)
 {
-	struct channel *ch = arg;
-	int rc;
-	struct net_device *dev;
+	struct channel *ch	= arg;
 	unsigned long saveflags;
+	int rc;
 
-	CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__);
-	if (ch == NULL) {
-		ctcm_pr_warn("chx_start ch=NULL\n");
-		return;
-	}
-	if (ch->netdev == NULL) {
-		ctcm_pr_warn("chx_start dev=NULL, id=%s\n", ch->id);
-		return;
-	}
-	dev = ch->netdev;
-
-	if (do_debug)
-		ctcm_pr_debug("%s: %s channel start\n", dev->name,
+	CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s(%s): %s",
+			CTCM_FUNTAIL, ch->id,
 			(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
 
 	if (ch->trans_skb != NULL) {
@@ -618,11 +616,12 @@
 		ch->ccw[1].count = 0;
 	}
 	if (ctcm_checkalloc_buffer(ch)) {
-		ctcm_pr_notice("%s: %s trans_skb allocation delayed "
-				"until first transfer\n", dev->name,
+		CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
+			"%s(%s): %s trans_skb alloc delayed "
+			"until first transfer",
+			CTCM_FUNTAIL, ch->id,
 			(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
 	}
-
 	ch->ccw[0].cmd_code = CCW_CMD_PREPARE;
 	ch->ccw[0].flags = CCW_FLAG_SLI | CCW_FLAG_CC;
 	ch->ccw[0].count = 0;
@@ -661,7 +660,6 @@
 	int rc;
 	int oldstate;
 
-	CTCM_DBF_TEXT(TRACE, 2, __FUNCTION__);
 	fsm_deltimer(&ch->timer);
 	if (IS_MPC(ch))
 		fsm_deltimer(&ch->sweep_timer);
@@ -684,7 +682,7 @@
 		fsm_deltimer(&ch->timer);
 		if (event != CTC_EVENT_STOP) {
 			fsm_newstate(fi, oldstate);
-			ctcm_ccw_check_rc(ch, rc, (char *)__FUNCTION__);
+			ctcm_ccw_check_rc(ch, rc, (char *)__func__);
 		}
 	}
 }
@@ -703,7 +701,9 @@
 	struct net_device *dev = ch->netdev;
 	struct ctcm_priv *priv = dev->priv;
 
-	CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
+	CTCM_DBF_TEXT_(SETUP, CTC_DBF_NOTICE,
+			"%s(%s): %s[%d]\n",
+			CTCM_FUNTAIL, dev->name, ch->id, state);
 
 	fsm_deltimer(&ch->timer);
 	if (IS_MPC(ch))
@@ -743,7 +743,6 @@
  */
 static void ctcm_chx_stopped(fsm_instance *fi, int event, void *arg)
 {
-	CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
 	ctcm_chx_cleanup(fi, CTC_STATE_STOPPED, arg);
 }
 
@@ -771,7 +770,6 @@
  */
 static void ctcm_chx_fail(fsm_instance *fi, int event, void *arg)
 {
-	CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
 	ctcm_chx_cleanup(fi, CTC_STATE_NOTOP, arg);
 }
 
@@ -809,8 +807,8 @@
 	}
 
 	CTCM_DBF_TEXT_(ERROR, CTC_DBF_CRIT,
-		"%s : %s error during %s channel setup state=%s\n",
-		dev->name, ctc_ch_event_names[event],
+		"%s(%s) : %s error during %s channel setup state=%s\n",
+		CTCM_FUNTAIL, dev->name, ctc_ch_event_names[event],
 		(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX",
 		fsm_getstate_str(fi));
 
@@ -838,10 +836,12 @@
 	int oldstate;
 	int rc;
 
-	CTCM_DBF_TEXT(TRACE, CTC_DBF_NOTICE, __FUNCTION__);
+	CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
+		"%s: %s[%d] of %s\n",
+			CTCM_FUNTAIL, ch->id, event, dev->name);
+
 	fsm_deltimer(&ch->timer);
-	ctcm_pr_debug("%s: %s channel restart\n", dev->name,
-		     (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+
 	fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch);
 	oldstate = fsm_getstate(fi);
 	fsm_newstate(fi, CTC_STATE_STARTWAIT);
@@ -876,13 +876,10 @@
 	struct net_device *dev = ch->netdev;
 	struct ctcm_priv *priv = dev->priv;
 
-	CTCM_DBF_TEXT(SETUP, 3, __FUNCTION__);
 	if (event == CTC_EVENT_TIMER) {
 		if (!IS_MPCDEV(dev))
 			/* TODO : check if MPC deletes timer somewhere */
 			fsm_deltimer(&ch->timer);
-		ctcm_pr_debug("%s: Timeout during RX init handshake\n",
-				dev->name);
 		if (ch->retry++ < 3)
 			ctcm_chx_restart(fi, event, arg);
 		else {
@@ -907,9 +904,10 @@
 	struct net_device *dev = ch->netdev;
 	struct ctcm_priv *priv = dev->priv;
 
-	CTCM_DBF_TEXT(SETUP, 3, __FUNCTION__);
+	CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+			"%s(%s): RX %s busy, init. fail",
+				CTCM_FUNTAIL, dev->name, ch->id);
 	fsm_newstate(fi, CTC_STATE_RXERR);
-	ctcm_pr_warn("%s: RX busy. Initialization failed\n", dev->name);
 	fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
 }
 
@@ -927,11 +925,10 @@
 	struct net_device *dev = ch->netdev;
 	struct ctcm_priv *priv = dev->priv;
 
-	CTCM_DBF_DEV_NAME(TRACE, dev, "Got remote disconnect, re-initializing");
+	CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
+			"%s: %s: remote disconnect - re-init ...",
+				CTCM_FUNTAIL, dev->name);
 	fsm_deltimer(&ch->timer);
-	if (do_debug)
-		ctcm_pr_debug("%s: Got remote disconnect, "
-				"re-initializing ...\n", dev->name);
 	/*
 	 * Notify device statemachine
 	 */
@@ -961,8 +958,6 @@
 
 	if (event == CTC_EVENT_TIMER) {
 		fsm_deltimer(&ch->timer);
-		CTCM_DBF_DEV_NAME(ERROR, dev,
-				"Timeout during TX init handshake");
 		if (ch->retry++ < 3)
 			ctcm_chx_restart(fi, event, arg);
 		else {
@@ -971,9 +966,8 @@
 		}
 	} else {
 		CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
-			"%s : %s error during channel setup state=%s",
-			dev->name, ctc_ch_event_names[event],
-			fsm_getstate_str(fi));
+			"%s(%s): %s in %s", CTCM_FUNTAIL, ch->id,
+			ctc_ch_event_names[event], fsm_getstate_str(fi));
 
 		ctcm_pr_warn("%s: Error during TX init handshake\n", dev->name);
 	}
@@ -993,15 +987,15 @@
 	struct ctcm_priv *priv = dev->priv;
 	struct sk_buff *skb;
 
-	if (do_debug)
-		ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
-			__FUNCTION__, smp_processor_id(), ch, ch->id);
+	CTCM_PR_DEBUG("Enter: %s: cp=%i ch=0x%p id=%s\n",
+			__func__, smp_processor_id(), ch, ch->id);
 
 	fsm_deltimer(&ch->timer);
 	if (ch->retry++ > 3) {
 		struct mpc_group *gptr = priv->mpcg;
-		ctcm_pr_debug("%s: TX retry failed, restarting channel\n",
-			     dev->name);
+		CTCM_DBF_TEXT_(TRACE, CTC_DBF_INFO,
+				"%s: %s: retries exceeded",
+					CTCM_FUNTAIL, ch->id);
 		fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
 		/* call restart if not MPC or if MPC and mpcg fsm is ready.
 			use gptr as mpc indicator */
@@ -1010,7 +1004,9 @@
 				goto done;
 	}
 
-	ctcm_pr_debug("%s: TX retry %d\n", dev->name, ch->retry);
+	CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
+			"%s : %s: retry %d",
+				CTCM_FUNTAIL, ch->id, ch->retry);
 	skb = skb_peek(&ch->io_queue);
 	if (skb) {
 		int rc = 0;
@@ -1018,8 +1014,9 @@
 		clear_normalized_cda(&ch->ccw[4]);
 		ch->ccw[4].count = skb->len;
 		if (set_normalized_cda(&ch->ccw[4], skb->data)) {
-			ctcm_pr_debug("%s: IDAL alloc failed, chan restart\n",
-						dev->name);
+			CTCM_DBF_TEXT_(TRACE, CTC_DBF_INFO,
+				"%s: %s: IDAL alloc failed",
+						CTCM_FUNTAIL, ch->id);
 			fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
 			ctcm_chx_restart(fi, event, arg);
 				goto done;
@@ -1061,22 +1058,21 @@
 	struct channel *ch = arg;
 	struct net_device *dev = ch->netdev;
 	struct ctcm_priv *priv = dev->priv;
+	int rd = CHANNEL_DIRECTION(ch->flags);
 
-	CTCM_DBF_TEXT(TRACE, 3, __FUNCTION__);
 	fsm_deltimer(&ch->timer);
-	ctcm_pr_warn("%s %s : unrecoverable channel error\n",
-			CTC_DRIVER_NAME, dev->name);
+	CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+		"%s: %s: %s unrecoverable channel error",
+			CTCM_FUNTAIL, ch->id, rd == READ ? "RX" : "TX");
+
 	if (IS_MPC(ch)) {
 		priv->stats.tx_dropped++;
 		priv->stats.tx_errors++;
 	}
-
-	if (CHANNEL_DIRECTION(ch->flags) == READ) {
-		ctcm_pr_debug("%s: RX I/O error\n", dev->name);
+	if (rd == READ) {
 		fsm_newstate(fi, CTC_STATE_RXERR);
 		fsm_event(priv->fsm, DEV_EVENT_RXDOWN, dev);
 	} else {
-		ctcm_pr_debug("%s: TX I/O error\n", dev->name);
 		fsm_newstate(fi, CTC_STATE_TXERR);
 		fsm_event(priv->fsm, DEV_EVENT_TXDOWN, dev);
 	}
@@ -1216,27 +1212,27 @@
 	struct sk_buff		*skb;
 	int		first = 1;
 	int		i;
-	struct timespec done_stamp;
 	__u32		data_space;
 	unsigned long	duration;
 	struct sk_buff	*peekskb;
 	int		rc;
 	struct th_header *header;
 	struct pdu	*p_header;
+	struct timespec done_stamp = current_kernel_time(); /* xtime */
 
-	if (do_debug)
-		ctcm_pr_debug("%s cp:%i enter:  %s()\n",
-			dev->name, smp_processor_id(), __FUNCTION__);
+	CTCM_PR_DEBUG("Enter %s: %s cp:%i\n",
+			__func__, dev->name, smp_processor_id());
 
-	done_stamp = current_kernel_time(); /* xtime */
-	duration = (done_stamp.tv_sec - ch->prof.send_stamp.tv_sec) * 1000000
-		+ (done_stamp.tv_nsec - ch->prof.send_stamp.tv_nsec) / 1000;
+	duration =
+		(done_stamp.tv_sec - ch->prof.send_stamp.tv_sec) * 1000000 +
+		(done_stamp.tv_nsec - ch->prof.send_stamp.tv_nsec) / 1000;
 	if (duration > ch->prof.tx_time)
 		ch->prof.tx_time = duration;
 
 	if (ch->irb->scsw.cmd.count != 0)
-		ctcm_pr_debug("%s: TX not complete, remaining %d bytes\n",
-				dev->name, ch->irb->scsw.cmd.count);
+		CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
+			"%s(%s): TX not complete, remaining %d bytes",
+			     CTCM_FUNTAIL, dev->name, ch->irb->scsw.cmd.count);
 	fsm_deltimer(&ch->timer);
 	while ((skb = skb_dequeue(&ch->io_queue))) {
 		priv->stats.tx_packets++;
@@ -1250,7 +1246,6 @@
 	}
 	spin_lock(&ch->collect_lock);
 	clear_normalized_cda(&ch->ccw[4]);
-
 	if ((ch->collect_len <= 0) || (grp->in_sweep != 0)) {
 		spin_unlock(&ch->collect_lock);
 		fsm_newstate(fi, CTC_STATE_TXIDLE);
@@ -1269,17 +1264,13 @@
 	if (ch->prof.maxcqueue < skb_queue_len(&ch->collect_queue))
 		ch->prof.maxcqueue = skb_queue_len(&ch->collect_queue);
 	i = 0;
-
-	if (do_debug_data)
-		ctcm_pr_debug("ctcmpc: %s() building "
-			       "trans_skb from collect_q \n", __FUNCTION__);
-
+	p_header = NULL;
 	data_space = grp->group_max_buflen - TH_HEADER_LENGTH;
 
-	if (do_debug_data)
-		ctcm_pr_debug("ctcmpc: %s() building trans_skb from collect_q"
-		       " data_space:%04x\n", __FUNCTION__, data_space);
-	p_header = NULL;
+	CTCM_PR_DBGDATA("%s: building trans_skb from collect_q"
+		       " data_space:%04x\n",
+		       __func__, data_space);
+
 	while ((skb = skb_dequeue(&ch->collect_queue))) {
 		memcpy(skb_put(ch->trans_skb, skb->len), skb->data, skb->len);
 		p_header = (struct pdu *)
@@ -1290,15 +1281,12 @@
 		else
 			p_header->pdu_flag |= 0x20;
 
-		if (do_debug_data) {
-			ctcm_pr_debug("ctcmpc: %s()trans_skb len:%04x \n",
-				       __FUNCTION__, ch->trans_skb->len);
-			ctcm_pr_debug("ctcmpc: %s() pdu header and data"
-				       " for up to 32 bytes sent to vtam\n",
-				       __FUNCTION__);
-			ctcmpc_dumpit((char *)p_header,
-						min_t(int, skb->len, 32));
-		}
+		CTCM_PR_DBGDATA("%s: trans_skb len:%04x \n",
+				__func__, ch->trans_skb->len);
+		CTCM_PR_DBGDATA("%s: pdu header and data for up"
+				" to 32 bytes sent to vtam\n", __func__);
+		CTCM_D3_DUMP((char *)p_header, min_t(int, skb->len, 32));
+
 		ch->collect_len -= skb->len;
 		data_space -= skb->len;
 		priv->stats.tx_packets++;
@@ -1314,46 +1302,38 @@
 	if (p_header)
 		p_header->pdu_flag |= PDU_LAST;	/*Say it's the last one*/
 	header = kzalloc(TH_HEADER_LENGTH, gfp_type());
-
 	if (!header) {
-		printk(KERN_WARNING "ctcmpc: OUT OF MEMORY IN %s()"
-		       ": Data Lost \n", __FUNCTION__);
 		spin_unlock(&ch->collect_lock);
 		fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
-		goto done;
+				goto done;
 	}
-
 	header->th_ch_flag = TH_HAS_PDU;  /* Normal data */
 	ch->th_seq_num++;
 	header->th_seq_num = ch->th_seq_num;
 
-	if (do_debug_data)
-		ctcm_pr_debug("%s: ToVTAM_th_seq= %08x\n" ,
-					__FUNCTION__, ch->th_seq_num);
+	CTCM_PR_DBGDATA("%s: ToVTAM_th_seq= %08x\n" ,
+					__func__, ch->th_seq_num);
 
 	memcpy(skb_push(ch->trans_skb, TH_HEADER_LENGTH), header,
 		TH_HEADER_LENGTH);	/* put the TH on the packet */
 
 	kfree(header);
 
-	if (do_debug_data) {
-		ctcm_pr_debug("ctcmpc: %s()trans_skb len:%04x \n",
-		       __FUNCTION__, ch->trans_skb->len);
-
-		ctcm_pr_debug("ctcmpc: %s() up-to-50 bytes of trans_skb "
-			"data to vtam from collect_q\n", __FUNCTION__);
-		ctcmpc_dumpit((char *)ch->trans_skb->data,
+	CTCM_PR_DBGDATA("%s: trans_skb len:%04x \n",
+		       __func__, ch->trans_skb->len);
+	CTCM_PR_DBGDATA("%s: up-to-50 bytes of trans_skb "
+			"data to vtam from collect_q\n", __func__);
+	CTCM_D3_DUMP((char *)ch->trans_skb->data,
 				min_t(int, ch->trans_skb->len, 50));
-	}
 
 	spin_unlock(&ch->collect_lock);
 	clear_normalized_cda(&ch->ccw[1]);
 	if (set_normalized_cda(&ch->ccw[1], ch->trans_skb->data)) {
 		dev_kfree_skb_any(ch->trans_skb);
 		ch->trans_skb = NULL;
-		printk(KERN_WARNING
-		       "ctcmpc: %s()CCW failure - data lost\n",
-		       __FUNCTION__);
+		CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_ERROR,
+			"%s: %s: IDAL alloc failed",
+				CTCM_FUNTAIL, ch->id);
 		fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
 		return;
 	}
@@ -1373,7 +1353,6 @@
 	}
 done:
 	ctcm_clear_busy(dev);
-	ctcm_pr_debug("ctcmpc exit: %s  %s()\n", dev->name, __FUNCTION__);
 	return;
 }
 
@@ -1393,26 +1372,25 @@
 	struct mpc_group	*grp = priv->mpcg;
 	struct sk_buff		*skb = ch->trans_skb;
 	struct sk_buff		*new_skb;
-	unsigned long	saveflags = 0;	/* avoids compiler warning */
+	unsigned long		saveflags = 0;	/* avoids compiler warning */
 	int len	= ch->max_bufsize - ch->irb->scsw.cmd.count;
 
-	if (do_debug_data) {
-		CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG, "mpc_ch_rx %s cp:%i %s\n",
-				dev->name, smp_processor_id(), ch->id);
-		CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG, "mpc_ch_rx: maxbuf: %04x "
-				"len: %04x\n", ch->max_bufsize, len);
-	}
+	CTCM_PR_DEBUG("%s: %s: cp:%i %s maxbuf : %04x, len: %04x\n",
+			CTCM_FUNTAIL, dev->name, smp_processor_id(),
+				ch->id, ch->max_bufsize, len);
 	fsm_deltimer(&ch->timer);
 
 	if (skb == NULL) {
-		ctcm_pr_debug("ctcmpc exit:  %s() TRANS_SKB = NULL \n",
-			       __FUNCTION__);
-					goto again;
+		CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+			"%s(%s): TRANS_SKB = NULL",
+				CTCM_FUNTAIL, dev->name);
+			goto again;
 	}
 
 	if (len < TH_HEADER_LENGTH) {
-		ctcm_pr_info("%s: got packet with invalid length %d\n",
-				dev->name, len);
+		CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+				"%s(%s): packet length %d to short",
+					CTCM_FUNTAIL, dev->name, len);
 		priv->stats.rx_dropped++;
 		priv->stats.rx_length_errors++;
 	} else {
@@ -1422,11 +1400,9 @@
 		new_skb = __dev_alloc_skb(ch->max_bufsize, GFP_ATOMIC);
 
 		if (new_skb == NULL) {
-			printk(KERN_INFO "ctcmpc:%s() NEW_SKB = NULL\n",
-			       __FUNCTION__);
-			printk(KERN_WARNING "ctcmpc: %s() MEMORY ALLOC FAILED"
-			       " - DATA LOST - MPC FAILED\n",
-			       __FUNCTION__);
+			CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+				"%s(%d): skb allocation failed",
+						CTCM_FUNTAIL, dev->name);
 			fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
 					goto again;
 		}
@@ -1479,9 +1455,8 @@
 		break;
 	}
 
-	if (do_debug)
-		ctcm_pr_debug("ctcmpc exit : %s %s(): ch=0x%p id=%s\n",
-				dev->name, __FUNCTION__, ch, ch->id);
+	CTCM_PR_DEBUG("Exit %s: %s, ch=0x%p, id=%s\n",
+			__func__, dev->name, ch, ch->id);
 
 }
 
@@ -1497,15 +1472,16 @@
 	struct channel		*ch = arg;
 	struct net_device	*dev = ch->netdev;
 	struct ctcm_priv	*priv = dev->priv;
+	struct mpc_group	*gptr = priv->mpcg;
 
-	if (do_debug) {
-		struct mpc_group *gptr = priv->mpcg;
-		ctcm_pr_debug("ctcmpc enter: %s(): ch=0x%p id=%s\n",
-				__FUNCTION__, ch, ch->id);
-		ctcm_pr_debug("%s() %s chstate:%i grpstate:%i chprotocol:%i\n",
-				__FUNCTION__, ch->id, fsm_getstate(fi),
-				fsm_getstate(gptr->fsm), ch->protocol);
-	}
+	CTCM_PR_DEBUG("Enter %s: id=%s, ch=0x%p\n",
+				__func__, ch->id, ch);
+
+	CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_INFO,
+			"%s: %s: chstate:%i, grpstate:%i, prot:%i\n",
+			CTCM_FUNTAIL, ch->id, fsm_getstate(fi),
+			fsm_getstate(gptr->fsm), ch->protocol);
+
 	if (fsm_getstate(fi) == CTC_STATE_TXIDLE)
 		MPC_DBF_DEV_NAME(TRACE, dev, "remote side issued READ? ");
 
@@ -1531,9 +1507,8 @@
 		     ? CTC_STATE_RXINIT : CTC_STATE_TXINIT);
 
 done:
-	if (do_debug)
-		ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
-			__FUNCTION__, ch, ch->id);
+	CTCM_PR_DEBUG("Exit %s: id=%s, ch=0x%p\n",
+				__func__, ch->id, ch);
 	return;
 }
 
@@ -1556,12 +1531,9 @@
 	unsigned long saveflags = 0;	/* avoids compiler warning */
 
 	fsm_deltimer(&ch->timer);
-	ctcm_pr_debug("%s cp:%i enter:  %s()\n",
-		       dev->name, smp_processor_id(), __FUNCTION__);
-	if (do_debug)
-		ctcm_pr_debug("%s() %s chstate:%i grpstate:%i\n",
-			__FUNCTION__, ch->id,
-			fsm_getstate(fi), fsm_getstate(grp->fsm));
+	CTCM_PR_DEBUG("%s: %s: %s: cp:%i, chstate:%i grpstate:%i\n",
+			__func__, ch->id, dev->name, smp_processor_id(),
+				fsm_getstate(fi), fsm_getstate(grp->fsm));
 
 	fsm_newstate(fi, CTC_STATE_RXIDLE);
 	/* XID processing complete */
@@ -1575,9 +1547,7 @@
 		skb_reset_tail_pointer(ch->trans_skb);
 		ch->trans_skb->len = 0;
 		ch->ccw[1].count = ch->max_bufsize;
-		if (do_debug_ccw)
-			ctcmpc_dumpit((char *)&ch->ccw[0],
-						sizeof(struct ccw1) * 3);
+		CTCM_CCW_DUMP((char *)&ch->ccw[0], sizeof(struct ccw1) * 3);
 		if (event == CTC_EVENT_START)
 			/* see remark about conditional locking */
 			spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
@@ -1598,9 +1568,6 @@
 
 	fsm_event(priv->fsm, DEV_EVENT_RXUP, dev);
 done:
-	if (do_debug)
-		ctcm_pr_debug("ctcmpc exit: %s  %s()\n",
-					dev->name, __FUNCTION__);
 	return;
 }
 
@@ -1616,13 +1583,9 @@
 	struct ctcm_priv  *priv   = dev->priv;
 	struct mpc_group  *grp = priv->mpcg;
 
-	if (do_debug) {
-		ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s"
-				"GrpState:%s ChState:%s\n",
-				__FUNCTION__, smp_processor_id(), ch, ch->id,
-		fsm_getstate_str(grp->fsm),
-		fsm_getstate_str(ch->fsm));
-	}
+	CTCM_PR_DEBUG("%s(%s): %s(ch=0x%p), cp=%i, ChStat:%s, GrpStat:%s\n",
+		__func__, dev->name, ch->id, ch, smp_processor_id(),
+			fsm_getstate_str(ch->fsm), fsm_getstate_str(grp->fsm));
 
 	switch (fsm_getstate(grp->fsm)) {
 	case MPCG_STATE_XID2INITW:
@@ -1664,11 +1627,7 @@
 		break;
 	}
 
-	if (do_debug)
-		ctcm_pr_debug("ctcmpc exit : %s(): cp=%i ch=0x%p id=%s\n",
-			__FUNCTION__, smp_processor_id(), ch, ch->id);
 	return;
-
 }
 
 /*
@@ -1683,11 +1642,9 @@
 	struct ctcm_priv  *priv   = dev->priv;
 	struct mpc_group  *grp    = priv->mpcg;
 
-	ctcm_pr_debug("ctcmpc enter: %s  %s() %s  \nGrpState:%s ChState:%s\n",
-		       dev->name,
-		       __FUNCTION__, ch->id,
-		       fsm_getstate_str(grp->fsm),
-		       fsm_getstate_str(ch->fsm));
+	CTCM_PR_DEBUG("%s(%s): %s\n  ChState:%s GrpState:%s\n",
+			__func__, dev->name, ch->id,
+			fsm_getstate_str(ch->fsm), fsm_getstate_str(grp->fsm));
 
 	fsm_deltimer(&ch->timer);
 
@@ -1750,16 +1707,12 @@
 	if (ch->in_mpcgroup)
 		fsm_event(grp->fsm, MPCG_EVENT_XID0DO, ch);
 	else
-		printk(KERN_WARNING "ctcmpc: %s() Not all channels have"
-			" been added to group\n", __FUNCTION__);
+		CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+			"%s(%s): channel %s not added to group",
+				CTCM_FUNTAIL, dev->name, ch->id);
 
 done:
-	if (do_debug)
-		ctcm_pr_debug("ctcmpc exit : %s()%s ch=0x%p id=%s\n",
-				__FUNCTION__, dev->name, ch, ch->id);
-
 	return;
-
 }
 
 /*
@@ -1774,13 +1727,7 @@
 	struct ctcm_priv   *priv   = dev->priv;
 	struct mpc_group   *grp    = priv->mpcg;
 
-	ctcm_pr_debug("ctcmpc enter: %s  %s() %s  \nGrpState:%s ChState:%s\n",
-		       dev->name, __FUNCTION__, ch->id,
-		       fsm_getstate_str(grp->fsm),
-		       fsm_getstate_str(ch->fsm));
-
 	fsm_event(grp->fsm, MPCG_EVENT_XID0DO, ch);
-
 	return;
 }
 
@@ -1802,19 +1749,16 @@
 	int rc = 0;
 	unsigned long saveflags = 0;
 
-	if (do_debug)
-		ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
-			__FUNCTION__, smp_processor_id(), ach, ach->id);
+	CTCM_PR_DEBUG("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
+			__func__, smp_processor_id(), ach, ach->id);
 
 	if (grp->in_sweep == 0)
 				goto done;
 
-	if (do_debug_data) {
-		ctcm_pr_debug("ctcmpc: %s() 1: ToVTAM_th_seq= %08x\n" ,
-			       __FUNCTION__, wch->th_seq_num);
-		ctcm_pr_debug("ctcmpc: %s() 1: FromVTAM_th_seq= %08x\n" ,
-				__FUNCTION__, rch->th_seq_num);
-	}
+	CTCM_PR_DBGDATA("%s: 1: ToVTAM_th_seq= %08x\n" ,
+				__func__, wch->th_seq_num);
+	CTCM_PR_DBGDATA("%s: 1: FromVTAM_th_seq= %08x\n" ,
+				__func__, rch->th_seq_num);
 
 	if (fsm_getstate(wch->fsm) != CTC_STATE_TXIDLE) {
 		/* give the previous IO time to complete */
@@ -1853,11 +1797,9 @@
 
 	header->sw.th_last_seq = wch->th_seq_num;
 
-	if (do_debug_ccw)
-		ctcmpc_dumpit((char *)&wch->ccw[3], sizeof(struct ccw1) * 3);
-
-	ctcm_pr_debug("ctcmpc: %s() sweep packet\n", __FUNCTION__);
-	ctcmpc_dumpit((char *)header, TH_SWEEP_LENGTH);
+	CTCM_CCW_DUMP((char *)&wch->ccw[3], sizeof(struct ccw1) * 3);
+	CTCM_PR_DBGDATA("%s: sweep packet\n", __func__);
+	CTCM_D3_DUMP((char *)header, TH_SWEEP_LENGTH);
 
 	fsm_addtimer(&wch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, wch);
 	fsm_newstate(wch->fsm, CTC_STATE_TX);
@@ -1876,19 +1818,13 @@
 		ctcm_clear_busy_do(dev);
 	}
 
-	if (do_debug_data) {
-		ctcm_pr_debug("ctcmpc: %s()2: ToVTAM_th_seq= %08x\n" ,
-			       __FUNCTION__, wch->th_seq_num);
-		ctcm_pr_debug("ctcmpc: %s()2: FromVTAM_th_seq= %08x\n" ,
-			       __FUNCTION__, rch->th_seq_num);
-	}
+	CTCM_PR_DBGDATA("%s: To-/From-VTAM_th_seq = %08x/%08x\n" ,
+			__func__, wch->th_seq_num, rch->th_seq_num);
 
 	if (rc != 0)
 		ctcm_ccw_check_rc(wch, rc, "send sweep");
 
 done:
-	if (do_debug)
-		ctcm_pr_debug("ctcmpc exit:  %s() %s\n", __FUNCTION__, ach->id);
 	return;
 }
 
@@ -2149,9 +2085,8 @@
 		struct channel *ch = priv->channel[direction];
 		fsm_event(ch->fsm, CTC_EVENT_STOP, ch);
 		ch->th_seq_num = 0x00;
-	if (do_debug)
-		ctcm_pr_debug("ctcm: %s() CH_th_seq= %08x\n",
-				__FUNCTION__, ch->th_seq_num);
+		CTCM_PR_DEBUG("%s: CH_th_seq= %08x\n",
+				__func__, ch->th_seq_num);
 	}
 	if (IS_MPC(priv))
 		fsm_newstate(priv->mpcg->fsm, MPCG_STATE_RESET);
@@ -2199,8 +2134,11 @@
 {
 	struct net_device *dev = arg;
 	struct ctcm_priv *priv = dev->priv;
+	int dev_stat = fsm_getstate(fi);
 
-	CTCMY_DBF_DEV_NAME(SETUP, dev, "");
+	CTCM_DBF_TEXT_(SETUP, CTC_DBF_NOTICE,
+			"%s(%s): priv = %p [%d,%d]\n ",	CTCM_FUNTAIL,
+				dev->name, dev->priv, dev_stat, event);
 
 	switch (fsm_getstate(fi)) {
 	case DEV_STATE_STARTWAIT_RXTX:
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
index 6b13c1c..126a3eb 100644
--- a/drivers/s390/net/ctcm_main.c
+++ b/drivers/s390/net/ctcm_main.c
@@ -84,20 +84,19 @@
 		skb_pull(pskb, LL_HEADER_LENGTH);
 		if ((ch->protocol == CTCM_PROTO_S390) &&
 		    (header->type != ETH_P_IP)) {
-
 			if (!(ch->logflags & LOG_FLAG_ILLEGALPKT)) {
+				ch->logflags |= LOG_FLAG_ILLEGALPKT;
 				/*
 				 * Check packet type only if we stick strictly
 				 * to S/390's protocol of OS390. This only
 				 * supports IP. Otherwise allow any packet
 				 * type.
 				 */
-				ctcm_pr_warn("%s Illegal packet type 0x%04x "
-						"received, dropping\n",
-						dev->name, header->type);
-				ch->logflags |= LOG_FLAG_ILLEGALPKT;
+				CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+					"%s(%s): Illegal packet type 0x%04x"
+					" - dropping",
+					CTCM_FUNTAIL, dev->name, header->type);
 			}
-
 			priv->stats.rx_dropped++;
 			priv->stats.rx_frame_errors++;
 			return;
@@ -105,11 +104,11 @@
 		pskb->protocol = ntohs(header->type);
 		if (header->length <= LL_HEADER_LENGTH) {
 			if (!(ch->logflags & LOG_FLAG_ILLEGALSIZE)) {
-				ctcm_pr_warn(
-					"%s Illegal packet size %d "
-					"received (MTU=%d blocklen=%d), "
-					"dropping\n", dev->name, header->length,
-					dev->mtu, len);
+				CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+					"%s(%s): Illegal packet size %d(%d,%d)"
+					"- dropping",
+					CTCM_FUNTAIL, dev->name,
+					header->length, dev->mtu, len);
 				ch->logflags |= LOG_FLAG_ILLEGALSIZE;
 			}
 
@@ -122,10 +121,10 @@
 		if ((header->length > skb_tailroom(pskb)) ||
 			(header->length > len)) {
 			if (!(ch->logflags & LOG_FLAG_OVERRUN)) {
-				ctcm_pr_warn(
-					"%s Illegal packet size %d (beyond the"
-					" end of received data), dropping\n",
-					dev->name, header->length);
+				CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+					"%s(%s): Packet size %d (overrun)"
+					" - dropping", CTCM_FUNTAIL,
+						dev->name, header->length);
 				ch->logflags |= LOG_FLAG_OVERRUN;
 			}
 
@@ -139,9 +138,9 @@
 		skb = dev_alloc_skb(pskb->len);
 		if (!skb) {
 			if (!(ch->logflags & LOG_FLAG_NOMEM)) {
-				ctcm_pr_warn(
-					"%s Out of memory in ctcm_unpack_skb\n",
-					dev->name);
+				CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+					"%s(%s): MEMORY allocation error",
+						CTCM_FUNTAIL, dev->name);
 				ch->logflags |= LOG_FLAG_NOMEM;
 			}
 			priv->stats.rx_dropped++;
@@ -184,7 +183,7 @@
  */
 static void channel_free(struct channel *ch)
 {
-	CTCM_DBF_TEXT(TRACE, 2, __FUNCTION__);
+	CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s(%s)", CTCM_FUNTAIL, ch->id);
 	ch->flags &= ~CHANNEL_FLAGS_INUSE;
 	fsm_newstate(ch->fsm, CTC_STATE_IDLE);
 }
@@ -251,19 +250,12 @@
 {
 	struct channel *ch = channels;
 
-	if (do_debug) {
-		char buf[64];
-		sprintf(buf, "%s(%d, %s, %d)\n",
-				CTCM_FUNTAIL, type, id, direction);
-		CTCM_DBF_TEXT(TRACE, CTC_DBF_INFO, buf);
-	}
 	while (ch && (strncmp(ch->id, id, CTCM_ID_SIZE) || (ch->type != type)))
 		ch = ch->next;
 	if (!ch) {
-		char buf[64];
-		sprintf(buf, "%s(%d, %s, %d) not found in channel list\n",
+		CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+				"%s(%d, %s, %d) not found in channel list\n",
 				CTCM_FUNTAIL, type, id, direction);
-		CTCM_DBF_TEXT(ERROR, CTC_DBF_ERROR, buf);
 	} else {
 		if (ch->flags & CHANNEL_FLAGS_INUSE)
 			ch = NULL;
@@ -283,8 +275,9 @@
 	if (!IS_ERR(irb))
 		return 0;
 
-	CTCM_DBF_TEXT_(ERROR, CTC_DBF_WARN, "irb error %ld on device %s\n",
-			PTR_ERR(irb), cdev->dev.bus_id);
+	CTCM_DBF_TEXT_(ERROR, CTC_DBF_WARN,
+			"irb error %ld on device %s\n",
+				PTR_ERR(irb), cdev->dev.bus_id);
 
 	switch (PTR_ERR(irb)) {
 	case -EIO:
@@ -307,58 +300,85 @@
  *  ch		The channel, the sense code belongs to.
  *  sense	The sense code to inspect.
  */
-static inline void ccw_unit_check(struct channel *ch, unsigned char sense)
+static inline void ccw_unit_check(struct channel *ch, __u8 sense)
 {
-	CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__);
+	CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
+			"%s(%s): %02x",
+				CTCM_FUNTAIL, ch->id, sense);
+
 	if (sense & SNS0_INTERVENTION_REQ) {
 		if (sense & 0x01) {
-			ctcm_pr_debug("%s: Interface disc. or Sel. reset "
-					"(remote)\n", ch->id);
+			if (ch->sense_rc != 0x01) {
+				ctcm_pr_debug("%s: Interface disc. or Sel. "
+					      "reset (remote)\n", ch->id);
+				ch->sense_rc = 0x01;
+			}
 			fsm_event(ch->fsm, CTC_EVENT_UC_RCRESET, ch);
 		} else {
-			ctcm_pr_debug("%s: System reset (remote)\n", ch->id);
+			if (ch->sense_rc != SNS0_INTERVENTION_REQ) {
+				ctcm_pr_debug("%s: System reset (remote)\n",
+					      ch->id);
+				ch->sense_rc = SNS0_INTERVENTION_REQ;
+			}
 			fsm_event(ch->fsm, CTC_EVENT_UC_RSRESET, ch);
 		}
 	} else if (sense & SNS0_EQUIPMENT_CHECK) {
 		if (sense & SNS0_BUS_OUT_CHECK) {
-			ctcm_pr_warn("%s: Hardware malfunction (remote)\n",
-				ch->id);
+			if (ch->sense_rc != SNS0_BUS_OUT_CHECK) {
+				CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
+					"%s(%s): remote HW error %02x",
+						CTCM_FUNTAIL, ch->id, sense);
+				ch->sense_rc = SNS0_BUS_OUT_CHECK;
+			}
 			fsm_event(ch->fsm, CTC_EVENT_UC_HWFAIL, ch);
 		} else {
-			ctcm_pr_warn("%s: Read-data parity error (remote)\n",
-				ch->id);
+			if (ch->sense_rc != SNS0_EQUIPMENT_CHECK) {
+				CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
+					"%s(%s): remote read parity error %02x",
+						CTCM_FUNTAIL, ch->id, sense);
+				ch->sense_rc = SNS0_EQUIPMENT_CHECK;
+			}
 			fsm_event(ch->fsm, CTC_EVENT_UC_RXPARITY, ch);
 		}
 	} else if (sense & SNS0_BUS_OUT_CHECK) {
-		if (sense & 0x04) {
-			ctcm_pr_warn("%s: Data-streaming timeout)\n", ch->id);
-			fsm_event(ch->fsm, CTC_EVENT_UC_TXTIMEOUT, ch);
-		} else {
-			ctcm_pr_warn("%s: Data-transfer parity error\n",
-					ch->id);
-			fsm_event(ch->fsm, CTC_EVENT_UC_TXPARITY, ch);
+		if (ch->sense_rc != SNS0_BUS_OUT_CHECK) {
+			CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
+				"%s(%s): BUS OUT error %02x",
+					CTCM_FUNTAIL, ch->id, sense);
+			ch->sense_rc = SNS0_BUS_OUT_CHECK;
 		}
+		if (sense & 0x04)	/* data-streaming timeout */
+			fsm_event(ch->fsm, CTC_EVENT_UC_TXTIMEOUT, ch);
+		else			/* Data-transfer parity error */
+			fsm_event(ch->fsm, CTC_EVENT_UC_TXPARITY, ch);
 	} else if (sense & SNS0_CMD_REJECT) {
-		ctcm_pr_warn("%s: Command reject\n", ch->id);
+		if (ch->sense_rc != SNS0_CMD_REJECT) {
+			CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
+				"%s(%s): Command rejected",
+						CTCM_FUNTAIL, ch->id);
+			ch->sense_rc = SNS0_CMD_REJECT;
+		}
 	} else if (sense == 0) {
-		ctcm_pr_debug("%s: Unit check ZERO\n", ch->id);
+		CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
+			"%s(%s): Unit check ZERO",
+					CTCM_FUNTAIL, ch->id);
 		fsm_event(ch->fsm, CTC_EVENT_UC_ZERO, ch);
 	} else {
-		ctcm_pr_warn("%s: Unit Check with sense code: %02x\n",
-			    ch->id, sense);
+		CTCM_DBF_TEXT_(TRACE, CTC_DBF_WARN,
+			"%s(%s): Unit check code %02x unknown",
+					CTCM_FUNTAIL, ch->id, sense);
 		fsm_event(ch->fsm, CTC_EVENT_UC_UNKNOWN, ch);
 	}
 }
 
 int ctcm_ch_alloc_buffer(struct channel *ch)
 {
-	CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__);
-
 	clear_normalized_cda(&ch->ccw[1]);
 	ch->trans_skb = __dev_alloc_skb(ch->max_bufsize, GFP_ATOMIC | GFP_DMA);
 	if (ch->trans_skb == NULL) {
-		ctcm_pr_warn("%s: Couldn't alloc %s trans_skb\n",
-			ch->id,
+		CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+			"%s(%s): %s trans_skb allocation error",
+			CTCM_FUNTAIL, ch->id,
 			(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
 		return -ENOMEM;
 	}
@@ -367,9 +387,9 @@
 	if (set_normalized_cda(&ch->ccw[1], ch->trans_skb->data)) {
 		dev_kfree_skb(ch->trans_skb);
 		ch->trans_skb = NULL;
-		ctcm_pr_warn("%s: set_normalized_cda for %s "
-			"trans_skb failed, dropping packets\n",
-			ch->id,
+		CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+			"%s(%s): %s set norm_cda failed",
+			CTCM_FUNTAIL, ch->id,
 			(CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
 		return -ENOMEM;
 	}
@@ -516,7 +536,7 @@
 			atomic_dec(&skb->users);
 			skb_pull(skb, LL_HEADER_LENGTH + 2);
 			ctcm_clear_busy(ch->netdev);
-			return -EBUSY;
+			return -ENOMEM;
 		}
 
 		skb_reset_tail_pointer(ch->trans_skb);
@@ -570,15 +590,12 @@
 	struct th_sweep *header;
 	struct sk_buff *sweep_skb;
 	struct channel *ch;
-	int rc = 0;
+	/* int rc = 0; */
 
 	priv = dev->priv;
 	grp = priv->mpcg;
 	ch = priv->channel[WRITE];
 
-	if (do_debug)
-		MPC_DBF_DEV_NAME(TRACE, dev, ch->id);
-
 	/* sweep processing is not complete until response and request */
 	/* has completed for all read channels in group		       */
 	if (grp->in_sweep == 0) {
@@ -590,17 +607,16 @@
 	sweep_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC|GFP_DMA);
 
 	if (sweep_skb == NULL)	{
-		printk(KERN_INFO "Couldn't alloc sweep_skb\n");
-		rc = -ENOMEM;
-					goto done;
+		/* rc = -ENOMEM; */
+				goto nomem;
 	}
 
 	header = kmalloc(TH_SWEEP_LENGTH, gfp_type());
 
 	if (!header) {
 		dev_kfree_skb_any(sweep_skb);
-		rc = -ENOMEM;
-					goto done;
+		/* rc = -ENOMEM; */
+				goto nomem;
 	}
 
 	header->th.th_seg	= 0x00 ;
@@ -621,12 +637,10 @@
 
 	return;
 
-done:
-	if (rc != 0) {
-		grp->in_sweep = 0;
-		ctcm_clear_busy(dev);
-		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
-	}
+nomem:
+	grp->in_sweep = 0;
+	ctcm_clear_busy(dev);
+	fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
 
 	return;
 }
@@ -648,11 +662,9 @@
 	unsigned long saveflags = 0;	/* avoids compiler warning */
 	__u16 block_len;
 
-	if (do_debug)
-		ctcm_pr_debug(
-			"ctcm enter: %s(): %s cp=%i ch=0x%p id=%s state=%s\n",
-			__FUNCTION__, dev->name, smp_processor_id(), ch,
-			ch->id, fsm_getstate_str(ch->fsm));
+	CTCM_PR_DEBUG("Enter %s: %s, cp=%i ch=0x%p id=%s state=%s\n",
+			__func__, dev->name, smp_processor_id(), ch,
+					ch->id, fsm_getstate_str(ch->fsm));
 
 	if ((fsm_getstate(ch->fsm) != CTC_STATE_TXIDLE) || grp->in_sweep) {
 		spin_lock_irqsave(&ch->collect_lock, saveflags);
@@ -660,14 +672,8 @@
 		p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type());
 
 		if (!p_header) {
-			printk(KERN_WARNING "ctcm: OUT OF MEMORY IN %s():"
-			       " Data Lost \n", __FUNCTION__);
-
-			atomic_dec(&skb->users);
-			dev_kfree_skb_any(skb);
 			spin_unlock_irqrestore(&ch->collect_lock, saveflags);
-			fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
-					goto done;
+				goto nomem_exit;
 		}
 
 		p_header->pdu_offset = skb->len;
@@ -682,13 +688,10 @@
 		memcpy(skb_push(skb, PDU_HEADER_LENGTH), p_header,
 		       PDU_HEADER_LENGTH);
 
-		if (do_debug_data) {
-			ctcm_pr_debug("ctcm: %s() Putting on collect_q"
-			       " - skb len: %04x \n", __FUNCTION__, skb->len);
-			ctcm_pr_debug("ctcm: %s() pdu header and data"
-			       " for up to 32 bytes\n", __FUNCTION__);
-			ctcmpc_dump32((char *)skb->data, skb->len);
-		}
+		CTCM_PR_DEBUG("%s(%s): Put on collect_q - skb len: %04x \n"
+				"pdu header and data for up to 32 bytes:\n",
+				__func__, dev->name, skb->len);
+		CTCM_D3_DUMP((char *)skb->data, min_t(int, 32, skb->len));
 
 		skb_queue_tail(&ch->collect_queue, skb);
 		ch->collect_len += skb->len;
@@ -713,12 +716,7 @@
 	if (hi) {
 		nskb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
 		if (!nskb) {
-			printk(KERN_WARNING "ctcm: %s() OUT OF MEMORY"
-				"-  Data Lost \n", __FUNCTION__);
-			atomic_dec(&skb->users);
-			dev_kfree_skb_any(skb);
-			fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
-				goto done;
+			goto nomem_exit;
 		} else {
 			memcpy(skb_put(nskb, skb->len), skb->data, skb->len);
 			atomic_inc(&nskb->users);
@@ -730,15 +728,8 @@
 
 	p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type());
 
-	if (!p_header) {
-		printk(KERN_WARNING "ctcm: %s() OUT OF MEMORY"
-		       ": Data Lost \n", __FUNCTION__);
-
-		atomic_dec(&skb->users);
-		dev_kfree_skb_any(skb);
-		fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
-				goto done;
-	}
+	if (!p_header)
+		goto nomem_exit;
 
 	p_header->pdu_offset = skb->len;
 	p_header->pdu_proto = 0x01;
@@ -768,15 +759,8 @@
 	ch->prof.txlen += skb->len - PDU_HEADER_LENGTH;
 
 	header = kmalloc(TH_HEADER_LENGTH, gfp_type());
-
-	if (!header) {
-		printk(KERN_WARNING "ctcm: %s() OUT OF MEMORY: Data Lost \n",
-				__FUNCTION__);
-		atomic_dec(&skb->users);
-		dev_kfree_skb_any(skb);
-		fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
-				goto done;
-	}
+	if (!header)
+		goto nomem_exit;
 
 	header->th_seg = 0x00;
 	header->th_ch_flag = TH_HAS_PDU;  /* Normal data */
@@ -785,41 +769,31 @@
 	ch->th_seq_num++;
 	header->th_seq_num = ch->th_seq_num;
 
-	if (do_debug_data)
-		ctcm_pr_debug("ctcm: %s() ToVTAM_th_seq= %08x\n" ,
-		       __FUNCTION__, ch->th_seq_num);
+	CTCM_PR_DBGDATA("%s(%s) ToVTAM_th_seq= %08x\n" ,
+		       __func__, dev->name, ch->th_seq_num);
 
 	/* put the TH on the packet */
 	memcpy(skb_push(skb, TH_HEADER_LENGTH), header, TH_HEADER_LENGTH);
 
 	kfree(header);
 
-	if (do_debug_data) {
-		ctcm_pr_debug("ctcm: %s(): skb len: %04x \n",
-				__FUNCTION__, skb->len);
-		ctcm_pr_debug("ctcm: %s(): pdu header and data for up to 32 "
-				"bytes sent to vtam\n", __FUNCTION__);
-		ctcmpc_dump32((char *)skb->data, skb->len);
-	}
+	CTCM_PR_DBGDATA("%s(%s): skb len: %04x\n - pdu header and data for "
+			"up to 32 bytes sent to vtam:\n",
+				__func__, dev->name, skb->len);
+	CTCM_D3_DUMP((char *)skb->data, min_t(int, 32, skb->len));
 
 	ch->ccw[4].count = skb->len;
 	if (set_normalized_cda(&ch->ccw[4], skb->data)) {
 		/*
-		 * idal allocation failed, try via copying to
-		 * trans_skb. trans_skb usually has a pre-allocated
-		 * idal.
+		 * idal allocation failed, try via copying to trans_skb.
+		 * trans_skb usually has a pre-allocated idal.
 		 */
 		if (ctcm_checkalloc_buffer(ch)) {
 			/*
-			 * Remove our header. It gets added
-			 * again on retransmit.
+			 * Remove our header.
+			 * It gets added again on retransmit.
 			 */
-			atomic_dec(&skb->users);
-			dev_kfree_skb_any(skb);
-			printk(KERN_WARNING "ctcm: %s()OUT OF MEMORY:"
-					" Data Lost \n", __FUNCTION__);
-			fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
-				goto done;
+				goto nomem_exit;
 		}
 
 		skb_reset_tail_pointer(ch->trans_skb);
@@ -829,14 +803,11 @@
 		atomic_dec(&skb->users);
 		dev_kfree_skb_irq(skb);
 		ccw_idx = 0;
-		if (do_debug_data) {
-			ctcm_pr_debug("ctcm: %s() TRANS skb len: %d \n",
-			       __FUNCTION__, ch->trans_skb->len);
-			ctcm_pr_debug("ctcm: %s up to 32 bytes of data"
-				" sent to vtam\n", __FUNCTION__);
-			ctcmpc_dump32((char *)ch->trans_skb->data,
-					ch->trans_skb->len);
-		}
+		CTCM_PR_DBGDATA("%s(%s): trans_skb len: %04x\n"
+				"up to 32 bytes sent to vtam:\n",
+				__func__, dev->name, ch->trans_skb->len);
+		CTCM_D3_DUMP((char *)ch->trans_skb->data,
+				min_t(int, 32, ch->trans_skb->len));
 	} else {
 		skb_queue_tail(&ch->io_queue, skb);
 		ccw_idx = 3;
@@ -865,13 +836,21 @@
 		priv->stats.tx_packets++;
 		priv->stats.tx_bytes += skb->len - TH_HEADER_LENGTH;
 	}
-	if (ch->th_seq_num > 0xf0000000)	/* Chose 4Billion at random. */
+	if (ch->th_seq_num > 0xf0000000)	/* Chose at random. */
 		ctcmpc_send_sweep_req(ch);
 
+	goto done;
+nomem_exit:
+	CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_CRIT,
+			"%s(%s): MEMORY allocation ERROR\n",
+			CTCM_FUNTAIL, ch->id);
+	rc = -ENOMEM;
+	atomic_dec(&skb->users);
+	dev_kfree_skb_any(skb);
+	fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
 done:
-	if (do_debug)
-		ctcm_pr_debug("ctcm exit: %s  %s()\n", dev->name, __FUNCTION__);
-	return 0;
+	CTCM_PR_DEBUG("Exit %s(%s)\n", __func__, dev->name);
+	return rc;
 }
 
 /**
@@ -888,20 +867,19 @@
 /* first merge version - leaving both functions separated */
 static int ctcm_tx(struct sk_buff *skb, struct net_device *dev)
 {
-	int rc = 0;
-	struct ctcm_priv *priv;
-
-	CTCM_DBF_TEXT(TRACE, 5, __FUNCTION__);
-	priv = dev->priv;
+	struct ctcm_priv *priv = dev->priv;
 
 	if (skb == NULL) {
-		ctcm_pr_warn("%s: NULL sk_buff passed\n", dev->name);
+		CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+				"%s(%s): NULL sk_buff passed",
+					CTCM_FUNTAIL, dev->name);
 		priv->stats.tx_dropped++;
 		return 0;
 	}
 	if (skb_headroom(skb) < (LL_HEADER_LENGTH + 2)) {
-		ctcm_pr_warn("%s: Got sk_buff with head room < %ld bytes\n",
-			    dev->name, LL_HEADER_LENGTH + 2);
+		CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+			"%s(%s): Got sk_buff with head room < %ld bytes",
+			CTCM_FUNTAIL, dev->name, LL_HEADER_LENGTH + 2);
 		dev_kfree_skb(skb);
 		priv->stats.tx_dropped++;
 		return 0;
@@ -925,51 +903,43 @@
 
 	dev->trans_start = jiffies;
 	if (ctcm_transmit_skb(priv->channel[WRITE], skb) != 0)
-		rc = 1;
-	return rc;
+		return 1;
+	return 0;
 }
 
 /* unmerged MPC variant of ctcm_tx */
 static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	int len = 0;
-	struct ctcm_priv *priv = NULL;
-	struct mpc_group *grp  = NULL;
+	struct ctcm_priv *priv = dev->priv;
+	struct mpc_group *grp  = priv->mpcg;
 	struct sk_buff *newskb = NULL;
 
-	if (do_debug)
-		ctcm_pr_debug("ctcmpc enter: %s(): skb:%0lx\n",
-			__FUNCTION__, (unsigned long)skb);
-
-	CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
-			"ctcmpc enter: %s(): skb:%0lx\n",
-			__FUNCTION__, (unsigned long)skb);
-
-	priv = dev->priv;
-	grp  = priv->mpcg;
 	/*
 	 * Some sanity checks ...
 	 */
 	if (skb == NULL) {
-		ctcm_pr_warn("ctcmpc: %s: NULL sk_buff passed\n", dev->name);
+		CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+			"%s(%s): NULL sk_buff passed",
+					CTCM_FUNTAIL, dev->name);
 		priv->stats.tx_dropped++;
 					goto done;
 	}
 	if (skb_headroom(skb) < (TH_HEADER_LENGTH + PDU_HEADER_LENGTH)) {
-		CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_WARN,
-			"%s: Got sk_buff with head room < %ld bytes\n",
-			dev->name, TH_HEADER_LENGTH + PDU_HEADER_LENGTH);
+		CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_ERROR,
+			"%s(%s): Got sk_buff with head room < %ld bytes",
+			CTCM_FUNTAIL, dev->name,
+				TH_HEADER_LENGTH + PDU_HEADER_LENGTH);
 
-		if (do_debug_data)
-			ctcmpc_dump32((char *)skb->data, skb->len);
+		CTCM_D3_DUMP((char *)skb->data, min_t(int, 32, skb->len));
 
 		len =  skb->len + TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
 		newskb = __dev_alloc_skb(len, gfp_type() | GFP_DMA);
 
 		if (!newskb) {
-			printk(KERN_WARNING "ctcmpc: %s() OUT OF MEMORY-"
-			       "Data Lost\n",
-			       __FUNCTION__);
+			CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_ERROR,
+				"%s: %s: __dev_alloc_skb failed",
+						__func__, dev->name);
 
 			dev_kfree_skb_any(skb);
 			priv->stats.tx_dropped++;
@@ -993,9 +963,9 @@
 	if ((fsm_getstate(priv->fsm) != DEV_STATE_RUNNING) ||
 	   (fsm_getstate(grp->fsm) <  MPCG_STATE_XID2INITW)) {
 		dev_kfree_skb_any(skb);
-		printk(KERN_INFO "ctcmpc: %s() DATA RCVD - MPC GROUP "
-		       "NOT ACTIVE - DROPPED\n",
-		       __FUNCTION__);
+		CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+			"%s(%s): inactive MPCGROUP - dropped",
+					CTCM_FUNTAIL, dev->name);
 		priv->stats.tx_dropped++;
 		priv->stats.tx_errors++;
 		priv->stats.tx_carrier_errors++;
@@ -1003,8 +973,9 @@
 	}
 
 	if (ctcm_test_and_set_busy(dev)) {
-		printk(KERN_WARNING "%s:DEVICE ERR - UNRECOVERABLE DATA LOSS\n",
-		       __FUNCTION__);
+		CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+			"%s(%s): device busy - dropped",
+					CTCM_FUNTAIL, dev->name);
 		dev_kfree_skb_any(skb);
 		priv->stats.tx_dropped++;
 		priv->stats.tx_errors++;
@@ -1015,12 +986,9 @@
 
 	dev->trans_start = jiffies;
 	if (ctcmpc_transmit_skb(priv->channel[WRITE], skb) != 0) {
-		printk(KERN_WARNING "ctcmpc: %s() DEVICE ERROR"
-		       ": Data Lost \n",
-		       __FUNCTION__);
-		printk(KERN_WARNING "ctcmpc: %s() DEVICE ERROR"
-		       " - UNRECOVERABLE DATA LOSS\n",
-		       __FUNCTION__);
+		CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+			"%s(%s): device error - dropped",
+					CTCM_FUNTAIL, dev->name);
 		dev_kfree_skb_any(skb);
 		priv->stats.tx_dropped++;
 		priv->stats.tx_errors++;
@@ -1054,8 +1022,6 @@
 	struct ctcm_priv *priv;
 	int max_bufsize;
 
-	CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
-
 	if (new_mtu < 576 || new_mtu > 65527)
 		return -EINVAL;
 
@@ -1087,30 +1053,13 @@
 	return &((struct ctcm_priv *)dev->priv)->stats;
 }
 
-
-static void ctcm_netdev_unregister(struct net_device *dev)
-{
-	CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
-	if (!dev)
-		return;
-	unregister_netdev(dev);
-}
-
-static int ctcm_netdev_register(struct net_device *dev)
-{
-	CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
-	return register_netdev(dev);
-}
-
 static void ctcm_free_netdevice(struct net_device *dev)
 {
 	struct ctcm_priv *priv;
 	struct mpc_group *grp;
 
-	CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
-
-	if (!dev)
-		return;
+	CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
+			"%s(%s)", CTCM_FUNTAIL, dev->name);
 	priv = dev->priv;
 	if (priv) {
 		grp = priv->mpcg;
@@ -1171,7 +1120,9 @@
 		dev = alloc_netdev(0, CTC_DEVICE_GENE, ctcm_dev_setup);
 
 	if (!dev) {
-		ctcm_pr_err("%s: Out of memory\n", __FUNCTION__);
+		CTCM_DBF_TEXT_(ERROR, CTC_DBF_CRIT,
+			"%s: MEMORY allocation ERROR",
+			CTCM_FUNTAIL);
 		return NULL;
 	}
 	dev->priv = priv;
@@ -1209,6 +1160,7 @@
 	}
 
 	CTCMY_DBF_DEV(SETUP, dev, "finished");
+
 	return dev;
 }
 
@@ -1226,18 +1178,24 @@
 	struct net_device	*dev;
 	struct ctcm_priv	*priv;
 	struct ccwgroup_device	*cgdev;
+	int cstat;
+	int dstat;
 
-	CTCM_DBF_TEXT(TRACE, CTC_DBF_DEBUG, __FUNCTION__);
+	CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
+		"Enter %s(%s)", CTCM_FUNTAIL, &cdev->dev.bus_id);
+
 	if (ctcm_check_irb_error(cdev, irb))
 		return;
 
 	cgdev = dev_get_drvdata(&cdev->dev);
 
+	cstat = irb->scsw.cmd.cstat;
+	dstat = irb->scsw.cmd.dstat;
+
 	/* Check for unsolicited interrupts. */
 	if (cgdev == NULL) {
-		ctcm_pr_warn("ctcm: Got unsolicited irq: %s c-%02x d-%02x\n",
-			    cdev->dev.bus_id, irb->scsw.cmd.cstat,
-			    irb->scsw.cmd.dstat);
+		ctcm_pr_warn("ctcm: Got unsolicited irq: c-%02x d-%02x\n",
+			     cstat, dstat);
 		return;
 	}
 
@@ -1254,26 +1212,22 @@
 		return;
 	}
 
-	dev = (struct net_device *)(ch->netdev);
+	dev = ch->netdev;
 	if (dev == NULL) {
 		ctcm_pr_crit("ctcm: %s dev=NULL bus_id=%s, ch=0x%p\n",
-				__FUNCTION__, cdev->dev.bus_id, ch);
+				__func__, cdev->dev.bus_id, ch);
 		return;
 	}
 
-	if (do_debug)
-		ctcm_pr_debug("%s: interrupt for device: %s "
-				"received c-%02x d-%02x\n",
-				dev->name,
-				ch->id,
-				irb->scsw.cmd.cstat,
-				irb->scsw.cmd.dstat);
+	CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG,
+		"%s(%s): int. for %s: cstat=%02x dstat=%02x",
+			CTCM_FUNTAIL, dev->name, ch->id, cstat, dstat);
 
 	/* Copy interruption response block. */
 	memcpy(ch->irb, irb, sizeof(struct irb));
 
-	/* Check for good subchannel return code, otherwise error message */
 	if (irb->scsw.cmd.cstat) {
+	/* Check for good subchannel return code, otherwise error message */
 		fsm_event(ch->fsm, CTC_EVENT_SC_UNKNOWN, ch);
 		ctcm_pr_warn("%s: subchannel check for dev: %s - %02x %02x\n",
 			    dev->name, ch->id, irb->scsw.cmd.cstat,
@@ -1283,6 +1237,11 @@
 
 	/* Check the reason-code of a unit check */
 	if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
+		if ((irb->ecw[0] & ch->sense_rc) == 0)
+			/* print it only once */
+			CTCM_DBF_TEXT_(TRACE, CTC_DBF_INFO,
+				"%s(%s): sense=%02x, ds=%02x",
+				CTCM_FUNTAIL, ch->id, irb->ecw[0], dstat);
 		ccw_unit_check(ch, irb->ecw[0]);
 		return;
 	}
@@ -1320,14 +1279,18 @@
 	struct ctcm_priv *priv;
 	int rc;
 
-	CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s %p", __FUNCTION__, cgdev);
+	CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
+			"%s %p",
+			__func__, cgdev);
 
 	if (!get_device(&cgdev->dev))
 		return -ENODEV;
 
 	priv = kzalloc(sizeof(struct ctcm_priv), GFP_KERNEL);
 	if (!priv) {
-		ctcm_pr_err("%s: Out of memory\n", __FUNCTION__);
+		CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR,
+			"%s: memory allocation failure",
+			CTCM_FUNTAIL);
 		put_device(&cgdev->dev);
 		return -ENOMEM;
 	}
@@ -1364,10 +1327,13 @@
 	int ccw_num;
 	int rc = 0;
 
-	CTCM_DBF_TEXT(TRACE, 2, __FUNCTION__);
+	CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
+		"%s(%s), type %d, proto %d",
+			__func__, cdev->dev.bus_id,	type, priv->protocol);
+
 	ch = kzalloc(sizeof(struct channel), GFP_KERNEL);
 	if (ch == NULL)
-					goto nomem_return;
+		return -ENOMEM;
 
 	ch->protocol = priv->protocol;
 	if (IS_MPC(priv)) {
@@ -1478,7 +1444,7 @@
 	if (*c && (!strncmp((*c)->id, ch->id, CTCM_ID_SIZE))) {
 		CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
 				"%s (%s) already in list, using old entry",
-				__FUNCTION__, (*c)->id);
+				__func__, (*c)->id);
 
 				goto free_return;
 	}
@@ -1498,11 +1464,10 @@
 	return 0;
 
 nomem_return:
-	ctcm_pr_warn("ctcm: Out of memory in %s\n", __FUNCTION__);
 	rc = -ENOMEM;
 
 free_return:	/* note that all channel pointers are 0 or valid */
-	kfree(ch->ccw);		/* TODO: check that again */
+	kfree(ch->ccw);
 	kfree(ch->discontact_th);
 	kfree_fsm(ch->fsm);
 	kfree(ch->irb);
@@ -1540,48 +1505,48 @@
 	enum channel_types type;
 	struct ctcm_priv *priv;
 	struct net_device *dev;
+	struct ccw_device *cdev0;
+	struct ccw_device *cdev1;
 	int ret;
 
-	CTCM_DBF_TEXT(SETUP, CTC_DBF_INFO, __FUNCTION__);
-
 	priv = dev_get_drvdata(&cgdev->dev);
 	if (!priv)
 		return -ENODEV;
 
-	type = get_channel_type(&cgdev->cdev[0]->id);
+	cdev0 = cgdev->cdev[0];
+	cdev1 = cgdev->cdev[1];
 
-	snprintf(read_id, CTCM_ID_SIZE, "ch-%s", cgdev->cdev[0]->dev.bus_id);
-	snprintf(write_id, CTCM_ID_SIZE, "ch-%s", cgdev->cdev[1]->dev.bus_id);
+	type = get_channel_type(&cdev0->id);
 
-	ret = add_channel(cgdev->cdev[0], type, priv);
+	snprintf(read_id, CTCM_ID_SIZE, "ch-%s", cdev0->dev.bus_id);
+	snprintf(write_id, CTCM_ID_SIZE, "ch-%s", cdev1->dev.bus_id);
+
+	ret = add_channel(cdev0, type, priv);
 	if (ret)
 		return ret;
-	ret = add_channel(cgdev->cdev[1], type, priv);
+	ret = add_channel(cdev1, type, priv);
 	if (ret)
 		return ret;
 
-	ret = ccw_device_set_online(cgdev->cdev[0]);
+	ret = ccw_device_set_online(cdev0);
 	if (ret != 0) {
-		CTCM_DBF_TEXT(SETUP, CTC_DBF_WARN,
-				"ccw_device_set_online (cdev[0]) failed ");
-		ctcm_pr_warn("ccw_device_set_online (cdev[0]) failed "
-				"with ret = %d\n", ret);
+		/* may be ok to fail now - can be done later */
+		CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
+			"%s(%s) set_online rc=%d",
+				CTCM_FUNTAIL, read_id, ret);
 	}
 
-	ret = ccw_device_set_online(cgdev->cdev[1]);
+	ret = ccw_device_set_online(cdev1);
 	if (ret != 0) {
-		CTCM_DBF_TEXT(SETUP, CTC_DBF_WARN,
-				"ccw_device_set_online (cdev[1]) failed ");
-		ctcm_pr_warn("ccw_device_set_online (cdev[1]) failed "
-				"with ret = %d\n", ret);
+		/* may be ok to fail now - can be done later */
+		CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
+			"%s(%s) set_online rc=%d",
+				CTCM_FUNTAIL, write_id, ret);
 	}
 
 	dev = ctcm_init_netdevice(priv);
-
-	if (dev == NULL) {
-		ctcm_pr_warn("ctcm_init_netdevice failed\n");
-					goto out;
-	}
+	if (dev == NULL)
+			goto out;
 
 	for (direction = READ; direction <= WRITE; direction++) {
 		priv->channel[direction] =
@@ -1590,8 +1555,7 @@
 		if (priv->channel[direction] == NULL) {
 			if (direction == WRITE)
 				channel_free(priv->channel[READ]);
-			ctcm_free_netdevice(dev);
-					goto out;
+			goto out_dev;
 		}
 		priv->channel[direction]->netdev = dev;
 		priv->channel[direction]->protocol = priv->protocol;
@@ -1600,26 +1564,24 @@
 	/* sysfs magic */
 	SET_NETDEV_DEV(dev, &cgdev->dev);
 
-	if (ctcm_netdev_register(dev) != 0) {
-		ctcm_free_netdevice(dev);
-					goto out;
-	}
+	if (register_netdev(dev))
+			goto out_dev;
 
 	if (ctcm_add_attributes(&cgdev->dev)) {
-		ctcm_netdev_unregister(dev);
-/*		dev->priv = NULL;	why that ????	*/
-		ctcm_free_netdevice(dev);
-					goto out;
+		unregister_netdev(dev);
+			goto out_dev;
 	}
 
 	strlcpy(priv->fsm->name, dev->name, sizeof(priv->fsm->name));
 
 	CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
-			"setup(%s) ok : r/w = %s / %s, proto : %d",
-			dev->name, priv->channel[READ]->id,
+		"setup(%s) OK : r/w = %s/%s, protocol : %d", dev->name,
+			priv->channel[READ]->id,
 			priv->channel[WRITE]->id, priv->protocol);
 
 	return 0;
+out_dev:
+	ctcm_free_netdevice(dev);
 out:
 	ccw_device_set_offline(cgdev->cdev[1]);
 	ccw_device_set_offline(cgdev->cdev[0]);
@@ -1658,8 +1620,7 @@
 		channel_free(priv->channel[WRITE]);
 
 	if (dev) {
-		ctcm_netdev_unregister(dev);
-/*		dev->priv = NULL;	why that ???	*/
+		unregister_netdev(dev);
 		ctcm_free_netdevice(dev);
 	}
 
@@ -1682,13 +1643,16 @@
 
 static void ctcm_remove_device(struct ccwgroup_device *cgdev)
 {
-	struct ctcm_priv *priv;
+	struct ctcm_priv *priv = dev_get_drvdata(&cgdev->dev);
 
-	CTCM_DBF_TEXT(SETUP, CTC_DBF_ERROR, __FUNCTION__);
+	BUG_ON(priv == NULL);
 
-	priv = dev_get_drvdata(&cgdev->dev);
-	if (!priv)
-		return;
+	CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
+			"removing device %s, r/w = %s/%s, proto : %d",
+			priv->channel[READ]->netdev->name,
+			priv->channel[READ]->id, priv->channel[WRITE]->id,
+			priv->protocol);
+
 	if (cgdev->state == CCWGROUP_ONLINE)
 		ctcm_shutdown_device(cgdev);
 	ctcm_remove_files(&cgdev->dev);
@@ -1748,8 +1712,6 @@
 
 	ret = ctcm_register_dbf_views();
 	if (ret) {
-		ctcm_pr_crit("ctcm_init failed with ctcm_register_dbf_views "
-				"rc = %d\n", ret);
 		return ret;
 	}
 	ret = register_cu3088_discipline(&ctcm_group_driver);
diff --git a/drivers/s390/net/ctcm_main.h b/drivers/s390/net/ctcm_main.h
index 95b0c0b..a72e0fe 100644
--- a/drivers/s390/net/ctcm_main.h
+++ b/drivers/s390/net/ctcm_main.h
@@ -22,9 +22,9 @@
 
 #define CTC_DRIVER_NAME	"ctcm"
 #define CTC_DEVICE_NAME	"ctc"
-#define CTC_DEVICE_GENE	"ctc%d"
 #define MPC_DEVICE_NAME	"mpc"
-#define MPC_DEVICE_GENE	"mpc%d"
+#define CTC_DEVICE_GENE CTC_DEVICE_NAME "%d"
+#define MPC_DEVICE_GENE	MPC_DEVICE_NAME "%d"
 
 #define CHANNEL_FLAGS_READ	0
 #define CHANNEL_FLAGS_WRITE	1
@@ -48,6 +48,30 @@
 #define ctcm_pr_err(fmt, arg...) printk(KERN_ERR fmt, ##arg)
 #define ctcm_pr_crit(fmt, arg...) printk(KERN_CRIT fmt, ##arg)
 
+#define CTCM_PR_DEBUG(fmt, arg...) \
+	do { \
+		if (do_debug) \
+			printk(KERN_DEBUG fmt, ##arg); \
+	} while (0)
+
+#define	CTCM_PR_DBGDATA(fmt, arg...) \
+	do { \
+		if (do_debug_data) \
+			printk(KERN_DEBUG fmt, ##arg); \
+	} while (0)
+
+#define	CTCM_D3_DUMP(buf, len) \
+	do { \
+		if (do_debug_data) \
+			ctcmpc_dumpit(buf, len); \
+	} while (0)
+
+#define	CTCM_CCW_DUMP(buf, len) \
+	do { \
+		if (do_debug_ccw) \
+			ctcmpc_dumpit(buf, len); \
+	} while (0)
+
 /*
  * CCW commands, used in this driver.
  */
@@ -161,8 +185,9 @@
 	fsm_instance *fsm;	/* finite state machine of this channel */
 	struct net_device *netdev;	/* corresponding net_device */
 	struct ctcm_profile prof;
-	unsigned char *trans_skb_data;
+	__u8 *trans_skb_data;
 	__u16 logflags;
+	__u8  sense_rc; /* last unit check sense code report control */
 };
 
 struct ctcm_priv {
diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c
index 044adde..49ae1cd 100644
--- a/drivers/s390/net/ctcm_mpc.c
+++ b/drivers/s390/net/ctcm_mpc.c
@@ -149,7 +149,7 @@
 	for (ct = 0; ct < len; ct++, ptr++, rptr++) {
 		if (sw == 0) {
 			#if (UTS_MACHINE == s390x)
-			sprintf(addr, "%16.16lx", (unsigned long)rptr);
+			sprintf(addr, "%16.16lx", (__u64)rptr);
 			#else
 			sprintf(addr, "%8.8X", (__u32)rptr);
 			#endif
@@ -164,7 +164,7 @@
 			strcat(bhex, "	");
 
 		#if (UTS_MACHINE == s390x)
-		sprintf(tbuf, "%2.2lX", (unsigned long)*ptr);
+		sprintf(tbuf, "%2.2lX", (__u64)*ptr);
 		#else
 		sprintf(tbuf, "%2.2X", (__u32)*ptr);
 		#endif
@@ -179,24 +179,24 @@
 		basc[sw+1] = '\0';
 		sw++;
 		rm--;
-		if (sw == 16) {
-			if ((strcmp(duphex, bhex)) != 0) {
-				if (dup != 0) {
-					sprintf(tdup, "Duplicate as above "
-						"to %s", addr);
-					printk(KERN_INFO "		  "
-						"     --- %s ---\n", tdup);
-				}
-				printk(KERN_INFO "   %s (+%s) : %s  [%s]\n",
+		if (sw != 16)
+			continue;
+		if ((strcmp(duphex, bhex)) != 0) {
+			if (dup != 0) {
+				sprintf(tdup,
+					"Duplicate as above to %s", addr);
+				ctcm_pr_debug("		       --- %s ---\n",
+						tdup);
+			}
+			ctcm_pr_debug("   %s (+%s) : %s  [%s]\n",
 					addr, boff, bhex, basc);
-				dup = 0;
-				strcpy(duphex, bhex);
-			} else
-				dup++;
+			dup = 0;
+			strcpy(duphex, bhex);
+		} else
+			dup++;
 
-			sw = 0;
-			rm = 16;
-		}
+		sw = 0;
+		rm = 16;
 	}  /* endfor */
 
 	if (sw != 0) {
@@ -210,19 +210,17 @@
 		}
 		if (dup != 0) {
 			sprintf(tdup, "Duplicate as above to %s", addr);
-			printk(KERN_INFO "		  "
-				"     --- %s ---\n", tdup);
+			ctcm_pr_debug("		       --- %s ---\n", tdup);
 		}
-		printk(KERN_INFO "   %s (+%s) : %s  [%s]\n",
-			addr, boff, bhex, basc);
+		ctcm_pr_debug("   %s (+%s) : %s  [%s]\n",
+					addr, boff, bhex, basc);
 	} else {
 		if (dup >= 1) {
 			sprintf(tdup, "Duplicate as above to %s", addr);
-			printk(KERN_INFO "		  "
-				"     --- %s ---\n", tdup);
+			ctcm_pr_debug("		       --- %s ---\n", tdup);
 		}
 		if (dup != 0) {
-			printk(KERN_INFO "   %s (+%s) : %s  [%s]\n",
+			ctcm_pr_debug("   %s (+%s) : %s  [%s]\n",
 				addr, boff, bhex, basc);
 		}
 	}
@@ -241,7 +239,7 @@
  */
 void ctcmpc_dump_skb(struct sk_buff *skb, int offset)
 {
-	unsigned char *p = skb->data;
+	__u8 *p = skb->data;
 	struct th_header *header;
 	struct pdu *pheader;
 	int bl = skb->len;
@@ -253,8 +251,8 @@
 	p += offset;
 	header = (struct th_header *)p;
 
-	printk(KERN_INFO "dump:\n");
-	printk(KERN_INFO "skb len=%d \n", skb->len);
+	ctcm_pr_debug("dump:\n");
+	ctcm_pr_debug("skb len=%d \n", skb->len);
 	if (skb->len > 2) {
 		switch (header->th_ch_flag) {
 		case TH_HAS_PDU:
@@ -273,32 +271,64 @@
 		}
 
 		pheader = (struct pdu *)p;
-		printk(KERN_INFO "pdu->offset: %d hex: %04x\n",
-		       pheader->pdu_offset, pheader->pdu_offset);
-		printk(KERN_INFO "pdu->flag  : %02x\n", pheader->pdu_flag);
-		printk(KERN_INFO "pdu->proto : %02x\n", pheader->pdu_proto);
-		printk(KERN_INFO "pdu->seq   : %02x\n", pheader->pdu_seq);
+		ctcm_pr_debug("pdu->offset: %d hex: %04x\n",
+			       pheader->pdu_offset, pheader->pdu_offset);
+		ctcm_pr_debug("pdu->flag  : %02x\n", pheader->pdu_flag);
+		ctcm_pr_debug("pdu->proto : %02x\n", pheader->pdu_proto);
+		ctcm_pr_debug("pdu->seq   : %02x\n", pheader->pdu_seq);
 					goto dumpdata;
 
 dumpth:
-		printk(KERN_INFO "th->seg     : %02x\n", header->th_seg);
-		printk(KERN_INFO "th->ch      : %02x\n", header->th_ch_flag);
-		printk(KERN_INFO "th->blk_flag: %02x\n", header->th_blk_flag);
-		printk(KERN_INFO "th->type    : %s\n",
-		       (header->th_is_xid) ? "DATA" : "XID");
-		printk(KERN_INFO "th->seqnum  : %04x\n", header->th_seq_num);
+		ctcm_pr_debug("th->seg     : %02x\n", header->th_seg);
+		ctcm_pr_debug("th->ch      : %02x\n", header->th_ch_flag);
+		ctcm_pr_debug("th->blk_flag: %02x\n", header->th_blk_flag);
+		ctcm_pr_debug("th->type    : %s\n",
+			       (header->th_is_xid) ? "DATA" : "XID");
+		ctcm_pr_debug("th->seqnum  : %04x\n", header->th_seq_num);
 
 	}
 dumpdata:
 	if (bl > 32)
 		bl = 32;
-	printk(KERN_INFO "data: ");
+	ctcm_pr_debug("data: ");
 	for (i = 0; i < bl; i++)
-		printk(KERN_INFO "%02x%s", *p++, (i % 16) ? " " : "\n<7>");
-	printk(KERN_INFO "\n");
+		ctcm_pr_debug("%02x%s", *p++, (i % 16) ? " " : "\n");
+	ctcm_pr_debug("\n");
 }
 #endif
 
+static struct net_device *ctcmpc_get_dev(int port_num)
+{
+	char device[20];
+	struct net_device *dev;
+	struct ctcm_priv *priv;
+
+	sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
+
+	dev = __dev_get_by_name(&init_net, device);
+
+	if (dev == NULL) {
+		CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+			"%s: Device not found by name: %s",
+					CTCM_FUNTAIL, device);
+		return NULL;
+	}
+	priv = dev->priv;
+	if (priv == NULL) {
+		CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+			"%s(%s): dev->priv is NULL",
+					CTCM_FUNTAIL, device);
+		return NULL;
+	}
+	if (priv->mpcg == NULL) {
+		CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+			"%s(%s): priv->mpcg is NULL",
+					CTCM_FUNTAIL, device);
+		return NULL;
+	}
+	return dev;
+}
+
 /*
  * ctc_mpc_alloc_channel
  *	(exported interface)
@@ -308,34 +338,23 @@
  */
 int ctc_mpc_alloc_channel(int port_num, void (*callback)(int, int))
 {
-	char device[20];
 	struct net_device *dev;
 	struct mpc_group *grp;
 	struct ctcm_priv *priv;
 
-	ctcm_pr_debug("ctcmpc enter:	%s()\n", __FUNCTION__);
-
-	sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
-	dev = __dev_get_by_name(&init_net, device);
-
-	if (dev == NULL) {
-		printk(KERN_INFO "ctc_mpc_alloc_channel %s dev=NULL\n", device);
+	dev = ctcmpc_get_dev(port_num);
+	if (dev == NULL)
 		return 1;
-	}
-
 	priv = dev->priv;
 	grp = priv->mpcg;
-	if (!grp)
-		return 1;
 
 	grp->allochanfunc = callback;
 	grp->port_num = port_num;
 	grp->port_persist = 1;
 
-	ctcm_pr_debug("ctcmpc: %s called for device %s state=%s\n",
-		       __FUNCTION__,
-		       dev->name,
-		       fsm_getstate_str(grp->fsm));
+	CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_INFO,
+			"%s(%s): state=%s",
+			CTCM_FUNTAIL, dev->name, fsm_getstate_str(grp->fsm));
 
 	switch (fsm_getstate(grp->fsm)) {
 	case MPCG_STATE_INOP:
@@ -377,12 +396,8 @@
 			grp->allocchan_callback_retries = 0;
 		}
 		break;
-	default:
-		return 0;
-
 	}
 
-	ctcm_pr_debug("ctcmpc exit:  %s()\n", __FUNCTION__);
 	return 0;
 }
 EXPORT_SYMBOL(ctc_mpc_alloc_channel);
@@ -394,31 +409,22 @@
 void ctc_mpc_establish_connectivity(int port_num,
 				void (*callback)(int, int, int))
 {
-	char device[20];
 	struct net_device *dev;
 	struct mpc_group *grp;
 	struct ctcm_priv *priv;
 	struct channel *rch, *wch;
 
-	ctcm_pr_debug("ctcmpc enter:	%s()\n", __FUNCTION__);
-
-	sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
-	dev = __dev_get_by_name(&init_net, device);
-
-	if (dev == NULL) {
-		printk(KERN_INFO "ctc_mpc_establish_connectivity "
-				"%s dev=NULL\n", device);
+	dev = ctcmpc_get_dev(port_num);
+	if (dev == NULL)
 		return;
-	}
 	priv = dev->priv;
+	grp = priv->mpcg;
 	rch = priv->channel[READ];
 	wch = priv->channel[WRITE];
 
-	grp = priv->mpcg;
-
-	ctcm_pr_debug("ctcmpc: %s() called for device %s state=%s\n",
-			__FUNCTION__, dev->name,
-			fsm_getstate_str(grp->fsm));
+	CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_INFO,
+			"%s(%s): state=%s",
+			CTCM_FUNTAIL, dev->name, fsm_getstate_str(grp->fsm));
 
 	grp->estconnfunc = callback;
 	grp->port_num = port_num;
@@ -446,8 +452,10 @@
 	case MPCG_STATE_RESET:
 		/* MPC Group is not ready to start XID - min num of */
 		/* 1 read and 1 write channel have not been acquired*/
-		printk(KERN_WARNING "ctcmpc: %s() REJECTED ACTIVE XID Req"
-			"uest - Channel Pair is not Active\n", __FUNCTION__);
+
+		CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+			"%s(%s): REJECTED - inactive channels",
+					CTCM_FUNTAIL, dev->name);
 		if (grp->estconnfunc) {
 			grp->estconnfunc(grp->port_num, -1, 0);
 			grp->estconnfunc = NULL;
@@ -457,11 +465,12 @@
 		/* alloc channel was called but no XID exchange    */
 		/* has occurred. initiate xside XID exchange	   */
 		/* make sure yside XID0 processing has not started */
+
 		if ((fsm_getstate(rch->fsm) > CH_XID0_PENDING) ||
 			(fsm_getstate(wch->fsm) > CH_XID0_PENDING)) {
-			printk(KERN_WARNING "mpc: %s() ABORT ACTIVE XID"
-			       " Request- PASSIVE XID in process\n"
-			       , __FUNCTION__);
+			CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+				"%s(%s): ABORT - PASSIVE XID",
+					CTCM_FUNTAIL, dev->name);
 			break;
 		}
 		grp->send_qllc_disc = 1;
@@ -476,9 +485,9 @@
 				(fsm_getstate(rch->fsm) == CH_XID0_PENDING))
 			fsm_event(grp->fsm, MPCG_EVENT_XID0DO, rch);
 		else {
-			printk(KERN_WARNING "mpc: %s() Unable to start"
-			       " ACTIVE XID0 on read channel\n",
-			       __FUNCTION__);
+			CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+				"%s(%s): RX-%s not ready for ACTIVE XID0",
+					CTCM_FUNTAIL, dev->name, rch->id);
 			if (grp->estconnfunc) {
 				grp->estconnfunc(grp->port_num, -1, 0);
 				grp->estconnfunc = NULL;
@@ -490,9 +499,9 @@
 				(fsm_getstate(wch->fsm) == CH_XID0_PENDING))
 			fsm_event(grp->fsm, MPCG_EVENT_XID0DO, wch);
 		else {
-			printk(KERN_WARNING "mpc: %s() Unable to start"
-				" ACTIVE XID0 on write channel\n",
-					__FUNCTION__);
+			CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+				"%s(%s): WX-%s not ready for ACTIVE XID0",
+					CTCM_FUNTAIL, dev->name, wch->id);
 			if (grp->estconnfunc) {
 				grp->estconnfunc(grp->port_num, -1, 0);
 				grp->estconnfunc = NULL;
@@ -508,7 +517,7 @@
 	}
 
 done:
-	ctcm_pr_debug("ctcmpc exit:  %s()\n", __FUNCTION__);
+	CTCM_PR_DEBUG("Exit %s()\n", __func__);
 	return;
 }
 EXPORT_SYMBOL(ctc_mpc_establish_connectivity);
@@ -520,40 +529,22 @@
 void ctc_mpc_dealloc_ch(int port_num)
 {
 	struct net_device *dev;
-	char device[20];
 	struct ctcm_priv *priv;
 	struct mpc_group *grp;
 
-	ctcm_pr_debug("ctcmpc enter:	%s()\n", __FUNCTION__);
-	sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
-	dev = __dev_get_by_name(&init_net, device);
-
-	if (dev == NULL) {
-		printk(KERN_INFO "%s() %s dev=NULL\n", __FUNCTION__, device);
-					goto done;
-	}
-
-	ctcm_pr_debug("ctcmpc:%s %s() called for device %s refcount=%d\n",
-			dev->name, __FUNCTION__,
-			dev->name, atomic_read(&dev->refcnt));
-
+	dev = ctcmpc_get_dev(port_num);
+	if (dev == NULL)
+		return;
 	priv = dev->priv;
-	if (priv == NULL) {
-		printk(KERN_INFO "%s() %s priv=NULL\n",
-				__FUNCTION__, device);
-					goto done;
-	}
-	fsm_deltimer(&priv->restart_timer);
-
 	grp = priv->mpcg;
-	if (grp == NULL) {
-		printk(KERN_INFO "%s() %s dev=NULL\n", __FUNCTION__, device);
-					goto done;
-	}
+
+	CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_DEBUG,
+			"%s: %s: refcount = %d\n",
+			CTCM_FUNTAIL, dev->name, atomic_read(&dev->refcnt));
+
+	fsm_deltimer(&priv->restart_timer);
 	grp->channels_terminating = 0;
-
 	fsm_deltimer(&grp->timer);
-
 	grp->allochanfunc = NULL;
 	grp->estconnfunc = NULL;
 	grp->port_persist = 0;
@@ -561,8 +552,6 @@
 	fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
 
 	ctcm_close(dev);
-done:
-	ctcm_pr_debug("ctcmpc exit:  %s()\n", __FUNCTION__);
 	return;
 }
 EXPORT_SYMBOL(ctc_mpc_dealloc_ch);
@@ -573,32 +562,22 @@
  */
 void ctc_mpc_flow_control(int port_num, int flowc)
 {
-	char device[20];
 	struct ctcm_priv *priv;
 	struct mpc_group *grp;
 	struct net_device *dev;
 	struct channel *rch;
 	int mpcg_state;
 
-	ctcm_pr_debug("ctcmpc enter:	%s() %i\n", __FUNCTION__, flowc);
-
-	sprintf(device, "%s%i", MPC_DEVICE_NAME, port_num);
-	dev = __dev_get_by_name(&init_net, device);
-
-	if (dev == NULL) {
-		printk(KERN_INFO "ctc_mpc_flow_control %s dev=NULL\n", device);
+	dev = ctcmpc_get_dev(port_num);
+	if (dev == NULL)
 		return;
-	}
-
-	ctcm_pr_debug("ctcmpc: %s %s called \n", dev->name, __FUNCTION__);
-
-	priv  = dev->priv;
-	if (priv == NULL) {
-		printk(KERN_INFO "ctcmpc:%s() %s priv=NULL\n",
-		       __FUNCTION__, device);
-		return;
-	}
+	priv = dev->priv;
 	grp = priv->mpcg;
+
+	CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
+			"%s: %s: flowc = %d",
+				CTCM_FUNTAIL, dev->name, flowc);
+
 	rch = priv->channel[READ];
 
 	mpcg_state = fsm_getstate(grp->fsm);
@@ -629,7 +608,6 @@
 		break;
 	}
 
-	ctcm_pr_debug("ctcmpc exit:  %s() %i\n", __FUNCTION__, flowc);
 }
 EXPORT_SYMBOL(ctc_mpc_flow_control);
 
@@ -646,12 +624,8 @@
 	struct mpc_group  *grp = priv->mpcg;
 	struct channel	  *ch = priv->channel[WRITE];
 
-	if (do_debug)
-		ctcm_pr_debug("ctcmpc enter: %s(): ch=0x%p id=%s\n",
-			__FUNCTION__, ch, ch->id);
-
-	if (do_debug_data)
-		ctcmpc_dumpit((char *)mpcginfo->sweep, TH_SWEEP_LENGTH);
+	CTCM_PR_DEBUG("%s: ch=0x%p id=%s\n", __func__, ch, ch->id);
+	CTCM_D3_DUMP((char *)mpcginfo->sweep, TH_SWEEP_LENGTH);
 
 	grp->sweep_rsp_pend_num--;
 
@@ -684,14 +658,13 @@
 	struct sk_buff *sweep_skb;
 	struct channel *ch  = priv->channel[WRITE];
 
-	if (do_debug)
-		ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
-			__FUNCTION__, rch, rch->id);
+	CTCM_PR_DEBUG("%s: ch=0x%p id=%s\n", __func__, rch, rch->id);
 
-	sweep_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT,
-				    GFP_ATOMIC|GFP_DMA);
+	sweep_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC | GFP_DMA);
 	if (sweep_skb == NULL) {
-		printk(KERN_INFO "Couldn't alloc sweep_skb\n");
+		CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+			"%s(%s): sweep_skb allocation ERROR\n",
+			CTCM_FUNTAIL, rch->id);
 		rc = -ENOMEM;
 				goto done;
 	}
@@ -746,7 +719,7 @@
 
 	if (do_debug)
 		CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
-			" %s(): ch=0x%p id=%s\n", __FUNCTION__, ch, ch->id);
+			" %s(): ch=0x%p id=%s\n", __func__, ch, ch->id);
 
 	if (grp->in_sweep == 0) {
 		grp->in_sweep = 1;
@@ -755,8 +728,7 @@
 		grp->sweep_rsp_pend_num = grp->active_channels[READ];
 	}
 
-	if (do_debug_data)
-		ctcmpc_dumpit((char *)mpcginfo->sweep, TH_SWEEP_LENGTH);
+	CTCM_D3_DUMP((char *)mpcginfo->sweep, TH_SWEEP_LENGTH);
 
 	grp->sweep_req_pend_num--;
 	ctcmpc_send_sweep_resp(ch);
@@ -875,25 +847,13 @@
 static void mpc_action_go_ready(fsm_instance *fsm, int event, void *arg)
 {
 	struct net_device *dev = arg;
-	struct ctcm_priv *priv = NULL;
-	struct mpc_group *grp = NULL;
+	struct ctcm_priv *priv = dev->priv;
+	struct mpc_group *grp = priv->mpcg;
 
-	if (dev == NULL) {
-		printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
-		return;
-	}
-
-	ctcm_pr_debug("ctcmpc enter: %s  %s()\n", dev->name, __FUNCTION__);
-
-	priv = dev->priv;
-	if (priv == NULL) {
-		printk(KERN_INFO "%s() priv=NULL\n", __FUNCTION__);
-		return;
-	}
-
-	grp = priv->mpcg;
 	if (grp == NULL) {
-		printk(KERN_INFO "%s() grp=NULL\n", __FUNCTION__);
+		CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+			"%s(%s): No MPC group",
+				CTCM_FUNTAIL, dev->name);
 		return;
 	}
 
@@ -907,7 +867,12 @@
 			grp->estconnfunc = NULL;
 		} else if (grp->allochanfunc)
 			grp->send_qllc_disc = 1;
-					goto done;
+
+		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+		CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+				"%s(%s): fails",
+					CTCM_FUNTAIL, dev->name);
+		return;
 	}
 
 	grp->port_persist = 1;
@@ -916,14 +881,7 @@
 
 	tasklet_hi_schedule(&grp->mpc_tasklet2);
 
-	ctcm_pr_debug("ctcmpc exit: %s  %s()\n", dev->name, __FUNCTION__);
 	return;
-
-done:
-	fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
-
-
-	ctcm_pr_info("ctcmpc: %s()failure occurred\n", __FUNCTION__);
 }
 
 /*
@@ -933,42 +891,28 @@
 void mpc_group_ready(unsigned long adev)
 {
 	struct net_device *dev = (struct net_device *)adev;
-	struct ctcm_priv *priv = NULL;
-	struct mpc_group  *grp = NULL;
+	struct ctcm_priv *priv = dev->priv;
+	struct mpc_group *grp = priv->mpcg;
 	struct channel *ch = NULL;
 
-
-	ctcm_pr_debug("ctcmpc enter:	%s()\n", __FUNCTION__);
-
-	if (dev == NULL) {
-		printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
-		return;
-	}
-
-	priv = dev->priv;
-	if (priv == NULL) {
-		printk(KERN_INFO "%s() priv=NULL\n", __FUNCTION__);
-		return;
-	}
-
-	grp = priv->mpcg;
 	if (grp == NULL) {
-		printk(KERN_INFO "ctcmpc:%s() grp=NULL\n", __FUNCTION__);
+		CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+			"%s(%s): No MPC group",
+				CTCM_FUNTAIL, dev->name);
 		return;
 	}
 
-	printk(KERN_NOTICE "ctcmpc: %s GROUP TRANSITIONED TO READY"
-	       "  maxbuf:%d\n",
-	       dev->name, grp->group_max_buflen);
+	CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_NOTICE,
+		"%s: %s: GROUP TRANSITIONED TO READY, maxbuf = %d\n",
+			CTCM_FUNTAIL, dev->name, grp->group_max_buflen);
 
 	fsm_newstate(grp->fsm, MPCG_STATE_READY);
 
 	/* Put up a read on the channel */
 	ch = priv->channel[READ];
 	ch->pdu_seq = 0;
-	if (do_debug_data)
-		ctcm_pr_debug("ctcmpc: %s() ToDCM_pdu_seq= %08x\n" ,
-			__FUNCTION__, ch->pdu_seq);
+	CTCM_PR_DBGDATA("ctcmpc: %s() ToDCM_pdu_seq= %08x\n" ,
+			__func__, ch->pdu_seq);
 
 	ctcmpc_chx_rxidle(ch->fsm, CTC_EVENT_START, ch);
 	/* Put the write channel in idle state */
@@ -980,22 +924,18 @@
 		spin_unlock(&ch->collect_lock);
 	}
 	ctcm_chx_txidle(ch->fsm, CTC_EVENT_START, ch);
-
 	ctcm_clear_busy(dev);
 
 	if (grp->estconnfunc) {
 		grp->estconnfunc(grp->port_num, 0,
 				    grp->group_max_buflen);
 		grp->estconnfunc = NULL;
-	} else
-		if (grp->allochanfunc)
-		grp->allochanfunc(grp->port_num,
-				     grp->group_max_buflen);
+	} else 	if (grp->allochanfunc)
+		grp->allochanfunc(grp->port_num, grp->group_max_buflen);
 
 	grp->send_qllc_disc = 1;
 	grp->changed_side = 0;
 
-	ctcm_pr_debug("ctcmpc exit:  %s()\n", __FUNCTION__);
 	return;
 
 }
@@ -1004,51 +944,26 @@
  * Increment the MPC Group Active Channel Counts
  * helper of dev_action (called from channel fsm)
  */
-int mpc_channel_action(struct channel *ch, int direction, int action)
+void mpc_channel_action(struct channel *ch, int direction, int action)
 {
-	struct net_device  *dev     = ch->netdev;
-	struct ctcm_priv    *priv;
-	struct mpc_group   *grp  = NULL;
-	int	    rc = 0;
-
-	if (do_debug)
-		ctcm_pr_debug("ctcmpc enter: %s(): ch=0x%p id=%s\n",
-			__FUNCTION__, ch, ch->id);
-
-	if (dev == NULL) {
-		printk(KERN_INFO "ctcmpc_channel_action %i dev=NULL\n",
-		       action);
-		rc = 1;
-					goto done;
-	}
-
-	priv = dev->priv;
-	if (priv == NULL) {
-		printk(KERN_INFO
-		       "ctcmpc_channel_action%i priv=NULL, dev=%s\n",
-		       action, dev->name);
-		rc = 2;
-					goto done;
-	}
-
-	grp = priv->mpcg;
+	struct net_device  *dev  = ch->netdev;
+	struct ctcm_priv   *priv = dev->priv;
+	struct mpc_group   *grp  = priv->mpcg;
 
 	if (grp == NULL) {
-		printk(KERN_INFO "ctcmpc: %s()%i mpcgroup=NULL, dev=%s\n",
-		       __FUNCTION__, action, dev->name);
-		rc = 3;
-					goto done;
+		CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+			"%s(%s): No MPC group",
+				CTCM_FUNTAIL, dev->name);
+		return;
 	}
 
-	ctcm_pr_info(
-		      "ctcmpc: %s() %i(): Grp:%s total_channel_paths=%i "
-		      "active_channels read=%i, write=%i\n",
-		      __FUNCTION__,
-		      action,
-		      fsm_getstate_str(grp->fsm),
-		      grp->num_channel_paths,
-		      grp->active_channels[READ],
-		      grp->active_channels[WRITE]);
+	CTCM_PR_DEBUG("enter %s: ch=0x%p id=%s\n", __func__, ch, ch->id);
+
+	CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_NOTICE,
+		"%s: %i / Grp:%s total_channels=%i, active_channels: "
+		"read=%i, write=%i\n", __func__, action,
+		fsm_getstate_str(grp->fsm), grp->num_channel_paths,
+		grp->active_channels[READ], grp->active_channels[WRITE]);
 
 	if ((action == MPC_CHANNEL_ADD) && (ch->in_mpcgroup == 0)) {
 		grp->num_channel_paths++;
@@ -1062,10 +977,11 @@
 		ch->xid_skb = __dev_alloc_skb(MPC_BUFSIZE_DEFAULT,
 					GFP_ATOMIC | GFP_DMA);
 		if (ch->xid_skb == NULL) {
-			printk(KERN_INFO "ctcmpc: %s()"
-			       "Couldn't alloc ch xid_skb\n", __FUNCTION__);
+			CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+				"%s(%s): Couldn't alloc ch xid_skb\n",
+				CTCM_FUNTAIL, dev->name);
 			fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
-			return 1;
+			return;
 		}
 		ch->xid_skb_data = ch->xid_skb->data;
 		ch->xid_th = (struct th_header *)ch->xid_skb->data;
@@ -1097,8 +1013,9 @@
 		    (grp->active_channels[WRITE] > 0) &&
 			(fsm_getstate(grp->fsm) < MPCG_STATE_XID2INITW)) {
 			fsm_newstate(grp->fsm, MPCG_STATE_XID2INITW);
-			printk(KERN_NOTICE "ctcmpc: %s MPC GROUP "
-					"CHANNELS ACTIVE\n", dev->name);
+			CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_NOTICE,
+				"%s: %s: MPC GROUP CHANNELS ACTIVE\n",
+						__func__, dev->name);
 		}
 	} else if ((action == MPC_CHANNEL_REMOVE) &&
 			(ch->in_mpcgroup == 1)) {
@@ -1119,25 +1036,14 @@
 					(grp->active_channels[READ] > 0)))
 			fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
 	}
-
 done:
+	CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
+		"exit %s: %i / Grp:%s total_channels=%i, active_channels: "
+		"read=%i, write=%i\n", __func__, action,
+		fsm_getstate_str(grp->fsm), grp->num_channel_paths,
+		grp->active_channels[READ], grp->active_channels[WRITE]);
 
-	if (do_debug) {
-		ctcm_pr_debug(
-		       "ctcmpc: %s() %i Grp:%s ttl_chan_paths=%i "
-		       "active_chans read=%i, write=%i\n",
-		       __FUNCTION__,
-		       action,
-		       fsm_getstate_str(grp->fsm),
-		       grp->num_channel_paths,
-		       grp->active_channels[READ],
-		       grp->active_channels[WRITE]);
-
-		ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
-				__FUNCTION__, ch, ch->id);
-	}
-	return rc;
-
+	CTCM_PR_DEBUG("exit %s: ch=0x%p id=%s\n", __func__, ch, ch->id);
 }
 
 /**
@@ -1163,9 +1069,8 @@
 	int skblen;
 	int sendrc = 0;
 
-	if (do_debug)
-		ctcm_pr_debug("ctcmpc enter: %s() %s cp:%i ch:%s\n",
-		       __FUNCTION__, dev->name, smp_processor_id(), ch->id);
+	CTCM_PR_DEBUG("ctcmpc enter: %s() %s cp:%i ch:%s\n",
+			__func__, dev->name, smp_processor_id(), ch->id);
 
 	header = (struct th_header *)pskb->data;
 	if ((header->th_seg == 0) &&
@@ -1174,21 +1079,16 @@
 		(header->th_seq_num == 0))
 		/* nothing for us */	goto done;
 
-	if (do_debug_data) {
-		ctcm_pr_debug("ctcmpc: %s() th_header\n", __FUNCTION__);
-		ctcmpc_dumpit((char *)header, TH_HEADER_LENGTH);
-		ctcm_pr_debug("ctcmpc: %s() pskb len: %04x \n",
-		       __FUNCTION__, pskb->len);
-	}
+	CTCM_PR_DBGDATA("%s: th_header\n", __func__);
+	CTCM_D3_DUMP((char *)header, TH_HEADER_LENGTH);
+	CTCM_PR_DBGDATA("%s: pskb len: %04x \n", __func__, pskb->len);
 
 	pskb->dev = dev;
 	pskb->ip_summed = CHECKSUM_UNNECESSARY;
 	skb_pull(pskb, TH_HEADER_LENGTH);
 
 	if (likely(header->th_ch_flag == TH_HAS_PDU)) {
-		if (do_debug_data)
-			ctcm_pr_debug("ctcmpc: %s() came into th_has_pdu\n",
-			       __FUNCTION__);
+		CTCM_PR_DBGDATA("%s: came into th_has_pdu\n", __func__);
 		if ((fsm_getstate(grp->fsm) == MPCG_STATE_FLOWC) ||
 		   ((fsm_getstate(grp->fsm) == MPCG_STATE_READY) &&
 		    (header->th_seq_num != ch->th_seq_num + 1) &&
@@ -1202,33 +1102,29 @@
 			grp->out_of_sequence += 1;
 			__skb_push(pskb, TH_HEADER_LENGTH);
 			skb_queue_tail(&ch->io_queue, pskb);
-			if (do_debug_data)
-				ctcm_pr_debug("ctcmpc: %s() th_seq_num "
-				       "expect:%08x got:%08x\n", __FUNCTION__,
-				       ch->th_seq_num + 1, header->th_seq_num);
+			CTCM_PR_DBGDATA("%s: th_seq_num expect:%08x "
+					"got:%08x\n", __func__,
+				ch->th_seq_num + 1, header->th_seq_num);
 
 			return;
 		}
 		grp->out_of_sequence = 0;
 		ch->th_seq_num = header->th_seq_num;
 
-		if (do_debug_data)
-			ctcm_pr_debug("ctcmpc: %s() FromVTAM_th_seq=%08x\n",
-			       __FUNCTION__, ch->th_seq_num);
+		CTCM_PR_DBGDATA("ctcmpc: %s() FromVTAM_th_seq=%08x\n",
+					__func__, ch->th_seq_num);
 
 		if (unlikely(fsm_getstate(grp->fsm) != MPCG_STATE_READY))
 					goto done;
 		pdu_last_seen = 0;
 		while ((pskb->len > 0) && !pdu_last_seen) {
 			curr_pdu = (struct pdu *)pskb->data;
-			if (do_debug_data) {
-				ctcm_pr_debug("ctcm: %s() pdu_header\n",
-				       __FUNCTION__);
-				ctcmpc_dumpit((char *)pskb->data,
-						PDU_HEADER_LENGTH);
-				ctcm_pr_debug("ctcm: %s() pskb len: %04x \n",
-				       __FUNCTION__, pskb->len);
-			}
+
+			CTCM_PR_DBGDATA("%s: pdu_header\n", __func__);
+			CTCM_D3_DUMP((char *)pskb->data, PDU_HEADER_LENGTH);
+			CTCM_PR_DBGDATA("%s: pskb len: %04x \n",
+						__func__, pskb->len);
+
 			skb_pull(pskb, PDU_HEADER_LENGTH);
 
 			if (curr_pdu->pdu_flag & PDU_LAST)
@@ -1239,46 +1135,39 @@
 				pskb->protocol = htons(ETH_P_SNA_DIX);
 
 			if ((pskb->len <= 0) || (pskb->len > ch->max_bufsize)) {
-				printk(KERN_INFO
-				       "%s Illegal packet size %d "
-				       "received "
-				       "dropping\n", dev->name,
-				       pskb->len);
+				CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+					"%s(%s): Dropping packet with "
+					"illegal siize %d",
+					CTCM_FUNTAIL, dev->name, pskb->len);
+
 				priv->stats.rx_dropped++;
 				priv->stats.rx_length_errors++;
 					goto done;
 			}
 			skb_reset_mac_header(pskb);
 			new_len = curr_pdu->pdu_offset;
-			if (do_debug_data)
-				ctcm_pr_debug("ctcmpc: %s() new_len: %04x \n",
-				       __FUNCTION__, new_len);
+			CTCM_PR_DBGDATA("%s: new_len: %04x \n",
+						__func__, new_len);
 			if ((new_len == 0) || (new_len > pskb->len)) {
 				/* should never happen		    */
 				/* pskb len must be hosed...bail out */
-				printk(KERN_INFO
-				       "ctcmpc: %s(): invalid pdu"
-				       " offset of %04x - data may be"
-				       "lost\n", __FUNCTION__, new_len);
-						goto done;
+				CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+					"%s(%s): non valid pdu_offset: %04x",
+					/* "data may be lost", */
+					CTCM_FUNTAIL, dev->name, new_len);
+				goto done;
 			}
 			skb = __dev_alloc_skb(new_len+4, GFP_ATOMIC);
 
 			if (!skb) {
-				printk(KERN_INFO
-				       "ctcm: %s Out of memory in "
-				       "%s()- request-len:%04x \n",
-				       dev->name,
-				       __FUNCTION__,
-				       new_len+4);
+				CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+					"%s(%s): MEMORY allocation error",
+						CTCM_FUNTAIL, dev->name);
 				priv->stats.rx_dropped++;
-				fsm_event(grp->fsm,
-					  MPCG_EVENT_INOP, dev);
+				fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
 						goto done;
 			}
-
-			memcpy(skb_put(skb, new_len),
-					pskb->data, new_len);
+			memcpy(skb_put(skb, new_len), pskb->data, new_len);
 
 			skb_reset_mac_header(skb);
 			skb->dev = pskb->dev;
@@ -1287,17 +1176,14 @@
 			*((__u32 *) skb_push(skb, 4)) = ch->pdu_seq;
 			ch->pdu_seq++;
 
-			if (do_debug_data)
-				ctcm_pr_debug("%s: ToDCM_pdu_seq= %08x\n",
-				       __FUNCTION__, ch->pdu_seq);
-
-			ctcm_pr_debug("ctcm: %s() skb:%0lx "
-				"skb len: %d \n", __FUNCTION__,
-			       (unsigned long)skb, skb->len);
 			if (do_debug_data) {
-				ctcm_pr_debug("ctcmpc: %s() up to 32 bytes"
-					       " of pdu_data sent\n",
-					       __FUNCTION__);
+				ctcm_pr_debug("%s: ToDCM_pdu_seq= %08x\n",
+						__func__, ch->pdu_seq);
+				ctcm_pr_debug("%s: skb:%0lx "
+					"skb len: %d \n", __func__,
+					(unsigned long)skb, skb->len);
+				ctcm_pr_debug("%s: up to 32 bytes "
+					"of pdu_data sent\n", __func__);
 				ctcmpc_dump32((char *)skb->data, skb->len);
 			}
 
@@ -1316,8 +1202,8 @@
 		mpcginfo->ch = ch;
 		mpcginfo->th = header;
 		mpcginfo->skb = pskb;
-		ctcm_pr_debug("ctcmpc: %s() Not PDU - may be control pkt\n",
-			       __FUNCTION__);
+		CTCM_PR_DEBUG("%s: Not PDU - may be control pkt\n",
+					__func__);
 		/*  it's a sweep?   */
 		sweep = (struct th_sweep *)pskb->data;
 		mpcginfo->sweep = sweep;
@@ -1333,8 +1219,9 @@
 		} else if (header->th_blk_flag == TH_DISCONTACT)
 			fsm_event(grp->fsm, MPCG_EVENT_DISCONC, mpcginfo);
 		else if (header->th_seq_num != 0) {
-			printk(KERN_INFO "%s unexpected packet"
-					" expected control pkt\n", dev->name);
+			CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+				"%s(%s): control pkt expected\n",
+						CTCM_FUNTAIL, dev->name);
 			priv->stats.rx_dropped++;
 			/* mpcginfo only used for non-data transfers */
 			kfree(mpcginfo);
@@ -1347,13 +1234,12 @@
 	dev_kfree_skb_any(pskb);
 	if (sendrc == NET_RX_DROP) {
 		printk(KERN_WARNING "%s %s() NETWORK BACKLOG EXCEEDED"
-		       " - PACKET DROPPED\n", dev->name, __FUNCTION__);
+		       " - PACKET DROPPED\n", dev->name, __func__);
 		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
 	}
 
-	if (do_debug)
-		ctcm_pr_debug("ctcmpc exit : %s %s(): ch=0x%p id=%s\n",
-				dev->name, __FUNCTION__, ch, ch->id);
+	CTCM_PR_DEBUG("exit %s: %s: ch=0x%p id=%s\n",
+			__func__, dev->name, ch, ch->id);
 }
 
 /**
@@ -1366,15 +1252,14 @@
  */
 void ctcmpc_bh(unsigned long thischan)
 {
-	struct channel	  *ch	    = (struct channel *)thischan;
+	struct channel	  *ch	= (struct channel *)thischan;
 	struct sk_buff	  *skb;
-	struct net_device *dev	    = ch->netdev;
-	struct ctcm_priv  *priv  = dev->priv;
-	struct mpc_group  *grp   = priv->mpcg;
+	struct net_device *dev	= ch->netdev;
+	struct ctcm_priv  *priv	= dev->priv;
+	struct mpc_group  *grp	= priv->mpcg;
 
-	if (do_debug)
-		ctcm_pr_debug("%s cp:%i enter:  %s() %s\n",
-		       dev->name, smp_processor_id(), __FUNCTION__, ch->id);
+	CTCM_PR_DEBUG("%s cp:%i enter:  %s() %s\n",
+	       dev->name, smp_processor_id(), __func__, ch->id);
 	/* caller has requested driver to throttle back */
 	while ((fsm_getstate(grp->fsm) != MPCG_STATE_FLOWC) &&
 			(skb = skb_dequeue(&ch->io_queue))) {
@@ -1390,9 +1275,8 @@
 		if (skb == skb_peek(&ch->io_queue))
 			break;
 	}
-	if (do_debug)
-		ctcm_pr_debug("ctcmpc exit : %s %s(): ch=0x%p id=%s\n",
-			dev->name, __FUNCTION__, ch,  ch->id);
+	CTCM_PR_DEBUG("exit %s: %s: ch=0x%p id=%s\n",
+			__func__, dev->name, ch, ch->id);
 	return;
 }
 
@@ -1403,16 +1287,16 @@
 {
 	struct mpc_group *grp;
 
-	CTCM_DBF_TEXT(MPC_SETUP, 3, __FUNCTION__);
+	CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_INFO,
+			"Enter %s(%p)", CTCM_FUNTAIL, priv);
 
 	grp = kzalloc(sizeof(struct mpc_group), GFP_KERNEL);
 	if (grp == NULL)
 		return NULL;
 
-	grp->fsm =
-		init_fsm("mpcg", mpcg_state_names, mpcg_event_names,
-				 MPCG_NR_STATES, MPCG_NR_EVENTS, mpcg_fsm,
-				 mpcg_fsm_len, GFP_KERNEL);
+	grp->fsm = init_fsm("mpcg", mpcg_state_names, mpcg_event_names,
+			MPCG_NR_STATES, MPCG_NR_EVENTS, mpcg_fsm,
+			mpcg_fsm_len, GFP_KERNEL);
 	if (grp->fsm == NULL) {
 		kfree(grp);
 		return NULL;
@@ -1424,7 +1308,6 @@
 	grp->xid_skb =
 		 __dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC | GFP_DMA);
 	if (grp->xid_skb == NULL) {
-		printk(KERN_INFO "Couldn't alloc MPCgroup xid_skb\n");
 		kfree_fsm(grp->fsm);
 		kfree(grp);
 		return NULL;
@@ -1435,7 +1318,7 @@
 	memcpy(skb_put(grp->xid_skb, TH_HEADER_LENGTH),
 			&thnorm, TH_HEADER_LENGTH);
 
-	grp->xid = (struct xid2 *) skb_tail_pointer(grp->xid_skb);
+	grp->xid = (struct xid2 *)skb_tail_pointer(grp->xid_skb);
 	memcpy(skb_put(grp->xid_skb, XID2_LENGTH), &init_xid, XID2_LENGTH);
 	grp->xid->xid2_adj_id = jiffies | 0xfff00000;
 	grp->xid->xid2_sender_id = jiffies;
@@ -1446,7 +1329,6 @@
 	grp->rcvd_xid_skb =
 		__dev_alloc_skb(MPC_BUFSIZE_DEFAULT, GFP_ATOMIC|GFP_DMA);
 	if (grp->rcvd_xid_skb == NULL) {
-		printk(KERN_INFO "Couldn't alloc MPCgroup rcvd_xid_skb\n");
 		kfree_fsm(grp->fsm);
 		dev_kfree_skb(grp->xid_skb);
 		kfree(grp);
@@ -1492,32 +1374,27 @@
 	int rc = 0;
 	struct channel *wch, *rch;
 
-	if (dev == NULL) {
-		printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
-		return;
-	}
-
-	ctcm_pr_debug("ctcmpc enter: %s  %s()\n", dev->name, __FUNCTION__);
+	BUG_ON(dev == NULL);
+	CTCM_PR_DEBUG("Enter %s: %s\n",	__func__, dev->name);
 
 	priv  = dev->priv;
 	grp =  priv->mpcg;
 	grp->flow_off_called = 0;
-
 	fsm_deltimer(&grp->timer);
-
 	if (grp->channels_terminating)
-					goto done;
+			return;
 
 	grp->channels_terminating = 1;
-
 	grp->saved_state = fsm_getstate(grp->fsm);
 	fsm_newstate(grp->fsm, MPCG_STATE_INOP);
 	if (grp->saved_state > MPCG_STATE_XID7INITF)
-		printk(KERN_NOTICE "%s:MPC GROUP INOPERATIVE\n", dev->name);
+		CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_NOTICE,
+			"%s(%s): MPC GROUP INOPERATIVE",
+				CTCM_FUNTAIL, dev->name);
 	if ((grp->saved_state != MPCG_STATE_RESET) ||
 		/* dealloc_channel has been called */
-		((grp->saved_state == MPCG_STATE_RESET) &&
-				(grp->port_persist == 0)))
+			((grp->saved_state == MPCG_STATE_RESET) &&
+						(grp->port_persist == 0)))
 		fsm_deltimer(&priv->restart_timer);
 
 	wch = priv->channel[WRITE];
@@ -1567,29 +1444,24 @@
 	/* This can result in INOP of VTAM PU due to halting of  */
 	/* outstanding IO which causes a sense to be returned	 */
 	/* Only about 3 senses are allowed and then IOS/VTAM will*/
-	/* ebcome unreachable without manual intervention	 */
-	if ((grp->port_persist == 1)	|| (grp->alloc_called)) {
+	/* become unreachable without manual intervention	 */
+	if ((grp->port_persist == 1) || (grp->alloc_called)) {
 		grp->alloc_called = 0;
 		fsm_deltimer(&priv->restart_timer);
-		fsm_addtimer(&priv->restart_timer,
-			     500,
-			     DEV_EVENT_RESTART,
-			     dev);
+		fsm_addtimer(&priv->restart_timer, 500, DEV_EVENT_RESTART, dev);
 		fsm_newstate(grp->fsm, MPCG_STATE_RESET);
 		if (grp->saved_state > MPCG_STATE_XID7INITF)
-			printk(KERN_NOTICE "%s:MPC GROUP RECOVERY SCHEDULED\n",
-			       dev->name);
+			CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_ALWAYS,
+				"%s(%s): MPC GROUP RECOVERY SCHEDULED",
+					CTCM_FUNTAIL, dev->name);
 	} else {
 		fsm_deltimer(&priv->restart_timer);
 		fsm_addtimer(&priv->restart_timer, 500, DEV_EVENT_STOP, dev);
 		fsm_newstate(grp->fsm, MPCG_STATE_RESET);
-		printk(KERN_NOTICE "%s:MPC GROUP RECOVERY NOT ATTEMPTED\n",
-		       dev->name);
+		CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_ALWAYS,
+			"%s(%s): NO MPC GROUP RECOVERY ATTEMPTED",
+						CTCM_FUNTAIL, dev->name);
 	}
-
-done:
-	ctcm_pr_debug("ctcmpc exit:%s  %s()\n", dev->name, __FUNCTION__);
-	return;
 }
 
 /**
@@ -1609,12 +1481,7 @@
 	struct channel *wch;
 	struct channel *rch;
 
-	CTCM_DBF_TEXT(MPC_TRACE, 6, __FUNCTION__);
-
-	if (dev == NULL) {
-		CTCM_DBF_TEXT_(MPC_ERROR, 4, "%s: dev=NULL\n", __FUNCTION__);
-		return;
-	}
+	BUG_ON(dev == NULL);
 
 	priv = dev->priv;
 	grp = priv->mpcg;
@@ -1633,8 +1500,9 @@
 		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
 	}
 
-	CTCM_DBF_TEXT_(MPC_TRACE, 6, "%s: dev=%s exit",
-					__FUNCTION__, dev->name);
+	CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG,
+			"%s: dev=%s exit",
+			CTCM_FUNTAIL, dev->name);
 	return;
 }
 
@@ -1646,25 +1514,25 @@
 {
 	struct mpcg_info   *mpcginfo   = arg;
 	struct channel	   *ch	       = mpcginfo->ch;
-	struct net_device  *dev        = ch->netdev;
-	struct ctcm_priv   *priv    = dev->priv;
-	struct mpc_group   *grp     = priv->mpcg;
+	struct net_device  *dev;
+	struct ctcm_priv   *priv;
+	struct mpc_group   *grp;
 
-	if (ch == NULL)	{
-		printk(KERN_INFO "%s() ch=NULL\n", __FUNCTION__);
-		return;
-	}
-	if (ch->netdev == NULL)	{
-		printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
-		return;
+	if (ch) {
+		dev = ch->netdev;
+		if (dev) {
+			priv = dev->priv;
+			if (priv) {
+				CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_NOTICE,
+					"%s: %s: %s\n",
+					CTCM_FUNTAIL, dev->name, ch->id);
+				grp = priv->mpcg;
+				grp->send_qllc_disc = 1;
+				fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+			}
+		}
 	}
 
-	ctcm_pr_debug("ctcmpc enter: %s  %s()\n", dev->name, __FUNCTION__);
-
-	grp->send_qllc_disc = 1;
-	fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
-
-	ctcm_pr_debug("ctcmpc exit: %s  %s()\n", dev->name, __FUNCTION__);
 	return;
 }
 
@@ -1675,26 +1543,9 @@
  */
 void mpc_action_send_discontact(unsigned long thischan)
 {
-	struct channel	   *ch;
-	struct net_device  *dev;
-	struct ctcm_priv    *priv;
-	struct mpc_group   *grp;
-	int rc = 0;
-	unsigned long	  saveflags;
-
-	ch = (struct channel *)thischan;
-	dev = ch->netdev;
-	priv = dev->priv;
-	grp = priv->mpcg;
-
-	ctcm_pr_info("ctcmpc: %s cp:%i enter: %s() GrpState:%s ChState:%s\n",
-		       dev->name,
-		       smp_processor_id(),
-		       __FUNCTION__,
-		       fsm_getstate_str(grp->fsm),
-		       fsm_getstate_str(ch->fsm));
-	saveflags = 0;	/* avoids compiler warning with
-			   spin_unlock_irqrestore */
+	int rc;
+	struct channel	*ch = (struct channel *)thischan;
+	unsigned long	saveflags = 0;
 
 	spin_lock_irqsave(get_ccwdev_lock(ch->cdev), saveflags);
 	rc = ccw_device_start(ch->cdev, &ch->ccw[15],
@@ -1702,16 +1553,9 @@
 	spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
 
 	if (rc != 0) {
-		ctcm_pr_info("ctcmpc: %s() ch:%s IO failed \n",
-			       __FUNCTION__,
-			       ch->id);
-		ctcm_ccw_check_rc(ch, rc, "send discontact");
-		/* Not checking return code value here */
-		/* Making best effort to notify partner*/
-		/* that MPC Group is going down        */
+		ctcm_ccw_check_rc(ch, rc, (char *)__func__);
 	}
 
-	ctcm_pr_debug("ctcmpc exit: %s  %s()\n", dev->name, __FUNCTION__);
 	return;
 }
 
@@ -1723,49 +1567,50 @@
 */
 static int mpc_validate_xid(struct mpcg_info *mpcginfo)
 {
-	struct channel	   *ch	    = mpcginfo->ch;
-	struct net_device  *dev     = ch->netdev;
+	struct channel	   *ch	 = mpcginfo->ch;
+	struct net_device  *dev  = ch->netdev;
 	struct ctcm_priv   *priv = dev->priv;
 	struct mpc_group   *grp  = priv->mpcg;
-	struct xid2	   *xid     = mpcginfo->xid;
-	int	failed	= 0;
-	int	rc	= 0;
-	__u64	our_id, their_id = 0;
-	int	len;
+	struct xid2	   *xid  = mpcginfo->xid;
+	int	rc	 = 0;
+	__u64	our_id   = 0;
+	__u64   their_id = 0;
+	int	len = TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
 
-	len = TH_HEADER_LENGTH + PDU_HEADER_LENGTH;
+	CTCM_PR_DEBUG("Enter %s: xid=%p\n", __func__, xid);
 
-	ctcm_pr_debug("ctcmpc enter:	%s()\n", __FUNCTION__);
-
-	if (mpcginfo->xid == NULL) {
-		printk(KERN_INFO "%s() xid=NULL\n", __FUNCTION__);
+	if (xid == NULL) {
 		rc = 1;
-					goto done;
+		/* XID REJECTED: xid == NULL */
+		CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+			"%s(%s): xid = NULL",
+				CTCM_FUNTAIL, ch->id);
+			goto done;
 	}
 
-	ctcm_pr_debug("ctcmpc :  %s  xid received()\n", __FUNCTION__);
-	ctcmpc_dumpit((char *)mpcginfo->xid, XID2_LENGTH);
+	CTCM_D3_DUMP((char *)xid, XID2_LENGTH);
 
 	/*the received direction should be the opposite of ours  */
 	if (((CHANNEL_DIRECTION(ch->flags) == READ) ? XID2_WRITE_SIDE :
 				XID2_READ_SIDE) != xid->xid2_dlc_type) {
-		failed = 1;
-		printk(KERN_INFO "ctcmpc:%s() XID REJECTED - READ-WRITE CH "
-			"Pairing Invalid \n", __FUNCTION__);
+		rc = 2;
+		/* XID REJECTED: r/w channel pairing mismatch */
+		CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+			"%s(%s): r/w channel pairing mismatch",
+				CTCM_FUNTAIL, ch->id);
+			goto done;
 	}
 
 	if (xid->xid2_dlc_type == XID2_READ_SIDE) {
-		ctcm_pr_debug("ctcmpc: %s(): grpmaxbuf:%d xid2buflen:%d\n",
-				__FUNCTION__, grp->group_max_buflen,
-				xid->xid2_buf_len);
+		CTCM_PR_DEBUG("%s: grpmaxbuf:%d xid2buflen:%d\n", __func__,
+				grp->group_max_buflen, xid->xid2_buf_len);
 
-		if (grp->group_max_buflen == 0 ||
-			grp->group_max_buflen > xid->xid2_buf_len - len)
+		if (grp->group_max_buflen == 0 || grp->group_max_buflen >
+						xid->xid2_buf_len - len)
 			grp->group_max_buflen = xid->xid2_buf_len - len;
 	}
 
-
-	if (grp->saved_xid2 == NULL)	{
+	if (grp->saved_xid2 == NULL) {
 		grp->saved_xid2 =
 			(struct xid2 *)skb_tail_pointer(grp->rcvd_xid_skb);
 
@@ -1786,49 +1631,54 @@
 		/* lower id assume the xside role */
 		if (our_id < their_id) {
 			grp->roll = XSIDE;
-			ctcm_pr_debug("ctcmpc :%s() WE HAVE LOW ID-"
-				       "TAKE XSIDE\n", __FUNCTION__);
+			CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_NOTICE,
+				"%s(%s): WE HAVE LOW ID - TAKE XSIDE",
+					CTCM_FUNTAIL, ch->id);
 		} else {
 			grp->roll = YSIDE;
-			ctcm_pr_debug("ctcmpc :%s() WE HAVE HIGH ID-"
-				       "TAKE YSIDE\n", __FUNCTION__);
+			CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_NOTICE,
+				"%s(%s): WE HAVE HIGH ID - TAKE YSIDE",
+					CTCM_FUNTAIL, ch->id);
 		}
 
 	} else {
 		if (xid->xid2_flag4 != grp->saved_xid2->xid2_flag4) {
-			failed = 1;
-			printk(KERN_INFO "%s XID REJECTED - XID Flag Byte4\n",
-			       __FUNCTION__);
+			rc = 3;
+			/* XID REJECTED: xid flag byte4 mismatch */
+			CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+				"%s(%s): xid flag byte4 mismatch",
+					CTCM_FUNTAIL, ch->id);
 		}
 		if (xid->xid2_flag2 == 0x40) {
-			failed = 1;
-			printk(KERN_INFO "%s XID REJECTED - XID NOGOOD\n",
-			       __FUNCTION__);
+			rc = 4;
+			/* XID REJECTED - xid NOGOOD */
+			CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+				"%s(%s): xid NOGOOD",
+					CTCM_FUNTAIL, ch->id);
 		}
 		if (xid->xid2_adj_id != grp->saved_xid2->xid2_adj_id) {
-			failed = 1;
-			printk(KERN_INFO "%s XID REJECTED - "
-				"Adjacent Station ID Mismatch\n",
-				__FUNCTION__);
+			rc = 5;
+			/* XID REJECTED - Adjacent Station ID Mismatch */
+			CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+				"%s(%s): Adjacent Station ID Mismatch",
+					CTCM_FUNTAIL, ch->id);
 		}
 		if (xid->xid2_sender_id != grp->saved_xid2->xid2_sender_id) {
-			failed = 1;
-			printk(KERN_INFO "%s XID REJECTED - "
-				"Sender Address Mismatch\n", __FUNCTION__);
-
+			rc = 6;
+			/* XID REJECTED - Sender Address Mismatch */
+			CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+				"%s(%s): Sender Address Mismatch",
+					CTCM_FUNTAIL, ch->id);
 		}
 	}
 
-	if (failed) {
-		ctcm_pr_info("ctcmpc	   :  %s() failed\n", __FUNCTION__);
-		priv->xid->xid2_flag2 = 0x40;
-		grp->saved_xid2->xid2_flag2 = 0x40;
-		rc = 1;
-	}
-
 done:
+	if (rc) {
+		ctcm_pr_info("ctcmpc	   :  %s() failed\n", __FUNCTION__);
+		priv->xid->xid2_flag2 = 0x40;
+		grp->saved_xid2->xid2_flag2 = 0x40;
+	}
 
-	ctcm_pr_debug("ctcmpc exit:  %s()\n", __FUNCTION__);
 	return rc;
 }
 
@@ -1839,46 +1689,20 @@
 static void mpc_action_side_xid(fsm_instance *fsm, void *arg, int side)
 {
 	struct channel *ch = arg;
-	struct ctcm_priv *priv;
-	struct mpc_group *grp = NULL;
-	struct net_device *dev = NULL;
 	int rc = 0;
 	int gotlock = 0;
 	unsigned long saveflags = 0;	/* avoids compiler warning with
-			   spin_unlock_irqrestore */
+					   spin_unlock_irqrestore */
 
-	if (ch == NULL)	{
-		printk(KERN_INFO "%s ch=NULL\n", __FUNCTION__);
-					goto done;
-	}
-
-	if (do_debug)
-		ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
-			__FUNCTION__, smp_processor_id(), ch, ch->id);
-
-	dev = ch->netdev;
-	if (dev == NULL) {
-		printk(KERN_INFO "%s dev=NULL\n", __FUNCTION__);
-					goto done;
-	}
-
-	priv = dev->priv;
-	if (priv == NULL) {
-		printk(KERN_INFO "%s priv=NULL\n", __FUNCTION__);
-					goto done;
-	}
-
-	grp = priv->mpcg;
-	if (grp == NULL) {
-		printk(KERN_INFO "%s grp=NULL\n", __FUNCTION__);
-					goto done;
-	}
+	CTCM_PR_DEBUG("Enter %s: cp=%i ch=0x%p id=%s\n",
+			__func__, smp_processor_id(), ch, ch->id);
 
 	if (ctcm_checkalloc_buffer(ch))
 					goto done;
 
-	/* skb data-buffer referencing: */
-
+	/*
+	 * skb data-buffer referencing:
+	 */
 	ch->trans_skb->data = ch->trans_skb_data;
 	skb_reset_tail_pointer(ch->trans_skb);
 	ch->trans_skb->len = 0;
@@ -1911,22 +1735,22 @@
 	ch->ccw[8].count	= 0;
 	ch->ccw[8].cda		= 0x00;
 
+	if (!(ch->xid_th && ch->xid && ch->xid_id))
+		CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_INFO,
+			"%s(%s): xid_th=%p, xid=%p, xid_id=%p",
+			CTCM_FUNTAIL, ch->id, ch->xid_th, ch->xid, ch->xid_id);
+
 	if (side == XSIDE) {
 		/* mpc_action_xside_xid */
-		if (ch->xid_th == NULL) {
-			printk(KERN_INFO "%s ch->xid_th=NULL\n", __FUNCTION__);
-					goto done;
-		}
+		if (ch->xid_th == NULL)
+				goto done;
 		ch->ccw[9].cmd_code	= CCW_CMD_WRITE;
 		ch->ccw[9].flags	= CCW_FLAG_SLI | CCW_FLAG_CC;
 		ch->ccw[9].count	= TH_HEADER_LENGTH;
 		ch->ccw[9].cda		= virt_to_phys(ch->xid_th);
 
-		if (ch->xid == NULL) {
-			printk(KERN_INFO "%s ch->xid=NULL\n", __FUNCTION__);
-					goto done;
-		}
-
+		if (ch->xid == NULL)
+				goto done;
 		ch->ccw[10].cmd_code	= CCW_CMD_WRITE;
 		ch->ccw[10].flags	= CCW_FLAG_SLI | CCW_FLAG_CC;
 		ch->ccw[10].count	= XID2_LENGTH;
@@ -1956,28 +1780,22 @@
 		ch->ccw[10].count	= XID2_LENGTH;
 		ch->ccw[10].cda		= virt_to_phys(ch->rcvd_xid);
 
-		if (ch->xid_th == NULL)	{
-			printk(KERN_INFO "%s ch->xid_th=NULL\n", __FUNCTION__);
-					goto done;
-		}
+		if (ch->xid_th == NULL)
+				goto done;
 		ch->ccw[11].cmd_code	= CCW_CMD_WRITE;
 		ch->ccw[11].flags	= CCW_FLAG_SLI | CCW_FLAG_CC;
 		ch->ccw[11].count	= TH_HEADER_LENGTH;
 		ch->ccw[11].cda		= virt_to_phys(ch->xid_th);
 
-		if (ch->xid == NULL) {
-			printk(KERN_INFO "%s ch->xid=NULL\n", __FUNCTION__);
-					goto done;
-		}
+		if (ch->xid == NULL)
+				goto done;
 		ch->ccw[12].cmd_code	= CCW_CMD_WRITE;
 		ch->ccw[12].flags	= CCW_FLAG_SLI | CCW_FLAG_CC;
 		ch->ccw[12].count	= XID2_LENGTH;
 		ch->ccw[12].cda		= virt_to_phys(ch->xid);
 
-		if (ch->xid_id == NULL)	{
-			printk(KERN_INFO "%s ch->xid_id=NULL\n", __FUNCTION__);
-					goto done;
-		}
+		if (ch->xid_id == NULL)
+				goto done;
 		ch->ccw[13].cmd_code	= CCW_CMD_WRITE;
 		ch->ccw[13].cda		= virt_to_phys(ch->xid_id);
 
@@ -1990,12 +1808,11 @@
 	ch->ccw[14].count	= 0;
 	ch->ccw[14].cda		= 0;
 
-	if (do_debug_ccw)
-		ctcmpc_dumpit((char *)&ch->ccw[8], sizeof(struct ccw1) * 7);
+	CTCM_CCW_DUMP((char *)&ch->ccw[8], sizeof(struct ccw1) * 7);
+	CTCM_D3_DUMP((char *)ch->xid_th, TH_HEADER_LENGTH);
+	CTCM_D3_DUMP((char *)ch->xid, XID2_LENGTH);
+	CTCM_D3_DUMP((char *)ch->xid_id, 4);
 
-	ctcmpc_dumpit((char *)ch->xid_th, TH_HEADER_LENGTH);
-	ctcmpc_dumpit((char *)ch->xid, XID2_LENGTH);
-	ctcmpc_dumpit((char *)ch->xid_id, 4);
 	if (!in_irq()) {
 			 /* Such conditional locking is a known problem for
 			  * sparse because its static undeterministic.
@@ -2012,16 +1829,13 @@
 		spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags);
 
 	if (rc != 0) {
-		ctcm_pr_info("ctcmpc: %s() ch:%s IO failed \n",
-				__FUNCTION__, ch->id);
 		ctcm_ccw_check_rc(ch, rc,
 				(side == XSIDE) ? "x-side XID" : "y-side XID");
 	}
 
 done:
-	if (do_debug)
-		ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
-				__FUNCTION__, ch, ch->id);
+	CTCM_PR_DEBUG("Exit %s: ch=0x%p id=%s\n",
+				__func__, ch, ch->id);
 	return;
 
 }
@@ -2050,41 +1864,19 @@
  */
 static void mpc_action_doxid0(fsm_instance *fsm, int event, void *arg)
 {
-	struct channel	   *ch = arg;
-	struct ctcm_priv    *priv;
-	struct mpc_group   *grp     = NULL;
-	struct net_device *dev = NULL;
+	struct channel	   *ch   = arg;
+	struct net_device  *dev  = ch->netdev;
+	struct ctcm_priv   *priv = dev->priv;
+	struct mpc_group   *grp  = priv->mpcg;
 
-	if (do_debug)
-		ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
-			__FUNCTION__, smp_processor_id(), ch, ch->id);
-
-	if (ch == NULL) {
-		printk(KERN_WARNING "%s ch=NULL\n", __FUNCTION__);
-					goto done;
-	}
-
-	dev = ch->netdev;
-	if (dev == NULL) {
-		printk(KERN_WARNING "%s dev=NULL\n", __FUNCTION__);
-					goto done;
-	}
-
-	priv = dev->priv;
-	if (priv == NULL) {
-		printk(KERN_WARNING "%s priv=NULL\n", __FUNCTION__);
-					goto done;
-	}
-
-	grp = priv->mpcg;
-	if (grp == NULL) {
-		printk(KERN_WARNING "%s grp=NULL\n", __FUNCTION__);
-					goto done;
-	}
+	CTCM_PR_DEBUG("Enter %s: cp=%i ch=0x%p id=%s\n",
+			__func__, smp_processor_id(), ch, ch->id);
 
 	if (ch->xid == NULL) {
-		printk(KERN_WARNING "%s ch-xid=NULL\n", __FUNCTION__);
-					goto done;
+		CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+			"%s(%s): ch->xid == NULL",
+				CTCM_FUNTAIL, dev->name);
+		return;
 	}
 
 	fsm_newstate(ch->fsm, CH_XID0_INPROGRESS);
@@ -2104,12 +1896,7 @@
 
 	fsm_event(grp->fsm, MPCG_EVENT_DOIO, ch);
 
-done:
-	if (do_debug)
-		ctcm_pr_debug("ctcmpc exit : %s(): ch=0x%p id=%s\n",
-			__FUNCTION__, ch, ch->id);
 	return;
-
 }
 
 /*
@@ -2119,32 +1906,16 @@
 static void mpc_action_doxid7(fsm_instance *fsm, int event, void *arg)
 {
 	struct net_device *dev = arg;
-	struct ctcm_priv   *priv = NULL;
-	struct mpc_group  *grp = NULL;
+	struct ctcm_priv  *priv = dev->priv;
+	struct mpc_group  *grp  = NULL;
 	int direction;
-	int rc = 0;
 	int send = 0;
 
-	ctcm_pr_debug("ctcmpc enter:	%s() \n", __FUNCTION__);
-
-	if (dev == NULL) {
-		printk(KERN_INFO "%s dev=NULL \n", __FUNCTION__);
-		rc = 1;
-					goto done;
-	}
-
-	priv = dev->priv;
-	if (priv == NULL) {
-		printk(KERN_INFO "%s priv=NULL \n", __FUNCTION__);
-		rc = 1;
-					goto done;
-	}
-
-	grp = priv->mpcg;
+	if (priv)
+		grp = priv->mpcg;
 	if (grp == NULL) {
-		printk(KERN_INFO "%s grp=NULL \n", __FUNCTION__);
-		rc = 1;
-					goto done;
+		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
+		return;
 	}
 
 	for (direction = READ; direction <= WRITE; direction++)	{
@@ -2199,11 +1970,6 @@
 			fsm_event(grp->fsm, MPCG_EVENT_DOIO, ch);
 	}
 
-done:
-
-	if (rc != 0)
-		fsm_event(grp->fsm, MPCG_EVENT_INOP, dev);
-
 	return;
 }
 
@@ -2214,24 +1980,15 @@
 static void mpc_action_rcvd_xid0(fsm_instance *fsm, int event, void *arg)
 {
 
-	struct mpcg_info   *mpcginfo   = arg;
-	struct channel	   *ch	       = mpcginfo->ch;
-	struct net_device  *dev        = ch->netdev;
-	struct ctcm_priv   *priv;
-	struct mpc_group   *grp;
+	struct mpcg_info   *mpcginfo  = arg;
+	struct channel	   *ch   = mpcginfo->ch;
+	struct net_device  *dev  = ch->netdev;
+	struct ctcm_priv   *priv = dev->priv;
+	struct mpc_group   *grp  = priv->mpcg;
 
-	if (do_debug)
-		ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
-			__FUNCTION__, smp_processor_id(), ch, ch->id);
-
-	priv = dev->priv;
-	grp = priv->mpcg;
-
-	ctcm_pr_debug("ctcmpc in:%s() %s xid2:%i xid7:%i xidt_p2:%i \n",
-		       __FUNCTION__, ch->id,
-		       grp->outstanding_xid2,
-		       grp->outstanding_xid7,
-		       grp->outstanding_xid7_p2);
+	CTCM_PR_DEBUG("%s: ch-id:%s xid2:%i xid7:%i xidt_p2:%i \n",
+			__func__, ch->id, grp->outstanding_xid2,
+			grp->outstanding_xid7, grp->outstanding_xid7_p2);
 
 	if (fsm_getstate(ch->fsm) < CH_XID7_PENDING)
 		fsm_newstate(ch->fsm, CH_XID7_PENDING);
@@ -2268,17 +2025,12 @@
 	}
 	kfree(mpcginfo);
 
-	if (do_debug) {
-		ctcm_pr_debug("ctcmpc:%s() %s xid2:%i xid7:%i xidt_p2:%i \n",
-				__FUNCTION__, ch->id,
-				grp->outstanding_xid2,
-				grp->outstanding_xid7,
-				grp->outstanding_xid7_p2);
-		ctcm_pr_debug("ctcmpc:%s() %s grpstate: %s chanstate: %s \n",
-				__FUNCTION__, ch->id,
-				fsm_getstate_str(grp->fsm),
-				fsm_getstate_str(ch->fsm));
-	}
+	CTCM_PR_DEBUG("ctcmpc:%s() %s xid2:%i xid7:%i xidt_p2:%i \n",
+		__func__, ch->id, grp->outstanding_xid2,
+		grp->outstanding_xid7, grp->outstanding_xid7_p2);
+	CTCM_PR_DEBUG("ctcmpc:%s() %s grpstate: %s chanstate: %s \n",
+		__func__, ch->id,
+		fsm_getstate_str(grp->fsm), fsm_getstate_str(ch->fsm));
 	return;
 
 }
@@ -2296,15 +2048,10 @@
 	struct ctcm_priv   *priv    = dev->priv;
 	struct mpc_group   *grp     = priv->mpcg;
 
-	if (do_debug) {
-		ctcm_pr_debug("ctcmpc enter: %s(): cp=%i ch=0x%p id=%s\n",
-				__FUNCTION__, smp_processor_id(), ch, ch->id);
-
-		ctcm_pr_debug("ctcmpc:  outstanding_xid7: %i, "
-				" outstanding_xid7_p2: %i\n",
-				grp->outstanding_xid7,
-				grp->outstanding_xid7_p2);
-	}
+	CTCM_PR_DEBUG("Enter %s: cp=%i ch=0x%p id=%s\n",
+		__func__, smp_processor_id(), ch, ch->id);
+	CTCM_PR_DEBUG("%s: outstanding_xid7: %i, outstanding_xid7_p2: %i\n",
+		__func__, grp->outstanding_xid7, grp->outstanding_xid7_p2);
 
 	grp->outstanding_xid7--;
 	ch->xid_skb->data = ch->xid_skb_data;
@@ -2337,14 +2084,8 @@
 		mpc_validate_xid(mpcginfo);
 		break;
 	}
-
 	kfree(mpcginfo);
-
-	if (do_debug)
-		ctcm_pr_debug("ctcmpc exit: %s(): cp=%i ch=0x%p id=%s\n",
-			__FUNCTION__, smp_processor_id(), ch, ch->id);
 	return;
-
 }
 
 /*
@@ -2353,36 +2094,14 @@
  */
 static int mpc_send_qllc_discontact(struct net_device *dev)
 {
-	int	rc	= 0;
 	__u32	new_len	= 0;
 	struct sk_buff   *skb;
 	struct qllc      *qllcptr;
-	struct ctcm_priv *priv;
-	struct mpc_group *grp;
+	struct ctcm_priv *priv = dev->priv;
+	struct mpc_group *grp = priv->mpcg;
 
-	ctcm_pr_debug("ctcmpc enter:	%s()\n", __FUNCTION__);
-
-	if (dev == NULL) {
-		printk(KERN_INFO "%s() dev=NULL\n", __FUNCTION__);
-		rc = 1;
-					goto done;
-	}
-
-	priv = dev->priv;
-	if (priv == NULL) {
-		printk(KERN_INFO "%s() priv=NULL\n", __FUNCTION__);
-		rc = 1;
-					goto done;
-	}
-
-	grp = priv->mpcg;
-	if (grp == NULL) {
-		printk(KERN_INFO "%s() grp=NULL\n", __FUNCTION__);
-		rc = 1;
-					goto done;
-	}
-	ctcm_pr_info("ctcmpc: %s() GROUP STATE: %s\n", __FUNCTION__,
-			mpcg_state_names[grp->saved_state]);
+	CTCM_PR_DEBUG("%s: GROUP STATE: %s\n",
+		__func__, mpcg_state_names[grp->saved_state]);
 
 	switch (grp->saved_state) {
 	/*
@@ -2408,11 +2127,10 @@
 		new_len = sizeof(struct qllc);
 		qllcptr = kzalloc(new_len, gfp_type() | GFP_DMA);
 		if (qllcptr == NULL) {
-			printk(KERN_INFO
-			       "ctcmpc: Out of memory in %s()\n",
-			       dev->name);
-			rc = 1;
-				goto done;
+			CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+				"%s(%s): qllcptr allocation error",
+						CTCM_FUNTAIL, dev->name);
+			return -ENOMEM;
 		}
 
 		qllcptr->qllc_address = 0xcc;
@@ -2421,31 +2139,29 @@
 		skb = __dev_alloc_skb(new_len, GFP_ATOMIC);
 
 		if (skb == NULL) {
-			printk(KERN_INFO "%s Out of memory in mpc_send_qllc\n",
-			       dev->name);
+			CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+				"%s(%s): skb allocation error",
+						CTCM_FUNTAIL, dev->name);
 			priv->stats.rx_dropped++;
-			rc = 1;
 			kfree(qllcptr);
-				goto done;
+			return -ENOMEM;
 		}
 
 		memcpy(skb_put(skb, new_len), qllcptr, new_len);
 		kfree(qllcptr);
 
 		if (skb_headroom(skb) < 4) {
-			printk(KERN_INFO "ctcmpc: %s() Unable to"
-			       " build discontact for %s\n",
-			       __FUNCTION__, dev->name);
-			rc = 1;
+			CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR,
+				"%s(%s): skb_headroom error",
+						CTCM_FUNTAIL, dev->name);
 			dev_kfree_skb_any(skb);
-				goto done;
+			return -ENOMEM;
 		}
 
 		*((__u32 *)skb_push(skb, 4)) = priv->channel[READ]->pdu_seq;
 		priv->channel[READ]->pdu_seq++;
-		if (do_debug_data)
-			ctcm_pr_debug("ctcmpc: %s ToDCM_pdu_seq= %08x\n",
-				__FUNCTION__, priv->channel[READ]->pdu_seq);
+		CTCM_PR_DBGDATA("ctcmpc: %s ToDCM_pdu_seq= %08x\n",
+				__func__, priv->channel[READ]->pdu_seq);
 
 		/* receipt of CC03 resets anticipated sequence number on
 		      receiving side */
@@ -2455,7 +2171,7 @@
 		skb->protocol = htons(ETH_P_SNAP);
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 
-		ctcmpc_dumpit((char *)skb->data, (sizeof(struct qllc) + 4));
+		CTCM_D3_DUMP(skb->data, (sizeof(struct qllc) + 4));
 
 		netif_rx(skb);
 		break;
@@ -2464,9 +2180,7 @@
 
 	}
 
-done:
-	ctcm_pr_debug("ctcmpc exit:  %s()\n", __FUNCTION__);
-	return rc;
+	return 0;
 }
 /* --- This is the END my friend --- */
 
diff --git a/drivers/s390/net/ctcm_mpc.h b/drivers/s390/net/ctcm_mpc.h
index f996860..5336120 100644
--- a/drivers/s390/net/ctcm_mpc.h
+++ b/drivers/s390/net/ctcm_mpc.h
@@ -231,7 +231,7 @@
 int ctcmpc_open(struct net_device *);
 void ctcm_ccw_check_rc(struct channel *, int, char *);
 void mpc_group_ready(unsigned long adev);
-int mpc_channel_action(struct channel *ch, int direction, int action);
+void mpc_channel_action(struct channel *ch, int direction, int action);
 void mpc_action_send_discontact(unsigned long thischan);
 void mpc_action_discontact(fsm_instance *fi, int event, void *arg);
 void ctcmpc_bh(unsigned long thischan);
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index b29afef..38de31b 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -2651,7 +2651,7 @@
 			tag = (u16 *)(new_skb->data + 12);
 			*tag = __constant_htons(ETH_P_8021Q);
 			*(tag + 1) = htons(vlan_tx_tag_get(new_skb));
-			VLAN_TX_SKB_CB(new_skb)->magic = 0;
+			new_skb->vlan_tci = 0;
 		}
 	}
 
diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c
index 513ba61..7776375 100644
--- a/drivers/sbus/char/uctrl.c
+++ b/drivers/sbus/char/uctrl.c
@@ -195,8 +195,8 @@
 
 static struct uctrl_driver drv;
 
-void uctrl_get_event_status(void);
-void uctrl_get_external_status(void);
+static void uctrl_get_event_status(void);
+static void uctrl_get_external_status(void);
 
 static int
 uctrl_ioctl(struct inode *inode, struct file *file,
@@ -266,12 +266,6 @@
   driver->regs->uctrl_stat = UCTRL_STAT_RXNE_STA; \
 }
 
-void uctrl_set_video(int status)
-{
-	struct uctrl_driver *driver = &drv;
-	
-}
-
 static void uctrl_do_txn(struct uctrl_txn *txn)
 {
 	struct uctrl_driver *driver = &drv;
@@ -311,7 +305,7 @@
 	}
 }
 
-void uctrl_get_event_status(void)
+static void uctrl_get_event_status(void)
 {
 	struct uctrl_driver *driver = &drv;
 	struct uctrl_txn txn;
@@ -331,7 +325,7 @@
 	dprintk(("ev is %x\n", driver->status.event_status));
 }
 
-void uctrl_get_external_status(void)
+static void uctrl_get_external_status(void)
 {
 	struct uctrl_driver *driver = &drv;
 	struct uctrl_txn txn;
@@ -363,7 +357,7 @@
 static int __init ts102_uctrl_init(void)
 {
 	struct uctrl_driver *driver = &drv;
-	int len, i;
+	int len;
 	struct linux_prom_irqs tmp_irq[2];
         unsigned int vaddr[2] = { 0, 0 };
 	int tmpnode, uctrlnode = prom_getchild(prom_root_node);
diff --git a/drivers/sbus/char/vfc.h b/drivers/sbus/char/vfc.h
index f1aa138..a5240c5 100644
--- a/drivers/sbus/char/vfc.h
+++ b/drivers/sbus/char/vfc.h
@@ -133,8 +133,6 @@
 	unsigned char saa9051_state_array[VFC_SAA9051_NR];
 };
 
-extern struct vfc_dev **vfc_dev_lst;
-
 void captstat_reset(struct vfc_dev *);
 void memptr_reset(struct vfc_dev *);
 
@@ -145,8 +143,6 @@
 int vfc_i2c_recvbuf(struct vfc_dev *, unsigned char, char *, int) ;
 int vfc_i2c_reset_bus(struct vfc_dev *);
 int vfc_init_i2c_bus(struct vfc_dev *);
-void vfc_lock_device(struct vfc_dev *);
-void vfc_unlock_device(struct vfc_dev *);
 
 #define VFC_CONTROL_DIAGMODE  0x10000000
 #define VFC_CONTROL_MEMPTR    0x20000000
diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c
index 1f6cb8a..25181bb 100644
--- a/drivers/sbus/char/vfc_dev.c
+++ b/drivers/sbus/char/vfc_dev.c
@@ -45,7 +45,7 @@
 #include <asm/vfc_ioctls.h>
 
 static const struct file_operations vfc_fops;
-struct vfc_dev **vfc_dev_lst;
+static struct vfc_dev **vfc_dev_lst;
 static char vfcstr[]="vfc";
 static unsigned char saa9051_init_array[VFC_SAA9051_NR] = {
 	0x00, 0x64, 0x72, 0x52,
@@ -54,18 +54,18 @@
 	0x3e
 };
 
-void vfc_lock_device(struct vfc_dev *dev)
+static void vfc_lock_device(struct vfc_dev *dev)
 {
 	mutex_lock(&dev->device_lock_mtx);
 }
 
-void vfc_unlock_device(struct vfc_dev *dev)
+static void vfc_unlock_device(struct vfc_dev *dev)
 {
 	mutex_unlock(&dev->device_lock_mtx);
 }
 
 
-void vfc_captstat_reset(struct vfc_dev *dev) 
+static void vfc_captstat_reset(struct vfc_dev *dev)
 {
 	dev->control_reg |= VFC_CONTROL_CAPTRESET;
 	sbus_writel(dev->control_reg, &dev->regs->control);
@@ -75,7 +75,7 @@
 	sbus_writel(dev->control_reg, &dev->regs->control);
 }
 
-void vfc_memptr_reset(struct vfc_dev *dev) 
+static void vfc_memptr_reset(struct vfc_dev *dev)
 {
 	dev->control_reg |= VFC_CONTROL_MEMPTR;
 	sbus_writel(dev->control_reg, &dev->regs->control);
@@ -85,7 +85,7 @@
 	sbus_writel(dev->control_reg, &dev->regs->control);
 }
 
-int vfc_csr_init(struct vfc_dev *dev)
+static int vfc_csr_init(struct vfc_dev *dev)
 {
 	dev->control_reg = 0x80000000;
 	sbus_writel(dev->control_reg, &dev->regs->control);
@@ -107,7 +107,7 @@
 	return 0;
 }
 
-int vfc_saa9051_init(struct vfc_dev *dev)
+static int vfc_saa9051_init(struct vfc_dev *dev)
 {
 	int i;
 
@@ -119,7 +119,7 @@
 	return 0;
 }
 
-int init_vfc_hw(struct vfc_dev *dev) 
+static int init_vfc_hw(struct vfc_dev *dev)
 {
 	vfc_lock_device(dev);
 	vfc_csr_init(dev);
@@ -132,7 +132,7 @@
 	return 0; 
 }
 
-int init_vfc_devstruct(struct vfc_dev *dev, int instance) 
+static int init_vfc_devstruct(struct vfc_dev *dev, int instance)
 {
 	dev->instance=instance;
 	mutex_init(&dev->device_lock_mtx);
@@ -141,7 +141,8 @@
 	return 0;
 }
 
-int init_vfc_device(struct sbus_dev *sdev,struct vfc_dev *dev, int instance)
+static int init_vfc_device(struct sbus_dev *sdev,struct vfc_dev *dev,
+			   int instance)
 {
 	if(dev == NULL) {
 		printk(KERN_ERR "VFC: Bogus pointer passed\n");
@@ -168,7 +169,7 @@
 }
 
 
-struct vfc_dev *vfc_get_dev_ptr(int instance) 
+static struct vfc_dev *vfc_get_dev_ptr(int instance)
 {
 	return vfc_dev_lst[instance];
 }
@@ -292,7 +293,7 @@
 	return 0;
 }
 
-int vfc_capture_start(struct vfc_dev *dev) 
+static int vfc_capture_start(struct vfc_dev *dev)
 {
 	vfc_captstat_reset(dev);
 	dev->control_reg = sbus_readl(&dev->regs->control);
@@ -314,7 +315,7 @@
 	return 0;
 }
 
-int vfc_capture_poll(struct vfc_dev *dev) 
+static int vfc_capture_poll(struct vfc_dev *dev)
 {
 	int timeout = 1000;
 
@@ -390,8 +391,8 @@
 }
 
 
-int vfc_port_change_ioctl(struct inode *inode, struct file *file, 
-			  struct vfc_dev *dev, unsigned long arg) 
+static int vfc_port_change_ioctl(struct inode *inode, struct file *file,
+				 struct vfc_dev *dev, unsigned long arg)
 {
 	int ret = 0;
 	int cmd;
@@ -460,8 +461,8 @@
 	return ret;
 }
 
-int vfc_set_video_ioctl(struct inode *inode, struct file *file, 
-			struct vfc_dev *dev, unsigned long arg) 
+static int vfc_set_video_ioctl(struct inode *inode, struct file *file,
+			       struct vfc_dev *dev, unsigned long arg)
 {
 	int ret = 0;
 	int cmd;
@@ -511,8 +512,8 @@
 	return ret;
 }
 
-int vfc_get_video_ioctl(struct inode *inode, struct file *file, 
-			struct vfc_dev *dev, unsigned long arg) 
+static int vfc_get_video_ioctl(struct inode *inode, struct file *file,
+			       struct vfc_dev *dev, unsigned long arg)
 {
 	int ret = 0;
 	unsigned int status = NO_LOCK;
diff --git a/drivers/sbus/char/vfc_i2c.c b/drivers/sbus/char/vfc_i2c.c
index 9efed77..32b986e 100644
--- a/drivers/sbus/char/vfc_i2c.c
+++ b/drivers/sbus/char/vfc_i2c.c
@@ -114,7 +114,7 @@
 	return 0;
 }
 
-int vfc_i2c_wait_for_bus(struct vfc_dev *dev) 
+static int vfc_i2c_wait_for_bus(struct vfc_dev *dev)
 {
 	int timeout = 1000; 
 
@@ -126,7 +126,7 @@
 	return 0;
 }
 
-int vfc_i2c_wait_for_pin(struct vfc_dev *dev, int ack)
+static int vfc_i2c_wait_for_pin(struct vfc_dev *dev, int ack)
 {
 	int timeout = 1000; 
 	int s1;
@@ -144,7 +144,8 @@
 }
 
 #define SHIFT(a) ((a) << 24)
-int vfc_i2c_xmit_addr(struct vfc_dev *dev, unsigned char addr, char mode) 
+static int vfc_i2c_xmit_addr(struct vfc_dev *dev, unsigned char addr,
+			     char mode)
 { 
 	int ret, raddr;
 #if 1
@@ -195,7 +196,7 @@
 	return 0;
 }
 
-int vfc_i2c_xmit_byte(struct vfc_dev *dev,unsigned char *byte) 
+static int vfc_i2c_xmit_byte(struct vfc_dev *dev,unsigned char *byte)
 {
 	int ret;
 	u32 val = SHIFT((unsigned int)*byte);
@@ -218,7 +219,8 @@
 	return ret;
 }
 
-int vfc_i2c_recv_byte(struct vfc_dev *dev, unsigned char *byte, int last) 
+static int vfc_i2c_recv_byte(struct vfc_dev *dev, unsigned char *byte,
+			     int last)
 {
 	int ret;
 
diff --git a/drivers/sbus/dvma.c b/drivers/sbus/dvma.c
index 57e1526..ab0d2de 100644
--- a/drivers/sbus/dvma.c
+++ b/drivers/sbus/dvma.c
@@ -16,7 +16,7 @@
 
 struct sbus_dma *dma_chain;
 
-void __init init_one_dvma(struct sbus_dma *dma, int num_dma)
+static void __init init_one_dvma(struct sbus_dma *dma, int num_dma)
 {
 	printk("dma%d: ", num_dma);
 	
diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c
index c37d7c2..73a86d0 100644
--- a/drivers/sbus/sbus.c
+++ b/drivers/sbus/sbus.c
@@ -78,7 +78,7 @@
 	else
 		sdev->ofdev.dev.parent = &sdev->bus->ofdev.dev;
 	sdev->ofdev.dev.bus = &sbus_bus_type;
-	sprintf(sdev->ofdev.dev.bus_id, "sbus[%08x]", dp->node);
+	dev_set_name(&sdev->ofdev.dev, "sbus[%08x]", dp->node);
 
 	if (of_device_register(&sdev->ofdev) != 0)
 		printk(KERN_DEBUG "sbus: device registration error for %s!\n",
@@ -257,11 +257,11 @@
 	sbus->ofdev.node = dp;
 	sbus->ofdev.dev.parent = NULL;
 	sbus->ofdev.dev.bus = &sbus_bus_type;
-	sprintf(sbus->ofdev.dev.bus_id, "sbus%d", num_sbus);
+	dev_set_name(&sbus->ofdev.dev, "sbus%d", num_sbus);
 
 	if (of_device_register(&sbus->ofdev) != 0)
 		printk(KERN_DEBUG "sbus: device registration error for %s!\n",
-		       sbus->ofdev.dev.bus_id);
+		       dev_name(&sbus->ofdev.dev));
 
 	dev_dp = dp->child;
 	while (dev_dp) {
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 2bc30e3..1fe0901 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -271,8 +271,8 @@
 		pHba->initialized = TRUE;
 		pHba->state &= ~DPTI_STATE_RESET;
 		if (adpt_sysfs_class) {
-			struct device *dev = device_create(adpt_sysfs_class,
-				NULL, MKDEV(DPTI_I2O_MAJOR, pHba->unit),
+			struct device *dev = device_create_drvdata(adpt_sysfs_class,
+				NULL, MKDEV(DPTI_I2O_MAJOR, pHba->unit), NULL,
 				"dpti%d", pHba->unit);
 			if (IS_ERR(dev)) {
 				printk(KERN_WARNING"dpti%d: unable to "
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 35cd892..fed0b02 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -232,8 +232,8 @@
 	}
 
 	if (shost->transportt->create_work_queue) {
-		snprintf(shost->work_q_name, KOBJ_NAME_LEN, "scsi_wq_%d",
-			shost->host_no);
+		snprintf(shost->work_q_name, sizeof(shost->work_q_name),
+			 "scsi_wq_%d", shost->host_no);
 		shost->work_q = create_singlethread_workqueue(
 					shost->work_q_name);
 		if (!shost->work_q) {
@@ -466,7 +466,8 @@
 	struct device *cdev;
 	struct Scsi_Host *shost = ERR_PTR(-ENXIO);
 
-	cdev = class_find_device(&shost_class, &hostnum, __scsi_host_match);
+	cdev = class_find_device(&shost_class, NULL, &hostnum,
+				 __scsi_host_match);
 	if (cdev) {
 		shost = scsi_host_get(class_to_shost(cdev));
 		put_device(cdev);
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index f843c13..5385524 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -84,7 +84,6 @@
 	struct Scsi_Host	*host;
 
 	struct ide_atapi_pc *pc;		/* Current packet command */
-	unsigned long flags;			/* Status/Action flags */
 	unsigned long transform;		/* SCSI cmd translation layer */
 	unsigned long log;			/* log flags */
 } idescsi_scsi_t;
@@ -126,23 +125,14 @@
 }
 
 /*
- *	Per ATAPI device status bits.
- */
-#define IDESCSI_DRQ_INTERRUPT		0	/* DRQ interrupt device */
-
-/*
- *	ide-scsi requests.
- */
-#define IDESCSI_PC_RQ			90
-
-/*
  *	PIO data transfer routine using the scatter gather table.
  */
 static void ide_scsi_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
 				unsigned int bcount, int write)
 {
 	ide_hwif_t *hwif = drive->hwif;
-	xfer_func_t *xf = write ? hwif->output_data : hwif->input_data;
+	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
+	xfer_func_t *xf = write ? tp_ops->output_data : tp_ops->input_data;
 	char *buf;
 	int count;
 
@@ -228,7 +218,6 @@
 	rq->cmd_type = REQ_TYPE_SENSE;
 	rq->cmd_flags |= REQ_PREEMPT;
 	pc->timeout = jiffies + WAIT_READY;
-	pc->callback = ide_scsi_callback;
 	/* NOTE! Save the failed packet command in "rq->buffer" */
 	rq->buffer = (void *) failed_cmd->special;
 	pc->scsi_cmd = ((struct ide_atapi_pc *) failed_cmd->special)->scsi_cmd;
@@ -237,6 +226,7 @@
 		ide_scsi_hex_dump(pc->c, 6);
 	}
 	rq->rq_disk = scsi->disk;
+	memcpy(rq->cmd, pc->c, 12);
 	ide_do_drive_cmd(drive, rq);
 	return 0;
 }
@@ -246,10 +236,9 @@
 {
 	ide_hwif_t *hwif = drive->hwif;
 
-	if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
+	if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT))
 		/* force an abort */
-		hwif->OUTBSYNC(hwif, WIN_IDLEIMMEDIATE,
-			       hwif->io_ports.command_addr);
+		hwif->tp_ops->exec_command(hwif, WIN_IDLEIMMEDIATE);
 
 	rq->errors++;
 
@@ -421,10 +410,6 @@
 
 	if (blk_sense_request(rq) || blk_special_request(rq)) {
 		struct ide_atapi_pc *pc = (struct ide_atapi_pc *)rq->special;
-		idescsi_scsi_t *scsi = drive_to_idescsi(drive);
-
-		if (test_bit(IDESCSI_DRQ_INTERRUPT, &scsi->flags))
-			pc->flags |= PC_FLAG_DRQ_INTERRUPT;
 
 		if (drive->using_dma && !idescsi_map_sg(drive, pc))
 			pc->flags |= PC_FLAG_DMA_OK;
@@ -460,11 +445,14 @@
 static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi)
 {
 	if (drive->id && (drive->id->config & 0x0060) == 0x20)
-		set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags);
+		set_bit(IDE_AFLAG_DRQ_INTERRUPT, &drive->atapi_flags);
 	clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
 #if IDESCSI_DEBUG_LOG
 	set_bit(IDESCSI_LOG_CMD, &scsi->log);
 #endif /* IDESCSI_DEBUG_LOG */
+
+	drive->pc_callback = ide_scsi_callback;
+
 	idescsi_add_settings(drive);
 }
 
@@ -616,7 +604,6 @@
 	pc->scsi_cmd = cmd;
 	pc->done = done;
 	pc->timeout = jiffies + cmd->timeout_per_command;
-	pc->callback = ide_scsi_callback;
 
 	if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
 		printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number);
@@ -631,6 +618,7 @@
 	rq->special = (char *) pc;
 	rq->cmd_type = REQ_TYPE_SPECIAL;
 	spin_unlock_irq(host->host_lock);
+	memcpy(rq->cmd, pc->c, 12);
 	blk_execute_rq_nowait(drive->queue, scsi->disk, rq, 0, NULL);
 	spin_lock_irq(host->host_lock);
 	return 0;
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 5fd64e7..a272b9a 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -417,15 +417,16 @@
 	fc_host->next_vport_number = 0;
 	fc_host->npiv_vports_inuse = 0;
 
-	snprintf(fc_host->work_q_name, KOBJ_NAME_LEN, "fc_wq_%d",
-		shost->host_no);
+	snprintf(fc_host->work_q_name, sizeof(fc_host->work_q_name),
+		 "fc_wq_%d", shost->host_no);
 	fc_host->work_q = create_singlethread_workqueue(
 					fc_host->work_q_name);
 	if (!fc_host->work_q)
 		return -ENOMEM;
 
-	snprintf(fc_host->devloss_work_q_name, KOBJ_NAME_LEN, "fc_dl_%d",
-		shost->host_no);
+	snprintf(fc_host->devloss_work_q_name,
+		 sizeof(fc_host->devloss_work_q_name),
+		 "fc_dl_%d", shost->host_no);
 	fc_host->devloss_work_q = create_singlethread_workqueue(
 					fc_host->devloss_work_q_name);
 	if (!fc_host->devloss_work_q) {
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 3af7cbc..043c392 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -170,7 +170,7 @@
 	int err;
 
 	for (id = 1; id < ISCSI_MAX_EPID; id++) {
-		dev = class_find_device(&iscsi_endpoint_class, &id,
+		dev = class_find_device(&iscsi_endpoint_class, NULL, &id,
 					iscsi_match_epid);
 		if (!dev)
 			break;
@@ -222,7 +222,7 @@
 	struct iscsi_endpoint *ep;
 	struct device *dev;
 
-	dev = class_find_device(&iscsi_endpoint_class, &handle,
+	dev = class_find_device(&iscsi_endpoint_class, NULL, &handle,
 				iscsi_match_epid);
 	if (!dev)
 		return NULL;
@@ -247,8 +247,8 @@
 	atomic_set(&ihost->nr_scans, 0);
 	mutex_init(&ihost->mutex);
 
-	snprintf(ihost->scan_workq_name, KOBJ_NAME_LEN, "iscsi_scan_%d",
-		shost->host_no);
+	snprintf(ihost->scan_workq_name, sizeof(ihost->scan_workq_name),
+		 "iscsi_scan_%d", shost->host_no);
 	ihost->scan_workq = create_singlethread_workqueue(
 						ihost->scan_workq_name);
 	if (!ihost->scan_workq)
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index ce948b6..27f34a9 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -1874,7 +1874,9 @@
 		 * the interrupt is enabled.  Delays are necessary to
 		 * allow register changes to become visible.
 		 */
-		spin_lock_irqsave(&up->port.lock, flags);
+		spin_lock(&up->port.lock);
+		if (up->port.flags & UPF_SHARE_IRQ)
+			disable_irq_nosync(up->port.irq);
 
 		wait_for_xmitr(up, UART_LSR_THRE);
 		serial_out_sync(up, UART_IER, UART_IER_THRI);
@@ -1886,7 +1888,9 @@
 		iir = serial_in(up, UART_IIR);
 		serial_out(up, UART_IER, 0);
 
-		spin_unlock_irqrestore(&up->port.lock, flags);
+		if (up->port.flags & UPF_SHARE_IRQ)
+			enable_irq(up->port.irq);
+		spin_unlock(&up->port.lock);
 
 		/*
 		 * If the interrupt is not reasserted, setup a timer to
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index abe129c..1ff80de1 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -201,6 +201,10 @@
 	cpm_uart_tx_pump(port);
 }
 
+#ifdef CONFIG_CONSOLE_POLL
+static int serial_polled;
+#endif
+
 /*
  * Receive characters
  */
@@ -209,7 +213,7 @@
 	int i;
 	unsigned char ch;
 	u8 *cp;
-	struct tty_struct *tty = port->info->tty;
+	struct tty_struct *tty = port->info->port.tty;
 	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
 	cbd_t __iomem *bdp;
 	u16 status;
@@ -222,6 +226,12 @@
 	 */
 	bdp = pinfo->rx_cur;
 	for (;;) {
+#ifdef CONFIG_CONSOLE_POLL
+		if (unlikely(serial_polled)) {
+			serial_polled = 0;
+			return;
+		}
+#endif
 		/* get status */
 		status = in_be16(&bdp->cbd_sc);
 		/* If this one is empty, return happy */
@@ -253,7 +263,12 @@
 				goto handle_error;
 			if (uart_handle_sysrq_char(port, ch))
 				continue;
-
+#ifdef CONFIG_CONSOLE_POLL
+			if (unlikely(serial_polled)) {
+				serial_polled = 0;
+				return;
+			}
+#endif
 		      error_return:
 			tty_insert_flip_char(tty, ch, flg);
 
@@ -865,6 +880,80 @@
 		cpm_uart_request_port(port);
 	}
 }
+
+#ifdef CONFIG_CONSOLE_POLL
+/* Serial polling routines for writing and reading from the uart while
+ * in an interrupt or debug context.
+ */
+
+#define GDB_BUF_SIZE	512	/* power of 2, please */
+
+static char poll_buf[GDB_BUF_SIZE];
+static char *pollp;
+static int poll_chars;
+
+static int poll_wait_key(char *obuf, struct uart_cpm_port *pinfo)
+{
+	u_char		c, *cp;
+	volatile cbd_t	*bdp;
+	int		i;
+
+	/* Get the address of the host memory buffer.
+	 */
+	bdp = pinfo->rx_cur;
+	while (bdp->cbd_sc & BD_SC_EMPTY)
+		;
+
+	/* If the buffer address is in the CPM DPRAM, don't
+	 * convert it.
+	 */
+	cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
+
+	if (obuf) {
+		i = c = bdp->cbd_datlen;
+		while (i-- > 0)
+			*obuf++ = *cp++;
+	} else
+		c = *cp;
+	bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV | BD_SC_ID);
+	bdp->cbd_sc |= BD_SC_EMPTY;
+
+	if (bdp->cbd_sc & BD_SC_WRAP)
+		bdp = pinfo->rx_bd_base;
+	else
+		bdp++;
+	pinfo->rx_cur = (cbd_t *)bdp;
+
+	return (int)c;
+}
+
+static int cpm_get_poll_char(struct uart_port *port)
+{
+	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+
+	if (!serial_polled) {
+		serial_polled = 1;
+		poll_chars = 0;
+	}
+	if (poll_chars <= 0) {
+		poll_chars = poll_wait_key(poll_buf, pinfo);
+		pollp = poll_buf;
+	}
+	poll_chars--;
+	return *pollp++;
+}
+
+static void cpm_put_poll_char(struct uart_port *port,
+			 unsigned char c)
+{
+	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+	static char ch[2];
+
+	ch[0] = (char)c;
+	cpm_uart_early_write(pinfo->port.line, ch, 1);
+}
+#endif /* CONFIG_CONSOLE_POLL */
+
 static struct uart_ops cpm_uart_pops = {
 	.tx_empty	= cpm_uart_tx_empty,
 	.set_mctrl	= cpm_uart_set_mctrl,
@@ -882,6 +971,10 @@
 	.request_port	= cpm_uart_request_port,
 	.config_port	= cpm_uart_config_port,
 	.verify_port	= cpm_uart_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+	.poll_get_char = cpm_get_poll_char,
+	.poll_put_char = cpm_put_poll_char,
+#endif
 };
 
 struct uart_cpm_port cpm_uart_ports[UART_NR];
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c
index 9c2df5c..2b7531d 100644
--- a/drivers/serial/icom.c
+++ b/drivers/serial/icom.c
@@ -730,7 +730,7 @@
 static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port)
 {
 	short int count, rcv_buff;
-	struct tty_struct *tty = icom_port->uart_port.info->tty;
+	struct tty_struct *tty = icom_port->uart_port.info->port.tty;
 	unsigned short int status;
 	struct uart_icount *icount;
 	unsigned long offset;
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c
index c9f53e7..61d3ade 100644
--- a/drivers/serial/mpsc.c
+++ b/drivers/serial/mpsc.c
@@ -921,6 +921,10 @@
 	return 0;
 }
 
+#ifdef CONFIG_CONSOLE_POLL
+static int serial_polled;
+#endif
+
 /*
  ******************************************************************************
  *
@@ -956,7 +960,12 @@
 	while (!((cmdstat = be32_to_cpu(rxre->cmdstat))
 				& SDMA_DESC_CMDSTAT_O)) {
 		bytes_in = be16_to_cpu(rxre->bytecnt);
-
+#ifdef CONFIG_CONSOLE_POLL
+		if (unlikely(serial_polled)) {
+			serial_polled = 0;
+			return 0;
+		}
+#endif
 		/* Following use of tty struct directly is deprecated */
 		if (unlikely(tty_buffer_request_room(tty, bytes_in)
 					< bytes_in)) {
@@ -1017,6 +1026,12 @@
 		if (uart_handle_sysrq_char(&pi->port, *bp)) {
 			bp++;
 			bytes_in--;
+#ifdef CONFIG_CONSOLE_POLL
+			if (unlikely(serial_polled)) {
+				serial_polled = 0;
+				return 0;
+			}
+#endif
 			goto next_frame;
 		}
 
@@ -1519,6 +1534,133 @@
 
 	return rc;
 }
+#ifdef CONFIG_CONSOLE_POLL
+/* Serial polling routines for writing and reading from the uart while
+ * in an interrupt or debug context.
+ */
+
+static char poll_buf[2048];
+static int poll_ptr;
+static int poll_cnt;
+static void mpsc_put_poll_char(struct uart_port *port,
+							   unsigned char c);
+
+static int mpsc_get_poll_char(struct uart_port *port)
+{
+	struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
+	struct mpsc_rx_desc *rxre;
+	u32	cmdstat, bytes_in, i;
+	u8	*bp;
+
+	if (!serial_polled)
+		serial_polled = 1;
+
+	pr_debug("mpsc_rx_intr[%d]: Handling Rx intr\n", pi->port.line);
+
+	if (poll_cnt) {
+		poll_cnt--;
+		return poll_buf[poll_ptr++];
+	}
+	poll_ptr = 0;
+	poll_cnt = 0;
+
+	while (poll_cnt == 0) {
+		rxre = (struct mpsc_rx_desc *)(pi->rxr +
+		       (pi->rxr_posn*MPSC_RXRE_SIZE));
+		dma_cache_sync(pi->port.dev, (void *)rxre,
+			       MPSC_RXRE_SIZE, DMA_FROM_DEVICE);
+#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
+		if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
+			invalidate_dcache_range((ulong)rxre,
+			(ulong)rxre + MPSC_RXRE_SIZE);
+#endif
+		/*
+		 * Loop through Rx descriptors handling ones that have
+		 * been completed.
+		 */
+		while (poll_cnt == 0 &&
+		       !((cmdstat = be32_to_cpu(rxre->cmdstat)) &
+			 SDMA_DESC_CMDSTAT_O)){
+			bytes_in = be16_to_cpu(rxre->bytecnt);
+			bp = pi->rxb + (pi->rxr_posn * MPSC_RXBE_SIZE);
+			dma_cache_sync(pi->port.dev, (void *) bp,
+				       MPSC_RXBE_SIZE, DMA_FROM_DEVICE);
+#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
+			if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
+				invalidate_dcache_range((ulong)bp,
+					(ulong)bp + MPSC_RXBE_SIZE);
+#endif
+			if ((unlikely(cmdstat & (SDMA_DESC_CMDSTAT_BR |
+			 SDMA_DESC_CMDSTAT_FR | SDMA_DESC_CMDSTAT_OR))) &&
+				!(cmdstat & pi->port.ignore_status_mask)) {
+				poll_buf[poll_cnt] = *bp;
+				poll_cnt++;
+			} else {
+				for (i = 0; i < bytes_in; i++) {
+					poll_buf[poll_cnt] = *bp++;
+					poll_cnt++;
+				}
+				pi->port.icount.rx += bytes_in;
+			}
+			rxre->bytecnt = cpu_to_be16(0);
+			wmb();
+			rxre->cmdstat = cpu_to_be32(SDMA_DESC_CMDSTAT_O |
+						    SDMA_DESC_CMDSTAT_EI |
+						    SDMA_DESC_CMDSTAT_F |
+						    SDMA_DESC_CMDSTAT_L);
+			wmb();
+			dma_cache_sync(pi->port.dev, (void *)rxre,
+				       MPSC_RXRE_SIZE, DMA_BIDIRECTIONAL);
+#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
+			if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
+				flush_dcache_range((ulong)rxre,
+					   (ulong)rxre + MPSC_RXRE_SIZE);
+#endif
+
+			/* Advance to next descriptor */
+			pi->rxr_posn = (pi->rxr_posn + 1) &
+				(MPSC_RXR_ENTRIES - 1);
+			rxre = (struct mpsc_rx_desc *)(pi->rxr +
+				       (pi->rxr_posn * MPSC_RXRE_SIZE));
+			dma_cache_sync(pi->port.dev, (void *)rxre,
+				       MPSC_RXRE_SIZE, DMA_FROM_DEVICE);
+#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
+			if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */
+				invalidate_dcache_range((ulong)rxre,
+						(ulong)rxre + MPSC_RXRE_SIZE);
+#endif
+		}
+
+		/* Restart rx engine, if its stopped */
+		if ((readl(pi->sdma_base + SDMA_SDCM) & SDMA_SDCM_ERD) == 0)
+			mpsc_start_rx(pi);
+	}
+	if (poll_cnt) {
+		poll_cnt--;
+		return poll_buf[poll_ptr++];
+	}
+
+	return 0;
+}
+
+
+static void mpsc_put_poll_char(struct uart_port *port,
+			 unsigned char c)
+{
+	struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
+	u32 data;
+
+	data = readl(pi->mpsc_base + MPSC_MPCR);
+	writeb(c, pi->mpsc_base + MPSC_CHR_1);
+	mb();
+	data = readl(pi->mpsc_base + MPSC_CHR_2);
+	data |= MPSC_CHR_2_TTCS;
+	writel(data, pi->mpsc_base + MPSC_CHR_2);
+	mb();
+
+	while (readl(pi->mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_TTCS);
+}
+#endif
 
 static struct uart_ops mpsc_pops = {
 	.tx_empty	= mpsc_tx_empty,
@@ -1537,6 +1679,10 @@
 	.request_port	= mpsc_request_port,
 	.config_port	= mpsc_config_port,
 	.verify_port	= mpsc_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+	.poll_get_char = mpsc_get_poll_char,
+	.poll_put_char = mpsc_put_poll_char,
+#endif
 };
 
 /*
diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c
index 4a3ecaa..d852f83 100644
--- a/drivers/serial/samsung.c
+++ b/drivers/serial/samsung.c
@@ -202,7 +202,7 @@
 {
 	struct s3c24xx_uart_port *ourport = dev_id;
 	struct uart_port *port = &ourport->port;
-	struct tty_struct *tty = port->info->tty;
+	struct tty_struct *tty = port->info->port.tty;
 	unsigned int ufcon, ch, flag, ufstat, uerstat;
 	int max_count = 64;
 
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 0bce1fe..f977c98 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -934,7 +934,7 @@
 	return ret;
 }
 
-static void uart_break_ctl(struct tty_struct *tty, int break_state)
+static int uart_break_ctl(struct tty_struct *tty, int break_state)
 {
 	struct uart_state *state = tty->driver_data;
 	struct uart_port *port = state->port;
@@ -945,6 +945,7 @@
 		port->ops->break_ctl(port, break_state);
 
 	mutex_unlock(&state->mutex);
+	return 0;
 }
 
 static int uart_do_autoconfig(struct uart_state *state)
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c
index 7ad2192..8fcb4c5 100644
--- a/drivers/serial/serial_txx9.c
+++ b/drivers/serial/serial_txx9.c
@@ -272,7 +272,7 @@
 static inline void
 receive_chars(struct uart_txx9_port *up, unsigned int *status)
 {
-	struct tty_struct *tty = up->port.info->tty;
+	struct tty_struct *tty = up->port.info->port.tty;
 	unsigned char ch;
 	unsigned int disr = *status;
 	int max_count = 256;
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 1ad12af..1771b24 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -502,7 +502,7 @@
 	struct device		*dev;
 	struct spi_master	*master = NULL;
 
-	dev = class_find_device(&spi_master_class, &bus_num,
+	dev = class_find_device(&spi_master_class, NULL, &bus_num,
 				__spi_master_match);
 	if (dev)
 		master = container_of(dev, struct spi_master, dev);
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index ddbe1a5..2833fd7 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -576,7 +576,8 @@
 		struct device *dev;
 
 		spidev->devt = MKDEV(SPIDEV_MAJOR, minor);
-		dev = device_create(spidev_class, &spi->dev, spidev->devt,
+		dev = device_create_drvdata(spidev_class, &spi->dev,
+				spidev->devt, spidev,
 				"spidev%d.%d",
 				spi->master->bus_num, spi->chip_select);
 		status = IS_ERR(dev) ? PTR_ERR(dev) : 0;
@@ -586,7 +587,6 @@
 	}
 	if (status == 0) {
 		set_bit(minor, minors);
-		spi_set_drvdata(spi, spidev);
 		list_add(&spidev->device_entry, &device_list);
 	}
 	mutex_unlock(&device_list_lock);
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index a4aaab9..2e9079d 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -15,7 +15,7 @@
 
 config UIO_CIF
 	tristate "generic Hilscher CIF Card driver"
-	depends on UIO && PCI
+	depends on PCI
 	default n
 	help
 	  Driver for Hilscher CIF DeviceNet and Profibus cards.  This
@@ -26,9 +26,15 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called uio_cif.
 
+config UIO_PDRV
+	tristate "Userspace I/O platform driver"
+	help
+	  Generic platform driver for Userspace I/O devices.
+
+	  If you don't know what to do here, say N.
+
 config UIO_SMX
 	tristate "SMX cryptengine UIO interface"
-	depends on UIO
 	default n
 	help
 	  Userspace IO interface to the Cryptography engine found on the
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
index 18c4566..e00ce0d 100644
--- a/drivers/uio/Makefile
+++ b/drivers/uio/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_UIO)	+= uio.o
 obj-$(CONFIG_UIO_CIF)	+= uio_cif.o
+obj-$(CONFIG_UIO_PDRV)	+= uio_pdrv.o
 obj-$(CONFIG_UIO_SMX)	+= uio_smx.o
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index 5a7ca2e..3a6934b 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -427,6 +427,31 @@
 	return retval;
 }
 
+static ssize_t uio_write(struct file *filep, const char __user *buf,
+			size_t count, loff_t *ppos)
+{
+	struct uio_listener *listener = filep->private_data;
+	struct uio_device *idev = listener->dev;
+	ssize_t retval;
+	s32 irq_on;
+
+	if (idev->info->irq == UIO_IRQ_NONE)
+		return -EIO;
+
+	if (count != sizeof(s32))
+		return -EINVAL;
+
+	if (!idev->info->irqcontrol)
+		return -ENOSYS;
+
+	if (copy_from_user(&irq_on, buf, count))
+		return -EFAULT;
+
+	retval = idev->info->irqcontrol(idev->info, irq_on);
+
+	return retval ? retval : sizeof(s32);
+}
+
 static int uio_find_mem_index(struct vm_area_struct *vma)
 {
 	int mi;
@@ -546,6 +571,7 @@
 	.open		= uio_open,
 	.release	= uio_release,
 	.read		= uio_read,
+	.write		= uio_write,
 	.mmap		= uio_mmap,
 	.poll		= uio_poll,
 	.fasync		= uio_fasync,
diff --git a/drivers/uio/uio_pdrv.c b/drivers/uio/uio_pdrv.c
new file mode 100644
index 0000000..5d0d2e8
--- /dev/null
+++ b/drivers/uio/uio_pdrv.c
@@ -0,0 +1,118 @@
+/*
+ * drivers/uio/uio_pdrv.c
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * 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/platform_device.h>
+#include <linux/uio_driver.h>
+#include <linux/stringify.h>
+
+#define DRIVER_NAME "uio"
+
+struct uio_platdata {
+	struct uio_info *uioinfo;
+};
+
+static int uio_pdrv_probe(struct platform_device *pdev)
+{
+	struct uio_info *uioinfo = pdev->dev.platform_data;
+	struct uio_platdata *pdata;
+	struct uio_mem *uiomem;
+	int ret = -ENODEV;
+	int i;
+
+	if (!uioinfo || !uioinfo->name || !uioinfo->version) {
+		dev_dbg(&pdev->dev, "%s: err_uioinfo\n", __func__);
+		goto err_uioinfo;
+	}
+
+	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		ret = -ENOMEM;
+		dev_dbg(&pdev->dev, "%s: err_alloc_pdata\n", __func__);
+		goto err_alloc_pdata;
+	}
+
+	pdata->uioinfo = uioinfo;
+
+	uiomem = &uioinfo->mem[0];
+
+	for (i = 0; i < pdev->num_resources; ++i) {
+		struct resource *r = &pdev->resource[i];
+
+		if (r->flags != IORESOURCE_MEM)
+			continue;
+
+		if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) {
+			dev_warn(&pdev->dev, "device has more than "
+					__stringify(MAX_UIO_MAPS)
+					" I/O memory resources.\n");
+			break;
+		}
+
+		uiomem->memtype = UIO_MEM_PHYS;
+		uiomem->addr = r->start;
+		uiomem->size = r->end - r->start + 1;
+		++uiomem;
+	}
+
+	while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) {
+		uiomem->size = 0;
+		++uiomem;
+	}
+
+	pdata->uioinfo->priv = pdata;
+
+	ret = uio_register_device(&pdev->dev, pdata->uioinfo);
+
+	if (ret) {
+		kfree(pdata);
+err_alloc_pdata:
+err_uioinfo:
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, pdata);
+
+	return 0;
+}
+
+static int uio_pdrv_remove(struct platform_device *pdev)
+{
+	struct uio_platdata *pdata = platform_get_drvdata(pdev);
+
+	uio_unregister_device(pdata->uioinfo);
+
+	return 0;
+}
+
+static struct platform_driver uio_pdrv = {
+	.probe = uio_pdrv_probe,
+	.remove = uio_pdrv_remove,
+	.driver = {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init uio_pdrv_init(void)
+{
+	return platform_driver_register(&uio_pdrv);
+}
+
+static void __exit uio_pdrv_exit(void)
+{
+	platform_driver_unregister(&uio_pdrv);
+}
+module_init(uio_pdrv_init);
+module_exit(uio_pdrv_exit);
+
+MODULE_AUTHOR("Uwe Kleine-Koenig");
+MODULE_DESCRIPTION("Userspace I/O platform driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index 90583d6..507a9bd 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -1052,7 +1052,6 @@
 
 	instance->usbatm = usbatm_instance;
 	instance->modem_type = (struct cxacru_modem_type *) id->driver_info;
-	memset(instance->card_info, 0, sizeof(instance->card_info));
 
 	mutex_init(&instance->poll_state_serialize);
 	instance->poll_state = CXPOLL_STOPPED;
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index 7d27c9c..76fce44 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -829,7 +829,6 @@
 	if (use_isoc) {
 		const struct usb_host_interface *desc = data_intf->cur_altsetting;
 		const __u8 target_address = USB_DIR_IN | usbatm->driver->isoc_in;
-		int i;
 
 		use_isoc = 0; /* fall back to bulk if endpoint not found */
 
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index c3201aff..0725b18 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -159,12 +159,34 @@
 	spin_lock_irqsave(&acm->write_lock, flags);
 	acm->write_ready = 1;
 	wb->use = 0;
+	acm->transmitting--;
 	spin_unlock_irqrestore(&acm->write_lock, flags);
 }
 
 /*
  * Poke write.
+ *
+ * the caller is responsible for locking
  */
+
+static int acm_start_wb(struct acm *acm, struct acm_wb *wb)
+{
+	int rc;
+
+	acm->transmitting++;
+
+	wb->urb->transfer_buffer = wb->buf;
+	wb->urb->transfer_dma = wb->dmah;
+	wb->urb->transfer_buffer_length = wb->len;
+	wb->urb->dev = acm->dev;
+
+	if ((rc = usb_submit_urb(wb->urb, GFP_ATOMIC)) < 0) {
+		dbg("usb_submit_urb(write bulk) failed: %d", rc);
+		acm_write_done(acm, wb);
+	}
+	return rc;
+}
+
 static int acm_write_start(struct acm *acm, int wbn)
 {
 	unsigned long flags;
@@ -182,26 +204,31 @@
 		return 0;	/* A white lie */
 	}
 
+	wb = &acm->wb[wbn];
+	if(acm_wb_is_avail(acm) <= 1)
+		acm->write_ready = 0;
+
+	dbg("%s susp_count: %d", __func__, acm->susp_count);
+	if (acm->susp_count) {
+		acm->old_ready = acm->write_ready;
+		acm->delayed_wb = wb;
+		acm->write_ready = 0;
+		schedule_work(&acm->waker);
+		spin_unlock_irqrestore(&acm->write_lock, flags);
+		return 0;	/* A white lie */
+	}
+	usb_mark_last_busy(acm->dev);
+
 	if (!acm_wb_is_used(acm, wbn)) {
 		spin_unlock_irqrestore(&acm->write_lock, flags);
 		return 0;
 	}
-	wb = &acm->wb[wbn];
 
-	if(acm_wb_is_avail(acm) <= 1)
-		acm->write_ready = 0;
+	rc = acm_start_wb(acm, wb);
 	spin_unlock_irqrestore(&acm->write_lock, flags);
 
-	wb->urb->transfer_buffer = wb->buf;
-	wb->urb->transfer_dma = wb->dmah;
-	wb->urb->transfer_buffer_length = wb->len;
-	wb->urb->dev = acm->dev;
-
-	if ((rc = usb_submit_urb(wb->urb, GFP_ATOMIC)) < 0) {
-		dbg("usb_submit_urb(write bulk) failed: %d", rc);
-		acm_write_done(acm, wb);
-	}
 	return rc;
+
 }
 /*
  * attributes exported through sysfs
@@ -304,6 +331,7 @@
 			break;
 	}
 exit:
+	usb_mark_last_busy(acm->dev);
 	retval = usb_submit_urb (urb, GFP_ATOMIC);
 	if (retval)
 		err ("%s - usb_submit_urb failed with result %d",
@@ -320,8 +348,11 @@
 
 	dbg("Entering acm_read_bulk with status %d", status);
 
-	if (!ACM_READY(acm))
+	if (!ACM_READY(acm)) {
+		dev_dbg(&acm->data->dev, "Aborting, acm not ready");
 		return;
+	}
+	usb_mark_last_busy(acm->dev);
 
 	if (status)
 		dev_dbg(&acm->data->dev, "bulk rx status %d\n", status);
@@ -331,6 +362,7 @@
 
 	if (likely(status == 0)) {
 		spin_lock(&acm->read_lock);
+		acm->processing++;
 		list_add_tail(&rcv->list, &acm->spare_read_urbs);
 		list_add_tail(&buf->list, &acm->filled_read_bufs);
 		spin_unlock(&acm->read_lock);
@@ -343,7 +375,8 @@
 		/* nevertheless the tasklet must be kicked unconditionally
 		so the queue cannot dry up */
 	}
-	tasklet_schedule(&acm->urb_task);
+	if (likely(!acm->susp_count))
+		tasklet_schedule(&acm->urb_task);
 }
 
 static void acm_rx_tasklet(unsigned long _acm)
@@ -354,16 +387,23 @@
 	struct acm_ru *rcv;
 	unsigned long flags;
 	unsigned char throttled;
+
 	dbg("Entering acm_rx_tasklet");
 
 	if (!ACM_READY(acm))
+	{
+		dbg("acm_rx_tasklet: ACM not ready");
 		return;
+	}
 
 	spin_lock_irqsave(&acm->throttle_lock, flags);
 	throttled = acm->throttle;
 	spin_unlock_irqrestore(&acm->throttle_lock, flags);
 	if (throttled)
+	{
+		dbg("acm_rx_tasklet: throttled");
 		return;
+	}
 
 next_buffer:
 	spin_lock_irqsave(&acm->read_lock, flags);
@@ -403,6 +443,7 @@
 	while (!list_empty(&acm->spare_read_bufs)) {
 		spin_lock_irqsave(&acm->read_lock, flags);
 		if (list_empty(&acm->spare_read_urbs)) {
+			acm->processing = 0;
 			spin_unlock_irqrestore(&acm->read_lock, flags);
 			return;
 		}
@@ -425,18 +466,23 @@
 		rcv->urb->transfer_dma = buf->dma;
 		rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-		dbg("acm_rx_tasklet: sending urb 0x%p, rcv 0x%p, buf 0x%p", rcv->urb, rcv, buf);
-
 		/* This shouldn't kill the driver as unsuccessful URBs are returned to the
 		   free-urbs-pool and resubmited ASAP */
-		if (usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) {
+		spin_lock_irqsave(&acm->read_lock, flags);
+		if (acm->susp_count || usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) {
 			list_add(&buf->list, &acm->spare_read_bufs);
-			spin_lock_irqsave(&acm->read_lock, flags);
 			list_add(&rcv->list, &acm->spare_read_urbs);
+			acm->processing = 0;
 			spin_unlock_irqrestore(&acm->read_lock, flags);
 			return;
+		} else {
+			spin_unlock_irqrestore(&acm->read_lock, flags);
+			dbg("acm_rx_tasklet: sending urb 0x%p, rcv 0x%p, buf 0x%p", rcv->urb, rcv, buf);
 		}
 	}
+	spin_lock_irqsave(&acm->read_lock, flags);
+	acm->processing = 0;
+	spin_unlock_irqrestore(&acm->read_lock, flags);
 }
 
 /* data interface wrote those outgoing bytes */
@@ -463,6 +509,27 @@
 	tty_wakeup(acm->tty);
 }
 
+static void acm_waker(struct work_struct *waker)
+{
+	struct acm *acm = container_of(waker, struct acm, waker);
+	long flags;
+	int rv;
+
+	rv = usb_autopm_get_interface(acm->control);
+	if (rv < 0) {
+		err("Autopm failure in %s", __func__);
+		return;
+	}
+	if (acm->delayed_wb) {
+		acm_start_wb(acm, acm->delayed_wb);
+		acm->delayed_wb = NULL;
+	}
+	spin_lock_irqsave(&acm->write_lock, flags);
+	acm->write_ready = acm->old_ready;
+	spin_unlock_irqrestore(&acm->write_lock, flags);
+	usb_autopm_put_interface(acm->control);
+}
+
 /*
  * TTY handlers
  */
@@ -492,6 +559,8 @@
 
 	if (usb_autopm_get_interface(acm->control) < 0)
 		goto early_bail;
+	else
+		acm->control->needs_remote_wakeup = 1;
 
 	mutex_lock(&acm->mutex);
 	if (acm->used++) {
@@ -509,6 +578,7 @@
 	if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) &&
 	    (acm->ctrl_caps & USB_CDC_CAP_LINE))
 		goto full_bailout;
+	usb_autopm_put_interface(acm->control);
 
 	INIT_LIST_HEAD(&acm->spare_read_urbs);
 	INIT_LIST_HEAD(&acm->spare_read_bufs);
@@ -570,12 +640,14 @@
 	mutex_lock(&open_mutex);
 	if (!--acm->used) {
 		if (acm->dev) {
+			usb_autopm_get_interface(acm->control);
 			acm_set_control(acm, acm->ctrlout = 0);
 			usb_kill_urb(acm->ctrlurb);
 			for (i = 0; i < ACM_NW; i++)
 				usb_kill_urb(acm->wb[i].urb);
 			for (i = 0; i < nr; i++)
 				usb_kill_urb(acm->ru[i].urb);
+			acm->control->needs_remote_wakeup = 0;
 			usb_autopm_put_interface(acm->control);
 		} else
 			acm_tty_unregister(acm);
@@ -660,13 +732,16 @@
 	tasklet_schedule(&acm->urb_task);
 }
 
-static void acm_tty_break_ctl(struct tty_struct *tty, int state)
+static int acm_tty_break_ctl(struct tty_struct *tty, int state)
 {
 	struct acm *acm = tty->driver_data;
+	int retval;
 	if (!ACM_READY(acm))
-		return;
-	if (acm_send_break(acm, state ? 0xffff : 0))
+		return -EINVAL;
+	retval = acm_send_break(acm, state ? 0xffff : 0);
+	if (retval < 0)
 		dbg("send break failed");
+	return retval;
 }
 
 static int acm_tty_tiocmget(struct tty_struct *tty, struct file *file)
@@ -766,7 +841,7 @@
  * USB probe and disconnect routines.
  */
 
-/* Little helper: write buffers free */
+/* Little helpers: write/read buffers free */
 static void acm_write_buffers_free(struct acm *acm)
 {
 	int i;
@@ -777,6 +852,15 @@
 	}
 }
 
+static void acm_read_buffers_free(struct acm *acm)
+{
+	struct usb_device *usb_dev = interface_to_usbdev(acm->control);
+	int i, n = acm->rx_buflimit;
+
+	for (i = 0; i < n; i++)
+		usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
+}
+
 /* Little helper: write buffers allocate */
 static int acm_write_buffers_alloc(struct acm *acm)
 {
@@ -987,6 +1071,7 @@
 	acm->urb_task.func = acm_rx_tasklet;
 	acm->urb_task.data = (unsigned long) acm;
 	INIT_WORK(&acm->work, acm_softint);
+	INIT_WORK(&acm->waker, acm_waker);
 	spin_lock_init(&acm->throttle_lock);
 	spin_lock_init(&acm->write_lock);
 	spin_lock_init(&acm->read_lock);
@@ -1098,8 +1183,7 @@
 	for (i = 0; i < ACM_NW; i++)
 		usb_free_urb(acm->wb[i].urb);
 alloc_fail7:
-	for (i = 0; i < num_rx_buf; i++)
-		usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
+	acm_read_buffers_free(acm);
 	for (i = 0; i < num_rx_buf; i++)
 		usb_free_urb(acm->ru[i].urb);
 	usb_free_urb(acm->ctrlurb);
@@ -1116,6 +1200,7 @@
 static void stop_data_traffic(struct acm *acm)
 {
 	int i;
+	dbg("Entering stop_data_traffic");
 
 	tasklet_disable(&acm->urb_task);
 
@@ -1128,21 +1213,16 @@
 	tasklet_enable(&acm->urb_task);
 
 	cancel_work_sync(&acm->work);
+	cancel_work_sync(&acm->waker);
 }
 
 static void acm_disconnect(struct usb_interface *intf)
 {
 	struct acm *acm = usb_get_intfdata(intf);
 	struct usb_device *usb_dev = interface_to_usbdev(intf);
-	int i;
-
-	if (!acm || !acm->dev) {
-		dbg("disconnect on nonexisting interface");
-		return;
-	}
 
 	mutex_lock(&open_mutex);
-	if (!usb_get_intfdata(intf)) {
+	if (!acm || !acm->dev) {
 		mutex_unlock(&open_mutex);
 		return;
 	}
@@ -1161,10 +1241,10 @@
 
 	acm_write_buffers_free(acm);
 	usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
-	for (i = 0; i < acm->rx_buflimit; i++)
-		usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
+	acm_read_buffers_free(acm);
 
-	usb_driver_release_interface(&acm_driver, intf == acm->control ? acm->data : intf);
+	usb_driver_release_interface(&acm_driver, intf == acm->control ?
+					acm->data : acm->control);
 
 	if (!acm->used) {
 		acm_tty_unregister(acm);
@@ -1178,11 +1258,31 @@
 		tty_hangup(acm->tty);
 }
 
+#ifdef CONFIG_PM
 static int acm_suspend(struct usb_interface *intf, pm_message_t message)
 {
 	struct acm *acm = usb_get_intfdata(intf);
+	int cnt;
 
-	if (acm->susp_count++)
+	if (acm->dev->auto_pm) {
+		int b;
+
+		spin_lock_irq(&acm->read_lock);
+		spin_lock(&acm->write_lock);
+		b = acm->processing + acm->transmitting;
+		spin_unlock(&acm->write_lock);
+		spin_unlock_irq(&acm->read_lock);
+		if (b)
+			return -EBUSY;
+	}
+
+	spin_lock_irq(&acm->read_lock);
+	spin_lock(&acm->write_lock);
+	cnt = acm->susp_count++;
+	spin_unlock(&acm->write_lock);
+	spin_unlock_irq(&acm->read_lock);
+
+	if (cnt)
 		return 0;
 	/*
 	we treat opened interfaces differently,
@@ -1201,15 +1301,21 @@
 {
 	struct acm *acm = usb_get_intfdata(intf);
 	int rv = 0;
+	int cnt;
 
-	if (--acm->susp_count)
+	spin_lock_irq(&acm->read_lock);
+	acm->susp_count -= 1;
+	cnt = acm->susp_count;
+	spin_unlock_irq(&acm->read_lock);
+
+	if (cnt)
 		return 0;
 
 	mutex_lock(&acm->mutex);
 	if (acm->used) {
 		rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO);
 		if (rv < 0)
-		goto err_out;
+			goto err_out;
 
 		tasklet_schedule(&acm->urb_task);
 	}
@@ -1218,6 +1324,8 @@
 	mutex_unlock(&acm->mutex);
 	return rv;
 }
+
+#endif /* CONFIG_PM */
 /*
  * USB driver structure.
  */
@@ -1273,10 +1381,14 @@
 	.name =		"cdc_acm",
 	.probe =	acm_probe,
 	.disconnect =	acm_disconnect,
+#ifdef CONFIG_PM
 	.suspend =	acm_suspend,
 	.resume =	acm_resume,
+#endif
 	.id_table =	acm_ids,
+#ifdef CONFIG_PM
 	.supports_autosuspend = 1,
+#endif
 };
 
 /*
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
index 046e064..85c3aaa 100644
--- a/drivers/usb/class/cdc-acm.h
+++ b/drivers/usb/class/cdc-acm.h
@@ -107,10 +107,14 @@
 	struct list_head filled_read_bufs;
 	int write_used;					/* number of non-empty write buffers */
 	int write_ready;				/* write urb is not running */
+	int old_ready;
+	int processing;
+	int transmitting;
 	spinlock_t write_lock;
 	struct mutex mutex;
 	struct usb_cdc_line_coding line;		/* bits, stop, parity */
 	struct work_struct work;			/* work queue entry for line discipline waking up */
+	struct work_struct waker;
 	struct tasklet_struct urb_task;                 /* rx processing */
 	spinlock_t throttle_lock;			/* synchronize throtteling and read callback */
 	unsigned int ctrlin;				/* input control lines (DCD, DSR, RI, break, overruns) */
@@ -123,6 +127,7 @@
 	unsigned char clocal;				/* termios CLOCAL */
 	unsigned int ctrl_caps;				/* control capabilities from the class specific header */
 	unsigned int susp_count;			/* number of suspended interfaces */
+	struct acm_wb *delayed_wb;			/* write queued for a device about to be woken */
 };
 
 #define CDC_DATA_INTERFACE_TYPE	0x0a
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 731db05..7e8e123 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -28,8 +28,9 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.02"
+#define DRIVER_VERSION "v0.03"
 #define DRIVER_AUTHOR "Oliver Neukum"
+#define DRIVER_DESC "USB Abstract Control Model driver for USB WCM Device Management"
 
 static struct usb_device_id wdm_ids[] = {
 	{
@@ -87,6 +88,7 @@
 	dma_addr_t		ihandle;
 	struct mutex		wlock;
 	struct mutex		rlock;
+	struct mutex		plock;
 	wait_queue_head_t	wait;
 	struct work_struct	rxwork;
 	int			werr;
@@ -205,7 +207,7 @@
 	req->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE;
 	req->wValue = 0;
 	req->wIndex = desc->inum;
-	req->wLength = cpu_to_le16(desc->bMaxPacketSize0);
+	req->wLength = cpu_to_le16(desc->wMaxCommand);
 
 	usb_fill_control_urb(
 		desc->response,
@@ -214,7 +216,7 @@
 		usb_rcvctrlpipe(interface_to_usbdev(desc->intf), 0),
 		(unsigned char *)req,
 		desc->inbuf,
-		desc->bMaxPacketSize0,
+		desc->wMaxCommand,
 		wdm_in_callback,
 		desc
 	);
@@ -247,6 +249,7 @@
 
 static void kill_urbs(struct wdm_device *desc)
 {
+	/* the order here is essential */
 	usb_kill_urb(desc->command);
 	usb_kill_urb(desc->validity);
 	usb_kill_urb(desc->response);
@@ -266,7 +269,7 @@
 			desc->sbuf,
 			desc->validity->transfer_dma);
 	usb_buffer_free(interface_to_usbdev(desc->intf),
-			desc->wMaxPacketSize,
+			desc->wMaxCommand,
 			desc->inbuf,
 			desc->response->transfer_dma);
 	kfree(desc->orq);
@@ -299,6 +302,9 @@
 	if (r)
 		goto outnl;
 
+	r = usb_autopm_get_interface(desc->intf);
+	if (r < 0)
+		goto outnp;
 	r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE,
 							   &desc->flags));
 	if (r < 0)
@@ -347,11 +353,14 @@
 	if (rv < 0) {
 		kfree(buf);
 		clear_bit(WDM_IN_USE, &desc->flags);
+		err("Tx URB error: %d", rv);
 	} else {
 		dev_dbg(&desc->intf->dev, "Tx URB has been submitted index=%d",
 			req->wIndex);
 	}
 out:
+	usb_autopm_put_interface(desc->intf);
+outnp:
 	mutex_unlock(&desc->wlock);
 outnl:
 	return rv < 0 ? rv : count;
@@ -376,6 +385,11 @@
 		rv = wait_event_interruptible(desc->wait,
 					      test_bit(WDM_READ, &desc->flags));
 
+		if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
+			rv = -ENODEV;
+			goto err;
+		}
+		usb_mark_last_busy(interface_to_usbdev(desc->intf));
 		if (rv < 0) {
 			rv = -ERESTARTSYS;
 			goto err;
@@ -418,6 +432,9 @@
 		desc->ubuf[i] = desc->ubuf[i + cntr];
 
 	desc->length -= cntr;
+	/* in case we had outstanding data */
+	if (!desc->length)
+		clear_bit(WDM_READ, &desc->flags);
 	rv = cntr;
 
 err:
@@ -480,18 +497,28 @@
 	if (test_bit(WDM_DISCONNECTING, &desc->flags))
 		goto out;
 
-	desc->count++;
+	;
 	file->private_data = desc;
 
-	rv = usb_submit_urb(desc->validity, GFP_KERNEL);
-
+	rv = usb_autopm_get_interface(desc->intf);
 	if (rv < 0) {
-		desc->count--;
-		err("Error submitting int urb - %d", rv);
+		err("Error autopm - %d", rv);
 		goto out;
 	}
-	rv = 0;
+	intf->needs_remote_wakeup = 1;
 
+	mutex_lock(&desc->plock);
+	if (!desc->count++) {
+		rv = usb_submit_urb(desc->validity, GFP_KERNEL);
+		if (rv < 0) {
+			desc->count--;
+			err("Error submitting int urb - %d", rv);
+		}
+	} else {
+		rv = 0;
+	}
+	mutex_unlock(&desc->plock);
+	usb_autopm_put_interface(desc->intf);
 out:
 	mutex_unlock(&wdm_mutex);
 	return rv;
@@ -502,10 +529,15 @@
 	struct wdm_device *desc = file->private_data;
 
 	mutex_lock(&wdm_mutex);
+	mutex_lock(&desc->plock);
 	desc->count--;
+	mutex_unlock(&desc->plock);
+
 	if (!desc->count) {
 		dev_dbg(&desc->intf->dev, "wdm_release: cleanup");
 		kill_urbs(desc);
+		if (!test_bit(WDM_DISCONNECTING, &desc->flags))
+			desc->intf->needs_remote_wakeup = 0;
 	}
 	mutex_unlock(&wdm_mutex);
 	return 0;
@@ -597,6 +629,7 @@
 		goto out;
 	mutex_init(&desc->wlock);
 	mutex_init(&desc->rlock);
+	mutex_init(&desc->plock);
 	spin_lock_init(&desc->iuspin);
 	init_waitqueue_head(&desc->wait);
 	desc->wMaxCommand = maxcom;
@@ -698,6 +731,7 @@
 	spin_lock_irqsave(&desc->iuspin, flags);
 	set_bit(WDM_DISCONNECTING, &desc->flags);
 	set_bit(WDM_READ, &desc->flags);
+	/* to terminate pending flushes */
 	clear_bit(WDM_IN_USE, &desc->flags);
 	spin_unlock_irqrestore(&desc->iuspin, flags);
 	cancel_work_sync(&desc->rxwork);
@@ -708,11 +742,81 @@
 	mutex_unlock(&wdm_mutex);
 }
 
+static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct wdm_device *desc = usb_get_intfdata(intf);
+	int rv = 0;
+
+	dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor);
+
+	mutex_lock(&desc->plock);
+#ifdef CONFIG_PM
+	if (interface_to_usbdev(desc->intf)->auto_pm && test_bit(WDM_IN_USE, &desc->flags)) {
+		rv = -EBUSY;
+	} else {
+#endif
+		cancel_work_sync(&desc->rxwork);
+		kill_urbs(desc);
+#ifdef CONFIG_PM
+	}
+#endif
+	mutex_unlock(&desc->plock);
+
+	return rv;
+}
+
+static int recover_from_urb_loss(struct wdm_device *desc)
+{
+	int rv = 0;
+
+	if (desc->count) {
+		rv = usb_submit_urb(desc->validity, GFP_NOIO);
+		if (rv < 0)
+			err("Error resume submitting int urb - %d", rv);
+	}
+	return rv;
+}
+static int wdm_resume(struct usb_interface *intf)
+{
+	struct wdm_device *desc = usb_get_intfdata(intf);
+	int rv;
+
+	dev_dbg(&desc->intf->dev, "wdm%d_resume\n", intf->minor);
+	mutex_lock(&desc->plock);
+	rv = recover_from_urb_loss(desc);
+	mutex_unlock(&desc->plock);
+	return rv;
+}
+
+static int wdm_pre_reset(struct usb_interface *intf)
+{
+	struct wdm_device *desc = usb_get_intfdata(intf);
+
+	mutex_lock(&desc->plock);
+	return 0;
+}
+
+static int wdm_post_reset(struct usb_interface *intf)
+{
+	struct wdm_device *desc = usb_get_intfdata(intf);
+	int rv;
+
+	rv = recover_from_urb_loss(desc);
+	mutex_unlock(&desc->plock);
+	return 0;
+}
+
 static struct usb_driver wdm_driver = {
 	.name =		"cdc_wdm",
 	.probe =	wdm_probe,
 	.disconnect =	wdm_disconnect,
+	.suspend =	wdm_suspend,
+	.resume =	wdm_resume,
+	.reset_resume =	wdm_resume,
+	.pre_reset =	wdm_pre_reset,
+	.post_reset =	wdm_post_reset,
 	.id_table =	wdm_ids,
+	.supports_autosuspend = 1,
 };
 
 /* --- low level module stuff --- */
@@ -735,6 +839,5 @@
 module_exit(wdm_exit);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION("USB Abstract Control Model driver for "
-		   "USB WCM Device Management");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index 83d9dc3..6ec3817 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -46,8 +46,6 @@
  * 2000-07-05: Ashley Montanaro <ashley@compsoc.man.ac.uk>
  *   Converted file reading routine to dump to buffer once
  *   per device, not per bus
- *
- * $Id: devices.c,v 1.5 2000/01/11 13:58:21 tom Exp $
  */
 
 #include <linux/fs.h>
@@ -63,8 +61,6 @@
 #include "usb.h"
 #include "hcd.h"
 
-#define MAX_TOPO_LEVEL		6
-
 /* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */
 #define ALLOW_SERIAL_NUMBER
 
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 9218cca..20290c5 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -19,8 +19,6 @@
  *      along with this program; if not, write to the Free Software
  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- *  $Id: devio.c,v 1.7 2000/02/01 17:28:48 fliegl Exp $
- *
  *  This file implements the usbfs/x/y files, where
  *  x is the bus number and y the device number.
  *
@@ -61,6 +59,22 @@
 /* Mutual exclusion for removal, open, and release */
 DEFINE_MUTEX(usbfs_mutex);
 
+struct dev_state {
+	struct list_head list;      /* state list */
+	struct usb_device *dev;
+	struct file *file;
+	spinlock_t lock;            /* protects the async urb lists */
+	struct list_head async_pending;
+	struct list_head async_completed;
+	wait_queue_head_t wait;     /* wake up if a request completed */
+	unsigned int discsignr;
+	struct pid *disc_pid;
+	uid_t disc_uid, disc_euid;
+	void __user *disccontext;
+	unsigned long ifclaimed;
+	u32 secid;
+};
+
 struct async {
 	struct list_head asynclist;
 	struct dev_state *ps;
@@ -536,23 +550,19 @@
 	return ret;
 }
 
-static int __match_minor(struct device *dev, void *data)
+static int match_devt(struct device *dev, void *data)
 {
-	int minor = *((int *)data);
-
-	if (dev->devt == MKDEV(USB_DEVICE_MAJOR, minor))
-		return 1;
-	return 0;
+	return dev->devt == (dev_t) (unsigned long) data;
 }
 
-static struct usb_device *usbdev_lookup_by_minor(int minor)
+static struct usb_device *usbdev_lookup_by_devt(dev_t devt)
 {
 	struct device *dev;
 
-	dev = bus_find_device(&usb_bus_type, NULL, &minor, __match_minor);
+	dev = bus_find_device(&usb_bus_type, NULL,
+			      (void *) (unsigned long) devt, match_devt);
 	if (!dev)
 		return NULL;
-	put_device(dev);
 	return container_of(dev, struct usb_device, dev);
 }
 
@@ -575,21 +585,27 @@
 		goto out;
 
 	ret = -ENOENT;
+
 	/* usbdev device-node */
 	if (imajor(inode) == USB_DEVICE_MAJOR)
-		dev = usbdev_lookup_by_minor(iminor(inode));
+		dev = usbdev_lookup_by_devt(inode->i_rdev);
 #ifdef CONFIG_USB_DEVICEFS
 	/* procfs file */
-	if (!dev)
+	if (!dev) {
 		dev = inode->i_private;
+		if (dev && dev->usbfs_dentry &&
+					dev->usbfs_dentry->d_inode == inode)
+			usb_get_dev(dev);
+		else
+			dev = NULL;
+	}
 #endif
-	if (!dev)
+	if (!dev || dev->state == USB_STATE_NOTATTACHED)
 		goto out;
 	ret = usb_autoresume_device(dev);
 	if (ret)
 		goto out;
 
-	usb_get_dev(dev);
 	ret = 0;
 	ps->dev = dev;
 	ps->file = file;
@@ -609,8 +625,10 @@
 	list_add_tail(&ps->list, &dev->filelist);
 	file->private_data = ps;
  out:
-	if (ret)
+	if (ret) {
 		kfree(ps);
+		usb_put_dev(dev);
+	}
 	mutex_unlock(&usbfs_mutex);
 	unlock_kernel();
 	return ret;
@@ -874,7 +892,7 @@
 
 static int proc_resetdevice(struct dev_state *ps)
 {
-	return usb_reset_composite_device(ps->dev, NULL);
+	return usb_reset_device(ps->dev);
 }
 
 static int proc_setintf(struct dev_state *ps, void __user *arg)
@@ -1682,25 +1700,49 @@
 	.release =	usbdev_release,
 };
 
+void usb_fs_classdev_common_remove(struct usb_device *udev)
+{
+	struct dev_state *ps;
+	struct siginfo sinfo;
+
+	while (!list_empty(&udev->filelist)) {
+		ps = list_entry(udev->filelist.next, struct dev_state, list);
+		destroy_all_async(ps);
+		wake_up_all(&ps->wait);
+		list_del_init(&ps->list);
+		if (ps->discsignr) {
+			sinfo.si_signo = ps->discsignr;
+			sinfo.si_errno = EPIPE;
+			sinfo.si_code = SI_ASYNCIO;
+			sinfo.si_addr = ps->disccontext;
+			kill_pid_info_as_uid(ps->discsignr, &sinfo,
+					ps->disc_pid, ps->disc_uid,
+					ps->disc_euid, ps->secid);
+		}
+	}
+}
+
 #ifdef CONFIG_USB_DEVICE_CLASS
 static struct class *usb_classdev_class;
 
 static int usb_classdev_add(struct usb_device *dev)
 {
-	int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1);
+	struct device *cldev;
 
-	dev->usb_classdev = device_create(usb_classdev_class, &dev->dev,
-				MKDEV(USB_DEVICE_MAJOR, minor),
-				"usbdev%d.%d", dev->bus->busnum, dev->devnum);
-	if (IS_ERR(dev->usb_classdev))
-		return PTR_ERR(dev->usb_classdev);
-
+	cldev = device_create_drvdata(usb_classdev_class, &dev->dev,
+				      dev->dev.devt, NULL, "usbdev%d.%d",
+				      dev->bus->busnum, dev->devnum);
+	if (IS_ERR(cldev))
+		return PTR_ERR(cldev);
+	dev->usb_classdev = cldev;
 	return 0;
 }
 
 static void usb_classdev_remove(struct usb_device *dev)
 {
-	device_unregister(dev->usb_classdev);
+	if (dev->usb_classdev)
+		device_unregister(dev->usb_classdev);
+	usb_fs_classdev_common_remove(dev);
 }
 
 static int usb_classdev_notify(struct notifier_block *self,
@@ -1750,6 +1792,11 @@
 		usb_classdev_class = NULL;
 		goto out;
 	}
+	/* devices of this class shadow the major:minor of their parent
+	 * device, so clear ->dev_kobj to prevent adding duplicate entries
+	 * to /sys/dev
+	 */
+	usb_classdev_class->dev_kobj = NULL;
 
 	usb_register_notify(&usbdev_nb);
 #endif
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 1e56f1c..ddb54e1 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -201,6 +201,7 @@
 
 	intf = to_usb_interface(dev);
 	udev = interface_to_usbdev(intf);
+	intf->needs_binding = 0;
 
 	if (udev->authorized == 0) {
 		dev_err(&intf->dev, "Device is not authorized for usage\n");
@@ -257,15 +258,16 @@
 	udev = interface_to_usbdev(intf);
 	error = usb_autoresume_device(udev);
 
-	/* release all urbs for this interface */
-	usb_disable_interface(interface_to_usbdev(intf), intf);
+	/* Terminate all URBs for this interface unless the driver
+	 * supports "soft" unbinding.
+	 */
+	if (!driver->soft_unbind)
+		usb_disable_interface(udev, intf);
 
 	driver->disconnect(intf);
 
 	/* reset other interface state */
-	usb_set_interface(interface_to_usbdev(intf),
-			intf->altsetting[0].desc.bInterfaceNumber,
-			0);
+	usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0);
 	usb_set_intfdata(intf, NULL);
 
 	intf->condition = USB_INTERFACE_UNBOUND;
@@ -310,6 +312,7 @@
 
 	dev->driver = &driver->drvwrap.driver;
 	usb_set_intfdata(iface, priv);
+	iface->needs_binding = 0;
 
 	usb_pm_lock(udev);
 	iface->condition = USB_INTERFACE_BOUND;
@@ -586,7 +589,7 @@
 	struct usb_device *usb_dev;
 
 	/* driver is often null here; dev_dbg() would oops */
-	pr_debug("usb %s: uevent\n", dev->bus_id);
+	pr_debug("usb %s: uevent\n", dev_name(dev));
 
 	if (is_usb_device(dev))
 		usb_dev = to_usb_device(dev);
@@ -596,11 +599,11 @@
 	}
 
 	if (usb_dev->devnum < 0) {
-		pr_debug("usb %s: already deleted?\n", dev->bus_id);
+		pr_debug("usb %s: already deleted?\n", dev_name(dev));
 		return -ENODEV;
 	}
 	if (!usb_dev->bus) {
-		pr_debug("usb %s: bus removed?\n", dev->bus_id);
+		pr_debug("usb %s: bus removed?\n", dev_name(dev));
 		return -ENODEV;
 	}
 
@@ -771,6 +774,104 @@
 }
 EXPORT_SYMBOL_GPL(usb_deregister);
 
+
+/* Forced unbinding of a USB interface driver, either because
+ * it doesn't support pre_reset/post_reset/reset_resume or
+ * because it doesn't support suspend/resume.
+ *
+ * The caller must hold @intf's device's lock, but not its pm_mutex
+ * and not @intf->dev.sem.
+ */
+void usb_forced_unbind_intf(struct usb_interface *intf)
+{
+	struct usb_driver *driver = to_usb_driver(intf->dev.driver);
+
+	dev_dbg(&intf->dev, "forced unbind\n");
+	usb_driver_release_interface(driver, intf);
+
+	/* Mark the interface for later rebinding */
+	intf->needs_binding = 1;
+}
+
+/* Delayed forced unbinding of a USB interface driver and scan
+ * for rebinding.
+ *
+ * The caller must hold @intf's device's lock, but not its pm_mutex
+ * and not @intf->dev.sem.
+ *
+ * FIXME: The caller must block system sleep transitions.
+ */
+void usb_rebind_intf(struct usb_interface *intf)
+{
+	int rc;
+
+	/* Delayed unbind of an existing driver */
+	if (intf->dev.driver) {
+		struct usb_driver *driver =
+				to_usb_driver(intf->dev.driver);
+
+		dev_dbg(&intf->dev, "forced unbind\n");
+		usb_driver_release_interface(driver, intf);
+	}
+
+	/* Try to rebind the interface */
+	intf->needs_binding = 0;
+	rc = device_attach(&intf->dev);
+	if (rc < 0)
+		dev_warn(&intf->dev, "rebind failed: %d\n", rc);
+}
+
+#define DO_UNBIND	0
+#define DO_REBIND	1
+
+/* Unbind drivers for @udev's interfaces that don't support suspend/resume,
+ * or rebind interfaces that have been unbound, according to @action.
+ *
+ * The caller must hold @udev's device lock.
+ * FIXME: For rebinds, the caller must block system sleep transitions.
+ */
+static void do_unbind_rebind(struct usb_device *udev, int action)
+{
+	struct usb_host_config	*config;
+	int			i;
+	struct usb_interface	*intf;
+	struct usb_driver	*drv;
+
+	config = udev->actconfig;
+	if (config) {
+		for (i = 0; i < config->desc.bNumInterfaces; ++i) {
+			intf = config->interface[i];
+			switch (action) {
+			case DO_UNBIND:
+				if (intf->dev.driver) {
+					drv = to_usb_driver(intf->dev.driver);
+					if (!drv->suspend || !drv->resume)
+						usb_forced_unbind_intf(intf);
+				}
+				break;
+			case DO_REBIND:
+				if (intf->needs_binding) {
+
+	/* FIXME: The next line is needed because we are going to probe
+	 * the interface, but as far as the PM core is concerned the
+	 * interface is still suspended.  The problem wouldn't exist
+	 * if we could rebind the interface during the interface's own
+	 * resume() call, but at the time the usb_device isn't locked!
+	 *
+	 * The real solution will be to carry this out during the device's
+	 * complete() callback.  Until that is implemented, we have to
+	 * use this hack.
+	 */
+//					intf->dev.power.sleeping = 0;
+
+					usb_rebind_intf(intf);
+				}
+				break;
+			}
+		}
+	}
+}
+
 #ifdef CONFIG_PM
 
 /* Caller has locked udev's pm_mutex */
@@ -805,8 +906,6 @@
 
 	if (udev->state == USB_STATE_NOTATTACHED)
 		goto done;
-	if (udev->state != USB_STATE_SUSPENDED && !udev->reset_resume)
-		goto done;
 
 	/* Can't resume it if it doesn't have a driver. */
 	if (udev->dev.driver == NULL) {
@@ -842,7 +941,7 @@
 		goto done;
 	driver = to_usb_driver(intf->dev.driver);
 
-	if (driver->suspend && driver->resume) {
+	if (driver->suspend) {
 		status = driver->suspend(intf, msg);
 		if (status == 0)
 			mark_quiesced(intf);
@@ -850,12 +949,10 @@
 			dev_err(&intf->dev, "%s error %d\n",
 					"suspend", status);
 	} else {
-		/*
-		 * FIXME else if there's no suspend method, disconnect...
-		 * Not possible if auto_pm is set...
-		 */
-		dev_warn(&intf->dev, "no suspend for driver %s?\n",
-				driver->name);
+		/* Later we will unbind the driver and reprobe */
+		intf->needs_binding = 1;
+		dev_warn(&intf->dev, "no %s for driver %s?\n",
+				"suspend", driver->name);
 		mark_quiesced(intf);
 	}
 
@@ -879,10 +976,12 @@
 		goto done;
 
 	/* Can't resume it if it doesn't have a driver. */
-	if (intf->condition == USB_INTERFACE_UNBOUND) {
-		status = -ENOTCONN;
+	if (intf->condition == USB_INTERFACE_UNBOUND)
 		goto done;
-	}
+
+	/* Don't resume if the interface is marked for rebinding */
+	if (intf->needs_binding)
+		goto done;
 	driver = to_usb_driver(intf->dev.driver);
 
 	if (reset_resume) {
@@ -892,7 +991,7 @@
 				dev_err(&intf->dev, "%s error %d\n",
 						"reset_resume", status);
 		} else {
-			/* status = -EOPNOTSUPP; */
+			intf->needs_binding = 1;
 			dev_warn(&intf->dev, "no %s for driver %s?\n",
 					"reset_resume", driver->name);
 		}
@@ -903,7 +1002,7 @@
 				dev_err(&intf->dev, "%s error %d\n",
 						"resume", status);
 		} else {
-			/* status = -EOPNOTSUPP; */
+			intf->needs_binding = 1;
 			dev_warn(&intf->dev, "no %s for driver %s?\n",
 					"resume", driver->name);
 		}
@@ -911,11 +1010,10 @@
 
 done:
 	dev_vdbg(&intf->dev, "%s: status %d\n", __func__, status);
-	if (status == 0)
+	if (status == 0 && intf->condition == USB_INTERFACE_BOUND)
 		mark_active(intf);
 
-	/* FIXME: Unbind the driver and reprobe if the resume failed
-	 * (not possible if auto_pm is set) */
+	/* Later we will unbind the driver and/or reprobe, if necessary */
 	return status;
 }
 
@@ -1173,11 +1271,8 @@
 			 * then we're stuck. */
 			status = usb_resume_device(udev);
 		}
-	} else {
-
-		/* Needed for reset-resume */
+	} else if (udev->reset_resume)
 		status = usb_resume_device(udev);
-	}
 
 	if (status == 0 && udev->actconfig) {
 		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
@@ -1474,6 +1569,7 @@
 {
 	int	status;
 
+	do_unbind_rebind(udev, DO_UNBIND);
 	usb_pm_lock(udev);
 	udev->auto_pm = 0;
 	status = usb_suspend_both(udev, msg);
@@ -1501,6 +1597,7 @@
 	status = usb_resume_both(udev);
 	udev->last_busy = jiffies;
 	usb_pm_unlock(udev);
+	do_unbind_rebind(udev, DO_REBIND);
 
 	/* Now that the device is awake, we can start trying to autosuspend
 	 * it again. */
@@ -1542,14 +1639,11 @@
 	udev = to_usb_device(dev);
 
 	/* If udev->skip_sys_resume is set then udev was already suspended
-	 * when the system suspend started, so we don't want to resume
-	 * udev during this system wakeup.  However a reset-resume counts
-	 * as a wakeup event, so allow a reset-resume to occur if remote
-	 * wakeup is enabled. */
-	if (udev->skip_sys_resume) {
-		if (!(udev->reset_resume && udev->do_remote_wakeup))
-			return -EHOSTUNREACH;
-	}
+	 * when the system sleep started, so we don't want to resume it
+	 * during this system wakeup.
+	 */
+	if (udev->skip_sys_resume)
+		return 0;
 	return usb_external_resume_device(udev);
 }
 
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index fae55a3..2291213 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -296,7 +296,7 @@
 	retval = endpoint_get_minor(ep_dev);
 	if (retval) {
 		dev_err(parent, "can not allocate minor number for %s\n",
-			ep_dev->dev.bus_id);
+			dev_name(&ep_dev->dev));
 		goto error_register;
 	}
 
@@ -307,7 +307,7 @@
 	ep_dev->dev.class = ep_class->class;
 	ep_dev->dev.parent = parent;
 	ep_dev->dev.release = ep_device_release;
-	snprintf(ep_dev->dev.bus_id, BUS_ID_SIZE, "usbdev%d.%d_ep%02x",
+	dev_set_name(&ep_dev->dev, "usbdev%d.%d_ep%02x",
 		 udev->bus->busnum, udev->devnum,
 		 endpoint->desc.bEndpointAddress);
 
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index c6a9539..6b1b229e 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -150,7 +150,7 @@
 	int retval = -EINVAL;
 	int minor_base = class_driver->minor_base;
 	int minor = 0;
-	char name[BUS_ID_SIZE];
+	char name[20];
 	char *temp;
 
 #ifdef CONFIG_USB_DYNAMIC_MINORS
@@ -190,14 +190,15 @@
 	intf->minor = minor;
 
 	/* create a usb class device for this usb interface */
-	snprintf(name, BUS_ID_SIZE, class_driver->name, minor - minor_base);
+	snprintf(name, sizeof(name), class_driver->name, minor - minor_base);
 	temp = strrchr(name, '/');
-	if (temp && (temp[1] != 0x00))
+	if (temp && (temp[1] != '\0'))
 		++temp;
 	else
 		temp = name;
-	intf->usb_dev = device_create(usb_class->class, &intf->dev,
-				      MKDEV(USB_MAJOR, minor), "%s", temp);
+	intf->usb_dev = device_create_drvdata(usb_class->class, &intf->dev,
+					      MKDEV(USB_MAJOR, minor), NULL,
+					      "%s", temp);
 	if (IS_ERR(intf->usb_dev)) {
 		down_write(&minor_rwsem);
 		usb_minors[intf->minor] = NULL;
@@ -227,7 +228,7 @@
 			struct usb_class_driver *class_driver)
 {
 	int minor_base = class_driver->minor_base;
-	char name[BUS_ID_SIZE];
+	char name[20];
 
 #ifdef CONFIG_USB_DYNAMIC_MINORS
 	minor_base = 0;
@@ -242,7 +243,7 @@
 	usb_minors[intf->minor] = NULL;
 	up_write(&minor_rwsem);
 
-	snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base);
+	snprintf(name, sizeof(name), class_driver->name, intf->minor - minor_base);
 	device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor));
 	intf->usb_dev = NULL;
 	intf->minor = -1;
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 42a4364..f7bfd72 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -900,14 +900,14 @@
 	if (retval != sizeof usb_dev->descriptor) {
 		mutex_unlock(&usb_bus_list_lock);
 		dev_dbg (parent_dev, "can't read %s device descriptor %d\n",
-				usb_dev->dev.bus_id, retval);
+				dev_name(&usb_dev->dev), retval);
 		return (retval < 0) ? retval : -EMSGSIZE;
 	}
 
 	retval = usb_new_device (usb_dev);
 	if (retval) {
 		dev_err (parent_dev, "can't register root hub for %s, %d\n",
-				usb_dev->dev.bus_id, retval);
+				dev_name(&usb_dev->dev), retval);
 	}
 	mutex_unlock(&usb_bus_list_lock);
 
@@ -1764,7 +1764,7 @@
  * If memory is unavailable, returns NULL.
  */
 struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
-		struct device *dev, char *bus_name)
+		struct device *dev, const char *bus_name)
 {
 	struct usb_hcd *hcd;
 
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index b9de156..5b0b59b 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -21,6 +21,8 @@
 
 #include <linux/rwsem.h>
 
+#define MAX_TOPO_LEVEL		6
+
 /* This file contains declarations of usbcore internals that are mostly
  * used or exposed by Host Controller Drivers.
  */
@@ -235,7 +237,7 @@
 extern int usb_hcd_get_frame_number(struct usb_device *udev);
 
 extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver,
-		struct device *dev, char *bus_name);
+		struct device *dev, const 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,
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 4cfe32a..107e1d2 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -72,7 +72,6 @@
 
 	unsigned		limited_power:1;
 	unsigned		quiescing:1;
-	unsigned		activating:1;
 	unsigned		disconnected:1;
 
 	unsigned		has_indicators:1;
@@ -131,6 +130,12 @@
 DECLARE_RWSEM(ehci_cf_port_reset_rwsem);
 EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem);
 
+#define HUB_DEBOUNCE_TIMEOUT	1500
+#define HUB_DEBOUNCE_STEP	  25
+#define HUB_DEBOUNCE_STABLE	 100
+
+
+static int usb_reset_and_verify_device(struct usb_device *udev);
 
 static inline char *portspeed(int portstatus)
 {
@@ -535,37 +540,6 @@
 	msleep(max(pgood_delay, (unsigned) 100));
 }
 
-static void hub_quiesce(struct usb_hub *hub)
-{
-	/* (nonblocking) khubd and related activity won't re-trigger */
-	hub->quiescing = 1;
-	hub->activating = 0;
-
-	/* (blocking) stop khubd and related activity */
-	usb_kill_urb(hub->urb);
-	if (hub->has_indicators)
-		cancel_delayed_work_sync(&hub->leds);
-	if (hub->tt.hub)
-		cancel_work_sync(&hub->tt.kevent);
-}
-
-static void hub_activate(struct usb_hub *hub)
-{
-	int	status;
-
-	hub->quiescing = 0;
-	hub->activating = 1;
-
-	status = usb_submit_urb(hub->urb, GFP_NOIO);
-	if (status < 0)
-		dev_err(hub->intfdev, "activate --> %d\n", status);
-	if (hub->has_indicators && blinkenlights)
-		schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);
-
-	/* scan all ports ASAP */
-	kick_khubd(hub);
-}
-
 static int hub_hub_status(struct usb_hub *hub,
 		u16 *status, u16 *change)
 {
@@ -624,136 +598,149 @@
  	kick_khubd(hub);
 }
 
-/* caller has locked the hub device */
-static void hub_stop(struct usb_hub *hub)
-{
-	struct usb_device *hdev = hub->hdev;
-	int i;
+enum hub_activation_type {
+	HUB_INIT, HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME
+};
 
-	/* Disconnect all the children */
-	for (i = 0; i < hdev->maxchild; ++i) {
-		if (hdev->children[i])
-			usb_disconnect(&hdev->children[i]);
-	}
-	hub_quiesce(hub);
-}
-
-#define HUB_RESET		1
-#define HUB_RESUME		2
-#define HUB_RESET_RESUME	3
-
-#ifdef CONFIG_PM
-
-/* Try to identify which devices need USB-PERSIST handling */
-static int persistent_device(struct usb_device *udev)
-{
-	int i;
-	int retval;
-	struct usb_host_config *actconfig;
-
-	/* Explicitly not marked persistent? */
-	if (!udev->persist_enabled)
-		return 0;
-
-	/* No active config? */
-	actconfig = udev->actconfig;
-	if (!actconfig)
-		return 0;
-
-	/* FIXME! We should check whether it's open here or not! */
-
-	/*
-	 * Check that all the interface drivers have a
-	 * 'reset_resume' entrypoint
-	 */
-	retval = 0;
-	for (i = 0; i < actconfig->desc.bNumInterfaces; i++) {
-		struct usb_interface *intf;
-		struct usb_driver *driver;
-
-		intf = actconfig->interface[i];
-		if (!intf->dev.driver)
-			continue;
-		driver = to_usb_driver(intf->dev.driver);
-		if (!driver->reset_resume)
-			return 0;
-		/*
-		 * We have at least one driver, and that one
-		 * has a reset_resume method.
-		 */
-		retval = 1;
-	}
-	return retval;
-}
-
-static void hub_restart(struct usb_hub *hub, int type)
+static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
 {
 	struct usb_device *hdev = hub->hdev;
 	int port1;
+	int status;
+	bool need_debounce_delay = false;
 
-	/* Check each of the children to see if they require
-	 * USB-PERSIST handling or disconnection.  Also check
-	 * each unoccupied port to make sure it is still disabled.
+	/* After a resume, port power should still be on.
+	 * For any other type of activation, turn it on.
+	 */
+	if (type != HUB_RESUME)
+		hub_power_on(hub);
+
+	/* Check each port and set hub->change_bits to let khubd know
+	 * which ports need attention.
 	 */
 	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
 		struct usb_device *udev = hdev->children[port1-1];
-		int status = 0;
 		u16 portstatus, portchange;
 
-		if (!udev || udev->state == USB_STATE_NOTATTACHED) {
-			if (type != HUB_RESET) {
-				status = hub_port_status(hub, port1,
-						&portstatus, &portchange);
-				if (status == 0 && (portstatus &
-						USB_PORT_STAT_ENABLE))
-					clear_port_feature(hdev, port1,
-							USB_PORT_FEAT_ENABLE);
-			}
-			continue;
-		}
-
-		/* Was the power session lost while we were suspended? */
+		portstatus = portchange = 0;
 		status = hub_port_status(hub, port1, &portstatus, &portchange);
+		if (udev || (portstatus & USB_PORT_STAT_CONNECTION))
+			dev_dbg(hub->intfdev,
+					"port %d: status %04x change %04x\n",
+					port1, portstatus, portchange);
 
-		/* If the device is gone, khubd will handle it later */
-		if (status == 0 && !(portstatus & USB_PORT_STAT_CONNECTION))
-			continue;
-
-		/* For "USB_PERSIST"-enabled children we must
-		 * mark the child device for reset-resume and
-		 * turn off the various status changes to prevent
-		 * khubd from disconnecting it later.
+		/* After anything other than HUB_RESUME (i.e., initialization
+		 * or any sort of reset), every port should be disabled.
+		 * Unconnected ports should likewise be disabled (paranoia),
+		 * and so should ports for which we have no usb_device.
 		 */
-		if (status == 0 && !(portstatus & USB_PORT_STAT_ENABLE) &&
-				persistent_device(udev)) {
-			if (portchange & USB_PORT_STAT_C_ENABLE)
-				clear_port_feature(hub->hdev, port1,
-						USB_PORT_FEAT_C_ENABLE);
-			if (portchange & USB_PORT_STAT_C_CONNECTION)
-				clear_port_feature(hub->hdev, port1,
-						USB_PORT_FEAT_C_CONNECTION);
-			udev->reset_resume = 1;
+		if ((portstatus & USB_PORT_STAT_ENABLE) && (
+				type != HUB_RESUME ||
+				!(portstatus & USB_PORT_STAT_CONNECTION) ||
+				!udev ||
+				udev->state == USB_STATE_NOTATTACHED)) {
+			clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
+			portstatus &= ~USB_PORT_STAT_ENABLE;
 		}
 
-		/* Otherwise for a reset_resume we must disconnect the child,
-		 * but as we may not lock the child device here
-		 * we have to do a "logical" disconnect.
-		 */
-		else if (type == HUB_RESET_RESUME)
-			hub_port_logical_disconnect(hub, port1);
+		/* Clear status-change flags; we'll debounce later */
+		if (portchange & USB_PORT_STAT_C_CONNECTION) {
+			need_debounce_delay = true;
+			clear_port_feature(hub->hdev, port1,
+					USB_PORT_FEAT_C_CONNECTION);
+		}
+		if (portchange & USB_PORT_STAT_C_ENABLE) {
+			need_debounce_delay = true;
+			clear_port_feature(hub->hdev, port1,
+					USB_PORT_FEAT_C_ENABLE);
+		}
+
+		if (!udev || udev->state == USB_STATE_NOTATTACHED) {
+			/* Tell khubd to disconnect the device or
+			 * check for a new connection
+			 */
+			if (udev || (portstatus & USB_PORT_STAT_CONNECTION))
+				set_bit(port1, hub->change_bits);
+
+		} else if (portstatus & USB_PORT_STAT_ENABLE) {
+			/* The power session apparently survived the resume.
+			 * If there was an overcurrent or suspend change
+			 * (i.e., remote wakeup request), have khubd
+			 * take care of it.
+			 */
+			if (portchange)
+				set_bit(port1, hub->change_bits);
+
+		} else if (udev->persist_enabled) {
+#ifdef CONFIG_PM
+			udev->reset_resume = 1;
+#endif
+			set_bit(port1, hub->change_bits);
+
+		} else {
+			/* The power session is gone; tell khubd */
+			usb_set_device_state(udev, USB_STATE_NOTATTACHED);
+			set_bit(port1, hub->change_bits);
+		}
 	}
 
-	hub_activate(hub);
+	/* If no port-status-change flags were set, we don't need any
+	 * debouncing.  If flags were set we can try to debounce the
+	 * ports all at once right now, instead of letting khubd do them
+	 * one at a time later on.
+	 *
+	 * If any port-status changes do occur during this delay, khubd
+	 * will see them later and handle them normally.
+	 */
+	if (need_debounce_delay)
+		msleep(HUB_DEBOUNCE_STABLE);
+
+	hub->quiescing = 0;
+
+	status = usb_submit_urb(hub->urb, GFP_NOIO);
+	if (status < 0)
+		dev_err(hub->intfdev, "activate --> %d\n", status);
+	if (hub->has_indicators && blinkenlights)
+		schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);
+
+	/* Scan all ports that need attention */
+	kick_khubd(hub);
 }
 
-#endif	/* CONFIG_PM */
+enum hub_quiescing_type {
+	HUB_DISCONNECT, HUB_PRE_RESET, HUB_SUSPEND
+};
+
+static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
+{
+	struct usb_device *hdev = hub->hdev;
+	int i;
+
+	/* khubd and related activity won't re-trigger */
+	hub->quiescing = 1;
+
+	if (type != HUB_SUSPEND) {
+		/* Disconnect all the children */
+		for (i = 0; i < hdev->maxchild; ++i) {
+			if (hdev->children[i])
+				usb_disconnect(&hdev->children[i]);
+		}
+	}
+
+	/* Stop khubd and related activity */
+	usb_kill_urb(hub->urb);
+	if (hub->has_indicators)
+		cancel_delayed_work_sync(&hub->leds);
+	if (hub->tt.hub)
+		cancel_work_sync(&hub->tt.kevent);
+}
 
 /* caller has locked the hub device */
 static int hub_pre_reset(struct usb_interface *intf)
 {
 	struct usb_hub *hub = usb_get_intfdata(intf);
 
-	hub_stop(hub);
+	hub_quiesce(hub, HUB_PRE_RESET);
 	return 0;
 }
 
@@ -762,8 +749,7 @@
 {
 	struct usb_hub *hub = usb_get_intfdata(intf);
 
-	hub_power_on(hub);
-	hub_activate(hub);
+	hub_activate(hub, HUB_POST_RESET);
 	return 0;
 }
 
@@ -1009,8 +995,7 @@
 	if (hub->has_indicators && blinkenlights)
 		hub->indicator [0] = INDICATOR_CYCLE;
 
-	hub_power_on(hub);
-	hub_activate(hub);
+	hub_activate(hub, HUB_INIT);
 	return 0;
 
 fail:
@@ -1042,7 +1027,7 @@
 
 	/* Disconnect all children and quiesce the hub */
 	hub->error = 0;
-	hub_stop(hub);
+	hub_quiesce(hub, HUB_DISCONNECT);
 
 	usb_set_intfdata (intf, NULL);
 
@@ -1068,6 +1053,12 @@
 	desc = intf->cur_altsetting;
 	hdev = interface_to_usbdev(intf);
 
+	if (hdev->level == MAX_TOPO_LEVEL) {
+		dev_err(&intf->dev, "Unsupported bus topology: "
+				"hub nested too deep\n");
+		return -E2BIG;
+	}
+
 #ifdef	CONFIG_USB_OTG_BLACKLIST_HUB
 	if (hdev->parent) {
 		dev_warn(&intf->dev, "ignoring external hub\n");
@@ -1814,6 +1805,51 @@
 
 #ifdef	CONFIG_PM
 
+#define MASK_BITS	(USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION | \
+				USB_PORT_STAT_SUSPEND)
+#define WANT_BITS	(USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION)
+
+/* Determine whether the device on a port is ready for a normal resume,
+ * is ready for a reset-resume, or should be disconnected.
+ */
+static int check_port_resume_type(struct usb_device *udev,
+		struct usb_hub *hub, int port1,
+		int status, unsigned portchange, unsigned portstatus)
+{
+	/* Is the device still present? */
+	if (status || (portstatus & MASK_BITS) != WANT_BITS) {
+		if (status >= 0)
+			status = -ENODEV;
+	}
+
+	/* Can't do a normal resume if the port isn't enabled,
+	 * so try a reset-resume instead.
+	 */
+	else if (!(portstatus & USB_PORT_STAT_ENABLE) && !udev->reset_resume) {
+		if (udev->persist_enabled)
+			udev->reset_resume = 1;
+		else
+			status = -ENODEV;
+	}
+
+	if (status) {
+		dev_dbg(hub->intfdev,
+				"port %d status %04x.%04x after resume, %d\n",
+				port1, portchange, portstatus, status);
+	} else if (udev->reset_resume) {
+
+		/* Late port handoff can set status-change bits */
+		if (portchange & USB_PORT_STAT_C_CONNECTION)
+			clear_port_feature(hub->hdev, port1,
+					USB_PORT_FEAT_C_CONNECTION);
+		if (portchange & USB_PORT_STAT_C_ENABLE)
+			clear_port_feature(hub->hdev, port1,
+					USB_PORT_FEAT_C_ENABLE);
+	}
+
+	return status;
+}
+
 #ifdef	CONFIG_USB_SUSPEND
 
 /*
@@ -1943,7 +1979,8 @@
 	 * resumed.
 	 */
 	if (udev->reset_resume)
-		status = usb_reset_device(udev);
+ retry_reset_resume:
+		status = usb_reset_and_verify_device(udev);
 
  	/* 10.5.4.5 says be sure devices in the tree are still there.
  	 * For now let's assume the device didn't go crazy on resume,
@@ -1954,6 +1991,13 @@
 		status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
 		if (status >= 0)
 			status = (status > 0 ? 0 : -ENODEV);
+
+		/* If a normal resume failed, try doing a reset-resume */
+		if (status && !udev->reset_resume && udev->persist_enabled) {
+			dev_dbg(&udev->dev, "retry with reset-resume\n");
+			udev->reset_resume = 1;
+			goto retry_reset_resume;
+		}
 	}
 
 	if (status) {
@@ -2002,7 +2046,7 @@
  * to it will be lost.  Using the USB_PERSIST facility, the device can be
  * made to appear as if it had not disconnected.
  *
- * This facility can be dangerous.  Although usb_reset_device() makes
+ * This facility can be dangerous.  Although usb_reset_and_verify_device() makes
  * every effort to insure that the same device is present after the
  * reset as before, it cannot provide a 100% guarantee.  Furthermore it's
  * quite possible for a device to remain unaltered but its media to be
@@ -2018,7 +2062,6 @@
 	int		port1 = udev->portnum;
 	int		status;
 	u16		portchange, portstatus;
-	unsigned	mask_flags, want_flags;
 
 	/* Skip the initial Clear-Suspend step for a remote wakeup */
 	status = hub_port_status(hub, port1, &portstatus, &portchange);
@@ -2047,35 +2090,23 @@
 		 */
 		status = hub_port_status(hub, port1, &portstatus, &portchange);
 
- SuspendCleared:
-		if (udev->reset_resume)
-			want_flags = USB_PORT_STAT_POWER
-					| USB_PORT_STAT_CONNECTION;
-		else
-			want_flags = USB_PORT_STAT_POWER
-					| USB_PORT_STAT_CONNECTION
-					| USB_PORT_STAT_ENABLE;
-		mask_flags = want_flags | USB_PORT_STAT_SUSPEND;
+		/* TRSMRCY = 10 msec */
+		msleep(10);
+	}
 
-		if (status < 0 || (portstatus & mask_flags) != want_flags) {
-			dev_dbg(hub->intfdev,
-				"port %d status %04x.%04x after resume, %d\n",
-				port1, portchange, portstatus, status);
-			if (status >= 0)
-				status = -ENODEV;
-		} else {
-			if (portchange & USB_PORT_STAT_C_SUSPEND)
-				clear_port_feature(hub->hdev, port1,
-						USB_PORT_FEAT_C_SUSPEND);
-			/* TRSMRCY = 10 msec */
-			msleep(10);
-		}
+ SuspendCleared:
+	if (status == 0) {
+		if (portchange & USB_PORT_STAT_C_SUSPEND)
+			clear_port_feature(hub->hdev, port1,
+					USB_PORT_FEAT_C_SUSPEND);
 	}
 
 	clear_bit(port1, hub->busy_bits);
 	if (!hub->hdev->parent && !hub->busy_bits[0])
 		usb_enable_root_hub_irq(hub->hdev->bus);
 
+	status = check_port_resume_type(udev,
+			hub, port1, status, portchange, portstatus);
 	if (status == 0)
 		status = finish_port_resume(udev);
 	if (status < 0) {
@@ -2085,17 +2116,16 @@
 	return status;
 }
 
+/* caller has locked udev */
 static int remote_wakeup(struct usb_device *udev)
 {
 	int	status = 0;
 
-	usb_lock_device(udev);
 	if (udev->state == USB_STATE_SUSPENDED) {
 		dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
 		usb_mark_last_busy(udev);
 		status = usb_external_resume_device(udev);
 	}
-	usb_unlock_device(udev);
 	return status;
 }
 
@@ -2108,14 +2138,25 @@
 	return 0;
 }
 
+/* However we may need to do a reset-resume */
+
 int usb_port_resume(struct usb_device *udev)
 {
-	int status = 0;
+	struct usb_hub	*hub = hdev_to_hub(udev->parent);
+	int		port1 = udev->portnum;
+	int		status;
+	u16		portchange, portstatus;
 
-	/* However we may need to do a reset-resume */
-	if (udev->reset_resume) {
+	status = hub_port_status(hub, port1, &portstatus, &portchange);
+	status = check_port_resume_type(udev,
+			hub, port1, status, portchange, portstatus);
+
+	if (status) {
+		dev_dbg(&udev->dev, "can't resume, status %d\n", status);
+		hub_port_logical_disconnect(hub, port1);
+	} else if (udev->reset_resume) {
 		dev_dbg(&udev->dev, "reset-resume\n");
-		status = usb_reset_device(udev);
+		status = usb_reset_and_verify_device(udev);
 	}
 	return status;
 }
@@ -2149,7 +2190,7 @@
 	dev_dbg(&intf->dev, "%s\n", __func__);
 
 	/* stop khubd and related activity */
-	hub_quiesce(hub);
+	hub_quiesce(hub, HUB_SUSPEND);
 	return 0;
 }
 
@@ -2158,7 +2199,7 @@
 	struct usb_hub *hub = usb_get_intfdata(intf);
 
 	dev_dbg(&intf->dev, "%s\n", __func__);
-	hub_restart(hub, HUB_RESUME);
+	hub_activate(hub, HUB_RESUME);
 	return 0;
 }
 
@@ -2167,8 +2208,7 @@
 	struct usb_hub *hub = usb_get_intfdata(intf);
 
 	dev_dbg(&intf->dev, "%s\n", __func__);
-	hub_power_on(hub);
-	hub_restart(hub, HUB_RESET_RESUME);
+	hub_activate(hub, HUB_RESET_RESUME);
 	return 0;
 }
 
@@ -2218,11 +2258,6 @@
  * every 25ms for transient disconnects.  When the port status has been
  * unchanged for 100ms it returns the port status.
  */
-
-#define HUB_DEBOUNCE_TIMEOUT	1500
-#define HUB_DEBOUNCE_STEP	  25
-#define HUB_DEBOUNCE_STABLE	 100
-
 static int hub_port_debounce(struct usb_hub *hub, int port1)
 {
 	int ret;
@@ -2302,7 +2337,7 @@
  * Returns device in USB_STATE_ADDRESS, except on error.
  *
  * If this is called for an already-existing device (as part of
- * usb_reset_device), the caller must own the device lock.  For a
+ * usb_reset_and_verify_device), the caller must own the device lock.  For a
  * newly detected device that is not accessible through any global
  * pointers, it's not necessary to lock the device.
  */
@@ -2619,7 +2654,7 @@
  * This routine is called when:
  * 	a port connection-change occurs;
  *	a port enable-change occurs (often caused by EMI);
- *	usb_reset_device() encounters changed descriptors (as from
+ *	usb_reset_and_verify_device() encounters changed descriptors (as from
  *		a firmware download)
  * caller already locked the hub
  */
@@ -2629,9 +2664,11 @@
 	struct usb_device *hdev = hub->hdev;
 	struct device *hub_dev = hub->intfdev;
 	struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
-	u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
+	unsigned wHubCharacteristics =
+			le16_to_cpu(hub->descriptor->wHubCharacteristics);
+	struct usb_device *udev;
 	int status, i;
- 
+
 	dev_dbg (hub_dev,
 		"port %d, status %04x, change %04x, %s\n",
 		port1, portstatus, portchange, portspeed (portstatus));
@@ -2640,30 +2677,73 @@
 		set_port_led(hub, port1, HUB_LED_AUTO);
 		hub->indicator[port1-1] = INDICATOR_AUTO;
 	}
- 
-	/* Disconnect any existing devices under this port */
-	if (hdev->children[port1-1])
-		usb_disconnect(&hdev->children[port1-1]);
-	clear_bit(port1, hub->change_bits);
 
 #ifdef	CONFIG_USB_OTG
 	/* during HNP, don't repeat the debounce */
 	if (hdev->bus->is_b_host)
-		portchange &= ~USB_PORT_STAT_C_CONNECTION;
+		portchange &= ~(USB_PORT_STAT_C_CONNECTION |
+				USB_PORT_STAT_C_ENABLE);
 #endif
 
-	if (portchange & USB_PORT_STAT_C_CONNECTION) {
+	/* Try to use the debounce delay for protection against
+	 * port-enable changes caused, for example, by EMI.
+	 */
+	if (portchange & (USB_PORT_STAT_C_CONNECTION |
+				USB_PORT_STAT_C_ENABLE)) {
 		status = hub_port_debounce(hub, port1);
 		if (status < 0) {
 			if (printk_ratelimit())
 				dev_err (hub_dev, "connect-debounce failed, "
 						"port %d disabled\n", port1);
-			goto done;
+			portstatus &= ~USB_PORT_STAT_CONNECTION;
+		} else {
+			portstatus = status;
 		}
-		portstatus = status;
 	}
 
-	/* Return now if nothing is connected */
+	/* Try to resuscitate an existing device */
+	udev = hdev->children[port1-1];
+	if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&
+			udev->state != USB_STATE_NOTATTACHED) {
+
+		usb_lock_device(udev);
+		if (portstatus & USB_PORT_STAT_ENABLE) {
+			status = 0;		/* Nothing to do */
+		} else if (!udev->persist_enabled) {
+			status = -ENODEV;	/* Mustn't resuscitate */
+
+#ifdef CONFIG_USB_SUSPEND
+		} else if (udev->state == USB_STATE_SUSPENDED) {
+			/* For a suspended device, treat this as a
+			 * remote wakeup event.
+			 */
+			if (udev->do_remote_wakeup)
+				status = remote_wakeup(udev);
+
+			/* Otherwise leave it be; devices can't tell the
+			 * difference between suspended and disabled.
+			 */
+			else
+				status = 0;
+#endif
+
+		} else {
+			status = usb_reset_device(udev);
+		}
+		usb_unlock_device(udev);
+
+		if (status == 0) {
+			clear_bit(port1, hub->change_bits);
+			return;
+		}
+	}
+
+	/* Disconnect any existing devices under this port */
+	if (udev)
+		usb_disconnect(&hdev->children[port1-1]);
+	clear_bit(port1, hub->change_bits);
+
+	/* Return now if debouncing failed or nothing is connected */
 	if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
 
 		/* maybe switch power back on (e.g. root hub was reset) */
@@ -2677,7 +2757,6 @@
 	}
 
 	for (i = 0; i < SET_CONFIG_TRIES; i++) {
-		struct usb_device *udev;
 
 		/* reallocate for each attempt, since references
 		 * to the previous one can escape in various ways
@@ -2858,7 +2937,7 @@
 		/* If the hub has died, clean up after it */
 		if (hdev->state == USB_STATE_NOTATTACHED) {
 			hub->error = -ENODEV;
-			hub_stop(hub);
+			hub_quiesce(hub, HUB_DISCONNECT);
 			goto loop;
 		}
 
@@ -2877,7 +2956,7 @@
 			dev_dbg (hub_dev, "resetting for error %d\n",
 				hub->error);
 
-			ret = usb_reset_composite_device(hdev, intf);
+			ret = usb_reset_device(hdev);
 			if (ret) {
 				dev_dbg (hub_dev,
 					"error resetting hub: %d\n", ret);
@@ -2894,7 +2973,7 @@
 				continue;
 			connect_change = test_bit(i, hub->change_bits);
 			if (!test_and_clear_bit(i, hub->event_bits) &&
-					!connect_change && !hub->activating)
+					!connect_change)
 				continue;
 
 			ret = hub_port_status(hub, i,
@@ -2902,11 +2981,6 @@
 			if (ret < 0)
 				continue;
 
-			if (hub->activating && !hdev->children[i-1] &&
-					(portstatus &
-						USB_PORT_STAT_CONNECTION))
-				connect_change = 1;
-
 			if (portchange & USB_PORT_STAT_C_CONNECTION) {
 				clear_port_feature(hdev, i,
 					USB_PORT_FEAT_C_CONNECTION);
@@ -2941,11 +3015,16 @@
 			}
 
 			if (portchange & USB_PORT_STAT_C_SUSPEND) {
+				struct usb_device *udev;
+
 				clear_port_feature(hdev, i,
 					USB_PORT_FEAT_C_SUSPEND);
-				if (hdev->children[i-1]) {
+				udev = hdev->children[i-1];
+				if (udev) {
+					usb_lock_device(udev);
 					ret = remote_wakeup(hdev->
 							children[i-1]);
+					usb_unlock_device(udev);
 					if (ret < 0)
 						connect_change = 1;
 				} else {
@@ -3002,8 +3081,6 @@
 			}
 		}
 
-		hub->activating = 0;
-
 		/* If this is a root hub, tell the HCD it's okay to
 		 * re-enable port-change interrupts now. */
 		if (!hdev->parent && !hub->busy_bits[0])
@@ -3172,12 +3249,12 @@
 }
 
 /**
- * usb_reset_device - perform a USB port reset to reinitialize a device
+ * usb_reset_and_verify_device - perform a USB port reset to reinitialize a device
  * @udev: device to reset (not in SUSPENDED or NOTATTACHED state)
  *
  * WARNING - don't use this routine to reset a composite device
  * (one with multiple interfaces owned by separate drivers)!
- * Use usb_reset_composite_device() instead.
+ * Use usb_reset_device() instead.
  *
  * Do a port reset, reassign the device's address, and establish its
  * former operating configuration.  If the reset fails, or the device's
@@ -3201,7 +3278,7 @@
  * holding the device lock because these tasks should always call
  * usb_autopm_resume_device(), thereby preventing any unwanted autoresume.
  */
-int usb_reset_device(struct usb_device *udev)
+static int usb_reset_and_verify_device(struct usb_device *udev)
 {
 	struct usb_device		*parent_hdev = udev->parent;
 	struct usb_hub			*parent_hub;
@@ -3289,26 +3366,28 @@
 	hub_port_logical_disconnect(parent_hub, port1);
 	return -ENODEV;
 }
-EXPORT_SYMBOL_GPL(usb_reset_device);
 
 /**
- * usb_reset_composite_device - warn interface drivers and perform a USB port reset
+ * usb_reset_device - warn interface drivers and perform a USB port reset
  * @udev: device to reset (not in SUSPENDED or NOTATTACHED state)
- * @iface: interface bound to the driver making the request (optional)
  *
  * Warns all drivers bound to registered interfaces (using their pre_reset
  * method), performs the port reset, and then lets the drivers know that
  * the reset is over (using their post_reset method).
  *
- * Return value is the same as for usb_reset_device().
+ * Return value is the same as for usb_reset_and_verify_device().
  *
  * The caller must own the device lock.  For example, it's safe to use
  * this from a driver probe() routine after downloading new firmware.
  * For calls that might not occur during probe(), drivers should lock
  * the device using usb_lock_device_for_reset().
+ *
+ * If an interface is currently being probed or disconnected, we assume
+ * its driver knows how to handle resets.  For all other interfaces,
+ * if the driver doesn't have pre_reset and post_reset methods then
+ * we attempt to unbind it and rebind afterward.
  */
-int usb_reset_composite_device(struct usb_device *udev,
-		struct usb_interface *iface)
+int usb_reset_device(struct usb_device *udev)
 {
 	int ret;
 	int i;
@@ -3324,40 +3403,47 @@
 	/* Prevent autosuspend during the reset */
 	usb_autoresume_device(udev);
 
-	if (iface && iface->condition != USB_INTERFACE_BINDING)
-		iface = NULL;
-
 	if (config) {
 		for (i = 0; i < config->desc.bNumInterfaces; ++i) {
 			struct usb_interface *cintf = config->interface[i];
 			struct usb_driver *drv;
+			int unbind = 0;
 
 			if (cintf->dev.driver) {
 				drv = to_usb_driver(cintf->dev.driver);
-				if (drv->pre_reset)
-					(drv->pre_reset)(cintf);
-	/* FIXME: Unbind if pre_reset returns an error or isn't defined */
+				if (drv->pre_reset && drv->post_reset)
+					unbind = (drv->pre_reset)(cintf);
+				else if (cintf->condition ==
+						USB_INTERFACE_BOUND)
+					unbind = 1;
+				if (unbind)
+					usb_forced_unbind_intf(cintf);
 			}
 		}
 	}
 
-	ret = usb_reset_device(udev);
+	ret = usb_reset_and_verify_device(udev);
 
 	if (config) {
 		for (i = config->desc.bNumInterfaces - 1; i >= 0; --i) {
 			struct usb_interface *cintf = config->interface[i];
 			struct usb_driver *drv;
+			int rebind = cintf->needs_binding;
 
-			if (cintf->dev.driver) {
+			if (!rebind && cintf->dev.driver) {
 				drv = to_usb_driver(cintf->dev.driver);
 				if (drv->post_reset)
-					(drv->post_reset)(cintf);
-	/* FIXME: Unbind if post_reset returns an error or isn't defined */
+					rebind = (drv->post_reset)(cintf);
+				else if (cintf->condition ==
+						USB_INTERFACE_BOUND)
+					rebind = 1;
 			}
+			if (rebind)
+				usb_rebind_intf(cintf);
 		}
 	}
 
 	usb_autosuspend_device(udev);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(usb_reset_composite_device);
+EXPORT_SYMBOL_GPL(usb_reset_device);
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index 1d253dd..db410e9 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -712,25 +712,11 @@
 
 static void usbfs_remove_device(struct usb_device *dev)
 {
-	struct dev_state *ds;
-	struct siginfo sinfo;
-
 	if (dev->usbfs_dentry) {
 		fs_remove_file (dev->usbfs_dentry);
 		dev->usbfs_dentry = NULL;
 	}
-	while (!list_empty(&dev->filelist)) {
-		ds = list_entry(dev->filelist.next, struct dev_state, list);
-		wake_up_all(&ds->wait);
-		list_del_init(&ds->list);
-		if (ds->discsignr) {
-			sinfo.si_signo = ds->discsignr;
-			sinfo.si_errno = EPIPE;
-			sinfo.si_code = SI_ASYNCIO;
-			sinfo.si_addr = ds->disccontext;
-			kill_pid_info_as_uid(ds->discsignr, &sinfo, ds->disc_pid, ds->disc_uid, ds->disc_euid, ds->secid);
-		}
-	}
+	usb_fs_classdev_common_remove(dev);
 }
 
 static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev)
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index fe47d14..2fcc06e 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -400,7 +400,7 @@
 	if (usb_pipein(pipe))
 		urb_flags |= URB_SHORT_NOT_OK;
 
-	for (i = 0; i < io->entries; i++) {
+	for_each_sg(sg, sg, io->entries, i) {
 		unsigned len;
 
 		io->urbs[i] = usb_alloc_urb(0, mem_flags);
@@ -434,17 +434,17 @@
 		 * to prevent stale pointers and to help spot bugs.
 		 */
 		if (dma) {
-			io->urbs[i]->transfer_dma = sg_dma_address(sg + i);
-			len = sg_dma_len(sg + i);
+			io->urbs[i]->transfer_dma = sg_dma_address(sg);
+			len = sg_dma_len(sg);
 #if defined(CONFIG_HIGHMEM) || defined(CONFIG_GART_IOMMU)
 			io->urbs[i]->transfer_buffer = NULL;
 #else
-			io->urbs[i]->transfer_buffer = sg_virt(&sg[i]);
+			io->urbs[i]->transfer_buffer = sg_virt(sg);
 #endif
 		} else {
 			/* hc may use _only_ transfer_buffer */
-			io->urbs[i]->transfer_buffer = sg_virt(&sg[i]);
-			len = sg[i].length;
+			io->urbs[i]->transfer_buffer = sg_virt(sg);
+			len = sg->length;
 		}
 
 		if (length) {
@@ -1090,7 +1090,7 @@
 			if (!device_is_registered(&interface->dev))
 				continue;
 			dev_dbg(&dev->dev, "unregistering interface %s\n",
-				interface->dev.bus_id);
+				dev_name(&interface->dev));
 			device_del(&interface->dev);
 			usb_remove_sysfs_intf_files(interface);
 		}
@@ -1476,7 +1476,7 @@
  *
  * This call is synchronous. The calling context must be able to sleep,
  * must own the device lock, and must not hold the driver model's USB
- * bus mutex; usb device driver probe() methods cannot use this routine.
+ * bus mutex; usb interface driver probe() methods cannot use this routine.
  *
  * Returns zero on success, or else the status code returned by the
  * underlying call that failed.  On successful completion, each interface
@@ -1611,7 +1611,7 @@
 		intf->dev.dma_mask = dev->dev.dma_mask;
 		device_initialize(&intf->dev);
 		mark_quiesced(intf);
-		sprintf(&intf->dev.bus_id[0], "%d-%s:%d.%d",
+		dev_set_name(&intf->dev, "%d-%s:%d.%d",
 			dev->bus->busnum, dev->devpath,
 			configuration, alt->desc.bInterfaceNumber);
 	}
@@ -1631,12 +1631,12 @@
 
 		dev_dbg(&dev->dev,
 			"adding %s (config #%d, interface %d)\n",
-			intf->dev.bus_id, configuration,
+			dev_name(&intf->dev), configuration,
 			intf->cur_altsetting->desc.bInterfaceNumber);
 		ret = device_add(&intf->dev);
 		if (ret != 0) {
 			dev_err(&dev->dev, "device_add(%s) --> %d\n",
-				intf->dev.bus_id, ret);
+				dev_name(&intf->dev), ret);
 			continue;
 		}
 		usb_create_sysfs_intf_files(intf);
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 3257743..84fcaa6 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -308,7 +308,7 @@
 	 * by location for diagnostics, tools, driver model, etc.  The
 	 * string is a path along hub ports, from the root.  Each device's
 	 * dev->devpath will be stable until USB is re-cabled, and hubs
-	 * are often labeled with these port numbers.  The bus_id isn't
+	 * are often labeled with these port numbers.  The name isn't
 	 * as stable:  bus->busnum changes easily from modprobe order,
 	 * cardbus or pci hotplugging, and so on.
 	 */
@@ -316,7 +316,7 @@
 		dev->devpath[0] = '0';
 
 		dev->dev.parent = bus->controller;
-		sprintf(&dev->dev.bus_id[0], "usb%d", bus->busnum);
+		dev_set_name(&dev->dev, "usb%d", bus->busnum);
 		root_hub = 1;
 	} else {
 		/* match any labeling on the hubs; it's one-based */
@@ -328,8 +328,7 @@
 				"%s.%d", parent->devpath, port1);
 
 		dev->dev.parent = &parent->dev;
-		sprintf(&dev->dev.bus_id[0], "%d-%s",
-			bus->busnum, dev->devpath);
+		dev_set_name(&dev->dev, "%d-%s", bus->busnum, dev->devpath);
 
 		/* hub driver sets up TT records */
 	}
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 1a8bc21..d9a6e16 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -29,6 +29,8 @@
 extern void usb_kick_khubd(struct usb_device *dev);
 extern int usb_match_device(struct usb_device *dev,
 			    const struct usb_device_id *id);
+extern void usb_forced_unbind_intf(struct usb_interface *intf);
+extern void usb_rebind_intf(struct usb_interface *intf);
 
 extern int  usb_hub_init(void);
 extern void usb_hub_cleanup(void);
@@ -140,26 +142,11 @@
 extern const struct file_operations usbfs_devices_fops;
 extern const struct file_operations usbdev_file_operations;
 extern void usbfs_conn_disc_event(void);
+extern void usb_fs_classdev_common_remove(struct usb_device *udev);
 
 extern int usb_devio_init(void);
 extern void usb_devio_cleanup(void);
 
-struct dev_state {
-	struct list_head list;      /* state list */
-	struct usb_device *dev;
-	struct file *file;
-	spinlock_t lock;            /* protects the async urb lists */
-	struct list_head async_pending;
-	struct list_head async_completed;
-	wait_queue_head_t wait;     /* wake up if a request completed */
-	unsigned int discsignr;
-	struct pid *disc_pid;
-	uid_t disc_uid, disc_euid;
-	void __user *disccontext;
-	unsigned long ifclaimed;
-	u32 secid;
-};
-
 /* internal notify stuff */
 extern void usb_notify_add_device(struct usb_device *udev);
 extern void usb_notify_remove_device(struct usb_device *udev);
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index d6bab0d..c6a8c6b 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -586,6 +586,20 @@
 	  For more information, see Documentation/usb/gadget_printer.txt
 	  which includes sample code for accessing the device file.
 
+config USB_CDC_COMPOSITE
+	tristate "CDC Composite Device (Ethernet and ACM)"
+	depends on NET
+	help
+	  This driver provides two functions in one configuration:
+	  a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link.
+
+	  This driver requires four bulk and two interrupt endpoints,
+	  plus the ability to handle altsettings.  Not all peripheral
+	  controllers are that capable.
+
+	  Say "y" to link the driver statically, or "m" to build a
+	  dynamically linked module.
+
 # 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 e258afd..fcb5cb9 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -22,18 +22,22 @@
 #
 # USB gadget drivers
 #
-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
+C_UTILS =	composite.o usbstring.o config.o epautoconf.o
+
+g_zero-objs			:= zero.o f_sourcesink.o f_loopback.o $(C_UTILS)
+g_ether-objs			:= ether.o u_ether.o f_subset.o f_ecm.o $(C_UTILS)
+g_serial-objs			:= serial.o u_serial.o f_acm.o f_serial.o $(C_UTILS)
 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
 g_printer-objs			:= printer.o usbstring.o config.o \
 					epautoconf.o
+g_cdc-objs			:= cdc2.o u_ether.o f_ecm.o \
+					u_serial.o f_acm.o $(C_UTILS)
 
 ifeq ($(CONFIG_USB_ETH_RNDIS),y)
-	g_ether-objs		+= rndis.o
+	g_ether-objs		+= f_rndis.o rndis.o
 endif
  
 obj-$(CONFIG_USB_ZERO)		+= g_zero.o
@@ -43,4 +47,5 @@
 obj-$(CONFIG_USB_G_SERIAL)	+= g_serial.o
 obj-$(CONFIG_USB_G_PRINTER)	+= g_printer.o
 obj-$(CONFIG_USB_MIDI_GADGET)	+= g_midi.o
+obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc.o
 
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index f261d2a..1500e1b 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -3342,7 +3342,7 @@
 	spin_lock_init(&dev->lock);
 	dev->gadget.ops = &udc_ops;
 
-	strcpy(dev->gadget.dev.bus_id, "gadget");
+	dev_set_name(&dev->gadget.dev, "gadget");
 	dev->gadget.dev.release = gadget_release;
 	dev->gadget.name = name;
 	dev->gadget.name = name;
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index b6b2a0a..e2d8a5d 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -1687,6 +1687,19 @@
 				udc->board.pullup_active_low);
 	}
 
+	/* newer chips have more FIFO memory than rm9200 */
+	if (cpu_is_at91sam9260()) {
+		udc->ep[0].maxpacket = 64;
+		udc->ep[3].maxpacket = 64;
+		udc->ep[4].maxpacket = 512;
+		udc->ep[5].maxpacket = 512;
+	} else if (cpu_is_at91sam9261()) {
+		udc->ep[3].maxpacket = 64;
+	} else if (cpu_is_at91sam9263()) {
+		udc->ep[0].maxpacket = 64;
+		udc->ep[3].maxpacket = 64;
+	}
+
 	udc->udp_baseaddr = ioremap(res->start, res->end - res->start + 1);
 	if (!udc->udp_baseaddr) {
 		retval = -ENOMEM;
diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c
new file mode 100644
index 0000000..d490d02
--- /dev/null
+++ b/drivers/usb/gadget/cdc2.c
@@ -0,0 +1,246 @@
+/*
+ * cdc2.c -- CDC Composite driver, with ECM and ACM support
+ *
+ * Copyright (C) 2008 David Brownell
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/utsname.h>
+
+#include "u_ether.h"
+#include "u_serial.h"
+
+
+#define DRIVER_DESC		"CDC Composite Gadget"
+#define DRIVER_VERSION		"King Kamehameha Day 2008"
+
+/*-------------------------------------------------------------------------*/
+
+/* DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
+ * Instead:  allocate your own, using normal USB-IF procedures.
+ */
+
+/* Thanks to NetChip Technologies for donating this product ID.
+ * It's for devices with only this composite CDC configuration.
+ */
+#define CDC_VENDOR_NUM		0x0525	/* NetChip */
+#define CDC_PRODUCT_NUM		0xa4aa	/* CDC Composite: ECM + ACM */
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_device_descriptor device_desc = {
+	.bLength =		sizeof device_desc,
+	.bDescriptorType =	USB_DT_DEVICE,
+
+	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+
+	.bDeviceClass =		USB_CLASS_COMM,
+	.bDeviceSubClass =	0,
+	.bDeviceProtocol =	0,
+	/* .bMaxPacketSize0 = f(hardware) */
+
+	/* Vendor and product id can be overridden by module parameters.  */
+	.idVendor =		__constant_cpu_to_le16(CDC_VENDOR_NUM),
+	.idProduct =		__constant_cpu_to_le16(CDC_PRODUCT_NUM),
+	/* .bcdDevice = f(hardware) */
+	/* .iManufacturer = DYNAMIC */
+	/* .iProduct = DYNAMIC */
+	/* NO SERIAL NUMBER */
+	.bNumConfigurations =	1,
+};
+
+static struct usb_otg_descriptor otg_descriptor = {
+	.bLength =		sizeof otg_descriptor,
+	.bDescriptorType =	USB_DT_OTG,
+
+	/* REVISIT SRP-only hardware is possible, although
+	 * it would not be called "OTG" ...
+	 */
+	.bmAttributes =		USB_OTG_SRP | USB_OTG_HNP,
+};
+
+static const struct usb_descriptor_header *otg_desc[] = {
+	(struct usb_descriptor_header *) &otg_descriptor,
+	NULL,
+};
+
+
+/* string IDs are assigned dynamically */
+
+#define STRING_MANUFACTURER_IDX		0
+#define STRING_PRODUCT_IDX		1
+
+static char manufacturer[50];
+
+static struct usb_string strings_dev[] = {
+	[STRING_MANUFACTURER_IDX].s = manufacturer,
+	[STRING_PRODUCT_IDX].s = DRIVER_DESC,
+	{  } /* end of list */
+};
+
+static struct usb_gadget_strings stringtab_dev = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= strings_dev,
+};
+
+static struct usb_gadget_strings *dev_strings[] = {
+	&stringtab_dev,
+	NULL,
+};
+
+static u8 hostaddr[ETH_ALEN];
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * We _always_ have both CDC ECM and CDC ACM functions.
+ */
+static int __init cdc_do_config(struct usb_configuration *c)
+{
+	int	status;
+
+	if (gadget_is_otg(c->cdev->gadget)) {
+		c->descriptors = otg_desc;
+		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+	}
+
+	status = ecm_bind_config(c, hostaddr);
+	if (status < 0)
+		return status;
+
+	status = acm_bind_config(c, 0);
+	if (status < 0)
+		return status;
+
+	return 0;
+}
+
+static struct usb_configuration cdc_config_driver = {
+	.label			= "CDC Composite (ECM + ACM)",
+	.bind			= cdc_do_config,
+	.bConfigurationValue	= 1,
+	/* .iConfiguration = DYNAMIC */
+	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower		= 1,	/* 2 mA, minimal */
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int __init cdc_bind(struct usb_composite_dev *cdev)
+{
+	int			gcnum;
+	struct usb_gadget	*gadget = cdev->gadget;
+	int			status;
+
+	if (!can_support_ecm(cdev->gadget)) {
+		ERROR(cdev, "controller '%s' not usable\n", gadget->name);
+		return -EINVAL;
+	}
+
+	/* set up network link layer */
+	status = gether_setup(cdev->gadget, hostaddr);
+	if (status < 0)
+		return status;
+
+	/* set up serial link layer */
+	status = gserial_setup(cdev->gadget, 1);
+	if (status < 0)
+		goto fail0;
+
+	gcnum = usb_gadget_controller_number(gadget);
+	if (gcnum >= 0)
+		device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);
+	else {
+		/* We assume that can_support_ecm() tells the truth;
+		 * but if the controller isn't recognized at all then
+		 * that assumption is a bit more likely to be wrong.
+		 */
+		WARN(cdev, "controller '%s' not recognized; trying %s\n",
+				gadget->name,
+				cdc_config_driver.label);
+		device_desc.bcdDevice =
+			__constant_cpu_to_le16(0x0300 | 0x0099);
+	}
+
+
+	/* Allocate string descriptor numbers ... note that string
+	 * contents can be overridden by the composite_dev glue.
+	 */
+
+	/* device descriptor strings: manufacturer, product */
+	snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
+		init_utsname()->sysname, init_utsname()->release,
+		gadget->name);
+	status = usb_string_id(cdev);
+	if (status < 0)
+		goto fail1;
+	strings_dev[STRING_MANUFACTURER_IDX].id = status;
+	device_desc.iManufacturer = status;
+
+	status = usb_string_id(cdev);
+	if (status < 0)
+		goto fail1;
+	strings_dev[STRING_PRODUCT_IDX].id = status;
+	device_desc.iProduct = status;
+
+	/* register our configuration */
+	status = usb_add_config(cdev, &cdc_config_driver);
+	if (status < 0)
+		goto fail1;
+
+	INFO(cdev, "%s, version: " DRIVER_VERSION "\n", DRIVER_DESC);
+
+	return 0;
+
+fail1:
+	gserial_cleanup();
+fail0:
+	gether_cleanup();
+	return status;
+}
+
+static int __exit cdc_unbind(struct usb_composite_dev *cdev)
+{
+	gserial_cleanup();
+	gether_cleanup();
+	return 0;
+}
+
+static struct usb_composite_driver cdc_driver = {
+	.name		= "g_cdc",
+	.dev		= &device_desc,
+	.strings	= dev_strings,
+	.bind		= cdc_bind,
+	.unbind		= __exit_p(cdc_unbind),
+};
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("David Brownell");
+MODULE_LICENSE("GPL");
+
+static int __init init(void)
+{
+	return usb_composite_register(&cdc_driver);
+}
+module_init(init);
+
+static void __exit cleanup(void)
+{
+	usb_composite_unregister(&cdc_driver);
+}
+module_exit(cleanup);
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
new file mode 100644
index 0000000..85c876c
--- /dev/null
+++ b/drivers/usb/gadget/composite.c
@@ -0,0 +1,1041 @@
+/*
+ * composite.c - infrastructure for Composite USB Gadgets
+ *
+ * Copyright (C) 2006-2008 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 option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kallsyms.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+
+#include <linux/usb/composite.h>
+
+
+/*
+ * The code in this file is utility code, used to build a gadget driver
+ * from one or more "function" drivers, one or more "configuration"
+ * objects, and a "usb_composite_driver" by gluing them together along
+ * with the relevant device-wide data.
+ */
+
+/* big enough to hold our biggest descriptor */
+#define USB_BUFSIZ	512
+
+static struct usb_composite_driver *composite;
+
+/* Some systems will need runtime overrides for the  product identifers
+ * published in the device descriptor, either numbers or strings or both.
+ * String parameters are in UTF-8 (superset of ASCII's 7 bit characters).
+ */
+
+static ushort idVendor;
+module_param(idVendor, ushort, 0);
+MODULE_PARM_DESC(idVendor, "USB Vendor ID");
+
+static ushort idProduct;
+module_param(idProduct, ushort, 0);
+MODULE_PARM_DESC(idProduct, "USB Product ID");
+
+static ushort bcdDevice;
+module_param(bcdDevice, ushort, 0);
+MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
+
+static char *iManufacturer;
+module_param(iManufacturer, charp, 0);
+MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
+
+static char *iProduct;
+module_param(iProduct, charp, 0);
+MODULE_PARM_DESC(iProduct, "USB Product string");
+
+static char *iSerialNumber;
+module_param(iSerialNumber, charp, 0);
+MODULE_PARM_DESC(iSerialNumber, "SerialNumber string");
+
+/*-------------------------------------------------------------------------*/
+
+/**
+ * usb_add_function() - add a function to a configuration
+ * @config: the configuration
+ * @function: the function being added
+ * Context: single threaded during gadget setup
+ *
+ * After initialization, each configuration must have one or more
+ * functions added to it.  Adding a function involves calling its @bind()
+ * method to allocate resources such as interface and string identifiers
+ * and endpoints.
+ *
+ * This function returns the value of the function's bind(), which is
+ * zero for success else a negative errno value.
+ */
+int __init usb_add_function(struct usb_configuration *config,
+		struct usb_function *function)
+{
+	int	value = -EINVAL;
+
+	DBG(config->cdev, "adding '%s'/%p to config '%s'/%p\n",
+			function->name, function,
+			config->label, config);
+
+	if (!function->set_alt || !function->disable)
+		goto done;
+
+	function->config = config;
+	list_add_tail(&function->list, &config->functions);
+
+	/* REVISIT *require* function->bind? */
+	if (function->bind) {
+		value = function->bind(config, function);
+		if (value < 0) {
+			list_del(&function->list);
+			function->config = NULL;
+		}
+	} else
+		value = 0;
+
+	/* We allow configurations that don't work at both speeds.
+	 * If we run into a lowspeed Linux system, treat it the same
+	 * as full speed ... it's the function drivers that will need
+	 * to avoid bulk and ISO transfers.
+	 */
+	if (!config->fullspeed && function->descriptors)
+		config->fullspeed = true;
+	if (!config->highspeed && function->hs_descriptors)
+		config->highspeed = true;
+
+done:
+	if (value)
+		DBG(config->cdev, "adding '%s'/%p --> %d\n",
+				function->name, function, value);
+	return value;
+}
+
+/**
+ * usb_interface_id() - allocate an unused interface ID
+ * @config: configuration associated with the interface
+ * @function: function handling the interface
+ * Context: single threaded during gadget setup
+ *
+ * usb_interface_id() is called from usb_function.bind() callbacks to
+ * allocate new interface IDs.  The function driver will then store that
+ * ID in interface, association, CDC union, and other descriptors.  It
+ * will also handle any control requests targetted at that interface,
+ * particularly changing its altsetting via set_alt().  There may
+ * also be class-specific or vendor-specific requests to handle.
+ *
+ * All interface identifier should be allocated using this routine, to
+ * ensure that for example different functions don't wrongly assign
+ * different meanings to the same identifier.  Note that since interface
+ * identifers are configuration-specific, functions used in more than
+ * one configuration (or more than once in a given configuration) need
+ * multiple versions of the relevant descriptors.
+ *
+ * Returns the interface ID which was allocated; or -ENODEV if no
+ * more interface IDs can be allocated.
+ */
+int __init usb_interface_id(struct usb_configuration *config,
+		struct usb_function *function)
+{
+	unsigned id = config->next_interface_id;
+
+	if (id < MAX_CONFIG_INTERFACES) {
+		config->interface[id] = function;
+		config->next_interface_id = id + 1;
+		return id;
+	}
+	return -ENODEV;
+}
+
+static int config_buf(struct usb_configuration *config,
+		enum usb_device_speed speed, void *buf, u8 type)
+{
+	struct usb_config_descriptor	*c = buf;
+	void				*next = buf + USB_DT_CONFIG_SIZE;
+	int				len = USB_BUFSIZ - USB_DT_CONFIG_SIZE;
+	struct usb_function		*f;
+	int				status;
+
+	/* write the config descriptor */
+	c = buf;
+	c->bLength = USB_DT_CONFIG_SIZE;
+	c->bDescriptorType = type;
+	/* wTotalLength is written later */
+	c->bNumInterfaces = config->next_interface_id;
+	c->bConfigurationValue = config->bConfigurationValue;
+	c->iConfiguration = config->iConfiguration;
+	c->bmAttributes = USB_CONFIG_ATT_ONE | config->bmAttributes;
+	c->bMaxPower = config->bMaxPower;
+
+	/* There may be e.g. OTG descriptors */
+	if (config->descriptors) {
+		status = usb_descriptor_fillbuf(next, len,
+				config->descriptors);
+		if (status < 0)
+			return status;
+		len -= status;
+		next += status;
+	}
+
+	/* add each function's descriptors */
+	list_for_each_entry(f, &config->functions, list) {
+		struct usb_descriptor_header **descriptors;
+
+		if (speed == USB_SPEED_HIGH)
+			descriptors = f->hs_descriptors;
+		else
+			descriptors = f->descriptors;
+		if (!descriptors)
+			continue;
+		status = usb_descriptor_fillbuf(next, len,
+			(const struct usb_descriptor_header **) descriptors);
+		if (status < 0)
+			return status;
+		len -= status;
+		next += status;
+	}
+
+	len = next - buf;
+	c->wTotalLength = cpu_to_le16(len);
+	return len;
+}
+
+static int config_desc(struct usb_composite_dev *cdev, unsigned w_value)
+{
+	struct usb_gadget		*gadget = cdev->gadget;
+	struct usb_configuration	*c;
+	u8				type = w_value >> 8;
+	enum usb_device_speed		speed = USB_SPEED_UNKNOWN;
+
+	if (gadget_is_dualspeed(gadget)) {
+		int			hs = 0;
+
+		if (gadget->speed == USB_SPEED_HIGH)
+			hs = 1;
+		if (type == USB_DT_OTHER_SPEED_CONFIG)
+			hs = !hs;
+		if (hs)
+			speed = USB_SPEED_HIGH;
+
+	}
+
+	/* This is a lookup by config *INDEX* */
+	w_value &= 0xff;
+	list_for_each_entry(c, &cdev->configs, list) {
+		/* ignore configs that won't work at this speed */
+		if (speed == USB_SPEED_HIGH) {
+			if (!c->highspeed)
+				continue;
+		} else {
+			if (!c->fullspeed)
+				continue;
+		}
+		if (w_value == 0)
+			return config_buf(c, speed, cdev->req->buf, type);
+		w_value--;
+	}
+	return -EINVAL;
+}
+
+static int count_configs(struct usb_composite_dev *cdev, unsigned type)
+{
+	struct usb_gadget		*gadget = cdev->gadget;
+	struct usb_configuration	*c;
+	unsigned			count = 0;
+	int				hs = 0;
+
+	if (gadget_is_dualspeed(gadget)) {
+		if (gadget->speed == USB_SPEED_HIGH)
+			hs = 1;
+		if (type == USB_DT_DEVICE_QUALIFIER)
+			hs = !hs;
+	}
+	list_for_each_entry(c, &cdev->configs, list) {
+		/* ignore configs that won't work at this speed */
+		if (hs) {
+			if (!c->highspeed)
+				continue;
+		} else {
+			if (!c->fullspeed)
+				continue;
+		}
+		count++;
+	}
+	return count;
+}
+
+static void device_qual(struct usb_composite_dev *cdev)
+{
+	struct usb_qualifier_descriptor	*qual = cdev->req->buf;
+
+	qual->bLength = sizeof(*qual);
+	qual->bDescriptorType = USB_DT_DEVICE_QUALIFIER;
+	/* POLICY: same bcdUSB and device type info at both speeds */
+	qual->bcdUSB = cdev->desc.bcdUSB;
+	qual->bDeviceClass = cdev->desc.bDeviceClass;
+	qual->bDeviceSubClass = cdev->desc.bDeviceSubClass;
+	qual->bDeviceProtocol = cdev->desc.bDeviceProtocol;
+	/* ASSUME same EP0 fifo size at both speeds */
+	qual->bMaxPacketSize0 = cdev->desc.bMaxPacketSize0;
+	qual->bNumConfigurations = count_configs(cdev, USB_DT_DEVICE_QUALIFIER);
+	qual->bRESERVED = 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void reset_config(struct usb_composite_dev *cdev)
+{
+	struct usb_function		*f;
+
+	DBG(cdev, "reset config\n");
+
+	list_for_each_entry(f, &cdev->config->functions, list) {
+		if (f->disable)
+			f->disable(f);
+	}
+	cdev->config = NULL;
+}
+
+static int set_config(struct usb_composite_dev *cdev,
+		const struct usb_ctrlrequest *ctrl, unsigned number)
+{
+	struct usb_gadget	*gadget = cdev->gadget;
+	struct usb_configuration *c = NULL;
+	int			result = -EINVAL;
+	unsigned		power = gadget_is_otg(gadget) ? 8 : 100;
+	int			tmp;
+
+	if (cdev->config)
+		reset_config(cdev);
+
+	if (number) {
+		list_for_each_entry(c, &cdev->configs, list) {
+			if (c->bConfigurationValue == number) {
+				result = 0;
+				break;
+			}
+		}
+		if (result < 0)
+			goto done;
+	} else
+		result = 0;
+
+	INFO(cdev, "%s speed config #%d: %s\n",
+		({ 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;
+		} ; speed; }), number, c ? c->label : "unconfigured");
+
+	if (!c)
+		goto done;
+
+	cdev->config = c;
+
+	/* Initialize all interfaces by setting them to altsetting zero. */
+	for (tmp = 0; tmp < MAX_CONFIG_INTERFACES; tmp++) {
+		struct usb_function	*f = c->interface[tmp];
+
+		if (!f)
+			break;
+
+		result = f->set_alt(f, tmp, 0);
+		if (result < 0) {
+			DBG(cdev, "interface %d (%s/%p) alt 0 --> %d\n",
+					tmp, f->name, f, result);
+
+			reset_config(cdev);
+			goto done;
+		}
+	}
+
+	/* when we return, be sure our power usage is valid */
+	power = 2 * c->bMaxPower;
+done:
+	usb_gadget_vbus_draw(gadget, power);
+	return result;
+}
+
+/**
+ * usb_add_config() - add a configuration to a device.
+ * @cdev: wraps the USB gadget
+ * @config: the configuration, with bConfigurationValue assigned
+ * Context: single threaded during gadget setup
+ *
+ * One of the main tasks of a composite driver's bind() routine is to
+ * add each of the configurations it supports, using this routine.
+ *
+ * This function returns the value of the configuration's bind(), which
+ * is zero for success else a negative errno value.  Binding configurations
+ * assigns global resources including string IDs, and per-configuration
+ * resources such as interface IDs and endpoints.
+ */
+int __init usb_add_config(struct usb_composite_dev *cdev,
+		struct usb_configuration *config)
+{
+	int				status = -EINVAL;
+	struct usb_configuration	*c;
+
+	DBG(cdev, "adding config #%u '%s'/%p\n",
+			config->bConfigurationValue,
+			config->label, config);
+
+	if (!config->bConfigurationValue || !config->bind)
+		goto done;
+
+	/* Prevent duplicate configuration identifiers */
+	list_for_each_entry(c, &cdev->configs, list) {
+		if (c->bConfigurationValue == config->bConfigurationValue) {
+			status = -EBUSY;
+			goto done;
+		}
+	}
+
+	config->cdev = cdev;
+	list_add_tail(&config->list, &cdev->configs);
+
+	INIT_LIST_HEAD(&config->functions);
+	config->next_interface_id = 0;
+
+	status = config->bind(config);
+	if (status < 0) {
+		list_del(&config->list);
+		config->cdev = NULL;
+	} else {
+		unsigned	i;
+
+		DBG(cdev, "cfg %d/%p speeds:%s%s\n",
+			config->bConfigurationValue, config,
+			config->highspeed ? " high" : "",
+			config->fullspeed
+				? (gadget_is_dualspeed(cdev->gadget)
+					? " full"
+					: " full/low")
+				: "");
+
+		for (i = 0; i < MAX_CONFIG_INTERFACES; i++) {
+			struct usb_function	*f = config->interface[i];
+
+			if (!f)
+				continue;
+			DBG(cdev, "  interface %d = %s/%p\n",
+				i, f->name, f);
+		}
+	}
+
+	/* set_alt(), or next config->bind(), sets up
+	 * ep->driver_data as needed.
+	 */
+	usb_ep_autoconfig_reset(cdev->gadget);
+
+done:
+	if (status)
+		DBG(cdev, "added config '%s'/%u --> %d\n", config->label,
+				config->bConfigurationValue, status);
+	return status;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* We support strings in multiple languages ... string descriptor zero
+ * says which languages are supported.  The typical case will be that
+ * only one language (probably English) is used, with I18N handled on
+ * the host side.
+ */
+
+static void collect_langs(struct usb_gadget_strings **sp, __le16 *buf)
+{
+	const struct usb_gadget_strings	*s;
+	u16				language;
+	__le16				*tmp;
+
+	while (*sp) {
+		s = *sp;
+		language = cpu_to_le16(s->language);
+		for (tmp = buf; *tmp && tmp < &buf[126]; tmp++) {
+			if (*tmp == language)
+				goto repeat;
+		}
+		*tmp++ = language;
+repeat:
+		sp++;
+	}
+}
+
+static int lookup_string(
+	struct usb_gadget_strings	**sp,
+	void				*buf,
+	u16				language,
+	int				id
+)
+{
+	struct usb_gadget_strings	*s;
+	int				value;
+
+	while (*sp) {
+		s = *sp++;
+		if (s->language != language)
+			continue;
+		value = usb_gadget_get_string(s, id, buf);
+		if (value > 0)
+			return value;
+	}
+	return -EINVAL;
+}
+
+static int get_string(struct usb_composite_dev *cdev,
+		void *buf, u16 language, int id)
+{
+	struct usb_configuration	*c;
+	struct usb_function		*f;
+	int				len;
+
+	/* Yes, not only is USB's I18N support probably more than most
+	 * folk will ever care about ... also, it's all supported here.
+	 * (Except for UTF8 support for Unicode's "Astral Planes".)
+	 */
+
+	/* 0 == report all available language codes */
+	if (id == 0) {
+		struct usb_string_descriptor	*s = buf;
+		struct usb_gadget_strings	**sp;
+
+		memset(s, 0, 256);
+		s->bDescriptorType = USB_DT_STRING;
+
+		sp = composite->strings;
+		if (sp)
+			collect_langs(sp, s->wData);
+
+		list_for_each_entry(c, &cdev->configs, list) {
+			sp = c->strings;
+			if (sp)
+				collect_langs(sp, s->wData);
+
+			list_for_each_entry(f, &c->functions, list) {
+				sp = f->strings;
+				if (sp)
+					collect_langs(sp, s->wData);
+			}
+		}
+
+		for (len = 0; s->wData[len] && len <= 126; len++)
+			continue;
+		if (!len)
+			return -EINVAL;
+
+		s->bLength = 2 * (len + 1);
+		return s->bLength;
+	}
+
+	/* Otherwise, look up and return a specified string.  String IDs
+	 * are device-scoped, so we look up each string table we're told
+	 * about.  These lookups are infrequent; simpler-is-better here.
+	 */
+	if (composite->strings) {
+		len = lookup_string(composite->strings, buf, language, id);
+		if (len > 0)
+			return len;
+	}
+	list_for_each_entry(c, &cdev->configs, list) {
+		if (c->strings) {
+			len = lookup_string(c->strings, buf, language, id);
+			if (len > 0)
+				return len;
+		}
+		list_for_each_entry(f, &c->functions, list) {
+			if (!f->strings)
+				continue;
+			len = lookup_string(f->strings, buf, language, id);
+			if (len > 0)
+				return len;
+		}
+	}
+	return -EINVAL;
+}
+
+/**
+ * usb_string_id() - allocate an unused string ID
+ * @cdev: the device whose string descriptor IDs are being allocated
+ * Context: single threaded during gadget setup
+ *
+ * @usb_string_id() is called from bind() callbacks to allocate
+ * string IDs.  Drivers for functions, configurations, or gadgets will
+ * then store that ID in the appropriate descriptors and string table.
+ *
+ * All string identifier should be allocated using this routine, to
+ * ensure that for example different functions don't wrongly assign
+ * different meanings to the same identifier.
+ */
+int __init usb_string_id(struct usb_composite_dev *cdev)
+{
+	if (cdev->next_string_id < 254) {
+		/* string id 0 is reserved */
+		cdev->next_string_id++;
+		return cdev->next_string_id;
+	}
+	return -ENODEV;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	if (req->status || req->actual != req->length)
+		DBG((struct usb_composite_dev *) 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 and function specific setup.
+ */
+static int
+composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+{
+	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
+	struct usb_request		*req = cdev->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);
+	struct usb_function		*f = NULL;
+
+	/* partial re-init of the response message; the function or the
+	 * gadget might need to intercept e.g. a control-OUT completion
+	 * when we delegate to it.
+	 */
+	req->zero = 0;
+	req->complete = composite_setup_complete;
+	req->length = USB_BUFSIZ;
+	gadget->ep0->driver_data = cdev;
+
+	switch (ctrl->bRequest) {
+
+	/* we handle all standard USB descriptors */
+	case USB_REQ_GET_DESCRIPTOR:
+		if (ctrl->bRequestType != USB_DIR_IN)
+			goto unknown;
+		switch (w_value >> 8) {
+
+		case USB_DT_DEVICE:
+			cdev->desc.bNumConfigurations =
+				count_configs(cdev, USB_DT_DEVICE);
+			value = min(w_length, (u16) sizeof cdev->desc);
+			memcpy(req->buf, &cdev->desc, value);
+			break;
+		case USB_DT_DEVICE_QUALIFIER:
+			if (!gadget_is_dualspeed(gadget))
+				break;
+			device_qual(cdev);
+			value = min_t(int, w_length,
+				sizeof(struct usb_qualifier_descriptor));
+			break;
+		case USB_DT_OTHER_SPEED_CONFIG:
+			if (!gadget_is_dualspeed(gadget))
+				break;
+			/* FALLTHROUGH */
+		case USB_DT_CONFIG:
+			value = config_desc(cdev, w_value);
+			if (value >= 0)
+				value = min(w_length, (u16) value);
+			break;
+		case USB_DT_STRING:
+			value = get_string(cdev, req->buf,
+					w_index, w_value & 0xff);
+			if (value >= 0)
+				value = min(w_length, (u16) value);
+			break;
+		}
+		break;
+
+	/* any number of configs can work */
+	case USB_REQ_SET_CONFIGURATION:
+		if (ctrl->bRequestType != 0)
+			goto unknown;
+		if (gadget_is_otg(gadget)) {
+			if (gadget->a_hnp_support)
+				DBG(cdev, "HNP available\n");
+			else if (gadget->a_alt_hnp_support)
+				DBG(cdev, "HNP on another port\n");
+			else
+				VDBG(cdev, "HNP inactive\n");
+		}
+		spin_lock(&cdev->lock);
+		value = set_config(cdev, ctrl, w_value);
+		spin_unlock(&cdev->lock);
+		break;
+	case USB_REQ_GET_CONFIGURATION:
+		if (ctrl->bRequestType != USB_DIR_IN)
+			goto unknown;
+		if (cdev->config)
+			*(u8 *)req->buf = cdev->config->bConfigurationValue;
+		else
+			*(u8 *)req->buf = 0;
+		value = min(w_length, (u16) 1);
+		break;
+
+	/* function drivers must handle get/set altsetting; if there's
+	 * no get() method, we know only altsetting zero works.
+	 */
+	case USB_REQ_SET_INTERFACE:
+		if (ctrl->bRequestType != USB_RECIP_INTERFACE)
+			goto unknown;
+		if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES)
+			break;
+		f = cdev->config->interface[w_index];
+		if (!f)
+			break;
+		if (w_value && !f->get_alt)
+			break;
+		value = f->set_alt(f, w_index, w_value);
+		break;
+	case USB_REQ_GET_INTERFACE:
+		if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))
+			goto unknown;
+		if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES)
+			break;
+		f = cdev->config->interface[w_index];
+		if (!f)
+			break;
+		/* lots of interfaces only need altsetting zero... */
+		value = f->get_alt ? f->get_alt(f, w_index) : 0;
+		if (value < 0)
+			break;
+		*((u8 *)req->buf) = value;
+		value = min(w_length, (u16) 1);
+		break;
+	default:
+unknown:
+		VDBG(cdev,
+			"non-core control req%02x.%02x v%04x i%04x l%d\n",
+			ctrl->bRequestType, ctrl->bRequest,
+			w_value, w_index, w_length);
+
+		/* functions always handle their interfaces ... punt other
+		 * recipients (endpoint, other, WUSB, ...) to the current
+		 * configuration code.
+		 *
+		 * REVISIT it could make sense to let the composite device
+		 * take such requests too, if that's ever needed:  to work
+		 * in config 0, etc.
+		 */
+		if ((ctrl->bRequestType & USB_RECIP_MASK)
+				== USB_RECIP_INTERFACE) {
+			f = cdev->config->interface[w_index];
+			if (f && f->setup)
+				value = f->setup(f, ctrl);
+			else
+				f = NULL;
+		}
+		if (value < 0 && !f) {
+			struct usb_configuration	*c;
+
+			c = cdev->config;
+			if (c && c->setup)
+				value = c->setup(c, ctrl);
+		}
+
+		goto done;
+	}
+
+	/* 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(cdev, "ep_queue --> %d\n", value);
+			req->status = 0;
+			composite_setup_complete(gadget->ep0, req);
+		}
+	}
+
+done:
+	/* device either stalls (value < 0) or reports success */
+	return value;
+}
+
+static void composite_disconnect(struct usb_gadget *gadget)
+{
+	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
+	unsigned long			flags;
+
+	/* REVISIT:  should we have config and device level
+	 * disconnect callbacks?
+	 */
+	spin_lock_irqsave(&cdev->lock, flags);
+	if (cdev->config)
+		reset_config(cdev);
+	spin_unlock_irqrestore(&cdev->lock, flags);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void /* __init_or_exit */
+composite_unbind(struct usb_gadget *gadget)
+{
+	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
+
+	/* composite_disconnect() must already have been called
+	 * by the underlying peripheral controller driver!
+	 * so there's no i/o concurrency that could affect the
+	 * state protected by cdev->lock.
+	 */
+	WARN_ON(cdev->config);
+
+	while (!list_empty(&cdev->configs)) {
+		struct usb_configuration	*c;
+
+		c = list_first_entry(&cdev->configs,
+				struct usb_configuration, list);
+		while (!list_empty(&c->functions)) {
+			struct usb_function		*f;
+
+			f = list_first_entry(&c->functions,
+					struct usb_function, list);
+			list_del(&f->list);
+			if (f->unbind) {
+				DBG(cdev, "unbind function '%s'/%p\n",
+						f->name, f);
+				f->unbind(c, f);
+				/* may free memory for "f" */
+			}
+		}
+		list_del(&c->list);
+		if (c->unbind) {
+			DBG(cdev, "unbind config '%s'/%p\n", c->label, c);
+			c->unbind(c);
+			/* may free memory for "c" */
+		}
+	}
+	if (composite->unbind)
+		composite->unbind(cdev);
+
+	if (cdev->req) {
+		kfree(cdev->req->buf);
+		usb_ep_free_request(gadget->ep0, cdev->req);
+	}
+	kfree(cdev);
+	set_gadget_data(gadget, NULL);
+	composite = NULL;
+}
+
+static void __init
+string_override_one(struct usb_gadget_strings *tab, u8 id, const char *s)
+{
+	struct usb_string		*str = tab->strings;
+
+	for (str = tab->strings; str->s; str++) {
+		if (str->id == id) {
+			str->s = s;
+			return;
+		}
+	}
+}
+
+static void __init
+string_override(struct usb_gadget_strings **tab, u8 id, const char *s)
+{
+	while (*tab) {
+		string_override_one(*tab, id, s);
+		tab++;
+	}
+}
+
+static int __init composite_bind(struct usb_gadget *gadget)
+{
+	struct usb_composite_dev	*cdev;
+	int				status = -ENOMEM;
+
+	cdev = kzalloc(sizeof *cdev, GFP_KERNEL);
+	if (!cdev)
+		return status;
+
+	spin_lock_init(&cdev->lock);
+	cdev->gadget = gadget;
+	set_gadget_data(gadget, cdev);
+	INIT_LIST_HEAD(&cdev->configs);
+
+	/* preallocate control response and buffer */
+	cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
+	if (!cdev->req)
+		goto fail;
+	cdev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL);
+	if (!cdev->req->buf)
+		goto fail;
+	cdev->req->complete = composite_setup_complete;
+	gadget->ep0->driver_data = cdev;
+
+	cdev->bufsiz = USB_BUFSIZ;
+	cdev->driver = composite;
+
+	usb_gadget_set_selfpowered(gadget);
+
+	/* interface and string IDs start at zero via kzalloc.
+	 * we force endpoints to start unassigned; few controller
+	 * drivers will zero ep->driver_data.
+	 */
+	usb_ep_autoconfig_reset(cdev->gadget);
+
+	/* composite gadget needs to assign strings for whole device (like
+	 * serial number), register function drivers, potentially update
+	 * power state and consumption, etc
+	 */
+	status = composite->bind(cdev);
+	if (status < 0)
+		goto fail;
+
+	cdev->desc = *composite->dev;
+	cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
+
+	/* standardized runtime overrides for device ID data */
+	if (idVendor)
+		cdev->desc.idVendor = cpu_to_le16(idVendor);
+	if (idProduct)
+		cdev->desc.idProduct = cpu_to_le16(idProduct);
+	if (bcdDevice)
+		cdev->desc.bcdDevice = cpu_to_le16(bcdDevice);
+
+	/* strings can't be assigned before bind() allocates the
+	 * releavnt identifiers
+	 */
+	if (cdev->desc.iManufacturer && iManufacturer)
+		string_override(composite->strings,
+			cdev->desc.iManufacturer, iManufacturer);
+	if (cdev->desc.iProduct && iProduct)
+		string_override(composite->strings,
+			cdev->desc.iProduct, iProduct);
+	if (cdev->desc.iSerialNumber && iSerialNumber)
+		string_override(composite->strings,
+			cdev->desc.iSerialNumber, iSerialNumber);
+
+	INFO(cdev, "%s ready\n", composite->name);
+	return 0;
+
+fail:
+	composite_unbind(gadget);
+	return status;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void
+composite_suspend(struct usb_gadget *gadget)
+{
+	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
+	struct usb_function		*f;
+
+	/* REVISIT:  should we have config and device level
+	 * suspend/resume callbacks?
+	 */
+	DBG(cdev, "suspend\n");
+	if (cdev->config) {
+		list_for_each_entry(f, &cdev->config->functions, list) {
+			if (f->suspend)
+				f->suspend(f);
+		}
+	}
+}
+
+static void
+composite_resume(struct usb_gadget *gadget)
+{
+	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
+	struct usb_function		*f;
+
+	/* REVISIT:  should we have config and device level
+	 * suspend/resume callbacks?
+	 */
+	DBG(cdev, "resume\n");
+	if (cdev->config) {
+		list_for_each_entry(f, &cdev->config->functions, list) {
+			if (f->resume)
+				f->resume(f);
+		}
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_gadget_driver composite_driver = {
+	.speed		= USB_SPEED_HIGH,
+
+	.bind		= composite_bind,
+	.unbind		= __exit_p(composite_unbind),
+
+	.setup		= composite_setup,
+	.disconnect	= composite_disconnect,
+
+	.suspend	= composite_suspend,
+	.resume		= composite_resume,
+
+	.driver	= {
+		.owner		= THIS_MODULE,
+	},
+};
+
+/**
+ * usb_composite_register() - register a composite driver
+ * @driver: the driver to register
+ * Context: single threaded during gadget setup
+ *
+ * This function is used to register drivers using the composite driver
+ * framework.  The return value is zero, or a negative errno value.
+ * Those values normally come from the driver's @bind method, which does
+ * all the work of setting up the driver to match the hardware.
+ *
+ * On successful return, the gadget is ready to respond to requests from
+ * the host, unless one of its components invokes usb_gadget_disconnect()
+ * while it was binding.  That would usually be done in order to wait for
+ * some userspace participation.
+ */
+int __init usb_composite_register(struct usb_composite_driver *driver)
+{
+	if (!driver || !driver->dev || !driver->bind || composite)
+		return -EINVAL;
+
+	if (!driver->name)
+		driver->name = "composite";
+	composite_driver.function =  (char *) driver->name;
+	composite_driver.driver.name = driver->name;
+	composite = driver;
+
+	return usb_gadget_register_driver(&composite_driver);
+}
+
+/**
+ * usb_composite_unregister() - unregister a composite driver
+ * @driver: the driver to unregister
+ *
+ * This function is used to unregister drivers using the composite
+ * driver framework.
+ */
+void __exit usb_composite_unregister(struct usb_composite_driver *driver)
+{
+	if (composite != driver)
+		return;
+	usb_gadget_unregister_driver(&composite_driver);
+}
diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c
index a4e54b2..1ca1c32 100644
--- a/drivers/usb/gadget/config.c
+++ b/drivers/usb/gadget/config.c
@@ -96,7 +96,7 @@
 	/* config descriptor first */
 	if (length < USB_DT_CONFIG_SIZE || !desc)
 		return -EINVAL;
-	*cp = *config; 
+	*cp = *config;
 
 	/* then interface/endpoint/class/vendor/... */
 	len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf,
@@ -115,3 +115,77 @@
 	return len;
 }
 
+/**
+ * usb_copy_descriptors - copy a vector of USB descriptors
+ * @src: null-terminated vector to copy
+ * Context: initialization code, which may sleep
+ *
+ * This makes a copy of a vector of USB descriptors.  Its primary use
+ * is to support usb_function objects which can have multiple copies,
+ * each needing different descriptors.  Functions may have static
+ * tables of descriptors, which are used as templates and customized
+ * with identifiers (for interfaces, strings, endpoints, and more)
+ * as needed by a given function instance.
+ */
+struct usb_descriptor_header **__init
+usb_copy_descriptors(struct usb_descriptor_header **src)
+{
+	struct usb_descriptor_header **tmp;
+	unsigned bytes;
+	unsigned n_desc;
+	void *mem;
+	struct usb_descriptor_header **ret;
+
+	/* count descriptors and their sizes; then add vector size */
+	for (bytes = 0, n_desc = 0, tmp = src; *tmp; tmp++, n_desc++)
+		bytes += (*tmp)->bLength;
+	bytes += (n_desc + 1) * sizeof(*tmp);
+
+	mem = kmalloc(bytes, GFP_KERNEL);
+	if (!mem)
+		return NULL;
+
+	/* fill in pointers starting at "tmp",
+	 * to descriptors copied starting at "mem";
+	 * and return "ret"
+	 */
+	tmp = mem;
+	ret = mem;
+	mem += (n_desc + 1) * sizeof(*tmp);
+	while (*src) {
+		memcpy(mem, *src, (*src)->bLength);
+		*tmp = mem;
+		tmp++;
+		mem += (*src)->bLength;
+		src++;
+	}
+	*tmp = NULL;
+
+	return ret;
+}
+
+/**
+ * usb_find_endpoint - find a copy of an endpoint descriptor
+ * @src: original vector of descriptors
+ * @copy: copy of @src
+ * @ep: endpoint descriptor found in @src
+ *
+ * This returns the copy of the @match descriptor made for @copy.  Its
+ * intended use is to help remembering the endpoint descriptor to use
+ * when enabling a given endpoint.
+ */
+struct usb_endpoint_descriptor *__init
+usb_find_endpoint(
+	struct usb_descriptor_header **src,
+	struct usb_descriptor_header **copy,
+	struct usb_endpoint_descriptor *match
+)
+{
+	while (*src) {
+		if (*src == (void *) match)
+			return (void *)*copy;
+		src++;
+		copy++;
+	}
+	return NULL;
+}
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 4203619..21d1406 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -862,7 +862,7 @@
 	/* maybe claim OTG support, though we won't complete HNP */
 	dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0);
 
-	strcpy (dum->gadget.dev.bus_id, "gadget");
+	dev_set_name(&dum->gadget.dev, "gadget");
 	dum->gadget.dev.parent = &pdev->dev;
 	dum->gadget.dev.release = dummy_gadget_release;
 	rc = device_register (&dum->gadget.dev);
@@ -1865,7 +1865,7 @@
 
 	dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
 
-	hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, pdev->dev.bus_id);
+	hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, dev_name(&pdev->dev));
 	if (!hcd)
 		return -ENOMEM;
 	the_controller = hcd_to_dummy (hcd);
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index 8bdad22..9462e30 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -159,6 +159,7 @@
 	/* MATCH!! */
 
 	/* report address */
+	desc->bEndpointAddress &= USB_DIR_IN;
 	if (isdigit (ep->name [2])) {
 		u8	num = simple_strtol (&ep->name [2], NULL, 10);
 		desc->bEndpointAddress |= num;
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 4ce3950..d7aaaa2 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -1,8 +1,9 @@
 /*
  * ether.c -- Ethernet gadget driver, with CDC and non-CDC options
  *
- * Copyright (C) 2003-2005 David Brownell
+ * Copyright (C) 2003-2005,2008 David Brownell
  * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
+ * Copyright (C) 2008 Nokia Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -23,18 +24,9 @@
 
 #include <linux/kernel.h>
 #include <linux/utsname.h>
-#include <linux/device.h>
-#include <linux/ctype.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
 
-#include <linux/usb/ch9.h>
-#include <linux/usb/cdc.h>
-#include <linux/usb/gadget.h>
+#include "u_ether.h"
 
-#include "gadget_chips.h"
-
-/*-------------------------------------------------------------------------*/
 
 /*
  * Ethernet gadget driver -- with CDC and non-CDC options
@@ -46,7 +38,11 @@
  * this USB-IF standard as its open-systems interoperability solution;
  * most host side USB stacks (except from Microsoft) support it.
  *
- * There's some hardware that can't talk CDC.  We make that hardware
+ * This is sometimes called "CDC ECM" (Ethernet Control Model) to support
+ * TLA-soup.  "CDC ACM" (Abstract Control Model) is for modems, and a new
+ * "CDC EEM" (Ethernet Emulation Model) is starting to spread.
+ *
+ * There's some hardware that can't talk CDC ECM.  We make that hardware
  * implement a "minimalist" vendor-agnostic CDC core:  same framing, but
  * link-level setup only requires activating the configuration.  Only the
  * endpoint descriptors, and product/vendor IDs, are relevant; no control
@@ -64,70 +60,40 @@
  * A third option is also in use.  Rather than CDC Ethernet, or something
  * simpler, Microsoft pushes their own approach: RNDIS.  The published
  * RNDIS specs are ambiguous and appear to be incomplete, and are also
- * needlessly complex.
+ * needlessly complex.  They borrow more from CDC ACM than CDC ECM.
  */
 
 #define DRIVER_DESC		"Ethernet Gadget"
-#define DRIVER_VERSION		"May Day 2005"
+#define DRIVER_VERSION		"Memorial Day 2008"
 
-static const char shortname [] = "ether";
-static const char driver_desc [] = DRIVER_DESC;
-
-#define RX_EXTRA	20		/* guard against rx overflows */
-
-#include "rndis.h"
-
-#ifndef	CONFIG_USB_ETH_RNDIS
-#define rndis_uninit(x)		do{}while(0)
-#define rndis_deregister(c)	do{}while(0)
-#define rndis_exit()		do{}while(0)
+#ifdef CONFIG_USB_ETH_RNDIS
+#define PREFIX			"RNDIS/"
+#else
+#define PREFIX			""
 #endif
 
-/* CDC and RNDIS support the same host-chosen outgoing packet filters. */
-#define	DEFAULT_FILTER	(USB_CDC_PACKET_TYPE_BROADCAST \
-			|USB_CDC_PACKET_TYPE_ALL_MULTICAST \
-			|USB_CDC_PACKET_TYPE_PROMISCUOUS \
-			|USB_CDC_PACKET_TYPE_DIRECTED)
-
-
-/*-------------------------------------------------------------------------*/
-
-struct eth_dev {
-	spinlock_t		lock;
-	struct usb_gadget	*gadget;
-	struct usb_request	*req;		/* for control responses */
-	struct usb_request	*stat_req;	/* for cdc & rndis status */
-
-	u8			config;
-	struct usb_ep		*in_ep, *out_ep, *status_ep;
-	const struct usb_endpoint_descriptor
-				*in, *out, *status;
-
-	spinlock_t		req_lock;
-	struct list_head	tx_reqs, rx_reqs;
-
-	struct net_device	*net;
-	struct net_device_stats	stats;
-	atomic_t		tx_qlen;
-
-	struct work_struct	work;
-	unsigned		zlp:1;
-	unsigned		cdc:1;
-	unsigned		rndis:1;
-	unsigned		suspended:1;
-	u16			cdc_filter;
-	unsigned long		todo;
-#define	WORK_RX_MEMORY		0
-	int			rndis_config;
-	u8			host_mac [ETH_ALEN];
-};
-
-/* This version autoconfigures as much as possible at run-time.
+/*
+ * This driver aims for interoperability by using CDC ECM unless
  *
- * It also ASSUMES a self-powered device, without remote wakeup,
- * although remote wakeup support would make sense.
+ *		can_support_ecm()
+ *
+ * returns false, in which case it supports the CDC Subset.  By default,
+ * that returns true; most hardware has no problems with CDC ECM, that's
+ * a good default.  Previous versions of this driver had no default; this
+ * version changes that, removing overhead for new controller support.
+ *
+ *	IF YOUR HARDWARE CAN'T SUPPORT CDC ECM, UPDATE THAT ROUTINE!
  */
 
+static inline bool has_rndis(void)
+{
+#ifdef	CONFIG_USB_ETH_RNDIS
+	return true;
+#else
+	return false;
+#endif
+}
+
 /*-------------------------------------------------------------------------*/
 
 /* DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
@@ -137,8 +103,8 @@
 /* Thanks to NetChip Technologies for donating this product ID.
  * It's for devices with only CDC Ethernet configurations.
  */
-#define CDC_VENDOR_NUM	0x0525		/* NetChip */
-#define CDC_PRODUCT_NUM	0xa4a1		/* Linux-USB Ethernet Gadget */
+#define CDC_VENDOR_NUM		0x0525	/* NetChip */
+#define CDC_PRODUCT_NUM		0xa4a1	/* Linux-USB Ethernet Gadget */
 
 /* For hardware that can't talk CDC, we use the same vendor ID that
  * ARM Linux has used for ethernet-over-usb, both with sa1100 and
@@ -162,274 +128,9 @@
 #define RNDIS_VENDOR_NUM	0x0525	/* NetChip */
 #define RNDIS_PRODUCT_NUM	0xa4a2	/* Ethernet/RNDIS Gadget */
 
-
-/* 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");
-
-/* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */
-static char *dev_addr;
-module_param(dev_addr, charp, S_IRUGO);
-MODULE_PARM_DESC(dev_addr, "Device Ethernet Address");
-
-/* this address is invisible to ifconfig */
-static char *host_addr;
-module_param(host_addr, charp, S_IRUGO);
-MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
-
-
 /*-------------------------------------------------------------------------*/
 
-/* Include CDC support if we could run on CDC-capable hardware. */
-
-#ifdef CONFIG_USB_GADGET_NET2280
-#define	DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_DUMMY_HCD
-#define	DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_GOKU
-#define	DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_LH7A40X
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_MQ11XX
-#define	DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_OMAP
-#define	DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_N9604
-#define	DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_S3C2410
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_AT91
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_MUSBHSFC
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_ATMEL_USBA
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_FSL_USB2
-#define DEV_CONFIG_CDC
-#endif
-
-/* For CDC-incapable hardware, choose the simple cdc subset.
- * Anything that talks bulk (without notable bugs) can do this.
- */
-#ifdef CONFIG_USB_GADGET_PXA25X
-#define	DEV_CONFIG_SUBSET
-#endif
-
-#ifdef CONFIG_USB_GADGET_PXA27X
-#define	DEV_CONFIG_SUBSET
-#endif
-
-#ifdef CONFIG_USB_GADGET_SUPERH
-#define	DEV_CONFIG_SUBSET
-#endif
-
-#ifdef CONFIG_USB_GADGET_SA1100
-/* use non-CDC for backwards compatibility */
-#define	DEV_CONFIG_SUBSET
-#endif
-
-#ifdef CONFIG_USB_GADGET_M66592
-#define DEV_CONFIG_CDC
-#endif
-
-#ifdef CONFIG_USB_GADGET_AMD5536UDC
-#define	DEV_CONFIG_CDC
-#endif
-
-
-/*-------------------------------------------------------------------------*/
-
-/* "main" config is either CDC, or its simple subset */
-static inline int is_cdc(struct eth_dev *dev)
-{
-#if	!defined(DEV_CONFIG_SUBSET)
-	return 1;		/* only cdc possible */
-#elif	!defined (DEV_CONFIG_CDC)
-	return 0;		/* only subset possible */
-#else
-	return dev->cdc;	/* depends on what hardware we found */
-#endif
-}
-
-/* "secondary" RNDIS config may sometimes be activated */
-static inline int rndis_active(struct eth_dev *dev)
-{
-#ifdef	CONFIG_USB_ETH_RNDIS
-	return dev->rndis;
-#else
-	return 0;
-#endif
-}
-
-#define	subset_active(dev)	(!is_cdc(dev) && !rndis_active(dev))
-#define	cdc_active(dev)		( is_cdc(dev) && !rndis_active(dev))
-
-
-
-#define DEFAULT_QLEN	2	/* double buffering by default */
-
-/* peak bulk transfer bits-per-second */
-#define	HS_BPS		(13 * 512 * 8 * 1000 * 8)
-#define	FS_BPS		(19 *  64 * 1 * 1000 * 8)
-
-#ifdef CONFIG_USB_GADGET_DUALSPEED
-#define	DEVSPEED	USB_SPEED_HIGH
-
-static unsigned qmult = 5;
-module_param (qmult, uint, S_IRUGO|S_IWUSR);
-
-
-/* for dual-speed hardware, use deeper queues at highspeed */
-#define qlen(gadget) \
-	(DEFAULT_QLEN*((gadget->speed == USB_SPEED_HIGH) ? qmult : 1))
-
-static inline int BITRATE(struct usb_gadget *g)
-{
-	return (g->speed == USB_SPEED_HIGH) ? HS_BPS : FS_BPS;
-}
-
-#else	/* full speed (low speed doesn't do bulk) */
-
-#define qmult		1
-
-#define	DEVSPEED	USB_SPEED_FULL
-
-#define qlen(gadget) DEFAULT_QLEN
-
-static inline int BITRATE(struct usb_gadget *g)
-{
-	return FS_BPS;
-}
-#endif
-
-
-/*-------------------------------------------------------------------------*/
-
-#define xprintk(d,level,fmt,args...) \
-	printk(level "%s: " fmt , (d)->net->name , ## args)
-
-#ifdef DEBUG
-#undef DEBUG
-#define DEBUG(dev,fmt,args...) \
-	xprintk(dev , KERN_DEBUG , fmt , ## args)
-#else
-#define DEBUG(dev,fmt,args...) \
-	do { } while (0)
-#endif /* DEBUG */
-
-#ifdef VERBOSE_DEBUG
-#define VDEBUG	DEBUG
-#else
-#define VDEBUG(dev,fmt,args...) \
-	do { } while (0)
-#endif /* DEBUG */
-
-#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)
-
-/*-------------------------------------------------------------------------*/
-
-/* USB DRIVER HOOKUP (to the hardware driver, below us), mostly
- * ep0 implementation:  descriptors, config management, setup().
- * also optional class-specific notification interrupt transfer.
- */
-
-/*
- * DESCRIPTORS ... most are static, but strings and (full) configuration
- * descriptors are built on demand.  For now we do either full CDC, or
- * our simple subset, with RNDIS as an optional second configuration.
- *
- * RNDIS includes some CDC ACM descriptors ... like CDC Ethernet.  But
- * the class descriptors match a modem (they're ignored; it's really just
- * Ethernet functionality), they don't need the NOP altsetting, and the
- * status transfer endpoint isn't optional.
- */
-
-#define STRING_MANUFACTURER		1
-#define STRING_PRODUCT			2
-#define STRING_ETHADDR			3
-#define STRING_DATA			4
-#define STRING_CONTROL			5
-#define STRING_RNDIS_CONTROL		6
-#define STRING_CDC			7
-#define STRING_SUBSET			8
-#define STRING_RNDIS			9
-#define STRING_SERIALNUMBER		10
-
-/* holds our biggest descriptor (or RNDIS response) */
-#define USB_BUFSIZ	256
-
-/*
- * This device advertises one configuration, eth_config, unless RNDIS
- * is enabled (rndis_config) on hardware supporting at least two configs.
- *
- * NOTE:  Controllers like superh_udc should probably be able to use
- * an RNDIS-only configuration.
- *
- * FIXME define some higher-powered configurations to make it easier
- * to recharge batteries ...
- */
-
-#define DEV_CONFIG_VALUE	1	/* cdc or subset */
-#define DEV_RNDIS_CONFIG_VALUE	2	/* rndis; optional */
-
-static struct usb_device_descriptor
-device_desc = {
+static struct usb_device_descriptor device_desc = {
 	.bLength =		sizeof device_desc,
 	.bDescriptorType =	USB_DT_DEVICE,
 
@@ -438,2220 +139,234 @@
 	.bDeviceClass =		USB_CLASS_COMM,
 	.bDeviceSubClass =	0,
 	.bDeviceProtocol =	0,
+	/* .bMaxPacketSize0 = f(hardware) */
 
+	/* Vendor and product id defaults change according to what configs
+	 * we support.  (As does bNumConfigurations.)  These values can
+	 * also be overridden by module parameters.
+	 */
 	.idVendor =		__constant_cpu_to_le16 (CDC_VENDOR_NUM),
 	.idProduct =		__constant_cpu_to_le16 (CDC_PRODUCT_NUM),
-	.iManufacturer =	STRING_MANUFACTURER,
-	.iProduct =		STRING_PRODUCT,
+	/* .bcdDevice = f(hardware) */
+	/* .iManufacturer = DYNAMIC */
+	/* .iProduct = DYNAMIC */
+	/* NO SERIAL NUMBER */
 	.bNumConfigurations =	1,
 };
 
-static struct usb_otg_descriptor
-otg_descriptor = {
+static struct usb_otg_descriptor otg_descriptor = {
 	.bLength =		sizeof otg_descriptor,
 	.bDescriptorType =	USB_DT_OTG,
 
-	.bmAttributes =		USB_OTG_SRP,
+	/* REVISIT SRP-only hardware is possible, although
+	 * it would not be called "OTG" ...
+	 */
+	.bmAttributes =		USB_OTG_SRP | USB_OTG_HNP,
 };
 
-static struct usb_config_descriptor
-eth_config = {
-	.bLength =		sizeof eth_config,
-	.bDescriptorType =	USB_DT_CONFIG,
-
-	/* compute wTotalLength on the fly */
-	.bNumInterfaces =	2,
-	.bConfigurationValue =	DEV_CONFIG_VALUE,
-	.iConfiguration =	STRING_CDC,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
-	.bMaxPower =		50,
-};
-
-#ifdef	CONFIG_USB_ETH_RNDIS
-static struct usb_config_descriptor
-rndis_config = {
-	.bLength =              sizeof rndis_config,
-	.bDescriptorType =      USB_DT_CONFIG,
-
-	/* compute wTotalLength on the fly */
-	.bNumInterfaces =       2,
-	.bConfigurationValue =  DEV_RNDIS_CONFIG_VALUE,
-	.iConfiguration =       STRING_RNDIS,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
-	.bMaxPower =            50,
-};
-#endif
-
-/*
- * Compared to the simple CDC subset, the full CDC Ethernet model adds
- * three class descriptors, two interface descriptors, optional status
- * endpoint.  Both have a "data" interface and two bulk endpoints.
- * There are also differences in how control requests are handled.
- *
- * RNDIS shares a lot with CDC-Ethernet, since it's a variant of the
- * CDC-ACM (modem) spec.  Unfortunately MSFT's RNDIS driver is buggy; it
- * may hang or oops.  Since bugfixes (or accurate specs, letting Linux
- * work around those bugs) are unlikely to ever come from MSFT, you may
- * wish to avoid using RNDIS.
- *
- * MCCI offers an alternative to RNDIS if you need to connect to Windows
- * but have hardware that can't support CDC Ethernet.   We add descriptors
- * to present the CDC Subset as a (nonconformant) CDC MDLM variant called
- * "SAFE".  That borrows from both CDC Ethernet and CDC MDLM.  You can
- * get those drivers from MCCI, or bundled with various products.
- */
-
-#ifdef	DEV_CONFIG_CDC
-static struct usb_interface_descriptor
-control_intf = {
-	.bLength =		sizeof control_intf,
-	.bDescriptorType =	USB_DT_INTERFACE,
-
-	.bInterfaceNumber =	0,
-	/* status endpoint is optional; this may be patched later */
-	.bNumEndpoints =	1,
-	.bInterfaceClass =	USB_CLASS_COMM,
-	.bInterfaceSubClass =	USB_CDC_SUBCLASS_ETHERNET,
-	.bInterfaceProtocol =	USB_CDC_PROTO_NONE,
-	.iInterface =		STRING_CONTROL,
-};
-#endif
-
-#ifdef	CONFIG_USB_ETH_RNDIS
-static const struct usb_interface_descriptor
-rndis_control_intf = {
-	.bLength =              sizeof rndis_control_intf,
-	.bDescriptorType =      USB_DT_INTERFACE,
-
-	.bInterfaceNumber =     0,
-	.bNumEndpoints =        1,
-	.bInterfaceClass =      USB_CLASS_COMM,
-	.bInterfaceSubClass =   USB_CDC_SUBCLASS_ACM,
-	.bInterfaceProtocol =   USB_CDC_ACM_PROTO_VENDOR,
-	.iInterface =           STRING_RNDIS_CONTROL,
-};
-#endif
-
-static const struct usb_cdc_header_desc header_desc = {
-	.bLength =		sizeof header_desc,
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
-
-	.bcdCDC =		__constant_cpu_to_le16 (0x0110),
-};
-
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
-
-static const struct usb_cdc_union_desc union_desc = {
-	.bLength =		sizeof union_desc,
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_UNION_TYPE,
-
-	.bMasterInterface0 =	0,	/* index of control interface */
-	.bSlaveInterface0 =	1,	/* index of DATA interface */
-};
-
-#endif	/* CDC || RNDIS */
-
-#ifdef	CONFIG_USB_ETH_RNDIS
-
-static const struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor = {
-	.bLength =		sizeof call_mgmt_descriptor,
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_CALL_MANAGEMENT_TYPE,
-
-	.bmCapabilities =	0x00,
-	.bDataInterface =	0x01,
-};
-
-static const struct usb_cdc_acm_descriptor acm_descriptor = {
-	.bLength =		sizeof acm_descriptor,
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_ACM_TYPE,
-
-	.bmCapabilities =	0x00,
-};
-
-#endif
-
-#ifndef DEV_CONFIG_CDC
-
-/* "SAFE" loosely follows CDC WMC MDLM, violating the spec in various
- * ways:  data endpoints live in the control interface, there's no data
- * interface, and it's not used to talk to a cell phone radio.
- */
-
-static const struct usb_cdc_mdlm_desc mdlm_desc = {
-	.bLength =		sizeof mdlm_desc,
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_MDLM_TYPE,
-
-	.bcdVersion =		__constant_cpu_to_le16(0x0100),
-	.bGUID = {
-		0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6,
-		0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f,
-	},
-};
-
-/* since "usb_cdc_mdlm_detail_desc" is a variable length structure, we
- * can't really use its struct.  All we do here is say that we're using
- * the submode of "SAFE" which directly matches the CDC Subset.
- */
-static const u8 mdlm_detail_desc[] = {
-	6,
-	USB_DT_CS_INTERFACE,
-	USB_CDC_MDLM_DETAIL_TYPE,
-
-	0,	/* "SAFE" */
-	0,	/* network control capabilities (none) */
-	0,	/* network data capabilities ("raw" encapsulation) */
-};
-
-#endif
-
-static const struct usb_cdc_ether_desc ether_desc = {
-	.bLength =		sizeof ether_desc,
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_ETHERNET_TYPE,
-
-	/* this descriptor actually adds value, surprise! */
-	.iMACAddress =		STRING_ETHADDR,
-	.bmEthernetStatistics =	__constant_cpu_to_le32 (0), /* no statistics */
-	.wMaxSegmentSize =	__constant_cpu_to_le16 (ETH_FRAME_LEN),
-	.wNumberMCFilters =	__constant_cpu_to_le16 (0),
-	.bNumberPowerFilters =	0,
-};
-
-
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
-
-/* include the status endpoint if we can, even where it's optional.
- * use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one
- * packet, to simplify cancellation; and a big transfer interval, to
- * waste less bandwidth.
- *
- * some drivers (like Linux 2.4 cdc-ether!) "need" it to exist even
- * if they ignore the connect/disconnect notifications that real aether
- * can provide.  more advanced cdc configurations might want to support
- * encapsulated commands (vendor-specific, using control-OUT).
- *
- * RNDIS requires the status endpoint, since it uses that encapsulation
- * mechanism for its funky RPC scheme.
- */
-
-#define LOG2_STATUS_INTERVAL_MSEC	5	/* 1 << 5 == 32 msec */
-#define STATUS_BYTECOUNT		16	/* 8 byte header + data */
-
-static struct usb_endpoint_descriptor
-fs_status_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	__constant_cpu_to_le16 (STATUS_BYTECOUNT),
-	.bInterval =		1 << LOG2_STATUS_INTERVAL_MSEC,
-};
-#endif
-
-#ifdef	DEV_CONFIG_CDC
-
-/* the default data interface has no endpoints ... */
-
-static const struct usb_interface_descriptor
-data_nop_intf = {
-	.bLength =		sizeof data_nop_intf,
-	.bDescriptorType =	USB_DT_INTERFACE,
-
-	.bInterfaceNumber =	1,
-	.bAlternateSetting =	0,
-	.bNumEndpoints =	0,
-	.bInterfaceClass =	USB_CLASS_CDC_DATA,
-	.bInterfaceSubClass =	0,
-	.bInterfaceProtocol =	0,
-};
-
-/* ... but the "real" data interface has two bulk endpoints */
-
-static const struct usb_interface_descriptor
-data_intf = {
-	.bLength =		sizeof data_intf,
-	.bDescriptorType =	USB_DT_INTERFACE,
-
-	.bInterfaceNumber =	1,
-	.bAlternateSetting =	1,
-	.bNumEndpoints =	2,
-	.bInterfaceClass =	USB_CLASS_CDC_DATA,
-	.bInterfaceSubClass =	0,
-	.bInterfaceProtocol =	0,
-	.iInterface =		STRING_DATA,
-};
-
-#endif
-
-#ifdef	CONFIG_USB_ETH_RNDIS
-
-/* RNDIS doesn't activate by changing to the "real" altsetting */
-
-static const struct usb_interface_descriptor
-rndis_data_intf = {
-	.bLength =		sizeof rndis_data_intf,
-	.bDescriptorType =	USB_DT_INTERFACE,
-
-	.bInterfaceNumber =	1,
-	.bAlternateSetting =	0,
-	.bNumEndpoints =	2,
-	.bInterfaceClass =	USB_CLASS_CDC_DATA,
-	.bInterfaceSubClass =	0,
-	.bInterfaceProtocol =	0,
-	.iInterface =		STRING_DATA,
-};
-
-#endif
-
-#ifdef DEV_CONFIG_SUBSET
-
-/*
- * "Simple" CDC-subset option is a simple vendor-neutral model that most
- * full speed controllers can handle:  one interface, two bulk endpoints.
- *
- * To assist host side drivers, we fancy it up a bit, and add descriptors
- * so some host side drivers will understand it as a "SAFE" variant.
- */
-
-static const struct usb_interface_descriptor
-subset_data_intf = {
-	.bLength =		sizeof subset_data_intf,
-	.bDescriptorType =	USB_DT_INTERFACE,
-
-	.bInterfaceNumber =	0,
-	.bAlternateSetting =	0,
-	.bNumEndpoints =	2,
-	.bInterfaceClass =      USB_CLASS_COMM,
-	.bInterfaceSubClass =	USB_CDC_SUBCLASS_MDLM,
-	.bInterfaceProtocol =	0,
-	.iInterface =		STRING_DATA,
-};
-
-#endif	/* SUBSET */
-
-
-static struct usb_endpoint_descriptor
-fs_source_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-};
-
-static struct usb_endpoint_descriptor
-fs_sink_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	USB_DIR_OUT,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-};
-
-static const struct usb_descriptor_header *fs_eth_function [11] = {
+static const struct usb_descriptor_header *otg_desc[] = {
 	(struct usb_descriptor_header *) &otg_descriptor,
-#ifdef DEV_CONFIG_CDC
-	/* "cdc" mode descriptors */
-	(struct usb_descriptor_header *) &control_intf,
-	(struct usb_descriptor_header *) &header_desc,
-	(struct usb_descriptor_header *) &union_desc,
-	(struct usb_descriptor_header *) &ether_desc,
-	/* NOTE: status endpoint may need to be removed */
-	(struct usb_descriptor_header *) &fs_status_desc,
-	/* data interface, with altsetting */
-	(struct usb_descriptor_header *) &data_nop_intf,
-	(struct usb_descriptor_header *) &data_intf,
-	(struct usb_descriptor_header *) &fs_source_desc,
-	(struct usb_descriptor_header *) &fs_sink_desc,
-	NULL,
-#endif /* DEV_CONFIG_CDC */
-};
-
-static inline void __init fs_subset_descriptors(void)
-{
-#ifdef DEV_CONFIG_SUBSET
-	/* behavior is "CDC Subset"; extra descriptors say "SAFE" */
-	fs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf;
-	fs_eth_function[2] = (struct usb_descriptor_header *) &header_desc;
-	fs_eth_function[3] = (struct usb_descriptor_header *) &mdlm_desc;
-	fs_eth_function[4] = (struct usb_descriptor_header *) &mdlm_detail_desc;
-	fs_eth_function[5] = (struct usb_descriptor_header *) &ether_desc;
-	fs_eth_function[6] = (struct usb_descriptor_header *) &fs_source_desc;
-	fs_eth_function[7] = (struct usb_descriptor_header *) &fs_sink_desc;
-	fs_eth_function[8] = NULL;
-#else
-	fs_eth_function[1] = NULL;
-#endif
-}
-
-#ifdef	CONFIG_USB_ETH_RNDIS
-static const struct usb_descriptor_header *fs_rndis_function [] = {
-	(struct usb_descriptor_header *) &otg_descriptor,
-	/* control interface matches ACM, not Ethernet */
-	(struct usb_descriptor_header *) &rndis_control_intf,
-	(struct usb_descriptor_header *) &header_desc,
-	(struct usb_descriptor_header *) &call_mgmt_descriptor,
-	(struct usb_descriptor_header *) &acm_descriptor,
-	(struct usb_descriptor_header *) &union_desc,
-	(struct usb_descriptor_header *) &fs_status_desc,
-	/* data interface has no altsetting */
-	(struct usb_descriptor_header *) &rndis_data_intf,
-	(struct usb_descriptor_header *) &fs_source_desc,
-	(struct usb_descriptor_header *) &fs_sink_desc,
 	NULL,
 };
-#endif
 
-/*
- * usb 2.0 devices need to expose both high speed and full speed
- * descriptors, unless they only run at full speed.
- */
 
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
-static struct usb_endpoint_descriptor
-hs_status_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
+/* string IDs are assigned dynamically */
 
-	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	__constant_cpu_to_le16 (STATUS_BYTECOUNT),
-	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4,
-};
-#endif /* DEV_CONFIG_CDC */
+#define STRING_MANUFACTURER_IDX		0
+#define STRING_PRODUCT_IDX		1
 
-static struct usb_endpoint_descriptor
-hs_source_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
+static char manufacturer[50];
 
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16 (512),
+static struct usb_string strings_dev[] = {
+	[STRING_MANUFACTURER_IDX].s = manufacturer,
+	[STRING_PRODUCT_IDX].s = PREFIX DRIVER_DESC,
+	{  } /* end of list */
 };
 
-static struct usb_endpoint_descriptor
-hs_sink_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16 (512),
-};
-
-static struct usb_qualifier_descriptor
-dev_qualifier = {
-	.bLength =		sizeof dev_qualifier,
-	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
-
-	.bcdUSB =		__constant_cpu_to_le16 (0x0200),
-	.bDeviceClass =		USB_CLASS_COMM,
-
-	.bNumConfigurations =	1,
-};
-
-static const struct usb_descriptor_header *hs_eth_function [11] = {
-	(struct usb_descriptor_header *) &otg_descriptor,
-#ifdef DEV_CONFIG_CDC
-	/* "cdc" mode descriptors */
-	(struct usb_descriptor_header *) &control_intf,
-	(struct usb_descriptor_header *) &header_desc,
-	(struct usb_descriptor_header *) &union_desc,
-	(struct usb_descriptor_header *) &ether_desc,
-	/* NOTE: status endpoint may need to be removed */
-	(struct usb_descriptor_header *) &hs_status_desc,
-	/* data interface, with altsetting */
-	(struct usb_descriptor_header *) &data_nop_intf,
-	(struct usb_descriptor_header *) &data_intf,
-	(struct usb_descriptor_header *) &hs_source_desc,
-	(struct usb_descriptor_header *) &hs_sink_desc,
-	NULL,
-#endif /* DEV_CONFIG_CDC */
-};
-
-static inline void __init hs_subset_descriptors(void)
-{
-#ifdef DEV_CONFIG_SUBSET
-	/* behavior is "CDC Subset"; extra descriptors say "SAFE" */
-	hs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf;
-	hs_eth_function[2] = (struct usb_descriptor_header *) &header_desc;
-	hs_eth_function[3] = (struct usb_descriptor_header *) &mdlm_desc;
-	hs_eth_function[4] = (struct usb_descriptor_header *) &mdlm_detail_desc;
-	hs_eth_function[5] = (struct usb_descriptor_header *) &ether_desc;
-	hs_eth_function[6] = (struct usb_descriptor_header *) &hs_source_desc;
-	hs_eth_function[7] = (struct usb_descriptor_header *) &hs_sink_desc;
-	hs_eth_function[8] = NULL;
-#else
-	hs_eth_function[1] = NULL;
-#endif
-}
-
-#ifdef	CONFIG_USB_ETH_RNDIS
-static const struct usb_descriptor_header *hs_rndis_function [] = {
-	(struct usb_descriptor_header *) &otg_descriptor,
-	/* control interface matches ACM, not Ethernet */
-	(struct usb_descriptor_header *) &rndis_control_intf,
-	(struct usb_descriptor_header *) &header_desc,
-	(struct usb_descriptor_header *) &call_mgmt_descriptor,
-	(struct usb_descriptor_header *) &acm_descriptor,
-	(struct usb_descriptor_header *) &union_desc,
-	(struct usb_descriptor_header *) &hs_status_desc,
-	/* data interface has no altsetting */
-	(struct usb_descriptor_header *) &rndis_data_intf,
-	(struct usb_descriptor_header *) &hs_source_desc,
-	(struct usb_descriptor_header *) &hs_sink_desc,
-	NULL,
-};
-#endif
-
-
-/* maxpacket and other transfer characteristics vary by speed. */
-static inline struct usb_endpoint_descriptor *
-ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs,
-		struct usb_endpoint_descriptor *fs)
-{
-	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
-		return hs;
-	return fs;
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* descriptors that are built on-demand */
-
-static char				manufacturer [50];
-static char				product_desc [40] = DRIVER_DESC;
-static char				serial_number [20];
-
-/* address that the host will use ... usually assigned at random */
-static char				ethaddr [2 * ETH_ALEN + 1];
-
-/* static strings, in UTF-8 */
-static struct usb_string		strings [] = {
-	{ STRING_MANUFACTURER,	manufacturer, },
-	{ STRING_PRODUCT,	product_desc, },
-	{ STRING_SERIALNUMBER,	serial_number, },
-	{ STRING_DATA,		"Ethernet Data", },
-	{ STRING_ETHADDR,	ethaddr, },
-#ifdef	DEV_CONFIG_CDC
-	{ STRING_CDC,		"CDC Ethernet", },
-	{ STRING_CONTROL,	"CDC Communications Control", },
-#endif
-#ifdef	DEV_CONFIG_SUBSET
-	{ STRING_SUBSET,	"CDC Ethernet Subset", },
-#endif
-#ifdef	CONFIG_USB_ETH_RNDIS
-	{ STRING_RNDIS,		"RNDIS", },
-	{ STRING_RNDIS_CONTROL,	"RNDIS Communications Control", },
-#endif
-	{  }		/* end of list */
-};
-
-static struct usb_gadget_strings	stringtab = {
+static struct usb_gadget_strings stringtab_dev = {
 	.language	= 0x0409,	/* en-us */
-	.strings	= strings,
+	.strings	= strings_dev,
 };
 
+static struct usb_gadget_strings *dev_strings[] = {
+	&stringtab_dev,
+	NULL,
+};
+
+static u8 hostaddr[ETH_ALEN];
+
+/*-------------------------------------------------------------------------*/
+
 /*
- * one config, two interfaces:  control, data.
- * complications: class descriptors, and an altsetting.
+ * We may not have an RNDIS configuration, but if we do it needs to be
+ * the first one present.  That's to make Microsoft's drivers happy,
+ * and to follow DOCSIS 1.0 (cable modem standard).
  */
-static int
-config_buf(struct usb_gadget *g, u8 *buf, u8 type, unsigned index, int is_otg)
+static int __init rndis_do_config(struct usb_configuration *c)
 {
-	int					len;
-	const struct usb_config_descriptor	*config;
-	const struct usb_descriptor_header	**function;
-	int					hs = 0;
+	/* FIXME alloc iConfiguration string, set it in c->strings */
 
-	if (gadget_is_dualspeed(g)) {
-		hs = (g->speed == USB_SPEED_HIGH);
-		if (type == USB_DT_OTHER_SPEED_CONFIG)
-			hs = !hs;
-	}
-#define which_fn(t)	(hs ? hs_ ## t ## _function : fs_ ## t ## _function)
-
-	if (index >= device_desc.bNumConfigurations)
-		return -EINVAL;
-
-#ifdef	CONFIG_USB_ETH_RNDIS
-	/* list the RNDIS config first, to make Microsoft's drivers
-	 * happy. DOCSIS 1.0 needs this too.
-	 */
-	if (device_desc.bNumConfigurations == 2 && index == 0) {
-		config = &rndis_config;
-		function = which_fn (rndis);
-	} else
-#endif
-	{
-		config = &eth_config;
-		function = which_fn (eth);
+	if (gadget_is_otg(c->cdev->gadget)) {
+		c->descriptors = otg_desc;
+		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 
-	/* for now, don't advertise srp-only devices */
-	if (!is_otg)
-		function++;
-
-	len = usb_gadget_config_buf (config, buf, USB_BUFSIZ, function);
-	if (len < 0)
-		return len;
-	((struct usb_config_descriptor *) buf)->bDescriptorType = type;
-	return len;
+	return rndis_bind_config(c, hostaddr);
 }
 
+static struct usb_configuration rndis_config_driver = {
+	.label			= "RNDIS",
+	.bind			= rndis_do_config,
+	.bConfigurationValue	= 2,
+	/* .iConfiguration = DYNAMIC */
+	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower		= 1,	/* 2 mA, minimal */
+};
+
 /*-------------------------------------------------------------------------*/
 
-static void eth_start (struct eth_dev *dev, gfp_t gfp_flags);
-static int alloc_requests (struct eth_dev *dev, unsigned n, gfp_t gfp_flags);
-
-static int
-set_ether_config (struct eth_dev *dev, gfp_t gfp_flags)
-{
-	int					result = 0;
-	struct usb_gadget			*gadget = dev->gadget;
-
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
-	/* status endpoint used for RNDIS and (optionally) CDC */
-	if (!subset_active(dev) && dev->status_ep) {
-		dev->status = ep_desc (gadget, &hs_status_desc,
-						&fs_status_desc);
-		dev->status_ep->driver_data = dev;
-
-		result = usb_ep_enable (dev->status_ep, dev->status);
-		if (result != 0) {
-			DEBUG (dev, "enable %s --> %d\n",
-				dev->status_ep->name, result);
-			goto done;
-		}
-	}
-#endif
-
-	dev->in = ep_desc(gadget, &hs_source_desc, &fs_source_desc);
-	dev->in_ep->driver_data = dev;
-
-	dev->out = ep_desc(gadget, &hs_sink_desc, &fs_sink_desc);
-	dev->out_ep->driver_data = dev;
-
-	/* With CDC,  the host isn't allowed to use these two data
-	 * endpoints in the default altsetting for the interface.
-	 * so we don't activate them yet.  Reset from SET_INTERFACE.
-	 *
-	 * Strictly speaking RNDIS should work the same: activation is
-	 * a side effect of setting a packet filter.  Deactivation is
-	 * from REMOTE_NDIS_HALT_MSG, reset from REMOTE_NDIS_RESET_MSG.
-	 */
-	if (!cdc_active(dev)) {
-		result = usb_ep_enable (dev->in_ep, dev->in);
-		if (result != 0) {
-			DEBUG(dev, "enable %s --> %d\n",
-				dev->in_ep->name, result);
-			goto done;
-		}
-
-		result = usb_ep_enable (dev->out_ep, dev->out);
-		if (result != 0) {
-			DEBUG (dev, "enable %s --> %d\n",
-				dev->out_ep->name, result);
-			goto done;
-		}
-	}
-
-done:
-	if (result == 0)
-		result = alloc_requests (dev, qlen (gadget), gfp_flags);
-
-	/* on error, disable any endpoints  */
-	if (result < 0) {
-		if (!subset_active(dev) && dev->status_ep)
-			(void) usb_ep_disable (dev->status_ep);
-		dev->status = NULL;
-		(void) usb_ep_disable (dev->in_ep);
-		(void) usb_ep_disable (dev->out_ep);
-		dev->in = NULL;
-		dev->out = NULL;
-	}
-
-	/* activate non-CDC configs right away
-	 * this isn't strictly according to the RNDIS spec
-	 */
-	else if (!cdc_active (dev)) {
-		netif_carrier_on (dev->net);
-		if (netif_running (dev->net)) {
-			spin_unlock (&dev->lock);
-			eth_start (dev, GFP_ATOMIC);
-			spin_lock (&dev->lock);
-		}
-	}
-
-	if (result == 0)
-		DEBUG (dev, "qlen %d\n", qlen (gadget));
-
-	/* caller is responsible for cleanup on error */
-	return result;
-}
-
-static void eth_reset_config (struct eth_dev *dev)
-{
-	struct usb_request	*req;
-
-	if (dev->config == 0)
-		return;
-
-	DEBUG (dev, "%s\n", __func__);
-
-	netif_stop_queue (dev->net);
-	netif_carrier_off (dev->net);
-	rndis_uninit(dev->rndis_config);
-
-	/* disable endpoints, forcing (synchronous) completion of
-	 * pending i/o.  then free the requests.
-	 */
-	if (dev->in) {
-		usb_ep_disable (dev->in_ep);
-		spin_lock(&dev->req_lock);
-		while (likely (!list_empty (&dev->tx_reqs))) {
-			req = container_of (dev->tx_reqs.next,
-						struct usb_request, list);
-			list_del (&req->list);
-
-			spin_unlock(&dev->req_lock);
-			usb_ep_free_request (dev->in_ep, req);
-			spin_lock(&dev->req_lock);
-		}
-		spin_unlock(&dev->req_lock);
-	}
-	if (dev->out) {
-		usb_ep_disable (dev->out_ep);
-		spin_lock(&dev->req_lock);
-		while (likely (!list_empty (&dev->rx_reqs))) {
-			req = container_of (dev->rx_reqs.next,
-						struct usb_request, list);
-			list_del (&req->list);
-
-			spin_unlock(&dev->req_lock);
-			usb_ep_free_request (dev->out_ep, req);
-			spin_lock(&dev->req_lock);
-		}
-		spin_unlock(&dev->req_lock);
-	}
-
-	if (dev->status) {
-		usb_ep_disable (dev->status_ep);
-	}
-	dev->rndis = 0;
-	dev->cdc_filter = 0;
-	dev->config = 0;
-}
-
-/* change our operational config.  must agree with the code
- * that returns config descriptors, and altsetting code.
+/*
+ * We _always_ have an ECM or CDC Subset configuration.
  */
-static int
-eth_set_config (struct eth_dev *dev, unsigned number, gfp_t gfp_flags)
+static int __init eth_do_config(struct usb_configuration *c)
 {
-	int			result = 0;
-	struct usb_gadget	*gadget = dev->gadget;
+	/* FIXME alloc iConfiguration string, set it in c->strings */
 
-	if (gadget_is_sa1100 (gadget)
-			&& dev->config
-			&& atomic_read (&dev->tx_qlen) != 0) {
-		/* tx fifo is full, but we can't clear it...*/
-		INFO (dev, "can't change configurations\n");
-		return -ESPIPE;
-	}
-	eth_reset_config (dev);
-
-	switch (number) {
-	case DEV_CONFIG_VALUE:
-		result = set_ether_config (dev, gfp_flags);
-		break;
-#ifdef	CONFIG_USB_ETH_RNDIS
-	case DEV_RNDIS_CONFIG_VALUE:
-		dev->rndis = 1;
-		result = set_ether_config (dev, gfp_flags);
-		break;
-#endif
-	default:
-		result = -EINVAL;
-		/* FALL THROUGH */
-	case 0:
-		break;
+	if (gadget_is_otg(c->cdev->gadget)) {
+		c->descriptors = otg_desc;
+		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 
-	if (result) {
-		if (number)
-			eth_reset_config (dev);
-		usb_gadget_vbus_draw(dev->gadget,
-				gadget_is_otg(dev->gadget) ? 8 : 100);
-	} else {
-		char *speed;
-		unsigned power;
-
-		power = 2 * eth_config.bMaxPower;
-		usb_gadget_vbus_draw(dev->gadget, power);
-
-		switch (gadget->speed) {
-		case USB_SPEED_FULL:	speed = "full"; break;
-#ifdef CONFIG_USB_GADGET_DUALSPEED
-		case USB_SPEED_HIGH:	speed = "high"; break;
-#endif
-		default:		speed = "?"; break;
-		}
-
-		dev->config = number;
-		INFO (dev, "%s speed config #%d: %d mA, %s, using %s\n",
-				speed, number, power, driver_desc,
-				rndis_active(dev)
-					? "RNDIS"
-					: (cdc_active(dev)
-						? "CDC Ethernet"
-						: "CDC Ethernet Subset"));
-	}
-	return result;
+	if (can_support_ecm(c->cdev->gadget))
+		return ecm_bind_config(c, hostaddr);
+	else
+		return geth_bind_config(c, hostaddr);
 }
 
+static struct usb_configuration eth_config_driver = {
+	/* .label = f(hardware) */
+	.bind			= eth_do_config,
+	.bConfigurationValue	= 1,
+	/* .iConfiguration = DYNAMIC */
+	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower		= 1,	/* 2 mA, minimal */
+};
+
 /*-------------------------------------------------------------------------*/
 
-#ifdef	DEV_CONFIG_CDC
-
-/* The interrupt endpoint is used in CDC networking models (Ethernet, ATM)
- * only to notify the host about link status changes (which we support) or
- * report completion of some encapsulated command (as used in RNDIS).  Since
- * we want this CDC Ethernet code to be vendor-neutral, we don't use that
- * command mechanism; and only one status request is ever queued.
- */
-
-static void eth_status_complete (struct usb_ep *ep, struct usb_request *req)
+static int __init eth_bind(struct usb_composite_dev *cdev)
 {
-	struct usb_cdc_notification	*event = req->buf;
-	int				value = req->status;
-	struct eth_dev			*dev = ep->driver_data;
-
-	/* issue the second notification if host reads the first */
-	if (event->bNotificationType == USB_CDC_NOTIFY_NETWORK_CONNECTION
-			&& value == 0) {
-		__le32	*data = req->buf + sizeof *event;
-
-		event->bmRequestType = 0xA1;
-		event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE;
-		event->wValue = __constant_cpu_to_le16 (0);
-		event->wIndex = __constant_cpu_to_le16 (1);
-		event->wLength = __constant_cpu_to_le16 (8);
-
-		/* SPEED_CHANGE data is up/down speeds in bits/sec */
-		data [0] = data [1] = cpu_to_le32 (BITRATE (dev->gadget));
-
-		req->length = STATUS_BYTECOUNT;
-		value = usb_ep_queue (ep, req, GFP_ATOMIC);
-		DEBUG (dev, "send SPEED_CHANGE --> %d\n", value);
-		if (value == 0)
-			return;
-	} else if (value != -ECONNRESET)
-		DEBUG (dev, "event %02x --> %d\n",
-			event->bNotificationType, value);
-	req->context = NULL;
-}
-
-static void issue_start_status (struct eth_dev *dev)
-{
-	struct usb_request		*req = dev->stat_req;
-	struct usb_cdc_notification	*event;
-	int				value;
-
-	DEBUG (dev, "%s, flush old status first\n", __func__);
-
-	/* flush old status
-	 *
-	 * FIXME ugly idiom, maybe we'd be better with just
-	 * a "cancel the whole queue" primitive since any
-	 * unlink-one primitive has way too many error modes.
-	 * here, we "know" toggle is already clear...
-	 *
-	 * FIXME iff req->context != null just dequeue it
-	 */
-	usb_ep_disable (dev->status_ep);
-	usb_ep_enable (dev->status_ep, dev->status);
-
-	/* 3.8.1 says to issue first NETWORK_CONNECTION, then
-	 * a SPEED_CHANGE.  could be useful in some configs.
-	 */
-	event = req->buf;
-	event->bmRequestType = 0xA1;
-	event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION;
-	event->wValue = __constant_cpu_to_le16 (1);	/* connected */
-	event->wIndex = __constant_cpu_to_le16 (1);
-	event->wLength = 0;
-
-	req->length = sizeof *event;
-	req->complete = eth_status_complete;
-	req->context = dev;
-
-	value = usb_ep_queue (dev->status_ep, req, GFP_ATOMIC);
-	if (value < 0)
-		DEBUG (dev, "status buf queue --> %d\n", value);
-}
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-static void eth_setup_complete (struct usb_ep *ep, struct usb_request *req)
-{
-	if (req->status || req->actual != req->length)
-		DEBUG ((struct eth_dev *) ep->driver_data,
-				"setup complete --> %d, %d/%d\n",
-				req->status, req->actual, req->length);
-}
-
-#ifdef CONFIG_USB_ETH_RNDIS
-
-static void rndis_response_complete (struct usb_ep *ep, struct usb_request *req)
-{
-	if (req->status || req->actual != req->length)
-		DEBUG ((struct eth_dev *) ep->driver_data,
-			"rndis response complete --> %d, %d/%d\n",
-			req->status, req->actual, req->length);
-
-	/* done sending after USB_CDC_GET_ENCAPSULATED_RESPONSE */
-}
-
-static void rndis_command_complete (struct usb_ep *ep, struct usb_request *req)
-{
-	struct eth_dev          *dev = ep->driver_data;
+	int			gcnum;
+	struct usb_gadget	*gadget = cdev->gadget;
 	int			status;
 
-	/* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */
-	spin_lock(&dev->lock);
-	status = rndis_msg_parser (dev->rndis_config, (u8 *) req->buf);
+	/* set up network link layer */
+	status = gether_setup(cdev->gadget, hostaddr);
 	if (status < 0)
-		ERROR(dev, "%s: rndis parse error %d\n", __func__, status);
-	spin_unlock(&dev->lock);
-}
+		return status;
 
-#endif	/* RNDIS */
+	/* set up main config label and device descriptor */
+	if (can_support_ecm(cdev->gadget)) {
+		/* ECM */
+		eth_config_driver.label = "CDC Ethernet (ECM)";
+	} else {
+		/* CDC Subset */
+		eth_config_driver.label = "CDC Subset/SAFE";
 
-/*
- * The setup() callback implements all the ep0 functionality that's not
- * handled lower down.  CDC has a number of less-common features:
- *
- *  - two interfaces:  control, and ethernet data
- *  - Ethernet data interface has two altsettings:  default, and active
- *  - class-specific descriptors for the control interface
- *  - class-specific control requests
- */
-static int
-eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
-{
-	struct eth_dev		*dev = get_gadget_data (gadget);
-	struct usb_request	*req = dev->req;
-	int			value = -EOPNOTSUPP;
-	u16			wIndex = le16_to_cpu(ctrl->wIndex);
-	u16			wValue = le16_to_cpu(ctrl->wValue);
-	u16			wLength = le16_to_cpu(ctrl->wLength);
-
-	/* descriptors just go into the pre-allocated ep0 buffer,
-	 * while config change events may enable network traffic.
-	 */
-	req->complete = eth_setup_complete;
-	switch (ctrl->bRequest) {
-
-	case USB_REQ_GET_DESCRIPTOR:
-		if (ctrl->bRequestType != USB_DIR_IN)
-			break;
-		switch (wValue >> 8) {
-
-		case USB_DT_DEVICE:
-			value = min (wLength, (u16) sizeof device_desc);
-			memcpy (req->buf, &device_desc, value);
-			break;
-		case USB_DT_DEVICE_QUALIFIER:
-			if (!gadget_is_dualspeed(gadget))
-				break;
-			value = min (wLength, (u16) sizeof dev_qualifier);
-			memcpy (req->buf, &dev_qualifier, value);
-			break;
-
-		case USB_DT_OTHER_SPEED_CONFIG:
-			if (!gadget_is_dualspeed(gadget))
-				break;
-			// FALLTHROUGH
-		case USB_DT_CONFIG:
-			value = config_buf(gadget, req->buf,
-					wValue >> 8,
-					wValue & 0xff,
-					gadget_is_otg(gadget));
-			if (value >= 0)
-				value = min (wLength, (u16) value);
-			break;
-
-		case USB_DT_STRING:
-			value = usb_gadget_get_string (&stringtab,
-					wValue & 0xff, req->buf);
-			if (value >= 0)
-				value = min (wLength, (u16) value);
-			break;
-		}
-		break;
-
-	case USB_REQ_SET_CONFIGURATION:
-		if (ctrl->bRequestType != 0)
-			break;
-		if (gadget->a_hnp_support)
-			DEBUG (dev, "HNP available\n");
-		else if (gadget->a_alt_hnp_support)
-			DEBUG (dev, "HNP needs a different root port\n");
-		spin_lock (&dev->lock);
-		value = eth_set_config (dev, wValue, GFP_ATOMIC);
-		spin_unlock (&dev->lock);
-		break;
-	case USB_REQ_GET_CONFIGURATION:
-		if (ctrl->bRequestType != USB_DIR_IN)
-			break;
-		*(u8 *)req->buf = dev->config;
-		value = min (wLength, (u16) 1);
-		break;
-
-	case USB_REQ_SET_INTERFACE:
-		if (ctrl->bRequestType != USB_RECIP_INTERFACE
-				|| !dev->config
-				|| wIndex > 1)
-			break;
-		if (!cdc_active(dev) && wIndex != 0)
-			break;
-		spin_lock (&dev->lock);
-
-		/* PXA hardware partially handles SET_INTERFACE;
-		 * we need to kluge around that interference.
-		 */
-		if (gadget_is_pxa (gadget)) {
-			value = eth_set_config (dev, DEV_CONFIG_VALUE,
-						GFP_ATOMIC);
-			goto done_set_intf;
-		}
-
-#ifdef DEV_CONFIG_CDC
-		switch (wIndex) {
-		case 0:		/* control/master intf */
-			if (wValue != 0)
-				break;
-			if (dev->status) {
-				usb_ep_disable (dev->status_ep);
-				usb_ep_enable (dev->status_ep, dev->status);
-			}
-			value = 0;
-			break;
-		case 1:		/* data intf */
-			if (wValue > 1)
-				break;
-			usb_ep_disable (dev->in_ep);
-			usb_ep_disable (dev->out_ep);
-
-			/* CDC requires the data transfers not be done from
-			 * the default interface setting ... also, setting
-			 * the non-default interface resets filters etc.
-			 */
-			if (wValue == 1) {
-				if (!cdc_active (dev))
-					break;
-				usb_ep_enable (dev->in_ep, dev->in);
-				usb_ep_enable (dev->out_ep, dev->out);
-				dev->cdc_filter = DEFAULT_FILTER;
-				netif_carrier_on (dev->net);
-				if (dev->status)
-					issue_start_status (dev);
-				if (netif_running (dev->net)) {
-					spin_unlock (&dev->lock);
-					eth_start (dev, GFP_ATOMIC);
-					spin_lock (&dev->lock);
-				}
-			} else {
-				netif_stop_queue (dev->net);
-				netif_carrier_off (dev->net);
-			}
-			value = 0;
-			break;
-		}
-#else
-		/* FIXME this is wrong, as is the assumption that
-		 * all non-PXA hardware talks real CDC ...
-		 */
-		dev_warn (&gadget->dev, "set_interface ignored!\n");
-#endif /* DEV_CONFIG_CDC */
-
-done_set_intf:
-		spin_unlock (&dev->lock);
-		break;
-	case USB_REQ_GET_INTERFACE:
-		if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)
-				|| !dev->config
-				|| wIndex > 1)
-			break;
-		if (!(cdc_active(dev) || rndis_active(dev)) && wIndex != 0)
-			break;
-
-		/* for CDC, iff carrier is on, data interface is active. */
-		if (rndis_active(dev) || wIndex != 1)
-			*(u8 *)req->buf = 0;
-		else
-			*(u8 *)req->buf = netif_carrier_ok (dev->net) ? 1 : 0;
-		value = min (wLength, (u16) 1);
-		break;
-
-#ifdef DEV_CONFIG_CDC
-	case USB_CDC_SET_ETHERNET_PACKET_FILTER:
-		/* see 6.2.30: no data, wIndex = interface,
-		 * wValue = packet filter bitmap
-		 */
-		if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE)
-				|| !cdc_active(dev)
-				|| wLength != 0
-				|| wIndex > 1)
-			break;
-		DEBUG (dev, "packet filter %02x\n", wValue);
-		dev->cdc_filter = wValue;
-		value = 0;
-		break;
-
-	/* and potentially:
-	 * case USB_CDC_SET_ETHERNET_MULTICAST_FILTERS:
-	 * case USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER:
-	 * case USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER:
-	 * case USB_CDC_GET_ETHERNET_STATISTIC:
-	 */
-
-#endif /* DEV_CONFIG_CDC */
-
-#ifdef CONFIG_USB_ETH_RNDIS
-	/* RNDIS uses the CDC command encapsulation mechanism to implement
-	 * an RPC scheme, with much getting/setting of attributes by OID.
-	 */
-	case USB_CDC_SEND_ENCAPSULATED_COMMAND:
-		if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE)
-				|| !rndis_active(dev)
-				|| wLength > USB_BUFSIZ
-				|| wValue
-				|| rndis_control_intf.bInterfaceNumber
-					!= wIndex)
-			break;
-		/* read the request, then process it */
-		value = wLength;
-		req->complete = rndis_command_complete;
-		/* later, rndis_control_ack () sends a notification */
-		break;
-
-	case USB_CDC_GET_ENCAPSULATED_RESPONSE:
-		if ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE)
-					== ctrl->bRequestType
-				&& rndis_active(dev)
-				// && wLength >= 0x0400
-				&& !wValue
-				&& rndis_control_intf.bInterfaceNumber
-					== wIndex) {
-			u8 *buf;
-			u32 n;
-
-			/* return the result */
-			buf = rndis_get_next_response(dev->rndis_config, &n);
-			if (buf) {
-				memcpy(req->buf, buf, n);
-				req->complete = rndis_response_complete;
-				rndis_free_response(dev->rndis_config, buf);
-				value = n;
-			}
-			/* else stalls ... spec says to avoid that */
-		}
-		break;
-#endif	/* RNDIS */
-
-	default:
-		VDEBUG (dev,
-			"unknown control req%02x.%02x v%04x i%04x l%d\n",
-			ctrl->bRequestType, ctrl->bRequest,
-			wValue, wIndex, wLength);
+		device_desc.idVendor = cpu_to_le16(SIMPLE_VENDOR_NUM),
+		device_desc.idProduct = cpu_to_le16(SIMPLE_PRODUCT_NUM),
+		device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
 	}
 
-	/* respond with data transfer before status phase? */
-	if (value >= 0) {
-		req->length = value;
-		req->zero = value < wLength
-				&& (value % gadget->ep0->maxpacket) == 0;
-		value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
-		if (value < 0) {
-			DEBUG (dev, "ep_queue --> %d\n", value);
-			req->status = 0;
-			eth_setup_complete (gadget->ep0, req);
-		}
+	if (has_rndis()) {
+		/* RNDIS plus ECM-or-Subset */
+		device_desc.idVendor = cpu_to_le16(RNDIS_VENDOR_NUM),
+		device_desc.idProduct = cpu_to_le16(RNDIS_PRODUCT_NUM),
+		device_desc.bNumConfigurations = 2;
 	}
 
-	/* host either stalls (value < 0) or reports success */
-	return value;
-}
-
-static void
-eth_disconnect (struct usb_gadget *gadget)
-{
-	struct eth_dev		*dev = get_gadget_data (gadget);
-	unsigned long		flags;
-
-	spin_lock_irqsave (&dev->lock, flags);
-	netif_stop_queue (dev->net);
-	netif_carrier_off (dev->net);
-	eth_reset_config (dev);
-	spin_unlock_irqrestore (&dev->lock, flags);
-
-	/* FIXME RNDIS should enter RNDIS_UNINITIALIZED */
-
-	/* next we may get setup() calls to enumerate new connections;
-	 * or an unbind() during shutdown (including removing module).
-	 */
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* NETWORK DRIVER HOOKUP (to the layer above this driver) */
-
-static int eth_change_mtu (struct net_device *net, int new_mtu)
-{
-	struct eth_dev	*dev = netdev_priv(net);
-
-	if (dev->rndis)
-		return -EBUSY;
-
-	if (new_mtu <= ETH_HLEN || new_mtu > ETH_FRAME_LEN)
-		return -ERANGE;
-	/* no zero-length packet read wanted after mtu-sized packets */
-	if (((new_mtu + sizeof (struct ethhdr)) % dev->in_ep->maxpacket) == 0)
-		return -EDOM;
-	net->mtu = new_mtu;
-	return 0;
-}
-
-static struct net_device_stats *eth_get_stats (struct net_device *net)
-{
-	return &((struct eth_dev *)netdev_priv(net))->stats;
-}
-
-static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p)
-{
-	struct eth_dev	*dev = netdev_priv(net);
-	strlcpy(p->driver, shortname, sizeof p->driver);
-	strlcpy(p->version, DRIVER_VERSION, sizeof p->version);
-	strlcpy(p->fw_version, dev->gadget->name, sizeof p->fw_version);
-	strlcpy (p->bus_info, dev->gadget->dev.bus_id, sizeof p->bus_info);
-}
-
-static u32 eth_get_link(struct net_device *net)
-{
-	struct eth_dev	*dev = netdev_priv(net);
-	return dev->gadget->speed != USB_SPEED_UNKNOWN;
-}
-
-static struct ethtool_ops ops = {
-	.get_drvinfo = eth_get_drvinfo,
-	.get_link = eth_get_link
-};
-
-static void defer_kevent (struct eth_dev *dev, int flag)
-{
-	if (test_and_set_bit (flag, &dev->todo))
-		return;
-	if (!schedule_work (&dev->work))
-		ERROR (dev, "kevent %d may have been dropped\n", flag);
-	else
-		DEBUG (dev, "kevent %d scheduled\n", flag);
-}
-
-static void rx_complete (struct usb_ep *ep, struct usb_request *req);
-
-static int
-rx_submit (struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
-{
-	struct sk_buff		*skb;
-	int			retval = -ENOMEM;
-	size_t			size;
-
-	/* Padding up to RX_EXTRA handles minor disagreements with host.
-	 * Normally we use the USB "terminate on short read" convention;
-	 * so allow up to (N*maxpacket), since that memory is normally
-	 * already allocated.  Some hardware doesn't deal well with short
-	 * reads (e.g. DMA must be N*maxpacket), so for now don't trim a
-	 * byte off the end (to force hardware errors on overflow).
-	 *
-	 * RNDIS uses internal framing, and explicitly allows senders to
-	 * pad to end-of-packet.  That's potentially nice for speed,
-	 * but means receivers can't recover synch on their own.
-	 */
-	size = (sizeof (struct ethhdr) + dev->net->mtu + RX_EXTRA);
-	size += dev->out_ep->maxpacket - 1;
-	if (rndis_active(dev))
-		size += sizeof (struct rndis_packet_msg_type);
-	size -= size % dev->out_ep->maxpacket;
-
-	skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags);
-	if (skb == NULL) {
-		DEBUG (dev, "no rx skb\n");
-		goto enomem;
-	}
-
-	/* Some platforms perform better when IP packets are aligned,
-	 * but on at least one, checksumming fails otherwise.  Note:
-	 * RNDIS headers involve variable numbers of LE32 values.
-	 */
-	skb_reserve(skb, NET_IP_ALIGN);
-
-	req->buf = skb->data;
-	req->length = size;
-	req->complete = rx_complete;
-	req->context = skb;
-
-	retval = usb_ep_queue (dev->out_ep, req, gfp_flags);
-	if (retval == -ENOMEM)
-enomem:
-		defer_kevent (dev, WORK_RX_MEMORY);
-	if (retval) {
-		DEBUG (dev, "rx submit --> %d\n", retval);
-		if (skb)
-			dev_kfree_skb_any(skb);
-		spin_lock(&dev->req_lock);
-		list_add (&req->list, &dev->rx_reqs);
-		spin_unlock(&dev->req_lock);
-	}
-	return retval;
-}
-
-static void rx_complete (struct usb_ep *ep, struct usb_request *req)
-{
-	struct sk_buff	*skb = req->context;
-	struct eth_dev	*dev = ep->driver_data;
-	int		status = req->status;
-
-	switch (status) {
-
-	/* normal completion */
-	case 0:
-		skb_put (skb, req->actual);
-		/* we know MaxPacketsPerTransfer == 1 here */
-		if (rndis_active(dev))
-			status = rndis_rm_hdr (skb);
-		if (status < 0
-				|| ETH_HLEN > skb->len
-				|| skb->len > ETH_FRAME_LEN) {
-			dev->stats.rx_errors++;
-			dev->stats.rx_length_errors++;
-			DEBUG (dev, "rx length %d\n", skb->len);
-			break;
-		}
-
-		skb->protocol = eth_type_trans (skb, dev->net);
-		dev->stats.rx_packets++;
-		dev->stats.rx_bytes += skb->len;
-
-		/* no buffer copies needed, unless hardware can't
-		 * use skb buffers.
-		 */
-		status = netif_rx (skb);
-		skb = NULL;
-		break;
-
-	/* software-driven interface shutdown */
-	case -ECONNRESET:		// unlink
-	case -ESHUTDOWN:		// disconnect etc
-		VDEBUG (dev, "rx shutdown, code %d\n", status);
-		goto quiesce;
-
-	/* for hardware automagic (such as pxa) */
-	case -ECONNABORTED:		// endpoint reset
-		DEBUG (dev, "rx %s reset\n", ep->name);
-		defer_kevent (dev, WORK_RX_MEMORY);
-quiesce:
-		dev_kfree_skb_any (skb);
-		goto clean;
-
-	/* data overrun */
-	case -EOVERFLOW:
-		dev->stats.rx_over_errors++;
-		// FALLTHROUGH
-
-	default:
-		dev->stats.rx_errors++;
-		DEBUG (dev, "rx status %d\n", status);
-		break;
-	}
-
-	if (skb)
-		dev_kfree_skb_any (skb);
-	if (!netif_running (dev->net)) {
-clean:
-		spin_lock(&dev->req_lock);
-		list_add (&req->list, &dev->rx_reqs);
-		spin_unlock(&dev->req_lock);
-		req = NULL;
-	}
-	if (req)
-		rx_submit (dev, req, GFP_ATOMIC);
-}
-
-static int prealloc (struct list_head *list, struct usb_ep *ep,
-			unsigned n, gfp_t gfp_flags)
-{
-	unsigned		i;
-	struct usb_request	*req;
-
-	if (!n)
-		return -ENOMEM;
-
-	/* queue/recycle up to N requests */
-	i = n;
-	list_for_each_entry (req, list, list) {
-		if (i-- == 0)
-			goto extra;
-	}
-	while (i--) {
-		req = usb_ep_alloc_request (ep, gfp_flags);
-		if (!req)
-			return list_empty (list) ? -ENOMEM : 0;
-		list_add (&req->list, list);
-	}
-	return 0;
-
-extra:
-	/* free extras */
-	for (;;) {
-		struct list_head	*next;
-
-		next = req->list.next;
-		list_del (&req->list);
-		usb_ep_free_request (ep, req);
-
-		if (next == list)
-			break;
-
-		req = container_of (next, struct usb_request, list);
-	}
-	return 0;
-}
-
-static int alloc_requests (struct eth_dev *dev, unsigned n, gfp_t gfp_flags)
-{
-	int status;
-
-	spin_lock(&dev->req_lock);
-	status = prealloc (&dev->tx_reqs, dev->in_ep, n, gfp_flags);
-	if (status < 0)
-		goto fail;
-	status = prealloc (&dev->rx_reqs, dev->out_ep, n, gfp_flags);
-	if (status < 0)
-		goto fail;
-	goto done;
-fail:
-	DEBUG (dev, "can't alloc requests\n");
-done:
-	spin_unlock(&dev->req_lock);
-	return status;
-}
-
-static void rx_fill (struct eth_dev *dev, gfp_t gfp_flags)
-{
-	struct usb_request	*req;
-	unsigned long		flags;
-
-	/* fill unused rxq slots with some skb */
-	spin_lock_irqsave(&dev->req_lock, flags);
-	while (!list_empty (&dev->rx_reqs)) {
-		req = container_of (dev->rx_reqs.next,
-				struct usb_request, list);
-		list_del_init (&req->list);
-		spin_unlock_irqrestore(&dev->req_lock, flags);
-
-		if (rx_submit (dev, req, gfp_flags) < 0) {
-			defer_kevent (dev, WORK_RX_MEMORY);
-			return;
-		}
-
-		spin_lock_irqsave(&dev->req_lock, flags);
-	}
-	spin_unlock_irqrestore(&dev->req_lock, flags);
-}
-
-static void eth_work (struct work_struct *work)
-{
-	struct eth_dev	*dev = container_of(work, struct eth_dev, work);
-
-	if (test_and_clear_bit (WORK_RX_MEMORY, &dev->todo)) {
-		if (netif_running (dev->net))
-			rx_fill (dev, GFP_KERNEL);
-	}
-
-	if (dev->todo)
-		DEBUG (dev, "work done, flags = 0x%lx\n", dev->todo);
-}
-
-static void tx_complete (struct usb_ep *ep, struct usb_request *req)
-{
-	struct sk_buff	*skb = req->context;
-	struct eth_dev	*dev = ep->driver_data;
-
-	switch (req->status) {
-	default:
-		dev->stats.tx_errors++;
-		VDEBUG (dev, "tx err %d\n", req->status);
-		/* FALLTHROUGH */
-	case -ECONNRESET:		// unlink
-	case -ESHUTDOWN:		// disconnect etc
-		break;
-	case 0:
-		dev->stats.tx_bytes += skb->len;
-	}
-	dev->stats.tx_packets++;
-
-	spin_lock(&dev->req_lock);
-	list_add (&req->list, &dev->tx_reqs);
-	spin_unlock(&dev->req_lock);
-	dev_kfree_skb_any (skb);
-
-	atomic_dec (&dev->tx_qlen);
-	if (netif_carrier_ok (dev->net))
-		netif_wake_queue (dev->net);
-}
-
-static inline int eth_is_promisc (struct eth_dev *dev)
-{
-	/* no filters for the CDC subset; always promisc */
-	if (subset_active (dev))
-		return 1;
-	return dev->cdc_filter & USB_CDC_PACKET_TYPE_PROMISCUOUS;
-}
-
-static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
-{
-	struct eth_dev		*dev = netdev_priv(net);
-	int			length = skb->len;
-	int			retval;
-	struct usb_request	*req = NULL;
-	unsigned long		flags;
-
-	/* apply outgoing CDC or RNDIS filters */
-	if (!eth_is_promisc (dev)) {
-		u8		*dest = skb->data;
-
-		if (is_multicast_ether_addr(dest)) {
-			u16	type;
-
-			/* ignores USB_CDC_PACKET_TYPE_MULTICAST and host
-			 * SET_ETHERNET_MULTICAST_FILTERS requests
-			 */
-			if (is_broadcast_ether_addr(dest))
-				type = USB_CDC_PACKET_TYPE_BROADCAST;
-			else
-				type = USB_CDC_PACKET_TYPE_ALL_MULTICAST;
-			if (!(dev->cdc_filter & type)) {
-				dev_kfree_skb_any (skb);
-				return 0;
-			}
-		}
-		/* ignores USB_CDC_PACKET_TYPE_DIRECTED */
-	}
-
-	spin_lock_irqsave(&dev->req_lock, flags);
-	/*
-	 * this freelist can be empty if an interrupt triggered disconnect()
-	 * and reconfigured the gadget (shutting down this queue) after the
-	 * network stack decided to xmit but before we got the spinlock.
-	 */
-	if (list_empty(&dev->tx_reqs)) {
-		spin_unlock_irqrestore(&dev->req_lock, flags);
-		return 1;
-	}
-
-	req = container_of (dev->tx_reqs.next, struct usb_request, list);
-	list_del (&req->list);
-
-	/* temporarily stop TX queue when the freelist empties */
-	if (list_empty (&dev->tx_reqs))
-		netif_stop_queue (net);
-	spin_unlock_irqrestore(&dev->req_lock, flags);
-
-	/* no buffer copies needed, unless the network stack did it
-	 * or the hardware can't use skb buffers.
-	 * or there's not enough space for any RNDIS headers we need
-	 */
-	if (rndis_active(dev)) {
-		struct sk_buff	*skb_rndis;
-
-		skb_rndis = skb_realloc_headroom (skb,
-				sizeof (struct rndis_packet_msg_type));
-		if (!skb_rndis)
-			goto drop;
-
-		dev_kfree_skb_any (skb);
-		skb = skb_rndis;
-		rndis_add_hdr (skb);
-		length = skb->len;
-	}
-	req->buf = skb->data;
-	req->context = skb;
-	req->complete = tx_complete;
-
-	/* use zlp framing on tx for strict CDC-Ether conformance,
-	 * though any robust network rx path ignores extra padding.
-	 * and some hardware doesn't like to write zlps.
-	 */
-	req->zero = 1;
-	if (!dev->zlp && (length % dev->in_ep->maxpacket) == 0)
-		length++;
-
-	req->length = length;
-
-	/* throttle highspeed IRQ rate back slightly */
-	if (gadget_is_dualspeed(dev->gadget))
-		req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH)
-			? ((atomic_read(&dev->tx_qlen) % qmult) != 0)
-			: 0;
-
-	retval = usb_ep_queue (dev->in_ep, req, GFP_ATOMIC);
-	switch (retval) {
-	default:
-		DEBUG (dev, "tx queue err %d\n", retval);
-		break;
-	case 0:
-		net->trans_start = jiffies;
-		atomic_inc (&dev->tx_qlen);
-	}
-
-	if (retval) {
-drop:
-		dev->stats.tx_dropped++;
-		dev_kfree_skb_any (skb);
-		spin_lock_irqsave(&dev->req_lock, flags);
-		if (list_empty (&dev->tx_reqs))
-			netif_start_queue (net);
-		list_add (&req->list, &dev->tx_reqs);
-		spin_unlock_irqrestore(&dev->req_lock, flags);
-	}
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#ifdef CONFIG_USB_ETH_RNDIS
-
-/* The interrupt endpoint is used in RNDIS to notify the host when messages
- * other than data packets are available ... notably the REMOTE_NDIS_*_CMPLT
- * messages, but also REMOTE_NDIS_INDICATE_STATUS_MSG and potentially even
- * REMOTE_NDIS_KEEPALIVE_MSG.
- *
- * The RNDIS control queue is processed by GET_ENCAPSULATED_RESPONSE, and
- * normally just one notification will be queued.
- */
-
-static struct usb_request *eth_req_alloc (struct usb_ep *, unsigned, gfp_t);
-static void eth_req_free (struct usb_ep *ep, struct usb_request *req);
-
-static void
-rndis_control_ack_complete (struct usb_ep *ep, struct usb_request *req)
-{
-	struct eth_dev          *dev = ep->driver_data;
-
-	if (req->status || req->actual != req->length)
-		DEBUG (dev,
-			"rndis control ack complete --> %d, %d/%d\n",
-			req->status, req->actual, req->length);
-	req->context = NULL;
-
-	if (req != dev->stat_req)
-		eth_req_free(ep, req);
-}
-
-static int rndis_control_ack (struct net_device *net)
-{
-	struct eth_dev          *dev = netdev_priv(net);
-	int                     length;
-	struct usb_request      *resp = dev->stat_req;
-
-	/* in case RNDIS calls this after disconnect */
-	if (!dev->status) {
-		DEBUG (dev, "status ENODEV\n");
-		return -ENODEV;
-	}
-
-	/* in case queue length > 1 */
-	if (resp->context) {
-		resp = eth_req_alloc (dev->status_ep, 8, GFP_ATOMIC);
-		if (!resp)
-			return -ENOMEM;
-	}
-
-	/* Send RNDIS RESPONSE_AVAILABLE notification;
-	 * USB_CDC_NOTIFY_RESPONSE_AVAILABLE should work too
-	 */
-	resp->length = 8;
-	resp->complete = rndis_control_ack_complete;
-	resp->context = dev;
-
-	*((__le32 *) resp->buf) = __constant_cpu_to_le32 (1);
-	*((__le32 *) resp->buf + 1) = __constant_cpu_to_le32 (0);
-
-	length = usb_ep_queue (dev->status_ep, resp, GFP_ATOMIC);
-	if (length < 0) {
-		resp->status = 0;
-		rndis_control_ack_complete (dev->status_ep, resp);
-	}
-
-	return 0;
-}
-
-#else
-
-#define	rndis_control_ack	NULL
-
-#endif	/* RNDIS */
-
-static void eth_start (struct eth_dev *dev, gfp_t gfp_flags)
-{
-	DEBUG (dev, "%s\n", __func__);
-
-	/* fill the rx queue */
-	rx_fill (dev, gfp_flags);
-
-	/* and open the tx floodgates */
-	atomic_set (&dev->tx_qlen, 0);
-	netif_wake_queue (dev->net);
-	if (rndis_active(dev)) {
-		rndis_set_param_medium (dev->rndis_config,
-					NDIS_MEDIUM_802_3,
-					BITRATE(dev->gadget)/100);
-		(void) rndis_signal_connect (dev->rndis_config);
-	}
-}
-
-static int eth_open (struct net_device *net)
-{
-	struct eth_dev		*dev = netdev_priv(net);
-
-	DEBUG (dev, "%s\n", __func__);
-	if (netif_carrier_ok (dev->net))
-		eth_start (dev, GFP_KERNEL);
-	return 0;
-}
-
-static int eth_stop (struct net_device *net)
-{
-	struct eth_dev		*dev = netdev_priv(net);
-
-	VDEBUG (dev, "%s\n", __func__);
-	netif_stop_queue (net);
-
-	DEBUG (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n",
-		dev->stats.rx_packets, dev->stats.tx_packets,
-		dev->stats.rx_errors, dev->stats.tx_errors
-		);
-
-	/* ensure there are no more active requests */
-	if (dev->config) {
-		usb_ep_disable (dev->in_ep);
-		usb_ep_disable (dev->out_ep);
-		if (netif_carrier_ok (dev->net)) {
-			DEBUG (dev, "host still using in/out endpoints\n");
-			// FIXME idiom may leave toggle wrong here
-			usb_ep_enable (dev->in_ep, dev->in);
-			usb_ep_enable (dev->out_ep, dev->out);
-		}
-		if (dev->status_ep) {
-			usb_ep_disable (dev->status_ep);
-			usb_ep_enable (dev->status_ep, dev->status);
-		}
-	}
-
-	if (rndis_active(dev)) {
-		rndis_set_param_medium(dev->rndis_config, NDIS_MEDIUM_802_3, 0);
-		(void) rndis_signal_disconnect (dev->rndis_config);
-	}
-
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static struct usb_request *
-eth_req_alloc (struct usb_ep *ep, unsigned size, gfp_t gfp_flags)
-{
-	struct usb_request	*req;
-
-	req = usb_ep_alloc_request (ep, gfp_flags);
-	if (!req)
-		return NULL;
-
-	req->buf = kmalloc (size, gfp_flags);
-	if (!req->buf) {
-		usb_ep_free_request (ep, req);
-		req = NULL;
-	}
-	return req;
-}
-
-static void
-eth_req_free (struct usb_ep *ep, struct usb_request *req)
-{
-	kfree (req->buf);
-	usb_ep_free_request (ep, req);
-}
-
-
-static void /* __init_or_exit */
-eth_unbind (struct usb_gadget *gadget)
-{
-	struct eth_dev		*dev = get_gadget_data (gadget);
-
-	DEBUG (dev, "unbind\n");
-	rndis_deregister (dev->rndis_config);
-	rndis_exit ();
-
-	/* we've already been disconnected ... no i/o is active */
-	if (dev->req) {
-		eth_req_free (gadget->ep0, dev->req);
-		dev->req = NULL;
-	}
-	if (dev->stat_req) {
-		eth_req_free (dev->status_ep, dev->stat_req);
-		dev->stat_req = NULL;
-	}
-
-	unregister_netdev (dev->net);
-	free_netdev(dev->net);
-
-	/* assuming we used keventd, it must quiesce too */
-	flush_scheduled_work ();
-	set_gadget_data (gadget, NULL);
-}
-
-static u8 __init nibble (unsigned char c)
-{
-	if (likely (isdigit (c)))
-		return c - '0';
-	c = toupper (c);
-	if (likely (isxdigit (c)))
-		return 10 + c - 'A';
-	return 0;
-}
-
-static int __init get_ether_addr(const char *str, u8 *dev_addr)
-{
-	if (str) {
-		unsigned	i;
-
-		for (i = 0; i < 6; i++) {
-			unsigned char num;
-
-			if((*str == '.') || (*str == ':'))
-				str++;
-			num = nibble(*str++) << 4;
-			num |= (nibble(*str++));
-			dev_addr [i] = num;
-		}
-		if (is_valid_ether_addr (dev_addr))
-			return 0;
-	}
-	random_ether_addr(dev_addr);
-	return 1;
-}
-
-static int __init
-eth_bind (struct usb_gadget *gadget)
-{
-	struct eth_dev		*dev;
-	struct net_device	*net;
-	u8			cdc = 1, zlp = 1, rndis = 1;
-	struct usb_ep		*in_ep, *out_ep, *status_ep = NULL;
-	int			status = -ENOMEM;
-	int			gcnum;
-
-	/* these flags are only ever cleared; compiler take note */
-#ifndef	DEV_CONFIG_CDC
-	cdc = 0;
-#endif
-#ifndef	CONFIG_USB_ETH_RNDIS
-	rndis = 0;
-#endif
-
-	/* Because most host side USB stacks handle CDC Ethernet, that
-	 * standard protocol is _strongly_ preferred for interop purposes.
-	 * (By everyone except Microsoft.)
-	 */
-	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;
-		rndis = 0;
-	} else if (gadget_is_sa1100 (gadget)) {
-		/* hardware can't write zlps */
-		zlp = 0;
-		/* sa1100 CAN do CDC, without status endpoint ... we use
-		 * non-CDC to be compatible with ARM Linux-2.4 "usb-eth".
-		 */
-		cdc = 0;
-	}
-
-	gcnum = usb_gadget_controller_number (gadget);
+	gcnum = usb_gadget_controller_number(gadget);
 	if (gcnum >= 0)
-		device_desc.bcdDevice = cpu_to_le16 (0x0200 + gcnum);
+		device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);
 	else {
-		/* can't assume CDC works.  don't want to default to
-		 * anything less functional on CDC-capable hardware,
-		 * so we fail in this case.
+		/* We assume that can_support_ecm() tells the truth;
+		 * but if the controller isn't recognized at all then
+		 * that assumption is a bit more likely to be wrong.
 		 */
-		dev_err (&gadget->dev,
-			"controller '%s' not recognized\n",
-			gadget->name);
-		return -ENODEV;
+		WARN(cdev, "controller '%s' not recognized; trying %s\n",
+				gadget->name,
+				eth_config_driver.label);
+		device_desc.bcdDevice =
+			__constant_cpu_to_le16(0x0300 | 0x0099);
 	}
-	snprintf (manufacturer, sizeof manufacturer, "%s %s/%s",
+
+
+	/* Allocate string descriptor numbers ... note that string
+	 * contents can be overridden by the composite_dev glue.
+	 */
+
+	/* device descriptor strings: manufacturer, product */
+	snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
 		init_utsname()->sysname, init_utsname()->release,
 		gadget->name);
-
-	/* If there's an RNDIS configuration, that's what Windows wants to
-	 * be using ... so use these product IDs here and in the "linux.inf"
-	 * needed to install MSFT drivers.  Current Linux kernels will use
-	 * the second configuration if it's CDC Ethernet, and need some help
-	 * to choose the right configuration otherwise.
-	 */
-	if (rndis) {
-		device_desc.idVendor =
-			__constant_cpu_to_le16(RNDIS_VENDOR_NUM);
-		device_desc.idProduct =
-			__constant_cpu_to_le16(RNDIS_PRODUCT_NUM);
-		snprintf (product_desc, sizeof product_desc,
-			"RNDIS/%s", driver_desc);
-
-	/* CDC subset ... recognized by Linux since 2.4.10, but Windows
-	 * drivers aren't widely available.  (That may be improved by
-	 * supporting one submode of the "SAFE" variant of MDLM.)
-	 */
-	} else if (!cdc) {
-		device_desc.idVendor =
-			__constant_cpu_to_le16(SIMPLE_VENDOR_NUM);
-		device_desc.idProduct =
-			__constant_cpu_to_le16(SIMPLE_PRODUCT_NUM);
-	}
-
-	/* support optional vendor/distro customization */
-	if (idVendor) {
-		if (!idProduct) {
-			dev_err (&gadget->dev, "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);
-	if (iProduct)
-		strlcpy (product_desc, iProduct, sizeof product_desc);
-	if (iSerialNumber) {
-		device_desc.iSerialNumber = STRING_SERIALNUMBER,
-		strlcpy(serial_number, iSerialNumber, sizeof serial_number);
-	}
-
-	/* all we really need is bulk IN/OUT */
-	usb_ep_autoconfig_reset (gadget);
-	in_ep = usb_ep_autoconfig (gadget, &fs_source_desc);
-	if (!in_ep) {
-autoconf_fail:
-		dev_err (&gadget->dev,
-			"can't autoconfigure on %s\n",
-			gadget->name);
-		return -ENODEV;
-	}
-	in_ep->driver_data = in_ep;	/* claim */
-
-	out_ep = usb_ep_autoconfig (gadget, &fs_sink_desc);
-	if (!out_ep)
-		goto autoconf_fail;
-	out_ep->driver_data = out_ep;	/* claim */
-
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
-	/* CDC Ethernet control interface doesn't require a status endpoint.
-	 * Since some hosts expect one, try to allocate one anyway.
-	 */
-	if (cdc || rndis) {
-		status_ep = usb_ep_autoconfig (gadget, &fs_status_desc);
-		if (status_ep) {
-			status_ep->driver_data = status_ep;	/* claim */
-		} else if (rndis) {
-			dev_err (&gadget->dev,
-				"can't run RNDIS on %s\n",
-				gadget->name);
-			return -ENODEV;
-#ifdef DEV_CONFIG_CDC
-		/* pxa25x only does CDC subset; often used with RNDIS */
-		} else if (cdc) {
-			control_intf.bNumEndpoints = 0;
-			/* FIXME remove endpoint from descriptor list */
-#endif
-		}
-	}
-#endif
-
-	/* one config:  cdc, else minimal subset */
-	if (!cdc) {
-		eth_config.bNumInterfaces = 1;
-		eth_config.iConfiguration = STRING_SUBSET;
-
-		/* use functions to set these up, in case we're built to work
-		 * with multiple controllers and must override CDC Ethernet.
-		 */
-		fs_subset_descriptors();
-		hs_subset_descriptors();
-	}
-
-	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
-	usb_gadget_set_selfpowered (gadget);
-
-	/* For now RNDIS is always a second config */
-	if (rndis)
-		device_desc.bNumConfigurations = 2;
-
-	if (gadget_is_dualspeed(gadget)) {
-		if (rndis)
-			dev_qualifier.bNumConfigurations = 2;
-		else if (!cdc)
-			dev_qualifier.bDeviceClass = USB_CLASS_VENDOR_SPEC;
-
-		/* assumes ep0 uses the same value for both speeds ... */
-		dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
-
-		/* and that all endpoints are dual-speed */
-		hs_source_desc.bEndpointAddress =
-				fs_source_desc.bEndpointAddress;
-		hs_sink_desc.bEndpointAddress =
-				fs_sink_desc.bEndpointAddress;
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
-		if (status_ep)
-			hs_status_desc.bEndpointAddress =
-					fs_status_desc.bEndpointAddress;
-#endif
-	}
-
-	if (gadget_is_otg(gadget)) {
-		otg_descriptor.bmAttributes |= USB_OTG_HNP,
-		eth_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
-		eth_config.bMaxPower = 4;
-#ifdef	CONFIG_USB_ETH_RNDIS
-		rndis_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
-		rndis_config.bMaxPower = 4;
-#endif
-	}
-
-	net = alloc_etherdev (sizeof *dev);
-	if (!net)
-		return status;
-	dev = netdev_priv(net);
-	spin_lock_init (&dev->lock);
-	spin_lock_init (&dev->req_lock);
-	INIT_WORK (&dev->work, eth_work);
-	INIT_LIST_HEAD (&dev->tx_reqs);
-	INIT_LIST_HEAD (&dev->rx_reqs);
-
-	/* network device setup */
-	dev->net = net;
-	strcpy (net->name, "usb%d");
-	dev->cdc = cdc;
-	dev->zlp = zlp;
-
-	dev->in_ep = in_ep;
-	dev->out_ep = out_ep;
-	dev->status_ep = status_ep;
-
-	/* Module params for these addresses should come from ID proms.
-	 * The host side address is used with CDC and RNDIS, and commonly
-	 * ends up in a persistent config database.  It's not clear if
-	 * host side code for the SAFE thing cares -- its original BLAN
-	 * thing didn't, Sharp never assigned those addresses on Zaurii.
-	 */
-	if (get_ether_addr(dev_addr, net->dev_addr))
-		dev_warn(&gadget->dev,
-			"using random %s ethernet address\n", "self");
-	if (get_ether_addr(host_addr, dev->host_mac))
-		dev_warn(&gadget->dev,
-			"using random %s ethernet address\n", "host");
-	snprintf (ethaddr, sizeof ethaddr, "%02X%02X%02X%02X%02X%02X",
-		dev->host_mac [0], dev->host_mac [1],
-		dev->host_mac [2], dev->host_mac [3],
-		dev->host_mac [4], dev->host_mac [5]);
-
-	if (rndis) {
-		status = rndis_init();
-		if (status < 0) {
-			dev_err (&gadget->dev, "can't init RNDIS, %d\n",
-				status);
-			goto fail;
-		}
-	}
-
-	net->change_mtu = eth_change_mtu;
-	net->get_stats = eth_get_stats;
-	net->hard_start_xmit = eth_start_xmit;
-	net->open = eth_open;
-	net->stop = eth_stop;
-	// watchdog_timeo, tx_timeout ...
-	// set_multicast_list
-	SET_ETHTOOL_OPS(net, &ops);
-
-	/* preallocate control message data and buffer */
-	dev->req = eth_req_alloc (gadget->ep0, USB_BUFSIZ, GFP_KERNEL);
-	if (!dev->req)
-		goto fail;
-	dev->req->complete = eth_setup_complete;
-
-	/* ... and maybe likewise for status transfer */
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
-	if (dev->status_ep) {
-		dev->stat_req = eth_req_alloc (dev->status_ep,
-					STATUS_BYTECOUNT, GFP_KERNEL);
-		if (!dev->stat_req) {
-			eth_req_free (gadget->ep0, dev->req);
-			goto fail;
-		}
-		dev->stat_req->context = NULL;
-	}
-#endif
-
-	/* finish hookup to lower layer ... */
-	dev->gadget = gadget;
-	set_gadget_data (gadget, dev);
-	gadget->ep0->driver_data = dev;
-
-	/* two kinds of host-initiated state changes:
-	 *  - iff DATA transfer is active, carrier is "on"
-	 *  - tx queueing enabled if open *and* carrier is "on"
-	 */
-	netif_stop_queue (dev->net);
-	netif_carrier_off (dev->net);
-
-	SET_NETDEV_DEV (dev->net, &gadget->dev);
-	status = register_netdev (dev->net);
+	status = usb_string_id(cdev);
 	if (status < 0)
-		goto fail1;
+		goto fail;
+	strings_dev[STRING_MANUFACTURER_IDX].id = status;
+	device_desc.iManufacturer = status;
 
-	INFO (dev, "%s, version: " DRIVER_VERSION "\n", driver_desc);
-	INFO (dev, "using %s, OUT %s IN %s%s%s\n", gadget->name,
-		out_ep->name, in_ep->name,
-		status_ep ? " STATUS " : "",
-		status_ep ? status_ep->name : ""
-		);
-	INFO (dev, "MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
-		net->dev_addr [0], net->dev_addr [1],
-		net->dev_addr [2], net->dev_addr [3],
-		net->dev_addr [4], net->dev_addr [5]);
+	status = usb_string_id(cdev);
+	if (status < 0)
+		goto fail;
+	strings_dev[STRING_PRODUCT_IDX].id = status;
+	device_desc.iProduct = status;
 
-	if (cdc || rndis)
-		INFO (dev, "HOST MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
-			dev->host_mac [0], dev->host_mac [1],
-			dev->host_mac [2], dev->host_mac [3],
-			dev->host_mac [4], dev->host_mac [5]);
-
-	if (rndis) {
-		u32	vendorID = 0;
-
-		/* FIXME RNDIS vendor id == "vendor NIC code" == ? */
-
-		dev->rndis_config = rndis_register (rndis_control_ack);
-		if (dev->rndis_config < 0) {
-fail0:
-			unregister_netdev (dev->net);
-			status = -ENODEV;
+	/* register our configuration(s); RNDIS first, if it's used */
+	if (has_rndis()) {
+		status = usb_add_config(cdev, &rndis_config_driver);
+		if (status < 0)
 			goto fail;
-		}
-
-		/* these set up a lot of the OIDs that RNDIS needs */
-		rndis_set_host_mac (dev->rndis_config, dev->host_mac);
-		if (rndis_set_param_dev (dev->rndis_config, dev->net,
-					 &dev->stats, &dev->cdc_filter))
-			goto fail0;
-		if (rndis_set_param_vendor(dev->rndis_config, vendorID,
-					manufacturer))
-			goto fail0;
-		if (rndis_set_param_medium(dev->rndis_config,
-					NDIS_MEDIUM_802_3, 0))
-			goto fail0;
-		INFO (dev, "RNDIS ready\n");
 	}
 
-	return status;
+	status = usb_add_config(cdev, &eth_config_driver);
+	if (status < 0)
+		goto fail;
 
-fail1:
-	dev_dbg(&gadget->dev, "register_netdev failed, %d\n", status);
+	INFO(cdev, "%s, version: " DRIVER_VERSION "\n", DRIVER_DESC);
+
+	return 0;
+
 fail:
-	eth_unbind (gadget);
+	gether_cleanup();
 	return status;
 }
 
-/*-------------------------------------------------------------------------*/
-
-static void
-eth_suspend (struct usb_gadget *gadget)
+static int __exit eth_unbind(struct usb_composite_dev *cdev)
 {
-	struct eth_dev		*dev = get_gadget_data (gadget);
-
-	DEBUG (dev, "suspend\n");
-	dev->suspended = 1;
+	gether_cleanup();
+	return 0;
 }
 
-static void
-eth_resume (struct usb_gadget *gadget)
-{
-	struct eth_dev		*dev = get_gadget_data (gadget);
-
-	DEBUG (dev, "resume\n");
-	dev->suspended = 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static struct usb_gadget_driver eth_driver = {
-	.speed		= DEVSPEED,
-
-	.function	= (char *) driver_desc,
+static struct usb_composite_driver eth_driver = {
+	.name		= "g_ether",
+	.dev		= &device_desc,
+	.strings	= dev_strings,
 	.bind		= eth_bind,
-	.unbind		= eth_unbind,
-
-	.setup		= eth_setup,
-	.disconnect	= eth_disconnect,
-
-	.suspend	= eth_suspend,
-	.resume		= eth_resume,
-
-	.driver	= {
-		.name		= (char *) shortname,
-		.owner		= THIS_MODULE,
-	},
+	.unbind		= __exit_p(eth_unbind),
 };
 
-MODULE_DESCRIPTION (DRIVER_DESC);
-MODULE_AUTHOR ("David Brownell, Benedikt Spanger");
-MODULE_LICENSE ("GPL");
+MODULE_DESCRIPTION(PREFIX DRIVER_DESC);
+MODULE_AUTHOR("David Brownell, Benedikt Spanger");
+MODULE_LICENSE("GPL");
 
-
-static int __init init (void)
+static int __init init(void)
 {
-	return usb_gadget_register_driver (&eth_driver);
+	return usb_composite_register(&eth_driver);
 }
-module_init (init);
+module_init(init);
 
-static void __exit cleanup (void)
+static void __exit cleanup(void)
 {
-	usb_gadget_unregister_driver (&eth_driver);
+	usb_composite_unregister(&eth_driver);
 }
-module_exit (cleanup);
-
+module_exit(cleanup);
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
new file mode 100644
index 0000000..d8faccf
--- /dev/null
+++ b/drivers/usb/gadget/f_acm.c
@@ -0,0 +1,589 @@
+/*
+ * f_acm.c -- USB CDC serial (ACM) function driver
+ *
+ * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
+ * Copyright (C) 2008 by David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
+ *
+ * This software is distributed under the terms of the GNU General
+ * Public License ("GPL") as published by the Free Software Foundation,
+ * either version 2 of that License or (at your option) any later version.
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+
+#include "u_serial.h"
+#include "gadget_chips.h"
+
+
+/*
+ * This CDC ACM function support just wraps control functions and
+ * notifications around the generic serial-over-usb code.
+ *
+ * Because CDC ACM is standardized by the USB-IF, many host operating
+ * systems have drivers for it.  Accordingly, ACM is the preferred
+ * interop solution for serial-port type connections.  The control
+ * models are often not necessary, and in any case don't do much in
+ * this bare-bones implementation.
+ *
+ * Note that even MS-Windows has some support for ACM.  However, that
+ * support is somewhat broken because when you use ACM in a composite
+ * device, having multiple interfaces confuses the poor OS.  It doesn't
+ * seem to understand CDC Union descriptors.  The new "association"
+ * descriptors (roughly equivalent to CDC Unions) may sometimes help.
+ */
+
+struct acm_ep_descs {
+	struct usb_endpoint_descriptor	*in;
+	struct usb_endpoint_descriptor	*out;
+	struct usb_endpoint_descriptor	*notify;
+};
+
+struct f_acm {
+	struct gserial			port;
+	u8				ctrl_id, data_id;
+	u8				port_num;
+
+	struct usb_descriptor_header	**fs_function;
+	struct acm_ep_descs		fs;
+	struct usb_descriptor_header	**hs_function;
+	struct acm_ep_descs		hs;
+
+	struct usb_ep			*notify;
+	struct usb_endpoint_descriptor	*notify_desc;
+
+	struct usb_cdc_line_coding	port_line_coding;	/* 8-N-1 etc */
+	u16				port_handshake_bits;
+#define RS232_RTS	(1 << 1)	/* unused with full duplex */
+#define RS232_DTR	(1 << 0)	/* host is ready for data r/w */
+};
+
+static inline struct f_acm *func_to_acm(struct usb_function *f)
+{
+	return container_of(f, struct f_acm, port.func);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* notification endpoint uses smallish and infrequent fixed-size messages */
+
+#define GS_LOG2_NOTIFY_INTERVAL		5	/* 1 << 5 == 32 msec */
+#define GS_NOTIFY_MAXPACKET		8
+
+/* interface and class descriptors: */
+
+static struct usb_interface_descriptor acm_control_interface_desc __initdata = {
+	.bLength =		USB_DT_INTERFACE_SIZE,
+	.bDescriptorType =	USB_DT_INTERFACE,
+	/* .bInterfaceNumber = DYNAMIC */
+	.bNumEndpoints =	1,
+	.bInterfaceClass =	USB_CLASS_COMM,
+	.bInterfaceSubClass =	USB_CDC_SUBCLASS_ACM,
+	.bInterfaceProtocol =	USB_CDC_ACM_PROTO_AT_V25TER,
+	/* .iInterface = DYNAMIC */
+};
+
+static struct usb_interface_descriptor acm_data_interface_desc __initdata = {
+	.bLength =		USB_DT_INTERFACE_SIZE,
+	.bDescriptorType =	USB_DT_INTERFACE,
+	/* .bInterfaceNumber = DYNAMIC */
+	.bNumEndpoints =	2,
+	.bInterfaceClass =	USB_CLASS_CDC_DATA,
+	.bInterfaceSubClass =	0,
+	.bInterfaceProtocol =	0,
+	/* .iInterface = DYNAMIC */
+};
+
+static struct usb_cdc_header_desc acm_header_desc __initdata = {
+	.bLength =		sizeof(acm_header_desc),
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
+	.bcdCDC =		__constant_cpu_to_le16(0x0110),
+};
+
+static struct usb_cdc_call_mgmt_descriptor
+acm_call_mgmt_descriptor __initdata = {
+	.bLength =		sizeof(acm_call_mgmt_descriptor),
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_CALL_MANAGEMENT_TYPE,
+	.bmCapabilities =	0,
+	/* .bDataInterface = DYNAMIC */
+};
+
+static struct usb_cdc_acm_descriptor acm_descriptor __initdata = {
+	.bLength =		sizeof(acm_descriptor),
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_ACM_TYPE,
+	.bmCapabilities =	(1 << 1),
+};
+
+static struct usb_cdc_union_desc acm_union_desc __initdata = {
+	.bLength =		sizeof(acm_union_desc),
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_UNION_TYPE,
+	/* .bMasterInterface0 =	DYNAMIC */
+	/* .bSlaveInterface0 =	DYNAMIC */
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor acm_fs_notify_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize =	__constant_cpu_to_le16(GS_NOTIFY_MAXPACKET),
+	.bInterval =		1 << GS_LOG2_NOTIFY_INTERVAL,
+};
+
+static struct usb_endpoint_descriptor acm_fs_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor acm_fs_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *acm_fs_function[] __initdata = {
+	(struct usb_descriptor_header *) &acm_control_interface_desc,
+	(struct usb_descriptor_header *) &acm_header_desc,
+	(struct usb_descriptor_header *) &acm_call_mgmt_descriptor,
+	(struct usb_descriptor_header *) &acm_descriptor,
+	(struct usb_descriptor_header *) &acm_union_desc,
+	(struct usb_descriptor_header *) &acm_fs_notify_desc,
+	(struct usb_descriptor_header *) &acm_data_interface_desc,
+	(struct usb_descriptor_header *) &acm_fs_in_desc,
+	(struct usb_descriptor_header *) &acm_fs_out_desc,
+	NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor acm_hs_notify_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize =	__constant_cpu_to_le16(GS_NOTIFY_MAXPACKET),
+	.bInterval =		GS_LOG2_NOTIFY_INTERVAL+4,
+};
+
+static struct usb_endpoint_descriptor acm_hs_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor acm_hs_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *acm_hs_function[] __initdata = {
+	(struct usb_descriptor_header *) &acm_control_interface_desc,
+	(struct usb_descriptor_header *) &acm_header_desc,
+	(struct usb_descriptor_header *) &acm_call_mgmt_descriptor,
+	(struct usb_descriptor_header *) &acm_descriptor,
+	(struct usb_descriptor_header *) &acm_union_desc,
+	(struct usb_descriptor_header *) &acm_hs_notify_desc,
+	(struct usb_descriptor_header *) &acm_data_interface_desc,
+	(struct usb_descriptor_header *) &acm_hs_in_desc,
+	(struct usb_descriptor_header *) &acm_hs_out_desc,
+	NULL,
+};
+
+/* string descriptors: */
+
+#define ACM_CTRL_IDX	0
+#define ACM_DATA_IDX	1
+
+/* static strings, in UTF-8 */
+static struct usb_string acm_string_defs[] = {
+	[ACM_CTRL_IDX].s = "CDC Abstract Control Model (ACM)",
+	[ACM_DATA_IDX].s = "CDC ACM Data",
+	{  /* ZEROES END LIST */ },
+};
+
+static struct usb_gadget_strings acm_string_table = {
+	.language =		0x0409,	/* en-us */
+	.strings =		acm_string_defs,
+};
+
+static struct usb_gadget_strings *acm_strings[] = {
+	&acm_string_table,
+	NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* ACM control ... data handling is delegated to tty library code.
+ * The main task of this function is to activate and deactivate
+ * that code based on device state; track parameters like line
+ * speed, handshake state, and so on; and issue notifications.
+ */
+
+static void acm_complete_set_line_coding(struct usb_ep *ep,
+		struct usb_request *req)
+{
+	struct f_acm	*acm = ep->driver_data;
+	struct usb_composite_dev *cdev = acm->port.func.config->cdev;
+
+	if (req->status != 0) {
+		DBG(cdev, "acm ttyGS%d completion, err %d\n",
+				acm->port_num, req->status);
+		return;
+	}
+
+	/* normal completion */
+	if (req->actual != sizeof(acm->port_line_coding)) {
+		DBG(cdev, "acm ttyGS%d short resp, len %d\n",
+				acm->port_num, req->actual);
+		usb_ep_set_halt(ep);
+	} else {
+		struct usb_cdc_line_coding	*value = req->buf;
+
+		/* REVISIT:  we currently just remember this data.
+		 * If we change that, (a) validate it first, then
+		 * (b) update whatever hardware needs updating,
+		 * (c) worry about locking.  This is information on
+		 * the order of 9600-8-N-1 ... most of which means
+		 * nothing unless we control a real RS232 line.
+		 */
+		acm->port_line_coding = *value;
+	}
+}
+
+static int acm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+	struct f_acm		*acm = func_to_acm(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+	struct usb_request	*req = cdev->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);
+
+	/* composite driver infrastructure handles everything except
+	 * CDC class messages; interface activation uses set_alt().
+	 */
+	switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
+
+	/* SET_LINE_CODING ... just read and save what the host sends */
+	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+			| USB_CDC_REQ_SET_LINE_CODING:
+		if (w_length != sizeof(struct usb_cdc_line_coding)
+				|| w_index != acm->ctrl_id)
+			goto invalid;
+
+		value = w_length;
+		cdev->gadget->ep0->driver_data = acm;
+		req->complete = acm_complete_set_line_coding;
+		break;
+
+	/* GET_LINE_CODING ... return what host sent, or initial value */
+	case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+			| USB_CDC_REQ_GET_LINE_CODING:
+		if (w_index != acm->ctrl_id)
+			goto invalid;
+
+		value = min_t(unsigned, w_length,
+				sizeof(struct usb_cdc_line_coding));
+		memcpy(req->buf, &acm->port_line_coding, value);
+		break;
+
+	/* SET_CONTROL_LINE_STATE ... save what the host sent */
+	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+			| USB_CDC_REQ_SET_CONTROL_LINE_STATE:
+		if (w_index != acm->ctrl_id)
+			goto invalid;
+
+		value = 0;
+
+		/* FIXME we should not allow data to flow until the
+		 * host sets the RS232_DTR bit; and when it clears
+		 * that bit, we should return to that no-flow state.
+		 */
+		acm->port_handshake_bits = w_value;
+		break;
+
+	default:
+invalid:
+		VDBG(cdev, "invalid 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 or status phase? */
+	if (value >= 0) {
+		DBG(cdev, "acm ttyGS%d req%02x.%02x v%04x i%04x l%d\n",
+			acm->port_num, ctrl->bRequestType, ctrl->bRequest,
+			w_value, w_index, w_length);
+		req->zero = 0;
+		req->length = value;
+		value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+		if (value < 0)
+			ERROR(cdev, "acm response on ttyGS%d, err %d\n",
+					acm->port_num, value);
+	}
+
+	/* device either stalls (value < 0) or reports success */
+	return value;
+}
+
+static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+	struct f_acm		*acm = func_to_acm(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	/* we know alt == 0, so this is an activation or a reset */
+
+	if (intf == acm->ctrl_id) {
+		/* REVISIT this may need more work when we start to
+		 * send notifications ...
+		 */
+		if (acm->notify->driver_data) {
+			VDBG(cdev, "reset acm control interface %d\n", intf);
+			usb_ep_disable(acm->notify);
+		} else {
+			VDBG(cdev, "init acm ctrl interface %d\n", intf);
+			acm->notify_desc = ep_choose(cdev->gadget,
+					acm->hs.notify,
+					acm->fs.notify);
+		}
+		usb_ep_enable(acm->notify, acm->notify_desc);
+		acm->notify->driver_data = acm;
+
+	} else if (intf == acm->data_id) {
+		if (acm->port.in->driver_data) {
+			DBG(cdev, "reset acm ttyGS%d\n", acm->port_num);
+			gserial_disconnect(&acm->port);
+		} else {
+			DBG(cdev, "activate acm ttyGS%d\n", acm->port_num);
+			acm->port.in_desc = ep_choose(cdev->gadget,
+					acm->hs.in, acm->fs.in);
+			acm->port.out_desc = ep_choose(cdev->gadget,
+					acm->hs.out, acm->fs.out);
+		}
+		gserial_connect(&acm->port, acm->port_num);
+
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+
+static void acm_disable(struct usb_function *f)
+{
+	struct f_acm	*acm = func_to_acm(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	DBG(cdev, "acm ttyGS%d deactivated\n", acm->port_num);
+	gserial_disconnect(&acm->port);
+	usb_ep_disable(acm->notify);
+	acm->notify->driver_data = NULL;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* ACM function driver setup/binding */
+static int __init
+acm_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct usb_composite_dev *cdev = c->cdev;
+	struct f_acm		*acm = func_to_acm(f);
+	int			status;
+	struct usb_ep		*ep;
+
+	/* allocate instance-specific interface IDs, and patch descriptors */
+	status = usb_interface_id(c, f);
+	if (status < 0)
+		goto fail;
+	acm->ctrl_id = status;
+
+	acm_control_interface_desc.bInterfaceNumber = status;
+	acm_union_desc .bMasterInterface0 = status;
+
+	status = usb_interface_id(c, f);
+	if (status < 0)
+		goto fail;
+	acm->data_id = status;
+
+	acm_data_interface_desc.bInterfaceNumber = status;
+	acm_union_desc.bSlaveInterface0 = status;
+	acm_call_mgmt_descriptor.bDataInterface = status;
+
+	status = -ENODEV;
+
+	/* allocate instance-specific endpoints */
+	ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_in_desc);
+	if (!ep)
+		goto fail;
+	acm->port.in = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_out_desc);
+	if (!ep)
+		goto fail;
+	acm->port.out = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_notify_desc);
+	if (!ep)
+		goto fail;
+	acm->notify = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	/* copy descriptors, and track endpoint copies */
+	f->descriptors = usb_copy_descriptors(acm_fs_function);
+
+	acm->fs.in = usb_find_endpoint(acm_fs_function,
+			f->descriptors, &acm_fs_in_desc);
+	acm->fs.out = usb_find_endpoint(acm_fs_function,
+			f->descriptors, &acm_fs_out_desc);
+	acm->fs.notify = usb_find_endpoint(acm_fs_function,
+			f->descriptors, &acm_fs_notify_desc);
+
+	/* support all relevant hardware speeds... we expect that when
+	 * hardware is dual speed, all bulk-capable endpoints work at
+	 * both speeds
+	 */
+	if (gadget_is_dualspeed(c->cdev->gadget)) {
+		acm_hs_in_desc.bEndpointAddress =
+				acm_fs_in_desc.bEndpointAddress;
+		acm_hs_out_desc.bEndpointAddress =
+				acm_fs_out_desc.bEndpointAddress;
+		acm_hs_notify_desc.bEndpointAddress =
+				acm_fs_notify_desc.bEndpointAddress;
+
+		/* copy descriptors, and track endpoint copies */
+		f->hs_descriptors = usb_copy_descriptors(acm_hs_function);
+
+		acm->hs.in = usb_find_endpoint(acm_hs_function,
+				f->hs_descriptors, &acm_hs_in_desc);
+		acm->hs.out = usb_find_endpoint(acm_hs_function,
+				f->hs_descriptors, &acm_hs_out_desc);
+		acm->hs.notify = usb_find_endpoint(acm_hs_function,
+				f->hs_descriptors, &acm_hs_notify_desc);
+	}
+
+	/* FIXME provide a callback for triggering notifications */
+
+	DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n",
+			acm->port_num,
+			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+			acm->port.in->name, acm->port.out->name,
+			acm->notify->name);
+	return 0;
+
+fail:
+	/* we might as well release our claims on endpoints */
+	if (acm->notify)
+		acm->notify->driver_data = NULL;
+	if (acm->port.out)
+		acm->port.out->driver_data = NULL;
+	if (acm->port.in)
+		acm->port.in->driver_data = NULL;
+
+	ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status);
+
+	return status;
+}
+
+static void
+acm_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	if (gadget_is_dualspeed(c->cdev->gadget))
+		usb_free_descriptors(f->hs_descriptors);
+	usb_free_descriptors(f->descriptors);
+	kfree(func_to_acm(f));
+}
+
+/* Some controllers can't support CDC ACM ... */
+static inline bool can_support_cdc(struct usb_configuration *c)
+{
+	/* SH3 doesn't support multiple interfaces */
+	if (gadget_is_sh(c->cdev->gadget))
+		return false;
+
+	/* sa1100 doesn't have a third interrupt endpoint */
+	if (gadget_is_sa1100(c->cdev->gadget))
+		return false;
+
+	/* everything else is *probably* fine ... */
+	return true;
+}
+
+/**
+ * acm_bind_config - add a CDC ACM function to a configuration
+ * @c: the configuration to support the CDC ACM instance
+ * @port_num: /dev/ttyGS* port this interface will use
+ * Context: single threaded during gadget setup
+ *
+ * Returns zero on success, else negative errno.
+ *
+ * Caller must have called @gserial_setup() with enough ports to
+ * handle all the ones it binds.  Caller is also responsible
+ * for calling @gserial_cleanup() before module unload.
+ */
+int __init acm_bind_config(struct usb_configuration *c, u8 port_num)
+{
+	struct f_acm	*acm;
+	int		status;
+
+	if (!can_support_cdc(c))
+		return -EINVAL;
+
+	/* REVISIT might want instance-specific strings to help
+	 * distinguish instances ...
+	 */
+
+	/* maybe allocate device-global string IDs, and patch descriptors */
+	if (acm_string_defs[ACM_CTRL_IDX].id == 0) {
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		acm_string_defs[ACM_CTRL_IDX].id = status;
+
+		acm_control_interface_desc.iInterface = status;
+
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		acm_string_defs[ACM_DATA_IDX].id = status;
+
+		acm_data_interface_desc.iInterface = status;
+	}
+
+	/* allocate and initialize one new instance */
+	acm = kzalloc(sizeof *acm, GFP_KERNEL);
+	if (!acm)
+		return -ENOMEM;
+
+	acm->port_num = port_num;
+
+	acm->port.func.name = "acm";
+	acm->port.func.strings = acm_strings;
+	/* descriptors are per-instance copies */
+	acm->port.func.bind = acm_bind;
+	acm->port.func.unbind = acm_unbind;
+	acm->port.func.set_alt = acm_set_alt;
+	acm->port.func.setup = acm_setup;
+	acm->port.func.disable = acm_disable;
+
+	status = usb_add_function(c, &acm->port.func);
+	if (status)
+		kfree(acm);
+	return status;
+}
diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c
new file mode 100644
index 0000000..0822e9d
--- /dev/null
+++ b/drivers/usb/gadget/f_ecm.c
@@ -0,0 +1,833 @@
+/*
+ * f_ecm.c -- USB CDC Ethernet (ECM) link function driver
+ *
+ * Copyright (C) 2003-2005,2008 David Brownell
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/etherdevice.h>
+
+#include "u_ether.h"
+
+
+/*
+ * This function is a "CDC Ethernet Networking Control Model" (CDC ECM)
+ * Ethernet link.  The data transfer model is simple (packets sent and
+ * received over bulk endpoints using normal short packet termination),
+ * and the control model exposes various data and optional notifications.
+ *
+ * ECM is well standardized and (except for Microsoft) supported by most
+ * operating systems with USB host support.  It's the preferred interop
+ * solution for Ethernet over USB, at least for firmware based solutions.
+ * (Hardware solutions tend to be more minimalist.)  A newer and simpler
+ * "Ethernet Emulation Model" (CDC EEM) hasn't yet caught on.
+ *
+ * Note that ECM requires the use of "alternate settings" for its data
+ * interface.  This means that the set_alt() method has real work to do,
+ * and also means that a get_alt() method is required.
+ */
+
+struct ecm_ep_descs {
+	struct usb_endpoint_descriptor	*in;
+	struct usb_endpoint_descriptor	*out;
+	struct usb_endpoint_descriptor	*notify;
+};
+
+enum ecm_notify_state {
+	ECM_NOTIFY_NONE,		/* don't notify */
+	ECM_NOTIFY_CONNECT,		/* issue CONNECT next */
+	ECM_NOTIFY_SPEED,		/* issue SPEED_CHANGE next */
+};
+
+struct f_ecm {
+	struct gether			port;
+	u8				ctrl_id, data_id;
+
+	char				ethaddr[14];
+
+	struct usb_descriptor_header	**fs_function;
+	struct ecm_ep_descs		fs;
+	struct usb_descriptor_header	**hs_function;
+	struct ecm_ep_descs		hs;
+
+	struct usb_ep			*notify;
+	struct usb_endpoint_descriptor	*notify_desc;
+	struct usb_request		*notify_req;
+	u8				notify_state;
+	bool				is_open;
+
+	/* FIXME is_open needs some irq-ish locking
+	 * ... possibly the same as port.ioport
+	 */
+};
+
+static inline struct f_ecm *func_to_ecm(struct usb_function *f)
+{
+	return container_of(f, struct f_ecm, port.func);
+}
+
+/* peak (theoretical) bulk transfer rate in bits-per-second */
+static inline unsigned bitrate(struct usb_gadget *g)
+{
+	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
+		return 13 * 512 * 8 * 1000 * 8;
+	else
+		return 19 *  64 * 1 * 1000 * 8;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Include the status endpoint if we can, even though it's optional.
+ *
+ * Use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one
+ * packet, to simplify cancellation; and a big transfer interval, to
+ * waste less bandwidth.
+ *
+ * Some drivers (like Linux 2.4 cdc-ether!) "need" it to exist even
+ * if they ignore the connect/disconnect notifications that real aether
+ * can provide.  More advanced cdc configurations might want to support
+ * encapsulated commands (vendor-specific, using control-OUT).
+ */
+
+#define LOG2_STATUS_INTERVAL_MSEC	5	/* 1 << 5 == 32 msec */
+#define STATUS_BYTECOUNT		16	/* 8 byte header + data */
+
+
+/* interface descriptor: */
+
+static struct usb_interface_descriptor ecm_control_intf __initdata = {
+	.bLength =		sizeof ecm_control_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	/* .bInterfaceNumber = DYNAMIC */
+	/* status endpoint is optional; this could be patched later */
+	.bNumEndpoints =	1,
+	.bInterfaceClass =	USB_CLASS_COMM,
+	.bInterfaceSubClass =	USB_CDC_SUBCLASS_ETHERNET,
+	.bInterfaceProtocol =	USB_CDC_PROTO_NONE,
+	/* .iInterface = DYNAMIC */
+};
+
+static struct usb_cdc_header_desc header_desc __initdata = {
+	.bLength =		sizeof header_desc,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
+
+	.bcdCDC =		__constant_cpu_to_le16(0x0110),
+};
+
+static struct usb_cdc_union_desc ecm_union_desc __initdata = {
+	.bLength =		sizeof(ecm_union_desc),
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_UNION_TYPE,
+	/* .bMasterInterface0 =	DYNAMIC */
+	/* .bSlaveInterface0 =	DYNAMIC */
+};
+
+static struct usb_cdc_ether_desc ether_desc __initdata = {
+	.bLength =		sizeof ether_desc,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_ETHERNET_TYPE,
+
+	/* this descriptor actually adds value, surprise! */
+	/* .iMACAddress = DYNAMIC */
+	.bmEthernetStatistics =	__constant_cpu_to_le32(0), /* no statistics */
+	.wMaxSegmentSize =	__constant_cpu_to_le16(ETH_FRAME_LEN),
+	.wNumberMCFilters =	__constant_cpu_to_le16(0),
+	.bNumberPowerFilters =	0,
+};
+
+/* the default data interface has no endpoints ... */
+
+static struct usb_interface_descriptor ecm_data_nop_intf __initdata = {
+	.bLength =		sizeof ecm_data_nop_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	.bInterfaceNumber =	1,
+	.bAlternateSetting =	0,
+	.bNumEndpoints =	0,
+	.bInterfaceClass =	USB_CLASS_CDC_DATA,
+	.bInterfaceSubClass =	0,
+	.bInterfaceProtocol =	0,
+	/* .iInterface = DYNAMIC */
+};
+
+/* ... but the "real" data interface has two bulk endpoints */
+
+static struct usb_interface_descriptor ecm_data_intf __initdata = {
+	.bLength =		sizeof ecm_data_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	.bInterfaceNumber =	1,
+	.bAlternateSetting =	1,
+	.bNumEndpoints =	2,
+	.bInterfaceClass =	USB_CLASS_CDC_DATA,
+	.bInterfaceSubClass =	0,
+	.bInterfaceProtocol =	0,
+	/* .iInterface = DYNAMIC */
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor fs_notify_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize =	__constant_cpu_to_le16(STATUS_BYTECOUNT),
+	.bInterval =		1 << LOG2_STATUS_INTERVAL_MSEC,
+};
+
+static struct usb_endpoint_descriptor fs_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor fs_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *eth_fs_function[] __initdata = {
+	/* CDC ECM control descriptors */
+	(struct usb_descriptor_header *) &ecm_control_intf,
+	(struct usb_descriptor_header *) &header_desc,
+	(struct usb_descriptor_header *) &ecm_union_desc,
+	(struct usb_descriptor_header *) &ether_desc,
+	/* NOTE: status endpoint might need to be removed */
+	(struct usb_descriptor_header *) &fs_notify_desc,
+	/* data interface, altsettings 0 and 1 */
+	(struct usb_descriptor_header *) &ecm_data_nop_intf,
+	(struct usb_descriptor_header *) &ecm_data_intf,
+	(struct usb_descriptor_header *) &fs_in_desc,
+	(struct usb_descriptor_header *) &fs_out_desc,
+	NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor hs_notify_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize =	__constant_cpu_to_le16(STATUS_BYTECOUNT),
+	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4,
+};
+static struct usb_endpoint_descriptor hs_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor hs_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *eth_hs_function[] __initdata = {
+	/* CDC ECM control descriptors */
+	(struct usb_descriptor_header *) &ecm_control_intf,
+	(struct usb_descriptor_header *) &header_desc,
+	(struct usb_descriptor_header *) &ecm_union_desc,
+	(struct usb_descriptor_header *) &ether_desc,
+	/* NOTE: status endpoint might need to be removed */
+	(struct usb_descriptor_header *) &hs_notify_desc,
+	/* data interface, altsettings 0 and 1 */
+	(struct usb_descriptor_header *) &ecm_data_nop_intf,
+	(struct usb_descriptor_header *) &ecm_data_intf,
+	(struct usb_descriptor_header *) &hs_in_desc,
+	(struct usb_descriptor_header *) &hs_out_desc,
+	NULL,
+};
+
+/* string descriptors: */
+
+static struct usb_string ecm_string_defs[] = {
+	[0].s = "CDC Ethernet Control Model (ECM)",
+	[1].s = NULL /* DYNAMIC */,
+	[2].s = "CDC Ethernet Data",
+	{  } /* end of list */
+};
+
+static struct usb_gadget_strings ecm_string_table = {
+	.language =		0x0409,	/* en-us */
+	.strings =		ecm_string_defs,
+};
+
+static struct usb_gadget_strings *ecm_strings[] = {
+	&ecm_string_table,
+	NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static void ecm_do_notify(struct f_ecm *ecm)
+{
+	struct usb_request		*req = ecm->notify_req;
+	struct usb_cdc_notification	*event;
+	struct usb_composite_dev	*cdev = ecm->port.func.config->cdev;
+	__le32				*data;
+	int				status;
+
+	/* notification already in flight? */
+	if (!req)
+		return;
+
+	event = req->buf;
+	switch (ecm->notify_state) {
+	case ECM_NOTIFY_NONE:
+		return;
+
+	case ECM_NOTIFY_CONNECT:
+		event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION;
+		if (ecm->is_open)
+			event->wValue = cpu_to_le16(1);
+		else
+			event->wValue = cpu_to_le16(0);
+		event->wLength = 0;
+		req->length = sizeof *event;
+
+		DBG(cdev, "notify connect %s\n",
+				ecm->is_open ? "true" : "false");
+		ecm->notify_state = ECM_NOTIFY_SPEED;
+		break;
+
+	case ECM_NOTIFY_SPEED:
+		event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE;
+		event->wValue = cpu_to_le16(0);
+		event->wLength = cpu_to_le16(8);
+		req->length = STATUS_BYTECOUNT;
+
+		/* SPEED_CHANGE data is up/down speeds in bits/sec */
+		data = req->buf + sizeof *event;
+		data[0] = cpu_to_le32(bitrate(cdev->gadget));
+		data[1] = data[0];
+
+		DBG(cdev, "notify speed %d\n", bitrate(cdev->gadget));
+		ecm->notify_state = ECM_NOTIFY_NONE;
+		break;
+	}
+	event->bmRequestType = 0xA1;
+	event->wIndex = cpu_to_le16(ecm->ctrl_id);
+
+	ecm->notify_req = NULL;
+	status = usb_ep_queue(ecm->notify, req, GFP_ATOMIC);
+	if (status < 0) {
+		ecm->notify_req = req;
+		DBG(cdev, "notify --> %d\n", status);
+	}
+}
+
+static void ecm_notify(struct f_ecm *ecm)
+{
+	/* NOTE on most versions of Linux, host side cdc-ethernet
+	 * won't listen for notifications until its netdevice opens.
+	 * The first notification then sits in the FIFO for a long
+	 * time, and the second one is queued.
+	 */
+	ecm->notify_state = ECM_NOTIFY_CONNECT;
+	ecm_do_notify(ecm);
+}
+
+static void ecm_notify_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_ecm			*ecm = req->context;
+	struct usb_composite_dev	*cdev = ecm->port.func.config->cdev;
+	struct usb_cdc_notification	*event = req->buf;
+
+	switch (req->status) {
+	case 0:
+		/* no fault */
+		break;
+	case -ECONNRESET:
+	case -ESHUTDOWN:
+		ecm->notify_state = ECM_NOTIFY_NONE;
+		break;
+	default:
+		DBG(cdev, "event %02x --> %d\n",
+			event->bNotificationType, req->status);
+		break;
+	}
+	ecm->notify_req = req;
+	ecm_do_notify(ecm);
+}
+
+static int ecm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+	struct f_ecm		*ecm = func_to_ecm(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+	struct usb_request	*req = cdev->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);
+
+	/* composite driver infrastructure handles everything except
+	 * CDC class messages; interface activation uses set_alt().
+	 */
+	switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
+	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+			| USB_CDC_SET_ETHERNET_PACKET_FILTER:
+		/* see 6.2.30: no data, wIndex = interface,
+		 * wValue = packet filter bitmap
+		 */
+		if (w_length != 0 || w_index != ecm->ctrl_id)
+			goto invalid;
+		DBG(cdev, "packet filter %02x\n", w_value);
+		/* REVISIT locking of cdc_filter.  This assumes the UDC
+		 * driver won't have a concurrent packet TX irq running on
+		 * another CPU; or that if it does, this write is atomic...
+		 */
+		ecm->port.cdc_filter = w_value;
+		value = 0;
+		break;
+
+	/* and optionally:
+	 * case USB_CDC_SEND_ENCAPSULATED_COMMAND:
+	 * case USB_CDC_GET_ENCAPSULATED_RESPONSE:
+	 * case USB_CDC_SET_ETHERNET_MULTICAST_FILTERS:
+	 * case USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER:
+	 * case USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER:
+	 * case USB_CDC_GET_ETHERNET_STATISTIC:
+	 */
+
+	default:
+invalid:
+		DBG(cdev, "invalid 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 or status phase? */
+	if (value >= 0) {
+		DBG(cdev, "ecm req%02x.%02x v%04x i%04x l%d\n",
+			ctrl->bRequestType, ctrl->bRequest,
+			w_value, w_index, w_length);
+		req->zero = 0;
+		req->length = value;
+		value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+		if (value < 0)
+			ERROR(cdev, "ecm req %02x.%02x response err %d\n",
+					ctrl->bRequestType, ctrl->bRequest,
+					value);
+	}
+
+	/* device either stalls (value < 0) or reports success */
+	return value;
+}
+
+
+static int ecm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+	struct f_ecm		*ecm = func_to_ecm(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	/* Control interface has only altsetting 0 */
+	if (intf == ecm->ctrl_id) {
+		if (alt != 0)
+			goto fail;
+
+		if (ecm->notify->driver_data) {
+			VDBG(cdev, "reset ecm control %d\n", intf);
+			usb_ep_disable(ecm->notify);
+		} else {
+			VDBG(cdev, "init ecm ctrl %d\n", intf);
+			ecm->notify_desc = ep_choose(cdev->gadget,
+					ecm->hs.notify,
+					ecm->fs.notify);
+		}
+		usb_ep_enable(ecm->notify, ecm->notify_desc);
+		ecm->notify->driver_data = ecm;
+
+	/* Data interface has two altsettings, 0 and 1 */
+	} else if (intf == ecm->data_id) {
+		if (alt > 1)
+			goto fail;
+
+		if (ecm->port.in_ep->driver_data) {
+			DBG(cdev, "reset ecm\n");
+			gether_disconnect(&ecm->port);
+		}
+
+		if (!ecm->port.in) {
+			DBG(cdev, "init ecm\n");
+			ecm->port.in = ep_choose(cdev->gadget,
+					ecm->hs.in, ecm->fs.in);
+			ecm->port.out = ep_choose(cdev->gadget,
+					ecm->hs.out, ecm->fs.out);
+		}
+
+		/* CDC Ethernet only sends data in non-default altsettings.
+		 * Changing altsettings resets filters, statistics, etc.
+		 */
+		if (alt == 1) {
+			struct net_device	*net;
+
+			/* Enable zlps by default for ECM conformance;
+			 * override for musb_hdrc (avoids txdma ovhead)
+			 * and sa1100 (can't).
+			 */
+			ecm->port.is_zlp_ok = !(
+				   gadget_is_sa1100(cdev->gadget)
+				|| gadget_is_musbhdrc(cdev->gadget)
+				);
+			ecm->port.cdc_filter = DEFAULT_FILTER;
+			DBG(cdev, "activate ecm\n");
+			net = gether_connect(&ecm->port);
+			if (IS_ERR(net))
+				return PTR_ERR(net);
+		}
+
+		/* NOTE this can be a minor disagreement with the ECM spec,
+		 * which says speed notifications will "always" follow
+		 * connection notifications.  But we allow one connect to
+		 * follow another (if the first is in flight), and instead
+		 * just guarantee that a speed notification is always sent.
+		 */
+		ecm_notify(ecm);
+	} else
+		goto fail;
+
+	return 0;
+fail:
+	return -EINVAL;
+}
+
+/* Because the data interface supports multiple altsettings,
+ * this ECM function *MUST* implement a get_alt() method.
+ */
+static int ecm_get_alt(struct usb_function *f, unsigned intf)
+{
+	struct f_ecm		*ecm = func_to_ecm(f);
+
+	if (intf == ecm->ctrl_id)
+		return 0;
+	return ecm->port.in_ep->driver_data ? 1 : 0;
+}
+
+static void ecm_disable(struct usb_function *f)
+{
+	struct f_ecm		*ecm = func_to_ecm(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	DBG(cdev, "ecm deactivated\n");
+
+	if (ecm->port.in_ep->driver_data)
+		gether_disconnect(&ecm->port);
+
+	if (ecm->notify->driver_data) {
+		usb_ep_disable(ecm->notify);
+		ecm->notify->driver_data = NULL;
+		ecm->notify_desc = NULL;
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Callbacks let us notify the host about connect/disconnect when the
+ * net device is opened or closed.
+ *
+ * For testing, note that link states on this side include both opened
+ * and closed variants of:
+ *
+ *   - disconnected/unconfigured
+ *   - configured but inactive (data alt 0)
+ *   - configured and active (data alt 1)
+ *
+ * Each needs to be tested with unplug, rmmod, SET_CONFIGURATION, and
+ * SET_INTERFACE (altsetting).  Remember also that "configured" doesn't
+ * imply the host is actually polling the notification endpoint, and
+ * likewise that "active" doesn't imply it's actually using the data
+ * endpoints for traffic.
+ */
+
+static void ecm_open(struct gether *geth)
+{
+	struct f_ecm		*ecm = func_to_ecm(&geth->func);
+
+	DBG(ecm->port.func.config->cdev, "%s\n", __func__);
+
+	ecm->is_open = true;
+	ecm_notify(ecm);
+}
+
+static void ecm_close(struct gether *geth)
+{
+	struct f_ecm		*ecm = func_to_ecm(&geth->func);
+
+	DBG(ecm->port.func.config->cdev, "%s\n", __func__);
+
+	ecm->is_open = false;
+	ecm_notify(ecm);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* ethernet function driver setup/binding */
+
+static int __init
+ecm_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct usb_composite_dev *cdev = c->cdev;
+	struct f_ecm		*ecm = func_to_ecm(f);
+	int			status;
+	struct usb_ep		*ep;
+
+	/* allocate instance-specific interface IDs */
+	status = usb_interface_id(c, f);
+	if (status < 0)
+		goto fail;
+	ecm->ctrl_id = status;
+
+	ecm_control_intf.bInterfaceNumber = status;
+	ecm_union_desc.bMasterInterface0 = status;
+
+	status = usb_interface_id(c, f);
+	if (status < 0)
+		goto fail;
+	ecm->data_id = status;
+
+	ecm_data_nop_intf.bInterfaceNumber = status;
+	ecm_data_intf.bInterfaceNumber = status;
+	ecm_union_desc.bSlaveInterface0 = status;
+
+	status = -ENODEV;
+
+	/* allocate instance-specific endpoints */
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc);
+	if (!ep)
+		goto fail;
+	ecm->port.in_ep = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc);
+	if (!ep)
+		goto fail;
+	ecm->port.out_ep = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	/* NOTE:  a status/notification endpoint is *OPTIONAL* but we
+	 * don't treat it that way.  It's simpler, and some newer CDC
+	 * profiles (wireless handsets) no longer treat it as optional.
+	 */
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_notify_desc);
+	if (!ep)
+		goto fail;
+	ecm->notify = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	status = -ENOMEM;
+
+	/* allocate notification request and buffer */
+	ecm->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL);
+	if (!ecm->notify_req)
+		goto fail;
+	ecm->notify_req->buf = kmalloc(STATUS_BYTECOUNT, GFP_KERNEL);
+	if (!ecm->notify_req->buf)
+		goto fail;
+	ecm->notify_req->context = ecm;
+	ecm->notify_req->complete = ecm_notify_complete;
+
+	/* copy descriptors, and track endpoint copies */
+	f->descriptors = usb_copy_descriptors(eth_fs_function);
+	if (!f->descriptors)
+		goto fail;
+
+	ecm->fs.in = usb_find_endpoint(eth_fs_function,
+			f->descriptors, &fs_in_desc);
+	ecm->fs.out = usb_find_endpoint(eth_fs_function,
+			f->descriptors, &fs_out_desc);
+	ecm->fs.notify = usb_find_endpoint(eth_fs_function,
+			f->descriptors, &fs_notify_desc);
+
+	/* support all relevant hardware speeds... we expect that when
+	 * hardware is dual speed, all bulk-capable endpoints work at
+	 * both speeds
+	 */
+	if (gadget_is_dualspeed(c->cdev->gadget)) {
+		hs_in_desc.bEndpointAddress =
+				fs_in_desc.bEndpointAddress;
+		hs_out_desc.bEndpointAddress =
+				fs_out_desc.bEndpointAddress;
+		hs_notify_desc.bEndpointAddress =
+				fs_notify_desc.bEndpointAddress;
+
+		/* copy descriptors, and track endpoint copies */
+		f->hs_descriptors = usb_copy_descriptors(eth_hs_function);
+		if (!f->hs_descriptors)
+			goto fail;
+
+		ecm->hs.in = usb_find_endpoint(eth_hs_function,
+				f->hs_descriptors, &hs_in_desc);
+		ecm->hs.out = usb_find_endpoint(eth_hs_function,
+				f->hs_descriptors, &hs_out_desc);
+		ecm->hs.notify = usb_find_endpoint(eth_hs_function,
+				f->hs_descriptors, &hs_notify_desc);
+	}
+
+	/* NOTE:  all that is done without knowing or caring about
+	 * the network link ... which is unavailable to this code
+	 * until we're activated via set_alt().
+	 */
+
+	ecm->port.open = ecm_open;
+	ecm->port.close = ecm_close;
+
+	DBG(cdev, "CDC Ethernet: %s speed IN/%s OUT/%s NOTIFY/%s\n",
+			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+			ecm->port.in_ep->name, ecm->port.out_ep->name,
+			ecm->notify->name);
+	return 0;
+
+fail:
+	if (f->descriptors)
+		usb_free_descriptors(f->descriptors);
+
+	if (ecm->notify_req) {
+		kfree(ecm->notify_req->buf);
+		usb_ep_free_request(ecm->notify, ecm->notify_req);
+	}
+
+	/* we might as well release our claims on endpoints */
+	if (ecm->notify)
+		ecm->notify->driver_data = NULL;
+	if (ecm->port.out)
+		ecm->port.out_ep->driver_data = NULL;
+	if (ecm->port.in)
+		ecm->port.in_ep->driver_data = NULL;
+
+	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
+
+	return status;
+}
+
+static void
+ecm_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct f_ecm		*ecm = func_to_ecm(f);
+
+	DBG(c->cdev, "ecm unbind\n");
+
+	if (gadget_is_dualspeed(c->cdev->gadget))
+		usb_free_descriptors(f->hs_descriptors);
+	usb_free_descriptors(f->descriptors);
+
+	kfree(ecm->notify_req->buf);
+	usb_ep_free_request(ecm->notify, ecm->notify_req);
+
+	ecm_string_defs[1].s = NULL;
+	kfree(ecm);
+}
+
+/**
+ * ecm_bind_config - add CDC Ethernet network link to a configuration
+ * @c: the configuration to support the network link
+ * @ethaddr: a buffer in which the ethernet address of the host side
+ *	side of the link was recorded
+ * Context: single threaded during gadget setup
+ *
+ * Returns zero on success, else negative errno.
+ *
+ * Caller must have called @gether_setup().  Caller is also responsible
+ * for calling @gether_cleanup() before module unload.
+ */
+int __init ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+{
+	struct f_ecm	*ecm;
+	int		status;
+
+	if (!can_support_ecm(c->cdev->gadget) || !ethaddr)
+		return -EINVAL;
+
+	/* maybe allocate device-global string IDs */
+	if (ecm_string_defs[0].id == 0) {
+
+		/* control interface label */
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		ecm_string_defs[0].id = status;
+		ecm_control_intf.iInterface = status;
+
+		/* data interface label */
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		ecm_string_defs[2].id = status;
+		ecm_data_intf.iInterface = status;
+
+		/* MAC address */
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		ecm_string_defs[1].id = status;
+		ether_desc.iMACAddress = status;
+	}
+
+	/* allocate and initialize one new instance */
+	ecm = kzalloc(sizeof *ecm, GFP_KERNEL);
+	if (!ecm)
+		return -ENOMEM;
+
+	/* export host's Ethernet address in CDC format */
+	snprintf(ecm->ethaddr, sizeof ecm->ethaddr,
+		"%02X%02X%02X%02X%02X%02X",
+		ethaddr[0], ethaddr[1], ethaddr[2],
+		ethaddr[3], ethaddr[4], ethaddr[5]);
+	ecm_string_defs[1].s = ecm->ethaddr;
+
+	ecm->port.cdc_filter = DEFAULT_FILTER;
+
+	ecm->port.func.name = "cdc_ethernet";
+	ecm->port.func.strings = ecm_strings;
+	/* descriptors are per-instance copies */
+	ecm->port.func.bind = ecm_bind;
+	ecm->port.func.unbind = ecm_unbind;
+	ecm->port.func.set_alt = ecm_set_alt;
+	ecm->port.func.get_alt = ecm_get_alt;
+	ecm->port.func.setup = ecm_setup;
+	ecm->port.func.disable = ecm_disable;
+
+	status = usb_add_function(c, &ecm->port.func);
+	if (status) {
+		ecm_string_defs[1].s = NULL;
+		kfree(ecm);
+	}
+	return status;
+}
diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c
new file mode 100644
index 0000000..eda4cde7
--- /dev/null
+++ b/drivers/usb/gadget/f_loopback.c
@@ -0,0 +1,381 @@
+/*
+ * f_loopback.c - USB peripheral loopback configuration driver
+ *
+ * Copyright (C) 2003-2008 David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/utsname.h>
+#include <linux/device.h>
+
+#include "g_zero.h"
+#include "gadget_chips.h"
+
+
+/*
+ * LOOPBACK FUNCTION ... a testing vehicle for USB peripherals,
+ *
+ * This takes messages of various sizes written OUT to a device, and loops
+ * them back so they can be read IN from it.  It has been used by certain
+ * test applications.  It supports limited testing of data queueing logic.
+ *
+ *
+ * This is currently packaged as a configuration driver, which can't be
+ * combined with other functions to make composite devices.  However, it
+ * can be combined with other independent configurations.
+ */
+struct f_loopback {
+	struct usb_function	function;
+
+	struct usb_ep		*in_ep;
+	struct usb_ep		*out_ep;
+};
+
+static inline struct f_loopback *func_to_loop(struct usb_function *f)
+{
+	return container_of(f, struct f_loopback, function);
+}
+
+static unsigned qlen = 32;
+module_param(qlen, uint, 0);
+MODULE_PARM_DESC(qlenn, "depth of loopback queue");
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_interface_descriptor loopback_intf = {
+	.bLength =		sizeof loopback_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	.bNumEndpoints =	2,
+	.bInterfaceClass =	USB_CLASS_VENDOR_SPEC,
+	/* .iInterface = DYNAMIC */
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor fs_source_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor fs_sink_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *fs_loopback_descs[] = {
+	(struct usb_descriptor_header *) &loopback_intf,
+	(struct usb_descriptor_header *) &fs_sink_desc,
+	(struct usb_descriptor_header *) &fs_source_desc,
+	NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor hs_source_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor hs_sink_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *hs_loopback_descs[] = {
+	(struct usb_descriptor_header *) &loopback_intf,
+	(struct usb_descriptor_header *) &hs_source_desc,
+	(struct usb_descriptor_header *) &hs_sink_desc,
+	NULL,
+};
+
+/* function-specific strings: */
+
+static struct usb_string strings_loopback[] = {
+	[0].s = "loop input to output",
+	{  }			/* end of list */
+};
+
+static struct usb_gadget_strings stringtab_loop = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= strings_loopback,
+};
+
+static struct usb_gadget_strings *loopback_strings[] = {
+	&stringtab_loop,
+	NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int __init
+loopback_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct usb_composite_dev *cdev = c->cdev;
+	struct f_loopback	*loop = func_to_loop(f);
+	int			id;
+
+	/* allocate interface ID(s) */
+	id = usb_interface_id(c, f);
+	if (id < 0)
+		return id;
+	loopback_intf.bInterfaceNumber = id;
+
+	/* allocate endpoints */
+
+	loop->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc);
+	if (!loop->in_ep) {
+autoconf_fail:
+		ERROR(cdev, "%s: can't autoconfigure on %s\n",
+			f->name, cdev->gadget->name);
+		return -ENODEV;
+	}
+	loop->in_ep->driver_data = cdev;	/* claim */
+
+	loop->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_sink_desc);
+	if (!loop->out_ep)
+		goto autoconf_fail;
+	loop->out_ep->driver_data = cdev;	/* claim */
+
+	/* support high speed hardware */
+	if (gadget_is_dualspeed(c->cdev->gadget)) {
+		hs_source_desc.bEndpointAddress =
+				fs_source_desc.bEndpointAddress;
+		hs_sink_desc.bEndpointAddress =
+				fs_sink_desc.bEndpointAddress;
+		f->hs_descriptors = hs_loopback_descs;
+	}
+
+	DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
+			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+			f->name, loop->in_ep->name, loop->out_ep->name);
+	return 0;
+}
+
+static void
+loopback_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	kfree(func_to_loop(f));
+}
+
+static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_loopback	*loop = ep->driver_data;
+	struct usb_composite_dev *cdev = loop->function.config->cdev;
+	int			status = req->status;
+
+	switch (status) {
+
+	case 0:				/* normal completion? */
+		if (ep == loop->out_ep) {
+			/* loop this OUT packet back IN to the host */
+			req->zero = (req->actual < req->length);
+			req->length = req->actual;
+			status = usb_ep_queue(loop->in_ep, req, GFP_ATOMIC);
+			if (status == 0)
+				return;
+
+			/* "should never get here" */
+			ERROR(cdev, "can't loop %s to %s: %d\n",
+				ep->name, loop->in_ep->name,
+				status);
+		}
+
+		/* queue the buffer for some later OUT packet */
+		req->length = buflen;
+		status = usb_ep_queue(loop->out_ep, req, GFP_ATOMIC);
+		if (status == 0)
+			return;
+
+		/* "should never get here" */
+		/* FALLTHROUGH */
+
+	default:
+		ERROR(cdev, "%s loop complete --> %d, %d/%d\n", ep->name,
+				status, req->actual, req->length);
+		/* FALLTHROUGH */
+
+	/* NOTE:  since this driver doesn't maintain an explicit record
+	 * of requests it submitted (just maintains qlen count), we
+	 * rely on the hardware driver to clean up on disconnect or
+	 * endpoint disable.
+	 */
+	case -ECONNABORTED:		/* hardware forced ep reset */
+	case -ECONNRESET:		/* request dequeued */
+	case -ESHUTDOWN:		/* disconnect from host */
+		free_ep_req(ep, req);
+		return;
+	}
+}
+
+static void disable_loopback(struct f_loopback *loop)
+{
+	struct usb_composite_dev	*cdev;
+
+	cdev = loop->function.config->cdev;
+	disable_endpoints(cdev, loop->in_ep, loop->out_ep);
+	VDBG(cdev, "%s disabled\n", loop->function.name);
+}
+
+static int
+enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
+{
+	int					result = 0;
+	const struct usb_endpoint_descriptor	*src, *sink;
+	struct usb_ep				*ep;
+	struct usb_request			*req;
+	unsigned				i;
+
+	src = ep_choose(cdev->gadget, &hs_source_desc, &fs_source_desc);
+	sink = ep_choose(cdev->gadget, &hs_sink_desc, &fs_sink_desc);
+
+	/* one endpoint writes data back IN to the host */
+	ep = loop->in_ep;
+	result = usb_ep_enable(ep, src);
+	if (result < 0)
+		return result;
+	ep->driver_data = loop;
+
+	/* one endpoint just reads OUT packets */
+	ep = loop->out_ep;
+	result = usb_ep_enable(ep, sink);
+	if (result < 0) {
+fail0:
+		ep = loop->in_ep;
+		usb_ep_disable(ep);
+		ep->driver_data = NULL;
+		return result;
+	}
+	ep->driver_data = loop;
+
+	/* allocate a bunch of read buffers and queue them all at once.
+	 * we buffer at most 'qlen' transfers; fewer if any need more
+	 * than 'buflen' bytes each.
+	 */
+	for (i = 0; i < qlen && result == 0; i++) {
+		req = alloc_ep_req(ep);
+		if (req) {
+			req->complete = loopback_complete;
+			result = usb_ep_queue(ep, req, GFP_ATOMIC);
+			if (result)
+				ERROR(cdev, "%s queue req --> %d\n",
+						ep->name, result);
+		} else {
+			usb_ep_disable(ep);
+			ep->driver_data = NULL;
+			result = -ENOMEM;
+			goto fail0;
+		}
+	}
+
+	DBG(cdev, "%s enabled\n", loop->function.name);
+	return result;
+}
+
+static int loopback_set_alt(struct usb_function *f,
+		unsigned intf, unsigned alt)
+{
+	struct f_loopback	*loop = func_to_loop(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	/* we know alt is zero */
+	if (loop->in_ep->driver_data)
+		disable_loopback(loop);
+	return enable_loopback(cdev, loop);
+}
+
+static void loopback_disable(struct usb_function *f)
+{
+	struct f_loopback	*loop = func_to_loop(f);
+
+	disable_loopback(loop);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int __init loopback_bind_config(struct usb_configuration *c)
+{
+	struct f_loopback	*loop;
+	int			status;
+
+	loop = kzalloc(sizeof *loop, GFP_KERNEL);
+	if (!loop)
+		return -ENOMEM;
+
+	loop->function.name = "loopback";
+	loop->function.descriptors = fs_loopback_descs;
+	loop->function.bind = loopback_bind;
+	loop->function.unbind = loopback_unbind;
+	loop->function.set_alt = loopback_set_alt;
+	loop->function.disable = loopback_disable;
+
+	status = usb_add_function(c, &loop->function);
+	if (status)
+		kfree(loop);
+	return status;
+}
+
+static struct usb_configuration loopback_driver = {
+	.label		= "loopback",
+	.strings	= loopback_strings,
+	.bind		= loopback_bind_config,
+	.bConfigurationValue = 2,
+	.bmAttributes	= USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower	= 1,	/* 2 mA, minimal */
+	/* .iConfiguration = DYNAMIC */
+};
+
+/**
+ * loopback_add - add a loopback testing configuration to a device
+ * @cdev: the device to support the loopback configuration
+ */
+int __init loopback_add(struct usb_composite_dev *cdev)
+{
+	int id;
+
+	/* allocate string ID(s) */
+	id = usb_string_id(cdev);
+	if (id < 0)
+		return id;
+	strings_loopback[0].id = id;
+
+	loopback_intf.iInterface = id;
+	loopback_driver.iConfiguration = id;
+
+	/* support OTG systems */
+	if (gadget_is_otg(cdev->gadget)) {
+		loopback_driver.descriptors = otg_desc;
+		loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+	}
+
+	return usb_add_config(cdev, &loopback_driver);
+}
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
new file mode 100644
index 0000000..61652f0
--- /dev/null
+++ b/drivers/usb/gadget/f_rndis.c
@@ -0,0 +1,827 @@
+/*
+ * f_rndis.c -- RNDIS link function driver
+ *
+ * Copyright (C) 2003-2005,2008 David Brownell
+ * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/etherdevice.h>
+
+#include <asm/atomic.h>
+
+#include "u_ether.h"
+#include "rndis.h"
+
+
+/*
+ * This function is an RNDIS Ethernet port -- a Microsoft protocol that's
+ * been promoted instead of the standard CDC Ethernet.  The published RNDIS
+ * spec is ambiguous, incomplete, and needlessly complex.  Variants such as
+ * ActiveSync have even worse status in terms of specification.
+ *
+ * In short:  it's a protocol controlled by (and for) Microsoft, not for an
+ * Open ecosystem or markets.  Linux supports it *only* because Microsoft
+ * doesn't support the CDC Ethernet standard.
+ *
+ * The RNDIS data transfer model is complex, with multiple Ethernet packets
+ * per USB message, and out of band data.  The control model is built around
+ * what's essentially an "RNDIS RPC" protocol.  It's all wrapped in a CDC ACM
+ * (modem, not Ethernet) veneer, with those ACM descriptors being entirely
+ * useless (they're ignored).  RNDIS expects to be the only function in its
+ * configuration, so it's no real help if you need composite devices; and
+ * it expects to be the first configuration too.
+ *
+ * There is a single technical advantage of RNDIS over CDC Ethernet, if you
+ * discount the fluff that its RPC can be made to deliver: it doesn't need
+ * a NOP altsetting for the data interface.  That lets it work on some of the
+ * "so smart it's stupid" hardware which takes over configuration changes
+ * from the software, and adds restrictions like "no altsettings".
+ *
+ * Unfortunately MSFT's RNDIS drivers are buggy.  They hang or oops, and
+ * have all sorts of contrary-to-specification oddities that can prevent
+ * them from working sanely.  Since bugfixes (or accurate specs, letting
+ * Linux work around those bugs) are unlikely to ever come from MSFT, you
+ * may want to avoid using RNDIS on purely operational grounds.
+ *
+ * Omissions from the RNDIS 1.0 specification include:
+ *
+ *   - Power management ... references data that's scattered around lots
+ *     of other documentation, which is incorrect/incomplete there too.
+ *
+ *   - There are various undocumented protocol requirements, like the need
+ *     to send garbage in some control-OUT messages.
+ *
+ *   - MS-Windows drivers sometimes emit undocumented requests.
+ */
+
+struct rndis_ep_descs {
+	struct usb_endpoint_descriptor	*in;
+	struct usb_endpoint_descriptor	*out;
+	struct usb_endpoint_descriptor	*notify;
+};
+
+struct f_rndis {
+	struct gether			port;
+	u8				ctrl_id, data_id;
+	u8				ethaddr[ETH_ALEN];
+	int				config;
+
+	struct usb_descriptor_header	**fs_function;
+	struct rndis_ep_descs		fs;
+	struct usb_descriptor_header	**hs_function;
+	struct rndis_ep_descs		hs;
+
+	struct usb_ep			*notify;
+	struct usb_endpoint_descriptor	*notify_desc;
+	struct usb_request		*notify_req;
+	atomic_t			notify_count;
+};
+
+static inline struct f_rndis *func_to_rndis(struct usb_function *f)
+{
+	return container_of(f, struct f_rndis, port.func);
+}
+
+/* peak (theoretical) bulk transfer rate in bits-per-second */
+static unsigned int bitrate(struct usb_gadget *g)
+{
+	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
+		return 13 * 512 * 8 * 1000 * 8;
+	else
+		return 19 *  64 * 1 * 1000 * 8;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ */
+
+#define LOG2_STATUS_INTERVAL_MSEC	5	/* 1 << 5 == 32 msec */
+#define STATUS_BYTECOUNT		8	/* 8 bytes data */
+
+
+/* interface descriptor: */
+
+static struct usb_interface_descriptor rndis_control_intf __initdata = {
+	.bLength =		sizeof rndis_control_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	/* .bInterfaceNumber = DYNAMIC */
+	/* status endpoint is optional; this could be patched later */
+	.bNumEndpoints =	1,
+	.bInterfaceClass =	USB_CLASS_COMM,
+	.bInterfaceSubClass =   USB_CDC_SUBCLASS_ACM,
+	.bInterfaceProtocol =   USB_CDC_ACM_PROTO_VENDOR,
+	/* .iInterface = DYNAMIC */
+};
+
+static struct usb_cdc_header_desc header_desc __initdata = {
+	.bLength =		sizeof header_desc,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
+
+	.bcdCDC =		__constant_cpu_to_le16(0x0110),
+};
+
+static struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor __initdata = {
+	.bLength =		sizeof call_mgmt_descriptor,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_CALL_MANAGEMENT_TYPE,
+
+	.bmCapabilities =	0x00,
+	.bDataInterface =	0x01,
+};
+
+static struct usb_cdc_acm_descriptor acm_descriptor __initdata = {
+	.bLength =		sizeof acm_descriptor,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_ACM_TYPE,
+
+	.bmCapabilities =	0x00,
+};
+
+static struct usb_cdc_union_desc rndis_union_desc __initdata = {
+	.bLength =		sizeof(rndis_union_desc),
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_UNION_TYPE,
+	/* .bMasterInterface0 =	DYNAMIC */
+	/* .bSlaveInterface0 =	DYNAMIC */
+};
+
+/* the data interface has two bulk endpoints */
+
+static struct usb_interface_descriptor rndis_data_intf __initdata = {
+	.bLength =		sizeof rndis_data_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	/* .bInterfaceNumber = DYNAMIC */
+	.bAlternateSetting =	1,
+	.bNumEndpoints =	2,
+	.bInterfaceClass =	USB_CLASS_CDC_DATA,
+	.bInterfaceSubClass =	0,
+	.bInterfaceProtocol =	0,
+	/* .iInterface = DYNAMIC */
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor fs_notify_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize =	__constant_cpu_to_le16(STATUS_BYTECOUNT),
+	.bInterval =		1 << LOG2_STATUS_INTERVAL_MSEC,
+};
+
+static struct usb_endpoint_descriptor fs_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor fs_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *eth_fs_function[] __initdata = {
+	/* control interface matches ACM, not Ethernet */
+	(struct usb_descriptor_header *) &rndis_control_intf,
+	(struct usb_descriptor_header *) &header_desc,
+	(struct usb_descriptor_header *) &call_mgmt_descriptor,
+	(struct usb_descriptor_header *) &acm_descriptor,
+	(struct usb_descriptor_header *) &rndis_union_desc,
+	(struct usb_descriptor_header *) &fs_notify_desc,
+	/* data interface has no altsetting */
+	(struct usb_descriptor_header *) &rndis_data_intf,
+	(struct usb_descriptor_header *) &fs_in_desc,
+	(struct usb_descriptor_header *) &fs_out_desc,
+	NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor hs_notify_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize =	__constant_cpu_to_le16(STATUS_BYTECOUNT),
+	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4,
+};
+static struct usb_endpoint_descriptor hs_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor hs_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *eth_hs_function[] __initdata = {
+	/* control interface matches ACM, not Ethernet */
+	(struct usb_descriptor_header *) &rndis_control_intf,
+	(struct usb_descriptor_header *) &header_desc,
+	(struct usb_descriptor_header *) &call_mgmt_descriptor,
+	(struct usb_descriptor_header *) &acm_descriptor,
+	(struct usb_descriptor_header *) &rndis_union_desc,
+	(struct usb_descriptor_header *) &hs_notify_desc,
+	/* data interface has no altsetting */
+	(struct usb_descriptor_header *) &rndis_data_intf,
+	(struct usb_descriptor_header *) &hs_in_desc,
+	(struct usb_descriptor_header *) &hs_out_desc,
+	NULL,
+};
+
+/* string descriptors: */
+
+static struct usb_string rndis_string_defs[] = {
+	[0].s = "RNDIS Communications Control",
+	[1].s = "RNDIS Ethernet Data",
+	{  } /* end of list */
+};
+
+static struct usb_gadget_strings rndis_string_table = {
+	.language =		0x0409,	/* en-us */
+	.strings =		rndis_string_defs,
+};
+
+static struct usb_gadget_strings *rndis_strings[] = {
+	&rndis_string_table,
+	NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static struct sk_buff *rndis_add_header(struct sk_buff *skb)
+{
+	skb = skb_realloc_headroom(skb, sizeof(struct rndis_packet_msg_type));
+	if (skb)
+		rndis_add_hdr(skb);
+	return skb;
+}
+
+static void rndis_response_available(void *_rndis)
+{
+	struct f_rndis			*rndis = _rndis;
+	struct usb_request		*req = rndis->notify_req;
+	struct usb_composite_dev	*cdev = rndis->port.func.config->cdev;
+	__le32				*data = req->buf;
+	int				status;
+
+	if (atomic_inc_return(&rndis->notify_count))
+		return;
+
+	/* Send RNDIS RESPONSE_AVAILABLE notification; a
+	 * USB_CDC_NOTIFY_RESPONSE_AVAILABLE "should" work too
+	 *
+	 * This is the only notification defined by RNDIS.
+	 */
+	data[0] = cpu_to_le32(1);
+	data[1] = cpu_to_le32(0);
+
+	status = usb_ep_queue(rndis->notify, req, GFP_ATOMIC);
+	if (status) {
+		atomic_dec(&rndis->notify_count);
+		DBG(cdev, "notify/0 --> %d\n", status);
+	}
+}
+
+static void rndis_response_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_rndis			*rndis = req->context;
+	struct usb_composite_dev	*cdev = rndis->port.func.config->cdev;
+	int				status = req->status;
+
+	/* after TX:
+	 *  - USB_CDC_GET_ENCAPSULATED_RESPONSE (ep0/control)
+	 *  - RNDIS_RESPONSE_AVAILABLE (status/irq)
+	 */
+	switch (status) {
+	case -ECONNRESET:
+	case -ESHUTDOWN:
+		/* connection gone */
+		atomic_set(&rndis->notify_count, 0);
+		break;
+	default:
+		DBG(cdev, "RNDIS %s response error %d, %d/%d\n",
+			ep->name, status,
+			req->actual, req->length);
+		/* FALLTHROUGH */
+	case 0:
+		if (ep != rndis->notify)
+			break;
+
+		/* handle multiple pending RNDIS_RESPONSE_AVAILABLE
+		 * notifications by resending until we're done
+		 */
+		if (atomic_dec_and_test(&rndis->notify_count))
+			break;
+		status = usb_ep_queue(rndis->notify, req, GFP_ATOMIC);
+		if (status) {
+			atomic_dec(&rndis->notify_count);
+			DBG(cdev, "notify/1 --> %d\n", status);
+		}
+		break;
+	}
+}
+
+static void rndis_command_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_rndis			*rndis = req->context;
+	struct usb_composite_dev	*cdev = rndis->port.func.config->cdev;
+	int				status;
+
+	/* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */
+//	spin_lock(&dev->lock);
+	status = rndis_msg_parser(rndis->config, (u8 *) req->buf);
+	if (status < 0)
+		ERROR(cdev, "RNDIS command error %d, %d/%d\n",
+			status, req->actual, req->length);
+//	spin_unlock(&dev->lock);
+}
+
+static int
+rndis_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+	struct f_rndis		*rndis = func_to_rndis(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+	struct usb_request	*req = cdev->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);
+
+	/* composite driver infrastructure handles everything except
+	 * CDC class messages; interface activation uses set_alt().
+	 */
+	switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
+
+	/* RNDIS uses the CDC command encapsulation mechanism to implement
+	 * an RPC scheme, with much getting/setting of attributes by OID.
+	 */
+	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+			| USB_CDC_SEND_ENCAPSULATED_COMMAND:
+		if (w_length > req->length || w_value
+				|| w_index != rndis->ctrl_id)
+			goto invalid;
+		/* read the request; process it later */
+		value = w_length;
+		req->complete = rndis_command_complete;
+		req->context = rndis;
+		/* later, rndis_response_available() sends a notification */
+		break;
+
+	case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+			| USB_CDC_GET_ENCAPSULATED_RESPONSE:
+		if (w_value || w_index != rndis->ctrl_id)
+			goto invalid;
+		else {
+			u8 *buf;
+			u32 n;
+
+			/* return the result */
+			buf = rndis_get_next_response(rndis->config, &n);
+			if (buf) {
+				memcpy(req->buf, buf, n);
+				req->complete = rndis_response_complete;
+				rndis_free_response(rndis->config, buf);
+				value = n;
+			}
+			/* else stalls ... spec says to avoid that */
+		}
+		break;
+
+	default:
+invalid:
+		VDBG(cdev, "invalid 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 or status phase? */
+	if (value >= 0) {
+		DBG(cdev, "rndis req%02x.%02x v%04x i%04x l%d\n",
+			ctrl->bRequestType, ctrl->bRequest,
+			w_value, w_index, w_length);
+		req->zero = 0;
+		req->length = value;
+		value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+		if (value < 0)
+			ERROR(cdev, "rndis response on err %d\n", value);
+	}
+
+	/* device either stalls (value < 0) or reports success */
+	return value;
+}
+
+
+static int rndis_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+	struct f_rndis		*rndis = func_to_rndis(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	/* we know alt == 0 */
+
+	if (intf == rndis->ctrl_id) {
+		if (rndis->notify->driver_data) {
+			VDBG(cdev, "reset rndis control %d\n", intf);
+			usb_ep_disable(rndis->notify);
+		} else {
+			VDBG(cdev, "init rndis ctrl %d\n", intf);
+			rndis->notify_desc = ep_choose(cdev->gadget,
+					rndis->hs.notify,
+					rndis->fs.notify);
+		}
+		usb_ep_enable(rndis->notify, rndis->notify_desc);
+		rndis->notify->driver_data = rndis;
+
+	} else if (intf == rndis->data_id) {
+		struct net_device	*net;
+
+		if (rndis->port.in_ep->driver_data) {
+			DBG(cdev, "reset rndis\n");
+			gether_disconnect(&rndis->port);
+		} else {
+			DBG(cdev, "init rndis\n");
+			rndis->port.in = ep_choose(cdev->gadget,
+					rndis->hs.in, rndis->fs.in);
+			rndis->port.out = ep_choose(cdev->gadget,
+					rndis->hs.out, rndis->fs.out);
+		}
+
+		/* Avoid ZLPs; they can be troublesome. */
+		rndis->port.is_zlp_ok = false;
+
+		/* RNDIS should be in the "RNDIS uninitialized" state,
+		 * either never activated or after rndis_uninit().
+		 *
+		 * We don't want data to flow here until a nonzero packet
+		 * filter is set, at which point it enters "RNDIS data
+		 * initialized" state ... but we do want the endpoints
+		 * to be activated.  It's a strange little state.
+		 *
+		 * REVISIT the RNDIS gadget code has done this wrong for a
+		 * very long time.  We need another call to the link layer
+		 * code -- gether_updown(...bool) maybe -- to do it right.
+		 */
+		rndis->port.cdc_filter = 0;
+
+		DBG(cdev, "RNDIS RX/TX early activation ... \n");
+		net = gether_connect(&rndis->port);
+		if (IS_ERR(net))
+			return PTR_ERR(net);
+
+		rndis_set_param_dev(rndis->config, net,
+				&rndis->port.cdc_filter);
+	} else
+		goto fail;
+
+	return 0;
+fail:
+	return -EINVAL;
+}
+
+static void rndis_disable(struct usb_function *f)
+{
+	struct f_rndis		*rndis = func_to_rndis(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	if (!rndis->notify->driver_data)
+		return;
+
+	DBG(cdev, "rndis deactivated\n");
+
+	rndis_uninit(rndis->config);
+	gether_disconnect(&rndis->port);
+
+	usb_ep_disable(rndis->notify);
+	rndis->notify->driver_data = NULL;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * This isn't quite the same mechanism as CDC Ethernet, since the
+ * notification scheme passes less data, but the same set of link
+ * states must be tested.  A key difference is that altsettings are
+ * not used to tell whether the link should send packets or not.
+ */
+
+static void rndis_open(struct gether *geth)
+{
+	struct f_rndis		*rndis = func_to_rndis(&geth->func);
+	struct usb_composite_dev *cdev = geth->func.config->cdev;
+
+	DBG(cdev, "%s\n", __func__);
+
+	rndis_set_param_medium(rndis->config, NDIS_MEDIUM_802_3,
+				bitrate(cdev->gadget) / 100);
+	rndis_signal_connect(rndis->config);
+}
+
+static void rndis_close(struct gether *geth)
+{
+	struct f_rndis		*rndis = func_to_rndis(&geth->func);
+
+	DBG(geth->func.config->cdev, "%s\n", __func__);
+
+	rndis_set_param_medium(rndis->config, NDIS_MEDIUM_802_3, 0);
+	rndis_signal_disconnect(rndis->config);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* ethernet function driver setup/binding */
+
+static int __init
+rndis_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct usb_composite_dev *cdev = c->cdev;
+	struct f_rndis		*rndis = func_to_rndis(f);
+	int			status;
+	struct usb_ep		*ep;
+
+	/* allocate instance-specific interface IDs */
+	status = usb_interface_id(c, f);
+	if (status < 0)
+		goto fail;
+	rndis->ctrl_id = status;
+
+	rndis_control_intf.bInterfaceNumber = status;
+	rndis_union_desc.bMasterInterface0 = status;
+
+	status = usb_interface_id(c, f);
+	if (status < 0)
+		goto fail;
+	rndis->data_id = status;
+
+	rndis_data_intf.bInterfaceNumber = status;
+	rndis_union_desc.bSlaveInterface0 = status;
+
+	status = -ENODEV;
+
+	/* allocate instance-specific endpoints */
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc);
+	if (!ep)
+		goto fail;
+	rndis->port.in_ep = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc);
+	if (!ep)
+		goto fail;
+	rndis->port.out_ep = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	/* NOTE:  a status/notification endpoint is, strictly speaking,
+	 * optional.  We don't treat it that way though!  It's simpler,
+	 * and some newer profiles don't treat it as optional.
+	 */
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_notify_desc);
+	if (!ep)
+		goto fail;
+	rndis->notify = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	status = -ENOMEM;
+
+	/* allocate notification request and buffer */
+	rndis->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL);
+	if (!rndis->notify_req)
+		goto fail;
+	rndis->notify_req->buf = kmalloc(STATUS_BYTECOUNT, GFP_KERNEL);
+	if (!rndis->notify_req->buf)
+		goto fail;
+	rndis->notify_req->length = STATUS_BYTECOUNT;
+	rndis->notify_req->context = rndis;
+	rndis->notify_req->complete = rndis_response_complete;
+
+	/* copy descriptors, and track endpoint copies */
+	f->descriptors = usb_copy_descriptors(eth_fs_function);
+	if (!f->descriptors)
+		goto fail;
+
+	rndis->fs.in = usb_find_endpoint(eth_fs_function,
+			f->descriptors, &fs_in_desc);
+	rndis->fs.out = usb_find_endpoint(eth_fs_function,
+			f->descriptors, &fs_out_desc);
+	rndis->fs.notify = usb_find_endpoint(eth_fs_function,
+			f->descriptors, &fs_notify_desc);
+
+	/* support all relevant hardware speeds... we expect that when
+	 * hardware is dual speed, all bulk-capable endpoints work at
+	 * both speeds
+	 */
+	if (gadget_is_dualspeed(c->cdev->gadget)) {
+		hs_in_desc.bEndpointAddress =
+				fs_in_desc.bEndpointAddress;
+		hs_out_desc.bEndpointAddress =
+				fs_out_desc.bEndpointAddress;
+
+		/* copy descriptors, and track endpoint copies */
+		f->hs_descriptors = usb_copy_descriptors(eth_hs_function);
+
+		if (!f->hs_descriptors)
+			goto fail;
+
+		rndis->hs.in = usb_find_endpoint(eth_hs_function,
+				f->hs_descriptors, &hs_in_desc);
+		rndis->hs.out = usb_find_endpoint(eth_hs_function,
+				f->hs_descriptors, &hs_out_desc);
+	}
+
+	rndis->port.open = rndis_open;
+	rndis->port.close = rndis_close;
+
+	status = rndis_register(rndis_response_available, rndis);
+	if (status < 0)
+		goto fail;
+	rndis->config = status;
+
+	rndis_set_param_medium(rndis->config, NDIS_MEDIUM_802_3, 0);
+	rndis_set_host_mac(rndis->config, rndis->ethaddr);
+
+#if 0
+// FIXME
+	if (rndis_set_param_vendor(rndis->config, vendorID,
+				manufacturer))
+		goto fail0;
+#endif
+
+	/* NOTE:  all that is done without knowing or caring about
+	 * the network link ... which is unavailable to this code
+	 * until we're activated via set_alt().
+	 */
+
+	DBG(cdev, "RNDIS: %s speed IN/%s OUT/%s NOTIFY/%s\n",
+			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+			rndis->port.in_ep->name, rndis->port.out_ep->name,
+			rndis->notify->name);
+	return 0;
+
+fail:
+	if (gadget_is_dualspeed(c->cdev->gadget) && f->hs_descriptors)
+		usb_free_descriptors(f->hs_descriptors);
+	if (f->descriptors)
+		usb_free_descriptors(f->descriptors);
+
+	if (rndis->notify_req) {
+		kfree(rndis->notify_req->buf);
+		usb_ep_free_request(rndis->notify, rndis->notify_req);
+	}
+
+	/* we might as well release our claims on endpoints */
+	if (rndis->notify)
+		rndis->notify->driver_data = NULL;
+	if (rndis->port.out)
+		rndis->port.out_ep->driver_data = NULL;
+	if (rndis->port.in)
+		rndis->port.in_ep->driver_data = NULL;
+
+	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
+
+	return status;
+}
+
+static void
+rndis_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct f_rndis		*rndis = func_to_rndis(f);
+
+	rndis_deregister(rndis->config);
+	rndis_exit();
+
+	if (gadget_is_dualspeed(c->cdev->gadget))
+		usb_free_descriptors(f->hs_descriptors);
+	usb_free_descriptors(f->descriptors);
+
+	kfree(rndis->notify_req->buf);
+	usb_ep_free_request(rndis->notify, rndis->notify_req);
+
+	kfree(rndis);
+}
+
+/* Some controllers can't support RNDIS ... */
+static inline bool can_support_rndis(struct usb_configuration *c)
+{
+	/* only two endpoints on sa1100 */
+	if (gadget_is_sa1100(c->cdev->gadget))
+		return false;
+
+	/* everything else is *presumably* fine */
+	return true;
+}
+
+/**
+ * rndis_bind_config - add RNDIS network link to a configuration
+ * @c: the configuration to support the network link
+ * @ethaddr: a buffer in which the ethernet address of the host side
+ *	side of the link was recorded
+ * Context: single threaded during gadget setup
+ *
+ * Returns zero on success, else negative errno.
+ *
+ * Caller must have called @gether_setup().  Caller is also responsible
+ * for calling @gether_cleanup() before module unload.
+ */
+int __init rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+{
+	struct f_rndis	*rndis;
+	int		status;
+
+	if (!can_support_rndis(c) || !ethaddr)
+		return -EINVAL;
+
+	/* maybe allocate device-global string IDs */
+	if (rndis_string_defs[0].id == 0) {
+
+		/* ... and setup RNDIS itself */
+		status = rndis_init();
+		if (status < 0)
+			return status;
+
+		/* control interface label */
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		rndis_string_defs[0].id = status;
+		rndis_control_intf.iInterface = status;
+
+		/* data interface label */
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		rndis_string_defs[1].id = status;
+		rndis_data_intf.iInterface = status;
+	}
+
+	/* allocate and initialize one new instance */
+	status = -ENOMEM;
+	rndis = kzalloc(sizeof *rndis, GFP_KERNEL);
+	if (!rndis)
+		goto fail;
+
+	memcpy(rndis->ethaddr, ethaddr, ETH_ALEN);
+
+	/* RNDIS activates when the host changes this filter */
+	rndis->port.cdc_filter = 0;
+
+	/* RNDIS has special (and complex) framing */
+	rndis->port.header_len = sizeof(struct rndis_packet_msg_type);
+	rndis->port.wrap = rndis_add_header;
+	rndis->port.unwrap = rndis_rm_hdr;
+
+	rndis->port.func.name = "rndis";
+	rndis->port.func.strings = rndis_strings;
+	/* descriptors are per-instance copies */
+	rndis->port.func.bind = rndis_bind;
+	rndis->port.func.unbind = rndis_unbind;
+	rndis->port.func.set_alt = rndis_set_alt;
+	rndis->port.func.setup = rndis_setup;
+	rndis->port.func.disable = rndis_disable;
+
+	status = usb_add_function(c, &rndis->port.func);
+	if (status) {
+		kfree(rndis);
+fail:
+		rndis_exit();
+	}
+	return status;
+}
diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c
new file mode 100644
index 0000000..1b6bde9
--- /dev/null
+++ b/drivers/usb/gadget/f_serial.c
@@ -0,0 +1,296 @@
+/*
+ * f_serial.c - generic USB serial function driver
+ *
+ * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
+ * Copyright (C) 2008 by David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
+ *
+ * This software is distributed under the terms of the GNU General
+ * Public License ("GPL") as published by the Free Software Foundation,
+ * either version 2 of that License or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+
+#include "u_serial.h"
+#include "gadget_chips.h"
+
+
+/*
+ * This function packages a simple "generic serial" port with no real
+ * control mechanisms, just raw data transfer over two bulk endpoints.
+ *
+ * Because it's not standardized, this isn't as interoperable as the
+ * CDC ACM driver.  However, for many purposes it's just as functional
+ * if you can arrange appropriate host side drivers.
+ */
+
+struct gser_descs {
+	struct usb_endpoint_descriptor	*in;
+	struct usb_endpoint_descriptor	*out;
+};
+
+struct f_gser {
+	struct gserial			port;
+	u8				data_id;
+	u8				port_num;
+
+	struct usb_descriptor_header	**fs_function;
+	struct gser_descs		fs;
+	struct usb_descriptor_header	**hs_function;
+	struct gser_descs		hs;
+};
+
+static inline struct f_gser *func_to_gser(struct usb_function *f)
+{
+	return container_of(f, struct f_gser, port.func);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* interface descriptor: */
+
+static struct usb_interface_descriptor gser_interface_desc __initdata = {
+	.bLength =		USB_DT_INTERFACE_SIZE,
+	.bDescriptorType =	USB_DT_INTERFACE,
+	/* .bInterfaceNumber = DYNAMIC */
+	.bNumEndpoints =	2,
+	.bInterfaceClass =	USB_CLASS_VENDOR_SPEC,
+	.bInterfaceSubClass =	0,
+	.bInterfaceProtocol =	0,
+	/* .iInterface = DYNAMIC */
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor gser_fs_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor gser_fs_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *gser_fs_function[] __initdata = {
+	(struct usb_descriptor_header *) &gser_interface_desc,
+	(struct usb_descriptor_header *) &gser_fs_in_desc,
+	(struct usb_descriptor_header *) &gser_fs_out_desc,
+	NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor gser_hs_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor gser_hs_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *gser_hs_function[] __initdata = {
+	(struct usb_descriptor_header *) &gser_interface_desc,
+	(struct usb_descriptor_header *) &gser_hs_in_desc,
+	(struct usb_descriptor_header *) &gser_hs_out_desc,
+	NULL,
+};
+
+/* string descriptors: */
+
+static struct usb_string gser_string_defs[] = {
+	[0].s = "Generic Serial",
+	{  } /* end of list */
+};
+
+static struct usb_gadget_strings gser_string_table = {
+	.language =		0x0409,	/* en-us */
+	.strings =		gser_string_defs,
+};
+
+static struct usb_gadget_strings *gser_strings[] = {
+	&gser_string_table,
+	NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+	struct f_gser		*gser = func_to_gser(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	/* we know alt == 0, so this is an activation or a reset */
+
+	if (gser->port.in->driver_data) {
+		DBG(cdev, "reset generic ttyGS%d\n", gser->port_num);
+		gserial_disconnect(&gser->port);
+	} else {
+		DBG(cdev, "activate generic ttyGS%d\n", gser->port_num);
+		gser->port.in_desc = ep_choose(cdev->gadget,
+				gser->hs.in, gser->fs.in);
+		gser->port.out_desc = ep_choose(cdev->gadget,
+				gser->hs.out, gser->fs.out);
+	}
+	gserial_connect(&gser->port, gser->port_num);
+	return 0;
+}
+
+static void gser_disable(struct usb_function *f)
+{
+	struct f_gser	*gser = func_to_gser(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	DBG(cdev, "generic ttyGS%d deactivated\n", gser->port_num);
+	gserial_disconnect(&gser->port);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* serial function driver setup/binding */
+
+static int __init
+gser_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct usb_composite_dev *cdev = c->cdev;
+	struct f_gser		*gser = func_to_gser(f);
+	int			status;
+	struct usb_ep		*ep;
+
+	/* allocate instance-specific interface IDs */
+	status = usb_interface_id(c, f);
+	if (status < 0)
+		goto fail;
+	gser->data_id = status;
+	gser_interface_desc.bInterfaceNumber = status;
+
+	status = -ENODEV;
+
+	/* allocate instance-specific endpoints */
+	ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_in_desc);
+	if (!ep)
+		goto fail;
+	gser->port.in = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_out_desc);
+	if (!ep)
+		goto fail;
+	gser->port.out = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	/* copy descriptors, and track endpoint copies */
+	f->descriptors = usb_copy_descriptors(gser_fs_function);
+
+	gser->fs.in = usb_find_endpoint(gser_fs_function,
+			f->descriptors, &gser_fs_in_desc);
+	gser->fs.out = usb_find_endpoint(gser_fs_function,
+			f->descriptors, &gser_fs_out_desc);
+
+
+	/* support all relevant hardware speeds... we expect that when
+	 * hardware is dual speed, all bulk-capable endpoints work at
+	 * both speeds
+	 */
+	if (gadget_is_dualspeed(c->cdev->gadget)) {
+		gser_hs_in_desc.bEndpointAddress =
+				gser_fs_in_desc.bEndpointAddress;
+		gser_hs_out_desc.bEndpointAddress =
+				gser_fs_out_desc.bEndpointAddress;
+
+		/* copy descriptors, and track endpoint copies */
+		f->hs_descriptors = usb_copy_descriptors(gser_hs_function);
+
+		gser->hs.in = usb_find_endpoint(gser_hs_function,
+				f->hs_descriptors, &gser_hs_in_desc);
+		gser->hs.out = usb_find_endpoint(gser_hs_function,
+				f->hs_descriptors, &gser_hs_out_desc);
+	}
+
+	DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n",
+			gser->port_num,
+			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+			gser->port.in->name, gser->port.out->name);
+	return 0;
+
+fail:
+	/* we might as well release our claims on endpoints */
+	if (gser->port.out)
+		gser->port.out->driver_data = NULL;
+	if (gser->port.in)
+		gser->port.in->driver_data = NULL;
+
+	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
+
+	return status;
+}
+
+static void
+gser_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	if (gadget_is_dualspeed(c->cdev->gadget))
+		usb_free_descriptors(f->hs_descriptors);
+	usb_free_descriptors(f->descriptors);
+	kfree(func_to_gser(f));
+}
+
+/**
+ * gser_bind_config - add a generic serial function to a configuration
+ * @c: the configuration to support the serial instance
+ * @port_num: /dev/ttyGS* port this interface will use
+ * Context: single threaded during gadget setup
+ *
+ * Returns zero on success, else negative errno.
+ *
+ * Caller must have called @gserial_setup() with enough ports to
+ * handle all the ones it binds.  Caller is also responsible
+ * for calling @gserial_cleanup() before module unload.
+ */
+int __init gser_bind_config(struct usb_configuration *c, u8 port_num)
+{
+	struct f_gser	*gser;
+	int		status;
+
+	/* REVISIT might want instance-specific strings to help
+	 * distinguish instances ...
+	 */
+
+	/* maybe allocate device-global string ID */
+	if (gser_string_defs[0].id == 0) {
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		gser_string_defs[0].id = status;
+	}
+
+	/* allocate and initialize one new instance */
+	gser = kzalloc(sizeof *gser, GFP_KERNEL);
+	if (!gser)
+		return -ENOMEM;
+
+	gser->port_num = port_num;
+
+	gser->port.func.name = "gser";
+	gser->port.func.strings = gser_strings;
+	gser->port.func.bind = gser_bind;
+	gser->port.func.unbind = gser_unbind;
+	gser->port.func.set_alt = gser_set_alt;
+	gser->port.func.disable = gser_disable;
+
+	status = usb_add_function(c, &gser->port.func);
+	if (status)
+		kfree(gser);
+	return status;
+}
diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c
new file mode 100644
index 0000000..f18c3a1
--- /dev/null
+++ b/drivers/usb/gadget/f_sourcesink.c
@@ -0,0 +1,587 @@
+/*
+ * f_sourcesink.c - USB peripheral source/sink configuration driver
+ *
+ * Copyright (C) 2003-2008 David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/utsname.h>
+#include <linux/device.h>
+
+#include "g_zero.h"
+#include "gadget_chips.h"
+
+
+/*
+ * SOURCE/SINK FUNCTION ... a primary testing vehicle for USB peripheral
+ * controller drivers.
+ *
+ * This just sinks bulk packets OUT to the peripheral and sources them IN
+ * to the host, optionally with specific data patterns for integrity tests.
+ * As such it supports basic functionality and load tests.
+ *
+ * In terms of control messaging, this supports all the standard requests
+ * plus two that support control-OUT tests.  If the optional "autoresume"
+ * mode is enabled, it provides good functional coverage for the "USBCV"
+ * test harness from USB-IF.
+ *
+ * Note that because this doesn't queue more than one request at a time,
+ * some other function must be used to test queueing logic.  The network
+ * link (g_ether) is the best overall option for that, since its TX and RX
+ * queues are relatively independent, will receive a range of packet sizes,
+ * and can often be made to run out completely.  Those issues are important
+ * when stress testing peripheral controller drivers.
+ *
+ *
+ * This is currently packaged as a configuration driver, which can't be
+ * combined with other functions to make composite devices.  However, it
+ * can be combined with other independent configurations.
+ */
+struct f_sourcesink {
+	struct usb_function	function;
+
+	struct usb_ep		*in_ep;
+	struct usb_ep		*out_ep;
+	struct timer_list	resume;
+};
+
+static inline struct f_sourcesink *func_to_ss(struct usb_function *f)
+{
+	return container_of(f, struct f_sourcesink, function);
+}
+
+static unsigned autoresume;
+module_param(autoresume, uint, 0);
+MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup");
+
+static unsigned pattern;
+module_param(pattern, uint, 0);
+MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63 ");
+
+/*-------------------------------------------------------------------------*/
+
+static struct usb_interface_descriptor source_sink_intf = {
+	.bLength =		sizeof source_sink_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	.bNumEndpoints =	2,
+	.bInterfaceClass =	USB_CLASS_VENDOR_SPEC,
+	/* .iInterface = DYNAMIC */
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor fs_source_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor fs_sink_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *fs_source_sink_descs[] = {
+	(struct usb_descriptor_header *) &source_sink_intf,
+	(struct usb_descriptor_header *) &fs_sink_desc,
+	(struct usb_descriptor_header *) &fs_source_desc,
+	NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor hs_source_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor hs_sink_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *hs_source_sink_descs[] = {
+	(struct usb_descriptor_header *) &source_sink_intf,
+	(struct usb_descriptor_header *) &hs_source_desc,
+	(struct usb_descriptor_header *) &hs_sink_desc,
+	NULL,
+};
+
+/* function-specific strings: */
+
+static struct usb_string strings_sourcesink[] = {
+	[0].s = "source and sink data",
+	{  }			/* end of list */
+};
+
+static struct usb_gadget_strings stringtab_sourcesink = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= strings_sourcesink,
+};
+
+static struct usb_gadget_strings *sourcesink_strings[] = {
+	&stringtab_sourcesink,
+	NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static void sourcesink_autoresume(unsigned long _c)
+{
+	struct usb_composite_dev *cdev = (void *)_c;
+	struct usb_gadget	*g = cdev->gadget;
+
+	/* Normally the host would be woken up for something
+	 * more significant than just a timer firing; likely
+	 * because of some direct user request.
+	 */
+	if (g->speed != USB_SPEED_UNKNOWN) {
+		int status = usb_gadget_wakeup(g);
+		DBG(cdev, "%s --> %d\n", __func__, status);
+	}
+}
+
+static int __init
+sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct usb_composite_dev *cdev = c->cdev;
+	struct f_sourcesink	*ss = func_to_ss(f);
+	int	id;
+
+	/* allocate interface ID(s) */
+	id = usb_interface_id(c, f);
+	if (id < 0)
+		return id;
+	source_sink_intf.bInterfaceNumber = id;
+
+	/* allocate endpoints */
+	ss->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc);
+	if (!ss->in_ep) {
+autoconf_fail:
+		ERROR(cdev, "%s: can't autoconfigure on %s\n",
+			f->name, cdev->gadget->name);
+		return -ENODEV;
+	}
+	ss->in_ep->driver_data = cdev;	/* claim */
+
+	ss->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_sink_desc);
+	if (!ss->out_ep)
+		goto autoconf_fail;
+	ss->out_ep->driver_data = cdev;	/* claim */
+
+	setup_timer(&ss->resume, sourcesink_autoresume,
+			(unsigned long) c->cdev);
+
+	/* support high speed hardware */
+	if (gadget_is_dualspeed(c->cdev->gadget)) {
+		hs_source_desc.bEndpointAddress =
+				fs_source_desc.bEndpointAddress;
+		hs_sink_desc.bEndpointAddress =
+				fs_sink_desc.bEndpointAddress;
+		f->hs_descriptors = hs_source_sink_descs;
+	}
+
+	DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
+			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+			f->name, ss->in_ep->name, ss->out_ep->name);
+	return 0;
+}
+
+static void
+sourcesink_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	kfree(func_to_ss(f));
+}
+
+/* optionally require specific source/sink data patterns  */
+static int check_read_data(struct f_sourcesink *ss, struct usb_request *req)
+{
+	unsigned		i;
+	u8			*buf = req->buf;
+	struct usb_composite_dev *cdev = ss->function.config->cdev;
+
+	for (i = 0; i < req->actual; i++, buf++) {
+		switch (pattern) {
+
+		/* all-zeroes has no synchronization issues */
+		case 0:
+			if (*buf == 0)
+				continue;
+			break;
+
+		/* "mod63" stays in sync with short-terminated transfers,
+		 * OR otherwise when host and gadget agree on how large
+		 * each usb transfer request should be.  Resync is done
+		 * with set_interface or set_config.  (We *WANT* it to
+		 * get quickly out of sync if controllers or their drivers
+		 * stutter for any reason, including buffer duplcation...)
+		 */
+		case 1:
+			if (*buf == (u8)(i % 63))
+				continue;
+			break;
+		}
+		ERROR(cdev, "bad OUT byte, buf[%d] = %d\n", i, *buf);
+		usb_ep_set_halt(ss->out_ep);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void reinit_write_data(struct usb_ep *ep, struct usb_request *req)
+{
+	unsigned	i;
+	u8		*buf = req->buf;
+
+	switch (pattern) {
+	case 0:
+		memset(req->buf, 0, req->length);
+		break;
+	case 1:
+		for  (i = 0; i < req->length; i++)
+			*buf++ = (u8) (i % 63);
+		break;
+	}
+}
+
+static void source_sink_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_sourcesink	*ss = ep->driver_data;
+	struct usb_composite_dev *cdev = ss->function.config->cdev;
+	int			status = req->status;
+
+	switch (status) {
+
+	case 0:				/* normal completion? */
+		if (ep == ss->out_ep) {
+			check_read_data(ss, req);
+			memset(req->buf, 0x55, req->length);
+		} else
+			reinit_write_data(ep, req);
+		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(cdev, "%s gone (%d), %d/%d\n", ep->name, status,
+				req->actual, req->length);
+		if (ep == ss->out_ep)
+			check_read_data(ss, req);
+		free_ep_req(ep, req);
+		return;
+
+	case -EOVERFLOW:		/* buffer overrun on read means that
+					 * we didn't provide a big enough
+					 * buffer.
+					 */
+	default:
+#if 1
+		DBG(cdev, "%s complete --> %d, %d/%d\n", ep->name,
+				status, req->actual, req->length);
+#endif
+	case -EREMOTEIO:		/* short read */
+		break;
+	}
+
+	status = usb_ep_queue(ep, req, GFP_ATOMIC);
+	if (status) {
+		ERROR(cdev, "kill %s:  resubmit %d bytes --> %d\n",
+				ep->name, req->length, status);
+		usb_ep_set_halt(ep);
+		/* FIXME recover later ... somehow */
+	}
+}
+
+static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in)
+{
+	struct usb_ep		*ep;
+	struct usb_request	*req;
+	int			status;
+
+	ep = is_in ? ss->in_ep : ss->out_ep;
+	req = alloc_ep_req(ep);
+	if (!req)
+		return -ENOMEM;
+
+	req->complete = source_sink_complete;
+	if (is_in)
+		reinit_write_data(ep, req);
+	else
+		memset(req->buf, 0x55, req->length);
+
+	status = usb_ep_queue(ep, req, GFP_ATOMIC);
+	if (status) {
+		struct usb_composite_dev	*cdev;
+
+		cdev = ss->function.config->cdev;
+		ERROR(cdev, "start %s %s --> %d\n",
+				is_in ? "IN" : "OUT",
+				ep->name, status);
+		free_ep_req(ep, req);
+	}
+
+	return status;
+}
+
+static void disable_source_sink(struct f_sourcesink *ss)
+{
+	struct usb_composite_dev	*cdev;
+
+	cdev = ss->function.config->cdev;
+	disable_endpoints(cdev, ss->in_ep, ss->out_ep);
+	del_timer(&ss->resume);
+	VDBG(cdev, "%s disabled\n", ss->function.name);
+}
+
+static int
+enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss)
+{
+	int					result = 0;
+	const struct usb_endpoint_descriptor	*src, *sink;
+	struct usb_ep				*ep;
+
+	src = ep_choose(cdev->gadget, &hs_source_desc, &fs_source_desc);
+	sink = ep_choose(cdev->gadget, &hs_sink_desc, &fs_sink_desc);
+
+	/* one endpoint writes (sources) zeroes IN (to the host) */
+	ep = ss->in_ep;
+	result = usb_ep_enable(ep, src);
+	if (result < 0)
+		return result;
+	ep->driver_data = ss;
+
+	result = source_sink_start_ep(ss, true);
+	if (result < 0) {
+fail:
+		ep = ss->in_ep;
+		usb_ep_disable(ep);
+		ep->driver_data = NULL;
+		return result;
+	}
+
+	/* one endpoint reads (sinks) anything OUT (from the host) */
+	ep = ss->out_ep;
+	result = usb_ep_enable(ep, sink);
+	if (result < 0)
+		goto fail;
+	ep->driver_data = ss;
+
+	result = source_sink_start_ep(ss, false);
+	if (result < 0) {
+		usb_ep_disable(ep);
+		ep->driver_data = NULL;
+		goto fail;
+	}
+
+	DBG(cdev, "%s enabled\n", ss->function.name);
+	return result;
+}
+
+static int sourcesink_set_alt(struct usb_function *f,
+		unsigned intf, unsigned alt)
+{
+	struct f_sourcesink	*ss = func_to_ss(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	/* we know alt is zero */
+	if (ss->in_ep->driver_data)
+		disable_source_sink(ss);
+	return enable_source_sink(cdev, ss);
+}
+
+static void sourcesink_disable(struct usb_function *f)
+{
+	struct f_sourcesink	*ss = func_to_ss(f);
+
+	disable_source_sink(ss);
+}
+
+static void sourcesink_suspend(struct usb_function *f)
+{
+	struct f_sourcesink	*ss = func_to_ss(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	if (cdev->gadget->speed == USB_SPEED_UNKNOWN)
+		return;
+
+	if (autoresume) {
+		mod_timer(&ss->resume, jiffies + (HZ * autoresume));
+		DBG(cdev, "suspend, wakeup in %d seconds\n", autoresume);
+	} else
+		DBG(cdev, "%s\n", __func__);
+}
+
+static void sourcesink_resume(struct usb_function *f)
+{
+	struct f_sourcesink	*ss = func_to_ss(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	DBG(cdev, "%s\n", __func__);
+	del_timer(&ss->resume);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int __init sourcesink_bind_config(struct usb_configuration *c)
+{
+	struct f_sourcesink	*ss;
+	int			status;
+
+	ss = kzalloc(sizeof *ss, GFP_KERNEL);
+	if (!ss)
+		return -ENOMEM;
+
+	ss->function.name = "source/sink";
+	ss->function.descriptors = fs_source_sink_descs;
+	ss->function.bind = sourcesink_bind;
+	ss->function.unbind = sourcesink_unbind;
+	ss->function.set_alt = sourcesink_set_alt;
+	ss->function.disable = sourcesink_disable;
+	ss->function.suspend = sourcesink_suspend;
+	ss->function.resume = sourcesink_resume;
+
+	status = usb_add_function(c, &ss->function);
+	if (status)
+		kfree(ss);
+	return status;
+}
+
+static int sourcesink_setup(struct usb_configuration *c,
+		const struct usb_ctrlrequest *ctrl)
+{
+	struct usb_request	*req = c->cdev->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);
+
+	/* composite driver infrastructure handles everything except
+	 * the two control test requests.
+	 */
+	switch (ctrl->bRequest) {
+
+	/*
+	 * These are the same vendor-specific requests supported by
+	 * Intel's USB 2.0 compliance test devices.  We exceed that
+	 * device spec by allowing multiple-packet requests.
+	 *
+	 * NOTE:  the Control-OUT data stays in req->buf ... better
+	 * would be copying it into a scratch buffer, so that other
+	 * requests may safely intervene.
+	 */
+	case 0x5b:	/* control WRITE test -- fill the buffer */
+		if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))
+			goto unknown;
+		if (w_value || w_index)
+			break;
+		/* just read that many bytes into the buffer */
+		if (w_length > req->length)
+			break;
+		value = w_length;
+		break;
+	case 0x5c:	/* control READ test -- return the buffer */
+		if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))
+			goto unknown;
+		if (w_value || w_index)
+			break;
+		/* expect those bytes are still in the buffer; send back */
+		if (w_length > req->length)
+			break;
+		value = w_length;
+		break;
+
+	default:
+unknown:
+		VDBG(c->cdev,
+			"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 or status phase? */
+	if (value >= 0) {
+		VDBG(c->cdev, "source/sink req%02x.%02x v%04x i%04x l%d\n",
+			ctrl->bRequestType, ctrl->bRequest,
+			w_value, w_index, w_length);
+		req->zero = 0;
+		req->length = value;
+		value = usb_ep_queue(c->cdev->gadget->ep0, req, GFP_ATOMIC);
+		if (value < 0)
+			ERROR(c->cdev, "source/sinkc response, err %d\n",
+					value);
+	}
+
+	/* device either stalls (value < 0) or reports success */
+	return value;
+}
+
+static struct usb_configuration sourcesink_driver = {
+	.label		= "source/sink",
+	.strings	= sourcesink_strings,
+	.bind		= sourcesink_bind_config,
+	.setup		= sourcesink_setup,
+	.bConfigurationValue = 3,
+	.bmAttributes	= USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower	= 1,	/* 2 mA, minimal */
+	/* .iConfiguration = DYNAMIC */
+};
+
+/**
+ * sourcesink_add - add a source/sink testing configuration to a device
+ * @cdev: the device to support the configuration
+ */
+int __init sourcesink_add(struct usb_composite_dev *cdev)
+{
+	int id;
+
+	/* allocate string ID(s) */
+	id = usb_string_id(cdev);
+	if (id < 0)
+		return id;
+	strings_sourcesink[0].id = id;
+
+	source_sink_intf.iInterface = id;
+	sourcesink_driver.iConfiguration = id;
+
+	/* support autoresume for remote wakeup testing */
+	if (autoresume)
+		sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+
+	/* support OTG systems */
+	if (gadget_is_otg(cdev->gadget)) {
+		sourcesink_driver.descriptors = otg_desc;
+		sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+	}
+
+	return usb_add_config(cdev, &sourcesink_driver);
+}
diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c
new file mode 100644
index 0000000..afeab9a
--- /dev/null
+++ b/drivers/usb/gadget/f_subset.c
@@ -0,0 +1,423 @@
+/*
+ * f_subset.c -- "CDC Subset" Ethernet link function driver
+ *
+ * Copyright (C) 2003-2005,2008 David Brownell
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/etherdevice.h>
+
+#include "u_ether.h"
+
+
+/*
+ * This function packages a simple "CDC Subset" Ethernet port with no real
+ * control mechanisms; just raw data transfer over two bulk endpoints.
+ * The data transfer model is exactly that of CDC Ethernet, which is
+ * why we call it the "CDC Subset".
+ *
+ * Because it's not standardized, this has some interoperability issues.
+ * They mostly relate to driver binding, since the data transfer model is
+ * so simple (CDC Ethernet).  The original versions of this protocol used
+ * specific product/vendor IDs:  byteswapped IDs for Digital Equipment's
+ * SA-1100 "Itsy" board, which could run Linux 2.4 kernels and supported
+ * daughtercards with USB peripheral connectors.  (It was used more often
+ * with other boards, using the Itsy identifiers.)  Linux hosts recognized
+ * this with CONFIG_USB_ARMLINUX; these devices have only one configuration
+ * and one interface.
+ *
+ * At some point, MCCI defined a (nonconformant) CDC MDLM variant called
+ * "SAFE", which happens to have a mode which is identical to the "CDC
+ * Subset" in terms of data transfer and lack of control model.  This was
+ * adopted by later Sharp Zaurus models, and by some other software which
+ * Linux hosts recognize with CONFIG_USB_NET_ZAURUS.
+ *
+ * Because Microsoft's RNDIS drivers are far from robust, we added a few
+ * descriptors to the CDC Subset code, making this code look like a SAFE
+ * implementation.  This lets you use MCCI's host side MS-Windows drivers
+ * if you get fed up with RNDIS.  It also makes it easier for composite
+ * drivers to work, since they can use class based binding instead of
+ * caring about specific product and vendor IDs.
+ */
+
+struct geth_descs {
+	struct usb_endpoint_descriptor	*in;
+	struct usb_endpoint_descriptor	*out;
+};
+
+struct f_gether {
+	struct gether			port;
+
+	char				ethaddr[14];
+
+	struct usb_descriptor_header	**fs_function;
+	struct geth_descs		fs;
+	struct usb_descriptor_header	**hs_function;
+	struct geth_descs		hs;
+};
+
+static inline struct f_gether *func_to_geth(struct usb_function *f)
+{
+	return container_of(f, struct f_gether, port.func);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * "Simple" CDC-subset option is a simple vendor-neutral model that most
+ * full speed controllers can handle:  one interface, two bulk endpoints.
+ * To assist host side drivers, we fancy it up a bit, and add descriptors so
+ * some host side drivers will understand it as a "SAFE" variant.
+ *
+ * "SAFE" loosely follows CDC WMC MDLM, violating the spec in various ways.
+ * Data endpoints live in the control interface, there's no data interface.
+ * And it's not used to talk to a cell phone radio.
+ */
+
+/* interface descriptor: */
+
+static struct usb_interface_descriptor subset_data_intf __initdata = {
+	.bLength =		sizeof subset_data_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	/* .bInterfaceNumber = DYNAMIC */
+	.bAlternateSetting =	0,
+	.bNumEndpoints =	2,
+	.bInterfaceClass =      USB_CLASS_COMM,
+	.bInterfaceSubClass =	USB_CDC_SUBCLASS_MDLM,
+	.bInterfaceProtocol =	0,
+	/* .iInterface = DYNAMIC */
+};
+
+static struct usb_cdc_header_desc header_desc __initdata = {
+	.bLength =		sizeof header_desc,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
+
+	.bcdCDC =		__constant_cpu_to_le16(0x0110),
+};
+
+static struct usb_cdc_mdlm_desc mdlm_desc __initdata = {
+	.bLength =		sizeof mdlm_desc,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_MDLM_TYPE,
+
+	.bcdVersion =		__constant_cpu_to_le16(0x0100),
+	.bGUID = {
+		0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6,
+		0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f,
+	},
+};
+
+/* since "usb_cdc_mdlm_detail_desc" is a variable length structure, we
+ * can't really use its struct.  All we do here is say that we're using
+ * the submode of "SAFE" which directly matches the CDC Subset.
+ */
+static u8 mdlm_detail_desc[] __initdata = {
+	6,
+	USB_DT_CS_INTERFACE,
+	USB_CDC_MDLM_DETAIL_TYPE,
+
+	0,	/* "SAFE" */
+	0,	/* network control capabilities (none) */
+	0,	/* network data capabilities ("raw" encapsulation) */
+};
+
+static struct usb_cdc_ether_desc ether_desc __initdata = {
+	.bLength =		sizeof ether_desc,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_ETHERNET_TYPE,
+
+	/* this descriptor actually adds value, surprise! */
+	/* .iMACAddress = DYNAMIC */
+	.bmEthernetStatistics =	__constant_cpu_to_le32(0), /* no statistics */
+	.wMaxSegmentSize =	__constant_cpu_to_le16(ETH_FRAME_LEN),
+	.wNumberMCFilters =	__constant_cpu_to_le16(0),
+	.bNumberPowerFilters =	0,
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor fs_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor fs_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *fs_eth_function[] __initdata = {
+	(struct usb_descriptor_header *) &subset_data_intf,
+	(struct usb_descriptor_header *) &header_desc,
+	(struct usb_descriptor_header *) &mdlm_desc,
+	(struct usb_descriptor_header *) &mdlm_detail_desc,
+	(struct usb_descriptor_header *) &ether_desc,
+	(struct usb_descriptor_header *) &fs_in_desc,
+	(struct usb_descriptor_header *) &fs_out_desc,
+	NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor hs_in_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor hs_out_desc __initdata = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	__constant_cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *hs_eth_function[] __initdata = {
+	(struct usb_descriptor_header *) &subset_data_intf,
+	(struct usb_descriptor_header *) &header_desc,
+	(struct usb_descriptor_header *) &mdlm_desc,
+	(struct usb_descriptor_header *) &mdlm_detail_desc,
+	(struct usb_descriptor_header *) &ether_desc,
+	(struct usb_descriptor_header *) &hs_in_desc,
+	(struct usb_descriptor_header *) &hs_out_desc,
+	NULL,
+};
+
+/* string descriptors: */
+
+static struct usb_string geth_string_defs[] = {
+	[0].s = "CDC Ethernet Subset/SAFE",
+	[1].s = NULL /* DYNAMIC */,
+	{  } /* end of list */
+};
+
+static struct usb_gadget_strings geth_string_table = {
+	.language =		0x0409,	/* en-us */
+	.strings =		geth_string_defs,
+};
+
+static struct usb_gadget_strings *geth_strings[] = {
+	&geth_string_table,
+	NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int geth_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+	struct f_gether		*geth = func_to_geth(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+	struct net_device	*net;
+
+	/* we know alt == 0, so this is an activation or a reset */
+
+	if (geth->port.in_ep->driver_data) {
+		DBG(cdev, "reset cdc subset\n");
+		gether_disconnect(&geth->port);
+	}
+
+	DBG(cdev, "init + activate cdc subset\n");
+	geth->port.in = ep_choose(cdev->gadget,
+			geth->hs.in, geth->fs.in);
+	geth->port.out = ep_choose(cdev->gadget,
+			geth->hs.out, geth->fs.out);
+
+	net = gether_connect(&geth->port);
+	return IS_ERR(net) ? PTR_ERR(net) : 0;
+}
+
+static void geth_disable(struct usb_function *f)
+{
+	struct f_gether	*geth = func_to_geth(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+
+	DBG(cdev, "net deactivated\n");
+	gether_disconnect(&geth->port);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* serial function driver setup/binding */
+
+static int __init
+geth_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct usb_composite_dev *cdev = c->cdev;
+	struct f_gether		*geth = func_to_geth(f);
+	int			status;
+	struct usb_ep		*ep;
+
+	/* allocate instance-specific interface IDs */
+	status = usb_interface_id(c, f);
+	if (status < 0)
+		goto fail;
+	subset_data_intf.bInterfaceNumber = status;
+
+	status = -ENODEV;
+
+	/* allocate instance-specific endpoints */
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc);
+	if (!ep)
+		goto fail;
+	geth->port.in_ep = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc);
+	if (!ep)
+		goto fail;
+	geth->port.out_ep = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	/* copy descriptors, and track endpoint copies */
+	f->descriptors = usb_copy_descriptors(fs_eth_function);
+
+	geth->fs.in = usb_find_endpoint(fs_eth_function,
+			f->descriptors, &fs_in_desc);
+	geth->fs.out = usb_find_endpoint(fs_eth_function,
+			f->descriptors, &fs_out_desc);
+
+
+	/* support all relevant hardware speeds... we expect that when
+	 * hardware is dual speed, all bulk-capable endpoints work at
+	 * both speeds
+	 */
+	if (gadget_is_dualspeed(c->cdev->gadget)) {
+		hs_in_desc.bEndpointAddress =
+				fs_in_desc.bEndpointAddress;
+		hs_out_desc.bEndpointAddress =
+				fs_out_desc.bEndpointAddress;
+
+		/* copy descriptors, and track endpoint copies */
+		f->hs_descriptors = usb_copy_descriptors(hs_eth_function);
+
+		geth->hs.in = usb_find_endpoint(hs_eth_function,
+				f->hs_descriptors, &hs_in_desc);
+		geth->hs.out = usb_find_endpoint(hs_eth_function,
+				f->hs_descriptors, &hs_out_desc);
+	}
+
+	/* NOTE:  all that is done without knowing or caring about
+	 * the network link ... which is unavailable to this code
+	 * until we're activated via set_alt().
+	 */
+
+	DBG(cdev, "CDC Subset: %s speed IN/%s OUT/%s\n",
+			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+			geth->port.in_ep->name, geth->port.out_ep->name);
+	return 0;
+
+fail:
+	/* we might as well release our claims on endpoints */
+	if (geth->port.out)
+		geth->port.out_ep->driver_data = NULL;
+	if (geth->port.in)
+		geth->port.in_ep->driver_data = NULL;
+
+	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
+
+	return status;
+}
+
+static void
+geth_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	if (gadget_is_dualspeed(c->cdev->gadget))
+		usb_free_descriptors(f->hs_descriptors);
+	usb_free_descriptors(f->descriptors);
+	geth_string_defs[1].s = NULL;
+	kfree(func_to_geth(f));
+}
+
+/**
+ * geth_bind_config - add CDC Subset network link to a configuration
+ * @c: the configuration to support the network link
+ * @ethaddr: a buffer in which the ethernet address of the host side
+ *	side of the link was recorded
+ * Context: single threaded during gadget setup
+ *
+ * Returns zero on success, else negative errno.
+ *
+ * Caller must have called @gether_setup().  Caller is also responsible
+ * for calling @gether_cleanup() before module unload.
+ */
+int __init geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+{
+	struct f_gether	*geth;
+	int		status;
+
+	if (!ethaddr)
+		return -EINVAL;
+
+	/* maybe allocate device-global string IDs */
+	if (geth_string_defs[0].id == 0) {
+
+		/* interface label */
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		geth_string_defs[0].id = status;
+		subset_data_intf.iInterface = status;
+
+		/* MAC address */
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		geth_string_defs[1].id = status;
+		ether_desc.iMACAddress = status;
+	}
+
+	/* allocate and initialize one new instance */
+	geth = kzalloc(sizeof *geth, GFP_KERNEL);
+	if (!geth)
+		return -ENOMEM;
+
+	/* export host's Ethernet address in CDC format */
+	snprintf(geth->ethaddr, sizeof geth->ethaddr,
+		"%02X%02X%02X%02X%02X%02X",
+		ethaddr[0], ethaddr[1], ethaddr[2],
+		ethaddr[3], ethaddr[4], ethaddr[5]);
+	geth_string_defs[1].s = geth->ethaddr;
+
+	geth->port.cdc_filter = DEFAULT_FILTER;
+
+	geth->port.func.name = "cdc_subset";
+	geth->port.func.strings = geth_strings;
+	geth->port.func.bind = geth_bind;
+	geth->port.func.unbind = geth_unbind;
+	geth->port.func.set_alt = geth_set_alt;
+	geth->port.func.disable = geth_disable;
+
+	status = usb_add_function(c, &geth->port.func);
+	if (status) {
+		geth_string_defs[1].s = NULL;
+		kfree(geth);
+	}
+	return status;
+}
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 47bb9f0..15c24ed 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -3867,8 +3867,8 @@
 		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);
+		dev_set_name(&curlun->dev,"%s-lun%d",
+			     dev_name(&gadget->dev), i);
 
 		if ((rc = device_register(&curlun->dev)) != 0) {
 			INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c
index 1868754..1695382 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.c
+++ b/drivers/usb/gadget/fsl_usb2_udc.c
@@ -2331,7 +2331,7 @@
 	udc_controller->gadget.name = driver_name;
 
 	/* Setup gadget.dev and register with kernel */
-	strcpy(udc_controller->gadget.dev.bus_id, "gadget");
+	dev_set_name(&udc_controller->gadget.dev, "gadget");
 	udc_controller->gadget.dev.release = fsl_udc_release;
 	udc_controller->gadget.dev.parent = &pdev->dev;
 	ret = device_register(&udc_controller->gadget.dev);
diff --git a/drivers/usb/gadget/g_zero.h b/drivers/usb/gadget/g_zero.h
new file mode 100644
index 0000000..dd2f16a
--- /dev/null
+++ b/drivers/usb/gadget/g_zero.h
@@ -0,0 +1,25 @@
+/*
+ * This header declares the utility functions used by "Gadget Zero", plus
+ * interfaces to its two single-configuration function drivers.
+ */
+
+#ifndef __G_ZERO_H
+#define __G_ZERO_H
+
+#include <linux/usb/composite.h>
+
+/* global state */
+extern unsigned buflen;
+extern const struct usb_descriptor_header *otg_desc[];
+
+/* common utilities */
+struct usb_request *alloc_ep_req(struct usb_ep *ep);
+void free_ep_req(struct usb_ep *ep, struct usb_request *req);
+void disable_endpoints(struct usb_composite_dev *cdev,
+		struct usb_ep *in, struct usb_ep *out);
+
+/* configuration-specific linkup */
+int sourcesink_add(struct usb_composite_dev *cdev);
+int loopback_add(struct usb_composite_dev *cdev);
+
+#endif /* __G_ZERO_H */
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index ca5149e..5246e8f 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -214,3 +214,26 @@
 		return 0x21;
 	return -ENOENT;
 }
+
+
+/**
+ * gadget_supports_altsettings - return true if altsettings work
+ * @gadget: the gadget in question
+ */
+static inline bool gadget_supports_altsettings(struct usb_gadget *gadget)
+{
+	/* PXA 21x/25x/26x has no altsettings at all */
+	if (gadget_is_pxa(gadget))
+		return false;
+
+	/* PXA 27x and 3xx have *broken* altsetting support */
+	if (gadget_is_pxa27x(gadget))
+		return false;
+
+	/* SH3 hardware just doesn't do altsettings */
+	if (gadget_is_sh(gadget))
+		return false;
+
+	/* Everything else is *presumably* fine ... */
+	return true;
+}
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index be6613a..48f1c63 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -1790,7 +1790,7 @@
 	dev->gadget.ops = &goku_ops;
 
 	/* the "gadget" abstracts/virtualizes the controller */
-	strcpy(dev->gadget.dev.bus_id, "gadget");
+	dev_set_name(&dev->gadget.dev, "gadget");
 	dev->gadget.dev.parent = &pdev->dev;
 	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
 	dev->gadget.dev.release = gadget_release;
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index f132a92..04692d5 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -32,6 +32,7 @@
 #include <asm/uaccess.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
+#include <linux/smp_lock.h>
 
 #include <linux/device.h>
 #include <linux/moduleparam.h>
@@ -483,8 +484,7 @@
 	return 0;
 }
 
-static int ep_ioctl (struct inode *inode, struct file *fd,
-		unsigned code, unsigned long value)
+static long ep_ioctl(struct file *fd, unsigned code, unsigned long value)
 {
 	struct ep_data		*data = fd->private_data;
 	int			status;
@@ -740,7 +740,7 @@
 
 	.read =		ep_read,
 	.write =	ep_write,
-	.ioctl =	ep_ioctl,
+	.unlocked_ioctl = ep_ioctl,
 	.release =	ep_release,
 
 	.aio_read =	ep_aio_read,
@@ -1294,15 +1294,18 @@
        return mask;
 }
 
-static int dev_ioctl (struct inode *inode, struct file *fd,
-		unsigned code, unsigned long value)
+static long dev_ioctl (struct file *fd, unsigned code, unsigned long value)
 {
 	struct dev_data		*dev = fd->private_data;
 	struct usb_gadget	*gadget = dev->gadget;
+	long ret = -ENOTTY;
 
-	if (gadget->ops->ioctl)
-		return gadget->ops->ioctl (gadget, code, value);
-	return -ENOTTY;
+	if (gadget->ops->ioctl) {
+		lock_kernel();
+		ret = gadget->ops->ioctl (gadget, code, value);
+		unlock_kernel();
+	}
+	return ret;
 }
 
 /* used after device configuration */
@@ -1314,7 +1317,7 @@
 	.write =	ep0_write,
 	.fasync =	ep0_fasync,
 	.poll =		ep0_poll,
-	.ioctl =	dev_ioctl,
+	.unlocked_ioctl =	dev_ioctl,
 	.release =	dev_release,
 };
 
@@ -1964,7 +1967,7 @@
 	.open =		dev_open,
 	.write =	dev_config,
 	.fasync =	ep0_fasync,
-	.ioctl =	dev_ioctl,
+	.unlocked_ioctl = dev_ioctl,
 	.release =	dev_release,
 };
 
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index 825abd2..c6e7df0 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/drivers/usb/gadget/lh7a40x_udc.c
@@ -1970,7 +1970,7 @@
 
 static void nop_release(struct device *dev)
 {
-	DEBUG("%s %s\n", __func__, dev->bus_id);
+	DEBUG("%s %s\n", __func__, dev_name(dev));
 }
 
 static struct lh7a40x_udc memory = {
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c
index ee6b35f..8da7535 100644
--- a/drivers/usb/gadget/m66592-udc.c
+++ b/drivers/usb/gadget/m66592-udc.c
@@ -1593,7 +1593,7 @@
 
 	m66592->gadget.ops = &m66592_gadget_ops;
 	device_initialize(&m66592->gadget.dev);
-	strcpy(m66592->gadget.dev.bus_id, "gadget");
+	dev_set_name(&m66592->gadget, "gadget");
 	m66592->gadget.is_dualspeed = 1;
 	m66592->gadget.dev.parent = &pdev->dev;
 	m66592->gadget.dev.dma_mask = pdev->dev.dma_mask;
diff --git a/drivers/usb/gadget/ndis.h b/drivers/usb/gadget/ndis.h
index 09e3ee4..df886ce 100644
--- a/drivers/usb/gadget/ndis.h
+++ b/drivers/usb/gadget/ndis.h
@@ -1,11 +1,11 @@
 /*
- * ndis.h 
- * 
+ * ndis.h
+ *
  * ntddndis.h modified by Benedikt Spranger <b.spranger@pengutronix.de>
- * 
- * Thanks to the cygwin development team, 
+ *
+ * Thanks to the cygwin development team,
  * espacially to Casper S. Hornstrup <chorns@users.sourceforge.net>
- * 
+ *
  * THIS SOFTWARE IS NOT COPYRIGHTED
  *
  * This source code is offered for use in the public domain. You may
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index e018623..b67ab67 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -2768,7 +2768,7 @@
 	dev->gadget.is_dualspeed = 1;
 
 	/* the "gadget" abstracts/virtualizes the controller */
-	strcpy (dev->gadget.dev.bus_id, "gadget");
+	dev_set_name(&dev->gadget.dev, "gadget");
 	dev->gadget.dev.parent = &pdev->dev;
 	dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
 	dev->gadget.dev.release = gadget_release;
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 03a7f49..4b79a85 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -2686,7 +2686,7 @@
 	udc->gadget.name = driver_name;
 
 	device_initialize(&udc->gadget.dev);
-	strcpy (udc->gadget.dev.bus_id, "gadget");
+	dev_set_name(&udc->gadget.dev, "gadget");
 	udc->gadget.dev.release = omap_udc_release;
 	udc->gadget.dev.parent = &odev->dev;
 	if (use_dma)
diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index ec8f2eb..49cd9e1 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -828,9 +828,8 @@
 	return status;
 }
 
-static int
-printer_ioctl(struct inode *inode, struct file *fd, unsigned int code,
-		unsigned long arg)
+static long
+printer_ioctl(struct file *fd, unsigned int code, unsigned long arg)
 {
 	struct printer_dev	*dev = fd->private_data;
 	unsigned long		flags;
@@ -869,7 +868,7 @@
 	.write =	printer_write,
 	.fsync =	printer_fsync,
 	.poll =		printer_poll,
-	.ioctl =	printer_ioctl,
+	.unlocked_ioctl = printer_ioctl,
 	.release =	printer_close
 };
 
@@ -1361,8 +1360,8 @@
 
 
 	/* Setup the sysfs files for the printer gadget. */
-	dev->pdev = device_create(usb_gadget_class, NULL, g_printer_devno,
-			"g_printer");
+	dev->pdev = device_create_drvdata(usb_gadget_class, NULL,
+					  g_printer_devno, NULL, "g_printer");
 	if (IS_ERR(dev->pdev)) {
 		ERROR(dev, "Failed to create device: g_printer\n");
 		goto fail;
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index 031dceb..8fb0066 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -152,9 +152,10 @@
 static void pullup_off(void)
 {
 	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
+	int off_level = mach->gpio_pullup_inverted;
 
 	if (mach->gpio_pullup)
-		gpio_set_value(mach->gpio_pullup, 0);
+		gpio_set_value(mach->gpio_pullup, off_level);
 	else if (mach->udc_command)
 		mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
 }
@@ -162,9 +163,10 @@
 static void pullup_on(void)
 {
 	struct pxa2xx_udc_mach_info		*mach = the_controller->mach;
+	int on_level = !mach->gpio_pullup_inverted;
 
 	if (mach->gpio_pullup)
-		gpio_set_value(mach->gpio_pullup, 1);
+		gpio_set_value(mach->gpio_pullup, on_level);
 	else if (mach->udc_command)
 		mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
 }
@@ -1818,7 +1820,7 @@
 
 static void nop_release (struct device *dev)
 {
-	DMSG("%s %s\n", __func__, dev->bus_id);
+	DMSG("%s %s\n", __func__, dev_name(dev));
 }
 
 /* this uses load-time allocation and initialization (instead of
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c
index 9c0e82e..9d447d8 100644
--- a/drivers/usb/gadget/pxa27x_udc.c
+++ b/drivers/usb/gadget/pxa27x_udc.c
@@ -1575,7 +1575,6 @@
 {
 	udc_writel(udc, UDCICR0, 0);
 	udc_writel(udc, UDCICR1, 0);
-	udc_writel(udc, UP2OCR, UP2OCR_HXOE);
 	udc_clear_mask_UDCCR(udc, UDCCR_UDE);
 
 	clk_enable(udc->clk);
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index d0677f5..7228e85 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -1,8 +1,6 @@
 /*
  * RNDIS MSG parser
  *
- * Version:     $Id: rndis.c,v 1.19 2004/03/25 21:33:46 robert Exp $
- *
  * Authors:	Benedikt Spranger, Pengutronix
  *		Robert Schwebel, Pengutronix
  *
@@ -30,6 +28,7 @@
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/netdevice.h>
 
 #include <asm/io.h>
@@ -38,9 +37,7 @@
 #include <asm/unaligned.h>
 
 
-#undef	RNDIS_PM
-#undef	RNDIS_WAKEUP
-#undef	VERBOSE
+#undef	VERBOSE_DEBUG
 
 #include "rndis.h"
 
@@ -96,9 +93,6 @@
 	OID_GEN_MAXIMUM_TOTAL_SIZE,
 	OID_GEN_MEDIA_CONNECT_STATUS,
 	OID_GEN_PHYSICAL_MEDIUM,
-#if 0
-	OID_GEN_RNDIS_CONFIG_PARAMETER,
-#endif
 
 	/* the statistical stuff */
 	OID_GEN_XMIT_OK,
@@ -146,7 +140,14 @@
 #endif	/* RNDIS_OPTIONAL_STATS */
 
 #ifdef	RNDIS_PM
-	/* PM and wakeup are mandatory for USB: */
+	/* PM and wakeup are "mandatory" for USB, but the RNDIS specs
+	 * don't say what they mean ... and the NDIS specs are often
+	 * confusing and/or ambiguous in this context.  (That is, more
+	 * so than their specs for the other OIDs.)
+	 *
+	 * FIXME someone who knows what these should do, please
+	 * implement them!
+	 */
 
 	/* power management */
 	OID_PNP_CAPABILITIES,
@@ -173,6 +174,8 @@
 	__le32			*outbuf;
 	int			i, count;
 	rndis_query_cmplt_type	*resp;
+	struct net_device	*net;
+	struct net_device_stats	*stats;
 
 	if (!r) return -ENOMEM;
 	resp = (rndis_query_cmplt_type *) r->buf;
@@ -194,6 +197,12 @@
 	outbuf = (__le32 *) &resp[1];
 	resp->InformationBufferOffset = __constant_cpu_to_le32 (16);
 
+	net = rndis_per_dev_params[configNr].dev;
+	if (net->get_stats)
+		stats = net->get_stats(net);
+	else
+		stats = NULL;
+
 	switch (OID) {
 
 	/* general oids (table 4-1) */
@@ -350,11 +359,9 @@
 	case OID_GEN_XMIT_OK:
 		if (rndis_debug > 1)
 			DBG("%s: OID_GEN_XMIT_OK\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (
-			    rndis_per_dev_params [configNr].stats->tx_packets -
-			    rndis_per_dev_params [configNr].stats->tx_errors -
-			    rndis_per_dev_params [configNr].stats->tx_dropped);
+		if (stats) {
+			*outbuf = cpu_to_le32(stats->tx_packets
+				- stats->tx_errors - stats->tx_dropped);
 			retval = 0;
 		}
 		break;
@@ -363,11 +370,9 @@
 	case OID_GEN_RCV_OK:
 		if (rndis_debug > 1)
 			DBG("%s: OID_GEN_RCV_OK\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (
-			    rndis_per_dev_params [configNr].stats->rx_packets -
-			    rndis_per_dev_params [configNr].stats->rx_errors -
-			    rndis_per_dev_params [configNr].stats->rx_dropped);
+		if (stats) {
+			*outbuf = cpu_to_le32(stats->rx_packets
+				- stats->rx_errors - stats->rx_dropped);
 			retval = 0;
 		}
 		break;
@@ -376,9 +381,8 @@
 	case OID_GEN_XMIT_ERROR:
 		if (rndis_debug > 1)
 			DBG("%s: OID_GEN_XMIT_ERROR\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->tx_errors);
+		if (stats) {
+			*outbuf = cpu_to_le32(stats->tx_errors);
 			retval = 0;
 		}
 		break;
@@ -387,9 +391,8 @@
 	case OID_GEN_RCV_ERROR:
 		if (rndis_debug > 1)
 			DBG("%s: OID_GEN_RCV_ERROR\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->rx_errors);
+		if (stats) {
+			*outbuf = cpu_to_le32(stats->rx_errors);
 			retval = 0;
 		}
 		break;
@@ -397,150 +400,12 @@
 	/* mandatory */
 	case OID_GEN_RCV_NO_BUFFER:
 		DBG("%s: OID_GEN_RCV_NO_BUFFER\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->rx_dropped);
+		if (stats) {
+			*outbuf = cpu_to_le32(stats->rx_dropped);
 			retval = 0;
 		}
 		break;
 
-#ifdef	RNDIS_OPTIONAL_STATS
-	case OID_GEN_DIRECTED_BYTES_XMIT:
-		DBG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __func__);
-		/*
-		 * Aunt Tilly's size of shoes
-		 * minus antarctica count of penguins
-		 * divided by weight of Alpha Centauri
-		 */
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (
-				(rndis_per_dev_params [configNr]
-					.stats->tx_packets -
-				 rndis_per_dev_params [configNr]
-					 .stats->tx_errors -
-				 rndis_per_dev_params [configNr]
-					 .stats->tx_dropped)
-				* 123);
-			retval = 0;
-		}
-		break;
-
-	case OID_GEN_DIRECTED_FRAMES_XMIT:
-		DBG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __func__);
-		/* dito */
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (
-				(rndis_per_dev_params [configNr]
-					.stats->tx_packets -
-				 rndis_per_dev_params [configNr]
-					 .stats->tx_errors -
-				 rndis_per_dev_params [configNr]
-					 .stats->tx_dropped)
-				/ 123);
-			retval = 0;
-		}
-		break;
-
-	case OID_GEN_MULTICAST_BYTES_XMIT:
-		DBG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->multicast*1234);
-			retval = 0;
-		}
-		break;
-
-	case OID_GEN_MULTICAST_FRAMES_XMIT:
-		DBG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->multicast);
-			retval = 0;
-		}
-		break;
-
-	case OID_GEN_BROADCAST_BYTES_XMIT:
-		DBG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->tx_packets/42*255);
-			retval = 0;
-		}
-		break;
-
-	case OID_GEN_BROADCAST_FRAMES_XMIT:
-		DBG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->tx_packets/42);
-			retval = 0;
-		}
-		break;
-
-	case OID_GEN_DIRECTED_BYTES_RCV:
-		DBG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __func__);
-		*outbuf = __constant_cpu_to_le32 (0);
-		retval = 0;
-		break;
-
-	case OID_GEN_DIRECTED_FRAMES_RCV:
-		DBG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __func__);
-		*outbuf = __constant_cpu_to_le32 (0);
-		retval = 0;
-		break;
-
-	case OID_GEN_MULTICAST_BYTES_RCV:
-		DBG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->multicast * 1111);
-			retval = 0;
-		}
-		break;
-
-	case OID_GEN_MULTICAST_FRAMES_RCV:
-		DBG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->multicast);
-			retval = 0;
-		}
-		break;
-
-	case OID_GEN_BROADCAST_BYTES_RCV:
-		DBG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->rx_packets/42*255);
-			retval = 0;
-		}
-		break;
-
-	case OID_GEN_BROADCAST_FRAMES_RCV:
-		DBG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->rx_packets/42);
-			retval = 0;
-		}
-		break;
-
-	case OID_GEN_RCV_CRC_ERROR:
-		DBG("%s: OID_GEN_RCV_CRC_ERROR\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->rx_crc_errors);
-			retval = 0;
-		}
-		break;
-
-	case OID_GEN_TRANSMIT_QUEUE_LENGTH:
-		DBG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __func__);
-		*outbuf = __constant_cpu_to_le32 (0);
-		retval = 0;
-		break;
-#endif	/* RNDIS_OPTIONAL_STATS */
-
 	/* ieee802.3 OIDs (table 4-3) */
 
 	/* mandatory */
@@ -592,9 +457,8 @@
 	/* mandatory */
 	case OID_802_3_RCV_ERROR_ALIGNMENT:
 		DBG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __func__);
-		if (rndis_per_dev_params [configNr].stats) {
-			*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
-					.stats->rx_frame_errors);
+		if (stats) {
+			*outbuf = cpu_to_le32(stats->rx_frame_errors);
 			retval = 0;
 		}
 		break;
@@ -613,64 +477,6 @@
 		retval = 0;
 		break;
 
-#ifdef	RNDIS_OPTIONAL_STATS
-	case OID_802_3_XMIT_DEFERRED:
-		DBG("%s: OID_802_3_XMIT_DEFERRED\n", __func__);
-		/* TODO */
-		break;
-
-	case OID_802_3_XMIT_MAX_COLLISIONS:
-		DBG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __func__);
-		/* TODO */
-		break;
-
-	case OID_802_3_RCV_OVERRUN:
-		DBG("%s: OID_802_3_RCV_OVERRUN\n", __func__);
-		/* TODO */
-		break;
-
-	case OID_802_3_XMIT_UNDERRUN:
-		DBG("%s: OID_802_3_XMIT_UNDERRUN\n", __func__);
-		/* TODO */
-		break;
-
-	case OID_802_3_XMIT_HEARTBEAT_FAILURE:
-		DBG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __func__);
-		/* TODO */
-		break;
-
-	case OID_802_3_XMIT_TIMES_CRS_LOST:
-		DBG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __func__);
-		/* TODO */
-		break;
-
-	case OID_802_3_XMIT_LATE_COLLISIONS:
-		DBG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __func__);
-		/* TODO */
-		break;
-#endif	/* RNDIS_OPTIONAL_STATS */
-
-#ifdef	RNDIS_PM
-	/* power management OIDs (table 4-5) */
-	case OID_PNP_CAPABILITIES:
-		DBG("%s: OID_PNP_CAPABILITIES\n", __func__);
-
-		/* for now, no wakeup capabilities */
-		length = sizeof (struct NDIS_PNP_CAPABILITIES);
-		memset(outbuf, 0, length);
-		retval = 0;
-		break;
-	case OID_PNP_QUERY_POWER:
-		DBG("%s: OID_PNP_QUERY_POWER D%d\n", __func__,
-				get_unaligned_le32(buf) - 1);
-		/* only suspend is a real power state, and
-		 * it can't be entered by OID_PNP_SET_POWER...
-		 */
-		length = 0;
-		retval = 0;
-		break;
-#endif
-
 	default:
 		pr_warning("%s: query unknown OID 0x%08X\n",
 			 __func__, OID);
@@ -726,9 +532,6 @@
 		 * what makes the packet flow start and stop, like
 		 * activating the CDC Ethernet altsetting.
 		 */
-#ifdef	RNDIS_PM
-update_linkstate:
-#endif
 		retval = 0;
 		if (*params->filter) {
 			params->state = RNDIS_DATA_INITIALIZED;
@@ -747,49 +550,6 @@
 		DBG("%s: OID_802_3_MULTICAST_LIST\n", __func__);
 		retval = 0;
 		break;
-#if 0
-	case OID_GEN_RNDIS_CONFIG_PARAMETER:
-		{
-		struct rndis_config_parameter	*param;
-		param = (struct rndis_config_parameter *) buf;
-		DBG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n",
-			__func__,
-			min(cpu_to_le32(param->ParameterNameLength),80),
-			buf + param->ParameterNameOffset);
-		retval = 0;
-		}
-		break;
-#endif
-
-#ifdef	RNDIS_PM
-	case OID_PNP_SET_POWER:
-		/* The only real power state is USB suspend, and RNDIS requests
-		 * can't enter it; this one isn't really about power.  After
-		 * resuming, Windows forces a reset, and then SET_POWER D0.
-		 * FIXME ... then things go batty; Windows wedges itself.
-		 */
-		i = get_unaligned_le32(buf);
-		DBG("%s: OID_PNP_SET_POWER D%d\n", __func__, i - 1);
-		switch (i) {
-		case NdisDeviceStateD0:
-			*params->filter = params->saved_filter;
-			goto update_linkstate;
-		case NdisDeviceStateD3:
-		case NdisDeviceStateD2:
-		case NdisDeviceStateD1:
-			params->saved_filter = *params->filter;
-			retval = 0;
-			break;
-		}
-		break;
-
-#ifdef	RNDIS_WAKEUP
-	// no wakeup support advertised, so wakeup OIDs always fail:
-	//  - OID_PNP_ENABLE_WAKE_UP
-	//  - OID_PNP_{ADD,REMOVE}_WAKE_UP_PATTERN
-#endif
-
-#endif	/* RNDIS_PM */
 
 	default:
 		pr_warning("%s: set unknown OID 0x%08X, size %d\n",
@@ -807,8 +567,10 @@
 {
 	rndis_init_cmplt_type	*resp;
 	rndis_resp_t            *r;
+	struct rndis_params	*params = rndis_per_dev_params + configNr;
 
-	if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
+	if (!params->dev)
+		return -ENOTSUPP;
 
 	r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type));
 	if (!r)
@@ -826,7 +588,7 @@
 	resp->Medium = __constant_cpu_to_le32 (RNDIS_MEDIUM_802_3);
 	resp->MaxPacketsPerTransfer = __constant_cpu_to_le32 (1);
 	resp->MaxTransferSize = cpu_to_le32 (
-		  rndis_per_dev_params [configNr].dev->mtu
+		  params->dev->mtu
 		+ sizeof (struct ethhdr)
 		+ sizeof (struct rndis_packet_msg_type)
 		+ 22);
@@ -834,10 +596,7 @@
 	resp->AFListOffset = __constant_cpu_to_le32 (0);
 	resp->AFListSize = __constant_cpu_to_le32 (0);
 
-	if (rndis_per_dev_params [configNr].ack)
-		rndis_per_dev_params [configNr].ack (
-			rndis_per_dev_params [configNr].dev);
-
+	params->resp_avail(params->v);
 	return 0;
 }
 
@@ -845,9 +604,11 @@
 {
 	rndis_query_cmplt_type *resp;
 	rndis_resp_t            *r;
+	struct rndis_params	*params = rndis_per_dev_params + configNr;
 
 	// DBG("%s: OID = %08X\n", __func__, cpu_to_le32(buf->OID));
-	if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
+	if (!params->dev)
+		return -ENOTSUPP;
 
 	/*
 	 * we need more memory:
@@ -878,9 +639,7 @@
 	} else
 		resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
 
-	if (rndis_per_dev_params [configNr].ack)
-		rndis_per_dev_params [configNr].ack (
-			rndis_per_dev_params [configNr].dev);
+	params->resp_avail(params->v);
 	return 0;
 }
 
@@ -889,6 +648,7 @@
 	u32			BufLength, BufOffset;
 	rndis_set_cmplt_type	*resp;
 	rndis_resp_t		*r;
+	struct rndis_params	*params = rndis_per_dev_params + configNr;
 
 	r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type));
 	if (!r)
@@ -898,7 +658,7 @@
 	BufLength = le32_to_cpu (buf->InformationBufferLength);
 	BufOffset = le32_to_cpu (buf->InformationBufferOffset);
 
-#ifdef	VERBOSE
+#ifdef	VERBOSE_DEBUG
 	DBG("%s: Length: %d\n", __func__, BufLength);
 	DBG("%s: Offset: %d\n", __func__, BufOffset);
 	DBG("%s: InfoBuffer: ", __func__);
@@ -919,10 +679,7 @@
 	else
 		resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
 
-	if (rndis_per_dev_params [configNr].ack)
-		rndis_per_dev_params [configNr].ack (
-			rndis_per_dev_params [configNr].dev);
-
+	params->resp_avail(params->v);
 	return 0;
 }
 
@@ -930,6 +687,7 @@
 {
 	rndis_reset_cmplt_type	*resp;
 	rndis_resp_t		*r;
+	struct rndis_params	*params = rndis_per_dev_params + configNr;
 
 	r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type));
 	if (!r)
@@ -942,10 +700,7 @@
 	/* resent information */
 	resp->AddressingReset = __constant_cpu_to_le32 (1);
 
-	if (rndis_per_dev_params [configNr].ack)
-		rndis_per_dev_params [configNr].ack (
-			rndis_per_dev_params [configNr].dev);
-
+	params->resp_avail(params->v);
 	return 0;
 }
 
@@ -954,6 +709,7 @@
 {
 	rndis_keepalive_cmplt_type	*resp;
 	rndis_resp_t			*r;
+	struct rndis_params	*params = rndis_per_dev_params + configNr;
 
 	/* host "should" check only in RNDIS_DATA_INITIALIZED state */
 
@@ -968,10 +724,7 @@
 	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
 	resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
 
-	if (rndis_per_dev_params [configNr].ack)
-		rndis_per_dev_params [configNr].ack (
-			rndis_per_dev_params [configNr].dev);
-
+	params->resp_avail(params->v);
 	return 0;
 }
 
@@ -983,8 +736,9 @@
 {
 	rndis_indicate_status_msg_type	*resp;
 	rndis_resp_t			*r;
+	struct rndis_params	*params = rndis_per_dev_params + configNr;
 
-	if (rndis_per_dev_params [configNr].state == RNDIS_UNINITIALIZED)
+	if (params->state == RNDIS_UNINITIALIZED)
 		return -ENOTSUPP;
 
 	r = rndis_add_response (configNr,
@@ -1000,9 +754,7 @@
 	resp->StatusBufferLength = __constant_cpu_to_le32 (0);
 	resp->StatusBufferOffset = __constant_cpu_to_le32 (0);
 
-	if (rndis_per_dev_params [configNr].ack)
-		rndis_per_dev_params [configNr].ack (
-			rndis_per_dev_params [configNr].dev);
+	params->resp_avail(params->v);
 	return 0;
 }
 
@@ -1029,7 +781,6 @@
 
 	if (configNr >= RNDIS_MAX_CONFIGS)
 		return;
-	rndis_per_dev_params [configNr].used = 0;
 	rndis_per_dev_params [configNr].state = RNDIS_UNINITIALIZED;
 
 	/* drain the response queue */
@@ -1142,21 +893,25 @@
 	return -ENOTSUPP;
 }
 
-int rndis_register (int (* rndis_control_ack) (struct net_device *))
+int rndis_register(void (*resp_avail)(void *v), void *v)
 {
 	u8 i;
 
+	if (!resp_avail)
+		return -EINVAL;
+
 	for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
 		if (!rndis_per_dev_params [i].used) {
 			rndis_per_dev_params [i].used = 1;
-			rndis_per_dev_params [i].ack = rndis_control_ack;
+			rndis_per_dev_params [i].resp_avail = resp_avail;
+			rndis_per_dev_params [i].v = v;
 			DBG("%s: configNr = %d\n", __func__, i);
 			return i;
 		}
 	}
 	DBG("failed\n");
 
-	return -1;
+	return -ENODEV;
 }
 
 void rndis_deregister (int configNr)
@@ -1169,16 +924,14 @@
 	return;
 }
 
-int rndis_set_param_dev (u8 configNr, struct net_device *dev,
-			 struct net_device_stats *stats,
-			 u16 *cdc_filter)
+int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter)
 {
 	DBG("%s:\n", __func__ );
-	if (!dev || !stats) return -1;
+	if (!dev)
+		return -EINVAL;
 	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
 
 	rndis_per_dev_params [configNr].dev = dev;
-	rndis_per_dev_params [configNr].stats = stats;
 	rndis_per_dev_params [configNr].filter = cdc_filter;
 
 	return 0;
@@ -1296,14 +1049,11 @@
 
 #ifdef	CONFIG_USB_GADGET_DEBUG_FILES
 
-static int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof,
-		void *data)
+static int rndis_proc_show(struct seq_file *m, void *v)
 {
-	char *out = page;
-	int len;
-	rndis_params *param = (rndis_params *) data;
+	rndis_params *param = m->private;
 
-	out += snprintf (out, count,
+	seq_printf(m,
 			 "Config Nr. %d\n"
 			 "used      : %s\n"
 			 "state     : %s\n"
@@ -1326,25 +1076,13 @@
 			 (param->media_state) ? 0 : param->speed*100,
 			 (param->media_state) ? "disconnected" : "connected",
 			 param->vendorID, param->vendorDescr);
-
-	len = out - page;
-	len -= off;
-
-	if (len < count) {
-		*eof = 1;
-		if (len <= 0)
-			return 0;
-	} else
-		len = count;
-
-	*start = page + off;
-	return len;
+	return 0;
 }
 
-static int rndis_proc_write (struct file *file, const char __user *buffer,
-		unsigned long count, void *data)
+static ssize_t rndis_proc_write(struct file *file, const char __user *buffer,
+		size_t count, loff_t *ppos)
 {
-	rndis_params *p = data;
+	rndis_params *p = PDE(file->f_path.dentry->d_inode)->data;
 	u32 speed = 0;
 	int i, fl_speed = 0;
 
@@ -1386,6 +1124,20 @@
 	return count;
 }
 
+static int rndis_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, rndis_proc_show, PDE(inode)->data);
+}
+
+static const struct file_operations rndis_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= rndis_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= rndis_proc_write,
+};
+
 #define	NAME_TEMPLATE	"driver/rndis-%03d"
 
 static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
@@ -1403,7 +1155,9 @@
 
 		sprintf (name, NAME_TEMPLATE, i);
 		if (!(rndis_connect_state [i]
-				= create_proc_entry (name, 0660, NULL)))
+				= proc_create_data(name, 0660, NULL,
+					&rndis_proc_fops,
+					(void *)(rndis_per_dev_params + i))))
 		{
 			DBG("%s :remove entries", __func__);
 			while (i) {
@@ -1413,11 +1167,6 @@
 			DBG("\n");
 			return -EIO;
 		}
-
-		rndis_connect_state [i]->write_proc = rndis_proc_write;
-		rndis_connect_state [i]->read_proc = rndis_proc_read;
-		rndis_connect_state [i]->data = (void *)
-				(rndis_per_dev_params + i);
 #endif
 		rndis_per_dev_params [i].confignr = i;
 		rndis_per_dev_params [i].used = 0;
diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h
index 397b149..aac61df 100644
--- a/drivers/usb/gadget/rndis.h
+++ b/drivers/usb/gadget/rndis.h
@@ -1,8 +1,6 @@
 /*
  * RNDIS	Definitions for Remote NDIS
  *
- * Version:	$Id: rndis.h,v 1.15 2004/03/25 21:33:46 robert Exp $
- *
  * Authors:	Benedikt Spranger, Pengutronix
  *		Robert Schwebel, Pengutronix
  *
@@ -235,20 +233,19 @@
 	const u8		*host_mac;
 	u16			*filter;
 	struct net_device	*dev;
-	struct net_device_stats *stats;
 
 	u32			vendorID;
 	const char		*vendorDescr;
-	int			(*ack) (struct net_device *);
+	void			(*resp_avail)(void *v);
+	void			*v;
 	struct list_head	resp_queue;
 } rndis_params;
 
 /* RNDIS Message parser and other useless functions */
 int  rndis_msg_parser (u8 configNr, u8 *buf);
-int  rndis_register (int (*rndis_control_ack) (struct net_device *));
+int  rndis_register(void (*resp_avail)(void *v), void *v);
 void rndis_deregister (int configNr);
 int  rndis_set_param_dev (u8 configNr, struct net_device *dev,
-			 struct net_device_stats *stats,
 			 u16 *cdc_filter);
 int  rndis_set_param_vendor (u8 configNr, u32 vendorID,
 			    const char *vendorDescr);
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index fa019fa..b3699af 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -1,15 +1,9 @@
 /*
- * g_serial.c -- USB gadget serial driver
+ * serial.c -- USB gadget serial driver
  *
- * Copyright 2003 (C) Al Borchers (alborchers@steinerpoint.com)
- *
- * This code is based in part on the Gadget Zero driver, which
- * is Copyright (C) 2003 by David Brownell, all rights reserved.
- *
- * This code also borrows from usbserial.c, which is
- * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2000 Peter Berger (pberger@brimson.com)
- * Copyright (C) 2000 Al Borchers (alborchers@steinerpoint.com)
+ * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
+ * Copyright (C) 2008 by David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
  *
  * This software is distributed under the terms of the GNU General
  * Public License ("GPL") as published by the Free Software Foundation,
@@ -22,2254 +16,237 @@
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 
-#include <linux/usb/ch9.h>
-#include <linux/usb/cdc.h>
-#include <linux/usb/gadget.h>
-
+#include "u_serial.h"
 #include "gadget_chips.h"
 
 
 /* Defines */
 
-#define GS_VERSION_STR			"v2.2"
-#define GS_VERSION_NUM			0x2200
+#define GS_VERSION_STR			"v2.4"
+#define GS_VERSION_NUM			0x2400
 
 #define GS_LONG_NAME			"Gadget Serial"
-#define GS_SHORT_NAME			"g_serial"
+#define GS_VERSION_NAME			GS_LONG_NAME " " GS_VERSION_STR
 
-#define GS_MAJOR			127
-#define GS_MINOR_START			0
-
-/* REVISIT only one port is supported for now;
- * see gs_{send,recv}_packet() ... no multiplexing,
- * and no support for multiple ACM devices.
- */
-#define GS_NUM_PORTS			1
-
-#define GS_NUM_CONFIGS			1
-#define GS_NO_CONFIG_ID			0
-#define GS_BULK_CONFIG_ID		1
-#define GS_ACM_CONFIG_ID		2
-
-#define GS_MAX_NUM_INTERFACES		2
-#define GS_BULK_INTERFACE_ID		0
-#define GS_CONTROL_INTERFACE_ID		0
-#define GS_DATA_INTERFACE_ID		1
-
-#define GS_MAX_DESC_LEN			256
-
-#define GS_DEFAULT_READ_Q_SIZE		32
-#define GS_DEFAULT_WRITE_Q_SIZE		32
-
-#define GS_DEFAULT_WRITE_BUF_SIZE	8192
-#define GS_TMP_BUF_SIZE			8192
-
-#define GS_CLOSE_TIMEOUT		15
-
-#define GS_DEFAULT_USE_ACM		0
-
-/* 9600-8-N-1 ... matches init_termios.c_cflag and defaults
- * expected by "usbser.sys" on MS-Windows.
- */
-#define GS_DEFAULT_DTE_RATE		9600
-#define GS_DEFAULT_DATA_BITS		8
-#define GS_DEFAULT_PARITY		USB_CDC_NO_PARITY
-#define GS_DEFAULT_CHAR_FORMAT		USB_CDC_1_STOP_BITS
-
-/* maxpacket and other transfer characteristics vary by speed. */
-static inline struct usb_endpoint_descriptor *
-choose_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs,
-		struct usb_endpoint_descriptor *fs)
-{
-	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
-		return hs;
-	return fs;
-}
-
-
-/* debug settings */
-#ifdef DEBUG
-static int debug = 1;
-#else
-#define	debug 0
-#endif
-
-#define gs_debug(format, arg...) \
-	do { if (debug) pr_debug(format, ## arg); } while (0)
-#define gs_debug_level(level, format, arg...) \
-	do { if (debug >= level) pr_debug(format, ## arg); } while (0)
-
+/*-------------------------------------------------------------------------*/
 
 /* Thanks to NetChip Technologies 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.
- */
+*
+* DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
+* Instead:  allocate your own, using normal USB-IF procedures.
+*/
 #define GS_VENDOR_ID			0x0525	/* NetChip */
 #define GS_PRODUCT_ID			0xa4a6	/* Linux-USB Serial Gadget */
 #define GS_CDC_PRODUCT_ID		0xa4a7	/* ... as CDC-ACM */
 
-#define GS_LOG2_NOTIFY_INTERVAL		5	/* 1 << 5 == 32 msec */
-#define GS_NOTIFY_MAXPACKET		8
+/* string IDs are assigned dynamically */
 
+#define STRING_MANUFACTURER_IDX		0
+#define STRING_PRODUCT_IDX		1
+#define STRING_DESCRIPTION_IDX		2
 
-/* circular buffer */
-struct gs_buf {
-	unsigned int		buf_size;
-	char			*buf_buf;
-	char			*buf_get;
-	char			*buf_put;
-};
-
-/* the port structure holds info for each port, one for each minor number */
-struct gs_port {
-	struct gs_dev		*port_dev;	/* pointer to device struct */
-	struct tty_struct	*port_tty;	/* pointer to tty struct */
-	spinlock_t		port_lock;
-	int			port_num;
-	int			port_open_count;
-	int			port_in_use;	/* open/close in progress */
-	wait_queue_head_t	port_write_wait;/* waiting to write */
-	struct gs_buf		*port_write_buf;
-	struct usb_cdc_line_coding port_line_coding;	/* 8-N-1 etc */
-	u16			port_handshake_bits;
-#define RS232_RTS	(1 << 1)
-#define RS232_DTE	(1 << 0)
-};
-
-/* the device structure holds info for the USB device */
-struct gs_dev {
-	struct usb_gadget	*dev_gadget;	/* gadget device pointer */
-	spinlock_t		dev_lock;	/* lock for set/reset config */
-	int			dev_config;	/* configuration number */
-	struct usb_ep		*dev_notify_ep;	/* address of notify endpoint */
-	struct usb_ep		*dev_in_ep;	/* address of in endpoint */
-	struct usb_ep		*dev_out_ep;	/* address of out endpoint */
-	struct usb_endpoint_descriptor		/* descriptor of notify ep */
-				*dev_notify_ep_desc;
-	struct usb_endpoint_descriptor		/* descriptor of in endpoint */
-				*dev_in_ep_desc;
-	struct usb_endpoint_descriptor		/* descriptor of out endpoint */
-				*dev_out_ep_desc;
-	struct usb_request	*dev_ctrl_req;	/* control request */
-	struct list_head	dev_req_list;	/* list of write requests */
-	int			dev_sched_port;	/* round robin port scheduled */
-	struct gs_port		*dev_port[GS_NUM_PORTS]; /* the ports */
-};
-
-
-/* Functions */
-
-/* tty driver internals */
-static int gs_send(struct gs_dev *dev);
-static int gs_send_packet(struct gs_dev *dev, char *packet,
-	unsigned int size);
-static int gs_recv_packet(struct gs_dev *dev, char *packet,
-	unsigned int size);
-static void gs_read_complete(struct usb_ep *ep, struct usb_request *req);
-static void gs_write_complete(struct usb_ep *ep, struct usb_request *req);
-
-/* gadget driver internals */
-static int gs_set_config(struct gs_dev *dev, unsigned config);
-static void gs_reset_config(struct gs_dev *dev);
-static int gs_build_config_buf(u8 *buf, struct usb_gadget *g,
-		u8 type, unsigned int index, int is_otg);
-
-static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len,
-	gfp_t kmalloc_flags);
-static void gs_free_req(struct usb_ep *ep, struct usb_request *req);
-
-static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags);
-static void gs_free_ports(struct gs_dev *dev);
-
-/* circular buffer */
-static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags);
-static void gs_buf_free(struct gs_buf *gb);
-static void gs_buf_clear(struct gs_buf *gb);
-static unsigned int gs_buf_data_avail(struct gs_buf *gb);
-static unsigned int gs_buf_space_avail(struct gs_buf *gb);
-static unsigned int gs_buf_put(struct gs_buf *gb, const char *buf,
-	unsigned int count);
-static unsigned int gs_buf_get(struct gs_buf *gb, char *buf,
-	unsigned int count);
-
-
-/* Globals */
-
-static struct gs_dev *gs_device;
-
-static struct mutex gs_open_close_lock[GS_NUM_PORTS];
-
-
-/*-------------------------------------------------------------------------*/
-
-/* USB descriptors */
-
-#define GS_MANUFACTURER_STR_ID	1
-#define GS_PRODUCT_STR_ID	2
-#define GS_SERIAL_STR_ID	3
-#define GS_BULK_CONFIG_STR_ID	4
-#define GS_ACM_CONFIG_STR_ID	5
-#define GS_CONTROL_STR_ID	6
-#define GS_DATA_STR_ID		7
-
-/* static strings, in UTF-8 */
 static char manufacturer[50];
-static struct usb_string gs_strings[] = {
-	{ GS_MANUFACTURER_STR_ID, manufacturer },
-	{ GS_PRODUCT_STR_ID, GS_LONG_NAME },
-	{ GS_BULK_CONFIG_STR_ID, "Gadget Serial Bulk" },
-	{ GS_ACM_CONFIG_STR_ID, "Gadget Serial CDC ACM" },
-	{ GS_CONTROL_STR_ID, "Gadget Serial Control" },
-	{ GS_DATA_STR_ID, "Gadget Serial Data" },
+
+static struct usb_string strings_dev[] = {
+	[STRING_MANUFACTURER_IDX].s = manufacturer,
+	[STRING_PRODUCT_IDX].s = GS_VERSION_NAME,
+	[STRING_DESCRIPTION_IDX].s = NULL /* updated; f(use_acm) */,
 	{  } /* end of list */
 };
 
-static struct usb_gadget_strings gs_string_table = {
-	.language =		0x0409,	/* en-us */
-	.strings =		gs_strings,
+static struct usb_gadget_strings stringtab_dev = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= strings_dev,
 };
 
-static struct usb_device_descriptor gs_device_desc = {
+static struct usb_gadget_strings *dev_strings[] = {
+	&stringtab_dev,
+	NULL,
+};
+
+static struct usb_device_descriptor device_desc = {
 	.bLength =		USB_DT_DEVICE_SIZE,
 	.bDescriptorType =	USB_DT_DEVICE,
 	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+	/* .bDeviceClass = f(use_acm) */
 	.bDeviceSubClass =	0,
 	.bDeviceProtocol =	0,
+	/* .bMaxPacketSize0 = f(hardware) */
 	.idVendor =		__constant_cpu_to_le16(GS_VENDOR_ID),
-	.idProduct =		__constant_cpu_to_le16(GS_PRODUCT_ID),
-	.iManufacturer =	GS_MANUFACTURER_STR_ID,
-	.iProduct =		GS_PRODUCT_STR_ID,
-	.bNumConfigurations =	GS_NUM_CONFIGS,
+	/* .idProduct =	f(use_acm) */
+	/* .bcdDevice = f(hardware) */
+	/* .iManufacturer = DYNAMIC */
+	/* .iProduct = DYNAMIC */
+	.bNumConfigurations =	1,
 };
 
-static struct usb_otg_descriptor gs_otg_descriptor = {
-	.bLength =		sizeof(gs_otg_descriptor),
+static struct usb_otg_descriptor otg_descriptor = {
+	.bLength =		sizeof otg_descriptor,
 	.bDescriptorType =	USB_DT_OTG,
-	.bmAttributes =		USB_OTG_SRP,
+
+	/* REVISIT SRP-only hardware is possible, although
+	 * it would not be called "OTG" ...
+	 */
+	.bmAttributes =		USB_OTG_SRP | USB_OTG_HNP,
 };
 
-static struct usb_config_descriptor gs_bulk_config_desc = {
-	.bLength =		USB_DT_CONFIG_SIZE,
-	.bDescriptorType =	USB_DT_CONFIG,
-	/* .wTotalLength computed dynamically */
-	.bNumInterfaces =	1,
-	.bConfigurationValue =	GS_BULK_CONFIG_ID,
-	.iConfiguration =	GS_BULK_CONFIG_STR_ID,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
-	.bMaxPower =		1,
-};
-
-static struct usb_config_descriptor gs_acm_config_desc = {
-	.bLength =		USB_DT_CONFIG_SIZE,
-	.bDescriptorType =	USB_DT_CONFIG,
-	/* .wTotalLength computed dynamically */
-	.bNumInterfaces =	2,
-	.bConfigurationValue =	GS_ACM_CONFIG_ID,
-	.iConfiguration =	GS_ACM_CONFIG_STR_ID,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
-	.bMaxPower =		1,
-};
-
-static const struct usb_interface_descriptor gs_bulk_interface_desc = {
-	.bLength =		USB_DT_INTERFACE_SIZE,
-	.bDescriptorType =	USB_DT_INTERFACE,
-	.bInterfaceNumber =	GS_BULK_INTERFACE_ID,
-	.bNumEndpoints =	2,
-	.bInterfaceClass =	USB_CLASS_VENDOR_SPEC,
-	.bInterfaceSubClass =	0,
-	.bInterfaceProtocol =	0,
-	.iInterface =		GS_DATA_STR_ID,
-};
-
-static const struct usb_interface_descriptor gs_control_interface_desc = {
-	.bLength =		USB_DT_INTERFACE_SIZE,
-	.bDescriptorType =	USB_DT_INTERFACE,
-	.bInterfaceNumber =	GS_CONTROL_INTERFACE_ID,
-	.bNumEndpoints =	1,
-	.bInterfaceClass =	USB_CLASS_COMM,
-	.bInterfaceSubClass =	USB_CDC_SUBCLASS_ACM,
-	.bInterfaceProtocol =	USB_CDC_ACM_PROTO_AT_V25TER,
-	.iInterface =		GS_CONTROL_STR_ID,
-};
-
-static const struct usb_interface_descriptor gs_data_interface_desc = {
-	.bLength =		USB_DT_INTERFACE_SIZE,
-	.bDescriptorType =	USB_DT_INTERFACE,
-	.bInterfaceNumber =	GS_DATA_INTERFACE_ID,
-	.bNumEndpoints =	2,
-	.bInterfaceClass =	USB_CLASS_CDC_DATA,
-	.bInterfaceSubClass =	0,
-	.bInterfaceProtocol =	0,
-	.iInterface =		GS_DATA_STR_ID,
-};
-
-static const struct usb_cdc_header_desc gs_header_desc = {
-	.bLength =		sizeof(gs_header_desc),
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
-	.bcdCDC =		__constant_cpu_to_le16(0x0110),
-};
-
-static const struct usb_cdc_call_mgmt_descriptor gs_call_mgmt_descriptor = {
-	.bLength =		sizeof(gs_call_mgmt_descriptor),
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_CALL_MANAGEMENT_TYPE,
-	.bmCapabilities =	0,
-	.bDataInterface =	1,	/* index of data interface */
-};
-
-static struct usb_cdc_acm_descriptor gs_acm_descriptor = {
-	.bLength =		sizeof(gs_acm_descriptor),
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_ACM_TYPE,
-	.bmCapabilities =	(1 << 1),
-};
-
-static const struct usb_cdc_union_desc gs_union_desc = {
-	.bLength =		sizeof(gs_union_desc),
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_UNION_TYPE,
-	.bMasterInterface0 =	0,	/* index of control interface */
-	.bSlaveInterface0 =	1,	/* index of data interface */
-};
-
-static struct usb_endpoint_descriptor gs_fullspeed_notify_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bEndpointAddress =	USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	__constant_cpu_to_le16(GS_NOTIFY_MAXPACKET),
-	.bInterval =		1 << GS_LOG2_NOTIFY_INTERVAL,
-};
-
-static struct usb_endpoint_descriptor gs_fullspeed_in_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bEndpointAddress =	USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-};
-
-static struct usb_endpoint_descriptor gs_fullspeed_out_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bEndpointAddress =	USB_DIR_OUT,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-};
-
-static const struct usb_descriptor_header *gs_bulk_fullspeed_function[] = {
-	(struct usb_descriptor_header *) &gs_otg_descriptor,
-	(struct usb_descriptor_header *) &gs_bulk_interface_desc,
-	(struct usb_descriptor_header *) &gs_fullspeed_in_desc,
-	(struct usb_descriptor_header *) &gs_fullspeed_out_desc,
+static const struct usb_descriptor_header *otg_desc[] = {
+	(struct usb_descriptor_header *) &otg_descriptor,
 	NULL,
 };
 
-static const struct usb_descriptor_header *gs_acm_fullspeed_function[] = {
-	(struct usb_descriptor_header *) &gs_otg_descriptor,
-	(struct usb_descriptor_header *) &gs_control_interface_desc,
-	(struct usb_descriptor_header *) &gs_header_desc,
-	(struct usb_descriptor_header *) &gs_call_mgmt_descriptor,
-	(struct usb_descriptor_header *) &gs_acm_descriptor,
-	(struct usb_descriptor_header *) &gs_union_desc,
-	(struct usb_descriptor_header *) &gs_fullspeed_notify_desc,
-	(struct usb_descriptor_header *) &gs_data_interface_desc,
-	(struct usb_descriptor_header *) &gs_fullspeed_in_desc,
-	(struct usb_descriptor_header *) &gs_fullspeed_out_desc,
-	NULL,
-};
-
-static struct usb_endpoint_descriptor gs_highspeed_notify_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bEndpointAddress =	USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_INT,
-	.wMaxPacketSize =	__constant_cpu_to_le16(GS_NOTIFY_MAXPACKET),
-	.bInterval =		GS_LOG2_NOTIFY_INTERVAL+4,
-};
-
-static struct usb_endpoint_descriptor gs_highspeed_in_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
-};
-
-static struct usb_endpoint_descriptor gs_highspeed_out_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
-};
-
-static struct usb_qualifier_descriptor gs_qualifier_desc = {
-	.bLength =		sizeof(struct usb_qualifier_descriptor),
-	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
-	.bcdUSB =		__constant_cpu_to_le16 (0x0200),
-	/* assumes ep0 uses the same value for both speeds ... */
-	.bNumConfigurations =	GS_NUM_CONFIGS,
-};
-
-static const struct usb_descriptor_header *gs_bulk_highspeed_function[] = {
-	(struct usb_descriptor_header *) &gs_otg_descriptor,
-	(struct usb_descriptor_header *) &gs_bulk_interface_desc,
-	(struct usb_descriptor_header *) &gs_highspeed_in_desc,
-	(struct usb_descriptor_header *) &gs_highspeed_out_desc,
-	NULL,
-};
-
-static const struct usb_descriptor_header *gs_acm_highspeed_function[] = {
-	(struct usb_descriptor_header *) &gs_otg_descriptor,
-	(struct usb_descriptor_header *) &gs_control_interface_desc,
-	(struct usb_descriptor_header *) &gs_header_desc,
-	(struct usb_descriptor_header *) &gs_call_mgmt_descriptor,
-	(struct usb_descriptor_header *) &gs_acm_descriptor,
-	(struct usb_descriptor_header *) &gs_union_desc,
-	(struct usb_descriptor_header *) &gs_highspeed_notify_desc,
-	(struct usb_descriptor_header *) &gs_data_interface_desc,
-	(struct usb_descriptor_header *) &gs_highspeed_in_desc,
-	(struct usb_descriptor_header *) &gs_highspeed_out_desc,
-	NULL,
-};
-
-
 /*-------------------------------------------------------------------------*/
 
 /* Module */
-MODULE_DESCRIPTION(GS_LONG_NAME);
+MODULE_DESCRIPTION(GS_VERSION_NAME);
 MODULE_AUTHOR("Al Borchers");
+MODULE_AUTHOR("David Brownell");
 MODULE_LICENSE("GPL");
 
-#ifdef DEBUG
-module_param(debug, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable debugging, 0=off, 1=on");
-#endif
+static int use_acm = true;
+module_param(use_acm, bool, 0);
+MODULE_PARM_DESC(use_acm, "Use CDC ACM, default=yes");
 
-static unsigned int read_q_size = GS_DEFAULT_READ_Q_SIZE;
-module_param(read_q_size, uint, S_IRUGO);
-MODULE_PARM_DESC(read_q_size, "Read request queue size, default=32");
-
-static unsigned int write_q_size = GS_DEFAULT_WRITE_Q_SIZE;
-module_param(write_q_size, uint, S_IRUGO);
-MODULE_PARM_DESC(write_q_size, "Write request queue size, default=32");
-
-static unsigned int write_buf_size = GS_DEFAULT_WRITE_BUF_SIZE;
-module_param(write_buf_size, uint, S_IRUGO);
-MODULE_PARM_DESC(write_buf_size, "Write buffer size, default=8192");
-
-static unsigned int use_acm = GS_DEFAULT_USE_ACM;
-module_param(use_acm, uint, S_IRUGO);
-MODULE_PARM_DESC(use_acm, "Use CDC ACM, 0=no, 1=yes, default=no");
+static unsigned n_ports = 1;
+module_param(n_ports, uint, 0);
+MODULE_PARM_DESC(n_ports, "number of ports to create, default=1");
 
 /*-------------------------------------------------------------------------*/
 
-/* TTY Driver */
-
-/*
- * gs_open
- */
-static int gs_open(struct tty_struct *tty, struct file *file)
+static int __init serial_bind_config(struct usb_configuration *c)
 {
-	int port_num;
-	unsigned long flags;
-	struct gs_port *port;
-	struct gs_dev *dev;
-	struct gs_buf *buf;
-	struct mutex *mtx;
-	int ret;
+	unsigned i;
+	int status = 0;
 
-	port_num = tty->index;
-
-	gs_debug("gs_open: (%d,%p,%p)\n", port_num, tty, file);
-
-	if (port_num < 0 || port_num >= GS_NUM_PORTS) {
-		pr_err("gs_open: (%d,%p,%p) invalid port number\n",
-			port_num, tty, file);
-		return -ENODEV;
+	for (i = 0; i < n_ports && status == 0; i++) {
+		if (use_acm)
+			status = acm_bind_config(c, i);
+		else
+			status = gser_bind_config(c, i);
 	}
-
-	dev = gs_device;
-
-	if (dev == NULL) {
-		pr_err("gs_open: (%d,%p,%p) NULL device pointer\n",
-			port_num, tty, file);
-		return -ENODEV;
-	}
-
-	mtx = &gs_open_close_lock[port_num];
-	if (mutex_lock_interruptible(mtx)) {
-		pr_err("gs_open: (%d,%p,%p) interrupted waiting for mutex\n",
-			port_num, tty, file);
-		return -ERESTARTSYS;
-	}
-
-	spin_lock_irqsave(&dev->dev_lock, flags);
-
-	if (dev->dev_config == GS_NO_CONFIG_ID) {
-		pr_err("gs_open: (%d,%p,%p) device is not connected\n",
-			port_num, tty, file);
-		ret = -ENODEV;
-		goto exit_unlock_dev;
-	}
-
-	port = dev->dev_port[port_num];
-
-	if (port == NULL) {
-		pr_err("gs_open: (%d,%p,%p) NULL port pointer\n",
-			port_num, tty, file);
-		ret = -ENODEV;
-		goto exit_unlock_dev;
-	}
-
-	spin_lock(&port->port_lock);
-	spin_unlock(&dev->dev_lock);
-
-	if (port->port_dev == NULL) {
-		pr_err("gs_open: (%d,%p,%p) port disconnected (1)\n",
-			port_num, tty, file);
-		ret = -EIO;
-		goto exit_unlock_port;
-	}
-
-	if (port->port_open_count > 0) {
-		++port->port_open_count;
-		gs_debug("gs_open: (%d,%p,%p) already open\n",
-			port_num, tty, file);
-		ret = 0;
-		goto exit_unlock_port;
-	}
-
-	tty->driver_data = NULL;
-
-	/* mark port as in use, we can drop port lock and sleep if necessary */
-	port->port_in_use = 1;
-
-	/* allocate write buffer on first open */
-	if (port->port_write_buf == NULL) {
-		spin_unlock_irqrestore(&port->port_lock, flags);
-		buf = gs_buf_alloc(write_buf_size, GFP_KERNEL);
-		spin_lock_irqsave(&port->port_lock, flags);
-
-		/* might have been disconnected while asleep, check */
-		if (port->port_dev == NULL) {
-			pr_err("gs_open: (%d,%p,%p) port disconnected (2)\n",
-				port_num, tty, file);
-			port->port_in_use = 0;
-			ret = -EIO;
-			goto exit_unlock_port;
-		}
-
-		if ((port->port_write_buf=buf) == NULL) {
-			pr_err("gs_open: (%d,%p,%p) cannot allocate "
-				"port write buffer\n",
-				port_num, tty, file);
-			port->port_in_use = 0;
-			ret = -ENOMEM;
-			goto exit_unlock_port;
-		}
-
-	}
-
-	/* wait for carrier detect (not implemented) */
-
-	/* might have been disconnected while asleep, check */
-	if (port->port_dev == NULL) {
-		pr_err("gs_open: (%d,%p,%p) port disconnected (3)\n",
-			port_num, tty, file);
-		port->port_in_use = 0;
-		ret = -EIO;
-		goto exit_unlock_port;
-	}
-
-	tty->driver_data = port;
-	port->port_tty = tty;
-	port->port_open_count = 1;
-	port->port_in_use = 0;
-
-	gs_debug("gs_open: (%d,%p,%p) completed\n", port_num, tty, file);
-
-	ret = 0;
-
-exit_unlock_port:
-	spin_unlock_irqrestore(&port->port_lock, flags);
-	mutex_unlock(mtx);
-	return ret;
-
-exit_unlock_dev:
-	spin_unlock_irqrestore(&dev->dev_lock, flags);
-	mutex_unlock(mtx);
-	return ret;
-
+	return status;
 }
 
-/*
- * gs_close
- */
-
-static int gs_write_finished_event_safely(struct gs_port *p)
-{
-	int cond;
-
-	spin_lock_irq(&(p)->port_lock);
-	cond = !(p)->port_dev || !gs_buf_data_avail((p)->port_write_buf);
-	spin_unlock_irq(&(p)->port_lock);
-	return cond;
-}
-
-static void gs_close(struct tty_struct *tty, struct file *file)
-{
-	struct gs_port *port = tty->driver_data;
-	struct mutex *mtx;
-
-	if (port == NULL) {
-		pr_err("gs_close: NULL port pointer\n");
-		return;
-	}
-
-	gs_debug("gs_close: (%d,%p,%p)\n", port->port_num, tty, file);
-
-	mtx = &gs_open_close_lock[port->port_num];
-	mutex_lock(mtx);
-
-	spin_lock_irq(&port->port_lock);
-
-	if (port->port_open_count == 0) {
-		pr_err("gs_close: (%d,%p,%p) port is already closed\n",
-			port->port_num, tty, file);
-		goto exit;
-	}
-
-	if (port->port_open_count > 1) {
-		--port->port_open_count;
-		goto exit;
-	}
-
-	/* free disconnected port on final close */
-	if (port->port_dev == NULL) {
-		kfree(port);
-		goto exit;
-	}
-
-	/* mark port as closed but in use, we can drop port lock */
-	/* and sleep if necessary */
-	port->port_in_use = 1;
-	port->port_open_count = 0;
-
-	/* wait for write buffer to drain, or */
-	/* at most GS_CLOSE_TIMEOUT seconds */
-	if (gs_buf_data_avail(port->port_write_buf) > 0) {
-		spin_unlock_irq(&port->port_lock);
-		wait_event_interruptible_timeout(port->port_write_wait,
-					gs_write_finished_event_safely(port),
-					GS_CLOSE_TIMEOUT * HZ);
-		spin_lock_irq(&port->port_lock);
-	}
-
-	/* free disconnected port on final close */
-	/* (might have happened during the above sleep) */
-	if (port->port_dev == NULL) {
-		kfree(port);
-		goto exit;
-	}
-
-	gs_buf_clear(port->port_write_buf);
-
-	tty->driver_data = NULL;
-	port->port_tty = NULL;
-	port->port_in_use = 0;
-
-	gs_debug("gs_close: (%d,%p,%p) completed\n",
-		port->port_num, tty, file);
-
-exit:
-	spin_unlock_irq(&port->port_lock);
-	mutex_unlock(mtx);
-}
-
-/*
- * gs_write
- */
-static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-	unsigned long flags;
-	struct gs_port *port = tty->driver_data;
-	int ret;
-
-	if (port == NULL) {
-		pr_err("gs_write: NULL port pointer\n");
-		return -EIO;
-	}
-
-	gs_debug("gs_write: (%d,%p) writing %d bytes\n", port->port_num, tty,
-		count);
-
-	if (count == 0)
-		return 0;
-
-	spin_lock_irqsave(&port->port_lock, flags);
-
-	if (port->port_dev == NULL) {
-		pr_err("gs_write: (%d,%p) port is not connected\n",
-			port->port_num, tty);
-		ret = -EIO;
-		goto exit;
-	}
-
-	if (port->port_open_count == 0) {
-		pr_err("gs_write: (%d,%p) port is closed\n",
-			port->port_num, tty);
-		ret = -EBADF;
-		goto exit;
-	}
-
-	count = gs_buf_put(port->port_write_buf, buf, count);
-
-	spin_unlock_irqrestore(&port->port_lock, flags);
-
-	gs_send(gs_device);
-
-	gs_debug("gs_write: (%d,%p) wrote %d bytes\n", port->port_num, tty,
-		count);
-
-	return count;
-
-exit:
-	spin_unlock_irqrestore(&port->port_lock, flags);
-	return ret;
-}
-
-/*
- * gs_put_char
- */
-static int gs_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	unsigned long flags;
-	struct gs_port *port = tty->driver_data;
-	int ret = 0;
-
-	if (port == NULL) {
-		pr_err("gs_put_char: NULL port pointer\n");
-		return 0;
-	}
-
-	gs_debug("gs_put_char: (%d,%p) char=0x%x, called from %p\n",
-		port->port_num, tty, ch, __builtin_return_address(0));
-
-	spin_lock_irqsave(&port->port_lock, flags);
-
-	if (port->port_dev == NULL) {
-		pr_err("gs_put_char: (%d,%p) port is not connected\n",
-			port->port_num, tty);
-		goto exit;
-	}
-
-	if (port->port_open_count == 0) {
-		pr_err("gs_put_char: (%d,%p) port is closed\n",
-			port->port_num, tty);
-		goto exit;
-	}
-
-	ret = gs_buf_put(port->port_write_buf, &ch, 1);
-
-exit:
-	spin_unlock_irqrestore(&port->port_lock, flags);
-	return ret;
-}
-
-/*
- * gs_flush_chars
- */
-static void gs_flush_chars(struct tty_struct *tty)
-{
-	unsigned long flags;
-	struct gs_port *port = tty->driver_data;
-
-	if (port == NULL) {
-		pr_err("gs_flush_chars: NULL port pointer\n");
-		return;
-	}
-
-	gs_debug("gs_flush_chars: (%d,%p)\n", port->port_num, tty);
-
-	spin_lock_irqsave(&port->port_lock, flags);
-
-	if (port->port_dev == NULL) {
-		pr_err("gs_flush_chars: (%d,%p) port is not connected\n",
-			port->port_num, tty);
-		goto exit;
-	}
-
-	if (port->port_open_count == 0) {
-		pr_err("gs_flush_chars: (%d,%p) port is closed\n",
-			port->port_num, tty);
-		goto exit;
-	}
-
-	spin_unlock_irqrestore(&port->port_lock, flags);
-
-	gs_send(gs_device);
-
-	return;
-
-exit:
-	spin_unlock_irqrestore(&port->port_lock, flags);
-}
-
-/*
- * gs_write_room
- */
-static int gs_write_room(struct tty_struct *tty)
-{
-
-	int room = 0;
-	unsigned long flags;
-	struct gs_port *port = tty->driver_data;
-
-
-	if (port == NULL)
-		return 0;
-
-	spin_lock_irqsave(&port->port_lock, flags);
-
-	if (port->port_dev != NULL && port->port_open_count > 0
-	&& port->port_write_buf != NULL)
-		room = gs_buf_space_avail(port->port_write_buf);
-
-	spin_unlock_irqrestore(&port->port_lock, flags);
-
-	gs_debug("gs_write_room: (%d,%p) room=%d\n",
-		port->port_num, tty, room);
-
-	return room;
-}
-
-/*
- * gs_chars_in_buffer
- */
-static int gs_chars_in_buffer(struct tty_struct *tty)
-{
-	int chars = 0;
-	unsigned long flags;
-	struct gs_port *port = tty->driver_data;
-
-	if (port == NULL)
-		return 0;
-
-	spin_lock_irqsave(&port->port_lock, flags);
-
-	if (port->port_dev != NULL && port->port_open_count > 0
-	&& port->port_write_buf != NULL)
-		chars = gs_buf_data_avail(port->port_write_buf);
-
-	spin_unlock_irqrestore(&port->port_lock, flags);
-
-	gs_debug("gs_chars_in_buffer: (%d,%p) chars=%d\n",
-		port->port_num, tty, chars);
-
-	return chars;
-}
-
-/*
- * gs_throttle
- */
-static void gs_throttle(struct tty_struct *tty)
-{
-}
-
-/*
- * gs_unthrottle
- */
-static void gs_unthrottle(struct tty_struct *tty)
-{
-}
-
-/*
- * gs_break
- */
-static void gs_break(struct tty_struct *tty, int break_state)
-{
-}
-
-/*
- * gs_ioctl
- */
-static int gs_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct gs_port *port = tty->driver_data;
-
-	if (port == NULL) {
-		pr_err("gs_ioctl: NULL port pointer\n");
-		return -EIO;
-	}
-
-	gs_debug("gs_ioctl: (%d,%p,%p) cmd=0x%4.4x, arg=%lu\n",
-		port->port_num, tty, file, cmd, arg);
-
-	/* handle ioctls */
-
-	/* could not handle ioctl */
-	return -ENOIOCTLCMD;
-}
-
-/*
- * gs_set_termios
- */
-static void gs_set_termios(struct tty_struct *tty, struct ktermios *old)
-{
-}
-
-static const struct tty_operations gs_tty_ops = {
-	.open =			gs_open,
-	.close =		gs_close,
-	.write =		gs_write,
-	.put_char =		gs_put_char,
-	.flush_chars =		gs_flush_chars,
-	.write_room =		gs_write_room,
-	.ioctl =		gs_ioctl,
-	.set_termios =		gs_set_termios,
-	.throttle =		gs_throttle,
-	.unthrottle =		gs_unthrottle,
-	.break_ctl =		gs_break,
-	.chars_in_buffer =	gs_chars_in_buffer,
+static struct usb_configuration serial_config_driver = {
+	/* .label = f(use_acm) */
+	.bind		= serial_bind_config,
+	/* .bConfigurationValue = f(use_acm) */
+	/* .iConfiguration = DYNAMIC */
+	.bmAttributes	= USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower	= 1,	/* 2 mA, minimal */
 };
 
-/*-------------------------------------------------------------------------*/
-
-/*
-* gs_send
-*
-* This function finds available write requests, calls
-* gs_send_packet to fill these packets with data, and
-* continues until either there are no more write requests
-* available or no more data to send.  This function is
-* run whenever data arrives or write requests are available.
-*/
-static int gs_send(struct gs_dev *dev)
+static int __init gs_bind(struct usb_composite_dev *cdev)
 {
-	int ret,len;
-	unsigned long flags;
-	struct usb_ep *ep;
-	struct usb_request *req;
+	int			gcnum;
+	struct usb_gadget	*gadget = cdev->gadget;
+	int			status;
 
-	if (dev == NULL) {
-		pr_err("gs_send: NULL device pointer\n");
-		return -ENODEV;
-	}
+	status = gserial_setup(cdev->gadget, n_ports);
+	if (status < 0)
+		return status;
 
-	spin_lock_irqsave(&dev->dev_lock, flags);
-
-	ep = dev->dev_in_ep;
-
-	while(!list_empty(&dev->dev_req_list)) {
-
-		req = list_entry(dev->dev_req_list.next,
-				struct usb_request, list);
-
-		len = gs_send_packet(dev, req->buf, ep->maxpacket);
-
-		if (len > 0) {
-			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->list);
-			req->length = len;
-			spin_unlock_irqrestore(&dev->dev_lock, flags);
-			if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
-				pr_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;
-		}
-
-	}
-
-	spin_unlock_irqrestore(&dev->dev_lock, flags);
-
-	return 0;
-}
-
-/*
- * gs_send_packet
- *
- * If there is data to send, a packet is built in the given
- * buffer and the size is returned.  If there is no data to
- * send, 0 is returned.  If there is any error a negative
- * error number is returned.
- *
- * Called during USB completion routine, on interrupt time.
- *
- * We assume that disconnect will not happen until all completion
- * routines have completed, so we can assume that the dev_port
- * array does not change during the lifetime of this function.
- */
-static int gs_send_packet(struct gs_dev *dev, char *packet, unsigned int size)
-{
-	unsigned int len;
-	struct gs_port *port;
-
-	/* TEMPORARY -- only port 0 is supported right now */
-	port = dev->dev_port[0];
-
-	if (port == NULL) {
-		pr_err("gs_send_packet: port=%d, NULL port pointer\n", 0);
-		return -EIO;
-	}
-
-	spin_lock(&port->port_lock);
-
-	len = gs_buf_data_avail(port->port_write_buf);
-	if (len < size)
-		size = len;
-
-	if (size == 0)
-		goto exit;
-
-	size = gs_buf_get(port->port_write_buf, packet, size);
-
-	if (port->port_tty)
-		wake_up_interruptible(&port->port_tty->write_wait);
-
-exit:
-	spin_unlock(&port->port_lock);
-	return size;
-}
-
-/*
- * gs_recv_packet
- *
- * Called for each USB packet received.  Reads the packet
- * header and stuffs the data in the appropriate tty buffer.
- * Returns 0 if successful, or a negative error number.
- *
- * Called during USB completion routine, on interrupt time.
- *
- * We assume that disconnect will not happen until all completion
- * routines have completed, so we can assume that the dev_port
- * array does not change during the lifetime of this function.
- */
-static int gs_recv_packet(struct gs_dev *dev, char *packet, unsigned int size)
-{
-	unsigned int len;
-	struct gs_port *port;
-	int ret;
-	struct tty_struct *tty;
-
-	/* TEMPORARY -- only port 0 is supported right now */
-	port = dev->dev_port[0];
-
-	if (port == NULL) {
-		pr_err("gs_recv_packet: port=%d, NULL port pointer\n",
-			port->port_num);
-		return -EIO;
-	}
-
-	spin_lock(&port->port_lock);
-
-	if (port->port_open_count == 0) {
-		pr_err("gs_recv_packet: port=%d, port is closed\n",
-			port->port_num);
-		ret = -EIO;
-		goto exit;
-	}
-
-
-	tty = port->port_tty;
-
-	if (tty == NULL) {
-		pr_err("gs_recv_packet: port=%d, NULL tty pointer\n",
-			port->port_num);
-		ret = -EIO;
-		goto exit;
-	}
-
-	if (port->port_tty->magic != TTY_MAGIC) {
-		pr_err("gs_recv_packet: port=%d, bad tty magic\n",
-			port->port_num);
-		ret = -EIO;
-		goto exit;
-	}
-
-	len = tty_buffer_request_room(tty, size);
-	if (len > 0) {
-		tty_insert_flip_string(tty, packet, len);
-		tty_flip_buffer_push(port->port_tty);
-		wake_up_interruptible(&port->port_tty->read_wait);
-	}
-	ret = 0;
-exit:
-	spin_unlock(&port->port_lock);
-	return ret;
-}
-
-/*
-* gs_read_complete
-*/
-static void gs_read_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	int ret;
-	struct gs_dev *dev = ep->driver_data;
-
-	if (dev == NULL) {
-		pr_err("gs_read_complete: NULL device pointer\n");
-		return;
-	}
-
-	switch(req->status) {
-	case 0:
-		/* normal completion */
-		gs_recv_packet(dev, req->buf, req->actual);
-requeue:
-		req->length = ep->maxpacket;
-		if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
-			pr_err(
-			"gs_read_complete: cannot queue read request, ret=%d\n",
-				ret);
-		}
-		break;
-
-	case -ESHUTDOWN:
-		/* disconnect */
-		gs_debug("gs_read_complete: shutdown\n");
-		gs_free_req(ep, req);
-		break;
-
-	default:
-		/* unexpected */
-		pr_err(
-		"gs_read_complete: unexpected status error, status=%d\n",
-			req->status);
-		goto requeue;
-		break;
-	}
-}
-
-/*
-* gs_write_complete
-*/
-static void gs_write_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	struct gs_dev *dev = ep->driver_data;
-
-	if (dev == NULL) {
-		pr_err("gs_write_complete: NULL device pointer\n");
-		return;
-	}
-
-	switch(req->status) {
-	case 0:
-		/* normal completion */
-requeue:
-		spin_lock(&dev->dev_lock);
-		list_add(&req->list, &dev->dev_req_list);
-		spin_unlock(&dev->dev_lock);
-
-		gs_send(dev);
-
-		break;
-
-	case -ESHUTDOWN:
-		/* disconnect */
-		gs_debug("gs_write_complete: shutdown\n");
-		gs_free_req(ep, req);
-		break;
-
-	default:
-		pr_err(
-		"gs_write_complete: unexpected status error, status=%d\n",
-			req->status);
-		goto requeue;
-		break;
-	}
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* Gadget Driver */
-
-/*
- * gs_unbind
- *
- * Called on module unload.  Frees the control request and device
- * structure.
- */
-static void /* __init_or_exit */ gs_unbind(struct usb_gadget *gadget)
-{
-	struct gs_dev *dev = get_gadget_data(gadget);
-
-	gs_device = NULL;
-
-	/* read/write requests already freed, only control request remains */
-	if (dev != NULL) {
-		if (dev->dev_ctrl_req != NULL) {
-			gs_free_req(gadget->ep0, dev->dev_ctrl_req);
-			dev->dev_ctrl_req = NULL;
-		}
-		gs_reset_config(dev);
-		gs_free_ports(dev);
-		kfree(dev);
-		set_gadget_data(gadget, NULL);
-	}
-
-	pr_info("gs_unbind: %s %s unbound\n", GS_LONG_NAME,
-		GS_VERSION_STR);
-}
-
-/*
- * gs_bind
- *
- * Called on module load.  Allocates and initializes the device
- * structure and a control request.
- */
-static int __init gs_bind(struct usb_gadget *gadget)
-{
-	int ret;
-	struct usb_ep *ep;
-	struct gs_dev *dev;
-	int gcnum;
-
-	/* Some controllers can't support CDC ACM:
-	 * - sh doesn't support multiple interfaces or configs;
-	 * - sa1100 doesn't have a third interrupt endpoint
+	/* Allocate string descriptor numbers ... note that string
+	 * contents can be overridden by the composite_dev glue.
 	 */
-	if (gadget_is_sh(gadget) || gadget_is_sa1100(gadget))
-		use_acm = 0;
 
-	gcnum = usb_gadget_controller_number(gadget);
-	if (gcnum >= 0)
-		gs_device_desc.bcdDevice =
-				cpu_to_le16(GS_VERSION_NUM | gcnum);
-	else {
-		pr_warning("gs_bind: controller '%s' not recognized\n",
-			gadget->name);
-		/* unrecognized, but safe unless bulk is REALLY quirky */
-		gs_device_desc.bcdDevice =
-			__constant_cpu_to_le16(GS_VERSION_NUM|0x0099);
-	}
-
-	dev = kzalloc(sizeof(struct gs_dev), GFP_KERNEL);
-	if (dev == NULL)
-		return -ENOMEM;
-
-	usb_ep_autoconfig_reset(gadget);
-
-	ep = usb_ep_autoconfig(gadget, &gs_fullspeed_in_desc);
-	if (!ep)
-		goto autoconf_fail;
-	dev->dev_in_ep = ep;
-	ep->driver_data = dev;	/* claim the endpoint */
-
-	ep = usb_ep_autoconfig(gadget, &gs_fullspeed_out_desc);
-	if (!ep)
-		goto autoconf_fail;
-	dev->dev_out_ep = ep;
-	ep->driver_data = dev;	/* claim the endpoint */
-
-	if (use_acm) {
-		ep = usb_ep_autoconfig(gadget, &gs_fullspeed_notify_desc);
-		if (!ep) {
-			pr_err("gs_bind: cannot run ACM on %s\n", gadget->name);
-			goto autoconf_fail;
-		}
-		gs_device_desc.idProduct = __constant_cpu_to_le16(
-						GS_CDC_PRODUCT_ID),
-		dev->dev_notify_ep = ep;
-		ep->driver_data = dev;	/* claim the endpoint */
-	}
-
-	gs_device_desc.bDeviceClass = use_acm
-		? USB_CLASS_COMM : USB_CLASS_VENDOR_SPEC;
-	gs_device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
-
-	if (gadget_is_dualspeed(gadget)) {
-		gs_qualifier_desc.bDeviceClass = use_acm
-			? USB_CLASS_COMM : USB_CLASS_VENDOR_SPEC;
-		/* assume ep0 uses the same packet size for both speeds */
-		gs_qualifier_desc.bMaxPacketSize0 =
-			gs_device_desc.bMaxPacketSize0;
-		/* assume endpoints are dual-speed */
-		gs_highspeed_notify_desc.bEndpointAddress =
-			gs_fullspeed_notify_desc.bEndpointAddress;
-		gs_highspeed_in_desc.bEndpointAddress =
-			gs_fullspeed_in_desc.bEndpointAddress;
-		gs_highspeed_out_desc.bEndpointAddress =
-			gs_fullspeed_out_desc.bEndpointAddress;
-	}
-
-	usb_gadget_set_selfpowered(gadget);
-
-	if (gadget_is_otg(gadget)) {
-		gs_otg_descriptor.bmAttributes |= USB_OTG_HNP,
-		gs_bulk_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
-		gs_acm_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
-	}
-
-	gs_device = dev;
-
-	snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s",
+	/* device description: manufacturer, product */
+	snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
 		init_utsname()->sysname, init_utsname()->release,
 		gadget->name);
+	status = usb_string_id(cdev);
+	if (status < 0)
+		goto fail;
+	strings_dev[STRING_MANUFACTURER_IDX].id = status;
 
-	dev->dev_gadget = gadget;
-	spin_lock_init(&dev->dev_lock);
-	INIT_LIST_HEAD(&dev->dev_req_list);
-	set_gadget_data(gadget, dev);
+	device_desc.iManufacturer = status;
 
-	if ((ret=gs_alloc_ports(dev, GFP_KERNEL)) != 0) {
-		pr_err("gs_bind: cannot allocate ports\n");
-		gs_unbind(gadget);
-		return ret;
+	status = usb_string_id(cdev);
+	if (status < 0)
+		goto fail;
+	strings_dev[STRING_PRODUCT_IDX].id = status;
+
+	device_desc.iProduct = status;
+
+	/* config description */
+	status = usb_string_id(cdev);
+	if (status < 0)
+		goto fail;
+	strings_dev[STRING_DESCRIPTION_IDX].id = status;
+
+	serial_config_driver.iConfiguration = status;
+
+	/* set up other descriptors */
+	gcnum = usb_gadget_controller_number(gadget);
+	if (gcnum >= 0)
+		device_desc.bcdDevice = cpu_to_le16(GS_VERSION_NUM | gcnum);
+	else {
+		/* this is so simple (for now, no altsettings) that it
+		 * SHOULD NOT have problems with bulk-capable hardware.
+		 * so warn about unrcognized controllers -- don't panic.
+		 *
+		 * things like configuration and altsetting numbering
+		 * can need hardware-specific attention though.
+		 */
+		pr_warning("gs_bind: controller '%s' not recognized\n",
+			gadget->name);
+		device_desc.bcdDevice =
+			__constant_cpu_to_le16(GS_VERSION_NUM | 0x0099);
 	}
 
-	/* preallocate control response and buffer */
-	dev->dev_ctrl_req = gs_alloc_req(gadget->ep0, GS_MAX_DESC_LEN,
-		GFP_KERNEL);
-	if (dev->dev_ctrl_req == NULL) {
-		gs_unbind(gadget);
-		return -ENOMEM;
+	if (gadget_is_otg(cdev->gadget)) {
+		serial_config_driver.descriptors = otg_desc;
+		serial_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
-	gadget->ep0->driver_data = dev;
 
-	pr_info("gs_bind: %s %s bound\n",
-		GS_LONG_NAME, GS_VERSION_STR);
+	/* register our configuration */
+	status = usb_add_config(cdev, &serial_config_driver);
+	if (status < 0)
+		goto fail;
+
+	INFO(cdev, "%s\n", GS_VERSION_NAME);
 
 	return 0;
 
-autoconf_fail:
-	kfree(dev);
-	pr_err("gs_bind: cannot autoconfigure on %s\n", gadget->name);
-	return -ENODEV;
+fail:
+	gserial_cleanup();
+	return status;
 }
 
-static int gs_setup_standard(struct usb_gadget *gadget,
-	const struct usb_ctrlrequest *ctrl)
-{
-	int ret = -EOPNOTSUPP;
-	struct gs_dev *dev = get_gadget_data(gadget);
-	struct usb_request *req = dev->dev_ctrl_req;
-	u16 wIndex = le16_to_cpu(ctrl->wIndex);
-	u16 wValue = le16_to_cpu(ctrl->wValue);
-	u16 wLength = le16_to_cpu(ctrl->wLength);
-
-	switch (ctrl->bRequest) {
-	case USB_REQ_GET_DESCRIPTOR:
-		if (ctrl->bRequestType != USB_DIR_IN)
-			break;
-
-		switch (wValue >> 8) {
-		case USB_DT_DEVICE:
-			ret = min(wLength,
-				(u16)sizeof(struct usb_device_descriptor));
-			memcpy(req->buf, &gs_device_desc, ret);
-			break;
-
-		case USB_DT_DEVICE_QUALIFIER:
-			if (!gadget_is_dualspeed(gadget))
-				break;
-			ret = min(wLength,
-				(u16)sizeof(struct usb_qualifier_descriptor));
-			memcpy(req->buf, &gs_qualifier_desc, ret);
-			break;
-
-		case USB_DT_OTHER_SPEED_CONFIG:
-			if (!gadget_is_dualspeed(gadget))
-				break;
-			/* fall through */
-		case USB_DT_CONFIG:
-			ret = gs_build_config_buf(req->buf, gadget,
-				wValue >> 8, wValue & 0xff,
-				gadget_is_otg(gadget));
-			if (ret >= 0)
-				ret = min(wLength, (u16)ret);
-			break;
-
-		case USB_DT_STRING:
-			/* wIndex == language code. */
-			ret = usb_gadget_get_string(&gs_string_table,
-				wValue & 0xff, req->buf);
-			if (ret >= 0)
-				ret = min(wLength, (u16)ret);
-			break;
-		}
-		break;
-
-	case USB_REQ_SET_CONFIGURATION:
-		if (ctrl->bRequestType != 0)
-			break;
-		spin_lock(&dev->dev_lock);
-		ret = gs_set_config(dev, wValue);
-		spin_unlock(&dev->dev_lock);
-		break;
-
-	case USB_REQ_GET_CONFIGURATION:
-		if (ctrl->bRequestType != USB_DIR_IN)
-			break;
-		*(u8 *)req->buf = dev->dev_config;
-		ret = min(wLength, (u16)1);
-		break;
-
-	case USB_REQ_SET_INTERFACE:
-		if (ctrl->bRequestType != USB_RECIP_INTERFACE
-				|| !dev->dev_config
-				|| wIndex >= GS_MAX_NUM_INTERFACES)
-			break;
-		if (dev->dev_config == GS_BULK_CONFIG_ID
-				&& wIndex != GS_BULK_INTERFACE_ID)
-			break;
-		/* no alternate interface settings */
-		if (wValue != 0)
-			break;
-		spin_lock(&dev->dev_lock);
-		/* PXA hardware partially handles SET_INTERFACE;
-		 * we need to kluge around that interference.  */
-		if (gadget_is_pxa(gadget)) {
-			ret = gs_set_config(dev, use_acm ?
-				GS_ACM_CONFIG_ID : GS_BULK_CONFIG_ID);
-			goto set_interface_done;
-		}
-		if (dev->dev_config != GS_BULK_CONFIG_ID
-				&& wIndex == GS_CONTROL_INTERFACE_ID) {
-			if (dev->dev_notify_ep) {
-				usb_ep_disable(dev->dev_notify_ep);
-				usb_ep_enable(dev->dev_notify_ep, dev->dev_notify_ep_desc);
-			}
-		} else {
-			usb_ep_disable(dev->dev_in_ep);
-			usb_ep_disable(dev->dev_out_ep);
-			usb_ep_enable(dev->dev_in_ep, dev->dev_in_ep_desc);
-			usb_ep_enable(dev->dev_out_ep, dev->dev_out_ep_desc);
-		}
-		ret = 0;
-set_interface_done:
-		spin_unlock(&dev->dev_lock);
-		break;
-
-	case USB_REQ_GET_INTERFACE:
-		if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)
-		|| dev->dev_config == GS_NO_CONFIG_ID)
-			break;
-		if (wIndex >= GS_MAX_NUM_INTERFACES
-				|| (dev->dev_config == GS_BULK_CONFIG_ID
-				&& wIndex != GS_BULK_INTERFACE_ID)) {
-			ret = -EDOM;
-			break;
-		}
-		/* no alternate interface settings */
-		*(u8 *)req->buf = 0;
-		ret = min(wLength, (u16)1);
-		break;
-
-	default:
-		pr_err("gs_setup: unknown standard request, type=%02x, "
-			"request=%02x, value=%04x, index=%04x, length=%d\n",
-			ctrl->bRequestType, ctrl->bRequest,
-			wValue, wIndex, wLength);
-		break;
-	}
-
-	return ret;
-}
-
-static void gs_setup_complete_set_line_coding(struct usb_ep *ep,
-		struct usb_request *req)
-{
-	struct gs_dev *dev = ep->driver_data;
-	struct gs_port *port = dev->dev_port[0]; /* ACM only has one port */
-
-	switch (req->status) {
-	case 0:
-		/* normal completion */
-		if (req->actual != sizeof(port->port_line_coding))
-			usb_ep_set_halt(ep);
-		else if (port) {
-			struct usb_cdc_line_coding	*value = req->buf;
-
-			/* REVISIT:  we currently just remember this data.
-			 * If we change that, (a) validate it first, then
-			 * (b) update whatever hardware needs updating.
-			 */
-			spin_lock(&port->port_lock);
-			port->port_line_coding = *value;
-			spin_unlock(&port->port_lock);
-		}
-		break;
-
-	case -ESHUTDOWN:
-		/* disconnect */
-		gs_free_req(ep, req);
-		break;
-
-	default:
-		/* unexpected */
-		break;
-	}
-	return;
-}
-
-static int gs_setup_class(struct usb_gadget *gadget,
-	const struct usb_ctrlrequest *ctrl)
-{
-	int ret = -EOPNOTSUPP;
-	struct gs_dev *dev = get_gadget_data(gadget);
-	struct gs_port *port = dev->dev_port[0];	/* ACM only has one port */
-	struct usb_request *req = dev->dev_ctrl_req;
-	u16 wIndex = le16_to_cpu(ctrl->wIndex);
-	u16 wValue = le16_to_cpu(ctrl->wValue);
-	u16 wLength = le16_to_cpu(ctrl->wLength);
-
-	switch (ctrl->bRequest) {
-	case USB_CDC_REQ_SET_LINE_CODING:
-		if (wLength != sizeof(struct usb_cdc_line_coding))
-			break;
-		ret = wLength;
-		req->complete = gs_setup_complete_set_line_coding;
-		break;
-
-	case USB_CDC_REQ_GET_LINE_CODING:
-		ret = min_t(int, wLength, sizeof(struct usb_cdc_line_coding));
-		if (port) {
-			spin_lock(&port->port_lock);
-			memcpy(req->buf, &port->port_line_coding, ret);
-			spin_unlock(&port->port_lock);
-		}
-		break;
-
-	case USB_CDC_REQ_SET_CONTROL_LINE_STATE:
-		if (wLength != 0)
-			break;
-		ret = 0;
-		if (port) {
-			/* REVISIT:  we currently just remember this data.
-			 * If we change that, update whatever hardware needs
-			 * updating.
-			 */
-			spin_lock(&port->port_lock);
-			port->port_handshake_bits = wValue;
-			spin_unlock(&port->port_lock);
-		}
-		break;
-
-	default:
-		/* NOTE:  strictly speaking, we should accept AT-commands
-		 * using SEND_ENCPSULATED_COMMAND/GET_ENCAPSULATED_RESPONSE.
-		 * But our call management descriptor says we don't handle
-		 * call management, so we should be able to get by without
-		 * handling those "required" commands (except by stalling).
-		 */
-		pr_err("gs_setup: unknown class request, "
-				"type=%02x, request=%02x, value=%04x, "
-				"index=%04x, length=%d\n",
-			ctrl->bRequestType, ctrl->bRequest,
-			wValue, wIndex, wLength);
-		break;
-	}
-
-	return ret;
-}
-
-/*
- * gs_setup_complete
- */
-static void gs_setup_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	if (req->status || req->actual != req->length) {
-		pr_err("gs_setup_complete: status error, status=%d, "
-			"actual=%d, length=%d\n",
-			req->status, req->actual, req->length);
-	}
-}
-
-/*
- * gs_setup
- *
- * Implements all the control endpoint functionality that's not
- * handled in hardware or the hardware driver.
- *
- * Returns the size of the data sent to the host, or a negative
- * error number.
- */
-static int gs_setup(struct usb_gadget *gadget,
-	const struct usb_ctrlrequest *ctrl)
-{
-	int		ret = -EOPNOTSUPP;
-	struct gs_dev	*dev = get_gadget_data(gadget);
-	struct usb_request *req = dev->dev_ctrl_req;
-	u16		wIndex = le16_to_cpu(ctrl->wIndex);
-	u16		wValue = le16_to_cpu(ctrl->wValue);
-	u16		wLength = le16_to_cpu(ctrl->wLength);
-
-	req->complete = gs_setup_complete;
-
-	switch (ctrl->bRequestType & USB_TYPE_MASK) {
-	case USB_TYPE_STANDARD:
-		ret = gs_setup_standard(gadget, ctrl);
-		break;
-
-	case USB_TYPE_CLASS:
-		ret = gs_setup_class(gadget, ctrl);
-		break;
-
-	default:
-		pr_err("gs_setup: unknown request, type=%02x, request=%02x, "
-			"value=%04x, index=%04x, length=%d\n",
-			ctrl->bRequestType, ctrl->bRequest,
-			wValue, wIndex, wLength);
-		break;
-	}
-
-	/* respond with data transfer before status phase? */
-	if (ret >= 0) {
-		req->length = ret;
-		req->zero = ret < wLength
-				&& (ret % gadget->ep0->maxpacket) == 0;
-		ret = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
-		if (ret < 0) {
-			pr_err("gs_setup: cannot queue response, ret=%d\n",
-				ret);
-			req->status = 0;
-			gs_setup_complete(gadget->ep0, req);
-		}
-	}
-
-	/* device either stalls (ret < 0) or reports success */
-	return ret;
-}
-
-/*
- * gs_disconnect
- *
- * Called when the device is disconnected.  Frees the closed
- * ports and disconnects open ports.  Open ports will be freed
- * on close.  Then reallocates the ports for the next connection.
- */
-static void gs_disconnect(struct usb_gadget *gadget)
-{
-	unsigned long flags;
-	struct gs_dev *dev = get_gadget_data(gadget);
-
-	spin_lock_irqsave(&dev->dev_lock, flags);
-
-	gs_reset_config(dev);
-
-	/* free closed ports and disconnect open ports */
-	/* (open ports will be freed when closed) */
-	gs_free_ports(dev);
-
-	/* re-allocate ports for the next connection */
-	if (gs_alloc_ports(dev, GFP_ATOMIC) != 0)
-		pr_err("gs_disconnect: cannot re-allocate ports\n");
-
-	spin_unlock_irqrestore(&dev->dev_lock, flags);
-
-	pr_info("gs_disconnect: %s disconnected\n", GS_LONG_NAME);
-}
-
-static struct usb_gadget_driver gs_gadget_driver = {
-#ifdef CONFIG_USB_GADGET_DUALSPEED
-	.speed =		USB_SPEED_HIGH,
-#else
-	.speed =		USB_SPEED_FULL,
-#endif /* CONFIG_USB_GADGET_DUALSPEED */
-	.function =		GS_LONG_NAME,
-	.bind =			gs_bind,
-	.unbind =		gs_unbind,
-	.setup =		gs_setup,
-	.disconnect =		gs_disconnect,
-	.driver = {
-		.name =		GS_SHORT_NAME,
-		.owner =	THIS_MODULE,
-	},
+static struct usb_composite_driver gserial_driver = {
+	.name		= "g_serial",
+	.dev		= &device_desc,
+	.strings	= dev_strings,
+	.bind		= gs_bind,
 };
 
-/*
- * gs_set_config
- *
- * Configures the device by enabling device specific
- * optimizations, setting up the endpoints, allocating
- * read and write requests and queuing read requests.
- *
- * The device lock must be held when calling this function.
- */
-static int gs_set_config(struct gs_dev *dev, unsigned config)
+static int __init init(void)
 {
-	int i;
-	int ret = 0;
-	struct usb_gadget *gadget = dev->dev_gadget;
-	struct usb_ep *ep;
-	struct usb_endpoint_descriptor *out, *in, *notify;
-	struct usb_request *req;
-
-	if (dev == NULL) {
-		pr_err("gs_set_config: NULL device pointer\n");
-		return 0;
-	}
-
-	if (config == dev->dev_config)
-		return 0;
-
-	gs_reset_config(dev);
-
-	switch (config) {
-	case GS_NO_CONFIG_ID:
-		return 0;
-	case GS_BULK_CONFIG_ID:
-		if (use_acm)
-			return -EINVAL;
-		break;
-	case GS_ACM_CONFIG_ID:
-		if (!use_acm)
-			return -EINVAL;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	in = choose_ep_desc(gadget,
-			&gs_highspeed_in_desc,
-			&gs_fullspeed_in_desc);
-	out = choose_ep_desc(gadget,
-			&gs_highspeed_out_desc,
-			&gs_fullspeed_out_desc);
-	notify = dev->dev_notify_ep
-		? choose_ep_desc(gadget,
-				&gs_highspeed_notify_desc,
-				&gs_fullspeed_notify_desc)
-		: NULL;
-
-	ret = usb_ep_enable(dev->dev_in_ep, in);
-	if (ret == 0) {
-		dev->dev_in_ep_desc = in;
-	} else {
-		pr_debug("%s: cannot enable %s %s, ret=%d\n",
-			__func__, "IN", dev->dev_in_ep->name, ret);
-		return ret;
-	}
-
-	ret = usb_ep_enable(dev->dev_out_ep, out);
-	if (ret == 0) {
-		dev->dev_out_ep_desc = out;
-	} else {
-		pr_debug("%s: cannot enable %s %s, ret=%d\n",
-			__func__, "OUT", dev->dev_out_ep->name, ret);
-fail0:
-		usb_ep_disable(dev->dev_in_ep);
-		return ret;
-	}
-
-	if (notify) {
-		ret = usb_ep_enable(dev->dev_notify_ep, notify);
-		if (ret == 0) {
-			dev->dev_notify_ep_desc = notify;
-		} else {
-			pr_debug("%s: cannot enable %s %s, ret=%d\n",
-				__func__, "NOTIFY",
-				dev->dev_notify_ep->name, ret);
-			usb_ep_disable(dev->dev_out_ep);
-			goto fail0;
-		}
-	}
-
-	dev->dev_config = config;
-
-	/* allocate and queue read requests */
-	ep = dev->dev_out_ep;
-	for (i=0; i<read_q_size && ret == 0; i++) {
-		if ((req=gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC))) {
-			req->complete = gs_read_complete;
-			if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
-				pr_err("gs_set_config: cannot queue read "
-					"request, ret=%d\n", ret);
-			}
-		} else {
-			pr_err("gs_set_config: cannot allocate "
-					"read requests\n");
-			ret = -ENOMEM;
-			goto exit_reset_config;
-		}
-	}
-
-	/* allocate write requests, and put on free list */
-	ep = dev->dev_in_ep;
-	for (i=0; i<write_q_size; i++) {
-		req = gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC);
-		if (req) {
-			req->complete = gs_write_complete;
-			list_add(&req->list, &dev->dev_req_list);
-		} else {
-			pr_err("gs_set_config: cannot allocate "
-					"write requests\n");
-			ret = -ENOMEM;
-			goto exit_reset_config;
-		}
-	}
-
-	/* REVISIT the ACM mode should be able to actually *issue* some
-	 * notifications, for at least serial state change events if
-	 * not also for network connection; say so in bmCapabilities.
+	/* We *could* export two configs; that'd be much cleaner...
+	 * but neither of these product IDs was defined that way.
 	 */
-
-	pr_info("gs_set_config: %s configured, %s speed %s config\n",
-		GS_LONG_NAME,
-		gadget->speed == USB_SPEED_HIGH ? "high" : "full",
-		config == GS_BULK_CONFIG_ID ? "BULK" : "CDC-ACM");
-
-	return 0;
-
-exit_reset_config:
-	gs_reset_config(dev);
-	return ret;
-}
-
-/*
- * gs_reset_config
- *
- * Mark the device as not configured, disable all endpoints,
- * which forces completion of pending I/O and frees queued
- * requests, and free the remaining write requests on the
- * free list.
- *
- * The device lock must be held when calling this function.
- */
-static void gs_reset_config(struct gs_dev *dev)
-{
-	struct usb_request *req;
-
-	if (dev == NULL) {
-		pr_err("gs_reset_config: NULL device pointer\n");
-		return;
-	}
-
-	if (dev->dev_config == GS_NO_CONFIG_ID)
-		return;
-
-	dev->dev_config = GS_NO_CONFIG_ID;
-
-	/* free write requests on the free list */
-	while(!list_empty(&dev->dev_req_list)) {
-		req = list_entry(dev->dev_req_list.next,
-				struct usb_request, list);
-		list_del(&req->list);
-		gs_free_req(dev->dev_in_ep, req);
-	}
-
-	/* disable endpoints, forcing completion of pending i/o; */
-	/* completion handlers free their requests in this case */
-	if (dev->dev_notify_ep)
-		usb_ep_disable(dev->dev_notify_ep);
-	usb_ep_disable(dev->dev_in_ep);
-	usb_ep_disable(dev->dev_out_ep);
-}
-
-/*
- * gs_build_config_buf
- *
- * Builds the config descriptors in the given buffer and returns the
- * length, or a negative error number.
- */
-static int gs_build_config_buf(u8 *buf, struct usb_gadget *g,
-	u8 type, unsigned int index, int is_otg)
-{
-	int len;
-	int high_speed = 0;
-	const struct usb_config_descriptor *config_desc;
-	const struct usb_descriptor_header **function;
-
-	if (index >= gs_device_desc.bNumConfigurations)
-		return -EINVAL;
-
-	/* other speed switches high and full speed */
-	if (gadget_is_dualspeed(g)) {
-		high_speed = (g->speed == USB_SPEED_HIGH);
-		if (type == USB_DT_OTHER_SPEED_CONFIG)
-			high_speed = !high_speed;
-	}
-
 	if (use_acm) {
-		config_desc = &gs_acm_config_desc;
-		function = high_speed
-			? gs_acm_highspeed_function
-			: gs_acm_fullspeed_function;
+		serial_config_driver.label = "CDC ACM config";
+		serial_config_driver.bConfigurationValue = 2;
+		device_desc.bDeviceClass = USB_CLASS_COMM;
+		device_desc.idProduct =
+				__constant_cpu_to_le16(GS_CDC_PRODUCT_ID);
 	} else {
-		config_desc = &gs_bulk_config_desc;
-		function = high_speed
-			? gs_bulk_highspeed_function
-			: gs_bulk_fullspeed_function;
+		serial_config_driver.label = "Generic Serial config";
+		serial_config_driver.bConfigurationValue = 1;
+		device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
+		device_desc.idProduct =
+				__constant_cpu_to_le16(GS_PRODUCT_ID);
 	}
+	strings_dev[STRING_DESCRIPTION_IDX].s = serial_config_driver.label;
 
-	/* for now, don't advertise srp-only devices */
-	if (!is_otg)
-		function++;
-
-	len = usb_gadget_config_buf(config_desc, buf, GS_MAX_DESC_LEN, function);
-	if (len < 0)
-		return len;
-
-	((struct usb_config_descriptor *)buf)->bDescriptorType = type;
-
-	return len;
+	return usb_composite_register(&gserial_driver);
 }
+module_init(init);
 
-/*
- * gs_alloc_req
- *
- * Allocate a usb_request and its buffer.  Returns a pointer to the
- * usb_request or NULL if there is an error.
- */
-static struct usb_request *
-gs_alloc_req(struct usb_ep *ep, unsigned int len, gfp_t kmalloc_flags)
+static void __exit cleanup(void)
 {
-	struct usb_request *req;
-
-	if (ep == NULL)
-		return NULL;
-
-	req = usb_ep_alloc_request(ep, kmalloc_flags);
-
-	if (req != NULL) {
-		req->length = len;
-		req->buf = kmalloc(len, kmalloc_flags);
-		if (req->buf == NULL) {
-			usb_ep_free_request(ep, req);
-			return NULL;
-		}
-	}
-
-	return req;
+	usb_composite_unregister(&gserial_driver);
+	gserial_cleanup();
 }
-
-/*
- * gs_free_req
- *
- * Free a usb_request and its buffer.
- */
-static void gs_free_req(struct usb_ep *ep, struct usb_request *req)
-{
-	if (ep != NULL && req != NULL) {
-		kfree(req->buf);
-		usb_ep_free_request(ep, req);
-	}
-}
-
-/*
- * gs_alloc_ports
- *
- * Allocate all ports and set the gs_dev struct to point to them.
- * Return 0 if successful, or a negative error number.
- *
- * The device lock is normally held when calling this function.
- */
-static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags)
-{
-	int i;
-	struct gs_port *port;
-
-	if (dev == NULL)
-		return -EIO;
-
-	for (i=0; i<GS_NUM_PORTS; i++) {
-		if ((port=kzalloc(sizeof(struct gs_port), kmalloc_flags)) == NULL)
-			return -ENOMEM;
-
-		port->port_dev = dev;
-		port->port_num = i;
-		port->port_line_coding.dwDTERate = cpu_to_le32(GS_DEFAULT_DTE_RATE);
-		port->port_line_coding.bCharFormat = GS_DEFAULT_CHAR_FORMAT;
-		port->port_line_coding.bParityType = GS_DEFAULT_PARITY;
-		port->port_line_coding.bDataBits = GS_DEFAULT_DATA_BITS;
-		spin_lock_init(&port->port_lock);
-		init_waitqueue_head(&port->port_write_wait);
-
-		dev->dev_port[i] = port;
-	}
-
-	return 0;
-}
-
-/*
- * gs_free_ports
- *
- * Free all closed ports.  Open ports are disconnected by
- * freeing their write buffers, setting their device pointers
- * and the pointers to them in the device to NULL.  These
- * ports will be freed when closed.
- *
- * The device lock is normally held when calling this function.
- */
-static void gs_free_ports(struct gs_dev *dev)
-{
-	int i;
-	unsigned long flags;
-	struct gs_port *port;
-
-	if (dev == NULL)
-		return;
-
-	for (i=0; i<GS_NUM_PORTS; i++) {
-		if ((port=dev->dev_port[i]) != NULL) {
-			dev->dev_port[i] = NULL;
-
-			spin_lock_irqsave(&port->port_lock, flags);
-
-			if (port->port_write_buf != NULL) {
-				gs_buf_free(port->port_write_buf);
-				port->port_write_buf = NULL;
-			}
-
-			if (port->port_open_count > 0 || port->port_in_use) {
-				port->port_dev = NULL;
-				wake_up_interruptible(&port->port_write_wait);
-				if (port->port_tty) {
-					tty_hangup(port->port_tty);
-				}
-				spin_unlock_irqrestore(&port->port_lock, flags);
-			} else {
-				spin_unlock_irqrestore(&port->port_lock, flags);
-				kfree(port);
-			}
-
-		}
-	}
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* Circular Buffer */
-
-/*
- * gs_buf_alloc
- *
- * Allocate a circular buffer and all associated memory.
- */
-static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags)
-{
-	struct gs_buf *gb;
-
-	if (size == 0)
-		return NULL;
-
-	gb = kmalloc(sizeof(struct gs_buf), kmalloc_flags);
-	if (gb == NULL)
-		return NULL;
-
-	gb->buf_buf = kmalloc(size, kmalloc_flags);
-	if (gb->buf_buf == NULL) {
-		kfree(gb);
-		return NULL;
-	}
-
-	gb->buf_size = size;
-	gb->buf_get = gb->buf_put = gb->buf_buf;
-
-	return gb;
-}
-
-/*
- * gs_buf_free
- *
- * Free the buffer and all associated memory.
- */
-static void gs_buf_free(struct gs_buf *gb)
-{
-	if (gb) {
-		kfree(gb->buf_buf);
-		kfree(gb);
-	}
-}
-
-/*
- * gs_buf_clear
- *
- * Clear out all data in the circular buffer.
- */
-static void gs_buf_clear(struct gs_buf *gb)
-{
-	if (gb != NULL)
-		gb->buf_get = gb->buf_put;
-		/* equivalent to a get of all data available */
-}
-
-/*
- * gs_buf_data_avail
- *
- * Return the number of bytes of data available in the circular
- * buffer.
- */
-static unsigned int gs_buf_data_avail(struct gs_buf *gb)
-{
-	if (gb != NULL)
-		return (gb->buf_size + gb->buf_put - gb->buf_get) % gb->buf_size;
-	else
-		return 0;
-}
-
-/*
- * gs_buf_space_avail
- *
- * Return the number of bytes of space available in the circular
- * buffer.
- */
-static unsigned int gs_buf_space_avail(struct gs_buf *gb)
-{
-	if (gb != NULL)
-		return (gb->buf_size + gb->buf_get - gb->buf_put - 1) % gb->buf_size;
-	else
-		return 0;
-}
-
-/*
- * gs_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
-gs_buf_put(struct gs_buf *gb, const char *buf, unsigned int count)
-{
-	unsigned int len;
-
-	if (gb == NULL)
-		return 0;
-
-	len  = gs_buf_space_avail(gb);
-	if (count > len)
-		count = len;
-
-	if (count == 0)
-		return 0;
-
-	len = gb->buf_buf + gb->buf_size - gb->buf_put;
-	if (count > len) {
-		memcpy(gb->buf_put, buf, len);
-		memcpy(gb->buf_buf, buf+len, count - len);
-		gb->buf_put = gb->buf_buf + count - len;
-	} else {
-		memcpy(gb->buf_put, buf, count);
-		if (count < len)
-			gb->buf_put += count;
-		else /* count == len */
-			gb->buf_put = gb->buf_buf;
-	}
-
-	return count;
-}
-
-/*
- * gs_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
-gs_buf_get(struct gs_buf *gb, char *buf, unsigned int count)
-{
-	unsigned int len;
-
-	if (gb == NULL)
-		return 0;
-
-	len = gs_buf_data_avail(gb);
-	if (count > len)
-		count = len;
-
-	if (count == 0)
-		return 0;
-
-	len = gb->buf_buf + gb->buf_size - gb->buf_get;
-	if (count > len) {
-		memcpy(buf, gb->buf_get, len);
-		memcpy(buf+len, gb->buf_buf, count - len);
-		gb->buf_get = gb->buf_buf + count - len;
-	} else {
-		memcpy(buf, gb->buf_get, count);
-		if (count < len)
-			gb->buf_get += count;
-		else /* count == len */
-			gb->buf_get = gb->buf_buf;
-	}
-
-	return count;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static struct tty_driver *gs_tty_driver;
-
-/*
- *  gs_module_init
- *
- *  Register as a USB gadget driver and a tty driver.
- */
-static int __init gs_module_init(void)
-{
-	int i;
-	int retval;
-
-	retval = usb_gadget_register_driver(&gs_gadget_driver);
-	if (retval) {
-		pr_err("gs_module_init: cannot register gadget driver, "
-			"ret=%d\n", retval);
-		return retval;
-	}
-
-	gs_tty_driver = alloc_tty_driver(GS_NUM_PORTS);
-	if (!gs_tty_driver)
-		return -ENOMEM;
-	gs_tty_driver->owner = THIS_MODULE;
-	gs_tty_driver->driver_name = GS_SHORT_NAME;
-	gs_tty_driver->name = "ttygs";
-	gs_tty_driver->major = GS_MAJOR;
-	gs_tty_driver->minor_start = GS_MINOR_START;
-	gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	gs_tty_driver->subtype = SERIAL_TYPE_NORMAL;
-	gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-	gs_tty_driver->init_termios = tty_std_termios;
-	/* must match GS_DEFAULT_DTE_RATE and friends */
-	gs_tty_driver->init_termios.c_cflag =
-		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	gs_tty_driver->init_termios.c_ispeed = GS_DEFAULT_DTE_RATE;
-	gs_tty_driver->init_termios.c_ospeed = GS_DEFAULT_DTE_RATE;
-	tty_set_operations(gs_tty_driver, &gs_tty_ops);
-
-	for (i = 0; i < GS_NUM_PORTS; i++)
-		mutex_init(&gs_open_close_lock[i]);
-
-	retval = tty_register_driver(gs_tty_driver);
-	if (retval) {
-		usb_gadget_unregister_driver(&gs_gadget_driver);
-		put_tty_driver(gs_tty_driver);
-		pr_err("gs_module_init: cannot register tty driver, "
-				"ret=%d\n", retval);
-		return retval;
-	}
-
-	pr_info("gs_module_init: %s %s loaded\n",
-			GS_LONG_NAME, GS_VERSION_STR);
-	return 0;
-}
-module_init(gs_module_init);
-
-/*
- * gs_module_exit
- *
- * Unregister as a tty driver and a USB gadget driver.
- */
-static void __exit gs_module_exit(void)
-{
-	tty_unregister_driver(gs_tty_driver);
-	put_tty_driver(gs_tty_driver);
-	usb_gadget_unregister_driver(&gs_gadget_driver);
-
-	pr_info("gs_module_exit: %s %s unloaded\n",
-			GS_LONG_NAME, GS_VERSION_STR);
-}
-module_exit(gs_module_exit);
+module_exit(cleanup);
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
new file mode 100644
index 0000000..5458f43
--- /dev/null
+++ b/drivers/usb/gadget/u_ether.c
@@ -0,0 +1,967 @@
+/*
+ * u_ether.c -- Ethernet-over-USB link layer utilities for Gadget stack
+ *
+ * Copyright (C) 2003-2005,2008 David Brownell
+ * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/utsname.h>
+#include <linux/device.h>
+#include <linux/ctype.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+
+#include "u_ether.h"
+
+
+/*
+ * This component encapsulates the Ethernet link glue needed to provide
+ * one (!) network link through the USB gadget stack, normally "usb0".
+ *
+ * The control and data models are handled by the function driver which
+ * connects to this code; such as CDC Ethernet, "CDC Subset", or RNDIS.
+ * That includes all descriptor and endpoint management.
+ *
+ * Link level addressing is handled by this component using module
+ * parameters; if no such parameters are provided, random link level
+ * addresses are used.  Each end of the link uses one address.  The
+ * host end address is exported in various ways, and is often recorded
+ * in configuration databases.
+ *
+ * The driver which assembles each configuration using such a link is
+ * responsible for ensuring that each configuration includes at most one
+ * instance of is network link.  (The network layer provides ways for
+ * this single "physical" link to be used by multiple virtual links.)
+ */
+
+#define DRIVER_VERSION	"29-May-2008"
+
+struct eth_dev {
+	/* lock is held while accessing port_usb
+	 * or updating its backlink port_usb->ioport
+	 */
+	spinlock_t		lock;
+	struct gether		*port_usb;
+
+	struct net_device	*net;
+	struct usb_gadget	*gadget;
+
+	spinlock_t		req_lock;	/* guard {rx,tx}_reqs */
+	struct list_head	tx_reqs, rx_reqs;
+	atomic_t		tx_qlen;
+
+	unsigned		header_len;
+	struct sk_buff		*(*wrap)(struct sk_buff *skb);
+	int			(*unwrap)(struct sk_buff *skb);
+
+	struct work_struct	work;
+
+	unsigned long		todo;
+#define	WORK_RX_MEMORY		0
+
+	bool			zlp;
+	u8			host_mac[ETH_ALEN];
+};
+
+/*-------------------------------------------------------------------------*/
+
+#define RX_EXTRA	20	/* bytes guarding against rx overflows */
+
+#define DEFAULT_QLEN	2	/* double buffering by default */
+
+
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+
+static unsigned qmult = 5;
+module_param(qmult, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(qmult, "queue length multiplier at high speed");
+
+#else	/* full speed (low speed doesn't do bulk) */
+#define qmult		1
+#endif
+
+/* for dual-speed hardware, use deeper queues at highspeed */
+static inline int qlen(struct usb_gadget *gadget)
+{
+	if (gadget_is_dualspeed(gadget) && gadget->speed == USB_SPEED_HIGH)
+		return qmult * DEFAULT_QLEN;
+	else
+		return DEFAULT_QLEN;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* REVISIT there must be a better way than having two sets
+ * of debug calls ...
+ */
+
+#undef DBG
+#undef VDBG
+#undef ERROR
+#undef WARN
+#undef INFO
+
+#define xprintk(d, level, fmt, args...) \
+	printk(level "%s: " fmt , (d)->net->name , ## args)
+
+#ifdef DEBUG
+#undef 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_DEBUG
+#define VDBG	DBG
+#else
+#define VDBG(dev, fmt, args...) \
+	do { } while (0)
+#endif /* DEBUG */
+
+#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)
+
+/*-------------------------------------------------------------------------*/
+
+/* NETWORK DRIVER HOOKUP (to the layer above this driver) */
+
+static int eth_change_mtu(struct net_device *net, int new_mtu)
+{
+	struct eth_dev	*dev = netdev_priv(net);
+	unsigned long	flags;
+	int		status = 0;
+
+	/* don't change MTU on "live" link (peer won't know) */
+	spin_lock_irqsave(&dev->lock, flags);
+	if (dev->port_usb)
+		status = -EBUSY;
+	else if (new_mtu <= ETH_HLEN || new_mtu > ETH_FRAME_LEN)
+		status = -ERANGE;
+	else
+		net->mtu = new_mtu;
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return status;
+}
+
+static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p)
+{
+	struct eth_dev	*dev = netdev_priv(net);
+
+	strlcpy(p->driver, "g_ether", sizeof p->driver);
+	strlcpy(p->version, DRIVER_VERSION, sizeof p->version);
+	strlcpy(p->fw_version, dev->gadget->name, sizeof p->fw_version);
+	strlcpy(p->bus_info, dev_name(&dev->gadget->dev), sizeof p->bus_info);
+}
+
+static u32 eth_get_link(struct net_device *net)
+{
+	struct eth_dev	*dev = netdev_priv(net);
+	return dev->gadget->speed != USB_SPEED_UNKNOWN;
+}
+
+/* REVISIT can also support:
+ *   - WOL (by tracking suspends and issuing remote wakeup)
+ *   - msglevel (implies updated messaging)
+ *   - ... probably more ethtool ops
+ */
+
+static struct ethtool_ops ops = {
+	.get_drvinfo = eth_get_drvinfo,
+	.get_link = eth_get_link
+};
+
+static void defer_kevent(struct eth_dev *dev, int flag)
+{
+	if (test_and_set_bit(flag, &dev->todo))
+		return;
+	if (!schedule_work(&dev->work))
+		ERROR(dev, "kevent %d may have been dropped\n", flag);
+	else
+		DBG(dev, "kevent %d scheduled\n", flag);
+}
+
+static void rx_complete(struct usb_ep *ep, struct usb_request *req);
+
+static int
+rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
+{
+	struct sk_buff	*skb;
+	int		retval = -ENOMEM;
+	size_t		size = 0;
+	struct usb_ep	*out;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	if (dev->port_usb)
+		out = dev->port_usb->out_ep;
+	else
+		out = NULL;
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	if (!out)
+		return -ENOTCONN;
+
+
+	/* Padding up to RX_EXTRA handles minor disagreements with host.
+	 * Normally we use the USB "terminate on short read" convention;
+	 * so allow up to (N*maxpacket), since that memory is normally
+	 * already allocated.  Some hardware doesn't deal well with short
+	 * reads (e.g. DMA must be N*maxpacket), so for now don't trim a
+	 * byte off the end (to force hardware errors on overflow).
+	 *
+	 * RNDIS uses internal framing, and explicitly allows senders to
+	 * pad to end-of-packet.  That's potentially nice for speed, but
+	 * means receivers can't recover lost synch on their own (because
+	 * new packets don't only start after a short RX).
+	 */
+	size += sizeof(struct ethhdr) + dev->net->mtu + RX_EXTRA;
+	size += dev->port_usb->header_len;
+	size += out->maxpacket - 1;
+	size -= size % out->maxpacket;
+
+	skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags);
+	if (skb == NULL) {
+		DBG(dev, "no rx skb\n");
+		goto enomem;
+	}
+
+	/* Some platforms perform better when IP packets are aligned,
+	 * but on at least one, checksumming fails otherwise.  Note:
+	 * RNDIS headers involve variable numbers of LE32 values.
+	 */
+	skb_reserve(skb, NET_IP_ALIGN);
+
+	req->buf = skb->data;
+	req->length = size;
+	req->complete = rx_complete;
+	req->context = skb;
+
+	retval = usb_ep_queue(out, req, gfp_flags);
+	if (retval == -ENOMEM)
+enomem:
+		defer_kevent(dev, WORK_RX_MEMORY);
+	if (retval) {
+		DBG(dev, "rx submit --> %d\n", retval);
+		if (skb)
+			dev_kfree_skb_any(skb);
+		spin_lock_irqsave(&dev->req_lock, flags);
+		list_add(&req->list, &dev->rx_reqs);
+		spin_unlock_irqrestore(&dev->req_lock, flags);
+	}
+	return retval;
+}
+
+static void rx_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct sk_buff	*skb = req->context;
+	struct eth_dev	*dev = ep->driver_data;
+	int		status = req->status;
+
+	switch (status) {
+
+	/* normal completion */
+	case 0:
+		skb_put(skb, req->actual);
+		if (dev->unwrap)
+			status = dev->unwrap(skb);
+		if (status < 0
+				|| ETH_HLEN > skb->len
+				|| skb->len > ETH_FRAME_LEN) {
+			dev->net->stats.rx_errors++;
+			dev->net->stats.rx_length_errors++;
+			DBG(dev, "rx length %d\n", skb->len);
+			break;
+		}
+
+		skb->protocol = eth_type_trans(skb, dev->net);
+		dev->net->stats.rx_packets++;
+		dev->net->stats.rx_bytes += skb->len;
+
+		/* no buffer copies needed, unless hardware can't
+		 * use skb buffers.
+		 */
+		status = netif_rx(skb);
+		skb = NULL;
+		break;
+
+	/* software-driven interface shutdown */
+	case -ECONNRESET:		/* unlink */
+	case -ESHUTDOWN:		/* disconnect etc */
+		VDBG(dev, "rx shutdown, code %d\n", status);
+		goto quiesce;
+
+	/* for hardware automagic (such as pxa) */
+	case -ECONNABORTED:		/* endpoint reset */
+		DBG(dev, "rx %s reset\n", ep->name);
+		defer_kevent(dev, WORK_RX_MEMORY);
+quiesce:
+		dev_kfree_skb_any(skb);
+		goto clean;
+
+	/* data overrun */
+	case -EOVERFLOW:
+		dev->net->stats.rx_over_errors++;
+		/* FALLTHROUGH */
+
+	default:
+		dev->net->stats.rx_errors++;
+		DBG(dev, "rx status %d\n", status);
+		break;
+	}
+
+	if (skb)
+		dev_kfree_skb_any(skb);
+	if (!netif_running(dev->net)) {
+clean:
+		spin_lock(&dev->req_lock);
+		list_add(&req->list, &dev->rx_reqs);
+		spin_unlock(&dev->req_lock);
+		req = NULL;
+	}
+	if (req)
+		rx_submit(dev, req, GFP_ATOMIC);
+}
+
+static int prealloc(struct list_head *list, struct usb_ep *ep, unsigned n)
+{
+	unsigned		i;
+	struct usb_request	*req;
+
+	if (!n)
+		return -ENOMEM;
+
+	/* queue/recycle up to N requests */
+	i = n;
+	list_for_each_entry(req, list, list) {
+		if (i-- == 0)
+			goto extra;
+	}
+	while (i--) {
+		req = usb_ep_alloc_request(ep, GFP_ATOMIC);
+		if (!req)
+			return list_empty(list) ? -ENOMEM : 0;
+		list_add(&req->list, list);
+	}
+	return 0;
+
+extra:
+	/* free extras */
+	for (;;) {
+		struct list_head	*next;
+
+		next = req->list.next;
+		list_del(&req->list);
+		usb_ep_free_request(ep, req);
+
+		if (next == list)
+			break;
+
+		req = container_of(next, struct usb_request, list);
+	}
+	return 0;
+}
+
+static int alloc_requests(struct eth_dev *dev, struct gether *link, unsigned n)
+{
+	int	status;
+
+	spin_lock(&dev->req_lock);
+	status = prealloc(&dev->tx_reqs, link->in_ep, n);
+	if (status < 0)
+		goto fail;
+	status = prealloc(&dev->rx_reqs, link->out_ep, n);
+	if (status < 0)
+		goto fail;
+	goto done;
+fail:
+	DBG(dev, "can't alloc requests\n");
+done:
+	spin_unlock(&dev->req_lock);
+	return status;
+}
+
+static void rx_fill(struct eth_dev *dev, gfp_t gfp_flags)
+{
+	struct usb_request	*req;
+	unsigned long		flags;
+
+	/* fill unused rxq slots with some skb */
+	spin_lock_irqsave(&dev->req_lock, flags);
+	while (!list_empty(&dev->rx_reqs)) {
+		req = container_of(dev->rx_reqs.next,
+				struct usb_request, list);
+		list_del_init(&req->list);
+		spin_unlock_irqrestore(&dev->req_lock, flags);
+
+		if (rx_submit(dev, req, gfp_flags) < 0) {
+			defer_kevent(dev, WORK_RX_MEMORY);
+			return;
+		}
+
+		spin_lock_irqsave(&dev->req_lock, flags);
+	}
+	spin_unlock_irqrestore(&dev->req_lock, flags);
+}
+
+static void eth_work(struct work_struct *work)
+{
+	struct eth_dev	*dev = container_of(work, struct eth_dev, work);
+
+	if (test_and_clear_bit(WORK_RX_MEMORY, &dev->todo)) {
+		if (netif_running(dev->net))
+			rx_fill(dev, GFP_KERNEL);
+	}
+
+	if (dev->todo)
+		DBG(dev, "work done, flags = 0x%lx\n", dev->todo);
+}
+
+static void tx_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct sk_buff	*skb = req->context;
+	struct eth_dev	*dev = ep->driver_data;
+
+	switch (req->status) {
+	default:
+		dev->net->stats.tx_errors++;
+		VDBG(dev, "tx err %d\n", req->status);
+		/* FALLTHROUGH */
+	case -ECONNRESET:		/* unlink */
+	case -ESHUTDOWN:		/* disconnect etc */
+		break;
+	case 0:
+		dev->net->stats.tx_bytes += skb->len;
+	}
+	dev->net->stats.tx_packets++;
+
+	spin_lock(&dev->req_lock);
+	list_add(&req->list, &dev->tx_reqs);
+	spin_unlock(&dev->req_lock);
+	dev_kfree_skb_any(skb);
+
+	atomic_dec(&dev->tx_qlen);
+	if (netif_carrier_ok(dev->net))
+		netif_wake_queue(dev->net);
+}
+
+static inline int is_promisc(u16 cdc_filter)
+{
+	return cdc_filter & USB_CDC_PACKET_TYPE_PROMISCUOUS;
+}
+
+static int eth_start_xmit(struct sk_buff *skb, struct net_device *net)
+{
+	struct eth_dev		*dev = netdev_priv(net);
+	int			length = skb->len;
+	int			retval;
+	struct usb_request	*req = NULL;
+	unsigned long		flags;
+	struct usb_ep		*in;
+	u16			cdc_filter;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	if (dev->port_usb) {
+		in = dev->port_usb->in_ep;
+		cdc_filter = dev->port_usb->cdc_filter;
+	} else {
+		in = NULL;
+		cdc_filter = 0;
+	}
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	if (!in) {
+		dev_kfree_skb_any(skb);
+		return 0;
+	}
+
+	/* apply outgoing CDC or RNDIS filters */
+	if (!is_promisc(cdc_filter)) {
+		u8		*dest = skb->data;
+
+		if (is_multicast_ether_addr(dest)) {
+			u16	type;
+
+			/* ignores USB_CDC_PACKET_TYPE_MULTICAST and host
+			 * SET_ETHERNET_MULTICAST_FILTERS requests
+			 */
+			if (is_broadcast_ether_addr(dest))
+				type = USB_CDC_PACKET_TYPE_BROADCAST;
+			else
+				type = USB_CDC_PACKET_TYPE_ALL_MULTICAST;
+			if (!(cdc_filter & type)) {
+				dev_kfree_skb_any(skb);
+				return 0;
+			}
+		}
+		/* ignores USB_CDC_PACKET_TYPE_DIRECTED */
+	}
+
+	spin_lock_irqsave(&dev->req_lock, flags);
+	/*
+	 * this freelist can be empty if an interrupt triggered disconnect()
+	 * and reconfigured the gadget (shutting down this queue) after the
+	 * network stack decided to xmit but before we got the spinlock.
+	 */
+	if (list_empty(&dev->tx_reqs)) {
+		spin_unlock_irqrestore(&dev->req_lock, flags);
+		return 1;
+	}
+
+	req = container_of(dev->tx_reqs.next, struct usb_request, list);
+	list_del(&req->list);
+
+	/* temporarily stop TX queue when the freelist empties */
+	if (list_empty(&dev->tx_reqs))
+		netif_stop_queue(net);
+	spin_unlock_irqrestore(&dev->req_lock, flags);
+
+	/* no buffer copies needed, unless the network stack did it
+	 * or the hardware can't use skb buffers.
+	 * or there's not enough space for extra headers we need
+	 */
+	if (dev->wrap) {
+		struct sk_buff	*skb_new;
+
+		skb_new = dev->wrap(skb);
+		if (!skb_new)
+			goto drop;
+
+		dev_kfree_skb_any(skb);
+		skb = skb_new;
+		length = skb->len;
+	}
+	req->buf = skb->data;
+	req->context = skb;
+	req->complete = tx_complete;
+
+	/* use zlp framing on tx for strict CDC-Ether conformance,
+	 * though any robust network rx path ignores extra padding.
+	 * and some hardware doesn't like to write zlps.
+	 */
+	req->zero = 1;
+	if (!dev->zlp && (length % in->maxpacket) == 0)
+		length++;
+
+	req->length = length;
+
+	/* throttle highspeed IRQ rate back slightly */
+	if (gadget_is_dualspeed(dev->gadget))
+		req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH)
+			? ((atomic_read(&dev->tx_qlen) % qmult) != 0)
+			: 0;
+
+	retval = usb_ep_queue(in, req, GFP_ATOMIC);
+	switch (retval) {
+	default:
+		DBG(dev, "tx queue err %d\n", retval);
+		break;
+	case 0:
+		net->trans_start = jiffies;
+		atomic_inc(&dev->tx_qlen);
+	}
+
+	if (retval) {
+drop:
+		dev->net->stats.tx_dropped++;
+		dev_kfree_skb_any(skb);
+		spin_lock_irqsave(&dev->req_lock, flags);
+		if (list_empty(&dev->tx_reqs))
+			netif_start_queue(net);
+		list_add(&req->list, &dev->tx_reqs);
+		spin_unlock_irqrestore(&dev->req_lock, flags);
+	}
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void eth_start(struct eth_dev *dev, gfp_t gfp_flags)
+{
+	DBG(dev, "%s\n", __func__);
+
+	/* fill the rx queue */
+	rx_fill(dev, gfp_flags);
+
+	/* and open the tx floodgates */
+	atomic_set(&dev->tx_qlen, 0);
+	netif_wake_queue(dev->net);
+}
+
+static int eth_open(struct net_device *net)
+{
+	struct eth_dev	*dev = netdev_priv(net);
+	struct gether	*link;
+
+	DBG(dev, "%s\n", __func__);
+	if (netif_carrier_ok(dev->net))
+		eth_start(dev, GFP_KERNEL);
+
+	spin_lock_irq(&dev->lock);
+	link = dev->port_usb;
+	if (link && link->open)
+		link->open(link);
+	spin_unlock_irq(&dev->lock);
+
+	return 0;
+}
+
+static int eth_stop(struct net_device *net)
+{
+	struct eth_dev	*dev = netdev_priv(net);
+	unsigned long	flags;
+
+	VDBG(dev, "%s\n", __func__);
+	netif_stop_queue(net);
+
+	DBG(dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n",
+		dev->net->stats.rx_packets, dev->net->stats.tx_packets,
+		dev->net->stats.rx_errors, dev->net->stats.tx_errors
+		);
+
+	/* ensure there are no more active requests */
+	spin_lock_irqsave(&dev->lock, flags);
+	if (dev->port_usb) {
+		struct gether	*link = dev->port_usb;
+
+		if (link->close)
+			link->close(link);
+
+		/* NOTE:  we have no abort-queue primitive we could use
+		 * to cancel all pending I/O.  Instead, we disable then
+		 * reenable the endpoints ... this idiom may leave toggle
+		 * wrong, but that's a self-correcting error.
+		 *
+		 * REVISIT:  we *COULD* just let the transfers complete at
+		 * their own pace; the network stack can handle old packets.
+		 * For the moment we leave this here, since it works.
+		 */
+		usb_ep_disable(link->in_ep);
+		usb_ep_disable(link->out_ep);
+		if (netif_carrier_ok(net)) {
+			DBG(dev, "host still using in/out endpoints\n");
+			usb_ep_enable(link->in_ep, link->in);
+			usb_ep_enable(link->out_ep, link->out);
+		}
+	}
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */
+static char *dev_addr;
+module_param(dev_addr, charp, S_IRUGO);
+MODULE_PARM_DESC(dev_addr, "Device Ethernet Address");
+
+/* this address is invisible to ifconfig */
+static char *host_addr;
+module_param(host_addr, charp, S_IRUGO);
+MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
+
+
+static u8 __init nibble(unsigned char c)
+{
+	if (isdigit(c))
+		return c - '0';
+	c = toupper(c);
+	if (isxdigit(c))
+		return 10 + c - 'A';
+	return 0;
+}
+
+static int __init get_ether_addr(const char *str, u8 *dev_addr)
+{
+	if (str) {
+		unsigned	i;
+
+		for (i = 0; i < 6; i++) {
+			unsigned char num;
+
+			if ((*str == '.') || (*str == ':'))
+				str++;
+			num = nibble(*str++) << 4;
+			num |= (nibble(*str++));
+			dev_addr [i] = num;
+		}
+		if (is_valid_ether_addr(dev_addr))
+			return 0;
+	}
+	random_ether_addr(dev_addr);
+	return 1;
+}
+
+static struct eth_dev *the_dev;
+
+
+/**
+ * gether_setup - initialize one ethernet-over-usb link
+ * @g: gadget to associated with these links
+ * @ethaddr: NULL, or a buffer in which the ethernet address of the
+ *	host side of the link is recorded
+ * Context: may sleep
+ *
+ * This sets up the single network link that may be exported by a
+ * gadget driver using this framework.  The link layer addresses are
+ * set up using module parameters.
+ *
+ * Returns negative errno, or zero on success
+ */
+int __init gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN])
+{
+	struct eth_dev		*dev;
+	struct net_device	*net;
+	int			status;
+
+	if (the_dev)
+		return -EBUSY;
+
+	net = alloc_etherdev(sizeof *dev);
+	if (!net)
+		return -ENOMEM;
+
+	dev = netdev_priv(net);
+	spin_lock_init(&dev->lock);
+	spin_lock_init(&dev->req_lock);
+	INIT_WORK(&dev->work, eth_work);
+	INIT_LIST_HEAD(&dev->tx_reqs);
+	INIT_LIST_HEAD(&dev->rx_reqs);
+
+	/* network device setup */
+	dev->net = net;
+	strcpy(net->name, "usb%d");
+
+	if (get_ether_addr(dev_addr, net->dev_addr))
+		dev_warn(&g->dev,
+			"using random %s ethernet address\n", "self");
+	if (get_ether_addr(host_addr, dev->host_mac))
+		dev_warn(&g->dev,
+			"using random %s ethernet address\n", "host");
+
+	if (ethaddr)
+		memcpy(ethaddr, dev->host_mac, ETH_ALEN);
+
+	net->change_mtu = eth_change_mtu;
+	net->hard_start_xmit = eth_start_xmit;
+	net->open = eth_open;
+	net->stop = eth_stop;
+	/* watchdog_timeo, tx_timeout ... */
+	/* set_multicast_list */
+	SET_ETHTOOL_OPS(net, &ops);
+
+	/* two kinds of host-initiated state changes:
+	 *  - iff DATA transfer is active, carrier is "on"
+	 *  - tx queueing enabled if open *and* carrier is "on"
+	 */
+	netif_stop_queue(net);
+	netif_carrier_off(net);
+
+	dev->gadget = g;
+	SET_NETDEV_DEV(net, &g->dev);
+
+	status = register_netdev(net);
+	if (status < 0) {
+		dev_dbg(&g->dev, "register_netdev failed, %d\n", status);
+		free_netdev(net);
+	} else {
+		DECLARE_MAC_BUF(tmp);
+
+		INFO(dev, "MAC %s\n", print_mac(tmp, net->dev_addr));
+		INFO(dev, "HOST MAC %s\n", print_mac(tmp, dev->host_mac));
+
+		the_dev = dev;
+	}
+
+	return status;
+}
+
+/**
+ * gether_cleanup - remove Ethernet-over-USB device
+ * Context: may sleep
+ *
+ * This is called to free all resources allocated by @gether_setup().
+ */
+void gether_cleanup(void)
+{
+	if (!the_dev)
+		return;
+
+	unregister_netdev(the_dev->net);
+	free_netdev(the_dev->net);
+
+	/* assuming we used keventd, it must quiesce too */
+	flush_scheduled_work();
+
+	the_dev = NULL;
+}
+
+
+/**
+ * gether_connect - notify network layer that USB link is active
+ * @link: the USB link, set up with endpoints, descriptors matching
+ *	current device speed, and any framing wrapper(s) set up.
+ * Context: irqs blocked
+ *
+ * This is called to activate endpoints and let the network layer know
+ * the connection is active ("carrier detect").  It may cause the I/O
+ * queues to open and start letting network packets flow, but will in
+ * any case activate the endpoints so that they respond properly to the
+ * USB host.
+ *
+ * Verify net_device pointer returned using IS_ERR().  If it doesn't
+ * indicate some error code (negative errno), ep->driver_data values
+ * have been overwritten.
+ */
+struct net_device *gether_connect(struct gether *link)
+{
+	struct eth_dev		*dev = the_dev;
+	int			result = 0;
+
+	if (!dev)
+		return ERR_PTR(-EINVAL);
+
+	link->in_ep->driver_data = dev;
+	result = usb_ep_enable(link->in_ep, link->in);
+	if (result != 0) {
+		DBG(dev, "enable %s --> %d\n",
+			link->in_ep->name, result);
+		goto fail0;
+	}
+
+	link->out_ep->driver_data = dev;
+	result = usb_ep_enable(link->out_ep, link->out);
+	if (result != 0) {
+		DBG(dev, "enable %s --> %d\n",
+			link->out_ep->name, result);
+		goto fail1;
+	}
+
+	if (result == 0)
+		result = alloc_requests(dev, link, qlen(dev->gadget));
+
+	if (result == 0) {
+		dev->zlp = link->is_zlp_ok;
+		DBG(dev, "qlen %d\n", qlen(dev->gadget));
+
+		dev->header_len = link->header_len;
+		dev->unwrap = link->unwrap;
+		dev->wrap = link->wrap;
+
+		spin_lock(&dev->lock);
+		dev->port_usb = link;
+		link->ioport = dev;
+		spin_unlock(&dev->lock);
+
+		netif_carrier_on(dev->net);
+		if (netif_running(dev->net))
+			eth_start(dev, GFP_ATOMIC);
+
+	/* on error, disable any endpoints  */
+	} else {
+		(void) usb_ep_disable(link->out_ep);
+fail1:
+		(void) usb_ep_disable(link->in_ep);
+	}
+fail0:
+	/* caller is responsible for cleanup on error */
+	if (result < 0)
+		return ERR_PTR(result);
+	return dev->net;
+}
+
+/**
+ * gether_disconnect - notify network layer that USB link is inactive
+ * @link: the USB link, on which gether_connect() was called
+ * Context: irqs blocked
+ *
+ * This is called to deactivate endpoints and let the network layer know
+ * the connection went inactive ("no carrier").
+ *
+ * On return, the state is as if gether_connect() had never been called.
+ * The endpoints are inactive, and accordingly without active USB I/O.
+ * Pointers to endpoint descriptors and endpoint private data are nulled.
+ */
+void gether_disconnect(struct gether *link)
+{
+	struct eth_dev		*dev = link->ioport;
+	struct usb_request	*req;
+
+	WARN_ON(!dev);
+	if (!dev)
+		return;
+
+	DBG(dev, "%s\n", __func__);
+
+	netif_stop_queue(dev->net);
+	netif_carrier_off(dev->net);
+
+	/* disable endpoints, forcing (synchronous) completion
+	 * of all pending i/o.  then free the request objects
+	 * and forget about the endpoints.
+	 */
+	usb_ep_disable(link->in_ep);
+	spin_lock(&dev->req_lock);
+	while (!list_empty(&dev->tx_reqs)) {
+		req = container_of(dev->tx_reqs.next,
+					struct usb_request, list);
+		list_del(&req->list);
+
+		spin_unlock(&dev->req_lock);
+		usb_ep_free_request(link->in_ep, req);
+		spin_lock(&dev->req_lock);
+	}
+	spin_unlock(&dev->req_lock);
+	link->in_ep->driver_data = NULL;
+	link->in = NULL;
+
+	usb_ep_disable(link->out_ep);
+	spin_lock(&dev->req_lock);
+	while (!list_empty(&dev->rx_reqs)) {
+		req = container_of(dev->rx_reqs.next,
+					struct usb_request, list);
+		list_del(&req->list);
+
+		spin_unlock(&dev->req_lock);
+		usb_ep_free_request(link->out_ep, req);
+		spin_lock(&dev->req_lock);
+	}
+	spin_unlock(&dev->req_lock);
+	link->out_ep->driver_data = NULL;
+	link->out = NULL;
+
+	/* finish forgetting about this USB link episode */
+	dev->header_len = 0;
+	dev->unwrap = NULL;
+	dev->wrap = NULL;
+
+	spin_lock(&dev->lock);
+	dev->port_usb = NULL;
+	link->ioport = NULL;
+	spin_unlock(&dev->lock);
+}
diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h
new file mode 100644
index 0000000..0d1f7ae
--- /dev/null
+++ b/drivers/usb/gadget/u_ether.h
@@ -0,0 +1,127 @@
+/*
+ * u_ether.h -- interface to USB gadget "ethernet link" utilities
+ *
+ * Copyright (C) 2003-2005,2008 David Brownell
+ * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __U_ETHER_H
+#define __U_ETHER_H
+
+#include <linux/err.h>
+#include <linux/if_ether.h>
+#include <linux/usb/composite.h>
+#include <linux/usb/cdc.h>
+
+#include "gadget_chips.h"
+
+
+/*
+ * This represents the USB side of an "ethernet" link, managed by a USB
+ * function which provides control and (maybe) framing.  Two functions
+ * in different configurations could share the same ethernet link/netdev,
+ * using different host interaction models.
+ *
+ * There is a current limitation that only one instance of this link may
+ * be present in any given configuration.  When that's a problem, network
+ * layer facilities can be used to package multiple logical links on this
+ * single "physical" one.
+ */
+struct gether {
+	struct usb_function		func;
+
+	/* updated by gether_{connect,disconnect} */
+	struct eth_dev			*ioport;
+
+	/* endpoints handle full and/or high speeds */
+	struct usb_ep			*in_ep;
+	struct usb_ep			*out_ep;
+
+	/* descriptors match device speed at gether_connect() time */
+	struct usb_endpoint_descriptor	*in;
+	struct usb_endpoint_descriptor	*out;
+
+	bool				is_zlp_ok;
+
+	u16				cdc_filter;
+
+	/* hooks for added framing, as needed for RNDIS and EEM.
+	 * we currently don't support multiple frames per SKB.
+	 */
+	u32				header_len;
+	struct sk_buff			*(*wrap)(struct sk_buff *skb);
+	int				(*unwrap)(struct sk_buff *skb);
+
+	/* called on network open/close */
+	void				(*open)(struct gether *);
+	void				(*close)(struct gether *);
+};
+
+#define	DEFAULT_FILTER	(USB_CDC_PACKET_TYPE_BROADCAST \
+			|USB_CDC_PACKET_TYPE_ALL_MULTICAST \
+			|USB_CDC_PACKET_TYPE_PROMISCUOUS \
+			|USB_CDC_PACKET_TYPE_DIRECTED)
+
+
+/* netdev setup/teardown as directed by the gadget driver */
+int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN]);
+void gether_cleanup(void);
+
+/* connect/disconnect is handled by individual functions */
+struct net_device *gether_connect(struct gether *);
+void gether_disconnect(struct gether *);
+
+/* Some controllers can't support CDC Ethernet (ECM) ... */
+static inline bool can_support_ecm(struct usb_gadget *gadget)
+{
+	if (!gadget_supports_altsettings(gadget))
+		return false;
+
+	/* SA1100 can do ECM, *without* status endpoint ... but we'll
+	 * only use it in non-ECM mode for backwards compatibility
+	 * (and since we currently require a status endpoint)
+	 */
+	if (gadget_is_sa1100(gadget))
+		return false;
+
+	/* Everything else is *presumably* fine ... but this is a bit
+	 * chancy, so be **CERTAIN** there are no hardware issues with
+	 * your controller.  Add it above if it can't handle CDC.
+	 */
+	return true;
+}
+
+/* each configuration may bind one instance of an ethernet link */
+int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
+int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
+
+#ifdef CONFIG_USB_ETH_RNDIS
+
+int rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
+
+#else
+
+static inline int
+rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+{
+	return 0;
+}
+
+#endif
+
+#endif /* __U_ETHER_H */
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
new file mode 100644
index 0000000..abf9505d
--- /dev/null
+++ b/drivers/usb/gadget/u_serial.c
@@ -0,0 +1,1246 @@
+/*
+ * u_serial.c - utilities for USB gadget "serial port"/TTY support
+ *
+ * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
+ * Copyright (C) 2008 David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
+ *
+ * This code also borrows from usbserial.c, which is
+ * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2000 Peter Berger (pberger@brimson.com)
+ * Copyright (C) 2000 Al Borchers (alborchers@steinerpoint.com)
+ *
+ * This software is distributed under the terms of the GNU General
+ * Public License ("GPL") as published by the Free Software Foundation,
+ * either version 2 of that License or (at your option) any later version.
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+
+#include "u_serial.h"
+
+
+/*
+ * This component encapsulates the TTY layer glue needed to provide basic
+ * "serial port" functionality through the USB gadget stack.  Each such
+ * port is exposed through a /dev/ttyGS* node.
+ *
+ * After initialization (gserial_setup), these TTY port devices stay
+ * available until they are removed (gserial_cleanup).  Each one may be
+ * connected to a USB function (gserial_connect), or disconnected (with
+ * gserial_disconnect) when the USB host issues a config change event.
+ * Data can only flow when the port is connected to the host.
+ *
+ * A given TTY port can be made available in multiple configurations.
+ * For example, each one might expose a ttyGS0 node which provides a
+ * login application.  In one case that might use CDC ACM interface 0,
+ * while another configuration might use interface 3 for that.  The
+ * work to handle that (including descriptor management) is not part
+ * of this component.
+ *
+ * Configurations may expose more than one TTY port.  For example, if
+ * ttyGS0 provides login service, then ttyGS1 might provide dialer access
+ * for a telephone or fax link.  And ttyGS2 might be something that just
+ * needs a simple byte stream interface for some messaging protocol that
+ * is managed in userspace ... OBEX, PTP, and MTP have been mentioned.
+ */
+
+/*
+ * gserial is the lifecycle interface, used by USB functions
+ * gs_port is the I/O nexus, used by the tty driver
+ * tty_struct links to the tty/filesystem framework
+ *
+ * gserial <---> gs_port ... links will be null when the USB link is
+ * inactive; managed by gserial_{connect,disconnect}().
+ *	gserial->ioport == usb_ep->driver_data ... gs_port
+ *	gs_port->port_usb ... gserial
+ *
+ * gs_port <---> tty_struct ... links will be null when the TTY file
+ * isn't opened; managed by gs_open()/gs_close()
+ *	gserial->port_tty ... tty_struct
+ *	tty_struct->driver_data ... gserial
+ */
+
+/* RX and TX queues can buffer QUEUE_SIZE packets before they hit the
+ * next layer of buffering.  For TX that's a circular buffer; for RX
+ * consider it a NOP.  A third layer is provided by the TTY code.
+ */
+#define QUEUE_SIZE		16
+#define WRITE_BUF_SIZE		8192		/* TX only */
+
+/* circular buffer */
+struct gs_buf {
+	unsigned		buf_size;
+	char			*buf_buf;
+	char			*buf_get;
+	char			*buf_put;
+};
+
+/*
+ * The port structure holds info for each port, one for each minor number
+ * (and thus for each /dev/ node).
+ */
+struct gs_port {
+	spinlock_t		port_lock;	/* guard port_* access */
+
+	struct gserial		*port_usb;
+	struct tty_struct	*port_tty;
+
+	unsigned		open_count;
+	bool			openclose;	/* open/close in progress */
+	u8			port_num;
+
+	wait_queue_head_t	close_wait;	/* wait for last close */
+
+	struct list_head	read_pool;
+	struct tasklet_struct	push;
+
+	struct list_head	write_pool;
+	struct gs_buf		port_write_buf;
+	wait_queue_head_t	drain_wait;	/* wait while writes drain */
+
+	/* REVISIT this state ... */
+	struct usb_cdc_line_coding port_line_coding;	/* 8-N-1 etc */
+};
+
+/* increase N_PORTS if you need more */
+#define N_PORTS		4
+static struct portmaster {
+	struct mutex	lock;			/* protect open/close */
+	struct gs_port	*port;
+} ports[N_PORTS];
+static unsigned	n_ports;
+
+#define GS_CLOSE_TIMEOUT		15		/* seconds */
+
+
+
+#ifdef VERBOSE_DEBUG
+#define pr_vdebug(fmt, arg...) \
+	pr_debug(fmt, ##arg)
+#else
+#define pr_vdebug(fmt, arg...) \
+	({ if (0) pr_debug(fmt, ##arg); })
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/* Circular Buffer */
+
+/*
+ * gs_buf_alloc
+ *
+ * Allocate a circular buffer and all associated memory.
+ */
+static int gs_buf_alloc(struct gs_buf *gb, unsigned size)
+{
+	gb->buf_buf = kmalloc(size, GFP_KERNEL);
+	if (gb->buf_buf == NULL)
+		return -ENOMEM;
+
+	gb->buf_size = size;
+	gb->buf_put = gb->buf_buf;
+	gb->buf_get = gb->buf_buf;
+
+	return 0;
+}
+
+/*
+ * gs_buf_free
+ *
+ * Free the buffer and all associated memory.
+ */
+static void gs_buf_free(struct gs_buf *gb)
+{
+	kfree(gb->buf_buf);
+	gb->buf_buf = NULL;
+}
+
+/*
+ * gs_buf_clear
+ *
+ * Clear out all data in the circular buffer.
+ */
+static void gs_buf_clear(struct gs_buf *gb)
+{
+	gb->buf_get = gb->buf_put;
+	/* equivalent to a get of all data available */
+}
+
+/*
+ * gs_buf_data_avail
+ *
+ * Return the number of bytes of data available in the circular
+ * buffer.
+ */
+static unsigned gs_buf_data_avail(struct gs_buf *gb)
+{
+	return (gb->buf_size + gb->buf_put - gb->buf_get) % gb->buf_size;
+}
+
+/*
+ * gs_buf_space_avail
+ *
+ * Return the number of bytes of space available in the circular
+ * buffer.
+ */
+static unsigned gs_buf_space_avail(struct gs_buf *gb)
+{
+	return (gb->buf_size + gb->buf_get - gb->buf_put - 1) % gb->buf_size;
+}
+
+/*
+ * gs_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
+gs_buf_put(struct gs_buf *gb, const char *buf, unsigned count)
+{
+	unsigned len;
+
+	len  = gs_buf_space_avail(gb);
+	if (count > len)
+		count = len;
+
+	if (count == 0)
+		return 0;
+
+	len = gb->buf_buf + gb->buf_size - gb->buf_put;
+	if (count > len) {
+		memcpy(gb->buf_put, buf, len);
+		memcpy(gb->buf_buf, buf+len, count - len);
+		gb->buf_put = gb->buf_buf + count - len;
+	} else {
+		memcpy(gb->buf_put, buf, count);
+		if (count < len)
+			gb->buf_put += count;
+		else /* count == len */
+			gb->buf_put = gb->buf_buf;
+	}
+
+	return count;
+}
+
+/*
+ * gs_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
+gs_buf_get(struct gs_buf *gb, char *buf, unsigned count)
+{
+	unsigned len;
+
+	len = gs_buf_data_avail(gb);
+	if (count > len)
+		count = len;
+
+	if (count == 0)
+		return 0;
+
+	len = gb->buf_buf + gb->buf_size - gb->buf_get;
+	if (count > len) {
+		memcpy(buf, gb->buf_get, len);
+		memcpy(buf+len, gb->buf_buf, count - len);
+		gb->buf_get = gb->buf_buf + count - len;
+	} else {
+		memcpy(buf, gb->buf_get, count);
+		if (count < len)
+			gb->buf_get += count;
+		else /* count == len */
+			gb->buf_get = gb->buf_buf;
+	}
+
+	return count;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* I/O glue between TTY (upper) and USB function (lower) driver layers */
+
+/*
+ * gs_alloc_req
+ *
+ * Allocate a usb_request and its buffer.  Returns a pointer to the
+ * usb_request or NULL if there is an error.
+ */
+static struct usb_request *
+gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags)
+{
+	struct usb_request *req;
+
+	req = usb_ep_alloc_request(ep, kmalloc_flags);
+
+	if (req != NULL) {
+		req->length = len;
+		req->buf = kmalloc(len, kmalloc_flags);
+		if (req->buf == NULL) {
+			usb_ep_free_request(ep, req);
+			return NULL;
+		}
+	}
+
+	return req;
+}
+
+/*
+ * gs_free_req
+ *
+ * Free a usb_request and its buffer.
+ */
+static void gs_free_req(struct usb_ep *ep, struct usb_request *req)
+{
+	kfree(req->buf);
+	usb_ep_free_request(ep, req);
+}
+
+/*
+ * gs_send_packet
+ *
+ * If there is data to send, a packet is built in the given
+ * buffer and the size is returned.  If there is no data to
+ * send, 0 is returned.
+ *
+ * Called with port_lock held.
+ */
+static unsigned
+gs_send_packet(struct gs_port *port, char *packet, unsigned size)
+{
+	unsigned len;
+
+	len = gs_buf_data_avail(&port->port_write_buf);
+	if (len < size)
+		size = len;
+	if (size != 0)
+		size = gs_buf_get(&port->port_write_buf, packet, size);
+	return size;
+}
+
+/*
+ * gs_start_tx
+ *
+ * This function finds available write requests, calls
+ * gs_send_packet to fill these packets with data, and
+ * continues until either there are no more write requests
+ * available or no more data to send.  This function is
+ * run whenever data arrives or write requests are available.
+ *
+ * Context: caller owns port_lock; port_usb is non-null.
+ */
+static int gs_start_tx(struct gs_port *port)
+/*
+__releases(&port->port_lock)
+__acquires(&port->port_lock)
+*/
+{
+	struct list_head	*pool = &port->write_pool;
+	struct usb_ep		*in = port->port_usb->in;
+	int			status = 0;
+	bool			do_tty_wake = false;
+
+	while (!list_empty(pool)) {
+		struct usb_request	*req;
+		int			len;
+
+		req = list_entry(pool->next, struct usb_request, list);
+		len = gs_send_packet(port, req->buf, in->maxpacket);
+		if (len == 0) {
+			wake_up_interruptible(&port->drain_wait);
+			break;
+		}
+		do_tty_wake = true;
+
+		req->length = len;
+		list_del(&req->list);
+
+#ifdef VERBOSE_DEBUG
+		pr_debug("%s: %s, len=%d, 0x%02x 0x%02x 0x%02x ...\n",
+				__func__, in->name, len, *((u8 *)req->buf),
+				*((u8 *)req->buf+1), *((u8 *)req->buf+2));
+#endif
+
+		/* Drop lock while we call out of driver; completions
+		 * could be issued while we do so.  Disconnection may
+		 * happen too; maybe immediately before we queue this!
+		 *
+		 * NOTE that we may keep sending data for a while after
+		 * the TTY closed (dev->ioport->port_tty is NULL).
+		 */
+		spin_unlock(&port->port_lock);
+		status = usb_ep_queue(in, req, GFP_ATOMIC);
+		spin_lock(&port->port_lock);
+
+		if (status) {
+			pr_debug("%s: %s %s err %d\n",
+					__func__, "queue", in->name, status);
+			list_add(&req->list, pool);
+			break;
+		}
+
+		/* abort immediately after disconnect */
+		if (!port->port_usb)
+			break;
+	}
+
+	if (do_tty_wake && port->port_tty)
+		tty_wakeup(port->port_tty);
+	return status;
+}
+
+static void gs_rx_push(unsigned long _port)
+{
+	struct gs_port		*port = (void *)_port;
+	struct tty_struct	*tty = port->port_tty;
+
+	/* With low_latency, tty_flip_buffer_push() doesn't put its
+	 * real work through a workqueue, so the ldisc has a better
+	 * chance to keep up with peak USB data rates.
+	 */
+	if (tty) {
+		tty_flip_buffer_push(tty);
+		wake_up_interruptible(&tty->read_wait);
+	}
+}
+
+/*
+ * gs_recv_packet
+ *
+ * Called for each USB packet received.  Reads the packet
+ * header and stuffs the data in the appropriate tty buffer.
+ * Returns 0 if successful, or a negative error number.
+ *
+ * Called during USB completion routine, on interrupt time.
+ * With port_lock.
+ */
+static int gs_recv_packet(struct gs_port *port, char *packet, unsigned size)
+{
+	unsigned		len;
+	struct tty_struct	*tty;
+
+	/* I/O completions can continue for a while after close(), until the
+	 * request queue empties.  Just discard any data we receive, until
+	 * something reopens this TTY ... as if there were no HW flow control.
+	 */
+	tty = port->port_tty;
+	if (tty == NULL) {
+		pr_vdebug("%s: ttyGS%d, after close\n",
+				__func__, port->port_num);
+		return -EIO;
+	}
+
+	len = tty_insert_flip_string(tty, packet, size);
+	if (len > 0)
+		tasklet_schedule(&port->push);
+	if (len < size)
+		pr_debug("%s: ttyGS%d, drop %d bytes\n",
+				__func__, port->port_num, size - len);
+	return 0;
+}
+
+/*
+ * Context: caller owns port_lock, and port_usb is set
+ */
+static unsigned gs_start_rx(struct gs_port *port)
+/*
+__releases(&port->port_lock)
+__acquires(&port->port_lock)
+*/
+{
+	struct list_head	*pool = &port->read_pool;
+	struct usb_ep		*out = port->port_usb->out;
+	unsigned		started = 0;
+
+	while (!list_empty(pool)) {
+		struct usb_request	*req;
+		int			status;
+		struct tty_struct	*tty;
+
+		/* no more rx if closed or throttled */
+		tty = port->port_tty;
+		if (!tty || test_bit(TTY_THROTTLED, &tty->flags))
+			break;
+
+		req = list_entry(pool->next, struct usb_request, list);
+		list_del(&req->list);
+		req->length = out->maxpacket;
+
+		/* drop lock while we call out; the controller driver
+		 * may need to call us back (e.g. for disconnect)
+		 */
+		spin_unlock(&port->port_lock);
+		status = usb_ep_queue(out, req, GFP_ATOMIC);
+		spin_lock(&port->port_lock);
+
+		if (status) {
+			pr_debug("%s: %s %s err %d\n",
+					__func__, "queue", out->name, status);
+			list_add(&req->list, pool);
+			break;
+		}
+		started++;
+
+		/* abort immediately after disconnect */
+		if (!port->port_usb)
+			break;
+	}
+	return started;
+}
+
+static void gs_read_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	int		status;
+	struct gs_port	*port = ep->driver_data;
+
+	spin_lock(&port->port_lock);
+	list_add(&req->list, &port->read_pool);
+
+	switch (req->status) {
+	case 0:
+		/* normal completion */
+		status = gs_recv_packet(port, req->buf, req->actual);
+		if (status && status != -EIO)
+			pr_debug("%s: %s %s err %d\n",
+				__func__, "recv", ep->name, status);
+		gs_start_rx(port);
+		break;
+
+	case -ESHUTDOWN:
+		/* disconnect */
+		pr_vdebug("%s: %s shutdown\n", __func__, ep->name);
+		break;
+
+	default:
+		/* presumably a transient fault */
+		pr_warning("%s: unexpected %s status %d\n",
+				__func__, ep->name, req->status);
+		gs_start_rx(port);
+		break;
+	}
+	spin_unlock(&port->port_lock);
+}
+
+static void gs_write_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct gs_port	*port = ep->driver_data;
+
+	spin_lock(&port->port_lock);
+	list_add(&req->list, &port->write_pool);
+
+	switch (req->status) {
+	default:
+		/* presumably a transient fault */
+		pr_warning("%s: unexpected %s status %d\n",
+				__func__, ep->name, req->status);
+		/* FALL THROUGH */
+	case 0:
+		/* normal completion */
+		gs_start_tx(port);
+		break;
+
+	case -ESHUTDOWN:
+		/* disconnect */
+		pr_vdebug("%s: %s shutdown\n", __func__, ep->name);
+		break;
+	}
+
+	spin_unlock(&port->port_lock);
+}
+
+static void gs_free_requests(struct usb_ep *ep, struct list_head *head)
+{
+	struct usb_request	*req;
+
+	while (!list_empty(head)) {
+		req = list_entry(head->next, struct usb_request, list);
+		list_del(&req->list);
+		gs_free_req(ep, req);
+	}
+}
+
+static int gs_alloc_requests(struct usb_ep *ep, struct list_head *head,
+		void (*fn)(struct usb_ep *, struct usb_request *))
+{
+	int			i;
+	struct usb_request	*req;
+
+	/* Pre-allocate up to QUEUE_SIZE transfers, but if we can't
+	 * do quite that many this time, don't fail ... we just won't
+	 * be as speedy as we might otherwise be.
+	 */
+	for (i = 0; i < QUEUE_SIZE; i++) {
+		req = gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC);
+		if (!req)
+			return list_empty(head) ? -ENOMEM : 0;
+		req->complete = fn;
+		list_add_tail(&req->list, head);
+	}
+	return 0;
+}
+
+/**
+ * gs_start_io - start USB I/O streams
+ * @dev: encapsulates endpoints to use
+ * Context: holding port_lock; port_tty and port_usb are non-null
+ *
+ * We only start I/O when something is connected to both sides of
+ * this port.  If nothing is listening on the host side, we may
+ * be pointlessly filling up our TX buffers and FIFO.
+ */
+static int gs_start_io(struct gs_port *port)
+{
+	struct list_head	*head = &port->read_pool;
+	struct usb_ep		*ep = port->port_usb->out;
+	int			status;
+	unsigned		started;
+
+	/* Allocate RX and TX I/O buffers.  We can't easily do this much
+	 * earlier (with GFP_KERNEL) because the requests are coupled to
+	 * endpoints, as are the packet sizes we'll be using.  Different
+	 * configurations may use different endpoints with a given port;
+	 * and high speed vs full speed changes packet sizes too.
+	 */
+	status = gs_alloc_requests(ep, head, gs_read_complete);
+	if (status)
+		return status;
+
+	status = gs_alloc_requests(port->port_usb->in, &port->write_pool,
+			gs_write_complete);
+	if (status) {
+		gs_free_requests(ep, head);
+		return status;
+	}
+
+	/* queue read requests */
+	started = gs_start_rx(port);
+
+	/* unblock any pending writes into our circular buffer */
+	if (started) {
+		tty_wakeup(port->port_tty);
+	} else {
+		gs_free_requests(ep, head);
+		gs_free_requests(port->port_usb->in, &port->write_pool);
+	}
+
+	return started ? 0 : status;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* TTY Driver */
+
+/*
+ * gs_open sets up the link between a gs_port and its associated TTY.
+ * That link is broken *only* by TTY close(), and all driver methods
+ * know that.
+ */
+static int gs_open(struct tty_struct *tty, struct file *file)
+{
+	int		port_num = tty->index;
+	struct gs_port	*port;
+	int		status;
+
+	if (port_num < 0 || port_num >= n_ports)
+		return -ENXIO;
+
+	do {
+		mutex_lock(&ports[port_num].lock);
+		port = ports[port_num].port;
+		if (!port)
+			status = -ENODEV;
+		else {
+			spin_lock_irq(&port->port_lock);
+
+			/* already open?  Great. */
+			if (port->open_count) {
+				status = 0;
+				port->open_count++;
+
+			/* currently opening/closing? wait ... */
+			} else if (port->openclose) {
+				status = -EBUSY;
+
+			/* ... else we do the work */
+			} else {
+				status = -EAGAIN;
+				port->openclose = true;
+			}
+			spin_unlock_irq(&port->port_lock);
+		}
+		mutex_unlock(&ports[port_num].lock);
+
+		switch (status) {
+		default:
+			/* fully handled */
+			return status;
+		case -EAGAIN:
+			/* must do the work */
+			break;
+		case -EBUSY:
+			/* wait for EAGAIN task to finish */
+			msleep(1);
+			/* REVISIT could have a waitchannel here, if
+			 * concurrent open performance is important
+			 */
+			break;
+		}
+	} while (status != -EAGAIN);
+
+	/* Do the "real open" */
+	spin_lock_irq(&port->port_lock);
+
+	/* allocate circular buffer on first open */
+	if (port->port_write_buf.buf_buf == NULL) {
+
+		spin_unlock_irq(&port->port_lock);
+		status = gs_buf_alloc(&port->port_write_buf, WRITE_BUF_SIZE);
+		spin_lock_irq(&port->port_lock);
+
+		if (status) {
+			pr_debug("gs_open: ttyGS%d (%p,%p) no buffer\n",
+				port->port_num, tty, file);
+			port->openclose = false;
+			goto exit_unlock_port;
+		}
+	}
+
+	/* REVISIT if REMOVED (ports[].port NULL), abort the open
+	 * to let rmmod work faster (but this way isn't wrong).
+	 */
+
+	/* REVISIT maybe wait for "carrier detect" */
+
+	tty->driver_data = port;
+	port->port_tty = tty;
+
+	port->open_count = 1;
+	port->openclose = false;
+
+	/* low_latency means ldiscs work in tasklet context, without
+	 * needing a workqueue schedule ... easier to keep up.
+	 */
+	tty->low_latency = 1;
+
+	/* if connected, start the I/O stream */
+	if (port->port_usb) {
+		pr_debug("gs_open: start ttyGS%d\n", port->port_num);
+		gs_start_io(port);
+
+		/* REVISIT for ACM, issue "network connected" event */
+	}
+
+	pr_debug("gs_open: ttyGS%d (%p,%p)\n", port->port_num, tty, file);
+
+	status = 0;
+
+exit_unlock_port:
+	spin_unlock_irq(&port->port_lock);
+	return status;
+}
+
+static int gs_writes_finished(struct gs_port *p)
+{
+	int cond;
+
+	/* return true on disconnect or empty buffer */
+	spin_lock_irq(&p->port_lock);
+	cond = (p->port_usb == NULL) || !gs_buf_data_avail(&p->port_write_buf);
+	spin_unlock_irq(&p->port_lock);
+
+	return cond;
+}
+
+static void gs_close(struct tty_struct *tty, struct file *file)
+{
+	struct gs_port *port = tty->driver_data;
+
+	spin_lock_irq(&port->port_lock);
+
+	if (port->open_count != 1) {
+		if (port->open_count == 0)
+			WARN_ON(1);
+		else
+			--port->open_count;
+		goto exit;
+	}
+
+	pr_debug("gs_close: ttyGS%d (%p,%p) ...\n", port->port_num, tty, file);
+
+	/* mark port as closing but in use; we can drop port lock
+	 * and sleep if necessary
+	 */
+	port->openclose = true;
+	port->open_count = 0;
+
+	if (port->port_usb)
+		/* REVISIT for ACM, issue "network disconnected" event */;
+
+	/* wait for circular write buffer to drain, disconnect, or at
+	 * most GS_CLOSE_TIMEOUT seconds; then discard the rest
+	 */
+	if (gs_buf_data_avail(&port->port_write_buf) > 0
+			&& port->port_usb) {
+		spin_unlock_irq(&port->port_lock);
+		wait_event_interruptible_timeout(port->drain_wait,
+					gs_writes_finished(port),
+					GS_CLOSE_TIMEOUT * HZ);
+		spin_lock_irq(&port->port_lock);
+	}
+
+	/* Iff we're disconnected, there can be no I/O in flight so it's
+	 * ok to free the circular buffer; else just scrub it.  And don't
+	 * let the push tasklet fire again until we're re-opened.
+	 */
+	if (port->port_usb == NULL)
+		gs_buf_free(&port->port_write_buf);
+	else
+		gs_buf_clear(&port->port_write_buf);
+
+	tasklet_kill(&port->push);
+
+	tty->driver_data = NULL;
+	port->port_tty = NULL;
+
+	port->openclose = false;
+
+	pr_debug("gs_close: ttyGS%d (%p,%p) done!\n",
+			port->port_num, tty, file);
+
+	wake_up_interruptible(&port->close_wait);
+exit:
+	spin_unlock_irq(&port->port_lock);
+}
+
+static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count)
+{
+	struct gs_port	*port = tty->driver_data;
+	unsigned long	flags;
+	int		status;
+
+	pr_vdebug("gs_write: ttyGS%d (%p) writing %d bytes\n",
+			port->port_num, tty, count);
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	if (count)
+		count = gs_buf_put(&port->port_write_buf, buf, count);
+	/* treat count == 0 as flush_chars() */
+	if (port->port_usb)
+		status = gs_start_tx(port);
+	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	return count;
+}
+
+static int gs_put_char(struct tty_struct *tty, unsigned char ch)
+{
+	struct gs_port	*port = tty->driver_data;
+	unsigned long	flags;
+	int		status;
+
+	pr_vdebug("gs_put_char: (%d,%p) char=0x%x, called from %p\n",
+		port->port_num, tty, ch, __builtin_return_address(0));
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	status = gs_buf_put(&port->port_write_buf, &ch, 1);
+	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	return status;
+}
+
+static void gs_flush_chars(struct tty_struct *tty)
+{
+	struct gs_port	*port = tty->driver_data;
+	unsigned long	flags;
+
+	pr_vdebug("gs_flush_chars: (%d,%p)\n", port->port_num, tty);
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	if (port->port_usb)
+		gs_start_tx(port);
+	spin_unlock_irqrestore(&port->port_lock, flags);
+}
+
+static int gs_write_room(struct tty_struct *tty)
+{
+	struct gs_port	*port = tty->driver_data;
+	unsigned long	flags;
+	int		room = 0;
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	if (port->port_usb)
+		room = gs_buf_space_avail(&port->port_write_buf);
+	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	pr_vdebug("gs_write_room: (%d,%p) room=%d\n",
+		port->port_num, tty, room);
+
+	return room;
+}
+
+static int gs_chars_in_buffer(struct tty_struct *tty)
+{
+	struct gs_port	*port = tty->driver_data;
+	unsigned long	flags;
+	int		chars = 0;
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	chars = gs_buf_data_avail(&port->port_write_buf);
+	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	pr_vdebug("gs_chars_in_buffer: (%d,%p) chars=%d\n",
+		port->port_num, tty, chars);
+
+	return chars;
+}
+
+/* undo side effects of setting TTY_THROTTLED */
+static void gs_unthrottle(struct tty_struct *tty)
+{
+	struct gs_port		*port = tty->driver_data;
+	unsigned long		flags;
+	unsigned		started = 0;
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	if (port->port_usb)
+		started = gs_start_rx(port);
+	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	pr_vdebug("gs_unthrottle: ttyGS%d, %d packets\n",
+			port->port_num, started);
+}
+
+static const struct tty_operations gs_tty_ops = {
+	.open =			gs_open,
+	.close =		gs_close,
+	.write =		gs_write,
+	.put_char =		gs_put_char,
+	.flush_chars =		gs_flush_chars,
+	.write_room =		gs_write_room,
+	.chars_in_buffer =	gs_chars_in_buffer,
+	.unthrottle =		gs_unthrottle,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static struct tty_driver *gs_tty_driver;
+
+static int __init
+gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
+{
+	struct gs_port	*port;
+
+	port = kzalloc(sizeof(struct gs_port), GFP_KERNEL);
+	if (port == NULL)
+		return -ENOMEM;
+
+	spin_lock_init(&port->port_lock);
+	init_waitqueue_head(&port->close_wait);
+	init_waitqueue_head(&port->drain_wait);
+
+	tasklet_init(&port->push, gs_rx_push, (unsigned long) port);
+
+	INIT_LIST_HEAD(&port->read_pool);
+	INIT_LIST_HEAD(&port->write_pool);
+
+	port->port_num = port_num;
+	port->port_line_coding = *coding;
+
+	ports[port_num].port = port;
+
+	return 0;
+}
+
+/**
+ * gserial_setup - initialize TTY driver for one or more ports
+ * @g: gadget to associate with these ports
+ * @count: how many ports to support
+ * Context: may sleep
+ *
+ * The TTY stack needs to know in advance how many devices it should
+ * plan to manage.  Use this call to set up the ports you will be
+ * exporting through USB.  Later, connect them to functions based
+ * on what configuration is activated by the USB host; and disconnect
+ * them as appropriate.
+ *
+ * An example would be a two-configuration device in which both
+ * configurations expose port 0, but through different functions.
+ * One configuration could even expose port 1 while the other
+ * one doesn't.
+ *
+ * Returns negative errno or zero.
+ */
+int __init gserial_setup(struct usb_gadget *g, unsigned count)
+{
+	unsigned			i;
+	struct usb_cdc_line_coding	coding;
+	int				status;
+
+	if (count == 0 || count > N_PORTS)
+		return -EINVAL;
+
+	gs_tty_driver = alloc_tty_driver(count);
+	if (!gs_tty_driver)
+		return -ENOMEM;
+
+	gs_tty_driver->owner = THIS_MODULE;
+	gs_tty_driver->driver_name = "g_serial";
+	gs_tty_driver->name = "ttyGS";
+	/* uses dynamically assigned dev_t values */
+
+	gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	gs_tty_driver->subtype = SERIAL_TYPE_NORMAL;
+	gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+	gs_tty_driver->init_termios = tty_std_termios;
+
+	/* 9600-8-N-1 ... matches defaults expected by "usbser.sys" on
+	 * MS-Windows.  Otherwise, most of these flags shouldn't affect
+	 * anything unless we were to actually hook up to a serial line.
+	 */
+	gs_tty_driver->init_termios.c_cflag =
+			B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	gs_tty_driver->init_termios.c_ispeed = 9600;
+	gs_tty_driver->init_termios.c_ospeed = 9600;
+
+	coding.dwDTERate = __constant_cpu_to_le32(9600);
+	coding.bCharFormat = 8;
+	coding.bParityType = USB_CDC_NO_PARITY;
+	coding.bDataBits = USB_CDC_1_STOP_BITS;
+
+	tty_set_operations(gs_tty_driver, &gs_tty_ops);
+
+	/* make devices be openable */
+	for (i = 0; i < count; i++) {
+		mutex_init(&ports[i].lock);
+		status = gs_port_alloc(i, &coding);
+		if (status) {
+			count = i;
+			goto fail;
+		}
+	}
+	n_ports = count;
+
+	/* export the driver ... */
+	status = tty_register_driver(gs_tty_driver);
+	if (status) {
+		put_tty_driver(gs_tty_driver);
+		pr_err("%s: cannot register, err %d\n",
+				__func__, status);
+		goto fail;
+	}
+
+	/* ... and sysfs class devices, so mdev/udev make /dev/ttyGS* */
+	for (i = 0; i < count; i++) {
+		struct device	*tty_dev;
+
+		tty_dev = tty_register_device(gs_tty_driver, i, &g->dev);
+		if (IS_ERR(tty_dev))
+			pr_warning("%s: no classdev for port %d, err %ld\n",
+				__func__, i, PTR_ERR(tty_dev));
+	}
+
+	pr_debug("%s: registered %d ttyGS* device%s\n", __func__,
+			count, (count == 1) ? "" : "s");
+
+	return status;
+fail:
+	while (count--)
+		kfree(ports[count].port);
+	put_tty_driver(gs_tty_driver);
+	gs_tty_driver = NULL;
+	return status;
+}
+
+static int gs_closed(struct gs_port *port)
+{
+	int cond;
+
+	spin_lock_irq(&port->port_lock);
+	cond = (port->open_count == 0) && !port->openclose;
+	spin_unlock_irq(&port->port_lock);
+	return cond;
+}
+
+/**
+ * gserial_cleanup - remove TTY-over-USB driver and devices
+ * Context: may sleep
+ *
+ * This is called to free all resources allocated by @gserial_setup().
+ * Accordingly, it may need to wait until some open /dev/ files have
+ * closed.
+ *
+ * The caller must have issued @gserial_disconnect() for any ports
+ * that had previously been connected, so that there is never any
+ * I/O pending when it's called.
+ */
+void gserial_cleanup(void)
+{
+	unsigned	i;
+	struct gs_port	*port;
+
+	if (!gs_tty_driver)
+		return;
+
+	/* start sysfs and /dev/ttyGS* node removal */
+	for (i = 0; i < n_ports; i++)
+		tty_unregister_device(gs_tty_driver, i);
+
+	for (i = 0; i < n_ports; i++) {
+		/* prevent new opens */
+		mutex_lock(&ports[i].lock);
+		port = ports[i].port;
+		ports[i].port = NULL;
+		mutex_unlock(&ports[i].lock);
+
+		/* wait for old opens to finish */
+		wait_event(port->close_wait, gs_closed(port));
+
+		WARN_ON(port->port_usb != NULL);
+
+		kfree(port);
+	}
+	n_ports = 0;
+
+	tty_unregister_driver(gs_tty_driver);
+	gs_tty_driver = NULL;
+
+	pr_debug("%s: cleaned up ttyGS* support\n", __func__);
+}
+
+/**
+ * gserial_connect - notify TTY I/O glue that USB link is active
+ * @gser: the function, set up with endpoints and descriptors
+ * @port_num: which port is active
+ * Context: any (usually from irq)
+ *
+ * This is called activate endpoints and let the TTY layer know that
+ * the connection is active ... not unlike "carrier detect".  It won't
+ * necessarily start I/O queues; unless the TTY is held open by any
+ * task, there would be no point.  However, the endpoints will be
+ * activated so the USB host can perform I/O, subject to basic USB
+ * hardware flow control.
+ *
+ * Caller needs to have set up the endpoints and USB function in @dev
+ * before calling this, as well as the appropriate (speed-specific)
+ * endpoint descriptors, and also have set up the TTY driver by calling
+ * @gserial_setup().
+ *
+ * Returns negative errno or zero.
+ * On success, ep->driver_data will be overwritten.
+ */
+int gserial_connect(struct gserial *gser, u8 port_num)
+{
+	struct gs_port	*port;
+	unsigned long	flags;
+	int		status;
+
+	if (!gs_tty_driver || port_num >= n_ports)
+		return -ENXIO;
+
+	/* we "know" gserial_cleanup() hasn't been called */
+	port = ports[port_num].port;
+
+	/* activate the endpoints */
+	status = usb_ep_enable(gser->in, gser->in_desc);
+	if (status < 0)
+		return status;
+	gser->in->driver_data = port;
+
+	status = usb_ep_enable(gser->out, gser->out_desc);
+	if (status < 0)
+		goto fail_out;
+	gser->out->driver_data = port;
+
+	/* then tell the tty glue that I/O can work */
+	spin_lock_irqsave(&port->port_lock, flags);
+	gser->ioport = port;
+	port->port_usb = gser;
+
+	/* REVISIT unclear how best to handle this state...
+	 * we don't really couple it with the Linux TTY.
+	 */
+	gser->port_line_coding = port->port_line_coding;
+
+	/* REVISIT if waiting on "carrier detect", signal. */
+
+	/* REVISIT for ACM, issue "network connection" status notification:
+	 * connected if open_count, else disconnected.
+	 */
+
+	/* if it's already open, start I/O */
+	if (port->open_count) {
+		pr_debug("gserial_connect: start ttyGS%d\n", port->port_num);
+		gs_start_io(port);
+	}
+
+	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	return status;
+
+fail_out:
+	usb_ep_disable(gser->in);
+	gser->in->driver_data = NULL;
+	return status;
+}
+
+/**
+ * gserial_disconnect - notify TTY I/O glue that USB link is inactive
+ * @gser: the function, on which gserial_connect() was called
+ * Context: any (usually from irq)
+ *
+ * This is called to deactivate endpoints and let the TTY layer know
+ * that the connection went inactive ... not unlike "hangup".
+ *
+ * On return, the state is as if gserial_connect() had never been called;
+ * there is no active USB I/O on these endpoints.
+ */
+void gserial_disconnect(struct gserial *gser)
+{
+	struct gs_port	*port = gser->ioport;
+	unsigned long	flags;
+
+	if (!port)
+		return;
+
+	/* tell the TTY glue not to do I/O here any more */
+	spin_lock_irqsave(&port->port_lock, flags);
+
+	/* REVISIT as above: how best to track this? */
+	port->port_line_coding = gser->port_line_coding;
+
+	port->port_usb = NULL;
+	gser->ioport = NULL;
+	if (port->open_count > 0 || port->openclose) {
+		wake_up_interruptible(&port->drain_wait);
+		if (port->port_tty)
+			tty_hangup(port->port_tty);
+	}
+	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	/* disable endpoints, aborting down any active I/O */
+	usb_ep_disable(gser->out);
+	gser->out->driver_data = NULL;
+
+	usb_ep_disable(gser->in);
+	gser->in->driver_data = NULL;
+
+	/* finally, free any unused/unusable I/O buffers */
+	spin_lock_irqsave(&port->port_lock, flags);
+	if (port->open_count == 0 && !port->openclose)
+		gs_buf_free(&port->port_write_buf);
+	gs_free_requests(gser->out, &port->read_pool);
+	gs_free_requests(gser->in, &port->write_pool);
+	spin_unlock_irqrestore(&port->port_lock, flags);
+}
diff --git a/drivers/usb/gadget/u_serial.h b/drivers/usb/gadget/u_serial.h
new file mode 100644
index 0000000..7b561138
--- /dev/null
+++ b/drivers/usb/gadget/u_serial.h
@@ -0,0 +1,58 @@
+/*
+ * u_serial.h - interface to USB gadget "serial port"/TTY utilities
+ *
+ * Copyright (C) 2008 David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
+ *
+ * This software is distributed under the terms of the GNU General
+ * Public License ("GPL") as published by the Free Software Foundation,
+ * either version 2 of that License or (at your option) any later version.
+ */
+
+#ifndef __U_SERIAL_H
+#define __U_SERIAL_H
+
+#include <linux/usb/composite.h>
+#include <linux/usb/cdc.h>
+
+/*
+ * One non-multiplexed "serial" I/O port ... there can be several of these
+ * on any given USB peripheral device, if it provides enough endpoints.
+ *
+ * The "u_serial" utility component exists to do one thing:  manage TTY
+ * style I/O using the USB peripheral endpoints listed here, including
+ * hookups to sysfs and /dev for each logical "tty" device.
+ *
+ * REVISIT need TTY --> USB event flow too, so ACM can report open/close
+ * as carrier detect events.  Model after ECM.  There's more ACM state too.
+ *
+ * REVISIT someday, allow multiplexing several TTYs over these endpoints.
+ */
+struct gserial {
+	struct usb_function		func;
+
+	/* port is managed by gserial_{connect,disconnect} */
+	struct gs_port			*ioport;
+
+	struct usb_ep			*in;
+	struct usb_ep			*out;
+	struct usb_endpoint_descriptor	*in_desc;
+	struct usb_endpoint_descriptor	*out_desc;
+
+	/* REVISIT avoid this CDC-ACM support harder ... */
+	struct usb_cdc_line_coding port_line_coding;	/* 9600-8-N-1 etc */
+};
+
+/* port setup/teardown is handled by gadget driver */
+int gserial_setup(struct usb_gadget *g, unsigned n_ports);
+void gserial_cleanup(void);
+
+/* connect/disconnect is handled by individual functions */
+int gserial_connect(struct gserial *, u8 port_num);
+void gserial_disconnect(struct gserial *);
+
+/* functions are bound to configurations by a config or gadget driver */
+int acm_bind_config(struct usb_configuration *c, u8 port_num);
+int gser_bind_config(struct usb_configuration *c, u8 port_num);
+
+#endif /* __U_SERIAL_H */
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index fce4924..aa0bd4f 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -1,8 +1,8 @@
 /*
  * zero.c -- Gadget Zero, for USB development
  *
- * Copyright (C) 2003-2007 David Brownell
- * All rights reserved.
+ * Copyright (C) 2003-2008 David Brownell
+ * Copyright (C) 2008 by Nokia Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -30,12 +30,7 @@
  *
  * It supports two similar configurations.  One sinks whatever the usb host
  * writes, and in return sources zeroes.  The other loops whatever the host
- * writes back, so the host can read it.  Module options include:
- *
- *   buflen=N		default N=4096, buffer size used
- *   qlen=N		default N=32, how many buffers in the loopback queue
- *   loopdefault	default false, list loopback config first
- *   autoresume=N	default N=0, seconds before triggering remote wakeup
+ * writes back, so the host can read it.
  *
  * Many drivers will only have one configuration, letting them be much
  * simpler if they also don't support high speed operation (like this
@@ -47,94 +42,35 @@
  * work with low capability USB controllers without four bulk endpoints.
  */
 
+/*
+ * driver assumes self-powered hardware, and
+ * has no way for users to trigger remote wakeup.
+ */
+
 /* #define VERBOSE_DEBUG */
 
 #include <linux/kernel.h>
 #include <linux/utsname.h>
 #include <linux/device.h>
 
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
+#include "g_zero.h"
 #include "gadget_chips.h"
 
 
 /*-------------------------------------------------------------------------*/
 
-#define DRIVER_VERSION		"Earth Day 2008"
+#define DRIVER_VERSION		"Cinco de Mayo 2008"
 
-static const char shortname[] = "zero";
 static const char longname[] = "Gadget Zero";
 
-static const char source_sink[] = "source and sink data";
-static const char loopback[] = "loop input to output";
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * driver assumes self-powered hardware, and
- * has no way for users to trigger remote wakeup.
- *
- * this version autoconfigures as much as possible,
- * which is reasonable for most "bulk-only" drivers.
- */
-static const char *EP_IN_NAME;		/* source */
-static const char *EP_OUT_NAME;		/* sink */
-
-/*-------------------------------------------------------------------------*/
-
-/* big enough to hold our biggest descriptor */
-#define USB_BUFSIZ	256
-
-struct zero_dev {
-	spinlock_t		lock;
-	struct usb_gadget	*gadget;
-	struct usb_request	*req;		/* for control responses */
-
-	/* when configured, we have one of two configs:
-	 * - source data (in to host) and sink it (out from host)
-	 * - or loop it back (out from host back in to host)
-	 */
-	u8			config;
-	struct usb_ep		*in_ep, *out_ep;
-
-	/* autoresume timer */
-	struct timer_list	resume;
-};
-
-#define DBG(d, fmt, args...) \
-	dev_dbg(&(d)->gadget->dev , fmt , ## args)
-#define VDBG(d, fmt, args...) \
-	dev_vdbg(&(d)->gadget->dev , fmt , ## args)
-#define ERROR(d, fmt, args...) \
-	dev_err(&(d)->gadget->dev , fmt , ## args)
-#define WARN(d, fmt, args...) \
-	dev_warn(&(d)->gadget->dev , fmt , ## args)
-#define INFO(d, fmt, args...) \
-	dev_info(&(d)->gadget->dev , fmt , ## args)
-
-/*-------------------------------------------------------------------------*/
-
-static unsigned buflen = 4096;
-static unsigned qlen = 32;
-static unsigned pattern = 0;
-
-module_param(buflen, uint, S_IRUGO);
-module_param(qlen, uint, S_IRUGO);
-module_param(pattern, uint, S_IRUGO|S_IWUSR);
-
-/*
- * if it's nonzero, autoresume says how many seconds to wait
- * before trying to wake up the host after suspend.
- */
-static unsigned autoresume = 0;
-module_param(autoresume, uint, 0);
+unsigned buflen = 4096;
+module_param(buflen, uint, 0);
 
 /*
  * Normally the "loopback" configuration is second (index 1) so
  * it's not the default.  Here's where to change that order, to
- * work better with hosts where config changes are problematic.
- * Or controllers (like superh) that only support one config.
+ * work better with hosts where config changes are problematic or
+ * controllers (like original superh) that only support one config.
  */
 static int loopdefault = 0;
 module_param(loopdefault, bool, S_IRUGO|S_IWUSR);
@@ -156,24 +92,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-/*
- * 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_SOURCE_SINK		250
-#define STRING_LOOPBACK			251
-
-/*
- * This device advertises two configurations; these numbers work
- * on a pxa250 as well as more flexible hardware.
- */
-#define	CONFIG_SOURCE_SINK	3
-#define	CONFIG_LOOPBACK		2
-
 static struct usb_device_descriptor device_desc = {
 	.bLength =		sizeof device_desc,
 	.bDescriptorType =	USB_DT_DEVICE,
@@ -183,248 +101,64 @@
 
 	.idVendor =		__constant_cpu_to_le16(DRIVER_VENDOR_NUM),
 	.idProduct =		__constant_cpu_to_le16(DRIVER_PRODUCT_NUM),
-	.iManufacturer =	STRING_MANUFACTURER,
-	.iProduct =		STRING_PRODUCT,
-	.iSerialNumber =	STRING_SERIAL,
 	.bNumConfigurations =	2,
 };
 
-static struct usb_config_descriptor source_sink_config = {
-	.bLength =		sizeof source_sink_config,
-	.bDescriptorType =	USB_DT_CONFIG,
-
-	/* compute wTotalLength on the fly */
-	.bNumInterfaces =	1,
-	.bConfigurationValue =	CONFIG_SOURCE_SINK,
-	.iConfiguration =	STRING_SOURCE_SINK,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
-	.bMaxPower =		1,	/* self-powered */
-};
-
-static struct usb_config_descriptor loopback_config = {
-	.bLength =		sizeof loopback_config,
-	.bDescriptorType =	USB_DT_CONFIG,
-
-	/* compute wTotalLength on the fly */
-	.bNumInterfaces =	1,
-	.bConfigurationValue =	CONFIG_LOOPBACK,
-	.iConfiguration =	STRING_LOOPBACK,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
-	.bMaxPower =		1,	/* self-powered */
-};
-
+#ifdef CONFIG_USB_OTG
 static struct usb_otg_descriptor otg_descriptor = {
 	.bLength =		sizeof otg_descriptor,
 	.bDescriptorType =	USB_DT_OTG,
 
-	.bmAttributes =		USB_OTG_SRP,
+	/* REVISIT SRP-only hardware is possible, although
+	 * it would not be called "OTG" ...
+	 */
+	.bmAttributes =		USB_OTG_SRP | USB_OTG_HNP,
 };
 
-/* one interface in each configuration */
-
-static const struct usb_interface_descriptor source_sink_intf = {
-	.bLength =		sizeof source_sink_intf,
-	.bDescriptorType =	USB_DT_INTERFACE,
-
-	.bNumEndpoints =	2,
-	.bInterfaceClass =	USB_CLASS_VENDOR_SPEC,
-	.iInterface =		STRING_SOURCE_SINK,
-};
-
-static const struct usb_interface_descriptor loopback_intf = {
-	.bLength =		sizeof loopback_intf,
-	.bDescriptorType =	USB_DT_INTERFACE,
-
-	.bNumEndpoints =	2,
-	.bInterfaceClass =	USB_CLASS_VENDOR_SPEC,
-	.iInterface =		STRING_LOOPBACK,
-};
-
-/* two full speed bulk endpoints; their use is config-dependent */
-
-static struct usb_endpoint_descriptor fs_source_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	USB_DIR_IN,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-};
-
-static struct usb_endpoint_descriptor fs_sink_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bEndpointAddress =	USB_DIR_OUT,
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-};
-
-static const struct usb_descriptor_header *fs_source_sink_function[] = {
+const struct usb_descriptor_header *otg_desc[] = {
 	(struct usb_descriptor_header *) &otg_descriptor,
-	(struct usb_descriptor_header *) &source_sink_intf,
-	(struct usb_descriptor_header *) &fs_sink_desc,
-	(struct usb_descriptor_header *) &fs_source_desc,
 	NULL,
 };
+#endif
 
-static const struct usb_descriptor_header *fs_loopback_function[] = {
-	(struct usb_descriptor_header *) &otg_descriptor,
-	(struct usb_descriptor_header *) &loopback_intf,
-	(struct usb_descriptor_header *) &fs_sink_desc,
-	(struct usb_descriptor_header *) &fs_source_desc,
-	NULL,
-};
+/* string IDs are assigned dynamically */
 
-/*
- * usb 2.0 devices need to expose both high speed and full speed
- * descriptors, unless they only run at full speed.
- *
- * that means alternate endpoint descriptors (bigger packets)
- * and a "device qualifier" ... plus more construction options
- * for the config descriptor.
- */
-
-static struct usb_endpoint_descriptor hs_source_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
-};
-
-static struct usb_endpoint_descriptor hs_sink_desc = {
-	.bLength =		USB_DT_ENDPOINT_SIZE,
-	.bDescriptorType =	USB_DT_ENDPOINT,
-
-	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(512),
-};
-
-static struct usb_qualifier_descriptor dev_qualifier = {
-	.bLength =		sizeof dev_qualifier,
-	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
-
-	.bcdUSB =		__constant_cpu_to_le16(0x0200),
-	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,
-
-	.bNumConfigurations =	2,
-};
-
-static const struct usb_descriptor_header *hs_source_sink_function[] = {
-	(struct usb_descriptor_header *) &otg_descriptor,
-	(struct usb_descriptor_header *) &source_sink_intf,
-	(struct usb_descriptor_header *) &hs_source_desc,
-	(struct usb_descriptor_header *) &hs_sink_desc,
-	NULL,
-};
-
-static const struct usb_descriptor_header *hs_loopback_function[] = {
-	(struct usb_descriptor_header *) &otg_descriptor,
-	(struct usb_descriptor_header *) &loopback_intf,
-	(struct usb_descriptor_header *) &hs_source_desc,
-	(struct usb_descriptor_header *) &hs_sink_desc,
-	NULL,
-};
-
-/* maxpacket and other transfer characteristics vary by speed. */
-static inline struct usb_endpoint_descriptor *
-ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs,
-		struct usb_endpoint_descriptor *fs)
-{
-	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
-		return hs;
-	return fs;
-}
+#define STRING_MANUFACTURER_IDX		0
+#define STRING_PRODUCT_IDX		1
+#define STRING_SERIAL_IDX		2
 
 static char manufacturer[50];
 
 /* default serial number takes at least two packets */
 static char serial[] = "0123456789.0123456789.0123456789";
 
-
-/* static strings, in UTF-8 */
-static struct usb_string strings[] = {
-	{ STRING_MANUFACTURER, manufacturer, },
-	{ STRING_PRODUCT, longname, },
-	{ STRING_SERIAL, serial, },
-	{ STRING_LOOPBACK, loopback, },
-	{ STRING_SOURCE_SINK, source_sink, },
+static struct usb_string strings_dev[] = {
+	[STRING_MANUFACTURER_IDX].s = manufacturer,
+	[STRING_PRODUCT_IDX].s = longname,
+	[STRING_SERIAL_IDX].s = serial,
 	{  }			/* end of list */
 };
 
-static struct usb_gadget_strings stringtab = {
+static struct usb_gadget_strings stringtab_dev = {
 	.language	= 0x0409,	/* en-us */
-	.strings	= strings,
+	.strings	= strings_dev,
 };
 
-/*
- * config descriptors are also handcrafted.  these must agree with code
- * that sets configurations, and with code managing interfaces and their
- * altsettings.  other complexity may come from:
- *
- *  - high speed support, including "other speed config" rules
- *  - multiple configurations
- *  - interfaces with alternate settings
- *  - embedded class or vendor-specific descriptors
- *
- * this handles high speed, and has a second config that could as easily
- * have been an alternate interface setting (on most hardware).
- *
- * NOTE:  to demonstrate (and test) more USB capabilities, this driver
- * should include an altsetting to test interrupt transfers, including
- * high bandwidth modes at high speed.  (Maybe work like Intel's test
- * device?)
- */
-static int config_buf(struct usb_gadget *gadget,
-		u8 *buf, u8 type, unsigned index)
-{
-	int				is_source_sink;
-	int				len;
-	const struct usb_descriptor_header **function;
-	int				hs = 0;
-
-	/* two configurations will always be index 0 and index 1 */
-	if (index > 1)
-		return -EINVAL;
-	is_source_sink = loopdefault ? (index == 1) : (index == 0);
-
-	if (gadget_is_dualspeed(gadget)) {
-		hs = (gadget->speed == USB_SPEED_HIGH);
-		if (type == USB_DT_OTHER_SPEED_CONFIG)
-			hs = !hs;
-	}
-	if (hs)
-		function = is_source_sink
-			? hs_source_sink_function
-			: hs_loopback_function;
-	else
-		function = is_source_sink
-			? fs_source_sink_function
-			: fs_loopback_function;
-
-	/* for now, don't advertise srp-only devices */
-	if (!gadget_is_otg(gadget))
-		function++;
-
-	len = usb_gadget_config_buf(is_source_sink
-					? &source_sink_config
-					: &loopback_config,
-			buf, USB_BUFSIZ, function);
-	if (len < 0)
-		return len;
-	((struct usb_config_descriptor *) buf)->bDescriptorType = type;
-	return len;
-}
+static struct usb_gadget_strings *dev_strings[] = {
+	&stringtab_dev,
+	NULL,
+};
 
 /*-------------------------------------------------------------------------*/
 
-static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length)
+struct usb_request *alloc_ep_req(struct usb_ep *ep)
 {
 	struct usb_request	*req;
 
 	req = usb_ep_alloc_request(ep, GFP_ATOMIC);
 	if (req) {
-		req->length = length;
-		req->buf = kmalloc(length, GFP_ATOMIC);
+		req->length = buflen;
+		req->buf = kmalloc(buflen, GFP_ATOMIC);
 		if (!req->buf) {
 			usb_ep_free_request(ep, req);
 			req = NULL;
@@ -433,681 +167,73 @@
 	return req;
 }
 
-static void free_ep_req(struct usb_ep *ep, struct usb_request *req)
+void free_ep_req(struct usb_ep *ep, struct usb_request *req)
 {
 	kfree(req->buf);
 	usb_ep_free_request(ep, req);
 }
 
-/*-------------------------------------------------------------------------*/
-
-/*
- * SOURCE/SINK FUNCTION ... a primary testing vehicle for USB peripherals,
- * this just sinks bulk packets OUT to the peripheral and sources them IN
- * to the host, optionally with specific data patterns.
- *
- * In terms of control messaging, this supports all the standard requests
- * plus two that support control-OUT tests.
- *
- * Note that because this doesn't queue more than one request at a time,
- * some other function must be used to test queueing logic.  The network
- * link (g_ether) is probably the best option for that.
- */
-
-/* optionally require specific source/sink data patterns  */
-
-static int
-check_read_data(
-	struct zero_dev		*dev,
-	struct usb_ep		*ep,
-	struct usb_request	*req
-)
+static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep)
 {
-	unsigned	i;
-	u8		*buf = req->buf;
+	int			value;
 
-	for (i = 0; i < req->actual; i++, buf++) {
-		switch (pattern) {
-		/* all-zeroes has no synchronization issues */
-		case 0:
-			if (*buf == 0)
-				continue;
-			break;
-		/* mod63 stays in sync with short-terminated transfers,
-		 * or otherwise when host and gadget agree on how large
-		 * each usb transfer request should be.  resync is done
-		 * with set_interface or set_config.
-		 */
-		case 1:
-			if (*buf == (u8)(i % 63))
-				continue;
-			break;
-		}
-		ERROR(dev, "bad OUT byte, buf[%d] = %d\n", i, *buf);
-		usb_ep_set_halt(ep);
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static void reinit_write_data(struct usb_ep *ep, struct usb_request *req)
-{
-	unsigned	i;
-	u8		*buf = req->buf;
-
-	switch (pattern) {
-	case 0:
-		memset(req->buf, 0, req->length);
-		break;
-	case 1:
-		for  (i = 0; i < req->length; i++)
-			*buf++ = (u8) (i % 63);
-		break;
+	if (ep->driver_data) {
+		value = usb_ep_disable(ep);
+		if (value < 0)
+			DBG(cdev, "disable %s --> %d\n",
+					ep->name, value);
+		ep->driver_data = NULL;
 	}
 }
 
-/* if there is only one request in the queue, there'll always be an
- * irq delay between end of one request and start of the next.
- * that prevents using hardware dma queues.
- */
-static void source_sink_complete(struct usb_ep *ep, struct usb_request *req)
+void disable_endpoints(struct usb_composite_dev *cdev,
+		struct usb_ep *in, struct usb_ep *out)
 {
-	struct zero_dev	*dev = ep->driver_data;
-	int		status = req->status;
-
-	switch (status) {
-
-	case 0:				/* normal completion? */
-		if (ep == dev->out_ep) {
-			check_read_data(dev, ep, req);
-			memset(req->buf, 0x55, req->length);
-		} else
-			reinit_write_data(ep, req);
-		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)
-			check_read_data(dev, 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:
-#if 1
-		DBG(dev, "%s complete --> %d, %d/%d\n", ep->name,
-				status, req->actual, req->length);
-#endif
-	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 struct usb_request *source_sink_start_ep(struct usb_ep *ep)
-{
-	struct usb_request	*req;
-	int			status;
-
-	req = alloc_ep_req(ep, buflen);
-	if (!req)
-		return NULL;
-
-	memset(req->buf, 0, req->length);
-	req->complete = source_sink_complete;
-
-	if (strcmp(ep->name, EP_IN_NAME) == 0)
-		reinit_write_data(ep, req);
-	else
-		memset(req->buf, 0x55, req->length);
-
-	status = usb_ep_queue(ep, req, GFP_ATOMIC);
-	if (status) {
-		struct zero_dev	*dev = ep->driver_data;
-
-		ERROR(dev, "start %s --> %d\n", ep->name, status);
-		free_ep_req(ep, req);
-		req = NULL;
-	}
-
-	return req;
-}
-
-static int set_source_sink_config(struct zero_dev *dev)
-{
-	int			result = 0;
-	struct usb_ep		*ep;
-	struct usb_gadget	*gadget = dev->gadget;
-
-	gadget_for_each_ep(ep, gadget) {
-		const struct usb_endpoint_descriptor	*d;
-
-		/* one endpoint writes (sources) zeroes in (to the host) */
-		if (strcmp(ep->name, EP_IN_NAME) == 0) {
-			d = ep_desc(gadget, &hs_source_desc, &fs_source_desc);
-			result = usb_ep_enable(ep, d);
-			if (result == 0) {
-				ep->driver_data = dev;
-				if (source_sink_start_ep(ep) != NULL) {
-					dev->in_ep = ep;
-					continue;
-				}
-				usb_ep_disable(ep);
-				result = -EIO;
-			}
-
-		/* one endpoint reads (sinks) anything out (from the host) */
-		} else if (strcmp(ep->name, EP_OUT_NAME) == 0) {
-			d = ep_desc(gadget, &hs_sink_desc, &fs_sink_desc);
-			result = usb_ep_enable(ep, d);
-			if (result == 0) {
-				ep->driver_data = dev;
-				if (source_sink_start_ep(ep) != NULL) {
-					dev->out_ep = ep;
-					continue;
-				}
-				usb_ep_disable(ep);
-				result = -EIO;
-			}
-
-		/* ignore any other endpoints */
-		} else
-			continue;
-
-		/* stop on error */
-		ERROR(dev, "can't start %s, result %d\n", ep->name, result);
-		break;
-	}
-	if (result == 0)
-		DBG(dev, "buflen %d\n", buflen);
-
-	/* caller is responsible for cleanup on error */
-	return result;
+	disable_ep(cdev, in);
+	disable_ep(cdev, out);
 }
 
 /*-------------------------------------------------------------------------*/
 
-static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
+static int __init zero_bind(struct usb_composite_dev *cdev)
 {
-	struct zero_dev	*dev = ep->driver_data;
-	int		status = req->status;
-
-	switch (status) {
-
-	case 0:				/* normal completion? */
-		if (ep == dev->out_ep) {
-			/* loop this OUT packet back IN to the host */
-			req->zero = (req->actual < req->length);
-			req->length = req->actual;
-			status = usb_ep_queue(dev->in_ep, req, GFP_ATOMIC);
-			if (status == 0)
-				return;
-
-			/* "should never get here" */
-			ERROR(dev, "can't loop %s to %s: %d\n",
-				ep->name, dev->in_ep->name,
-				status);
-		}
-
-		/* queue the buffer for some later OUT packet */
-		req->length = buflen;
-		status = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC);
-		if (status == 0)
-			return;
-
-		/* "should never get here" */
-		/* FALLTHROUGH */
-
-	default:
-		ERROR(dev, "%s loop complete --> %d, %d/%d\n", ep->name,
-				status, req->actual, req->length);
-		/* FALLTHROUGH */
-
-	/* NOTE:  since this driver doesn't maintain an explicit record
-	 * of requests it submitted (just maintains qlen count), we
-	 * rely on the hardware driver to clean up on disconnect or
-	 * endpoint disable.
-	 */
-	case -ECONNABORTED:		/* hardware forced ep reset */
-	case -ECONNRESET:		/* request dequeued */
-	case -ESHUTDOWN:		/* disconnect from host */
-		free_ep_req(ep, req);
-		return;
-	}
-}
-
-static int set_loopback_config(struct zero_dev *dev)
-{
-	int			result = 0;
-	struct usb_ep		*ep;
-	struct usb_gadget	*gadget = dev->gadget;
-
-	gadget_for_each_ep(ep, gadget) {
-		const struct usb_endpoint_descriptor	*d;
-
-		/* one endpoint writes data back IN to the host */
-		if (strcmp(ep->name, EP_IN_NAME) == 0) {
-			d = ep_desc(gadget, &hs_source_desc, &fs_source_desc);
-			result = usb_ep_enable(ep, d);
-			if (result == 0) {
-				ep->driver_data = dev;
-				dev->in_ep = ep;
-				continue;
-			}
-
-		/* one endpoint just reads OUT packets */
-		} else if (strcmp(ep->name, EP_OUT_NAME) == 0) {
-			d = ep_desc(gadget, &hs_sink_desc, &fs_sink_desc);
-			result = usb_ep_enable(ep, d);
-			if (result == 0) {
-				ep->driver_data = dev;
-				dev->out_ep = ep;
-				continue;
-			}
-
-		/* ignore any other endpoints */
-		} else
-			continue;
-
-		/* stop on error */
-		ERROR(dev, "can't enable %s, result %d\n", ep->name, result);
-		break;
-	}
-
-	/* allocate a bunch of read buffers and queue them all at once.
-	 * we buffer at most 'qlen' transfers; fewer if any need more
-	 * than 'buflen' bytes each.
-	 */
-	if (result == 0) {
-		struct usb_request	*req;
-		unsigned		i;
-
-		ep = dev->out_ep;
-		for (i = 0; i < qlen && result == 0; i++) {
-			req = alloc_ep_req(ep, buflen);
-			if (req) {
-				req->complete = loopback_complete;
-				result = usb_ep_queue(ep, req, GFP_ATOMIC);
-				if (result)
-					DBG(dev, "%s queue req --> %d\n",
-							ep->name, result);
-			} else
-				result = -ENOMEM;
-		}
-	}
-	if (result == 0)
-		DBG(dev, "qlen %d, buflen %d\n", qlen, buflen);
-
-	/* caller is responsible for cleanup on error */
-	return result;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void zero_reset_config(struct zero_dev *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.
-	 */
-	if (dev->in_ep) {
-		usb_ep_disable(dev->in_ep);
-		dev->in_ep = NULL;
-	}
-	if (dev->out_ep) {
-		usb_ep_disable(dev->out_ep);
-		dev->out_ep = NULL;
-	}
-	dev->config = 0;
-	del_timer(&dev->resume);
-}
-
-/* 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 zero_set_config(struct zero_dev *dev, unsigned number)
-{
-	int			result = 0;
-	struct usb_gadget	*gadget = dev->gadget;
-
-	if (number == dev->config)
-		return 0;
-
-	if (gadget_is_sa1100(gadget) && dev->config) {
-		/* tx fifo is full, but we can't clear it...*/
-		ERROR(dev, "can't change configurations\n");
-		return -ESPIPE;
-	}
-	zero_reset_config(dev);
-
-	switch (number) {
-	case CONFIG_SOURCE_SINK:
-		result = set_source_sink_config(dev);
-		break;
-	case CONFIG_LOOPBACK:
-		result = set_loopback_config(dev);
-		break;
-	default:
-		result = -EINVAL;
-		/* FALL THROUGH */
-	case 0:
-		return result;
-	}
-
-	if (!result && (!dev->in_ep || !dev->out_ep))
-		result = -ENODEV;
-	if (result)
-		zero_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 config #%d: %s\n", speed, number,
-				(number == CONFIG_SOURCE_SINK)
-					? source_sink : loopback);
-	}
-	return result;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void zero_setup_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	if (req->status || req->actual != req->length)
-		DBG((struct zero_dev *) 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
-zero_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
-{
-	struct zero_dev		*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_DEVICE_QUALIFIER:
-			if (!gadget_is_dualspeed(gadget))
-				break;
-			value = min(w_length, (u16) sizeof dev_qualifier);
-			memcpy(req->buf, &dev_qualifier, value);
-			break;
-
-		case USB_DT_OTHER_SPEED_CONFIG:
-			if (!gadget_is_dualspeed(gadget))
-				break;
-			// FALLTHROUGH
-		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 = zero_set_config(dev, w_value);
-		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 == 0 && 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.
-			 */
-			zero_reset_config(dev);
-			zero_set_config(dev, config);
-			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 != 0) {
-			value = -EDOM;
-			break;
-		}
-		*(u8 *)req->buf = 0;
-		value = min(w_length, (u16) 1);
-		break;
-
-	/*
-	 * These are the same vendor-specific requests supported by
-	 * Intel's USB 2.0 compliance test devices.  We exceed that
-	 * device spec by allowing multiple-packet requests.
-	 */
-	case 0x5b:	/* control WRITE test -- fill the buffer */
-		if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))
-			goto unknown;
-		if (w_value || w_index)
-			break;
-		/* just read that many bytes into the buffer */
-		if (w_length > USB_BUFSIZ)
-			break;
-		value = w_length;
-		break;
-	case 0x5c:	/* control READ test -- return the buffer */
-		if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))
-			goto unknown;
-		if (w_value || w_index)
-			break;
-		/* expect those bytes are still in the buffer; send back */
-		if (w_length > USB_BUFSIZ
-				|| w_length != req->length)
-			break;
-		value = w_length;
-		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;
-			zero_setup_complete(gadget->ep0, req);
-		}
-	}
-
-	/* device either stalls (value < 0) or reports success */
-	return value;
-}
-
-static void zero_disconnect(struct usb_gadget *gadget)
-{
-	struct zero_dev		*dev = get_gadget_data(gadget);
-	unsigned long		flags;
-
-	spin_lock_irqsave(&dev->lock, flags);
-	zero_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 zero_autoresume(unsigned long _dev)
-{
-	struct zero_dev	*dev = (struct zero_dev *) _dev;
-	int		status;
-
-	/* normally the host would be woken up for something
-	 * more significant than just a timer firing...
-	 */
-	if (dev->gadget->speed != USB_SPEED_UNKNOWN) {
-		status = usb_gadget_wakeup(dev->gadget);
-		DBG(dev, "wakeup --> %d\n", status);
-	}
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void zero_unbind(struct usb_gadget *gadget)
-{
-	struct zero_dev		*dev = get_gadget_data(gadget);
-
-	DBG(dev, "unbind\n");
-
-	/* 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);
-	}
-	del_timer_sync(&dev->resume);
-	kfree(dev);
-	set_gadget_data(gadget, NULL);
-}
-
-static int __init zero_bind(struct usb_gadget *gadget)
-{
-	struct zero_dev		*dev;
-	struct usb_ep		*ep;
 	int			gcnum;
+	struct usb_gadget	*gadget = cdev->gadget;
+	int			id;
 
-	/* FIXME this can't yet work right with SH ... it has only
-	 * one configuration, numbered one.
+	/* Allocate string descriptor numbers ... note that string
+	 * contents can be overridden by the composite_dev glue.
 	 */
-	if (gadget_is_sh(gadget))
-		return -ENODEV;
+	id = usb_string_id(cdev);
+	if (id < 0)
+		return id;
+	strings_dev[STRING_MANUFACTURER_IDX].id = id;
+	device_desc.iManufacturer = id;
 
-	/* 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.
+	id = usb_string_id(cdev);
+	if (id < 0)
+		return id;
+	strings_dev[STRING_PRODUCT_IDX].id = id;
+	device_desc.iProduct = id;
+
+	id = usb_string_id(cdev);
+	if (id < 0)
+		return id;
+	strings_dev[STRING_SERIAL_IDX].id = id;
+	device_desc.iSerialNumber = id;
+
+	/* Register primary, then secondary configuration.  Note that
+	 * SH3 only allows one config...
 	 */
-	usb_ep_autoconfig_reset(gadget);
-	ep = usb_ep_autoconfig(gadget, &fs_source_desc);
-	if (!ep) {
-autoconf_fail:
-		pr_err("%s: can't autoconfigure on %s\n",
-			shortname, gadget->name);
-		return -ENODEV;
+	if (loopdefault) {
+		loopback_add(cdev);
+		if (!gadget_is_sh(gadget))
+			sourcesink_add(cdev);
+	} else {
+		sourcesink_add(cdev);
+		if (!gadget_is_sh(gadget))
+			loopback_add(cdev);
 	}
-	EP_IN_NAME = ep->name;
-	ep->driver_data = ep;	/* claim */
-
-	ep = usb_ep_autoconfig(gadget, &fs_sink_desc);
-	if (!ep)
-		goto autoconf_fail;
-	EP_OUT_NAME = ep->name;
-	ep->driver_data = ep;	/* claim */
 
 	gcnum = usb_gadget_controller_number(gadget);
 	if (gcnum >= 0)
@@ -1115,144 +241,44 @@
 	else {
 		/* gadget zero is so simple (for now, no altsettings) that
 		 * it SHOULD NOT have problems with bulk-capable hardware.
-		 * so warn about unrcognized controllers, don't panic.
+		 * so just warn about unrcognized controllers -- don't panic.
 		 *
 		 * things like configuration and altsetting numbering
 		 * can need hardware-specific attention though.
 		 */
 		pr_warning("%s: controller '%s' not recognized\n",
-			shortname, gadget->name);
+			longname, gadget->name);
 		device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
 	}
 
 
-	/* ok, we made sense of the hardware ... */
-	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-	if (!dev)
-		return -ENOMEM;
-	spin_lock_init(&dev->lock);
-	dev->gadget = gadget;
-	set_gadget_data(gadget, dev);
-
-	init_timer(&dev->resume);
-	dev->resume.function = zero_autoresume;
-	dev->resume.data = (unsigned long) dev;
-
-	/* preallocate control response and buffer */
-	dev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
-	if (!dev->req)
-		goto enomem;
-	dev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL);
-	if (!dev->req->buf)
-		goto enomem;
-
-	dev->req->complete = zero_setup_complete;
-
-	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
-
-	if (gadget_is_dualspeed(gadget)) {
-		/* assume ep0 uses the same value for both speeds ... */
-		dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
-
-		/* and that all endpoints are dual-speed */
-		hs_source_desc.bEndpointAddress =
-				fs_source_desc.bEndpointAddress;
-		hs_sink_desc.bEndpointAddress =
-				fs_sink_desc.bEndpointAddress;
-	}
-
-	if (gadget_is_otg(gadget)) {
-		otg_descriptor.bmAttributes |= USB_OTG_HNP,
-		source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
-		loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
-	}
-
-	usb_gadget_set_selfpowered(gadget);
-
-	if (autoresume) {
-		source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
-		loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
-	}
-
-	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);
+	INFO(cdev, "%s, version: " DRIVER_VERSION "\n", longname);
 
 	snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
 		init_utsname()->sysname, init_utsname()->release,
 		gadget->name);
 
 	return 0;
-
-enomem:
-	zero_unbind(gadget);
-	return -ENOMEM;
 }
 
-/*-------------------------------------------------------------------------*/
-
-static void zero_suspend(struct usb_gadget *gadget)
-{
-	struct zero_dev		*dev = get_gadget_data(gadget);
-
-	if (gadget->speed == USB_SPEED_UNKNOWN)
-		return;
-
-	if (autoresume) {
-		mod_timer(&dev->resume, jiffies + (HZ * autoresume));
-		DBG(dev, "suspend, wakeup in %d seconds\n", autoresume);
-	} else
-		DBG(dev, "suspend\n");
-}
-
-static void zero_resume(struct usb_gadget *gadget)
-{
-	struct zero_dev		*dev = get_gadget_data(gadget);
-
-	DBG(dev, "resume\n");
-	del_timer(&dev->resume);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-static struct usb_gadget_driver zero_driver = {
-#ifdef CONFIG_USB_GADGET_DUALSPEED
-	.speed		= USB_SPEED_HIGH,
-#else
-	.speed		= USB_SPEED_FULL,
-#endif
-	.function	= (char *) longname,
+static struct usb_composite_driver zero_driver = {
+	.name		= "zero",
+	.dev		= &device_desc,
+	.strings	= dev_strings,
 	.bind		= zero_bind,
-	.unbind		= __exit_p(zero_unbind),
-
-	.setup		= zero_setup,
-	.disconnect	= zero_disconnect,
-
-	.suspend	= zero_suspend,
-	.resume		= zero_resume,
-
-	.driver		= {
-		.name		= (char *) shortname,
-		.owner		= THIS_MODULE,
-	},
 };
 
 MODULE_AUTHOR("David Brownell");
 MODULE_LICENSE("GPL");
 
-
 static int __init init(void)
 {
-	return usb_gadget_register_driver(&zero_driver);
+	return usb_composite_register(&zero_driver);
 }
 module_init(init);
 
 static void __exit cleanup(void)
 {
-	usb_gadget_unregister_driver(&zero_driver);
+	usb_composite_unregister(&zero_driver);
 }
 module_exit(cleanup);
-
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
index 08a4335..bf69f47 100644
--- a/drivers/usb/host/ehci-au1xxx.c
+++ b/drivers/usb/host/ehci-au1xxx.c
@@ -19,178 +19,66 @@
 #define USB_MCFG_RDCOMB   (1<<30)
 #define USB_MCFG_SSDEN    (1<<23)
 #define USB_MCFG_PHYPLLEN (1<<19)
+#define USB_MCFG_UCECLKEN (1<<18)
 #define USB_MCFG_EHCCLKEN (1<<17)
+#ifdef CONFIG_DMA_COHERENT
 #define USB_MCFG_UCAM     (1<<7)
+#else
+#define USB_MCFG_UCAM     (0)
+#endif
 #define USB_MCFG_EBMEN    (1<<3)
 #define USB_MCFG_EMEMEN   (1<<2)
 
-#define USBH_ENABLE_CE    (USB_MCFG_PHYPLLEN | USB_MCFG_EHCCLKEN)
+#define USBH_ENABLE_CE	(USB_MCFG_PHYPLLEN | USB_MCFG_EHCCLKEN)
+#define USBH_ENABLE_INIT (USB_MCFG_PFEN  | USB_MCFG_RDCOMB |	\
+			  USBH_ENABLE_CE | USB_MCFG_SSDEN  |	\
+			  USB_MCFG_UCAM  | USB_MCFG_EBMEN  |	\
+			  USB_MCFG_EMEMEN)
 
-#ifdef CONFIG_DMA_COHERENT
-#define USBH_ENABLE_INIT  (USBH_ENABLE_CE \
-                         | USB_MCFG_PFEN | USB_MCFG_RDCOMB \
-                         | USB_MCFG_SSDEN | USB_MCFG_UCAM \
-                         | USB_MCFG_EBMEN | USB_MCFG_EMEMEN)
-#else
-#define USBH_ENABLE_INIT  (USBH_ENABLE_CE \
-                         | USB_MCFG_PFEN | USB_MCFG_RDCOMB \
-                         | USB_MCFG_SSDEN \
-                         | USB_MCFG_EBMEN | USB_MCFG_EMEMEN)
-#endif
 #define USBH_DISABLE      (USB_MCFG_EBMEN | USB_MCFG_EMEMEN)
 
 extern int usb_disabled(void);
 
-/*-------------------------------------------------------------------------*/
-
-static void au1xxx_start_ehc(struct platform_device *dev)
+static void au1xxx_start_ehc(void)
 {
-	pr_debug(__FILE__ ": starting Au1xxx EHCI USB Controller\n");
-
-	/* write HW defaults again in case Yamon cleared them */
-	if (au_readl(USB_HOST_CONFIG) == 0) {
-		au_writel(0x00d02000, USB_HOST_CONFIG);
-		au_readl(USB_HOST_CONFIG);
-		udelay(1000);
-	}
-	/* enable host controller */
-	au_writel(USBH_ENABLE_CE | au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG);
-	au_readl(USB_HOST_CONFIG);
-	udelay(1000);
-	au_writel(USBH_ENABLE_INIT | au_readl(USB_HOST_CONFIG),
-		  USB_HOST_CONFIG);
-	au_readl(USB_HOST_CONFIG);
+	/* enable clock to EHCI block and HS PHY PLL*/
+	au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_CE, USB_HOST_CONFIG);
+	au_sync();
 	udelay(1000);
 
-	pr_debug(__FILE__ ": Clock to USB host has been enabled\n");
+	/* enable EHCI mmio */
+	au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_INIT, USB_HOST_CONFIG);
+	au_sync();
+	udelay(1000);
 }
 
-static void au1xxx_stop_ehc(struct platform_device *dev)
+static void au1xxx_stop_ehc(void)
 {
-	pr_debug(__FILE__ ": stopping Au1xxx EHCI USB Controller\n");
+	unsigned long c;
 
 	/* Disable mem */
-	au_writel(~USBH_DISABLE & au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG);
+	au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_DISABLE, USB_HOST_CONFIG);
+	au_sync();
 	udelay(1000);
-	/* Disable clock */
-	au_writel(~USB_MCFG_EHCCLKEN & au_readl(USB_HOST_CONFIG),
-		  USB_HOST_CONFIG);
-	au_readl(USB_HOST_CONFIG);
+
+	/* Disable EHC clock. If the HS PHY is unused disable it too. */
+	c = au_readl(USB_HOST_CONFIG) & ~USB_MCFG_EHCCLKEN;
+	if (!(c & USB_MCFG_UCECLKEN))		/* UDC disabled? */
+		c &= ~USB_MCFG_PHYPLLEN;	/* yes: disable HS PHY PLL */
+	au_writel(c, USB_HOST_CONFIG);
+	au_sync();
 }
 
-/*-------------------------------------------------------------------------*/
-
-/* configure so an HC device and id are always provided */
-/* always called with process context; sleeping is OK */
-
-/**
- * usb_ehci_au1xxx_probe - initialize Au1xxx-based HCDs
- * Context: !in_interrupt()
- *
- * Allocates basic resources for this USB host controller, and
- * then invokes the start() method for the HCD associated with it
- * through the hotplug entry's driver_data.
- *
- */
-int usb_ehci_au1xxx_probe(const struct hc_driver *driver,
-			  struct usb_hcd **hcd_out, struct platform_device *dev)
-{
-	int retval;
-	struct usb_hcd *hcd;
-	struct ehci_hcd *ehci;
-
-#if defined(CONFIG_SOC_AU1200) && defined(CONFIG_DMA_COHERENT)
-
-	/* Au1200 AB USB does not support coherent memory */
-	if (!(read_c0_prid() & 0xff)) {
-		pr_info("%s: this is chip revision AB!\n", dev->name);
-		pr_info("%s: update your board or re-configure the kernel\n",
-			dev->name);
-		return -ENODEV;
-	}
-#endif
-
-	au1xxx_start_ehc(dev);
-
-	if (dev->resource[1].flags != IORESOURCE_IRQ) {
-		pr_debug("resource[1] is not IORESOURCE_IRQ");
-		retval = -ENOMEM;
-	}
-	hcd = usb_create_hcd(driver, &dev->dev, "Au1xxx");
-	if (!hcd)
-		return -ENOMEM;
-	hcd->rsrc_start = dev->resource[0].start;
-	hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
-
-	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-		pr_debug("request_mem_region failed");
-		retval = -EBUSY;
-		goto err1;
-	}
-
-	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-	if (!hcd->regs) {
-		pr_debug("ioremap failed");
-		retval = -ENOMEM;
-		goto err2;
-	}
-
-	ehci = hcd_to_ehci(hcd);
-	ehci->caps = hcd->regs;
-	ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase));
-	/* cache this readonly data; minimize chip reads */
-	ehci->hcs_params = readl(&ehci->caps->hcs_params);
-
-	/* ehci_hcd_init(hcd_to_ehci(hcd)); */
-
-	retval =
-	    usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED | IRQF_SHARED);
-	if (retval == 0)
-		return retval;
-
-	au1xxx_stop_ehc(dev);
-	iounmap(hcd->regs);
-err2:
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-err1:
-	usb_put_hcd(hcd);
-	return retval;
-}
-
-/* may be called without controller electrically present */
-/* may be called with controller, bus, and devices active */
-
-/**
- * usb_ehci_hcd_au1xxx_remove - shutdown processing for Au1xxx-based HCDs
- * @dev: USB Host Controller being removed
- * Context: !in_interrupt()
- *
- * Reverses the effect of usb_ehci_hcd_au1xxx_probe(), first invoking
- * the HCD's stop() method.  It is always called from a thread
- * context, normally "rmmod", "apmd", or something similar.
- *
- */
-void usb_ehci_au1xxx_remove(struct usb_hcd *hcd, struct platform_device *dev)
-{
-	usb_remove_hcd(hcd);
-	iounmap(hcd->regs);
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-	usb_put_hcd(hcd);
-	au1xxx_stop_ehc(dev);
-}
-
-/*-------------------------------------------------------------------------*/
-
 static const struct hc_driver ehci_au1xxx_hc_driver = {
-	.description = hcd_name,
-	.product_desc = "Au1xxx EHCI",
-	.hcd_priv_size = sizeof(struct ehci_hcd),
+	.description		= hcd_name,
+	.product_desc		= "Au1xxx EHCI",
+	.hcd_priv_size		= sizeof(struct ehci_hcd),
 
 	/*
 	 * generic hardware linkage
 	 */
-	.irq = ehci_irq,
-	.flags = HCD_MEMORY | HCD_USB2,
+	.irq			= ehci_irq,
+	.flags			= HCD_MEMORY | HCD_USB2,
 
 	/*
 	 * basic lifecycle operations
@@ -198,48 +86,98 @@
 	 * FIXME -- ehci_init() doesn't do enough here.
 	 * See ehci-ppc-soc for a complete implementation.
 	 */
-	.reset = ehci_init,
-	.start = ehci_run,
-	.stop = ehci_stop,
-	.shutdown = ehci_shutdown,
+	.reset			= ehci_init,
+	.start			= ehci_run,
+	.stop			= ehci_stop,
+	.shutdown		= ehci_shutdown,
 
 	/*
 	 * managing i/o requests and associated device resources
 	 */
-	.urb_enqueue = ehci_urb_enqueue,
-	.urb_dequeue = ehci_urb_dequeue,
-	.endpoint_disable = ehci_endpoint_disable,
+	.urb_enqueue		= ehci_urb_enqueue,
+	.urb_dequeue		= ehci_urb_dequeue,
+	.endpoint_disable	= ehci_endpoint_disable,
 
 	/*
 	 * scheduling support
 	 */
-	.get_frame_number = ehci_get_frame,
+	.get_frame_number	= ehci_get_frame,
 
 	/*
 	 * root hub support
 	 */
-	.hub_status_data = ehci_hub_status_data,
-	.hub_control = ehci_hub_control,
-	.bus_suspend = ehci_bus_suspend,
-	.bus_resume = ehci_bus_resume,
-	.relinquish_port = ehci_relinquish_port,
-	.port_handed_over = ehci_port_handed_over,
+	.hub_status_data	= ehci_hub_status_data,
+	.hub_control		= ehci_hub_control,
+	.bus_suspend		= ehci_bus_suspend,
+	.bus_resume		= ehci_bus_resume,
+	.relinquish_port	= ehci_relinquish_port,
+	.port_handed_over	= ehci_port_handed_over,
 };
 
-/*-------------------------------------------------------------------------*/
-
 static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
 {
-	struct usb_hcd *hcd = NULL;
+	struct usb_hcd *hcd;
+	struct ehci_hcd *ehci;
 	int ret;
 
-	pr_debug("In ehci_hcd_au1xxx_drv_probe\n");
-
 	if (usb_disabled())
 		return -ENODEV;
 
-	/* FIXME we only want one one probe() not two */
-	ret = usb_ehci_au1xxx_probe(&ehci_au1xxx_hc_driver, &hcd, pdev);
+#if defined(CONFIG_SOC_AU1200) && defined(CONFIG_DMA_COHERENT)
+	/* Au1200 AB USB does not support coherent memory */
+	if (!(read_c0_prid() & 0xff)) {
+		printk(KERN_INFO "%s: this is chip revision AB!\n", pdev->name);
+		printk(KERN_INFO "%s: update your board or re-configure"
+				 " the kernel\n", pdev->name);
+		return -ENODEV;
+	}
+#endif
+
+	if (pdev->resource[1].flags != IORESOURCE_IRQ) {
+		pr_debug("resource[1] is not IORESOURCE_IRQ");
+		return -ENOMEM;
+	}
+	hcd = usb_create_hcd(&ehci_au1xxx_hc_driver, &pdev->dev, "Au1xxx");
+	if (!hcd)
+		return -ENOMEM;
+
+	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)) {
+		pr_debug("request_mem_region failed");
+		ret = -EBUSY;
+		goto err1;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		pr_debug("ioremap failed");
+		ret = -ENOMEM;
+		goto err2;
+	}
+
+	au1xxx_start_ehc();
+
+	ehci = hcd_to_ehci(hcd);
+	ehci->caps = hcd->regs;
+	ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase));
+	/* cache this readonly data; minimize chip reads */
+	ehci->hcs_params = readl(&ehci->caps->hcs_params);
+
+	ret = usb_add_hcd(hcd, pdev->resource[1].start,
+			  IRQF_DISABLED | IRQF_SHARED);
+	if (ret == 0) {
+		platform_set_drvdata(pdev, hcd);
+		return ret;
+	}
+
+	au1xxx_stop_ehc();
+	iounmap(hcd->regs);
+err2:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err1:
+	usb_put_hcd(hcd);
 	return ret;
 }
 
@@ -247,35 +185,138 @@
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 
-	/* FIXME we only want one one remove() not two */
-	usb_ehci_au1xxx_remove(hcd, pdev);
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+	au1xxx_stop_ehc();
+	platform_set_drvdata(pdev, NULL);
+
 	return 0;
 }
 
- /*TBD*/
-/*static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
+#ifdef CONFIG_PM
+static int ehci_hcd_au1xxx_drv_suspend(struct platform_device *pdev,
+					pm_message_t message)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	unsigned long flags;
+	int rc;
 
 	return 0;
+	rc = 0;
+
+	if (time_before(jiffies, ehci->next_statechange))
+		msleep(10);
+
+	/* Root hub was already suspended. Disable irq emission and
+	 * mark HW unaccessible, bail out if RH has been resumed. Use
+	 * the spinlock to properly synchronize with possible pending
+	 * RH suspend or resume activity.
+	 *
+	 * This is still racy as hcd->state is manipulated outside of
+	 * any locks =P But that will be a different fix.
+	 */
+	spin_lock_irqsave(&ehci->lock, flags);
+	if (hcd->state != HC_STATE_SUSPENDED) {
+		rc = -EINVAL;
+		goto bail;
+	}
+	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+	(void)ehci_readl(ehci, &ehci->regs->intr_enable);
+
+	/* make sure snapshot being resumed re-enumerates everything */
+	if (message.event == PM_EVENT_PRETHAW) {
+		ehci_halt(ehci);
+		ehci_reset(ehci);
+	}
+
+	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+	au1xxx_stop_ehc();
+
+bail:
+	spin_unlock_irqrestore(&ehci->lock, flags);
+
+	// could save FLADJ in case of Vaux power loss
+	// ... we'd only use it to handle clock skew
+
+	return rc;
 }
-static int ehci_hcd_au1xxx_drv_resume(struct device *dev)
+
+
+static int ehci_hcd_au1xxx_drv_resume(struct platform_device *pdev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+
+	au1xxx_start_ehc();
+
+	// maybe restore FLADJ
+
+	if (time_before(jiffies, ehci->next_statechange))
+		msleep(100);
+
+	/* Mark hardware accessible again as we are out of D3 state by now */
+	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+	/* If CF is still set, we maintained PCI Vaux power.
+	 * Just undo the effect of ehci_pci_suspend().
+	 */
+	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
+		int	mask = INTR_MASK;
+
+		if (!hcd->self.root_hub->do_remote_wakeup)
+			mask &= ~STS_PCD;
+		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+		ehci_readl(ehci, &ehci->regs->intr_enable);
+		return 0;
+	}
+
+	ehci_dbg(ehci, "lost power, restarting\n");
+	usb_root_hub_lost_power(hcd->self.root_hub);
+
+	/* Else reset, to cope with power loss or flush-to-storage
+	 * style "resume" having let BIOS kick in during reboot.
+	 */
+	(void) ehci_halt(ehci);
+	(void) ehci_reset(ehci);
+
+	/* emptying the schedule aborts any urbs */
+	spin_lock_irq(&ehci->lock);
+	if (ehci->reclaim)
+		end_unlink_async(ehci);
+	ehci_work(ehci);
+	spin_unlock_irq(&ehci->lock);
+
+	ehci_writel(ehci, ehci->command, &ehci->regs->command);
+	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
+	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
+
+	/* here we "know" root ports should always stay powered */
+	ehci_port_power(ehci, 1);
+
+	hcd->state = HC_STATE_SUSPENDED;
 
 	return 0;
 }
-*/
-MODULE_ALIAS("platform:au1xxx-ehci");
+
+#else
+#define ehci_hcd_au1xxx_drv_suspend NULL
+#define ehci_hcd_au1xxx_drv_resume NULL
+#endif
+
 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, */
+	.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 = {
-		.name = "au1xxx-ehci",
+		.name	= "au1xxx-ehci",
+		.owner	= THIS_MODULE,
 	}
 };
+
+MODULE_ALIAS("platform:au1xxx-ehci");
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 0f82fdc..b0f8ed5 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -676,7 +676,7 @@
 			"%s\n"
 			"SUSPENDED (no register access)\n",
 			hcd->self.controller->bus->name,
-			hcd->self.controller->bus_id,
+			dev_name(hcd->self.controller),
 			hcd->product_desc);
 		goto done;
 	}
@@ -688,7 +688,7 @@
 		"%s\n"
 		"EHCI %x.%02x, hcd state %d\n",
 		hcd->self.controller->bus->name,
-		hcd->self.controller->bus_id,
+		dev_name(hcd->self.controller),
 		hcd->product_desc,
 		i >> 8, i & 0x0ff, hcd->state);
 	size -= temp;
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 7370d61..01c3da3 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -56,7 +56,7 @@
 	pdata = (struct fsl_usb2_platform_data *)pdev->dev.platform_data;
 	if (!pdata) {
 		dev_err(&pdev->dev,
-			"No platform data for %s.\n", pdev->dev.bus_id);
+			"No platform data for %s.\n", dev_name(&pdev->dev));
 		return -ENODEV;
 	}
 
@@ -69,7 +69,7 @@
 	      (pdata->operating_mode == FSL_USB2_DR_OTG))) {
 		dev_err(&pdev->dev,
 			"Non Host Mode configured for %s. Wrong driver linked.\n",
-			pdev->dev.bus_id);
+			dev_name(&pdev->dev));
 		return -ENODEV;
 	}
 
@@ -77,12 +77,12 @@
 	if (!res) {
 		dev_err(&pdev->dev,
 			"Found HC with no IRQ. Check %s setup!\n",
-			pdev->dev.bus_id);
+			dev_name(&pdev->dev));
 		return -ENODEV;
 	}
 	irq = res->start;
 
-	hcd = usb_create_hcd(driver, &pdev->dev, pdev->dev.bus_id);
+	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
 	if (!hcd) {
 		retval = -ENOMEM;
 		goto err1;
@@ -92,7 +92,7 @@
 	if (!res) {
 		dev_err(&pdev->dev,
 			"Found HC with no register addr. Check %s setup!\n",
-			pdev->dev.bus_id);
+			dev_name(&pdev->dev));
 		retval = -ENODEV;
 		goto err2;
 	}
@@ -132,7 +132,7 @@
       err2:
 	usb_put_hcd(hcd);
       err1:
-	dev_err(&pdev->dev, "init %s fail, %d\n", pdev->dev.bus_id, retval);
+	dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval);
 	return retval;
 }
 
@@ -230,8 +230,13 @@
 
 	/* put controller in host mode. */
 	ehci_writel(ehci, 0x00000003, non_ehci + FSL_SOC_USB_USBMODE);
+#ifdef CONFIG_PPC_85xx
+	out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);
+	out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
+#else
 	out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
 	out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
+#endif
 	out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
 }
 
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 369a8a5..d9d53f2 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -84,7 +84,7 @@
 #define EHCI_IAA_MSECS		10		/* arbitrary */
 #define EHCI_IO_JIFFIES		(HZ/10)		/* io watchdog > irq_thresh */
 #define EHCI_ASYNC_JIFFIES	(HZ/20)		/* async idle timeout */
-#define EHCI_SHRINK_JIFFIES	(HZ/200)	/* async qh unlink delay */
+#define EHCI_SHRINK_FRAMES	5		/* async qh unlink delay */
 
 /* Initial IRQ latency:  faster than hw default */
 static int log2_irq_thresh = 0;		// 0 to 6
diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c
index 9d042f2..f9575c4 100644
--- a/drivers/usb/host/ehci-ixp4xx.c
+++ b/drivers/usb/host/ehci-ixp4xx.c
@@ -77,12 +77,12 @@
 	if (!res) {
 		dev_err(&pdev->dev,
 			"Found HC with no IRQ. Check %s setup!\n",
-			pdev->dev.bus_id);
+			dev_name(&pdev->dev));
 		return -ENODEV;
 	}
 	irq = res->start;
 
-	hcd = usb_create_hcd(driver, &pdev->dev, pdev->dev.bus_id);
+	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
 	if (!hcd) {
 		retval = -ENOMEM;
 		goto fail_create_hcd;
@@ -92,7 +92,7 @@
 	if (!res) {
 		dev_err(&pdev->dev,
 			"Found HC with no register addr. Check %s setup!\n",
-			pdev->dev.bus_id);
+			dev_name(&pdev->dev));
 		retval = -ENODEV;
 		goto fail_request_resource;
 	}
@@ -126,7 +126,7 @@
 fail_request_resource:
 	usb_put_hcd(hcd);
 fail_create_hcd:
-	dev_err(&pdev->dev, "init %s fail, %d\n", pdev->dev.bus_id, retval);
+	dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval);
 	return retval;
 }
 
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index ab625f0..5fbdc14 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -204,7 +204,7 @@
 	if (irq <= 0) {
 		dev_err(&pdev->dev,
 			"Found HC with no IRQ. Check %s setup!\n",
-			pdev->dev.bus_id);
+			dev_name(&pdev->dev));
 		err = -ENODEV;
 		goto err1;
 	}
@@ -213,7 +213,7 @@
 	if (!res) {
 		dev_err(&pdev->dev,
 			"Found HC with no register addr. Check %s setup!\n",
-			pdev->dev.bus_id);
+			dev_name(&pdev->dev));
 		err = -ENODEV;
 		goto err1;
 	}
@@ -233,7 +233,7 @@
 	}
 
 	hcd = usb_create_hcd(&ehci_orion_hc_driver,
-			&pdev->dev, pdev->dev.bus_id);
+			&pdev->dev, dev_name(&pdev->dev));
 	if (!hcd) {
 		err = -ENOMEM;
 		goto err3;
@@ -276,7 +276,7 @@
 	release_mem_region(res->start, res->end - res->start + 1);
 err1:
 	dev_err(&pdev->dev, "init %s fail, %d\n",
-		pdev->dev.bus_id, err);
+		dev_name(&pdev->dev), err);
 
 	return err;
 }
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
index 37e6abe..0eba894 100644
--- a/drivers/usb/host/ehci-ps3.c
+++ b/drivers/usb/host/ehci-ps3.c
@@ -128,7 +128,7 @@
 
 	dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */
 
-	hcd = usb_create_hcd(&ps3_ehci_hc_driver, &dev->core, dev->core.bus_id);
+	hcd = usb_create_hcd(&ps3_ehci_hc_driver, &dev->core, dev_name(&dev->core));
 
 	if (!hcd) {
 		dev_dbg(&dev->core, "%s:%d: usb_create_hcd failed\n", __func__,
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index b85b541..2622b65 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -1116,8 +1116,7 @@
 	struct ehci_qh		*qh;
 	enum ehci_timer_action	action = TIMER_IO_WATCHDOG;
 
-	if (!++(ehci->stamp))
-		ehci->stamp++;
+	ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index);
 	timer_action_done (ehci, TIMER_ASYNC_SHRINK);
 rescan:
 	qh = ehci->async->qh_next.qh;
@@ -1142,18 +1141,20 @@
 				}
 			}
 
-			/* unlink idle entries, reducing HC PCI usage as well
+			/* unlink idle entries, reducing DMA usage as well
 			 * as HCD schedule-scanning costs.  delay for any qh
 			 * we just scanned, there's a not-unusual case that it
 			 * doesn't stay idle for long.
 			 * (plus, avoids some kind of re-activation race.)
 			 */
-			if (list_empty (&qh->qtd_list)) {
-				if (qh->stamp == ehci->stamp)
+			if (list_empty(&qh->qtd_list)
+					&& qh->qh_state == QH_STATE_LINKED) {
+				if (!ehci->reclaim
+					&& ((ehci->stamp - qh->stamp) & 0x1fff)
+						>= (EHCI_SHRINK_FRAMES * 8))
+					start_unlink_async(ehci, qh);
+				else
 					action = TIMER_ASYNC_SHRINK;
-				else if (!ehci->reclaim
-					    && qh->qh_state == QH_STATE_LINKED)
-					start_unlink_async (ehci, qh);
 			}
 
 			qh = qh->qh_next.qh;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 90245fd..5799298 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -198,7 +198,10 @@
 			break;
 		// case TIMER_ASYNC_SHRINK:
 		default:
-			t = EHCI_SHRINK_JIFFIES;
+			/* add a jiffie since we synch against the
+			 * 8 KHz uframe counter.
+			 */
+			t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1;
 			break;
 		}
 		mod_timer(&ehci->watchdog, t + jiffies);
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 20b9a0d..31178e1 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -94,6 +94,10 @@
 	u16 w;
 	int quot = len % 4;
 
+	/* buffer is already in 'usb data order', which is LE. */
+	/* When reading buffer as u16, we have to take care byte order */
+	/* doesn't get mixed up */
+
 	if ((unsigned long)dp2 & 1) {
 		/* not aligned */
 		for (; len > 1; len -= 2) {
@@ -105,8 +109,11 @@
 			isp116x_write_data16(isp116x, (u16) * dp);
 	} else {
 		/* aligned */
-		for (; len > 1; len -= 2)
-			isp116x_raw_write_data16(isp116x, *dp2++);
+		for (; len > 1; len -= 2) {
+			/* Keep byte order ! */
+			isp116x_raw_write_data16(isp116x, cpu_to_le16(*dp2++));
+		}
+
 		if (len)
 			isp116x_write_data16(isp116x, 0xff & *((u8 *) dp2));
 	}
@@ -124,6 +131,10 @@
 	u16 w;
 	int quot = len % 4;
 
+	/* buffer is already in 'usb data order', which is LE. */
+	/* When reading buffer as u16, we have to take care byte order */
+	/* doesn't get mixed up */
+
 	if ((unsigned long)dp2 & 1) {
 		/* not aligned */
 		for (; len > 1; len -= 2) {
@@ -131,12 +142,16 @@
 			*dp++ = w & 0xff;
 			*dp++ = (w >> 8) & 0xff;
 		}
+
 		if (len)
 			*dp = 0xff & isp116x_read_data16(isp116x);
 	} else {
 		/* aligned */
-		for (; len > 1; len -= 2)
-			*dp2++ = isp116x_raw_read_data16(isp116x);
+		for (; len > 1; len -= 2) {
+			/* Keep byte order! */
+			*dp2++ = le16_to_cpu(isp116x_raw_read_data16(isp116x));
+		}
+
 		if (len)
 			*(u8 *) dp2 = 0xff & isp116x_read_data16(isp116x);
 	}
@@ -1592,7 +1607,7 @@
 	}
 
 	/* allocate and initialize hcd */
-	hcd = usb_create_hcd(&isp116x_hc_driver, &pdev->dev, pdev->dev.bus_id);
+	hcd = usb_create_hcd(&isp116x_hc_driver, &pdev->dev, dev_name(&pdev->dev));
 	if (!hcd) {
 		ret = -ENOMEM;
 		goto err5;
diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c
index 65aa5ec..c858f2a 100644
--- a/drivers/usb/host/isp1760-hcd.c
+++ b/drivers/usb/host/isp1760-hcd.c
@@ -38,6 +38,7 @@
 	unsigned		i_thresh;
 	unsigned long		reset_done;
 	unsigned long		next_statechange;
+	unsigned int		devflags;
 };
 
 static inline struct isp1760_hcd *hcd_to_priv(struct usb_hcd *hcd)
@@ -378,9 +379,31 @@
 {
 	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	int result;
-	u32 scratch;
+	u32 scratch, hwmode;
+
+	/* Setup HW Mode Control: This assumes a level active-low interrupt */
+	hwmode = HW_DATA_BUS_32BIT;
+
+	if (priv->devflags & ISP1760_FLAG_BUS_WIDTH_16)
+		hwmode &= ~HW_DATA_BUS_32BIT;
+	if (priv->devflags & ISP1760_FLAG_ANALOG_OC)
+		hwmode |= HW_ANA_DIGI_OC;
+	if (priv->devflags & ISP1760_FLAG_DACK_POL_HIGH)
+		hwmode |= HW_DACK_POL_HIGH;
+	if (priv->devflags & ISP1760_FLAG_DREQ_POL_HIGH)
+		hwmode |= HW_DREQ_POL_HIGH;
+
+	/*
+	 * We have to set this first in case we're in 16-bit mode.
+	 * Write it twice to ensure correct upper bits if switching
+	 * to 16-bit mode.
+	 */
+	isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL);
+	isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL);
 
 	isp1760_writel(0xdeadbabe, hcd->regs + HC_SCRATCH_REG);
+	/* Change bus pattern */
+	scratch = isp1760_readl(hcd->regs + HC_CHIP_ID_REG);
 	scratch = isp1760_readl(hcd->regs + HC_SCRATCH_REG);
 	if (scratch != 0xdeadbabe) {
 		printk(KERN_ERR "ISP1760: Scratch test failed.\n");
@@ -403,17 +426,29 @@
 
 	/* Step 11 passed */
 
+	isp1760_info(priv, "bus width: %d, oc: %s\n",
+			   (priv->devflags & ISP1760_FLAG_BUS_WIDTH_16) ?
+			   16 : 32, (priv->devflags & ISP1760_FLAG_ANALOG_OC) ?
+			   "analog" : "digital");
+
+	/* ATL reset */
+	isp1760_writel(hwmode | ALL_ATX_RESET, hcd->regs + HC_HW_MODE_CTRL);
+	mdelay(10);
+	isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL);
+
 	isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_REG);
 	isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_ENABLE);
 
-	/* ATL reset */
-	scratch = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
-	isp1760_writel(scratch | ALL_ATX_RESET, hcd->regs + HC_HW_MODE_CTRL);
-	mdelay(10);
-	isp1760_writel(scratch, hcd->regs + HC_HW_MODE_CTRL);
-
-	isp1760_writel(PORT1_POWER | PORT1_INIT2, hcd->regs + HC_PORT1_CTRL);
-	mdelay(10);
+	/*
+	 * PORT 1 Control register of the ISP1760 is the OTG control
+	 * register on ISP1761.
+	 */
+	if (!(priv->devflags & ISP1760_FLAG_ISP1761) &&
+	    !(priv->devflags & ISP1760_FLAG_PORT1_DIS)) {
+		isp1760_writel(PORT1_POWER | PORT1_INIT2,
+			       hcd->regs + HC_PORT1_CTRL);
+		mdelay(10);
+	}
 
 	priv->hcs_params = isp1760_readl(hcd->regs + HC_HCSPARAMS);
 
@@ -453,8 +488,7 @@
 	hcd->state = HC_STATE_RUNNING;
 	isp1760_enable_interrupts(hcd);
 	temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
-	temp |= FINAL_HW_CONFIG;
-	isp1760_writel(temp, hcd->regs + HC_HW_MODE_CTRL);
+	isp1760_writel(temp | HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL);
 
 	command = isp1760_readl(hcd->regs + HC_USBCMD);
 	command &= ~(CMD_LRESET|CMD_RESET);
@@ -782,8 +816,8 @@
 	qtd->status |= slot << 16;
 }
 
-void enqueue_an_ATL_packet(struct usb_hcd *hcd, struct isp1760_qh *qh,
-		struct isp1760_qtd *qtd)
+static void enqueue_an_ATL_packet(struct usb_hcd *hcd, struct isp1760_qh *qh,
+				  struct isp1760_qtd *qtd)
 {
 	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	u32 skip_map, or_map;
@@ -816,8 +850,8 @@
 	isp1760_writel(buffstatus, hcd->regs + HC_BUFFER_STATUS_REG);
 }
 
-void enqueue_an_INT_packet(struct usb_hcd *hcd, struct isp1760_qh *qh,
-		struct isp1760_qtd *qtd)
+static void enqueue_an_INT_packet(struct usb_hcd *hcd, struct isp1760_qh *qh,
+				  struct isp1760_qtd *qtd)
 {
 	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	u32 skip_map, or_map;
@@ -1592,7 +1626,7 @@
 	struct inter_packet_info *ints;
 	u32 i;
 	u32 reg_base, or_reg, skip_reg;
-	int flags;
+	unsigned long flags;
 	struct ptd ptd;
 
 	switch (usb_pipetype(urb->pipe)) {
@@ -2061,7 +2095,7 @@
 	struct isp1760_hcd *priv = hcd_to_priv(usb_hcd);
 	struct isp1760_qh *qh;
 	struct isp1760_qtd *qtd;
-	u32 flags;
+	unsigned long flags;
 
 	spin_lock_irqsave(&priv->lock, flags);
 	qh = ep->hcpriv;
@@ -2112,6 +2146,7 @@
 static void isp1760_stop(struct usb_hcd *hcd)
 {
 	struct isp1760_hcd *priv = hcd_to_priv(hcd);
+	u32 temp;
 
 	isp1760_hub_control(hcd, ClearPortFeature, USB_PORT_FEAT_POWER,	1,
 			NULL, 0);
@@ -2120,7 +2155,8 @@
 	spin_lock_irq(&priv->lock);
 	ehci_reset(priv);
 	/* Disable IRQ */
-	isp1760_writel(HW_DATA_BUS_32BIT, hcd->regs + HC_HW_MODE_CTRL);
+	temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
+	isp1760_writel(temp &= ~HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL);
 	spin_unlock_irq(&priv->lock);
 
 	isp1760_writel(0, hcd->regs + HC_CONFIGFLAG);
@@ -2128,10 +2164,11 @@
 
 static void isp1760_shutdown(struct usb_hcd *hcd)
 {
-	u32 command;
+	u32 command, temp;
 
 	isp1760_stop(hcd);
-	isp1760_writel(HW_DATA_BUS_32BIT, hcd->regs + HC_HW_MODE_CTRL);
+	temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
+	isp1760_writel(temp &= ~HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL);
 
 	command = isp1760_readl(hcd->regs + HC_USBCMD);
 	command &= ~CMD_RUN;
@@ -2183,7 +2220,8 @@
 }
 
 struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq,
-		u64 irqflags, struct device *dev, const char *busname)
+		u64 irqflags, struct device *dev, const char *busname,
+		unsigned int devflags)
 {
 	struct usb_hcd *hcd;
 	struct isp1760_hcd *priv;
@@ -2195,11 +2233,12 @@
 	/* prevent usb-core allocating DMA pages */
 	dev->dma_mask = NULL;
 
-	hcd = usb_create_hcd(&isp1760_hc_driver, dev, dev->bus_id);
+	hcd = usb_create_hcd(&isp1760_hc_driver, dev, dev_name(dev));
 	if (!hcd)
 		return ERR_PTR(-ENOMEM);
 
 	priv = hcd_to_priv(hcd);
+	priv->devflags = devflags;
 	init_memory(priv);
 	hcd->regs = ioremap(res_start, res_len);
 	if (!hcd->regs) {
diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h
index 3d86d0f..6473dd8 100644
--- a/drivers/usb/host/isp1760-hcd.h
+++ b/drivers/usb/host/isp1760-hcd.h
@@ -3,7 +3,8 @@
 
 /* exports for if */
 struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq,
-		u64 irqflags, struct device *dev, const char *busname);
+		u64 irqflags, struct device *dev, const char *busname,
+		unsigned int devflags);
 int init_kmem_once(void);
 void deinit_kmem_cache(void);
 
@@ -31,6 +32,7 @@
 /* Configuration Register */
 #define HC_HW_MODE_CTRL		0x300
 #define ALL_ATX_RESET		(1 << 31)
+#define HW_ANA_DIGI_OC		(1 << 15)
 #define HW_DATA_BUS_32BIT	(1 << 8)
 #define HW_DACK_POL_HIGH	(1 << 6)
 #define HW_DREQ_POL_HIGH	(1 << 5)
@@ -56,13 +58,14 @@
 #define PORT1_POWER		(3 << 3)
 #define PORT1_INIT1		(1 << 7)
 #define PORT1_INIT2		(1 << 23)
+#define HW_OTG_CTRL_SET		0x374
+#define HW_OTG_CTRL_CLR		0x376
 
 /* Interrupt Register */
 #define HC_INTERRUPT_REG	0x310
 
 #define HC_INTERRUPT_ENABLE	0x314
 #define INTERRUPT_ENABLE_MASK	(HC_INTL_INT | HC_ATL_INT | HC_EOT_INT)
-#define FINAL_HW_CONFIG	(HW_GLOBAL_INTR_EN | HW_DATA_BUS_32BIT)
 
 #define HC_ISO_INT		(1 << 9)
 #define HC_ATL_INT		(1 << 8)
@@ -122,6 +125,19 @@
 #define isp1760_err(priv, fmt, args...) \
 	dev_err(priv_to_hcd(priv)->self.controller, fmt, ##args)
 
+/*
+ * Device flags that can vary from board to board.  All of these
+ * indicate the most "atypical" case, so that a devflags of 0 is
+ * a sane default configuration.
+ */
+#define ISP1760_FLAG_PORT1_DIS		0x00000001 /* Port 1 disabled */
+#define ISP1760_FLAG_BUS_WIDTH_16	0x00000002 /* 16-bit data bus width */
+#define ISP1760_FLAG_OTG_EN		0x00000004 /* Port 1 supports OTG */
+#define ISP1760_FLAG_ANALOG_OC		0x00000008 /* Analog overcurrent */
+#define ISP1760_FLAG_DACK_POL_HIGH	0x00000010 /* DACK active high */
+#define ISP1760_FLAG_DREQ_POL_HIGH	0x00000020 /* DREQ active high */
+#define ISP1760_FLAG_ISP1761		0x00000040 /* Chip is ISP1761 */
+
 /* chip memory management */
 struct memory_chunk {
 	unsigned int start;
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c
index c9db3fe..051ef7b 100644
--- a/drivers/usb/host/isp1760-if.c
+++ b/drivers/usb/host/isp1760-if.c
@@ -35,13 +35,15 @@
 	int virq;
 	u64 res_len;
 	int ret;
+	const unsigned int *prop;
+	unsigned int devflags = 0;
 
 	ret = of_address_to_resource(dp, 0, &memory);
 	if (ret)
 		return -ENXIO;
 
 	res = request_mem_region(memory.start, memory.end - memory.start + 1,
-			dev->dev.bus_id);
+			dev_name(&dev->dev));
 	if (!res)
 		return -EBUSY;
 
@@ -55,8 +57,32 @@
 	virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
 			oirq.size);
 
+	if (of_device_is_compatible(dp, "nxp,usb-isp1761"))
+		devflags |= ISP1760_FLAG_ISP1761;
+
+	if (of_get_property(dp, "port1-disable", NULL) != NULL)
+		devflags |= ISP1760_FLAG_PORT1_DIS;
+
+	/* Some systems wire up only 16 of the 32 data lines */
+	prop = of_get_property(dp, "bus-width", NULL);
+	if (prop && *prop == 16)
+		devflags |= ISP1760_FLAG_BUS_WIDTH_16;
+
+	if (of_get_property(dp, "port1-otg", NULL) != NULL)
+		devflags |= ISP1760_FLAG_OTG_EN;
+
+	if (of_get_property(dp, "analog-oc", NULL) != NULL)
+		devflags |= ISP1760_FLAG_ANALOG_OC;
+
+	if (of_get_property(dp, "dack-polarity", NULL) != NULL)
+		devflags |= ISP1760_FLAG_DACK_POL_HIGH;
+
+	if (of_get_property(dp, "dreq-polarity", NULL) != NULL)
+		devflags |= ISP1760_FLAG_DREQ_POL_HIGH;
+
 	hcd = isp1760_register(memory.start, res_len, virq,
-		IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev->dev.bus_id);
+		IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev),
+		devflags);
 	if (IS_ERR(hcd)) {
 		ret = PTR_ERR(hcd);
 		goto release_reg;
@@ -87,6 +113,9 @@
 	{
 		.compatible = "nxp,usb-isp1760",
 	},
+	{
+		.compatible = "nxp,usb-isp1761",
+	},
 	{ },
 };
 MODULE_DEVICE_TABLE(of, of_isp1760_match);
@@ -116,6 +145,7 @@
 	int length;
 	int status = 1;
 	struct usb_hcd *hcd;
+	unsigned int devflags = 0;
 
 	if (usb_disabled())
 		return -ENODEV;
@@ -200,7 +230,8 @@
 
 	dev->dev.dma_mask = NULL;
 	hcd = isp1760_register(pci_mem_phy0, length, dev->irq,
-		IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev->dev.bus_id);
+		IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev),
+		devflags);
 	pci_set_drvdata(dev, hcd);
 	if (!hcd)
 		return 0;
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index e534f9d..a5d8e550 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -91,7 +91,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);
+static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);
 
 /* configure so an HC device and id are always provided */
 /* always called with process context; sleeping is OK */
@@ -184,13 +184,14 @@
  * context, "rmmod" or something similar.
  *
  */
-static int usb_hcd_at91_remove(struct usb_hcd *hcd,
+static void usb_hcd_at91_remove(struct usb_hcd *hcd,
 				struct platform_device *pdev)
 {
 	usb_remove_hcd(hcd);
 	at91_stop_hc(pdev);
 	iounmap(hcd->regs);
 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
 
 	if (cpu_is_at91sam9261())
 		clk_put(hclk);
@@ -199,7 +200,6 @@
 	fclk = iclk = hclk = NULL;
 
 	dev_set_drvdata(&pdev->dev, NULL);
-	return 0;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -309,7 +309,8 @@
 	}
 
 	device_init_wakeup(&pdev->dev, 0);
-	return usb_hcd_at91_remove(platform_get_drvdata(pdev), pdev);
+	usb_hcd_at91_remove(platform_get_drvdata(pdev), pdev);
+	return 0;
 }
 
 #ifdef CONFIG_PM
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
index 68c17f5..c094800 100644
--- a/drivers/usb/host/ohci-au1xxx.c
+++ b/drivers/usb/host/ohci-au1xxx.c
@@ -34,7 +34,8 @@
 #ifdef __LITTLE_ENDIAN
 #define USBH_ENABLE_INIT (USBH_ENABLE_CE | USBH_ENABLE_E | USBH_ENABLE_C)
 #elif __BIG_ENDIAN
-#define USBH_ENABLE_INIT (USBH_ENABLE_CE | USBH_ENABLE_E | USBH_ENABLE_C | USBH_ENABLE_BE)
+#define USBH_ENABLE_INIT (USBH_ENABLE_CE | USBH_ENABLE_E | USBH_ENABLE_C | \
+			  USBH_ENABLE_BE)
 #else
 #error not byte order defined
 #endif
@@ -46,213 +47,87 @@
 #define USB_MCFG_RDCOMB   (1<<30)
 #define USB_MCFG_SSDEN    (1<<23)
 #define USB_MCFG_OHCCLKEN (1<<16)
+#ifdef CONFIG_DMA_COHERENT
 #define USB_MCFG_UCAM     (1<<7)
+#else
+#define USB_MCFG_UCAM     (0)
+#endif
 #define USB_MCFG_OBMEN    (1<<1)
 #define USB_MCFG_OMEMEN   (1<<0)
 
 #define USBH_ENABLE_CE    USB_MCFG_OHCCLKEN
-#ifdef CONFIG_DMA_COHERENT
-#define USBH_ENABLE_INIT  (USB_MCFG_OHCCLKEN \
-                         | USB_MCFG_PFEN | USB_MCFG_RDCOMB \
-                         | USB_MCFG_SSDEN | USB_MCFG_UCAM \
-                         | USB_MCFG_OBMEN | USB_MCFG_OMEMEN)
-#else
-#define USBH_ENABLE_INIT  (USB_MCFG_OHCCLKEN \
-                         | USB_MCFG_PFEN | USB_MCFG_RDCOMB \
-                         | USB_MCFG_SSDEN \
-                         | USB_MCFG_OBMEN | USB_MCFG_OMEMEN)
-#endif
+
+#define USBH_ENABLE_INIT  (USB_MCFG_PFEN  | USB_MCFG_RDCOMB 	|	\
+			   USBH_ENABLE_CE | USB_MCFG_SSDEN	|	\
+			   USB_MCFG_UCAM  |				\
+			   USB_MCFG_OBMEN | USB_MCFG_OMEMEN)
+
 #define USBH_DISABLE      (USB_MCFG_OBMEN | USB_MCFG_OMEMEN)
 
 #endif  /* Au1200 */
 
 extern int usb_disabled(void);
 
-/*-------------------------------------------------------------------------*/
-
-static void au1xxx_start_ohc(struct platform_device *dev)
+static void au1xxx_start_ohc(void)
 {
-	printk(KERN_DEBUG __FILE__
-		": starting Au1xxx OHCI USB Controller\n");
-
 	/* enable host controller */
-
 #ifndef CONFIG_SOC_AU1200
-
 	au_writel(USBH_ENABLE_CE, USB_HOST_CONFIG);
-	udelay(1000);
-	au_writel(USBH_ENABLE_INIT, USB_HOST_CONFIG);
+	au_sync();
 	udelay(1000);
 
-#else   /* Au1200 */
-
-	/* write HW defaults again in case Yamon cleared them */
-	if (au_readl(USB_HOST_CONFIG) == 0) {
-		au_writel(0x00d02000, USB_HOST_CONFIG);
-		au_readl(USB_HOST_CONFIG);
-		udelay(1000);
-	}
-	au_writel(USBH_ENABLE_CE | au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG);
-	au_readl(USB_HOST_CONFIG);
-	udelay(1000);
-	au_writel(USBH_ENABLE_INIT | au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG);
-	au_readl(USB_HOST_CONFIG);
+	au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_INIT, USB_HOST_CONFIG);
+	au_sync();
 	udelay(1000);
 
-#endif  /* Au1200 */
-
-#ifndef CONFIG_SOC_AU1200
 	/* wait for reset complete (read register twice; see au1500 errata) */
 	while (au_readl(USB_HOST_CONFIG),
 		!(au_readl(USB_HOST_CONFIG) & USBH_ENABLE_RD))
-#endif
 		udelay(1000);
 
-	printk(KERN_DEBUG __FILE__
-	": Clock to USB host has been enabled \n");
-}
-
-static void au1xxx_stop_ohc(struct platform_device *dev)
-{
-	printk(KERN_DEBUG __FILE__
-	       ": stopping Au1xxx OHCI USB Controller\n");
-
-#ifndef CONFIG_SOC_AU1200
-
-	/* Disable clock */
-	au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_ENABLE_CE, USB_HOST_CONFIG);
-
 #else   /* Au1200 */
-
-	/* Disable mem */
-	au_writel(~USBH_DISABLE & au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG);
+	au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_CE, USB_HOST_CONFIG);
+	au_sync();
 	udelay(1000);
-	/* Disable clock */
-	au_writel(~USBH_ENABLE_CE & au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG);
-	au_readl(USB_HOST_CONFIG);
+
+	au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_INIT, USB_HOST_CONFIG);
+	au_sync();
+	udelay(2000);
 #endif  /* Au1200 */
 }
 
-
-/*-------------------------------------------------------------------------*/
-
-/* configure so an HC device and id are always provided */
-/* always called with process context; sleeping is OK */
-
-
-/**
- * usb_ohci_au1xxx_probe - initialize Au1xxx-based HCDs
- * Context: !in_interrupt()
- *
- * Allocates basic resources for this USB host controller, and
- * then invokes the start() method for the HCD associated with it
- * through the hotplug entry's driver_data.
- *
- */
-static int usb_ohci_au1xxx_probe(const struct hc_driver *driver,
-			  struct platform_device *dev)
+static void au1xxx_stop_ohc(void)
 {
-	int retval;
-	struct usb_hcd *hcd;
-
-#if defined(CONFIG_SOC_AU1200) && defined(CONFIG_DMA_COHERENT)
-	/* Au1200 AB USB does not support coherent memory */
-	if (!(read_c0_prid() & 0xff)) {
-		pr_info("%s: this is chip revision AB !!\n",
-			dev->name);
-		pr_info("%s: update your board or re-configure the kernel\n",
-			dev->name);
-		return -ENODEV;
-	}
+#ifdef CONFIG_SOC_AU1200
+	/* Disable mem */
+	au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_DISABLE, USB_HOST_CONFIG);
+	au_sync();
+	udelay(1000);
 #endif
-
-	if (dev->resource[1].flags != IORESOURCE_IRQ) {
-		pr_debug("resource[1] is not IORESOURCE_IRQ\n");
-		return -ENOMEM;
-	}
-
-	hcd = usb_create_hcd(driver, &dev->dev, "au1xxx");
-	if (!hcd)
-		return -ENOMEM;
-	hcd->rsrc_start = dev->resource[0].start;
-	hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
-
-	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-		pr_debug("request_mem_region failed\n");
-		retval = -EBUSY;
-		goto err1;
-	}
-
-	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-	if (!hcd->regs) {
-		pr_debug("ioremap failed\n");
-		retval = -ENOMEM;
-		goto err2;
-	}
-
-	au1xxx_start_ohc(dev);
-	ohci_hcd_init(hcd_to_ohci(hcd));
-
-	retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED | IRQF_SHARED);
-	if (retval == 0)
-		return retval;
-
-	au1xxx_stop_ohc(dev);
-	iounmap(hcd->regs);
- err2:
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- err1:
-	usb_put_hcd(hcd);
-	return retval;
+	/* Disable clock */
+	au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_ENABLE_CE, USB_HOST_CONFIG);
+	au_sync();
 }
 
-
-/* may be called without controller electrically present */
-/* may be called with controller, bus, and devices active */
-
-/**
- * usb_hcd_au1xxx_remove - shutdown processing for Au1xxx-based HCDs
- * @dev: USB Host Controller being removed
- * Context: !in_interrupt()
- *
- * Reverses the effect of usb_hcd_au1xxx_probe(), first invoking
- * the HCD's stop() method.  It is always called from a thread
- * context, normally "rmmod", "apmd", or something similar.
- *
- */
-static void usb_ohci_au1xxx_remove(struct usb_hcd *hcd, struct platform_device *dev)
+static int __devinit ohci_au1xxx_start(struct usb_hcd *hcd)
 {
-	usb_remove_hcd(hcd);
-	au1xxx_stop_ohc(dev);
-	iounmap(hcd->regs);
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-	usb_put_hcd(hcd);
-}
+	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+	int ret;
 
-/*-------------------------------------------------------------------------*/
+	ohci_dbg(ohci, "ohci_au1xxx_start, ohci:%p", ohci);
 
-static int __devinit
-ohci_au1xxx_start (struct usb_hcd *hcd)
-{
-	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
-	int		ret;
-
-	ohci_dbg (ohci, "ohci_au1xxx_start, ohci:%p", ohci);
-
-	if ((ret = ohci_init (ohci)) < 0)
+	if ((ret = ohci_init(ohci)) < 0)
 		return ret;
 
-	if ((ret = ohci_run (ohci)) < 0) {
+	if ((ret = ohci_run(ohci)) < 0) {
 		err ("can't start %s", hcd->self.bus_name);
-		ohci_stop (hcd);
+		ohci_stop(hcd);
 		return ret;
 	}
 
 	return 0;
 }
 
-/*-------------------------------------------------------------------------*/
-
 static const struct hc_driver ohci_au1xxx_hc_driver = {
 	.description =		hcd_name,
 	.product_desc =		"Au1xxx OHCI",
@@ -296,18 +171,66 @@
 	.start_port_reset =	ohci_start_port_reset,
 };
 
-/*-------------------------------------------------------------------------*/
-
 static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
 {
 	int ret;
-
-	pr_debug ("In ohci_hcd_au1xxx_drv_probe");
+	struct usb_hcd *hcd;
 
 	if (usb_disabled())
 		return -ENODEV;
 
-	ret = usb_ohci_au1xxx_probe(&ohci_au1xxx_hc_driver, pdev);
+#if defined(CONFIG_SOC_AU1200) && defined(CONFIG_DMA_COHERENT)
+	/* Au1200 AB USB does not support coherent memory */
+	if (!(read_c0_prid() & 0xff)) {
+		printk(KERN_INFO "%s: this is chip revision AB !!\n",
+			pdev->name);
+		printk(KERN_INFO "%s: update your board or re-configure "
+				 "the kernel\n", pdev->name);
+		return -ENODEV;
+	}
+#endif
+
+	if (pdev->resource[1].flags != IORESOURCE_IRQ) {
+		pr_debug("resource[1] is not IORESOURCE_IRQ\n");
+		return -ENOMEM;
+	}
+
+	hcd = usb_create_hcd(&ohci_au1xxx_hc_driver, &pdev->dev, "au1xxx");
+	if (!hcd)
+		return -ENOMEM;
+
+	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)) {
+		pr_debug("request_mem_region failed\n");
+		ret = -EBUSY;
+		goto err1;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		pr_debug("ioremap failed\n");
+		ret = -ENOMEM;
+		goto err2;
+	}
+
+	au1xxx_start_ohc();
+	ohci_hcd_init(hcd_to_ohci(hcd));
+
+	ret = usb_add_hcd(hcd, pdev->resource[1].start,
+			  IRQF_DISABLED | IRQF_SHARED);
+	if (ret == 0) {
+		platform_set_drvdata(pdev, hcd);
+		return ret;
+	}
+
+	au1xxx_stop_ohc();
+	iounmap(hcd->regs);
+err2:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err1:
+	usb_put_hcd(hcd);
 	return ret;
 }
 
@@ -315,30 +238,78 @@
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 
-	usb_ohci_au1xxx_remove(hcd, pdev);
-	return 0;
-}
-	/*TBD*/
-/*static int ohci_hcd_au1xxx_drv_suspend(struct platform_device *dev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(dev);
+	usb_remove_hcd(hcd);
+	au1xxx_stop_ohc();
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+	platform_set_drvdata(pdev, NULL);
 
 	return 0;
 }
-static int ohci_hcd_au1xxx_drv_resume(struct platform_device *dev)
+
+#ifdef CONFIG_PM
+static int ohci_hcd_au1xxx_drv_suspend(struct platform_device *pdev,
+					pm_message_t message)
 {
-	struct usb_hcd *hcd = platform_get_drvdata(dev);
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+	unsigned long flags;
+	int rc;
+
+	rc = 0;
+
+	/* Root hub was already suspended. Disable irq emission and
+	 * mark HW unaccessible, bail out if RH has been resumed. Use
+	 * the spinlock to properly synchronize with possible pending
+	 * RH suspend or resume activity.
+	 *
+	 * This is still racy as hcd->state is manipulated outside of
+	 * any locks =P But that will be a different fix.
+	 */
+	spin_lock_irqsave(&ohci->lock, flags);
+	if (hcd->state != HC_STATE_SUSPENDED) {
+		rc = -EINVAL;
+		goto bail;
+	}
+	ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
+	(void)ohci_readl(ohci, &ohci->regs->intrdisable);
+
+	/* make sure snapshot being resumed re-enumerates everything */
+	if (message.event == PM_EVENT_PRETHAW)
+		ohci_usb_reset(ohci);
+
+	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+	au1xxx_stop_ohc();
+bail:
+	spin_unlock_irqrestore(&ohci->lock, flags);
+
+	return rc;
+}
+
+static int ohci_hcd_au1xxx_drv_resume(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+	au1xxx_start_ohc();
+
+	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+	ohci_finish_controller_resume(hcd);
 
 	return 0;
 }
-*/
+#else
+#define ohci_hcd_au1xxx_drv_suspend NULL
+#define ohci_hcd_au1xxx_drv_resume NULL
+#endif
 
 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, */
+	.suspend	= ohci_hcd_au1xxx_drv_suspend,
+	.resume		= ohci_hcd_au1xxx_drv_resume,
 	.driver		= {
 		.name	= "au1xxx-ohci",
 		.owner	= THIS_MODULE,
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index e06bfae..7cef1d2 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -651,7 +651,7 @@
 		"%s\n"
 		"%s version " DRIVER_VERSION "\n",
 		hcd->self.controller->bus->name,
-		hcd->self.controller->bus_id,
+		dev_name(hcd->self.controller),
 		hcd->product_desc,
 		hcd_name);
 
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index a8160d6..26bc479 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -974,7 +974,7 @@
 #define PCI_DRIVER		ohci_pci_driver
 #endif
 
-#ifdef CONFIG_SA1111
+#if defined(CONFIG_ARCH_SA1100) && defined(CONFIG_SA1111)
 #include "ohci-sa1111.c"
 #define SA1111_DRIVER		ohci_hcd_sa1111_driver
 #endif
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index a19a4f8..6e5e5f8 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -329,7 +329,7 @@
 	}
 
 
-	hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id);
+	hcd = usb_create_hcd (driver, &pdev->dev, dev_name(&pdev->dev));
 	if (!hcd) {
 		retval = -ENOMEM;
 		goto err0;
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
index 28b458f2..6ad8f2f 100644
--- a/drivers/usb/host/ohci-pnx4008.c
+++ b/drivers/usb/host/ohci-pnx4008.c
@@ -109,8 +109,6 @@
 
 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 const unsigned short normal_i2c[] =
     { ISP1301_I2C_ADDR, ISP1301_I2C_ADDR + 1, I2C_CLIENT_END };
@@ -123,30 +121,37 @@
 };
 
 struct i2c_driver isp1301_driver = {
-	.class = I2C_CLASS_HWMON,
+	.driver = {
+		.name = "isp1301_pnx",
+	},
 	.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;
+	int err;
 
 	c = kzalloc(sizeof(*c), GFP_KERNEL);
-
 	if (!c)
 		return -ENOMEM;
 
-	strcpy(c->name, "isp1301");
+	strlcpy(c->name, "isp1301_pnx", I2C_NAME_SIZE);
 	c->flags = 0;
 	c->addr = addr;
 	c->adapter = adap;
 	c->driver = &isp1301_driver;
 
+	err = i2c_attach_client(c);
+	if (err) {
+		kfree(c);
+		return err;
+	}
+
 	isp1301_i2c_client = c;
 
-	return i2c_attach_client(c);
+	return 0;
 }
 
 static int isp1301_probe(struct i2c_adapter *adap)
@@ -161,13 +166,6 @@
 	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];
@@ -389,7 +387,7 @@
 	while ((__raw_readl(USB_OTG_CLK_STAT) & USB_CLOCK_MASK) !=
 	       USB_CLOCK_MASK) ;
 
-	hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id);
+	hcd = usb_create_hcd (driver, &pdev->dev, dev_name(&pdev->dev));
 	if (!hcd) {
 		err("Failed to allocate HC buffer");
 		ret = -ENOMEM;
diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
index a672527..91e6e10 100644
--- a/drivers/usb/host/ohci-ppc-of.c
+++ b/drivers/usb/host/ohci-ppc-of.c
@@ -14,8 +14,8 @@
  */
 
 #include <linux/signal.h>
+#include <linux/of_platform.h>
 
-#include <asm/of_platform.h>
 #include <asm/prom.h>
 
 
diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c
index c1935ae..55c9564 100644
--- a/drivers/usb/host/ohci-ps3.c
+++ b/drivers/usb/host/ohci-ps3.c
@@ -129,7 +129,7 @@
 
 	dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */
 
-	hcd = usb_create_hcd(&ps3_ohci_hc_driver, &dev->core, dev->core.bus_id);
+	hcd = usb_create_hcd(&ps3_ohci_hc_driver, &dev->core, dev_name(&dev->core));
 
 	if (!hcd) {
 		dev_dbg(&dev->core, "%s:%d: usb_create_hcd failed\n", __func__,
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index 9b54740..6a9b4c5 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -159,9 +159,6 @@
 {
 	int	branch;
 
-	if (ohci_to_hcd(ohci)->state == HC_STATE_QUIESCING)
-		return -EAGAIN;
-
 	ed->state = ED_OPER;
 	ed->ed_prev = NULL;
 	ed->ed_next = NULL;
diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
index e610698..21b164e 100644
--- a/drivers/usb/host/ohci-sm501.c
+++ b/drivers/usb/host/ohci-sm501.c
@@ -143,7 +143,7 @@
 		goto err2;
 	}
 
-	hcd = usb_create_hcd(driver, &pdev->dev, pdev->dev.bus_id);
+	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
 	if (!hcd) {
 		retval = -ENOMEM;
 		goto err2;
diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c
index 7275186..3660c83 100644
--- a/drivers/usb/host/ohci-ssb.c
+++ b/drivers/usb/host/ohci-ssb.c
@@ -113,7 +113,7 @@
 	ssb_device_enable(dev, flags);
 
 	hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev,
-			dev->dev->bus_id);
+			dev_name(dev->dev));
 	if (!hcd)
 		goto err_dev_disable;
 	ohcidev = hcd_to_ssb_ohci(hcd);
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index 1666734..d5f02dd 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -312,9 +312,9 @@
 static void set_pipe_reg_addr(struct r8a66597_pipe *pipe, u8 dma_ch)
 {
 	u16 pipenum = pipe->info.pipenum;
-	unsigned long fifoaddr[] = {D0FIFO, D1FIFO, CFIFO};
-	unsigned long fifosel[] = {D0FIFOSEL, D1FIFOSEL, CFIFOSEL};
-	unsigned long fifoctr[] = {D0FIFOCTR, D1FIFOCTR, CFIFOCTR};
+	const unsigned long fifoaddr[] = {D0FIFO, D1FIFO, CFIFO};
+	const unsigned long fifosel[] = {D0FIFOSEL, D1FIFOSEL, CFIFOSEL};
+	const unsigned long fifoctr[] = {D0FIFOCTR, D1FIFOCTR, CFIFOCTR};
 
 	if (dma_ch > R8A66597_PIPE_NO_DMA)	/* dma fifo not use? */
 		dma_ch = R8A66597_PIPE_NO_DMA;
@@ -863,6 +863,32 @@
 	dev->dma_map = 0;
 }
 
+static u16 get_interval(struct urb *urb, __u8 interval)
+{
+	u16 time = 1;
+	int i;
+
+	if (urb->dev->speed == USB_SPEED_HIGH) {
+		if (interval > IITV)
+			time = IITV;
+		else
+			time = interval ? interval - 1 : 0;
+	} else {
+		if (interval > 128) {
+			time = IITV;
+		} else {
+			/* calculate the nearest value for PIPEPERI */
+			for (i = 0; i < 7; i++) {
+				if ((1 << i) < interval &&
+				    (1 << (i + 1) > interval))
+					time = 1 << i;
+			}
+		}
+	}
+
+	return time;
+}
+
 static unsigned long get_timer_interval(struct urb *urb, __u8 interval)
 {
 	__u8 i;
@@ -901,10 +927,7 @@
 		info.interval = 0;
 		info.timer_interval = 0;
 	} else {
-		if (ep->bInterval > IITV)
-			info.interval = IITV;
-		else
-			info.interval = ep->bInterval ? ep->bInterval - 1 : 0;
+		info.interval = get_interval(urb, ep->bInterval);
 		info.timer_interval = get_timer_interval(urb, ep->bInterval);
 	}
 	if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
@@ -2244,6 +2267,7 @@
 	struct r8a66597 *r8a66597;
 	int ret = 0;
 	int i;
+	unsigned long irq_trigger;
 
 	if (pdev->dev.dma_mask) {
 		ret = -EINVAL;
@@ -2302,7 +2326,11 @@
 	INIT_LIST_HEAD(&r8a66597->child_device);
 
 	hcd->rsrc_start = res->start;
-	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
+	if (irq_sense == INTL)
+		irq_trigger = IRQF_TRIGGER_LOW;
+	else
+		irq_trigger = IRQF_TRIGGER_FALLING;
+	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | irq_trigger);
 	if (ret != 0) {
 		err("Failed to add hcd");
 		goto clean_up;
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 4265752..340d72d 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -1674,7 +1674,7 @@
 	}
 
 	/* allocate and initialize hcd */
-	hcd = usb_create_hcd(&sl811h_hc_driver, &dev->dev, dev->dev.bus_id);
+	hcd = usb_create_hcd(&sl811h_hc_driver, &dev->dev, dev_name(&dev->dev));
 	if (!hcd) {
 		retval = -ENOMEM;
 		goto err5;
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
index 9b6323f..20ad3c4 100644
--- a/drivers/usb/host/u132-hcd.c
+++ b/drivers/usb/host/u132-hcd.c
@@ -3124,7 +3124,7 @@
 	if (pdev->dev.dma_mask)
 		return -EINVAL;
 
-	hcd = usb_create_hcd(&u132_hc_driver, &pdev->dev, pdev->dev.bus_id);
+	hcd = usb_create_hcd(&u132_hc_driver, &pdev->dev, dev_name(&pdev->dev));
 	if (!hcd) {
 		printk(KERN_ERR "failed to create the usb hcd struct for U132\n"
 			);
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index 8e4427a..885b585 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -12,7 +12,7 @@
  * (C) Copyright 2004 Alan Stern, stern@rowland.harvard.edu
  */
 
-static __u8 root_hub_hub_des[] =
+static const __u8 root_hub_hub_des[] =
 {
 	0x09,			/*  __u8  bLength; */
 	0x29,			/*  __u8  bDescriptorType; Hub-descriptor */
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index 0939386..d2f61d5 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -1421,7 +1421,8 @@
 
 
 /* IOCTL functions */
-static int auerchar_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long auerchar_ioctl(struct file *file, unsigned int cmd,
+							unsigned long arg)
 {
 	pauerchar_t ccp = (pauerchar_t) file->private_data;
 	int ret = 0;
@@ -1452,7 +1453,7 @@
 		mutex_unlock(&ccp->mutex);
                 return -ENODEV;
 	}
-
+	lock_kernel();
 	switch (cmd) {
 
 	/* return != 0 if Transmitt channel ready to send */
@@ -1547,9 +1548,10 @@
 
 	default:
 		dbg ("IOCTL_AU_UNKNOWN");
-		ret = -ENOIOCTLCMD;
+		ret = -ENOTTY;
 		break;
         }
+        unlock_kernel();
 	/* release the mutexes */
 	mutex_unlock(&cp->mutex);
 	mutex_unlock(&ccp->mutex);
@@ -1860,7 +1862,7 @@
 	.llseek =	no_llseek,
 	.read =		auerchar_read,
 	.write =        auerchar_write,
-	.ioctl =	auerchar_ioctl,
+	.unlocked_ioctl = auerchar_ioctl,
 	.open =		auerchar_open,
 	.release =	auerchar_release,
 };
diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c
index 20886c2..5d859de 100644
--- a/drivers/usb/misc/emi62.c
+++ b/drivers/usb/misc/emi62.c
@@ -6,8 +6,6 @@
  * 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.
- * 
- * $Id: emi62.c,v 1.15 2002/04/23 06:13:59 tapio Exp $
  */
 #include <linux/kernel.h>
 #include <linux/errno.h>
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index ec88b3b..97c2809 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -656,29 +656,6 @@
 }
 
 
-#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
@@ -1222,7 +1199,6 @@
 static const 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,
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
index 1cb54a2..e6ca997 100644
--- a/drivers/usb/misc/iowarrior.c
+++ b/drivers/usb/misc/iowarrior.c
@@ -474,8 +474,8 @@
 /**
  *	iowarrior_ioctl
  */
-static int iowarrior_ioctl(struct inode *inode, struct file *file,
-			   unsigned int cmd, unsigned long arg)
+static long iowarrior_ioctl(struct file *file, unsigned int cmd,
+							unsigned long arg)
 {
 	struct iowarrior *dev = NULL;
 	__u8 *buffer;
@@ -493,6 +493,7 @@
 		return -ENOMEM;
 
 	/* lock this object */
+	lock_kernel();
 	mutex_lock(&dev->mutex);
 
 	/* verify that the device wasn't unplugged */
@@ -584,6 +585,7 @@
 error_out:
 	/* unlock the device */
 	mutex_unlock(&dev->mutex);
+	unlock_kernel();
 	kfree(buffer);
 	return retval;
 }
@@ -719,7 +721,7 @@
 	.owner = THIS_MODULE,
 	.write = iowarrior_write,
 	.read = iowarrior_read,
-	.ioctl = iowarrior_ioctl,
+	.unlocked_ioctl = iowarrior_ioctl,
 	.open = iowarrior_open,
 	.release = iowarrior_release,
 	.poll = iowarrior_poll,
diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
index 330c18e..248a12a 100644
--- a/drivers/usb/misc/rio500.c
+++ b/drivers/usb/misc/rio500.c
@@ -104,9 +104,7 @@
 	return 0;
 }
 
-static int
-ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd,
-	  unsigned long arg)
+static long ioctl_rio(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	struct RioCommand rio_cmd;
 	struct rio_usb_data *rio = &rio_instance;
@@ -116,6 +114,7 @@
 	int retries;
 	int retval=0;
 
+	lock_kernel();
 	mutex_lock(&(rio->lock));
         /* Sanity check to make sure rio is connected, powered, etc */
         if (rio->present == 0 || rio->rio_dev == NULL) {
@@ -254,6 +253,7 @@
 
 err_out:
 	mutex_unlock(&(rio->lock));
+	unlock_kernel();
 	return retval;
 }
 
@@ -433,7 +433,7 @@
 	.owner =	THIS_MODULE,
 	.read =		read_rio,
 	.write =	write_rio,
-	.ioctl =	ioctl_rio,
+	.unlocked_ioctl = ioctl_rio,
 	.open =		open_rio,
 	.release =	close_rio,
 };
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 33182f4..fbace41 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -2982,9 +2982,8 @@
 	return retval;
 }
 
-static int
-sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-							unsigned long arg)
+static long
+sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	struct sisusb_usb_data *sisusb;
 	struct sisusb_info x;
@@ -2995,6 +2994,7 @@
 	if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
 		return -ENODEV;
 
+	lock_kernel();
 	mutex_lock(&sisusb->lock);
 
 	/* Sanity check */
@@ -3053,6 +3053,7 @@
 
 err_out:
 	mutex_unlock(&sisusb->lock);
+	unlock_kernel();
 	return retval;
 }
 
@@ -3066,9 +3067,7 @@
 		case SISUSB_GET_CONFIG_SIZE:
 		case SISUSB_GET_CONFIG:
 		case SISUSB_COMMAND:
-			lock_kernel();
-			retval = sisusb_ioctl(f->f_path.dentry->d_inode, f, cmd, arg);
-			unlock_kernel();
+			retval = sisusb_ioctl(f, cmd, arg);
 			return retval;
 
 		default:
@@ -3087,7 +3086,7 @@
 #ifdef SISUSB_NEW_CONFIG_COMPAT
 	.compat_ioctl = sisusb_compat_ioctl,
 #endif
-	.ioctl =	sisusb_ioctl
+	.unlocked_ioctl = sisusb_ioctl
 };
 
 static struct usb_class_driver usb_sisusb_class = {
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index 7f7021e..2db4228 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -146,7 +146,7 @@
 	return retval;
 }
 
-static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long lcd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	struct usb_lcd *dev;
 	u16 bcdDevice;
@@ -158,12 +158,14 @@
 	
 	switch (cmd) {
 	case IOCTL_GET_HARD_VERSION:
+		lock_kernel();
 		bcdDevice = le16_to_cpu((dev->udev)->descriptor.bcdDevice);
 		sprintf(buf,"%1d%1d.%1d%1d",
 			(bcdDevice & 0xF000)>>12,
 			(bcdDevice & 0xF00)>>8,
 			(bcdDevice & 0xF0)>>4,
 			(bcdDevice & 0xF));
+		unlock_kernel();
 		if (copy_to_user((void __user *)arg,buf,strlen(buf))!=0)
 			return -EFAULT;
 		break;
@@ -272,7 +274,7 @@
         .read =         lcd_read,
         .write =        lcd_write,
         .open =         lcd_open,
-	.ioctl =        lcd_ioctl,
+	.unlocked_ioctl = lcd_ioctl,
         .release =      lcd_release,
 };
 
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index 293a462..6566fc0 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -1162,8 +1162,9 @@
 	if (minor >= MON_BIN_MAX_MINOR)
 		return 0;
 
-	dev = device_create(mon_bin_class, ubus? ubus->controller: NULL,
-			MKDEV(MAJOR(mon_bin_dev0), minor), "usbmon%d", minor);
+	dev = device_create_drvdata(mon_bin_class, ubus? ubus->controller: NULL,
+				    MKDEV(MAJOR(mon_bin_dev0), minor), NULL,
+				    "usbmon%d", minor);
 	if (IS_ERR(dev))
 		return 0;
 
diff --git a/drivers/usb/mon/mon_stat.c b/drivers/usb/mon/mon_stat.c
index c7a595c..ac8b0d5 100644
--- a/drivers/usb/mon/mon_stat.c
+++ b/drivers/usb/mon/mon_stat.c
@@ -9,6 +9,7 @@
 
 #include <linux/kernel.h>
 #include <linux/usb.h>
+#include <linux/fs.h>
 #include <asm/uaccess.h>
 
 #include "usb_mon.h"
@@ -42,19 +43,8 @@
 				size_t nbytes, loff_t *ppos)
 {
 	struct snap *sp = file->private_data;
-	loff_t pos = *ppos;
-	int cnt;
 
-	if (pos < 0 || pos >= sp->slen)
-		return 0;
-	if (nbytes == 0)
-		return 0;
-	if ((cnt = sp->slen - pos) > nbytes)
-		cnt = nbytes;
-	if (copy_to_user(buf, sp->str + pos, cnt))
-		return -EFAULT;
-	*ppos = pos + cnt;
-	return cnt;
+	return simple_read_from_buffer(buf, nbytes, ppos, sp->str, sp->slen);
 }
 
 static int mon_stat_release(struct inode *inode, struct file *file)
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 9a7681b..8878c17 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -64,14 +64,6 @@
 	    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"
-	help
-	  Say Y here if you want to use a AirPrime CDMA Wireless PC card.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called airprime.
-
 config USB_SERIAL_ARK3116
 	tristate "USB ARK Micro 3116 USB Serial Driver"
 	help
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 17a762a..6047f81 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -12,7 +12,6 @@
 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
 obj-$(CONFIG_USB_SERIAL_CH341)			+= ch341.o
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
index db6f97a..79ea98c 100644
--- a/drivers/usb/serial/aircable.c
+++ b/drivers/usb/serial/aircable.c
@@ -272,7 +272,7 @@
 	 * 64 bytes, to ensure I do not get throttled.
 	 * Ask USB mailing list for better aproach.
 	 */
-	tty = port->tty;
+	tty = port->port.tty;
 
 	if (!tty) {
 		schedule_work(&priv->rx_work);
@@ -378,13 +378,14 @@
 	}
 }
 
-static int aircable_write_room(struct usb_serial_port *port)
+static int aircable_write_room(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	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,
+static int aircable_write(struct tty_struct *tty, struct usb_serial_port *port,
 			  const unsigned char *source, int count)
 {
 	struct aircable_private *priv = usb_get_serial_port_data(port);
@@ -466,7 +467,7 @@
 
 	if (status) {
 		dbg("%s - urb status = %d", __func__, status);
-		if (!port->open_count) {
+		if (!port->port.count) {
 			dbg("%s - port is closed, exiting.", __func__);
 			return;
 		}
@@ -494,7 +495,7 @@
 	usb_serial_debug_data(debug, &port->dev, __func__,
 				urb->actual_length, urb->transfer_buffer);
 
-	tty = port->tty;
+	tty = port->port.tty;
 	if (tty && urb->actual_length) {
 		if (urb->actual_length <= 2) {
 			/* This is an incomplete package */
@@ -528,7 +529,7 @@
 	}
 
 	/* Schedule the next read _if_ we are still open */
-	if (port->open_count) {
+	if (port->port.count) {
 		usb_fill_bulk_urb(port->read_urb, port->serial->dev,
 				  usb_rcvbulkpipe(port->serial->dev,
 					  port->bulk_in_endpointAddress),
@@ -547,8 +548,9 @@
 }
 
 /* Based on ftdi_sio.c throttle */
-static void aircable_throttle(struct usb_serial_port *port)
+static void aircable_throttle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct aircable_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 
@@ -560,8 +562,9 @@
 }
 
 /* Based on ftdi_sio.c unthrottle */
-static void aircable_unthrottle(struct usb_serial_port *port)
+static void aircable_unthrottle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct aircable_private *priv = usb_get_serial_port_data(port);
 	int actually_throttled;
 	unsigned long flags;
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
deleted file mode 100644
index 0798c14..0000000
--- a/drivers/usb/serial/airprime.c
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * AirPrime CDMA Wireless Serial USB driver
- *
- * Copyright (C) 2005-2006 Greg Kroah-Hartman <gregkh@suse.de>
- *
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the GNU General Public License version
- *	2 as published by the Free Software Foundation.
- */
-
-#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 */
-	{ },
-};
-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];
-
-	/* Settings for the port */
-	int rts_state;	/* Handshaking pins (outputs) */
-	int dtr_state;
-	int cts_state;	/* Handshaking pins (inputs) */
-	int dsr_state;
-	int dcd_state;
-	int ri_state;
-};
-
-static int airprime_send_setup(struct usb_serial_port *port)
-{
-	struct usb_serial *serial = port->serial;
-	struct airprime_private *priv;
-
-	dbg("%s", __func__);
-
-	if (port->number != 0)
-		return 0;
-
-	priv = usb_get_serial_port_data(port);
-
-	if (port->tty) {
-		int val = 0;
-		if (priv->dtr_state)
-			val |= 0x01;
-		if (priv->rts_state)
-			val |= 0x02;
-
-		return usb_control_msg(serial->dev,
-					usb_rcvctrlpipe(serial->dev, 0),
-					0x22, 0x21, val, 0, NULL, 0,
-					USB_CTRL_SET_TIMEOUT);
-	}
-
-	return 0;
-}
-
-static void airprime_read_bulk_callback(struct urb *urb)
-{
-	struct usb_serial_port *port = urb->context;
-	unsigned char *data = urb->transfer_buffer;
-	struct tty_struct *tty;
-	int result;
-	int status = urb->status;
-
-	dbg("%s - port %d", __func__, port->number);
-
-	if (status) {
-		dbg("%s - nonzero read bulk status received: %d",
-		    __func__, status);
-		return;
-	}
-	usb_serial_debug_data(debug, &port->dev, __func__,
-						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",
-			__func__, result);
-	return;
-}
-
-static void airprime_write_bulk_callback(struct urb *urb)
-{
-	struct usb_serial_port *port = urb->context;
-	struct airprime_private *priv = usb_get_serial_port_data(port);
-	int status = urb->status;
-	unsigned long flags;
-
-	dbg("%s - port %d", __func__, port->number);
-
-	/* free up the transfer buffer, as usb_free_urb() does not do this */
-	kfree(urb->transfer_buffer);
-
-	if (status)
-		dbg("%s - nonzero write bulk status received: %d",
-		    __func__, 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", __func__, 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);
-	}
-
-	/* Set some sane defaults */
-	priv->rts_state = 1;
-	priv->dtr_state = 1;
-
-	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",
-				__func__);
-			result = -ENOMEM;
-			goto errout;
-		}
-		urb = usb_alloc_urb(0, GFP_KERNEL);
-		if (!urb) {
-			kfree(buffer);
-			dev_err(&port->dev, "%s - no more urbs?\n",
-				__func__);
-			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) {
-			usb_free_urb(urb);
-			kfree(buffer);
-			dev_err(&port->dev,
-				"%s - failed submitting read urb %d for port %d, error %d\n",
-				__func__, i, port->number, result);
-			goto errout;
-		}
-		/* remember this urb so we can kill it when the
-		   port is closed */
-		priv->read_urbp[i] = urb;
-	}
-
-	airprime_send_setup(port);
-
-	goto out;
-
- errout:
-	/* some error happened, cancel any submitted urbs and clean up
-	   anything that got allocated successfully */
-
-	while (i-- != 0) {
-		urb = priv->read_urbp[i];
-		buffer = urb->transfer_buffer;
-		usb_kill_urb(urb);
-		usb_free_urb(urb);
-		kfree(buffer);
-	}
-
- 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", __func__, port->number);
-
-	priv->rts_state = 0;
-	priv->dtr_state = 0;
-
-	mutex_lock(&port->serial->disc_mutex);
-	if (!port->serial->disconnected)
-		airprime_send_setup(port);
-	mutex_unlock(&port->serial->disc_mutex);
-
-	for (i = 0; i < NUM_READ_URBS; ++i) {
-		usb_kill_urb(priv->read_urbp[i]);
-		kfree(priv->read_urbp[i]->transfer_buffer);
-		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", __func__, 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", __func__);
-		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, __func__, 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",
-			__func__, 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,
-};
-
-static struct usb_serial_driver airprime_device = {
-	.driver = {
-		.owner =	THIS_MODULE,
-		.name =		"airprime",
-	},
-	.usb_driver =		&airprime_driver,
-	.id_table =		id_table,
-	.open =			airprime_open,
-	.close =		airprime_close,
-	.write =		airprime_write,
-};
-
-static int __init airprime_init(void)
-{
-	int retval;
-
-	airprime_device.num_ports = endpoints;
-	if (endpoints < 0 || endpoints >= MAX_BULK_EPS)
-		airprime_device.num_ports = NUM_BULK_EPS;
-
-	retval = usb_serial_register(&airprime_device);
-	if (retval)
-		return retval;
-	retval = usb_register(&airprime_driver);
-	if (retval)
-		usb_serial_deregister(&airprime_device);
-	return retval;
-}
-
-static void __exit airprime_exit(void)
-{
-	dbg("%s", __func__);
-
-	usb_deregister(&airprime_driver);
-	usb_serial_deregister(&airprime_device);
-}
-
-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 77895c8..aec6188 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -158,12 +158,13 @@
 	return -ENOMEM;
 }
 
-static void ark3116_set_termios(struct usb_serial_port *port,
+static void ark3116_set_termios(struct tty_struct *tty,
+				struct usb_serial_port *port,
 				struct ktermios *old_termios)
 {
 	struct usb_serial *serial = port->serial;
 	struct ark3116_private *priv = usb_get_serial_port_data(port);
-	struct ktermios *termios = port->tty->termios;
+	struct ktermios *termios = tty->termios;
 	unsigned int cflag = termios->c_cflag;
 	unsigned long flags;
 	int baud;
@@ -177,8 +178,8 @@
 
 	spin_lock_irqsave(&priv->lock, flags);
 	if (!priv->termios_initialized) {
-		*(port->tty->termios) = tty_std_termios;
-		port->tty->termios->c_cflag = B9600 | CS8
+		*termios = tty_std_termios;
+		termios->c_cflag = B9600 | CS8
 					      | CREAD | HUPCL | CLOCAL;
 		termios->c_ispeed = 9600;
 		termios->c_ospeed = 9600;
@@ -192,7 +193,7 @@
 	buf = kmalloc(1, GFP_KERNEL);
 	if (!buf) {
 		dbg("error kmalloc");
-		*port->tty->termios = *old_termios;
+		*termios = *old_termios;
 		return;
 	}
 
@@ -243,7 +244,7 @@
 	}
 
 	/* set baudrate */
-	baud = tty_get_baud_rate(port->tty);
+	baud = tty_get_baud_rate(tty);
 
 	switch (baud) {
 	case 75:
@@ -262,11 +263,11 @@
 	case 230400:
 	case 460800:
 		/* Report the resulting rate back to the caller */
-		tty_encode_baud_rate(port->tty, baud, baud);
+		tty_encode_baud_rate(tty, baud, baud);
 		break;
 	/* set 9600 as default (if given baudrate is invalid for example) */
 	default:
-		tty_encode_baud_rate(port->tty, 9600, 9600);
+		tty_encode_baud_rate(tty, 9600, 9600);
 	case 0:
 		baud = 9600;
 	}
@@ -317,7 +318,8 @@
 	return;
 }
 
-static int ark3116_open(struct usb_serial_port *port, struct file *filp)
+static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port,
+					struct file *filp)
 {
 	struct ktermios tmp_termios;
 	struct usb_serial *serial = port->serial;
@@ -332,7 +334,7 @@
 		return -ENOMEM;
 	}
 
-	result = usb_serial_generic_open(port, filp);
+	result = usb_serial_generic_open(tty, port, filp);
 	if (result)
 		goto err_out;
 
@@ -362,8 +364,8 @@
 	ARK3116_RCV(serial, 124, 0xFE, 0xC0, 0x0000, 0x0006, 0xFF, buf);
 
 	/* initialise termios */
-	if (port->tty)
-		ark3116_set_termios(port, &tmp_termios);
+	if (tty)
+		ark3116_set_termios(tty, port, &tmp_termios);
 
 err_out:
 	kfree(buf);
@@ -371,9 +373,10 @@
 	return result;
 }
 
-static int ark3116_ioctl(struct usb_serial_port *port, struct file *file,
+static int ark3116_ioctl(struct tty_struct *tty, struct file *file,
 			 unsigned int cmd, unsigned long arg)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct serial_struct serstruct;
 	void __user *user_arg = (void __user *)arg;
 
@@ -403,8 +406,9 @@
 	return -ENOIOCTLCMD;
 }
 
-static int ark3116_tiocmget(struct usb_serial_port *port, struct file *file)
+static int ark3116_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct usb_serial *serial = port->serial;
 	char *buf;
 	char temp;
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 0a322fc..2ebe06c 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -7,13 +7,14 @@
  *  This program is largely derived from work by the linux-usb group
  *  and associated source files.  Please see the usb/serial files for
  *  individual credits and copyrights.
- *  
+ *
  * 	This program is free software; you can redistribute it and/or modify
  * 	it under the terms of the GNU General Public License as published by
  * 	the Free Software Foundation; either version 2 of the License, or
  * 	(at your option) any later version.
  *
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
  *
  * TODO:
  * -- Add true modem contol line query capability.  Currently we track the
@@ -28,7 +29,8 @@
  * 	compressed all the differnent device entries into 1.
  *
  * 30-May-2001 gkh
- *	switched from using spinlock to a semaphore, which fixes lots of problems.
+ *	switched from using spinlock to a semaphore, which fixes lots of
+ *	problems.
  *
  * 08-Apr-2001 gb
  *	- Identify version on module load.
@@ -41,7 +43,7 @@
  *	- Added support for the old Belkin and Peracom devices.
  *	- Made the port able to be opened multiple times.
  *	- Added some defaults incase the line settings are things these devices
- *	  can't support. 
+ *	  can't support.
  *
  * 18-Oct-2000 William Greathouse
  *    Released into the wild (linux-usb-devel)
@@ -72,7 +74,7 @@
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 #include "belkin_sa.h"
@@ -87,16 +89,19 @@
 #define DRIVER_DESC "USB Belkin Serial converter driver"
 
 /* function prototypes for a Belkin USB Serial Adapter F5U103 */
-static int  belkin_sa_startup		(struct usb_serial *serial);
-static void belkin_sa_shutdown		(struct usb_serial *serial);
-static int  belkin_sa_open		(struct usb_serial_port *port, struct file *filp);
-static void belkin_sa_close		(struct usb_serial_port *port, struct file *filp);
-static void belkin_sa_read_int_callback (struct urb *urb);
-static void belkin_sa_set_termios	(struct usb_serial_port *port, struct ktermios * old);
-static int  belkin_sa_ioctl		(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void belkin_sa_break_ctl		(struct usb_serial_port *port, int break_state );
-static int  belkin_sa_tiocmget		(struct usb_serial_port *port, struct file *file);
-static int  belkin_sa_tiocmset		(struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
+static int  belkin_sa_startup(struct usb_serial *serial);
+static void belkin_sa_shutdown(struct usb_serial *serial);
+static int  belkin_sa_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
+static void belkin_sa_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
+static void belkin_sa_read_int_callback(struct urb *urb);
+static void belkin_sa_set_termios(struct tty_struct *tty,
+			struct usb_serial_port *port, struct ktermios * old);
+static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state);
+static int  belkin_sa_tiocmget(struct tty_struct *tty, struct file *file);
+static int  belkin_sa_tiocmset(struct tty_struct *tty, struct file *file,
+					unsigned int set, unsigned int clear);
 
 
 static struct usb_device_id id_table_combined [] = {
@@ -106,10 +111,10 @@
 	{ USB_DEVICE(GOHUBS_VID, GOHUBS_PID) },
 	{ USB_DEVICE(GOHUBS_VID, HANDYLINK_PID) },
 	{ USB_DEVICE(BELKIN_DOCKSTATION_VID, BELKIN_DOCKSTATION_PID) },
-	{ }							/* Terminating entry */
+	{ }	/* Terminating entry */
 };
 
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
 
 static struct usb_driver belkin_driver = {
 	.name =		"belkin",
@@ -131,8 +136,8 @@
 	.num_ports =		1,
 	.open =			belkin_sa_open,
 	.close =		belkin_sa_close,
-	.read_int_callback =	belkin_sa_read_int_callback,	/* How we get the status info */
-	.ioctl =		belkin_sa_ioctl,
+	.read_int_callback =	belkin_sa_read_int_callback,
+					/* How we get the status info */
 	.set_termios =		belkin_sa_set_termios,
 	.break_ctl =		belkin_sa_break_ctl,
 	.tiocmget =		belkin_sa_tiocmget,
@@ -160,12 +165,12 @@
 #define WDR_TIMEOUT 5000 /* default urb timeout */
 
 /* assumes that struct usb_serial *serial is available */
-#define BSA_USB_CMD(c,v) usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), \
+#define BSA_USB_CMD(c, v) usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), \
 					    (c), BELKIN_SA_SET_REQUEST_TYPE, \
 					    (v), 0, NULL, 0, WDR_TIMEOUT)
 
 /* do some startup allocations not currently performed by usb_serial_probe() */
-static int belkin_sa_startup (struct usb_serial *serial)
+static int belkin_sa_startup(struct usb_serial *serial)
 {
 	struct usb_device *dev = serial->dev;
 	struct belkin_sa_private *priv;
@@ -173,32 +178,35 @@
 	/* allocate the private data structure */
 	priv = kmalloc(sizeof(struct belkin_sa_private), GFP_KERNEL);
 	if (!priv)
-		return (-1); /* error */
+		return -1; /* error */
 	/* set initial values for control structures */
 	spin_lock_init(&priv->lock);
 	priv->control_state = 0;
 	priv->last_lsr = 0;
 	priv->last_msr = 0;
 	/* see comments at top of file */
-	priv->bad_flow_control = (le16_to_cpu(dev->descriptor.bcdDevice) <= 0x0206) ? 1 : 0;
-	info("bcdDevice: %04x, bfc: %d", le16_to_cpu(dev->descriptor.bcdDevice), priv->bad_flow_control);
+	priv->bad_flow_control =
+		(le16_to_cpu(dev->descriptor.bcdDevice) <= 0x0206) ? 1 : 0;
+	info("bcdDevice: %04x, bfc: %d",
+					le16_to_cpu(dev->descriptor.bcdDevice),
+					priv->bad_flow_control);
 
 	init_waitqueue_head(&serial->port[0]->write_wait);
 	usb_set_serial_port_data(serial->port[0], priv);
-	
-	return (0);
+
+	return 0;
 }
 
 
-static void belkin_sa_shutdown (struct usb_serial *serial)
+static void belkin_sa_shutdown(struct usb_serial *serial)
 {
 	struct belkin_sa_private *priv;
 	int i;
-	
-	dbg ("%s", __func__);
+
+	dbg("%s", __func__);
 
 	/* stop reads and writes on all ports */
-	for (i=0; i < serial->num_ports; ++i) {
+	for (i = 0; i < serial->num_ports; ++i) {
 		/* My special items, the standard routines free my urbs */
 		priv = usb_get_serial_port_data(serial->port[i]);
 		kfree(priv);
@@ -206,7 +214,8 @@
 }
 
 
-static int  belkin_sa_open (struct usb_serial_port *port, struct file *filp)
+static int  belkin_sa_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	int retval = 0;
 
@@ -235,7 +244,8 @@
 } /* belkin_sa_open */
 
 
-static void belkin_sa_close (struct usb_serial_port *port, struct file *filp)
+static void belkin_sa_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	dbg("%s port %d", __func__, port->number);
 
@@ -246,7 +256,7 @@
 } /* belkin_sa_close */
 
 
-static void belkin_sa_read_int_callback (struct urb *urb)
+static void belkin_sa_read_int_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 	struct belkin_sa_private *priv;
@@ -272,7 +282,8 @@
 		goto exit;
 	}
 
-	usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+	usb_serial_debug_data(debug, &port->dev, __func__,
+					urb->actual_length, data);
 
 	/* Handle known interrupt data */
 	/* ignore data[0] and data[1] */
@@ -280,7 +291,7 @@
 	priv = usb_get_serial_port_data(port);
 	spin_lock_irqsave(&priv->lock, flags);
 	priv->last_msr = data[BELKIN_SA_MSR_INDEX];
-	
+
 	/* Record Control Line states */
 	if (priv->last_msr & BELKIN_SA_MSR_DSR)
 		priv->control_state |= TIOCM_DSR;
@@ -311,7 +322,7 @@
 	 * to look in to this before committing any code.
 	 */
 	if (priv->last_lsr & BELKIN_SA_LSR_ERR) {
-		tty = port->tty;
+		tty = port->port.tty;
 		/* Overrun Error */
 		if (priv->last_lsr & BELKIN_SA_LSR_OE) {
 		}
@@ -328,13 +339,14 @@
 #endif
 	spin_unlock_irqrestore(&priv->lock, flags);
 exit:
-	retval = usb_submit_urb (urb, GFP_ATOMIC);
+	retval = usb_submit_urb(urb, GFP_ATOMIC);
 	if (retval)
-		err ("%s - usb_submit_urb failed with result %d",
+		err("%s - usb_submit_urb failed with result %d",
 		     __func__, retval);
 }
 
-static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
+static void belkin_sa_set_termios(struct tty_struct *tty,
+		struct usb_serial_port *port, struct ktermios *old_termios)
 {
 	struct usb_serial *serial = port->serial;
 	struct belkin_sa_private *priv = usb_get_serial_port_data(port);
@@ -347,8 +359,8 @@
 	unsigned long control_state;
 	int bad_flow_control;
 	speed_t baud;
-	struct ktermios *termios = port->tty->termios;
-	
+	struct ktermios *termios = tty->termios;
+
 	iflag = termios->c_iflag;
 	cflag = termios->c_cflag;
 
@@ -359,25 +371,26 @@
 	control_state = priv->control_state;
 	bad_flow_control = priv->bad_flow_control;
 	spin_unlock_irqrestore(&priv->lock, flags);
-	
+
 	old_iflag = old_termios->c_iflag;
 	old_cflag = old_termios->c_cflag;
 
 	/* Set the baud rate */
 	if ((cflag & CBAUD) != (old_cflag & CBAUD)) {
 		/* reassert DTR and (maybe) RTS on transition from B0 */
-		if( (old_cflag&CBAUD) == B0 ) {
+		if ((old_cflag & CBAUD) == B0) {
 			control_state |= (TIOCM_DTR|TIOCM_RTS);
 			if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 1) < 0)
 				err("Set DTR error");
 			/* don't set RTS if using hardware flow control */
 			if (!(old_cflag & CRTSCTS))
-				if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 1) < 0)
+				if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST
+								, 1) < 0)
 					err("Set RTS error");
 		}
 	}
 
-	baud = tty_get_baud_rate(port->tty);
+	baud = tty_get_baud_rate(tty);
 	if (baud) {
 		urb_value = BELKIN_SA_BAUD(baud);
 		/* Clip to maximum speed */
@@ -387,12 +400,13 @@
 		baud = BELKIN_SA_BAUD(urb_value);
 
 		/* Report the actual baud rate back to the caller */
-		tty_encode_baud_rate(port->tty, baud, baud);
+		tty_encode_baud_rate(tty, baud, baud);
 		if (BSA_USB_CMD(BELKIN_SA_SET_BAUDRATE_REQUEST, urb_value) < 0)
 			err("Set baudrate error");
 	} else {
 		/* Disable flow control */
-		if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST, BELKIN_SA_FLOW_NONE) < 0)
+		if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST,
+						BELKIN_SA_FLOW_NONE) < 0)
 			err("Disable flowcontrol error");
 		/* Drop RTS and DTR */
 		control_state &= ~(TIOCM_DTR | TIOCM_RTS);
@@ -403,9 +417,10 @@
 	}
 
 	/* set the parity */
-	if( (cflag&(PARENB|PARODD)) != (old_cflag&(PARENB|PARODD)) ) {
+	if ((cflag ^ old_cflag) & (PARENB | PARODD)) {
 		if (cflag & PARENB)
-			urb_value = (cflag & PARODD) ?  BELKIN_SA_PARITY_ODD : BELKIN_SA_PARITY_EVEN;
+			urb_value = (cflag & PARODD) ?  BELKIN_SA_PARITY_ODD
+						: BELKIN_SA_PARITY_EVEN;
 		else
 			urb_value = BELKIN_SA_PARITY_NONE;
 		if (BSA_USB_CMD(BELKIN_SA_SET_PARITY_REQUEST, urb_value) < 0)
@@ -413,31 +428,40 @@
 	}
 
 	/* set the number of data bits */
-	if( (cflag&CSIZE) != (old_cflag&CSIZE) ) {
+	if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
 		switch (cflag & CSIZE) {
-			case CS5: urb_value = BELKIN_SA_DATA_BITS(5); break;
-			case CS6: urb_value = BELKIN_SA_DATA_BITS(6); break;
-			case CS7: urb_value = BELKIN_SA_DATA_BITS(7); break;
-			case CS8: urb_value = BELKIN_SA_DATA_BITS(8); break;
-			default: dbg("CSIZE was not CS5-CS8, using default of 8");
-				urb_value = BELKIN_SA_DATA_BITS(8);
-				break;
+		case CS5:
+			urb_value = BELKIN_SA_DATA_BITS(5);
+			break;
+		case CS6:
+			urb_value = BELKIN_SA_DATA_BITS(6);
+			break;
+		case CS7:
+			urb_value = BELKIN_SA_DATA_BITS(7);
+			break;
+		case CS8:
+			urb_value = BELKIN_SA_DATA_BITS(8);
+			break;
+		default: dbg("CSIZE was not CS5-CS8, using default of 8");
+			urb_value = BELKIN_SA_DATA_BITS(8);
+			break;
 		}
 		if (BSA_USB_CMD(BELKIN_SA_SET_DATA_BITS_REQUEST, urb_value) < 0)
 			err("Set data bits error");
 	}
 
 	/* set the number of stop bits */
-	if( (cflag&CSTOPB) != (old_cflag&CSTOPB) ) {
-		urb_value = (cflag & CSTOPB) ? BELKIN_SA_STOP_BITS(2) : BELKIN_SA_STOP_BITS(1);
-		if (BSA_USB_CMD(BELKIN_SA_SET_STOP_BITS_REQUEST, urb_value) < 0)
+	if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) {
+		urb_value = (cflag & CSTOPB) ? BELKIN_SA_STOP_BITS(2)
+						: BELKIN_SA_STOP_BITS(1);
+		if (BSA_USB_CMD(BELKIN_SA_SET_STOP_BITS_REQUEST,
+							urb_value) < 0)
 			err("Set stop bits error");
 	}
 
 	/* Set flow control */
-	if( (iflag&IXOFF)   != (old_iflag&IXOFF)
-	||	(iflag&IXON)    != (old_iflag&IXON)
-	||  (cflag&CRTSCTS) != (old_cflag&CRTSCTS) ) {
+	if (((iflag ^ old_iflag) & (IXOFF | IXON)) ||
+		((cflag ^ old_cflag) & CRTSCTS)) {
 		urb_value = 0;
 		if ((iflag & IXOFF) || (iflag & IXON))
 			urb_value |= (BELKIN_SA_FLOW_OXON | BELKIN_SA_FLOW_IXON);
@@ -463,8 +487,9 @@
 } /* belkin_sa_set_termios */
 
 
-static void belkin_sa_break_ctl( struct usb_serial_port *port, int break_state )
+static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct usb_serial *serial = port->serial;
 
 	if (BSA_USB_CMD(BELKIN_SA_SET_BREAK_REQUEST, break_state ? 1 : 0) < 0)
@@ -472,12 +497,13 @@
 }
 
 
-static int belkin_sa_tiocmget (struct usb_serial_port *port, struct file *file)
+static int belkin_sa_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct belkin_sa_private *priv = usb_get_serial_port_data(port);
 	unsigned long control_state;
 	unsigned long flags;
-	
+
 	dbg("%s", __func__);
 
 	spin_lock_irqsave(&priv->lock, flags);
@@ -488,9 +514,10 @@
 }
 
 
-static int belkin_sa_tiocmset (struct usb_serial_port *port, struct file *file,
+static int belkin_sa_tiocmset(struct tty_struct *tty, struct file *file,
 			       unsigned int set, unsigned int clear)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct usb_serial *serial = port->serial;
 	struct belkin_sa_private *priv = usb_get_serial_port_data(port);
 	unsigned long control_state;
@@ -498,7 +525,7 @@
 	int retval;
 	int rts = 0;
 	int dtr = 0;
-	
+
 	dbg("%s", __func__);
 
 	spin_lock_irqsave(&priv->lock, flags);
@@ -540,29 +567,7 @@
 }
 
 
-static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
-{
-	switch (cmd) {
-	case TIOCMIWAIT:
-		/* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
-		/* TODO */
-		return( 0 );
-
-	case TIOCGICOUNT:
-		/* return count of modemline transitions */
-		/* TODO */
-		return 0;
-
-	default:
-		dbg("belkin_sa_ioctl arg not supported - 0x%04x",cmd);
-		return(-ENOIOCTLCMD);
-		break;
-	}
-	return 0;
-} /* belkin_sa_ioctl */
-
-
-static int __init belkin_sa_init (void)
+static int __init belkin_sa_init(void)
 {
 	int retval;
 	retval = usb_serial_register(&belkin_device);
@@ -582,17 +587,17 @@
 
 static void __exit belkin_sa_exit (void)
 {
-	usb_deregister (&belkin_driver);
-	usb_serial_deregister (&belkin_device);
+	usb_deregister(&belkin_driver);
+	usb_serial_deregister(&belkin_device);
 }
 
 
-module_init (belkin_sa_init);
-module_exit (belkin_sa_exit);
+module_init(belkin_sa_init);
+module_exit(belkin_sa_exit);
 
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_VERSION( DRIVER_VERSION );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/belkin_sa.h b/drivers/usb/serial/belkin_sa.h
index 9116b92..c66a673 100644
--- a/drivers/usb/serial/belkin_sa.h
+++ b/drivers/usb/serial/belkin_sa.h
@@ -7,13 +7,14 @@
  *  This program is largely derived from work by the linux-usb group
  *  and associated source files.  Please see the usb/serial files for
  *  individual credits and copyrights.
- *  
+ *
  * 	This program is free software; you can redistribute it and/or modify
  * 	it under the terms of the GNU General Public License as published by
  * 	the Free Software Foundation; either version 2 of the License, or
  * 	(at your option) any later version.
  *
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
  *
  * 12-Mar-2001 gkh
  *	Added GoHubs GO-COM232 device id.
@@ -27,7 +28,7 @@
  *    adapter, so pardon any stupid mistakes.  All of the information
  *    I am using to write this driver was acquired by using a modified
  *    UsbSnoop on Windows2000.
- *    
+ *
  */
 
 #ifndef __LINUX_USB_SERIAL_BSA_H
@@ -96,20 +97,20 @@
 
 /*
  * It seems that the interrupt pipe is closely modelled after the
- * 16550 register layout.  This is probably because the adapter can 
+ * 16550 register layout.  This is probably because the adapter can
  * be used in a "DOS" environment to simulate a standard hardware port.
  */
-#define BELKIN_SA_LSR_INDEX		2		/* Line Status Register */
+#define BELKIN_SA_LSR_INDEX		2	/*     Line Status Register */
 #define BELKIN_SA_LSR_RDR		0x01	/* receive data ready */
 #define BELKIN_SA_LSR_OE		0x02	/* overrun error */
 #define BELKIN_SA_LSR_PE		0x04	/* parity error */
 #define BELKIN_SA_LSR_FE		0x08	/* framing error */
 #define BELKIN_SA_LSR_BI		0x10	/* break indicator */
-#define BELKIN_SA_LSR_THE		0x20	/* transmit holding register empty */
+#define BELKIN_SA_LSR_THE		0x20	/* tx holding register empty */
 #define BELKIN_SA_LSR_TE		0x40	/* transmit register empty */
 #define BELKIN_SA_LSR_ERR		0x80	/* OE | PE | FE | BI */
 
-#define BELKIN_SA_MSR_INDEX		3		/* Modem Status Register */
+#define BELKIN_SA_MSR_INDEX		3	/*     Modem Status Register */
 #define BELKIN_SA_MSR_DCTS		0x01	/* Delta CTS */
 #define BELKIN_SA_MSR_DDSR		0x02	/* Delta DSR */
 #define BELKIN_SA_MSR_DRI		0x04	/* Delta RI */
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index 0b14aea..83bbb5b 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -15,7 +15,8 @@
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
-static int usb_serial_device_match (struct device *dev, struct device_driver *drv)
+static int usb_serial_device_match(struct device *dev,
+						struct device_driver *drv)
 {
 	struct usb_serial_driver *driver;
 	const struct usb_serial_port *port;
@@ -46,7 +47,7 @@
 
 static DEVICE_ATTR(port_number, S_IRUGO, show_port_number, NULL);
 
-static int usb_serial_device_probe (struct device *dev)
+static int usb_serial_device_probe(struct device *dev)
 {
 	struct usb_serial_driver *driver;
 	struct usb_serial_port *port;
@@ -66,7 +67,7 @@
 			retval = -EIO;
 			goto exit;
 		}
-		retval = driver->port_probe (port);
+		retval = driver->port_probe(port);
 		module_put(driver->driver.owner);
 		if (retval)
 			goto exit;
@@ -77,8 +78,8 @@
 		goto exit;
 
 	minor = port->number;
-	tty_register_device (usb_serial_tty_driver, minor, dev);
-	dev_info(&port->serial->dev->dev, 
+	tty_register_device(usb_serial_tty_driver, minor, dev);
+	dev_info(&port->serial->dev->dev,
 		 "%s converter now attached to ttyUSB%d\n",
 		 driver->description, minor);
 
@@ -86,7 +87,7 @@
 	return retval;
 }
 
-static int usb_serial_device_remove (struct device *dev)
+static int usb_serial_device_remove(struct device *dev)
 {
 	struct usb_serial_driver *driver;
 	struct usb_serial_port *port;
@@ -94,9 +95,8 @@
 	int minor;
 
 	port = to_usb_serial_port(dev);
-	if (!port) {
+	if (!port)
 		return -ENODEV;
-	}
 
 	device_remove_file(&port->dev, &dev_attr_port_number);
 
@@ -107,12 +107,12 @@
 			retval = -EIO;
 			goto exit;
 		}
-		retval = driver->port_remove (port);
+		retval = driver->port_remove(port);
 		module_put(driver->driver.owner);
 	}
 exit:
 	minor = port->number;
-	tty_unregister_device (usb_serial_tty_driver, minor);
+	tty_unregister_device(usb_serial_tty_driver, minor);
 	dev_info(dev, "%s converter now disconnected from ttyUSB%d\n",
 		 driver->description, minor);
 
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 1f7c86b..f61e3ca 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -232,7 +232,8 @@
 }
 
 /* open this device, set default parameters */
-static int ch341_open(struct usb_serial_port *port, struct file *filp)
+static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port,
+				struct file *filp)
 {
 	struct usb_serial *serial = port->serial;
 	struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]);
@@ -256,7 +257,7 @@
 	if (r)
 		goto out;
 
-	r = usb_serial_generic_open(port, filp);
+	r = usb_serial_generic_open(tty, port, filp);
 
 out:	return r;
 }
@@ -264,11 +265,10 @@
 /* Old_termios contains the original termios settings and
  * tty->termios contains the new setting to be used.
  */
-static void ch341_set_termios(struct usb_serial_port *port,
-			      struct ktermios *old_termios)
+static void ch341_set_termios(struct tty_struct *tty,
+		struct usb_serial_port *port, struct ktermios *old_termios)
 {
 	struct ch341_private *priv = usb_get_serial_port_data(port);
-	struct tty_struct *tty = port->tty;
 	unsigned baud_rate;
 
 	dbg("ch341_set_termios()");
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 201184c..7b74238 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -6,7 +6,7 @@
  *	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.
- * 
+ *
  * Thanks to Randy Dunlap for the original version of this code.
  *
  */
@@ -67,7 +67,7 @@
 	struct tty_struct *tty = NULL;
 	struct ktermios *termios = NULL, dummy;
 
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 
 	if (options) {
 		baud = simple_strtoul(options, NULL, 10);
@@ -81,55 +81,27 @@
 		if (*s)
 			doflow = (*s++ == 'r');
 	}
+	
+	/* Sane default */
+	if (baud == 0)
+		baud = 9600;
 
-	/* build a cflag setting */
-	switch (baud) {
-		case 1200:
-			cflag |= B1200;
-			break;
-		case 2400:
-			cflag |= B2400;
-			break;
-		case 4800:
-			cflag |= B4800;
-			break;
-		case 19200:
-			cflag |= B19200;
-			break;
-		case 38400:
-			cflag |= B38400;
-			break;
-		case 57600:
-			cflag |= B57600;
-			break;
-		case 115200:
-			cflag |= B115200;
-			break;
-		case 9600:
-		default:
-			cflag |= B9600;
-			/*
-			 * Set this to a sane value to prevent a divide error
-			 */
-			baud  = 9600;
-			break;
-	}
 	switch (bits) {
-		case 7:
-			cflag |= CS7;
-			break;
-		default:
-		case 8:
-			cflag |= CS8;
-			break;
+	case 7:
+		cflag |= CS7;
+		break;
+	default:
+	case 8:
+		cflag |= CS8;
+		break;
 	}
 	switch (parity) {
-		case 'o': case 'O':
-			cflag |= PARODD;
-			break;
-		case 'e': case 'E':
-			cflag |= PARENB;
-			break;
+	case 'o': case 'O':
+		cflag |= PARODD;
+		break;
+	case 'e': case 'E':
+		cflag |= PARENB;
+		break;
 	}
 	co->cflag = cflag;
 
@@ -140,17 +112,17 @@
 	serial = usb_serial_get_by_index(co->index);
 	if (serial == NULL) {
 		/* no device is connected yet, sorry :( */
-		err ("No USB device connected to ttyUSB%i", co->index);
+		err("No USB device connected to ttyUSB%i", co->index);
 		return -ENODEV;
 	}
 
 	port = serial->port[0];
-	port->tty = NULL;
+	port->port.tty = NULL;
 
 	info->port = port;
-	 
-	++port->open_count;
-	if (port->open_count == 1) {
+
+	++port->port.count;
+	if (port->port.count == 1) {
 		if (serial->type->set_termios) {
 			/*
 			 * allocate a fake tty so the driver can initialize
@@ -171,15 +143,15 @@
 			}
 			memset(&dummy, 0, sizeof(struct ktermios));
 			tty->termios = termios;
-			port->tty = tty;
+			port->port.tty = tty;
 		}
 
-		/* only call the device specific open if this 
+		/* only call the device specific open if this
 		 * is the first time the port is opened */
 		if (serial->type->open)
-			retval = serial->type->open(port, NULL);
+			retval = serial->type->open(NULL, port, NULL);
 		else
-			retval = usb_serial_generic_open(port, NULL);
+			retval = usb_serial_generic_open(NULL, port, NULL);
 
 		if (retval) {
 			err("could not open USB console port");
@@ -188,9 +160,10 @@
 
 		if (serial->type->set_termios) {
 			termios->c_cflag = cflag;
-			serial->type->set_termios(port, &dummy);
+			tty_termios_encode_baud_rate(termios, baud, baud);
+			serial->type->set_termios(NULL, port, &dummy);
 
-			port->tty = NULL;
+			port->port.tty = NULL;
 			kfree(termios);
 			kfree(tty);
 		}
@@ -203,15 +176,16 @@
 	return retval;
 free_termios:
 	kfree(termios);
-	port->tty = NULL;
+	port->port.tty = NULL;
 free_tty:
 	kfree(tty);
 reset_open_count:
-	port->open_count = 0;
+	port->port.count = 0;
 goto out;
 }
 
-static void usb_console_write(struct console *co, const char *buf, unsigned count)
+static void usb_console_write(struct console *co,
+					const char *buf, unsigned count)
 {
 	static struct usbcons_info *info = &usbcons_info;
 	struct usb_serial_port *port = info->port;
@@ -227,8 +201,8 @@
 
 	dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
 
-	if (!port->open_count) {
-		dbg ("%s - port not opened", __func__);
+	if (!port->port.count) {
+		dbg("%s - port not opened", __func__);
 		return;
 	}
 
@@ -236,26 +210,29 @@
 		unsigned int i;
 		unsigned int lf;
 		/* search for LF so we can insert CR if necessary */
-		for (i=0, lf=0 ; i < count ; i++) {
+		for (i = 0, lf = 0 ; i < count ; i++) {
 			if (*(buf + i) == 10) {
 				lf = 1;
 				i++;
 				break;
 			}
 		}
-		/* pass on to the driver specific version of this function if it is available */
+		/* pass on to the driver specific version of this function if
+		   it is available */
 		if (serial->type->write)
-			retval = serial->type->write(port, buf, i);
+			retval = serial->type->write(NULL, port, buf, i);
 		else
-			retval = usb_serial_generic_write(port, buf, i);
+			retval = usb_serial_generic_write(NULL, port, buf, i);
 		dbg("%s - return value : %d", __func__, retval);
 		if (lf) {
 			/* append CR after LF */
 			unsigned char cr = 13;
 			if (serial->type->write)
-				retval = serial->type->write(port, &cr, 1);
+				retval = serial->type->write(NULL,
+								port, &cr, 1);
 			else
-				retval = usb_serial_generic_write(port, &cr, 1);
+				retval = usb_serial_generic_write(NULL,
+								port, &cr, 1);
 			dbg("%s - return value : %d", __func__, retval);
 		}
 		buf += i;
@@ -273,18 +250,19 @@
 
 void usb_serial_console_disconnect(struct usb_serial *serial)
 {
-	if (serial && serial->port && serial->port[0] && serial->port[0] == usbcons_info.port) {
+	if (serial && serial->port && serial->port[0]
+				&& serial->port[0] == usbcons_info.port) {
 		usb_serial_console_exit();
 		usb_serial_put(serial);
 	}
 }
 
-void usb_serial_console_init (int serial_debug, int minor)
+void usb_serial_console_init(int serial_debug, int minor)
 {
 	debug = serial_debug;
 
 	if (minor == 0) {
-		/* 
+		/*
 		 * Call register_console() if this is the first device plugged
 		 * in.  If we call it earlier, then the callback to
 		 * console_setup() will fail, as there is not a device seen by
@@ -293,21 +271,21 @@
 		/*
 		 * Register console.
 		 * NOTES:
-		 * console_setup() is called (back) immediately (from register_console).
-		 * console_write() is called immediately from register_console iff
-		 * CON_PRINTBUFFER is set in flags.
+		 * console_setup() is called (back) immediately (from
+		 * register_console). console_write() is called immediately
+		 * from register_console iff CON_PRINTBUFFER is set in flags.
 		 */
-		dbg ("registering the USB serial console.");
+		dbg("registering the USB serial console.");
 		register_console(&usbcons);
 	}
 }
 
-void usb_serial_console_exit (void)
+void usb_serial_console_exit(void)
 {
 	if (usbcons_info.port) {
 		unregister_console(&usbcons);
-		if (usbcons_info.port->open_count)
-			usbcons_info.port->open_count--;
+		if (usbcons_info.port->port.count)
+			usbcons_info.port->port.count--;
 		usbcons_info.port = NULL;
 	}
 }
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index f5b57b1..442cba6 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -25,7 +25,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/usb.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/usb/serial.h>
 
 /*
@@ -37,17 +37,20 @@
 /*
  * Function Prototypes
  */
-static int cp2101_open(struct usb_serial_port*, struct file*);
-static void cp2101_cleanup(struct usb_serial_port*);
-static void cp2101_close(struct usb_serial_port*, struct file*);
-static void cp2101_get_termios(struct usb_serial_port*);
-static void cp2101_set_termios(struct usb_serial_port*, struct ktermios*);
-static int cp2101_tiocmget (struct usb_serial_port *, struct file *);
-static int cp2101_tiocmset (struct usb_serial_port *, struct file *,
+static int cp2101_open(struct tty_struct *, struct usb_serial_port *,
+							struct file *);
+static void cp2101_cleanup(struct usb_serial_port *);
+static void cp2101_close(struct tty_struct *, struct usb_serial_port *,
+							struct file*);
+static void cp2101_get_termios(struct tty_struct *);
+static void cp2101_set_termios(struct tty_struct *, struct usb_serial_port *,
+							struct ktermios*);
+static int cp2101_tiocmget(struct tty_struct *, struct file *);
+static int cp2101_tiocmset(struct tty_struct *, struct file *,
 		unsigned int, unsigned int);
-static void cp2101_break_ctl(struct usb_serial_port*, int);
-static int cp2101_startup (struct usb_serial *);
-static void cp2101_shutdown(struct usb_serial*);
+static void cp2101_break_ctl(struct tty_struct *, int);
+static int cp2101_startup(struct usb_serial *);
+static void cp2101_shutdown(struct usb_serial *);
 
 
 static int debug;
@@ -93,7 +96,7 @@
 	{ } /* Terminating Entry */
 };
 
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
 
 static struct usb_driver cp2101_driver = {
 	.name		= "cp2101",
@@ -182,7 +185,7 @@
  * 'data' is a pointer to a pre-allocated array of integers large
  * enough to hold 'size' bytes (with 4 bytes to each integer)
  */
-static int cp2101_get_config(struct usb_serial_port* port, u8 request,
+static int cp2101_get_config(struct usb_serial_port *port, u8 request,
 		unsigned int *data, int size)
 {
 	struct usb_serial *serial = port->serial;
@@ -202,12 +205,12 @@
 	request++;
 
 	/* Issue the request, attempting to read 'size' bytes */
-	result = usb_control_msg (serial->dev,usb_rcvctrlpipe (serial->dev, 0),
+	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
 				request, REQTYPE_DEVICE_TO_HOST, 0x0000,
 				0, buf, size, 300);
 
 	/* Convert data into an array of integers */
-	for (i=0; i<length; i++)
+	for (i = 0; i < length; i++)
 		data[i] = le32_to_cpu(buf[i]);
 
 	kfree(buf);
@@ -228,7 +231,7 @@
  * Values less than 16 bits wide are sent directly
  * 'size' is specified in bytes.
  */
-static int cp2101_set_config(struct usb_serial_port* port, u8 request,
+static int cp2101_set_config(struct usb_serial_port *port, u8 request,
 		unsigned int *data, int size)
 {
 	struct usb_serial *serial = port->serial;
@@ -250,12 +253,12 @@
 		buf[i] = cpu_to_le32(data[i]);
 
 	if (size > 2) {
-		result = usb_control_msg (serial->dev,
+		result = usb_control_msg(serial->dev,
 				usb_sndctrlpipe(serial->dev, 0),
 				request, REQTYPE_HOST_TO_DEVICE, 0x0000,
 				0, buf, size, 300);
 	} else {
-		result = usb_control_msg (serial->dev,
+		result = usb_control_msg(serial->dev,
 				usb_sndctrlpipe(serial->dev, 0),
 				request, REQTYPE_HOST_TO_DEVICE, data[0],
 				0, NULL, 0, 300);
@@ -271,7 +274,7 @@
 	}
 
 	/* Single data value */
-	result = usb_control_msg (serial->dev,
+	result = usb_control_msg(serial->dev,
 			usb_sndctrlpipe(serial->dev, 0),
 			request, REQTYPE_HOST_TO_DEVICE, data[0],
 			0, NULL, 0, 300);
@@ -283,13 +286,14 @@
  * Convenience function for calling cp2101_set_config on single data values
  * without requiring an integer pointer
  */
-static inline int cp2101_set_config_single(struct usb_serial_port* port,
+static inline int cp2101_set_config_single(struct usb_serial_port *port,
 		u8 request, unsigned int data)
 {
 	return cp2101_set_config(port, request, &data, 2);
 }
 
-static int cp2101_open (struct usb_serial_port *port, struct file *filp)
+static int cp2101_open(struct tty_struct *tty, struct usb_serial_port *port,
+				struct file *filp)
 {
 	struct usb_serial *serial = port->serial;
 	int result;
@@ -303,7 +307,7 @@
 	}
 
 	/* Start reading from the device */
-	usb_fill_bulk_urb (port->read_urb, serial->dev,
+	usb_fill_bulk_urb(port->read_urb, serial->dev,
 			usb_rcvbulkpipe(serial->dev,
 			port->bulk_in_endpointAddress),
 			port->read_urb->transfer_buffer,
@@ -318,15 +322,15 @@
 	}
 
 	/* Configure the termios structure */
-	cp2101_get_termios(port);
+	cp2101_get_termios(tty);
 
 	/* Set the DTR and RTS pins low */
-	cp2101_tiocmset(port, NULL, TIOCM_DTR | TIOCM_RTS, 0);
+	cp2101_tiocmset(tty, NULL, TIOCM_DTR | TIOCM_RTS, 0);
 
 	return 0;
 }
 
-static void cp2101_cleanup (struct usb_serial_port *port)
+static void cp2101_cleanup(struct usb_serial_port *port)
 {
 	struct usb_serial *serial = port->serial;
 
@@ -341,7 +345,8 @@
 	}
 }
 
-static void cp2101_close (struct usb_serial_port *port, struct file * filp)
+static void cp2101_close(struct tty_struct *tty, struct usb_serial_port *port,
+					struct file *filp)
 {
 	dbg("%s - port %d", __func__, port->number);
 
@@ -362,19 +367,15 @@
  * from the device, corrects any unsupported values, and configures the
  * termios structure to reflect the state of the device
  */
-static void cp2101_get_termios (struct usb_serial_port *port)
+static void cp2101_get_termios (struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	unsigned int cflag, modem_ctl[4];
-	int baud;
-	int bits;
+	unsigned int baud;
+	unsigned int bits;
 
 	dbg("%s - port %d", __func__, port->number);
 
-	if (!port->tty || !port->tty->termios) {
-		dbg("%s - no tty structures", __func__);
-		return;
-	}
-
 	cp2101_get_config(port, CP2101_BAUDRATE, &baud, 2);
 	/* Convert to baudrate */
 	if (baud)
@@ -382,104 +383,102 @@
 
 	dbg("%s - baud rate = %d", __func__, baud);
 
-	tty_encode_baud_rate(port->tty, baud, baud);
-	cflag = port->tty->termios->c_cflag;
+	tty_encode_baud_rate(tty, baud, baud);
+	cflag = tty->termios->c_cflag;
 
 	cp2101_get_config(port, CP2101_BITS, &bits, 2);
 	cflag &= ~CSIZE;
-	switch(bits & BITS_DATA_MASK) {
-		case BITS_DATA_5:
-			dbg("%s - data bits = 5", __func__);
-			cflag |= CS5;
-			break;
-		case BITS_DATA_6:
-			dbg("%s - data bits = 6", __func__);
-			cflag |= CS6;
-			break;
-		case BITS_DATA_7:
-			dbg("%s - data bits = 7", __func__);
-			cflag |= CS7;
-			break;
-		case BITS_DATA_8:
-			dbg("%s - data bits = 8", __func__);
-			cflag |= CS8;
-			break;
-		case BITS_DATA_9:
-			dbg("%s - data bits = 9 (not supported, "
-					"using 8 data bits)", __func__);
-			cflag |= CS8;
-			bits &= ~BITS_DATA_MASK;
-			bits |= BITS_DATA_8;
-			cp2101_set_config(port, CP2101_BITS, &bits, 2);
-			break;
-		default:
-			dbg("%s - Unknown number of data bits, "
-					"using 8", __func__);
-			cflag |= CS8;
-			bits &= ~BITS_DATA_MASK;
-			bits |= BITS_DATA_8;
-			cp2101_set_config(port, CP2101_BITS, &bits, 2);
-			break;
+	switch (bits & BITS_DATA_MASK) {
+	case BITS_DATA_5:
+		dbg("%s - data bits = 5", __func__);
+		cflag |= CS5;
+		break;
+	case BITS_DATA_6:
+		dbg("%s - data bits = 6", __func__);
+		cflag |= CS6;
+		break;
+	case BITS_DATA_7:
+		dbg("%s - data bits = 7", __func__);
+		cflag |= CS7;
+		break;
+	case BITS_DATA_8:
+		dbg("%s - data bits = 8", __func__);
+		cflag |= CS8;
+		break;
+	case BITS_DATA_9:
+		dbg("%s - data bits = 9 (not supported, using 8 data bits)",
+								__func__);
+		cflag |= CS8;
+		bits &= ~BITS_DATA_MASK;
+		bits |= BITS_DATA_8;
+		cp2101_set_config(port, CP2101_BITS, &bits, 2);
+		break;
+	default:
+		dbg("%s - Unknown number of data bits, using 8", __func__);
+		cflag |= CS8;
+		bits &= ~BITS_DATA_MASK;
+		bits |= BITS_DATA_8;
+		cp2101_set_config(port, CP2101_BITS, &bits, 2);
+		break;
 	}
 
-	switch(bits & BITS_PARITY_MASK) {
-		case BITS_PARITY_NONE:
-			dbg("%s - parity = NONE", __func__);
-			cflag &= ~PARENB;
-			break;
-		case BITS_PARITY_ODD:
-			dbg("%s - parity = ODD", __func__);
-			cflag |= (PARENB|PARODD);
-			break;
-		case BITS_PARITY_EVEN:
-			dbg("%s - parity = EVEN", __func__);
-			cflag &= ~PARODD;
-			cflag |= PARENB;
-			break;
-		case BITS_PARITY_MARK:
-			dbg("%s - parity = MARK (not supported, "
-					"disabling parity)", __func__);
-			cflag &= ~PARENB;
-			bits &= ~BITS_PARITY_MASK;
-			cp2101_set_config(port, CP2101_BITS, &bits, 2);
-			break;
-		case BITS_PARITY_SPACE:
-			dbg("%s - parity = SPACE (not supported, "
-					"disabling parity)", __func__);
-			cflag &= ~PARENB;
-			bits &= ~BITS_PARITY_MASK;
-			cp2101_set_config(port, CP2101_BITS, &bits, 2);
-			break;
-		default:
-			dbg("%s - Unknown parity mode, "
-					"disabling parity", __func__);
-			cflag &= ~PARENB;
-			bits &= ~BITS_PARITY_MASK;
-			cp2101_set_config(port, CP2101_BITS, &bits, 2);
-			break;
+	switch (bits & BITS_PARITY_MASK) {
+	case BITS_PARITY_NONE:
+		dbg("%s - parity = NONE", __func__);
+		cflag &= ~PARENB;
+		break;
+	case BITS_PARITY_ODD:
+		dbg("%s - parity = ODD", __func__);
+		cflag |= (PARENB|PARODD);
+		break;
+	case BITS_PARITY_EVEN:
+		dbg("%s - parity = EVEN", __func__);
+		cflag &= ~PARODD;
+		cflag |= PARENB;
+		break;
+	case BITS_PARITY_MARK:
+		dbg("%s - parity = MARK (not supported, disabling parity)",
+				__func__);
+		cflag &= ~PARENB;
+		bits &= ~BITS_PARITY_MASK;
+		cp2101_set_config(port, CP2101_BITS, &bits, 2);
+		break;
+	case BITS_PARITY_SPACE:
+		dbg("%s - parity = SPACE (not supported, disabling parity)",
+				__func__);
+		cflag &= ~PARENB;
+		bits &= ~BITS_PARITY_MASK;
+		cp2101_set_config(port, CP2101_BITS, &bits, 2);
+		break;
+	default:
+		dbg("%s - Unknown parity mode, disabling parity", __func__);
+		cflag &= ~PARENB;
+		bits &= ~BITS_PARITY_MASK;
+		cp2101_set_config(port, CP2101_BITS, &bits, 2);
+		break;
 	}
 
 	cflag &= ~CSTOPB;
-	switch(bits & BITS_STOP_MASK) {
-		case BITS_STOP_1:
-			dbg("%s - stop bits = 1", __func__);
-			break;
-		case BITS_STOP_1_5:
-			dbg("%s - stop bits = 1.5 (not supported, "
-					"using 1 stop bit)", __func__);
-			bits &= ~BITS_STOP_MASK;
-			cp2101_set_config(port, CP2101_BITS, &bits, 2);
-			break;
-		case BITS_STOP_2:
-			dbg("%s - stop bits = 2", __func__);
-			cflag |= CSTOPB;
-			break;
-		default:
-			dbg("%s - Unknown number of stop bits, "
-					"using 1 stop bit", __func__);
-			bits &= ~BITS_STOP_MASK;
-			cp2101_set_config(port, CP2101_BITS, &bits, 2);
-			break;
+	switch (bits & BITS_STOP_MASK) {
+	case BITS_STOP_1:
+		dbg("%s - stop bits = 1", __func__);
+		break;
+	case BITS_STOP_1_5:
+		dbg("%s - stop bits = 1.5 (not supported, using 1 stop bit)",
+								__func__);
+		bits &= ~BITS_STOP_MASK;
+		cp2101_set_config(port, CP2101_BITS, &bits, 2);
+		break;
+	case BITS_STOP_2:
+		dbg("%s - stop bits = 2", __func__);
+		cflag |= CSTOPB;
+		break;
+	default:
+		dbg("%s - Unknown number of stop bits, using 1 stop bit",
+								__func__);
+		bits &= ~BITS_STOP_MASK;
+		cp2101_set_config(port, CP2101_BITS, &bits, 2);
+		break;
 	}
 
 	cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16);
@@ -491,55 +490,53 @@
 		cflag &= ~CRTSCTS;
 	}
 
-	port->tty->termios->c_cflag = cflag;
+	tty->termios->c_cflag = cflag;
 }
 
-static void cp2101_set_termios (struct usb_serial_port *port,
-		struct ktermios *old_termios)
+static void cp2101_set_termios(struct tty_struct *tty,
+		struct usb_serial_port *port, struct ktermios *old_termios)
 {
 	unsigned int cflag, old_cflag;
-	int baud=0, bits;
+	unsigned int baud = 0, bits;
 	unsigned int modem_ctl[4];
 
 	dbg("%s - port %d", __func__, port->number);
 
-	if (!port->tty || !port->tty->termios) {
-		dbg("%s - no tty structures", __func__);
+	if (!tty)
 		return;
-	}
-	port->tty->termios->c_cflag &= ~CMSPAR;
 
-	cflag = port->tty->termios->c_cflag;
+	tty->termios->c_cflag &= ~CMSPAR;
+	cflag = tty->termios->c_cflag;
 	old_cflag = old_termios->c_cflag;
-	baud = tty_get_baud_rate(port->tty);
+	baud = tty_get_baud_rate(tty);
 
 	/* If the baud rate is to be updated*/
 	if (baud != tty_termios_baud_rate(old_termios)) {
 		switch (baud) {
-			case 0:
-			case 600:
-			case 1200:
-			case 1800:
-			case 2400:
-			case 4800:
-			case 7200:
-			case 9600:
-			case 14400:
-			case 19200:
-			case 28800:
-			case 38400:
-			case 55854:
-			case 57600:
-			case 115200:
-			case 127117:
-			case 230400:
-			case 460800:
-			case 921600:
-			case 3686400:
-				break;
-			default:
-				baud = 9600;
-				break;
+		case 0:
+		case 600:
+		case 1200:
+		case 1800:
+		case 2400:
+		case 4800:
+		case 7200:
+		case 9600:
+		case 14400:
+		case 19200:
+		case 28800:
+		case 38400:
+		case 55854:
+		case 57600:
+		case 115200:
+		case 127117:
+		case 230400:
+		case 460800:
+		case 921600:
+		case 3686400:
+			break;
+		default:
+			baud = 9600;
+			break;
 		}
 
 		if (baud) {
@@ -554,35 +551,35 @@
 		}
 	}
 	/* Report back the resulting baud rate */
-	tty_encode_baud_rate(port->tty, baud, baud);
+	tty_encode_baud_rate(tty, baud, baud);
 
 	/* If the number of data bits is to be updated */
 	if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
 		cp2101_get_config(port, CP2101_BITS, &bits, 2);
 		bits &= ~BITS_DATA_MASK;
 		switch (cflag & CSIZE) {
-			case CS5:
-				bits |= BITS_DATA_5;
-				dbg("%s - data bits = 5", __func__);
-				break;
-			case CS6:
-				bits |= BITS_DATA_6;
-				dbg("%s - data bits = 6", __func__);
-				break;
-			case CS7:
-				bits |= BITS_DATA_7;
-				dbg("%s - data bits = 7", __func__);
-				break;
-			case CS8:
-				bits |= BITS_DATA_8;
-				dbg("%s - data bits = 8", __func__);
-				break;
-			/*case CS9:
-			 	bits |= BITS_DATA_9;
-				dbg("%s - data bits = 9", __func__);
-				break;*/
-			default:
-				dev_err(&port->dev, "cp2101 driver does not "
+		case CS5:
+			bits |= BITS_DATA_5;
+			dbg("%s - data bits = 5", __func__);
+			break;
+		case CS6:
+			bits |= BITS_DATA_6;
+			dbg("%s - data bits = 6", __func__);
+			break;
+		case CS7:
+			bits |= BITS_DATA_7;
+			dbg("%s - data bits = 7", __func__);
+			break;
+		case CS8:
+			bits |= BITS_DATA_8;
+			dbg("%s - data bits = 8", __func__);
+			break;
+		/*case CS9:
+			bits |= BITS_DATA_9;
+			dbg("%s - data bits = 9", __func__);
+			break;*/
+		default:
+			dev_err(&port->dev, "cp2101 driver does not "
 					"support the number of bits requested,"
 					" using 8 bit mode\n");
 				bits |= BITS_DATA_8;
@@ -651,10 +648,11 @@
 
 }
 
-static int cp2101_tiocmset (struct usb_serial_port *port, struct file *file,
+static int cp2101_tiocmset (struct tty_struct *tty, struct file *file,
 		unsigned int set, unsigned int clear)
 {
-	int control = 0;
+	struct usb_serial_port *port = tty->driver_data;
+	unsigned int control = 0;
 
 	dbg("%s - port %d", __func__, port->number);
 
@@ -681,9 +679,11 @@
 
 }
 
-static int cp2101_tiocmget (struct usb_serial_port *port, struct file *file)
+static int cp2101_tiocmget (struct tty_struct *tty, struct file *file)
 {
-	int control, result;
+	struct usb_serial_port *port = tty->driver_data;
+	unsigned int control;
+	int result;
 
 	dbg("%s - port %d", __func__, port->number);
 
@@ -701,9 +701,10 @@
 	return result;
 }
 
-static void cp2101_break_ctl (struct usb_serial_port *port, int break_state)
+static void cp2101_break_ctl (struct tty_struct *tty, int break_state)
 {
-	int state;
+	struct usb_serial_port *port = tty->driver_data;
+	unsigned int state;
 
 	dbg("%s - port %d", __func__, port->number);
 	if (break_state == 0)
@@ -711,30 +712,29 @@
 	else
 		state = BREAK_ON;
 	dbg("%s - turning break %s", __func__,
-			state==BREAK_OFF ? "off" : "on");
+			state == BREAK_OFF ? "off" : "on");
 	cp2101_set_config(port, CP2101_BREAK, &state, 2);
 }
 
-static int cp2101_startup (struct usb_serial *serial)
+static int cp2101_startup(struct usb_serial *serial)
 {
 	/* CP2101 buffers behave strangely unless device is reset */
 	usb_reset_device(serial->dev);
 	return 0;
 }
 
-static void cp2101_shutdown (struct usb_serial *serial)
+static void cp2101_shutdown(struct usb_serial *serial)
 {
 	int i;
 
 	dbg("%s", __func__);
 
 	/* Stop reads and writes on all ports */
-	for (i=0; i < serial->num_ports; ++i) {
+	for (i = 0; i < serial->num_ports; ++i)
 		cp2101_cleanup(serial->port[i]);
-	}
 }
 
-static int __init cp2101_init (void)
+static int __init cp2101_init(void)
 {
 	int retval;
 
@@ -754,10 +754,10 @@
 	return 0;
 }
 
-static void __exit cp2101_exit (void)
+static void __exit cp2101_exit(void)
 {
-	usb_deregister (&cp2101_driver);
-	usb_serial_deregister (&cp2101_device);
+	usb_deregister(&cp2101_driver);
+	usb_serial_deregister(&cp2101_device);
 }
 
 module_init(cp2101_init);
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index c164e2c..b4d7235 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -37,7 +37,7 @@
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
@@ -57,22 +57,25 @@
 #define CYBERJACK_PRODUCT_ID	0x0100
 
 /* Function prototypes */
-static int cyberjack_startup (struct usb_serial *serial);
-static void cyberjack_shutdown (struct usb_serial *serial);
-static int  cyberjack_open (struct usb_serial_port *port, struct file *filp);
-static void cyberjack_close (struct usb_serial_port *port, struct file *filp);
-static int cyberjack_write (struct usb_serial_port *port, const unsigned char *buf, int count);
-static int cyberjack_write_room( struct usb_serial_port *port );
-static void cyberjack_read_int_callback (struct urb *urb);
-static void cyberjack_read_bulk_callback (struct urb *urb);
-static void cyberjack_write_bulk_callback (struct urb *urb);
+static int cyberjack_startup(struct usb_serial *serial);
+static void cyberjack_shutdown(struct usb_serial *serial);
+static int  cyberjack_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
+static void cyberjack_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
+static int cyberjack_write(struct tty_struct *tty,
+	struct usb_serial_port *port, const unsigned char *buf, int count);
+static int cyberjack_write_room(struct tty_struct *tty);
+static void cyberjack_read_int_callback(struct urb *urb);
+static void cyberjack_read_bulk_callback(struct urb *urb);
+static void cyberjack_write_bulk_callback(struct urb *urb);
 
 static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(CYBERJACK_VENDOR_ID, CYBERJACK_PRODUCT_ID) },
 	{ }			/* Terminating entry */
 };
 
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
 
 static struct usb_driver cyberjack_driver = {
 	.name =		"cyberjack",
@@ -111,7 +114,7 @@
 };
 
 /* do some startup allocations not currently performed by usb_serial_probe() */
-static int cyberjack_startup (struct usb_serial *serial)
+static int cyberjack_startup(struct usb_serial *serial)
 {
 	struct cyberjack_private *priv;
 	int i;
@@ -135,20 +138,20 @@
 	for (i = 0; i < serial->num_ports; ++i) {
 		int result;
 		serial->port[i]->interrupt_in_urb->dev = serial->dev;
-		result = usb_submit_urb(serial->port[i]->interrupt_in_urb, 
+		result = usb_submit_urb(serial->port[i]->interrupt_in_urb,
 					GFP_KERNEL);
 		if (result)
 			err(" usb_submit_urb(read int) failed");
 		dbg("%s - usb_submit_urb(int urb)", __func__);
 	}
 
-	return( 0 );
+	return 0;
 }
 
-static void cyberjack_shutdown (struct usb_serial *serial)
+static void cyberjack_shutdown(struct usb_serial *serial)
 {
 	int i;
-	
+
 	dbg("%s", __func__);
 
 	for (i = 0; i < serial->num_ports; ++i) {
@@ -158,8 +161,9 @@
 		usb_set_serial_port_data(serial->port[i], NULL);
 	}
 }
-	
-static int  cyberjack_open (struct usb_serial_port *port, struct file *filp)
+
+static int  cyberjack_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct cyberjack_private *priv;
 	unsigned long flags;
@@ -167,14 +171,15 @@
 
 	dbg("%s - port %d", __func__, port->number);
 
-	dbg("%s - usb_clear_halt", __func__ );
+	dbg("%s - usb_clear_halt", __func__);
 	usb_clear_halt(port->serial->dev, port->write_urb->pipe);
 
 	/* 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.
 	 */
-	port->tty->low_latency = 1;
+	if (tty)
+		tty->low_latency = 1;
 
 	priv = usb_get_serial_port_data(port);
 	spin_lock_irqsave(&priv->lock, flags);
@@ -186,7 +191,8 @@
 	return result;
 }
 
-static void cyberjack_close (struct usb_serial_port *port, struct file *filp)
+static void cyberjack_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	dbg("%s - port %d", __func__, port->number);
 
@@ -197,7 +203,8 @@
 	}
 }
 
-static int cyberjack_write (struct usb_serial_port *port, const unsigned char *buf, int count)
+static int cyberjack_write(struct tty_struct *tty,
+	struct usb_serial_port *port, const unsigned char *buf, int count)
 {
 	struct usb_serial *serial = port->serial;
 	struct cyberjack_private *priv = usb_get_serial_port_data(port);
@@ -223,7 +230,7 @@
 
 	spin_lock_irqsave(&priv->lock, flags);
 
-	if( (count+priv->wrfilled) > sizeof(priv->wrbuf) ) {
+	if (count+priv->wrfilled > sizeof(priv->wrbuf)) {
 		/* To much data for buffer. Reset buffer. */
 		priv->wrfilled = 0;
 		port->write_urb_busy = 0;
@@ -232,42 +239,43 @@
 	}
 
 	/* Copy data */
-	memcpy (priv->wrbuf+priv->wrfilled, buf, count);
+	memcpy(priv->wrbuf + priv->wrfilled, buf, count);
 
 	usb_serial_debug_data(debug, &port->dev, __func__, count,
-		priv->wrbuf+priv->wrfilled);
+		priv->wrbuf + priv->wrfilled);
 	priv->wrfilled += count;
 
-	if( priv->wrfilled >= 3 ) {
+	if (priv->wrfilled >= 3) {
 		wrexpected = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3;
 		dbg("%s - expected data: %d", __func__, wrexpected);
-	} else {
+	} else
 		wrexpected = sizeof(priv->wrbuf);
-	}
 
-	if( priv->wrfilled >= wrexpected ) {
+	if (priv->wrfilled >= wrexpected) {
 		/* We have enough data to begin transmission */
 		int length;
 
 		dbg("%s - transmitting data (frame 1)", __func__);
-		length = (wrexpected > port->bulk_out_size) ? port->bulk_out_size : wrexpected;
+		length = (wrexpected > port->bulk_out_size) ?
+					port->bulk_out_size : wrexpected;
 
-		memcpy (port->write_urb->transfer_buffer, priv->wrbuf, length );
-		priv->wrsent=length;
+		memcpy(port->write_urb->transfer_buffer, priv->wrbuf, length);
+		priv->wrsent = length;
 
 		/* set up our urb */
-		usb_fill_bulk_urb(port->write_urb, serial->dev, 
+		usb_fill_bulk_urb(port->write_urb, serial->dev,
 			      usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
 			      port->write_urb->transfer_buffer, length,
-			      ((serial->type->write_bulk_callback) ? 
-			       serial->type->write_bulk_callback : 
-			       cyberjack_write_bulk_callback), 
+			      ((serial->type->write_bulk_callback) ?
+			       serial->type->write_bulk_callback :
+			       cyberjack_write_bulk_callback),
 			      port);
 
 		/* send the data out the bulk port */
 		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
 		if (result) {
-			err("%s - failed submitting write urb, error %d", __func__, result);
+			err("%s - failed submitting write urb, error %d",
+							__func__, result);
 			/* Throw away data. No better idea what to do with it. */
 			priv->wrfilled = 0;
 			priv->wrsent = 0;
@@ -276,12 +284,12 @@
 			return 0;
 		}
 
-		dbg("%s - priv->wrsent=%d", __func__,priv->wrsent);
-		dbg("%s - priv->wrfilled=%d", __func__,priv->wrfilled);
+		dbg("%s - priv->wrsent=%d", __func__, priv->wrsent);
+		dbg("%s - priv->wrfilled=%d", __func__, priv->wrfilled);
 
-		if( priv->wrsent>=priv->wrfilled ) {
+		if (priv->wrsent >= priv->wrfilled) {
 			dbg("%s - buffer cleaned", __func__);
-			memset( priv->wrbuf, 0, sizeof(priv->wrbuf) );
+			memset(priv->wrbuf, 0, sizeof(priv->wrbuf));
 			priv->wrfilled = 0;
 			priv->wrsent = 0;
 		}
@@ -289,16 +297,16 @@
 
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	return (count);
-} 
+	return count;
+}
 
-static int cyberjack_write_room( struct usb_serial_port *port )
+static int cyberjack_write_room(struct tty_struct *tty)
 {
 	/* FIXME: .... */
 	return CYBERJACK_LOCAL_BUF_SIZE;
 }
 
-static void cyberjack_read_int_callback( struct urb *urb )
+static void cyberjack_read_int_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 	struct cyberjack_private *priv = usb_get_serial_port_data(port);
@@ -312,10 +320,11 @@
 	if (status)
 		return;
 
-	usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+	usb_serial_debug_data(debug, &port->dev, __func__,
+						urb->actual_length, data);
 
 	/* React only to interrupts signaling a bulk_in transfer */
-	if( (urb->actual_length == 4) && (data[0] == 0x01) ) {
+	if (urb->actual_length == 4 && data[0] == 0x01) {
 		short old_rdtodo;
 
 		/* This is a announcement of coming bulk_ins. */
@@ -325,8 +334,8 @@
 
 		old_rdtodo = priv->rdtodo;
 
-		if( (old_rdtodo+size)<(old_rdtodo) ) {
-			dbg( "To many bulk_in urbs to do." );
+		if (old_rdtodo + size < old_rdtodo) {
+			dbg("To many bulk_in urbs to do.");
 			spin_unlock(&priv->lock);
 			goto resubmit;
 		}
@@ -338,10 +347,10 @@
 
 		spin_unlock(&priv->lock);
 
-		if( !old_rdtodo ) {
+		if (!old_rdtodo) {
 			port->read_urb->dev = port->serial->dev;
 			result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
-			if( result )
+			if (result)
 				err("%s - failed resubmitting read urb, error %d", __func__, result);
 			dbg("%s - usb_submit_urb(read urb)", __func__);
 		}
@@ -355,7 +364,7 @@
 	dbg("%s - usb_submit_urb(int urb)", __func__);
 }
 
-static void cyberjack_read_bulk_callback (struct urb *urb)
+static void cyberjack_read_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 	struct cyberjack_private *priv = usb_get_serial_port_data(port);
@@ -367,14 +376,15 @@
 
 	dbg("%s - port %d", __func__, port->number);
 
-	usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+	usb_serial_debug_data(debug, &port->dev, __func__,
+						urb->actual_length, data);
 	if (status) {
 		dbg("%s - nonzero read bulk status received: %d",
 		    __func__, status);
 		return;
 	}
 
-	tty = port->tty;
+	tty = port->port.tty;
 	if (!tty) {
 		dbg("%s - ignoring since device not open\n", __func__);
 		return;
@@ -382,15 +392,16 @@
 	if (urb->actual_length) {
 		tty_buffer_request_room(tty, urb->actual_length);
 		tty_insert_flip_string(tty, data, urb->actual_length);
-	  	tty_flip_buffer_push(tty);
+		tty_flip_buffer_push(tty);
 	}
 
 	spin_lock(&priv->lock);
 
 	/* Reduce urbs to do by one. */
-	priv->rdtodo-=urb->actual_length;
+	priv->rdtodo -= urb->actual_length;
 	/* Just to be sure */
-	if ( priv->rdtodo<0 ) priv->rdtodo = 0;
+	if (priv->rdtodo < 0)
+		priv->rdtodo = 0;
 	todo = priv->rdtodo;
 
 	spin_unlock(&priv->lock);
@@ -398,16 +409,17 @@
 	dbg("%s - rdtodo: %d", __func__, todo);
 
 	/* Continue to read if we have still urbs to do. */
-	if( todo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/ ) {
+	if (todo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/) {
 		port->read_urb->dev = port->serial->dev;
 		result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 		if (result)
-			err("%s - failed resubmitting read urb, error %d", __func__, result);
+			err("%s - failed resubmitting read urb, error %d",
+				__func__, result);
 		dbg("%s - usb_submit_urb(read urb)", __func__);
 	}
 }
 
-static void cyberjack_write_bulk_callback (struct urb *urb)
+static void cyberjack_write_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 	struct cyberjack_private *priv = usb_get_serial_port_data(port);
@@ -425,7 +437,7 @@
 	spin_lock(&priv->lock);
 
 	/* only do something if we have more data to send */
-	if( priv->wrfilled ) {
+	if (priv->wrfilled) {
 		int length, blksize, result;
 
 		dbg("%s - transmitting data (frame n)", __func__);
@@ -433,37 +445,39 @@
 		length = ((priv->wrfilled - priv->wrsent) > port->bulk_out_size) ?
 			port->bulk_out_size : (priv->wrfilled - priv->wrsent);
 
-		memcpy (port->write_urb->transfer_buffer, priv->wrbuf + priv->wrsent,
-			length );
-		priv->wrsent+=length;
+		memcpy(port->write_urb->transfer_buffer,
+					priv->wrbuf + priv->wrsent, length);
+		priv->wrsent += length;
 
 		/* set up our urb */
-		usb_fill_bulk_urb(port->write_urb, port->serial->dev, 
+		usb_fill_bulk_urb(port->write_urb, port->serial->dev,
 			      usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress),
 			      port->write_urb->transfer_buffer, length,
-			      ((port->serial->type->write_bulk_callback) ? 
-			       port->serial->type->write_bulk_callback : 
-			       cyberjack_write_bulk_callback), 
+			      ((port->serial->type->write_bulk_callback) ?
+			       port->serial->type->write_bulk_callback :
+			       cyberjack_write_bulk_callback),
 			      port);
 
 		/* send the data out the bulk port */
 		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
 		if (result) {
-			err("%s - failed submitting write urb, error %d", __func__, result);
+			err("%s - failed submitting write urb, error %d",
+								__func__, result);
 			/* Throw away data. No better idea what to do with it. */
 			priv->wrfilled = 0;
 			priv->wrsent = 0;
 			goto exit;
 		}
 
-		dbg("%s - priv->wrsent=%d", __func__,priv->wrsent);
-		dbg("%s - priv->wrfilled=%d", __func__,priv->wrfilled);
+		dbg("%s - priv->wrsent=%d", __func__, priv->wrsent);
+		dbg("%s - priv->wrfilled=%d", __func__, priv->wrfilled);
 
 		blksize = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3;
 
-		if( (priv->wrsent>=priv->wrfilled) || (priv->wrsent>=blksize) ) {
+		if (priv->wrsent >= priv->wrfilled ||
+					priv->wrsent >= blksize) {
 			dbg("%s - buffer cleaned", __func__);
-			memset( priv->wrbuf, 0, sizeof(priv->wrbuf) );
+			memset(priv->wrbuf, 0, sizeof(priv->wrbuf));
 			priv->wrfilled = 0;
 			priv->wrsent = 0;
 		}
@@ -474,14 +488,14 @@
 	usb_serial_port_softint(port);
 }
 
-static int __init cyberjack_init (void)
+static int __init cyberjack_init(void)
 {
 	int retval;
 	retval  = usb_serial_register(&cyberjack_device);
 	if (retval)
 		goto failed_usb_serial_register;
 	retval = usb_register(&cyberjack_driver);
-	if (retval) 
+	if (retval)
 		goto failed_usb_register;
 
 	info(DRIVER_VERSION " " DRIVER_AUTHOR);
@@ -494,18 +508,18 @@
 	return retval;
 }
 
-static void __exit cyberjack_exit (void)
+static void __exit cyberjack_exit(void)
 {
-	usb_deregister (&cyberjack_driver);
-	usb_serial_deregister (&cyberjack_device);
+	usb_deregister(&cyberjack_driver);
+	usb_serial_deregister(&cyberjack_device);
 }
 
 module_init(cyberjack_init);
 module_exit(cyberjack_exit);
 
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_VERSION( DRIVER_VERSION );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 0230d3c..22837a3 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -2,7 +2,7 @@
  * USB Cypress M8 driver
  *
  * 	Copyright (C) 2004
- * 	    Lonnie Mendez (dignome@gmail.com) 
+ * 	    Lonnie Mendez (dignome@gmail.com)
  *	Copyright (C) 2003,2004
  *	    Neil Whelchel (koyama@firstlight.net)
  *
@@ -11,19 +11,21 @@
  * 	the Free Software Foundation; either version 2 of the License, or
  * 	(at your option) any later version.
  *
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
  *
  * See http://geocities.com/i0xox0i for information on this driver and the
  * earthmate usb device.
  *
  *  Lonnie Mendez <dignome@gmail.com>
  *  4-29-2005
- *	Fixed problem where setting or retreiving the serial config would fail with
- * 	EPIPE.  Removed CRTS toggling so the driver behaves more like other usbserial
- * 	adapters.  Issued new interval of 1ms instead of the default 10ms.  As a
- * 	result, transfer speed has been substantially increased.  From avg. 850bps to
- * 	avg. 3300bps.  initial termios has also been modified.  Cleaned up code and
- * 	formatting issues so it is more readable.  Replaced the C++ style comments.
+ *	Fixed problem where setting or retreiving the serial config would fail
+ *	with EPIPE.  Removed CRTS toggling so the driver behaves more like
+ *	other usbserial adapters.  Issued new interval of 1ms instead of the
+ *	default 10ms.  As a result, transfer speed has been substantially
+ *	increased from avg. 850bps to avg. 3300bps.  initial termios has also
+ *	been modified.  Cleaned up code and formatting issues so it is more
+ *	readable.  Replaced the C++ style comments.
  *
  *  Lonnie Mendez <dignome@gmail.com>
  *  12-15-2004
@@ -42,10 +44,11 @@
  *
  */
 
-/* Thanks to Neil Whelchel for writing the first cypress m8 implementation for linux. */
+/* Thanks to Neil Whelchel for writing the first cypress m8 implementation
+   for linux. */
 /* Thanks to cypress for providing references for the hid reports. */
 /* Thanks to Jiang Zhang for providing links and for general help. */
-/* Code originates and was built up from ftdi_sio, belkin, pl2303 and others. */
+/* Code originates and was built up from ftdi_sio, belkin, pl2303 and others.*/
 
 
 #include <linux/kernel.h>
@@ -62,7 +65,7 @@
 #include <linux/usb/serial.h>
 #include <linux/serial.h>
 #include <linux/delay.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "cypress_m8.h"
 
@@ -112,7 +115,7 @@
 	{ }						/* Terminating entry */
 };
 
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
 
 static struct usb_driver cypress_driver = {
 	.name =		"cypress",
@@ -146,11 +149,13 @@
 	__u8 rx_flags;			   /* throttling - used from whiteheat/ftdi_sio */
 	enum packet_format pkt_fmt;	   /* format to use for packet send / receive */
 	int get_cfg_unsafe;		   /* If true, the CYPRESS_GET_CONFIG is unsafe */
-	int baud_rate;			   /* stores current baud rate in integer form */
+	int baud_rate;			   /* stores current baud rate in
+					      integer form */
 	int isthrottled;		   /* if throttled, discard reads */
 	wait_queue_head_t delta_msr_wait;  /* used for TIOCMIWAIT */
 	char prev_status, diff_status;	   /* used for TIOCMIWAIT */
-	/* we pass a pointer to this as the arguement sent to cypress_set_termios old_termios */
+	/* we pass a pointer to this as the arguement sent to
+	   cypress_set_termios old_termios */
 	struct ktermios tmp_termios; 	   /* stores the old termios settings */
 };
 
@@ -163,33 +168,41 @@
 };
 
 /* function prototypes for the Cypress USB to serial device */
-static int  cypress_earthmate_startup	(struct usb_serial *serial);
-static int  cypress_hidcom_startup	(struct usb_serial *serial);
-static int  cypress_ca42v2_startup	(struct usb_serial *serial);
-static void cypress_shutdown		(struct usb_serial *serial);
-static int  cypress_open		(struct usb_serial_port *port, struct file *filp);
-static void cypress_close		(struct usb_serial_port *port, struct file *filp);
-static int  cypress_write		(struct usb_serial_port *port, const unsigned char *buf, int count);
-static void cypress_send		(struct usb_serial_port *port);
-static int  cypress_write_room		(struct usb_serial_port *port);
-static int  cypress_ioctl		(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void cypress_set_termios		(struct usb_serial_port *port, struct ktermios * old);
-static int  cypress_tiocmget		(struct usb_serial_port *port, struct file *file);
-static int  cypress_tiocmset		(struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
-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);
-static void cypress_write_int_callback	(struct urb *urb);
+static int  cypress_earthmate_startup(struct usb_serial *serial);
+static int  cypress_hidcom_startup(struct usb_serial *serial);
+static int  cypress_ca42v2_startup(struct usb_serial *serial);
+static void cypress_shutdown(struct usb_serial *serial);
+static int  cypress_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
+static void cypress_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
+static int  cypress_write(struct tty_struct *tty, struct usb_serial_port *port,
+			const unsigned char *buf, int count);
+static void cypress_send(struct usb_serial_port *port);
+static int  cypress_write_room(struct tty_struct *tty);
+static int  cypress_ioctl(struct tty_struct *tty, struct file *file,
+			unsigned int cmd, unsigned long arg);
+static void cypress_set_termios(struct tty_struct *tty,
+			struct usb_serial_port *port, struct ktermios *old);
+static int  cypress_tiocmget(struct tty_struct *tty, struct file *file);
+static int  cypress_tiocmset(struct tty_struct *tty, struct file *file,
+			unsigned int set, unsigned int clear);
+static int  cypress_chars_in_buffer(struct tty_struct *tty);
+static void cypress_throttle(struct tty_struct *tty);
+static void cypress_unthrottle(struct tty_struct *tty);
+static void cypress_set_dead(struct usb_serial_port *port);
+static void cypress_read_int_callback(struct urb *urb);
+static void cypress_write_int_callback(struct urb *urb);
 /* write buffer functions */
 static struct cypress_buf *cypress_buf_alloc(unsigned int size);
-static void 		  cypress_buf_free(struct cypress_buf *cb);
-static void		  cypress_buf_clear(struct cypress_buf *cb);
-static unsigned int	  cypress_buf_data_avail(struct cypress_buf *cb);
-static unsigned int	  cypress_buf_space_avail(struct cypress_buf *cb);
-static unsigned int	  cypress_buf_put(struct cypress_buf *cb, const char *buf, unsigned int count);
-static unsigned int	  cypress_buf_get(struct cypress_buf *cb, char *buf, unsigned int count);
+static void cypress_buf_free(struct cypress_buf *cb);
+static void cypress_buf_clear(struct cypress_buf *cb);
+static unsigned int cypress_buf_data_avail(struct cypress_buf *cb);
+static unsigned int cypress_buf_space_avail(struct cypress_buf *cb);
+static unsigned int cypress_buf_put(struct cypress_buf *cb,
+					const char *buf, unsigned int count);
+static unsigned int cypress_buf_get(struct cypress_buf *cb,
+					char *buf, unsigned int count);
 
 
 static struct usb_serial_driver cypress_earthmate_device = {
@@ -247,7 +260,7 @@
 static struct usb_serial_driver cypress_ca42v2_device = {
 	.driver = {
 		.owner =		THIS_MODULE,
-                .name =			"nokiaca42v2",
+		.name =			"nokiaca42v2",
 	},
 	.description =			"Nokia CA-42 V2 Adapter",
 	.usb_driver = 			&cypress_driver,
@@ -322,8 +335,10 @@
 
 
 /* This function can either set or retrieve the current serial line settings */
-static int cypress_serial_control (struct usb_serial_port *port, speed_t baud_rate, int data_bits, int stop_bits,
-				   int parity_enable, int parity_type, int reset, int cypress_request_type)
+static int cypress_serial_control(struct tty_struct *tty,
+	struct usb_serial_port *port, speed_t baud_rate, int data_bits,
+	int stop_bits, int parity_enable, int parity_type, int reset,
+	int cypress_request_type)
 {
 	int new_baudrate = 0, retval = 0, tries = 0;
 	struct cypress_private *priv;
@@ -331,111 +346,114 @@
 	unsigned long flags;
 
 	dbg("%s", __func__);
-	
+
 	priv = usb_get_serial_port_data(port);
 
 	if (!priv->comm_is_ok)
 		return -ENODEV;
 
-	switch(cypress_request_type) {
-		case CYPRESS_SET_CONFIG:
+	switch (cypress_request_type) {
+	case CYPRESS_SET_CONFIG:
+		new_baudrate = priv->baud_rate;
+		/* 0 means 'Hang up' so doesn't change the true bit rate */
+		if (baud_rate == 0)
 			new_baudrate = priv->baud_rate;
-			/* 0 means 'Hang up' so doesn't change the true bit rate */
-			if (baud_rate == 0)
-				new_baudrate = priv->baud_rate;
-			/* Change of speed ? */
-			else if (baud_rate != priv->baud_rate) {
-				dbg("%s - baud rate is changing", __func__);
-				retval = analyze_baud_rate(port, baud_rate);
-				if (retval >=  0) {
-					new_baudrate = retval;
-					dbg("%s - New baud rate set to %d",
-					    __func__, new_baudrate);
-				}
+		/* Change of speed ? */
+		else if (baud_rate != priv->baud_rate) {
+			dbg("%s - baud rate is changing", __func__);
+			retval = analyze_baud_rate(port, baud_rate);
+			if (retval >=  0) {
+				new_baudrate = retval;
+				dbg("%s - New baud rate set to %d",
+				    __func__, new_baudrate);
 			}
-			dbg("%s - baud rate is being sent as %d", __func__, new_baudrate);
-			
-			memset(feature_buffer, 0, sizeof(feature_buffer));
-			/* fill the feature_buffer with new configuration */
-			*((u_int32_t *)feature_buffer) = new_baudrate;
+		}
+		dbg("%s - baud rate is being sent as %d",
+					__func__, new_baudrate);
 
-			feature_buffer[4] |= data_bits;   /* assign data bits in 2 bit space ( max 3 ) */
-			/* 1 bit gap */
-			feature_buffer[4] |= (stop_bits << 3);   /* assign stop bits in 1 bit space */
-			feature_buffer[4] |= (parity_enable << 4);   /* assign parity flag in 1 bit space */
-			feature_buffer[4] |= (parity_type << 5);   /* assign parity type in 1 bit space */
-			/* 1 bit gap */
-			feature_buffer[4] |= (reset << 7);   /* assign reset at end of byte, 1 bit space */
-				
-			dbg("%s - device is being sent this feature report:", __func__);
-			dbg("%s - %02X - %02X - %02X - %02X - %02X", __func__, feature_buffer[0], feature_buffer[1],
-		            feature_buffer[2], feature_buffer[3], feature_buffer[4]);
-			
-			do {
-				retval = usb_control_msg(port->serial->dev,
-						usb_sndctrlpipe(port->serial->dev, 0),
-						HID_REQ_SET_REPORT,
-						USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
-						0x0300, 0, feature_buffer,
-						sizeof(feature_buffer), 500);
+		memset(feature_buffer, 0, sizeof(feature_buffer));
+		/* fill the feature_buffer with new configuration */
+		*((u_int32_t *)feature_buffer) = new_baudrate;
+		feature_buffer[4] |= data_bits;   /* assign data bits in 2 bit space ( max 3 ) */
+		/* 1 bit gap */
+		feature_buffer[4] |= (stop_bits << 3);   /* assign stop bits in 1 bit space */
+		feature_buffer[4] |= (parity_enable << 4);   /* assign parity flag in 1 bit space */
+		feature_buffer[4] |= (parity_type << 5);   /* assign parity type in 1 bit space */
+		/* 1 bit gap */
+		feature_buffer[4] |= (reset << 7);   /* assign reset at end of byte, 1 bit space */
 
-				if (tries++ >= 3)
-					break;
+		dbg("%s - device is being sent this feature report:",
+								__func__);
+		dbg("%s - %02X - %02X - %02X - %02X - %02X", __func__,
+			feature_buffer[0], feature_buffer[1],
+			feature_buffer[2], feature_buffer[3],
+			feature_buffer[4]);
 
-			} while (retval != sizeof(feature_buffer) &&
-				 retval != -ENODEV);
+		do {
+			retval = usb_control_msg(port->serial->dev,
+					usb_sndctrlpipe(port->serial->dev, 0),
+					HID_REQ_SET_REPORT,
+					USB_DIR_OUT | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
+					0x0300, 0, feature_buffer,
+					sizeof(feature_buffer), 500);
 
-			if (retval != sizeof(feature_buffer)) {
-				err("%s - failed sending serial line settings - %d", __func__, retval);
-				cypress_set_dead(port);
-			} else {
-				spin_lock_irqsave(&priv->lock, flags);
-				priv->baud_rate = new_baudrate;
-				priv->current_config = feature_buffer[4];
-				spin_unlock_irqrestore(&priv->lock, flags);
-				/* If we asked for a speed change encode it */
-				if (baud_rate)
-					tty_encode_baud_rate(port->tty,
-							new_baudrate, new_baudrate);
-			}
-		break;
-		case CYPRESS_GET_CONFIG:
-			if (priv->get_cfg_unsafe) {
-				/* Not implemented for this device,
-				   and if we try to do it we're likely
-				   to crash the hardware. */
-				return -ENOTTY;
-			}
-			dbg("%s - retreiving serial line settings", __func__);
-			/* set initial values in feature buffer */
-			memset(feature_buffer, 0, sizeof(feature_buffer));
+			if (tries++ >= 3)
+				break;
 
-			do {
-				retval = usb_control_msg(port->serial->dev,
-						usb_rcvctrlpipe(port->serial->dev, 0),
-						HID_REQ_GET_REPORT,
-						USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
-						0x0300, 0, feature_buffer,
-						sizeof(feature_buffer), 500);
+		} while (retval != sizeof(feature_buffer) &&
+			 retval != -ENODEV);
 
-				if (tries++ >= 3)
-					break;
+		if (retval != sizeof(feature_buffer)) {
+			err("%s - failed sending serial line settings - %d",
+							__func__, retval);
+			cypress_set_dead(port);
+		} else {
+			spin_lock_irqsave(&priv->lock, flags);
+			priv->baud_rate = new_baudrate;
+			priv->current_config = feature_buffer[4];
+			spin_unlock_irqrestore(&priv->lock, flags);
+			/* If we asked for a speed change encode it */
+			if (baud_rate)
+				tty_encode_baud_rate(tty,
+					new_baudrate, new_baudrate);
+		}
+	break;
+	case CYPRESS_GET_CONFIG:
+		if (priv->get_cfg_unsafe) {
+			/* Not implemented for this device,
+			   and if we try to do it we're likely
+			   to crash the hardware. */
+			return -ENOTTY;
+		}
+		dbg("%s - retreiving serial line settings", __func__);
+		/* set initial values in feature buffer */
+		memset(feature_buffer, 0, sizeof(feature_buffer));
 
-			} while (retval != sizeof(feature_buffer) &&
-				 retval != -ENODEV);
+		do {
+			retval = usb_control_msg(port->serial->dev,
+					usb_rcvctrlpipe(port->serial->dev, 0),
+					HID_REQ_GET_REPORT,
+					USB_DIR_IN | USB_RECIP_INTERFACE | USB_TYPE_CLASS,
+					0x0300, 0, feature_buffer,
+					sizeof(feature_buffer), 500);
 
-			if (retval != sizeof(feature_buffer)) {
-				err("%s - failed to retrieve serial line settings - %d", __func__, retval);
-				cypress_set_dead(port);
-				return retval;
-			} else {
-				spin_lock_irqsave(&priv->lock, flags);
+			if (tries++ >= 3)
+				break;
+		} while (retval != sizeof(feature_buffer)
+						&& retval != -ENODEV);
 
-				/* store the config in one byte, and later use bit masks to check values */
-				priv->current_config = feature_buffer[4];
-				priv->baud_rate = *((u_int32_t *)feature_buffer);
-				spin_unlock_irqrestore(&priv->lock, flags);
-			}
+		if (retval != sizeof(feature_buffer)) {
+			err("%s - failed to retrieve serial line settings - %d", __func__, retval);
+			cypress_set_dead(port);
+			return retval;
+		} else {
+			spin_lock_irqsave(&priv->lock, flags);
+			/* store the config in one byte, and later
+			   use bit masks to check values */
+			priv->current_config = feature_buffer[4];
+			priv->baud_rate = *((u_int32_t *)feature_buffer);
+			spin_unlock_irqrestore(&priv->lock, flags);
+		}
 	}
 	spin_lock_irqsave(&priv->lock, flags);
 	++priv->cmd_count;
@@ -468,14 +486,14 @@
  *****************************************************************************/
 
 
-static int generic_startup (struct usb_serial *serial)
+static int generic_startup(struct usb_serial *serial)
 {
 	struct cypress_private *priv;
 	struct usb_serial_port *port = serial->port[0];
 
 	dbg("%s - port %d", __func__, port->number);
 
-	priv = kzalloc(sizeof (struct cypress_private), GFP_KERNEL);
+	priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
@@ -487,9 +505,9 @@
 		return -ENOMEM;
 	}
 	init_waitqueue_head(&priv->delta_msr_wait);
-	
-	usb_reset_configuration (serial->dev);
-	
+
+	usb_reset_configuration(serial->dev);
+
 	priv->cmd_ctrl = 0;
 	priv->line_control = 0;
 	priv->termios_initialized = 0;
@@ -500,30 +518,30 @@
 	   small.  Otherwise we can use the slightly more compact
 	   format.  This is in accordance with the cypress_m8 serial
 	   converter app note. */
-	if (port->interrupt_out_size > 9) {
+	if (port->interrupt_out_size > 9)
 		priv->pkt_fmt = packet_format_1;
-	} else {
+	else
 		priv->pkt_fmt = packet_format_2;
-	}
+
 	if (interval > 0) {
 		priv->write_urb_interval = interval;
 		priv->read_urb_interval = interval;
 		dbg("%s - port %d read & write intervals forced to %d",
-		    __func__,port->number,interval);
+		    __func__, 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",
-		    __func__,port->number,
-		    priv->read_urb_interval,priv->write_urb_interval);
+		    __func__, port->number,
+		    priv->read_urb_interval, priv->write_urb_interval);
 	}
 	usb_set_serial_port_data(port, priv);
-	
+
 	return 0;
 }
 
 
-static int cypress_earthmate_startup (struct usb_serial *serial)
+static int cypress_earthmate_startup(struct usb_serial *serial)
 {
 	struct cypress_private *priv;
 	struct usb_serial_port *port = serial->port[0];
@@ -541,7 +559,8 @@
 	/* All Earthmate devices use the separated-count packet
 	   format!  Idiotic. */
 	priv->pkt_fmt = packet_format_1;
-	if (serial->dev->descriptor.idProduct != cpu_to_le16(PRODUCT_ID_EARTHMATEUSB)) {
+	if (serial->dev->descriptor.idProduct !=
+				cpu_to_le16(PRODUCT_ID_EARTHMATEUSB)) {
 		/* The old original USB Earthmate seemed able to
 		   handle GET_CONFIG requests; everything they've
 		   produced since that time crashes if this command is
@@ -555,7 +574,7 @@
 } /* cypress_earthmate_startup */
 
 
-static int cypress_hidcom_startup (struct usb_serial *serial)
+static int cypress_hidcom_startup(struct usb_serial *serial)
 {
 	struct cypress_private *priv;
 
@@ -569,12 +588,12 @@
 
 	priv = usb_get_serial_port_data(serial->port[0]);
 	priv->chiptype = CT_CYPHIDCOM;
-	
+
 	return 0;
 } /* cypress_hidcom_startup */
 
 
-static int cypress_ca42v2_startup (struct usb_serial *serial)
+static int cypress_ca42v2_startup(struct usb_serial *serial)
 {
 	struct cypress_private *priv;
 
@@ -593,11 +612,11 @@
 } /* cypress_ca42v2_startup */
 
 
-static void cypress_shutdown (struct usb_serial *serial)
+static void cypress_shutdown(struct usb_serial *serial)
 {
 	struct cypress_private *priv;
 
-	dbg ("%s - port %d", __func__, serial->port[0]->number);
+	dbg("%s - port %d", __func__, serial->port[0]->number);
 
 	/* all open ports are closed at this point */
 
@@ -611,7 +630,8 @@
 }
 
 
-static int cypress_open (struct usb_serial_port *port, struct file *filp)
+static int cypress_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct cypress_private *priv = usb_get_serial_port_data(port);
 	struct usb_serial *serial = port->serial;
@@ -636,37 +656,44 @@
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	/* setting to zero could cause data loss */
-	port->tty->low_latency = 1;
+	if (tty)
+		tty->low_latency = 1;
 
 	/* raise both lines and set termios */
 	spin_lock_irqsave(&priv->lock, flags);
 	priv->line_control = CONTROL_DTR | CONTROL_RTS;
 	priv->cmd_ctrl = 1;
 	spin_unlock_irqrestore(&priv->lock, flags);
-	result = cypress_write(port, NULL, 0);
+	result = cypress_write(tty, port, NULL, 0);
 
 	if (result) {
-		dev_err(&port->dev, "%s - failed setting the control lines - error %d\n", __func__, result);
+		dev_err(&port->dev,
+			"%s - failed setting the control lines - error %d\n",
+							__func__, result);
 		return result;
 	} else
 		dbg("%s - success setting the control lines", __func__);
 
-	cypress_set_termios(port, &priv->tmp_termios);
+	if (tty)
+		cypress_set_termios(tty, port, &priv->tmp_termios);
 
 	/* setup the port and start reading from the device */
-	if(!port->interrupt_in_urb){
+	if (!port->interrupt_in_urb) {
 		err("%s - interrupt_in_urb is empty!", __func__);
-		return(-1);
+		return -1;
 	}
 
 	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,
+		port->interrupt_in_urb->transfer_buffer,
+		port->interrupt_in_urb->transfer_buffer_length,
 		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", __func__, result);
+	if (result) {
+		dev_err(&port->dev,
+			"%s - failed submitting read urb, error %d\n",
+							__func__, result);
 		cypress_set_dead(port);
 	}
 
@@ -674,7 +701,8 @@
 } /* cypress_open */
 
 
-static void cypress_close(struct usb_serial_port *port, struct file * filp)
+static void cypress_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct cypress_private *priv = usb_get_serial_port_data(port);
 	unsigned int c_cflag;
@@ -688,7 +716,7 @@
 	spin_lock_irq(&priv->lock);
 	timeout = CYPRESS_CLOSING_WAIT;
 	init_waitqueue_entry(&wait, current);
-	add_wait_queue(&port->tty->write_wait, &wait);
+	add_wait_queue(&tty->write_wait, &wait);
 	for (;;) {
 		set_current_state(TASK_INTERRUPTIBLE);
 		if (cypress_buf_data_avail(priv->buf) == 0
@@ -701,7 +729,7 @@
 		spin_lock_irq(&priv->lock);
 	}
 	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&port->tty->write_wait, &wait);
+	remove_wait_queue(&tty->write_wait, &wait);
 	/* clear out any remaining data in the buffer */
 	cypress_buf_clear(priv->buf);
 	spin_unlock_irq(&priv->lock);
@@ -713,19 +741,21 @@
 		return;
 	}
 	/* wait for characters to drain from device */
-	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);
+	if (tty) {
+		bps = tty_get_baud_rate(tty);
+		if (bps > 1200)
+			timeout = max((HZ * 2560) / bps, HZ / 10);
+		else
+			timeout = 2 * HZ;
+		schedule_timeout_interruptible(timeout);
+	}
 
 	dbg("%s - stopping urbs", __func__);
-	usb_kill_urb (port->interrupt_in_urb);
-	usb_kill_urb (port->interrupt_out_urb);
+	usb_kill_urb(port->interrupt_in_urb);
+	usb_kill_urb(port->interrupt_out_urb);
 
-	if (port->tty) {
-		c_cflag = port->tty->termios->c_cflag;
+	if (tty) {
+		c_cflag = tty->termios->c_cflag;
 		if (c_cflag & HUPCL) {
 			/* drop dtr and rts */
 			priv = usb_get_serial_port_data(port);
@@ -733,22 +763,23 @@
 			priv->line_control = 0;
 			priv->cmd_ctrl = 1;
 			spin_unlock_irq(&priv->lock);
-			cypress_write(port, NULL, 0);
+			cypress_write(tty, port, NULL, 0);
 		}
 	}
 
 	if (stats)
-		dev_info (&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
-		          priv->bytes_in, priv->bytes_out, priv->cmd_count);
+		dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
+			priv->bytes_in, priv->bytes_out, priv->cmd_count);
 	mutex_unlock(&port->serial->disc_mutex);
 } /* cypress_close */
 
 
-static int cypress_write(struct usb_serial_port *port, const unsigned char *buf, int count)
+static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port,
+					const unsigned char *buf, int count)
 {
 	struct cypress_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
-	
+
 	dbg("%s - port %d, %d bytes", __func__, port->number, count);
 
 	/* line control commands, which need to be executed immediately,
@@ -758,10 +789,10 @@
 		count = 0;
 		goto finish;
 	}
-	
+
 	if (!count)
 		return count;
-	
+
 	spin_lock_irqsave(&priv->lock, flags);
 	count = cypress_buf_put(priv->buf, buf, count);
 	spin_unlock_irqrestore(&priv->lock, flags);
@@ -778,13 +809,14 @@
 	int count = 0, result, offset, actual_size;
 	struct cypress_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
-	
+
 	if (!priv->comm_is_ok)
 		return;
 
 	dbg("%s - port %d", __func__, port->number);
-	dbg("%s - interrupt out size is %d", __func__, port->interrupt_out_size);
-	
+	dbg("%s - interrupt out size is %d", __func__,
+						port->interrupt_out_size);
+
 	spin_lock_irqsave(&priv->lock, flags);
 	if (priv->write_urb_in_use) {
 		dbg("%s - can't write, urb in use", __func__);
@@ -794,7 +826,8 @@
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	/* clear buffer */
-	memset(port->interrupt_out_urb->transfer_buffer, 0, port->interrupt_out_size);
+	memset(port->interrupt_out_urb->transfer_buffer, 0,
+						port->interrupt_out_size);
 
 	spin_lock_irqsave(&priv->lock, flags);
 	switch (priv->pkt_fmt) {
@@ -825,9 +858,8 @@
 	count = cypress_buf_get(priv->buf, &port->interrupt_out_buffer[offset],
 				port->interrupt_out_size-offset);
 
-	if (count == 0) {
+	if (count == 0)
 		return;
-	}
 
 	switch (priv->pkt_fmt) {
 	default:
@@ -851,26 +883,29 @@
 		actual_size = count +
 			      (priv->pkt_fmt == packet_format_1 ? 2 : 1);
 
-	usb_serial_debug_data(debug, &port->dev, __func__, port->interrupt_out_size,
-			      port->interrupt_out_urb->transfer_buffer);
+	usb_serial_debug_data(debug, &port->dev, __func__,
+		port->interrupt_out_size,
+		port->interrupt_out_urb->transfer_buffer);
 
 	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);
+	result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
 	if (result) {
-		dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__,
-			result);
+		dev_err(&port->dev,
+				"%s - failed submitting write urb, error %d\n",
+							__func__, result);
 		priv->write_urb_in_use = 0;
 		cypress_set_dead(port);
 	}
 
 	spin_lock_irqsave(&priv->lock, flags);
-	if (priv->cmd_ctrl) {
+	if (priv->cmd_ctrl)
 		priv->cmd_ctrl = 0;
-	}
-	priv->bytes_out += count; /* do not count the line control and size bytes */
+
+	/* do not count the line control and size bytes */
+	priv->bytes_out += count;
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	usb_serial_port_softint(port);
@@ -878,8 +913,9 @@
 
 
 /* returns how much space is available in the soft buffer */
-static int cypress_write_room(struct usb_serial_port *port)
+static int cypress_write_room(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct cypress_private *priv = usb_get_serial_port_data(port);
 	int room = 0;
 	unsigned long flags;
@@ -895,13 +931,14 @@
 }
 
 
-static int cypress_tiocmget (struct usb_serial_port *port, struct file *file)
+static int cypress_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct cypress_private *priv = usb_get_serial_port_data(port);
 	__u8 status, control;
 	unsigned int result = 0;
 	unsigned long flags;
-	
+
 	dbg("%s - port %d", __func__, port->number);
 
 	spin_lock_irqsave(&priv->lock, flags);
@@ -922,12 +959,13 @@
 }
 
 
-static int cypress_tiocmset (struct usb_serial_port *port, struct file *file,
+static int cypress_tiocmset(struct tty_struct *tty, struct file *file,
 			       unsigned int set, unsigned int clear)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct cypress_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
-	
+
 	dbg("%s - port %d", __func__, port->number);
 
 	spin_lock_irqsave(&priv->lock, flags);
@@ -942,63 +980,60 @@
 	priv->cmd_ctrl = 1;
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	return cypress_write(port, NULL, 0);
+	return cypress_write(tty, port, NULL, 0);
 }
 
 
-static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+static int cypress_ioctl(struct tty_struct *tty, struct file *file,
+					unsigned int cmd, unsigned long arg)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct cypress_private *priv = usb_get_serial_port_data(port);
 
 	dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
 
 	switch (cmd) {
-		/* This code comes from drivers/char/serial.c and ftdi_sio.c */
-		case TIOCMIWAIT:
-			while (priv != NULL) {
-				interruptible_sleep_on(&priv->delta_msr_wait);
-				/* see if a signal did it */
-				if (signal_pending(current))
-					return -ERESTARTSYS;
-				else {
-					char diff = priv->diff_status;
+	/* This code comes from drivers/char/serial.c and ftdi_sio.c */
+	case TIOCMIWAIT:
+		while (priv != NULL) {
+			interruptible_sleep_on(&priv->delta_msr_wait);
+			/* see if a signal did it */
+			if (signal_pending(current))
+				return -ERESTARTSYS;
+			else {
+				char diff = priv->diff_status;
+				if (diff == 0)
+					return -EIO; /* no change => error */
 
-					if (diff == 0) {
-						return -EIO; /* no change => error */
-					}
-					
-					/* consume all events */
-					priv->diff_status = 0;
+				/* consume all events */
+				priv->diff_status = 0;
 
-					/* return 0 if caller wanted to know about these bits */
-					if ( ((arg & TIOCM_RNG) && (diff & UART_RI)) ||
-					     ((arg & TIOCM_DSR) && (diff & UART_DSR)) ||
-					     ((arg & TIOCM_CD) && (diff & UART_CD)) ||
-					     ((arg & TIOCM_CTS) && (diff & UART_CTS)) ) {
-						return 0;
-					}
-					/* otherwise caller can't care less about what happened,
-					 * and so we continue to wait for more events.
-					 */
-				}
+				/* return 0 if caller wanted to know about
+				   these bits */
+				if (((arg & TIOCM_RNG) && (diff & UART_RI)) ||
+				    ((arg & TIOCM_DSR) && (diff & UART_DSR)) ||
+				    ((arg & TIOCM_CD) && (diff & UART_CD)) ||
+				    ((arg & TIOCM_CTS) && (diff & UART_CTS)))
+					return 0;
+				/* otherwise caller can't care less about what
+				 * happened, and so we continue to wait for
+				 * more events.
+				 */
 			}
-			return 0;
-			break;
-		default:
-			break;
+		}
+		return 0;
+	default:
+		break;
 	}
-
 	dbg("%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h", __func__, cmd);
-
 	return -ENOIOCTLCMD;
 } /* cypress_ioctl */
 
 
-static void cypress_set_termios (struct usb_serial_port *port,
-		struct ktermios *old_termios)
+static void cypress_set_termios(struct tty_struct *tty,
+	struct usb_serial_port *port, struct ktermios *old_termios)
 {
 	struct cypress_private *priv = usb_get_serial_port_data(port);
-	struct tty_struct *tty;
 	int data_bits, stop_bits, parity_type, parity_enable;
 	unsigned cflag, iflag;
 	unsigned long flags;
@@ -1007,8 +1042,6 @@
 
 	dbg("%s - port %d", __func__, port->number);
 
-	tty = port->tty;
-
 	spin_lock_irqsave(&priv->lock, flags);
 	if (!priv->termios_initialized) {
 		if (priv->chiptype == CT_EARTHMATE) {
@@ -1060,28 +1093,24 @@
 	} else
 		parity_enable = parity_type = 0;
 
-	if (cflag & CSIZE) {
-		switch (cflag & CSIZE) {
-			case CS5:
-				data_bits = 0;
-				break;
-			case CS6:
-				data_bits = 1;
-				break;
-			case CS7:
-				data_bits = 2;
-				break;
-			case CS8:
-				data_bits = 3;
-				break;
-			default:
-				err("%s - CSIZE was set, but not CS5-CS8",
-						__func__);
-				data_bits = 3;
-		}
-	} else
+	switch (cflag & CSIZE) {
+	case CS5:
+		data_bits = 0;
+		break;
+	case CS6:
+		data_bits = 1;
+		break;
+	case CS7:
+		data_bits = 2;
+		break;
+	case CS8:
 		data_bits = 3;
-
+		break;
+	default:
+		err("%s - CSIZE was set, but not CS5-CS8",
+				__func__);
+		data_bits = 3;
+	}
 	spin_lock_irqsave(&priv->lock, flags);
 	oldlines = priv->line_control;
 	if ((cflag & CBAUD) == B0) {
@@ -1096,19 +1125,21 @@
 			"%d data_bits (+5)", __func__, stop_bits,
 			parity_enable, parity_type, data_bits);
 
-	cypress_serial_control(port, tty_get_baud_rate(tty), data_bits, stop_bits,
-			parity_enable, parity_type, 0, CYPRESS_SET_CONFIG);
+	cypress_serial_control(tty, port, tty_get_baud_rate(tty),
+			data_bits, stop_bits,
+			parity_enable, parity_type,
+			0, CYPRESS_SET_CONFIG);
 
 	/* we perform a CYPRESS_GET_CONFIG so that the current settings are
 	 * filled into the private structure this should confirm that all is
 	 * working if it returns what we just set */
-	cypress_serial_control(port, 0, 0, 0, 0, 0, 0, CYPRESS_GET_CONFIG);
+	cypress_serial_control(tty, port, 0, 0, 0, 0, 0, 0, CYPRESS_GET_CONFIG);
 
 	/* Here we can define custom tty settings for devices; the main tty
 	 * termios flag base comes from empeg.c */
 
 	spin_lock_irqsave(&priv->lock, flags);
-	if ( (priv->chiptype == CT_EARTHMATE) && (priv->baud_rate == 4800) ) {
+	if (priv->chiptype == CT_EARTHMATE && priv->baud_rate == 4800) {
 		dbg("Using custom termios settings for a baud rate of "
 				"4800bps.");
 		/* define custom termios settings for NMEA protocol */
@@ -1142,20 +1173,21 @@
 	/* if necessary, set lines */
 	if (linechange) {
 		priv->cmd_ctrl = 1;
-		cypress_write(port, NULL, 0);
+		cypress_write(tty, port, NULL, 0);
 	}
 } /* cypress_set_termios */
 
 
 /* returns amount of data still left in soft buffer */
-static int cypress_chars_in_buffer(struct usb_serial_port *port)
+static int cypress_chars_in_buffer(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct cypress_private *priv = usb_get_serial_port_data(port);
 	int chars = 0;
 	unsigned long flags;
 
 	dbg("%s - port %d", __func__, port->number);
-	
+
 	spin_lock_irqsave(&priv->lock, flags);
 	chars = cypress_buf_data_avail(priv->buf);
 	spin_unlock_irqrestore(&priv->lock, flags);
@@ -1165,8 +1197,9 @@
 }
 
 
-static void cypress_throttle (struct usb_serial_port *port)
+static void cypress_throttle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct cypress_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 
@@ -1178,8 +1211,9 @@
 }
 
 
-static void cypress_unthrottle (struct usb_serial_port *port)
+static void cypress_unthrottle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct cypress_private *priv = usb_get_serial_port_data(port);
 	int actually_throttled, result;
 	unsigned long flags;
@@ -1232,12 +1266,13 @@
 		/* precursor to disconnect so just go away */
 		return;
 	case -EPIPE:
-		usb_clear_halt(port->serial->dev,0x81);
+		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",
-			__func__, status);
+		dev_err(&urb->dev->dev,
+			"%s - unexpected nonzero read status received: %d\n",
+							__func__, status);
 		cypress_set_dead(port);
 		return;
 	}
@@ -1251,7 +1286,7 @@
 	}
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	tty = port->tty;
+	tty = port->port.tty;
 	if (!tty) {
 		dbg("%s - bad tty pointer - exiting", __func__);
 		return;
@@ -1285,8 +1320,8 @@
 		goto continue_read;
 	}
 
-	usb_serial_debug_data (debug, &port->dev, __func__,
-			urb->actual_length, data);
+	usb_serial_debug_data(debug, &port->dev, __func__,
+						urb->actual_length, data);
 
 	spin_lock_irqsave(&priv->lock, flags);
 	/* check to see if status has changed */
@@ -1327,7 +1362,7 @@
 					data[i]);
 			tty_insert_flip_char(tty, data[i], tty_flag);
 		}
-		tty_flip_buffer_push(port->tty);
+		tty_flip_buffer_push(port->port.tty);
 	}
 
 	spin_lock_irqsave(&priv->lock, flags);
@@ -1339,13 +1374,14 @@
 
 	/* Continue trying to always read... unless the port has closed. */
 
-	if (port->open_count > 0 && priv->comm_is_ok) {
+	if (port->port.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, priv->read_urb_interval);
+				cypress_read_int_callback, port,
+				priv->read_urb_interval);
 		result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
 		if (result) {
 			dev_err(&urb->dev->dev, "%s - failed resubmitting "
@@ -1369,42 +1405,43 @@
 	dbg("%s - port %d", __func__, port->number);
 
 	switch (status) {
-		case 0:
-			/* success */
+	case 0:
+		/* success */
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/* this urb is terminated, clean up */
+		dbg("%s - urb shutting down with status: %d",
+						__func__, status);
+		priv->write_urb_in_use = 0;
+		return;
+	case -EPIPE: /* no break needed; clear halt and resubmit */
+		if (!priv->comm_is_ok)
 			break;
-		case -ECONNRESET:
-		case -ENOENT:
-		case -ESHUTDOWN:
-			/* this urb is terminated, clean up */
-			dbg("%s - urb shutting down with status: %d",
-			    __func__, status);
-			priv->write_urb_in_use = 0;
+		usb_clear_halt(port->serial->dev, 0x02);
+		/* error in the urb, so we have to resubmit it */
+		dbg("%s - nonzero write bulk status received: %d",
+			__func__, 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)
 			return;
-		case -EPIPE: /* no break needed; clear halt and resubmit */
-			if (!priv->comm_is_ok)
-				break;
-			usb_clear_halt(port->serial->dev, 0x02);
-			/* error in the urb, so we have to resubmit it */
-			dbg("%s - nonzero write bulk status received: %d",
-			    __func__, 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)
-				return;
-			dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n",
-				__func__, result);
-			cypress_set_dead(port);
-			break;
-		default:
-			dev_err(&urb->dev->dev,"%s - unexpected nonzero write status received: %d\n",
-				__func__, status);
-			cypress_set_dead(port);
-			break;
+		dev_err(&urb->dev->dev,
+			"%s - failed resubmitting write urb, error %d\n",
+							__func__, result);
+		cypress_set_dead(port);
+		break;
+	default:
+		dev_err(&urb->dev->dev,
+			 "%s - unexpected nonzero write status received: %d\n",
+							__func__, status);
+		cypress_set_dead(port);
+		break;
 	}
-	
 	priv->write_urb_in_use = 0;
-	
+
 	/* send any buffered data */
 	cypress_send(port);
 }
@@ -1486,7 +1523,8 @@
 static unsigned int cypress_buf_data_avail(struct cypress_buf *cb)
 {
 	if (cb != NULL)
-		return ((cb->buf_size + cb->buf_put - cb->buf_get) % cb->buf_size);
+		return (cb->buf_size + cb->buf_put - cb->buf_get)
+							% cb->buf_size;
 	else
 		return 0;
 }
@@ -1502,7 +1540,8 @@
 static unsigned int cypress_buf_space_avail(struct cypress_buf *cb)
 {
 	if (cb != NULL)
-		return ((cb->buf_size + cb->buf_get - cb->buf_put - 1) % cb->buf_size);
+		return (cb->buf_size + cb->buf_get - cb->buf_put - 1)
+							% cb->buf_size;
 	else
 		return 0;
 }
@@ -1602,9 +1641,9 @@
 static int __init cypress_init(void)
 {
 	int retval;
-	
+
 	dbg("%s", __func__);
-	
+
 	retval = usb_serial_register(&cypress_earthmate_device);
 	if (retval)
 		goto failed_em_register;
@@ -1632,23 +1671,23 @@
 }
 
 
-static void __exit cypress_exit (void)
+static void __exit cypress_exit(void)
 {
 	dbg("%s", __func__);
 
-	usb_deregister (&cypress_driver);
-	usb_serial_deregister (&cypress_earthmate_device);
-	usb_serial_deregister (&cypress_hidcom_device);
-	usb_serial_deregister (&cypress_ca42v2_device);
+	usb_deregister(&cypress_driver);
+	usb_serial_deregister(&cypress_earthmate_device);
+	usb_serial_deregister(&cypress_hidcom_device);
+	usb_serial_deregister(&cypress_ca42v2_device);
 }
 
 
 module_init(cypress_init);
 module_exit(cypress_exit);
 
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_VERSION( DRIVER_VERSION );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/cypress_m8.h b/drivers/usb/serial/cypress_m8.h
index 0388065..e772b01 100644
--- a/drivers/usb/serial/cypress_m8.h
+++ b/drivers/usb/serial/cypress_m8.h
@@ -54,7 +54,7 @@
 #define UART_DSR	0x20	/* data set ready - flow control - device to host */
 #define CONTROL_RTS 	0x10	/* request to send - flow control - host to device */
 #define UART_CTS	0x10	/* clear to send - flow control - device to host */
-#define	UART_RI		0x10	/* ring indicator - modem - device to host */ 
+#define	UART_RI		0x10	/* ring indicator - modem - device to host */
 #define UART_CD		0x40	/* carrier detect - modem - device to host */
 #define CYP_ERROR 	0x08	/* received from input report - device to host */
 /* Note - the below has nothing to to with the "feature report" reset */
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 04a56f3..240aad1 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -15,7 +15,7 @@
 *  Al Borchers (borchers@steinerpoint.com)
 * 
 * (12/03/2001) gkh
-*	switched to using port->open_count instead of private version.
+*	switched to using port->port.count instead of private version.
 *	Removed port->active
 *
 * (04/08/2001) gb
@@ -229,8 +229,6 @@
 *    in case a wake up is lost.
 *  - Following Documentation/DocBook/kernel-locking.pdf no spin locks
 *    are held when calling copy_to/from_user or printk.
-*    
-*  $Id: digi_acceleport.c,v 1.80.1.2 2000/11/02 05:45:08 root Exp $
 */
 
 #include <linux/kernel.h>
@@ -243,7 +241,7 @@
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/wait.h>
 #include <linux/usb/serial.h>
@@ -443,22 +441,23 @@
 	unsigned int modem_signals, int interruptible);
 static int digi_transmit_idle(struct usb_serial_port *port,
 	unsigned long timeout);
-static void digi_rx_throttle (struct usb_serial_port *port);
-static void digi_rx_unthrottle (struct usb_serial_port *port);
-static void digi_set_termios(struct usb_serial_port *port,
-	struct ktermios *old_termios);
-static void digi_break_ctl(struct usb_serial_port *port, int break_state);
-static int digi_ioctl(struct usb_serial_port *port, struct file *file,
-	unsigned int cmd, unsigned long arg);
-static int digi_tiocmget(struct usb_serial_port *port, struct file *file);
-static int digi_tiocmset(struct usb_serial_port *port, struct file *file,
+static void digi_rx_throttle(struct tty_struct *tty);
+static void digi_rx_unthrottle(struct tty_struct *tty);
+static void digi_set_termios(struct tty_struct *tty,
+		struct usb_serial_port *port, struct ktermios *old_termios);
+static void digi_break_ctl(struct tty_struct *tty, int break_state);
+static int digi_tiocmget(struct tty_struct *tty, struct file *file);
+static int digi_tiocmset(struct tty_struct *tty, struct file *file,
 	unsigned int set, unsigned int clear);
-static int digi_write(struct usb_serial_port *port, const unsigned char *buf, int count);
+static int digi_write(struct tty_struct *tty, struct usb_serial_port *port,
+	const unsigned char *buf, int count);
 static void digi_write_bulk_callback(struct urb *urb);
-static int digi_write_room(struct usb_serial_port *port);
-static int digi_chars_in_buffer(struct usb_serial_port *port);
-static int digi_open(struct usb_serial_port *port, struct file *filp);
-static void digi_close(struct usb_serial_port *port, struct file *filp);
+static int digi_write_room(struct tty_struct *tty);
+static int digi_chars_in_buffer(struct tty_struct *tty);
+static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
+	struct file *filp);
+static void digi_close(struct tty_struct *tty, struct usb_serial_port *port,
+	struct file *filp);
 static int digi_startup_device(struct usb_serial *serial);
 static int digi_startup(struct usb_serial *serial);
 static void digi_shutdown(struct usb_serial *serial);
@@ -487,7 +486,7 @@
 	{ }						/* Terminating entry */
 };
 
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
 
 static struct usb_driver digi_driver = {
 	.name =		"digi_acceleport",
@@ -518,7 +517,6 @@
 	.chars_in_buffer =		digi_chars_in_buffer,
 	.throttle =			digi_rx_throttle,
 	.unthrottle =			digi_rx_unthrottle,
-	.ioctl =			digi_ioctl,
 	.set_termios =			digi_set_termios,
 	.break_ctl =			digi_break_ctl,
 	.tiocmget =			digi_tiocmget,
@@ -545,7 +543,6 @@
 	.chars_in_buffer =		digi_chars_in_buffer,
 	.throttle =			digi_rx_throttle,
 	.unthrottle =			digi_rx_unthrottle,
-	.ioctl =			digi_ioctl,
 	.set_termios =			digi_set_termios,
 	.break_ctl =			digi_break_ctl,
 	.tiocmget =			digi_tiocmget,
@@ -558,21 +555,22 @@
 /* Functions */
 
 /*
-*  Cond Wait Interruptible Timeout Irqrestore
-*
-*  Do spin_unlock_irqrestore and interruptible_sleep_on_timeout
-*  so that wake ups are not lost if they occur between the unlock
-*  and the sleep.  In other words, spin_unlock_irqrestore and
-*  interruptible_sleep_on_timeout are "atomic" with respect to
-*  wake ups.  This is used to implement condition variables.
-*
-*  interruptible_sleep_on_timeout is deprecated and has been replaced
-*  with the equivalent code.
-*/
+ *  Cond Wait Interruptible Timeout Irqrestore
+ *
+ *  Do spin_unlock_irqrestore and interruptible_sleep_on_timeout
+ *  so that wake ups are not lost if they occur between the unlock
+ *  and the sleep.  In other words, spin_unlock_irqrestore and
+ *  interruptible_sleep_on_timeout are "atomic" with respect to
+ *  wake ups.  This is used to implement condition variables.
+ *
+ *  interruptible_sleep_on_timeout is deprecated and has been replaced
+ *  with the equivalent code.
+ */
 
 static long cond_wait_interruptible_timeout_irqrestore(
 	wait_queue_head_t *q, long timeout,
 	spinlock_t *lock, unsigned long flags)
+__releases(lock)
 {
 	DEFINE_WAIT(wait);
 
@@ -586,15 +584,16 @@
 
 
 /*
-*  Digi Wakeup Write
-*
-*  Wake up port, line discipline, and tty processes sleeping
-*  on writes.
-*/
+ *  Digi Wakeup Write
+ *
+ *  Wake up port, line discipline, and tty processes sleeping
+ *  on writes.
+ */
 
 static void digi_wakeup_write_lock(struct work_struct *work)
 {
-	struct digi_port *priv = container_of(work, struct digi_port, dp_wakeup_work);
+	struct digi_port *priv =
+			container_of(work, struct digi_port, dp_wakeup_work);
 	struct usb_serial_port *port = priv->dp_port;
 	unsigned long flags;
 
@@ -605,20 +604,20 @@
 
 static void digi_wakeup_write(struct usb_serial_port *port)
 {
-	tty_wakeup(port->tty);
+	tty_wakeup(port->port.tty);
 }
 
 
 /*
-*  Digi Write OOB Command
-*
-*  Write commands on the out of band port.  Commands are 4
-*  bytes each, multiple commands can be sent at once, and
-*  no command will be split across USB packets.  Returns 0
-*  if successful, -EINTR if interrupted while sleeping and
-*  the interruptible flag is true, or a negative error
-*  returned by usb_submit_urb.
-*/
+ *  Digi Write OOB Command
+ *
+ *  Write commands on the out of band port.  Commands are 4
+ *  bytes each, multiple commands can be sent at once, and
+ *  no command will be split across USB packets.  Returns 0
+ *  if successful, -EINTR if interrupted while sleeping and
+ *  the interruptible flag is true, or a negative error
+ *  returned by usb_submit_urb.
+ */
 
 static int digi_write_oob_command(struct usb_serial_port *port,
 	unsigned char *buf, int count, int interruptible)
@@ -633,8 +632,8 @@
 	dbg("digi_write_oob_command: TOP: port=%d, count=%d", oob_priv->dp_port_num, count);
 
 	spin_lock_irqsave(&oob_priv->dp_port_lock, flags);
-	while(count > 0) {
-		while(oob_port->write_urb->status == -EINPROGRESS
+	while (count > 0) {
+		while (oob_port->write_urb->status == -EINPROGRESS
 			|| oob_priv->dp_write_urb_in_use) {
 			cond_wait_interruptible_timeout_irqrestore(
 				&oob_port->write_wait, DIGI_RETRY_TIMEOUT,
@@ -651,7 +650,8 @@
 		memcpy(oob_port->write_urb->transfer_buffer, buf, len);
 		oob_port->write_urb->transfer_buffer_length = len;
 		oob_port->write_urb->dev = port->serial->dev;
-		if ((ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC)) == 0) {
+		ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC);
+		if (ret == 0) {
 			oob_priv->dp_write_urb_in_use = 1;
 			count -= len;
 			buf += len;
@@ -666,16 +666,16 @@
 
 
 /*
-*  Digi Write In Band Command
-*
-*  Write commands on the given port.  Commands are 4
-*  bytes each, multiple commands can be sent at once, and
-*  no command will be split across USB packets.  If timeout
-*  is non-zero, write in band command will return after
-*  waiting unsuccessfully for the URB status to clear for
-*  timeout ticks.  Returns 0 if successful, or a negative
-*  error returned by digi_write.
-*/
+ *  Digi Write In Band Command
+ *
+ *  Write commands on the given port.  Commands are 4
+ *  bytes each, multiple commands can be sent at once, and
+ *  no command will be split across USB packets.  If timeout
+ *  is non-zero, write in band command will return after
+ *  waiting unsuccessfully for the URB status to clear for
+ *  timeout ticks.  Returns 0 if successful, or a negative
+ *  error returned by digi_write.
+ */
 
 static int digi_write_inb_command(struct usb_serial_port *port,
 	unsigned char *buf, int count, unsigned long timeout)
@@ -695,9 +695,10 @@
 		timeout = ULONG_MAX;
 
 	spin_lock_irqsave(&priv->dp_port_lock, flags);
-	while(count > 0 && ret == 0) {
-		while((port->write_urb->status == -EINPROGRESS
-			|| priv->dp_write_urb_in_use) && time_before(jiffies, timeout)) {
+	while (count > 0 && ret == 0) {
+		while ((port->write_urb->status == -EINPROGRESS
+				|| priv->dp_write_urb_in_use)
+					&& time_before(jiffies, timeout)) {
 			cond_wait_interruptible_timeout_irqrestore(
 				&port->write_wait, DIGI_RETRY_TIMEOUT,
 				&priv->dp_port_lock, flags);
@@ -728,7 +729,8 @@
 		}
 		port->write_urb->dev = port->serial->dev;
 
-		if ((ret = usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0) {
+		ret = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+		if (ret == 0) {
 			priv->dp_write_urb_in_use = 1;
 			priv->dp_out_buf_len = 0;
 			count -= len;
@@ -746,14 +748,14 @@
 
 
 /*
-*  Digi Set Modem Signals
-*
-*  Sets or clears DTR and RTS on the port, according to the
-*  modem_signals argument.  Use TIOCM_DTR and TIOCM_RTS flags
-*  for the modem_signals argument.  Returns 0 if successful,
-*  -EINTR if interrupted while sleeping, or a non-zero error
-*  returned by usb_submit_urb.
-*/
+ *  Digi Set Modem Signals
+ *
+ *  Sets or clears DTR and RTS on the port, according to the
+ *  modem_signals argument.  Use TIOCM_DTR and TIOCM_RTS flags
+ *  for the modem_signals argument.  Returns 0 if successful,
+ *  -EINTR if interrupted while sleeping, or a non-zero error
+ *  returned by usb_submit_urb.
+ */
 
 static int digi_set_modem_signals(struct usb_serial_port *port,
 	unsigned int modem_signals, int interruptible)
@@ -761,7 +763,7 @@
 
 	int ret;
 	struct digi_port *port_priv = usb_get_serial_port_data(port);
-	struct usb_serial_port *oob_port = (struct usb_serial_port *)((struct digi_serial *)(usb_get_serial_data(port->serial)))->ds_oob_port;
+	struct usb_serial_port *oob_port = (struct usb_serial_port *) ((struct digi_serial *)(usb_get_serial_data(port->serial)))->ds_oob_port;
 	struct digi_port *oob_priv = usb_get_serial_port_data(oob_port);
 	unsigned char *data = oob_port->write_urb->transfer_buffer;
 	unsigned long flags = 0;
@@ -773,7 +775,8 @@
 	spin_lock_irqsave(&oob_priv->dp_port_lock, flags);
 	spin_lock(&port_priv->dp_port_lock);
 
-	while(oob_port->write_urb->status == -EINPROGRESS || oob_priv->dp_write_urb_in_use) {
+	while (oob_port->write_urb->status == -EINPROGRESS ||
+					oob_priv->dp_write_urb_in_use) {
 		spin_unlock(&port_priv->dp_port_lock);
 		cond_wait_interruptible_timeout_irqrestore(
 			&oob_port->write_wait, DIGI_RETRY_TIMEOUT,
@@ -785,17 +788,20 @@
 	}
 	data[0] = DIGI_CMD_SET_DTR_SIGNAL;
 	data[1] = port_priv->dp_port_num;
-	data[2] = (modem_signals&TIOCM_DTR) ? DIGI_DTR_ACTIVE : DIGI_DTR_INACTIVE;
+	data[2] = (modem_signals & TIOCM_DTR) ?
+					DIGI_DTR_ACTIVE : DIGI_DTR_INACTIVE;
 	data[3] = 0;
 	data[4] = DIGI_CMD_SET_RTS_SIGNAL;
 	data[5] = port_priv->dp_port_num;
-	data[6] = (modem_signals&TIOCM_RTS) ? DIGI_RTS_ACTIVE : DIGI_RTS_INACTIVE;
+	data[6] = (modem_signals & TIOCM_RTS) ?
+					DIGI_RTS_ACTIVE : DIGI_RTS_INACTIVE;
 	data[7] = 0;
 
 	oob_port->write_urb->transfer_buffer_length = 8;
 	oob_port->write_urb->dev = port->serial->dev;
 
-	if ((ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC)) == 0) {
+	ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC);
+	if (ret == 0) {
 		oob_priv->dp_write_urb_in_use = 1;
 		port_priv->dp_modem_signals =
 			(port_priv->dp_modem_signals&~(TIOCM_DTR|TIOCM_RTS))
@@ -809,16 +815,16 @@
 }
 
 /*
-*  Digi Transmit Idle
-*
-*  Digi transmit idle waits, up to timeout ticks, for the transmitter
-*  to go idle.  It returns 0 if successful or a negative error.
-*
-*  There are race conditions here if more than one process is calling
-*  digi_transmit_idle on the same port at the same time.  However, this
-*  is only called from close, and only one process can be in close on a
-*  port at a time, so its ok.
-*/
+ *  Digi Transmit Idle
+ *
+ *  Digi transmit idle waits, up to timeout ticks, for the transmitter
+ *  to go idle.  It returns 0 if successful or a negative error.
+ *
+ *  There are race conditions here if more than one process is calling
+ *  digi_transmit_idle on the same port at the same time.  However, this
+ *  is only called from close, and only one process can be in close on a
+ *  port at a time, so its ok.
+ */
 
 static int digi_transmit_idle(struct usb_serial_port *port,
 	unsigned long timeout)
@@ -837,12 +843,13 @@
 
 	timeout += jiffies;
 
-	if ((ret = digi_write_inb_command(port, buf, 2, timeout - jiffies)) != 0)
+	ret = digi_write_inb_command(port, buf, 2, timeout - jiffies);
+	if (ret != 0)
 		return ret;
 
 	spin_lock_irqsave(&priv->dp_port_lock, flags);
 
-	while(time_before(jiffies, timeout) && !priv->dp_transmit_idle) {
+	while (time_before(jiffies, timeout) && !priv->dp_transmit_idle) {
 		cond_wait_interruptible_timeout_irqrestore(
 			&priv->dp_transmit_idle_wait, DIGI_RETRY_TIMEOUT,
 			&priv->dp_port_lock, flags);
@@ -857,9 +864,10 @@
 }
 
 
-static void digi_rx_throttle(struct usb_serial_port *port)
+static void digi_rx_throttle(struct tty_struct *tty)
 {
 	unsigned long flags;
+	struct usb_serial_port *port = tty->driver_data;
 	struct digi_port *priv = usb_get_serial_port_data(port);
 
 
@@ -873,10 +881,11 @@
 }
 
 
-static void digi_rx_unthrottle(struct usb_serial_port *port)
+static void digi_rx_unthrottle(struct tty_struct *tty)
 {
 	int ret = 0;
 	unsigned long flags;
+	struct usb_serial_port *port = tty->driver_data;
 	struct digi_port *priv = usb_get_serial_port_data(port);
 
 	dbg("digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num);
@@ -901,26 +910,25 @@
 }
 
 
-static void digi_set_termios(struct usb_serial_port *port,
-					struct ktermios *old_termios)
+static void digi_set_termios(struct tty_struct *tty,
+		struct usb_serial_port *port, struct ktermios *old_termios)
 {
-
 	struct digi_port *priv = usb_get_serial_port_data(port);
-	struct tty_struct *tty = port->tty;
 	unsigned int iflag = tty->termios->c_iflag;
 	unsigned int cflag = tty->termios->c_cflag;
 	unsigned int old_iflag = old_termios->c_iflag;
 	unsigned int old_cflag = old_termios->c_cflag;
 	unsigned char buf[32];
 	unsigned int modem_signals;
-	int arg,ret;
+	int arg, ret;
 	int i = 0;
 	speed_t baud;
 
 	dbg("digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, old_cflag=0x%x", priv->dp_port_num, iflag, old_iflag, cflag, old_cflag);
 
 	/* set baud rate */
-	if ((baud = tty_get_baud_rate(tty)) != tty_termios_baud_rate(old_termios)) {
+	baud = tty_get_baud_rate(tty);
+	if (baud != tty_termios_baud_rate(old_termios)) {
 		arg = -1;
 
 		/* reassert DTR and (maybe) RTS on transition from B0 */
@@ -934,30 +942,30 @@
 			digi_set_modem_signals(port, modem_signals, 1);
 		}
 		switch (baud) {
-			/* drop DTR and RTS on transition to B0 */
-			case 0: digi_set_modem_signals(port, 0, 1); break;
-			case 50: arg = DIGI_BAUD_50; break;
-			case 75: arg = DIGI_BAUD_75; break;
-			case 110: arg = DIGI_BAUD_110; break;
-			case 150: arg = DIGI_BAUD_150; break;
-			case 200: arg = DIGI_BAUD_200; break;
-			case 300: arg = DIGI_BAUD_300; break;
-			case 600: arg = DIGI_BAUD_600; break;
-			case 1200: arg = DIGI_BAUD_1200; break;
-			case 1800: arg = DIGI_BAUD_1800; break;
-			case 2400: arg = DIGI_BAUD_2400; break;
-			case 4800: arg = DIGI_BAUD_4800; break;
-			case 9600: arg = DIGI_BAUD_9600; break;
-			case 19200: arg = DIGI_BAUD_19200; break;
-			case 38400: arg = DIGI_BAUD_38400; break;
-			case 57600: arg = DIGI_BAUD_57600; break;
-			case 115200: arg = DIGI_BAUD_115200; break;
-			case 230400: arg = DIGI_BAUD_230400; break;
-			case 460800: arg = DIGI_BAUD_460800; break;
-			default:
-				arg = DIGI_BAUD_9600;
-				baud = 9600;
-				break;
+		/* drop DTR and RTS on transition to B0 */
+		case 0: digi_set_modem_signals(port, 0, 1); break;
+		case 50: arg = DIGI_BAUD_50; break;
+		case 75: arg = DIGI_BAUD_75; break;
+		case 110: arg = DIGI_BAUD_110; break;
+		case 150: arg = DIGI_BAUD_150; break;
+		case 200: arg = DIGI_BAUD_200; break;
+		case 300: arg = DIGI_BAUD_300; break;
+		case 600: arg = DIGI_BAUD_600; break;
+		case 1200: arg = DIGI_BAUD_1200; break;
+		case 1800: arg = DIGI_BAUD_1800; break;
+		case 2400: arg = DIGI_BAUD_2400; break;
+		case 4800: arg = DIGI_BAUD_4800; break;
+		case 9600: arg = DIGI_BAUD_9600; break;
+		case 19200: arg = DIGI_BAUD_19200; break;
+		case 38400: arg = DIGI_BAUD_38400; break;
+		case 57600: arg = DIGI_BAUD_57600; break;
+		case 115200: arg = DIGI_BAUD_115200; break;
+		case 230400: arg = DIGI_BAUD_230400; break;
+		case 460800: arg = DIGI_BAUD_460800; break;
+		default:
+			arg = DIGI_BAUD_9600;
+			baud = 9600;
+			break;
 		}
 		if (arg != -1) {
 			buf[i++] = DIGI_CMD_SET_BAUD_RATE;
@@ -1083,14 +1091,16 @@
 		buf[i++] = arg;
 		buf[i++] = 0;
 	}
-	if ((ret = digi_write_oob_command(port, buf, i, 1)) != 0)
+	ret = digi_write_oob_command(port, buf, i, 1);
+	if (ret != 0)
 		dbg("digi_set_termios: write oob failed, ret=%d", ret);
 	tty_encode_baud_rate(tty, baud, baud);
 }
 
 
-static void digi_break_ctl(struct usb_serial_port *port, int break_state)
+static void digi_break_ctl(struct tty_struct *tty, int break_state)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	unsigned char buf[4];
 
 	buf[0] = DIGI_CMD_BREAK_CONTROL;
@@ -1101,8 +1111,9 @@
 }
 
 
-static int digi_tiocmget(struct usb_serial_port *port, struct file *file)
+static int digi_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct digi_port *priv = usb_get_serial_port_data(port);
 	unsigned int val;
 	unsigned long flags;
@@ -1116,9 +1127,10 @@
 }
 
 
-static int digi_tiocmset(struct usb_serial_port *port, struct file *file,
+static int digi_tiocmset(struct tty_struct *tty, struct file *file,
 	unsigned int set, unsigned int clear)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct digi_port *priv = usb_get_serial_port_data(port);
 	unsigned int val;
 	unsigned long flags;
@@ -1132,30 +1144,11 @@
 }
 
 
-static int digi_ioctl(struct usb_serial_port *port, struct file *file,
-	unsigned int cmd, unsigned long arg)
-{
-	struct digi_port *priv = usb_get_serial_port_data(port);
-	dbg("digi_ioctl: TOP: port=%d, cmd=0x%x", priv->dp_port_num, cmd);
-
-	switch (cmd) {
-	case TIOCMIWAIT:
-		/* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
-		/* TODO */
-		return 0;
-	case TIOCGICOUNT:
-		/* return count of modemline transitions */
-		/* TODO */
-		return 0;
-	}
-	return -ENOIOCTLCMD;
-
-}
-
-static int digi_write(struct usb_serial_port *port, const unsigned char *buf, int count)
+static int digi_write(struct tty_struct *tty, struct usb_serial_port *port,
+					const unsigned char *buf, int count)
 {
 
-	int ret,data_len,new_len;
+	int ret, data_len, new_len;
 	struct digi_port *priv = usb_get_serial_port_data(port);
 	unsigned char *data = port->write_urb->transfer_buffer;
 	unsigned long flags = 0;
@@ -1173,7 +1166,8 @@
 	spin_lock_irqsave(&priv->dp_port_lock, flags);
 
 	/* wait for urb status clear to submit another urb */
-	if (port->write_urb->status == -EINPROGRESS || priv->dp_write_urb_in_use) {
+	if (port->write_urb->status == -EINPROGRESS ||
+					priv->dp_write_urb_in_use) {
 		/* buffer data if count is 1 (probably put_char) if possible */
 		if (count == 1 && priv->dp_out_buf_len < DIGI_OUT_BUF_SIZE) {
 			priv->dp_out_buf[priv->dp_out_buf_len++] = *buf;
@@ -1208,7 +1202,8 @@
 	/* copy in new data */
 	memcpy(data, buf, new_len);
 
-	if ((ret = usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0) {
+	ret = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+	if (ret == 0) {
 		priv->dp_write_urb_in_use = 1;
 		ret = new_len;
 		priv->dp_out_buf_len = 0;
@@ -1222,7 +1217,7 @@
 	dbg("digi_write: returning %d", ret);
 	return ret;
 
-} 
+}
 
 static void digi_write_bulk_callback(struct urb *urb)
 {
@@ -1237,13 +1232,13 @@
 	dbg("digi_write_bulk_callback: TOP, urb->status=%d", status);
 
 	/* port and serial sanity check */
-	if (port == NULL || (priv=usb_get_serial_port_data(port)) == NULL) {
+	if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) {
 		err("%s: port or port->private is NULL, status=%d",
 		    __func__, status);
 		return;
 	}
 	serial = port->serial;
-	if (serial == NULL || (serial_priv=usb_get_serial_data(serial)) == NULL) {
+	if (serial == NULL || (serial_priv = usb_get_serial_data(serial)) == NULL) {
 		err("%s: serial or serial->private is NULL, status=%d",
 		    __func__, status);
 		return;
@@ -1262,17 +1257,19 @@
 	/* try to send any buffered data on this port, if it is open */
 	spin_lock(&priv->dp_port_lock);
 	priv->dp_write_urb_in_use = 0;
-	if (port->open_count && port->write_urb->status != -EINPROGRESS
+	if (port->port.count && port->write_urb->status != -EINPROGRESS
 	    && priv->dp_out_buf_len > 0) {
 		*((unsigned char *)(port->write_urb->transfer_buffer))
 			= (unsigned char)DIGI_CMD_SEND_DATA;
-		*((unsigned char *)(port->write_urb->transfer_buffer)+1)
+		*((unsigned char *)(port->write_urb->transfer_buffer) + 1)
 			= (unsigned char)priv->dp_out_buf_len;
-		port->write_urb->transfer_buffer_length = priv->dp_out_buf_len+2;
+		port->write_urb->transfer_buffer_length =
+						priv->dp_out_buf_len + 2;
 		port->write_urb->dev = serial->dev;
-		memcpy(port->write_urb->transfer_buffer+2, priv->dp_out_buf,
+		memcpy(port->write_urb->transfer_buffer + 2, priv->dp_out_buf,
 			priv->dp_out_buf_len);
-		if ((ret = usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0) {
+		ret = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+		if (ret == 0) {
 			priv->dp_write_urb_in_use = 1;
 			priv->dp_out_buf_len = 0;
 		}
@@ -1289,16 +1286,17 @@
 			__func__, ret, priv->dp_port_num);
 }
 
-static int digi_write_room(struct usb_serial_port *port)
+static int digi_write_room(struct tty_struct *tty)
 {
-
-	int room;
+	struct usb_serial_port *port = tty->driver_data;
 	struct digi_port *priv = usb_get_serial_port_data(port);
+	int room;
 	unsigned long flags = 0;
 
 	spin_lock_irqsave(&priv->dp_port_lock, flags);
 
-	if (port->write_urb->status == -EINPROGRESS || priv->dp_write_urb_in_use)
+	if (port->write_urb->status == -EINPROGRESS ||
+					priv->dp_write_urb_in_use)
 		room = 0;
 	else
 		room = port->bulk_out_size - 2 - priv->dp_out_buf_len;
@@ -1309,12 +1307,11 @@
 
 }
 
-static int digi_chars_in_buffer(struct usb_serial_port *port)
+static int digi_chars_in_buffer(struct tty_struct *tty)
 {
-
+	struct usb_serial_port *port = tty->driver_data;
 	struct digi_port *priv = usb_get_serial_port_data(port);
 
-
 	if (port->write_urb->status == -EINPROGRESS
 	    || priv->dp_write_urb_in_use) {
 		dbg("digi_chars_in_buffer: port=%d, chars=%d",
@@ -1330,7 +1327,8 @@
 }
 
 
-static int digi_open(struct usb_serial_port *port, struct file *filp)
+static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
+				struct file *filp)
 {
 	int ret;
 	unsigned char buf[32];
@@ -1339,7 +1337,7 @@
 	unsigned long flags = 0;
 
 	dbg("digi_open: TOP: port=%d, open_count=%d",
-		priv->dp_port_num, port->open_count);
+		priv->dp_port_num, port->port.count);
 
 	/* be sure the device is started up */
 	if (digi_startup_device(port->serial) != 0)
@@ -1354,7 +1352,7 @@
 	}
 
 	/* wait for a close in progress to finish */
-	while(priv->dp_in_close) {
+	while (priv->dp_in_close) {
 		cond_wait_interruptible_timeout_irqrestore(
 			&priv->dp_close_wait, DIGI_RETRY_TIMEOUT,
 			&priv->dp_port_lock, flags);
@@ -1364,7 +1362,7 @@
 	}
 
 	spin_unlock_irqrestore(&priv->dp_port_lock, flags);
- 
+
 	/* read modem signals automatically whenever they change */
 	buf[0] = DIGI_CMD_READ_INPUT_SIGNALS;
 	buf[1] = priv->dp_port_num;
@@ -1377,13 +1375,16 @@
 	buf[6] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
 	buf[7] = 0;
 
-	if ((ret = digi_write_oob_command(port, buf, 8, 1)) != 0)
+	ret = digi_write_oob_command(port, buf, 8, 1);
+	if (ret != 0)
 		dbg("digi_open: write oob failed, ret=%d", ret);
 
 	/* set termios settings */
-	not_termios.c_cflag = ~port->tty->termios->c_cflag;
-	not_termios.c_iflag = ~port->tty->termios->c_iflag;
-	digi_set_termios(port, &not_termios);
+	if (tty) {
+		not_termios.c_cflag = ~tty->termios->c_cflag;
+		not_termios.c_iflag = ~tty->termios->c_iflag;
+		digi_set_termios(tty, port, &not_termios);
+	}
 
 	/* set DTR and RTS */
 	digi_set_modem_signals(port, TIOCM_DTR|TIOCM_RTS, 1);
@@ -1392,16 +1393,16 @@
 }
 
 
-static void digi_close(struct usb_serial_port *port, struct file *filp)
+static void digi_close(struct tty_struct *tty, struct usb_serial_port *port,
+				struct file *filp)
 {
 	DEFINE_WAIT(wait);
 	int ret;
 	unsigned char buf[32];
-	struct tty_struct *tty = port->tty;
 	struct digi_port *priv = usb_get_serial_port_data(port);
 
 	dbg("digi_close: TOP: port=%d, open_count=%d",
-		priv->dp_port_num, port->open_count);
+		priv->dp_port_num, port->port.count);
 
 	mutex_lock(&port->serial->disc_mutex);
 	/* if disconnected, just clear flags */
@@ -1426,9 +1427,8 @@
 
 	if (port->serial->dev) {
 		/* wait for transmit idle */
-		if ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0) {
+		if ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0)
 			digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT);
-		}
 		/* drop DTR and RTS */
 		digi_set_modem_signals(port, 0, 0);
 
@@ -1462,11 +1462,13 @@
 		buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
 		buf[19] = 0;
 
-		if ((ret = digi_write_oob_command(port, buf, 20, 0)) != 0)
+		ret = digi_write_oob_command(port, buf, 20, 0);
+		if (ret != 0)
 			dbg("digi_close: write oob failed, ret=%d", ret);
 
 		/* wait for final commands on oob port to complete */
-		prepare_to_wait(&priv->dp_flush_wait, &wait, TASK_INTERRUPTIBLE);
+		prepare_to_wait(&priv->dp_flush_wait, &wait,
+							TASK_INTERRUPTIBLE);
 		schedule_timeout(DIGI_CLOSE_TIMEOUT);
 		finish_wait(&priv->dp_flush_wait, &wait);
 
@@ -1486,15 +1488,15 @@
 
 
 /*
-*  Digi Startup Device
-*
-*  Starts reads on all ports.  Must be called AFTER startup, with
-*  urbs initialized.  Returns 0 if successful, non-zero error otherwise.
-*/
+ *  Digi Startup Device
+ *
+ *  Starts reads on all ports.  Must be called AFTER startup, with
+ *  urbs initialized.  Returns 0 if successful, non-zero error otherwise.
+ */
 
 static int digi_startup_device(struct usb_serial *serial)
 {
-	int i,ret = 0;
+	int i, ret = 0;
 	struct digi_serial *serial_priv = usb_get_serial_data(serial);
 	struct usb_serial_port *port;
 
@@ -1512,7 +1514,8 @@
 	for (i = 0; i < serial->type->num_ports + 1; i++) {
 		port = serial->port[i];
 		port->write_urb->dev = port->serial->dev;
-		if ((ret = usb_submit_urb(port->read_urb, GFP_KERNEL)) != 0) {
+		ret = usb_submit_urb(port->read_urb, GFP_KERNEL);
+		if (ret != 0) {
 			err("%s: usb_submit_urb failed, ret=%d, port=%d",
 					__func__, ret, i);
 			break;
@@ -1533,7 +1536,7 @@
 
 	/* allocate the private data structures for all ports */
 	/* number of regular ports + 1 for the out-of-band port */
-	for(i = 0; i < serial->type->num_ports + 1; i++) {
+	for (i = 0; i < serial->type->num_ports + 1; i++) {
 		/* allocate port private structure */
 		priv = kmalloc(sizeof(struct digi_port), GFP_KERNEL);
 		if (priv == NULL) {
@@ -1596,7 +1599,7 @@
 
 	/* free the private data structures for all ports */
 	/* number of regular ports + 1 for the out-of-band port */
-	for(i = 0; i < serial->type->num_ports + 1; i++)
+	for (i = 0; i < serial->type->num_ports + 1; i++)
 		kfree(usb_get_serial_port_data(serial->port[i]));
 	kfree(usb_get_serial_data(serial));
 }
@@ -1619,7 +1622,7 @@
 		return;
 	}
 	if (port->serial == NULL ||
-		(serial_priv=usb_get_serial_data(port->serial)) == NULL) {
+		(serial_priv = usb_get_serial_data(port->serial)) == NULL) {
 		err("%s: serial is bad or serial->private is NULL, status=%d",
 			__func__, status);
 		return;
@@ -1643,45 +1646,46 @@
 
 	/* continue read */
 	urb->dev = port->serial->dev;
-	if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+	ret = usb_submit_urb(urb, GFP_ATOMIC);
+	if (ret != 0) {
 		err("%s: failed resubmitting urb, ret=%d, port=%d",
 		    __func__, ret, priv->dp_port_num);
 	}
 
 }
 
-/* 
-*  Digi Read INB Callback
-*
-*  Digi Read INB Callback handles reads on the in band ports, sending
-*  the data on to the tty subsystem.  When called we know port and
-*  port->private are not NULL and port->serial has been validated.
-*  It returns 0 if successful, 1 if successful but the port is
-*  throttled, and -1 if the sanity checks failed.
-*/
+/*
+ *  Digi Read INB Callback
+ *
+ *  Digi Read INB Callback handles reads on the in band ports, sending
+ *  the data on to the tty subsystem.  When called we know port and
+ *  port->private are not NULL and port->serial has been validated.
+ *  It returns 0 if successful, 1 if successful but the port is
+ *  throttled, and -1 if the sanity checks failed.
+ */
 
 static int digi_read_inb_callback(struct urb *urb)
 {
 
 	struct usb_serial_port *port = urb->context;
-	struct tty_struct *tty = port->tty;
+	struct tty_struct *tty = port->port.tty;
 	struct digi_port *priv = usb_get_serial_port_data(port);
 	int opcode = ((unsigned char *)urb->transfer_buffer)[0];
 	int len = ((unsigned char *)urb->transfer_buffer)[1];
 	int port_status = ((unsigned char *)urb->transfer_buffer)[2];
-	unsigned char *data = ((unsigned char *)urb->transfer_buffer)+3;
-	int flag,throttled;
+	unsigned char *data = ((unsigned char *)urb->transfer_buffer) + 3;
+	int flag, throttled;
 	int i;
 	int status = urb->status;
 
 	/* do not process callbacks on closed ports */
 	/* but do continue the read chain */
-	if (port->open_count == 0)
+	if (port->port.count == 0)
 		return 0;
 
 	/* short/multiple packet check */
 	if (urb->actual_length != len + 2) {
-     		err("%s: INCOMPLETE OR MULTIPLE PACKET, urb->status=%d, "
+		err("%s: INCOMPLETE OR MULTIPLE PACKET, urb->status=%d, "
 		    "port=%d, opcode=%d, len=%d, actual_length=%d, "
 		    "status=%d", __func__, status, priv->dp_port_num,
 		    opcode, len, urb->actual_length, port_status);
@@ -1723,8 +1727,9 @@
 			if (flag == TTY_NORMAL)
 				tty_insert_flip_string(tty, data, len);
 			else {
-				for(i = 0; i < len; i++)
-					tty_insert_flip_char(tty, data[i], flag);
+				for (i = 0; i < len; i++)
+					tty_insert_flip_char(tty,
+								data[i], flag);
 			}
 			tty_flip_buffer_push(tty);
 		}
@@ -1736,19 +1741,19 @@
 	else if (opcode != DIGI_CMD_RECEIVE_DATA)
 		dbg("%s: unknown opcode: %d", __func__, opcode);
 
-	return(throttled ? 1 : 0);
+	return throttled ? 1 : 0;
 
 }
 
 
-/* 
-*  Digi Read OOB Callback
-*
-*  Digi Read OOB Callback handles reads on the out of band port.
-*  When called we know port and port->private are not NULL and
-*  the port->serial is valid.  It returns 0 if successful, and
-*  -1 if the sanity checks failed.
-*/
+/*
+ *  Digi Read OOB Callback
+ *
+ *  Digi Read OOB Callback handles reads on the out of band port.
+ *  When called we know port and port->private are not NULL and
+ *  the port->serial is valid.  It returns 0 if successful, and
+ *  -1 if the sanity checks failed.
+ */
 
 static int digi_read_oob_callback(struct urb *urb)
 {
@@ -1758,12 +1763,13 @@
 	struct digi_port *priv = usb_get_serial_port_data(port);
 	int opcode, line, status, val;
 	int i;
+	unsigned int rts;
 
 	dbg("digi_read_oob_callback: port=%d, len=%d",
 			priv->dp_port_num, urb->actual_length);
 
 	/* handle each oob command */
-	for(i = 0; i < urb->actual_length - 3;) {
+	for (i = 0; i < urb->actual_length - 3;) {
 		opcode = ((unsigned char *)urb->transfer_buffer)[i++];
 		line = ((unsigned char *)urb->transfer_buffer)[i++];
 		status = ((unsigned char *)urb->transfer_buffer)[i++];
@@ -1777,27 +1783,29 @@
 
 		port = serial->port[line];
 
-		if ((priv=usb_get_serial_port_data(port)) == NULL)
+		priv = usb_get_serial_port_data(port);
+		if (priv == NULL)
 			return -1;
 
+		rts = 0;
+		if (port->port.count)
+			rts = port->port.tty->termios->c_cflag & CRTSCTS;
+
 		if (opcode == DIGI_CMD_READ_INPUT_SIGNALS) {
 			spin_lock(&priv->dp_port_lock);
 			/* convert from digi flags to termiox flags */
 			if (val & DIGI_READ_INPUT_SIGNALS_CTS) {
 				priv->dp_modem_signals |= TIOCM_CTS;
 				/* port must be open to use tty struct */
-				if (port->open_count
-					&& port->tty->termios->c_cflag & CRTSCTS) {
-					port->tty->hw_stopped = 0;
+				if (rts) {
+					port->port.tty->hw_stopped = 0;
 					digi_wakeup_write(port);
 				}
 			} else {
 				priv->dp_modem_signals &= ~TIOCM_CTS;
 				/* port must be open to use tty struct */
-				if (port->open_count
-					&& port->tty->termios->c_cflag & CRTSCTS) {
-					port->tty->hw_stopped = 1;
-				}
+				if (rts)
+					port->port.tty->hw_stopped = 1;
 			}
 			if (val & DIGI_READ_INPUT_SIGNALS_DSR)
 				priv->dp_modem_signals |= TIOCM_DSR;
@@ -1834,7 +1842,7 @@
 	if (retval)
 		goto failed_acceleport_2_device;
 	retval = usb_serial_register(&digi_acceleport_4_device);
-	if (retval) 
+	if (retval)
 		goto failed_acceleport_4_device;
 	retval = usb_register(&digi_driver);
 	if (retval)
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index c5ec309..a6ab5b5 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -11,36 +11,39 @@
  *	it under the terms of the GNU General Public License, as published by
  *	the Free Software Foundation, version 2.
  *
- * See Documentation/usb/usb-serial.txt for more information on using this driver
- * 
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
+ *
  * (07/16/2001) gb
- *	remove unused code in empeg_close() (thanks to Oliver Neukum for pointing this
- *	out) and rewrote empeg_set_termios().
- * 
+ *	remove unused code in empeg_close() (thanks to Oliver Neukum for
+ *	pointing this out) and rewrote empeg_set_termios().
+ *
  * (05/30/2001) gkh
- *	switched from using spinlock to a semaphore, which fixes lots of problems.
+ *	switched from using spinlock to a semaphore, which fixes lots of
+ * problems.
  *
  * (04/08/2001) gb
  *      Identify version on module load.
- * 
+ *
  * (01/22/2001) gb
- *	Added write_room() and chars_in_buffer() support. 
- * 
+ *	Added write_room() and chars_in_buffer() support.
+ *
  * (12/21/2000) gb
  *	Moved termio stuff inside the port->active check.
  *	Moved MOD_DEC_USE_COUNT to end of empeg_close().
- * 
+ *
  * (12/03/2000) gb
- *	Added port->tty->ldisc.set_termios(port->tty, NULL) to empeg_open()
- *	This notifies the tty driver that the termios have changed.
- * 
+ *	Added port->port.tty->ldisc.set_termios(port->port.tty, NULL) to
+ *	empeg_open(). This notifies the tty driver that the termios have
+ *	changed.
+ *
  * (11/13/2000) gb
- *	Moved tty->low_latency = 1 from empeg_read_bulk_callback() to empeg_open()
- *	(It only needs to be set once - Doh!)
- * 
+ *	Moved tty->low_latency = 1 from empeg_read_bulk_callback() to
+ *	empeg_open() (It only needs to be set once - Doh!)
+ *
  * (11/11/2000) gb
  *	Updated to work with id_table structure.
- * 
+ *
  * (11/04/2000) gb
  *	Forked this from visor.c, and hacked it up to work with an
  *	Empeg ltd. empeg-car player.  Constructive criticism welcomed.
@@ -48,7 +51,7 @@
  *	use of his code, and for his guidance, advice and patience. :)
  *	A 'Thank You' is in order for John Ripley of Empeg ltd for his
  *	advice, and patience too.
- * 
+ *
  */
 
 #include <linux/kernel.h>
@@ -60,7 +63,7 @@
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
@@ -77,31 +80,30 @@
 #define EMPEG_PRODUCT_ID		0x0001
 
 /* function prototypes for an empeg-car player */
-static int  empeg_open			(struct usb_serial_port *port, struct file *filp);
-static void empeg_close			(struct usb_serial_port *port, struct file *filp);
-static int  empeg_write			(struct usb_serial_port *port,
-					const unsigned char *buf,
-					int count);
-static int  empeg_write_room		(struct usb_serial_port *port);
-static int  empeg_chars_in_buffer	(struct usb_serial_port *port);
-static void empeg_throttle		(struct usb_serial_port *port);
-static void empeg_unthrottle		(struct usb_serial_port *port);
-static int  empeg_startup		(struct usb_serial *serial);
-static void empeg_shutdown		(struct usb_serial *serial);
-static int  empeg_ioctl			(struct usb_serial_port *port,
-					struct file * file,
-					unsigned int cmd,
-					unsigned long arg);
-static void empeg_set_termios		(struct usb_serial_port *port, struct ktermios *old_termios);
-static void empeg_write_bulk_callback	(struct urb *urb);
-static void empeg_read_bulk_callback	(struct urb *urb);
+static int  empeg_open(struct tty_struct *tty, struct usb_serial_port *port,
+						struct file *filp);
+static void empeg_close(struct tty_struct *tty, struct usb_serial_port *port,
+						struct file *filp);
+static int  empeg_write(struct tty_struct *tty, struct usb_serial_port *port,
+						const unsigned char *buf,
+						int count);
+static int  empeg_write_room(struct tty_struct *tty);
+static int  empeg_chars_in_buffer(struct tty_struct *tty);
+static void empeg_throttle(struct tty_struct *tty);
+static void empeg_unthrottle(struct tty_struct *tty);
+static int  empeg_startup(struct usb_serial *serial);
+static void empeg_shutdown(struct usb_serial *serial);
+static void empeg_set_termios(struct tty_struct *tty,
+		struct usb_serial_port *port, struct ktermios *old_termios);
+static void empeg_write_bulk_callback(struct urb *urb);
+static void empeg_read_bulk_callback(struct urb *urb);
 
 static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(EMPEG_VENDOR_ID, EMPEG_PRODUCT_ID) },
 	{ }					/* Terminating entry */
 };
 
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
 
 static struct usb_driver empeg_driver = {
 	.name =		"empeg",
@@ -125,7 +127,6 @@
 	.unthrottle =		empeg_unthrottle,
 	.attach =		empeg_startup,
 	.shutdown =		empeg_shutdown,
-	.ioctl =		empeg_ioctl,
 	.set_termios =		empeg_set_termios,
 	.write =		empeg_write,
 	.write_room =		empeg_write_room,
@@ -145,7 +146,8 @@
 /******************************************************************************
  * Empeg specific driver functions
  ******************************************************************************/
-static int empeg_open (struct usb_serial_port *port, struct file *filp)
+static int empeg_open(struct tty_struct *tty, struct usb_serial_port *port,
+				struct file *filp)
 {
 	struct usb_serial *serial = port->serial;
 	int result = 0;
@@ -153,7 +155,7 @@
 	dbg("%s - port %d", __func__, port->number);
 
 	/* Force default termio settings */
-	empeg_set_termios (port, NULL) ;
+	empeg_set_termios(tty, port, NULL) ;
 
 	bytes_in = 0;
 	bytes_out = 0;
@@ -161,7 +163,7 @@
 	/* Start reading from the device */
 	usb_fill_bulk_urb(
 		port->read_urb,
-		serial->dev, 
+		serial->dev,
 		usb_rcvbulkpipe(serial->dev,
 			port->bulk_in_endpointAddress),
 		port->read_urb->transfer_buffer,
@@ -172,13 +174,16 @@
 	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 
 	if (result)
-		dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
+		dev_err(&port->dev,
+			"%s - failed submitting read urb, error %d\n",
+							__func__, result);
 
 	return result;
 }
 
 
-static void empeg_close (struct usb_serial_port *port, struct file * filp)
+static void empeg_close(struct tty_struct *tty, struct usb_serial_port *port,
+				struct file *filp)
 {
 	dbg("%s - port %d", __func__, port->number);
 
@@ -189,7 +194,8 @@
 }
 
 
-static int empeg_write (struct usb_serial_port *port, const unsigned char *buf, int count)
+static int empeg_write(struct tty_struct *tty, struct usb_serial_port *port,
+					const unsigned char *buf, int count)
 {
 	struct usb_serial *serial = port->serial;
 	struct urb *urb;
@@ -203,11 +209,10 @@
 	dbg("%s - port %d", __func__, port->number);
 
 	while (count > 0) {
-
 		/* try to find a free urb in our list of them */
 		urb = NULL;
 
-		spin_lock_irqsave (&write_urb_pool_lock, flags);
+		spin_lock_irqsave(&write_urb_pool_lock, flags);
 
 		for (i = 0; i < NUM_URBS; ++i) {
 			if (write_urb_pool[i]->status != -EINPROGRESS) {
@@ -216,7 +221,7 @@
 			}
 		}
 
-		spin_unlock_irqrestore (&write_urb_pool_lock, flags);
+		spin_unlock_irqrestore(&write_urb_pool_lock, flags);
 
 		if (urb == NULL) {
 			dbg("%s - no more free urbs", __func__);
@@ -224,25 +229,27 @@
 		}
 
 		if (urb->transfer_buffer == NULL) {
-			urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
+			urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
 			if (urb->transfer_buffer == NULL) {
-				dev_err(&port->dev, "%s no more kernel memory...\n", __func__);
+				dev_err(&port->dev,
+					"%s no more kernel memory...\n",
+								__func__);
 				goto exit;
 			}
 		}
 
-		transfer_size = min (count, URB_TRANSFER_BUFFER_SIZE);
+		transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE);
 
-		memcpy (urb->transfer_buffer, current_position, transfer_size);
+		memcpy(urb->transfer_buffer, current_position, transfer_size);
 
 		usb_serial_debug_data(debug, &port->dev, __func__, transfer_size, urb->transfer_buffer);
 
 		/* build up our urb */
-		usb_fill_bulk_urb (
+		usb_fill_bulk_urb(
 			urb,
 			serial->dev,
 			usb_sndbulkpipe(serial->dev,
-				port->bulk_out_endpointAddress), 
+					port->bulk_out_endpointAddress),
 			urb->transfer_buffer,
 			transfer_size,
 			empeg_write_bulk_callback,
@@ -262,66 +269,57 @@
 		bytes_out += transfer_size;
 
 	}
-
 exit:
 	return bytes_sent;
-
-} 
+}
 
 
-static int empeg_write_room (struct usb_serial_port *port)
+static int empeg_write_room(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	unsigned long flags;
 	int i;
 	int room = 0;
 
 	dbg("%s - port %d", __func__, port->number);
 
-	spin_lock_irqsave (&write_urb_pool_lock, flags);
-
+	spin_lock_irqsave(&write_urb_pool_lock, flags);
 	/* tally up the number of bytes available */
 	for (i = 0; i < NUM_URBS; ++i) {
-		if (write_urb_pool[i]->status != -EINPROGRESS) {
+		if (write_urb_pool[i]->status != -EINPROGRESS)
 			room += URB_TRANSFER_BUFFER_SIZE;
-		}
-	} 
-
-	spin_unlock_irqrestore (&write_urb_pool_lock, flags);
-
+	}
+	spin_unlock_irqrestore(&write_urb_pool_lock, flags);
 	dbg("%s - returns %d", __func__, room);
-
-	return (room);
+	return room;
 
 }
 
 
-static int empeg_chars_in_buffer (struct usb_serial_port *port)
+static int empeg_chars_in_buffer(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	unsigned long flags;
 	int i;
 	int chars = 0;
 
 	dbg("%s - port %d", __func__, port->number);
 
-	spin_lock_irqsave (&write_urb_pool_lock, flags);
+	spin_lock_irqsave(&write_urb_pool_lock, flags);
 
 	/* tally up the number of bytes waiting */
 	for (i = 0; i < NUM_URBS; ++i) {
-		if (write_urb_pool[i]->status == -EINPROGRESS) {
+		if (write_urb_pool[i]->status == -EINPROGRESS)
 			chars += URB_TRANSFER_BUFFER_SIZE;
-		}
 	}
 
-	spin_unlock_irqrestore (&write_urb_pool_lock, flags);
-
+	spin_unlock_irqrestore(&write_urb_pool_lock, flags);
 	dbg("%s - returns %d", __func__, chars);
-
-	return (chars);
-
+	return chars;
 }
 
 
-static void empeg_write_bulk_callback (struct urb *urb)
+static void empeg_write_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 	int status = urb->status;
@@ -338,7 +336,7 @@
 }
 
 
-static void empeg_read_bulk_callback (struct urb *urb)
+static void empeg_read_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 	struct tty_struct *tty;
@@ -354,9 +352,9 @@
 		return;
 	}
 
-	usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
-
-	tty = port->tty;
+	usb_serial_debug_data(debug, &port->dev, __func__,
+						urb->actual_length, data);
+	tty = port->port.tty;
 
 	if (urb->actual_length) {
 		tty_buffer_request_room(tty, urb->actual_length);
@@ -368,7 +366,7 @@
 	/* Continue trying to always read  */
 	usb_fill_bulk_urb(
 		port->read_urb,
-		port->serial->dev, 
+		port->serial->dev,
 		usb_rcvbulkpipe(port->serial->dev,
 			port->bulk_in_endpointAddress),
 		port->read_urb->transfer_buffer,
@@ -379,38 +377,39 @@
 	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 
 	if (result)
-		dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
+		dev_err(&urb->dev->dev,
+			"%s - failed resubmitting read urb, error %d\n",
+							__func__, result);
 
 	return;
 
 }
 
 
-static void empeg_throttle (struct usb_serial_port *port)
+static void empeg_throttle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	dbg("%s - port %d", __func__, port->number);
 	usb_kill_urb(port->read_urb);
 }
 
 
-static void empeg_unthrottle (struct usb_serial_port *port)
+static void empeg_unthrottle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	int result;
-
 	dbg("%s - port %d", __func__, port->number);
 
 	port->read_urb->dev = port->serial->dev;
-
 	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
-
 	if (result)
-		dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
-
-	return;
+		dev_err(&port->dev,
+			"%s - failed submitting read urb, error %d\n",
+							__func__, result);
 }
 
 
-static int  empeg_startup (struct usb_serial *serial)
+static int  empeg_startup(struct usb_serial *serial)
 {
 	int r;
 
@@ -422,7 +421,7 @@
 		return -ENODEV;
 	}
 	dbg("%s - reset config", __func__);
-	r = usb_reset_configuration (serial->dev);
+	r = usb_reset_configuration(serial->dev);
 
 	/* continue on with initialization */
 	return r;
@@ -430,34 +429,27 @@
 }
 
 
-static void empeg_shutdown (struct usb_serial *serial)
+static void empeg_shutdown(struct usb_serial *serial)
 {
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 }
 
 
-static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+static void empeg_set_termios(struct tty_struct *tty,
+		struct usb_serial_port *port, struct ktermios *old_termios)
 {
-	dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
-
-	return -ENOIOCTLCMD;
-}
-
-
-static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
-{
-	struct ktermios *termios = port->tty->termios;
+	struct ktermios *termios = tty->termios;
 	dbg("%s - port %d", __func__, port->number);
 
 	/*
-         * The empeg-car player wants these particular tty settings.
-         * You could, for example, change the baud rate, however the
-         * player only supports 115200 (currently), so there is really
-         * no point in support for changes to the tty settings.
-         * (at least for now)
-         *
-         * The default requirements for this device are:
-         */
+	 * The empeg-car player wants these particular tty settings.
+	 * You could, for example, change the baud rate, however the
+	 * player only supports 115200 (currently), so there is really
+	 * no point in support for changes to the tty settings.
+	 * (at least for now)
+	 *
+	 * The default requirements for this device are:
+	 */
 	termios->c_iflag
 		&= ~(IGNBRK	/* disable ignore break */
 		| BRKINT	/* disable break causes interrupt */
@@ -491,18 +483,18 @@
 	 * this is bad as it opens up the possibility of dropping bytes
 	 * on the floor.  We don't want to drop bytes on the floor. :)
 	 */
-	port->tty->low_latency = 1;
-	tty_encode_baud_rate(port->tty, 115200, 115200);
+	tty->low_latency = 1;
+	tty_encode_baud_rate(tty, 115200, 115200);
 }
 
 
-static int __init empeg_init (void)
+static int __init empeg_init(void)
 {
 	struct urb *urb;
 	int i, retval;
 
-	/* create our write urb pool and transfer buffers */ 
-	spin_lock_init (&write_urb_pool_lock);
+	/* create our write urb pool and transfer buffers */
+	spin_lock_init(&write_urb_pool_lock);
 	for (i = 0; i < NUM_URBS; ++i) {
 		urb = usb_alloc_urb(0, GFP_KERNEL);
 		write_urb_pool[i] = urb;
@@ -511,9 +503,10 @@
 			continue;
 		}
 
-		urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+		urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
+								GFP_KERNEL);
 		if (!urb->transfer_buffer) {
-			err("%s - out of memory for urb buffers.", 
+			err("%s - out of memory for urb buffers.",
 			    __func__);
 			continue;
 		}
@@ -542,36 +535,36 @@
 }
 
 
-static void __exit empeg_exit (void)
+static void __exit empeg_exit(void)
 {
 	int i;
 	unsigned long flags;
 
 	usb_deregister(&empeg_driver);
-	usb_serial_deregister (&empeg_device);
+	usb_serial_deregister(&empeg_device);
 
-	spin_lock_irqsave (&write_urb_pool_lock, flags);
+	spin_lock_irqsave(&write_urb_pool_lock, flags);
 
 	for (i = 0; i < NUM_URBS; ++i) {
 		if (write_urb_pool[i]) {
-			/* FIXME - uncomment the following usb_kill_urb call when
-			 * the host controllers get fixed to set urb->dev = NULL after
-			 * the urb is finished.  Otherwise this call oopses. */
+			/* FIXME - uncomment the following usb_kill_urb call
+			 * when the host controllers get fixed to set urb->dev
+			 * = NULL after the urb is finished.  Otherwise this
+			 * call oopses. */
 			/* usb_kill_urb(write_urb_pool[i]); */
 			kfree(write_urb_pool[i]->transfer_buffer);
-			usb_free_urb (write_urb_pool[i]);
+			usb_free_urb(write_urb_pool[i]);
 		}
 	}
-
-	spin_unlock_irqrestore (&write_urb_pool_lock, flags);
+	spin_unlock_irqrestore(&write_urb_pool_lock, flags);
 }
 
 
 module_init(empeg_init);
 module_exit(empeg_exit);
 
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c
index cc4fbd9..711e84f 100644
--- a/drivers/usb/serial/ezusb.c
+++ b/drivers/usb/serial/ezusb.c
@@ -20,7 +20,8 @@
 /* EZ-USB Control and Status Register.  Bit 0 controls 8051 reset */
 #define CPUCS_REG    0x7F92
 
-int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest)
+int ezusb_writememory(struct usb_serial *serial, int address,
+				unsigned char *data, int length, __u8 request)
 {
 	int result;
 	unsigned char *transfer_buffer;
@@ -33,26 +34,27 @@
 
 	transfer_buffer = kmemdup(data, length, GFP_KERNEL);
 	if (!transfer_buffer) {
-		dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, length);
+		dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n",
+							__func__, length);
 		return -ENOMEM;
 	}
-	result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 3000);
-	kfree (transfer_buffer);
+	result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+		     request, 0x40, address, 0, transfer_buffer, length, 3000);
+	kfree(transfer_buffer);
 	return result;
 }
+EXPORT_SYMBOL_GPL(ezusb_writememory);
 
-int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit)
+int ezusb_set_reset(struct usb_serial *serial, unsigned char reset_bit)
 {
 	int response;
 
 	/* dbg("%s - %d", __func__, reset_bit); */
-	response = ezusb_writememory (serial, CPUCS_REG, &reset_bit, 1, 0xa0);
+	response = ezusb_writememory(serial, CPUCS_REG, &reset_bit, 1, 0xa0);
 	if (response < 0)
-		dev_err(&serial->dev->dev, "%s- %d failed\n", __func__, reset_bit);
+		dev_err(&serial->dev->dev, "%s- %d failed\n",
+						__func__, reset_bit);
 	return response;
 }
-
-
-EXPORT_SYMBOL_GPL(ezusb_writememory);
 EXPORT_SYMBOL_GPL(ezusb_set_reset);
 
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 0ff4a39..8387172 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -12,7 +12,8 @@
  *	the Free Software Foundation; either version 2 of the License, or
  *	(at your option) any later version.
  *
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
  *
  * See http://ftdi-usb-sio.sourceforge.net for upto date testing info
  *	and extra documentation
@@ -25,7 +26,8 @@
 /* Bill Ryder - bryder@sgi.com - wrote the FTDI_SIO implementation */
 /* Thanx to FTDI for so kindly providing details of the protocol required */
 /*   to talk to the device */
-/* Thanx to gkh and the rest of the usb dev group for all code I have assimilated :-) */
+/* Thanx to gkh and the rest of the usb dev group for all code I have
+   assimilated :-) */
 
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -36,7 +38,7 @@
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/serial.h>
 #include <linux/usb/serial.h>
@@ -55,17 +57,22 @@
 
 struct ftdi_private {
 	ftdi_chip_type_t chip_type;
-				/* type of the device, either SIO or FT8U232AM */
+				/* type of device, either SIO or FT8U232AM */
 	int baud_base;		/* baud base clock for divisor setting */
-	int custom_divisor;	/* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */
+	int custom_divisor;	/* custom_divisor kludge, this is for
+				   baud_base (different from what goes to the
+				   chip!) */
 	__u16 last_set_data_urb_value ;
-				/* the last data state set - needed for doing a break */
-        int write_offset;       /* This is the offset in the usb data block to write the serial data -
-				 * it is different between devices
+				/* the last data state set - needed for doing
+				 * a break
+				 */
+	int write_offset;       /* This is the offset in the usb data block to
+				 * write the serial data - it varies between
+				 * devices
 				 */
 	int flags;		/* some ASYNC_xxxx flags are supported */
 	unsigned long last_dtr_rts;	/* saved modem control outputs */
-        wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
+	wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
 	char prev_status, diff_status;        /* Used for TIOCMIWAIT */
 	__u8 rx_flags;		/* receive state flags (throttling) */
 	spinlock_t rx_lock;	/* spinlock for receive state */
@@ -76,8 +83,10 @@
 
 	__u16 interface;	/* FT2232C port interface (0 for FT232/245) */
 
-	speed_t force_baud;	/* if non-zero, force the baud rate to this value */
-	int force_rtscts;	/* if non-zero, force RTS-CTS to always be enabled */
+	speed_t force_baud;	/* if non-zero, force the baud rate to
+				   this value */
+	int force_rtscts;	/* if non-zero, force RTS-CTS to always
+				   be enabled */
 
 	spinlock_t tx_lock;	/* spinlock for transmit state */
 	unsigned long tx_bytes;
@@ -88,13 +97,14 @@
 /* struct ftdi_sio_quirk is used by devices requiring special attention. */
 struct ftdi_sio_quirk {
 	int (*probe)(struct usb_serial *);
-	void (*port_probe)(struct ftdi_private *); /* Special settings for probed ports. */
+	/* Special settings for probed ports. */
+	void (*port_probe)(struct ftdi_private *);
 };
 
-static int   ftdi_jtag_probe		(struct usb_serial *serial);
-static int   ftdi_mtxorb_hack_setup	(struct usb_serial *serial);
-static void  ftdi_USB_UIRT_setup	(struct ftdi_private *priv);
-static void  ftdi_HE_TIRA1_setup	(struct ftdi_private *priv);
+static int   ftdi_jtag_probe(struct usb_serial *serial);
+static int   ftdi_mtxorb_hack_setup(struct usb_serial *serial);
+static void  ftdi_USB_UIRT_setup(struct ftdi_private *priv);
+static void  ftdi_HE_TIRA1_setup(struct ftdi_private *priv);
 
 static struct ftdi_sio_quirk ftdi_jtag_quirk = {
 	.probe	= ftdi_jtag_probe,
@@ -174,270 +184,270 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_4_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0100_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0101_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0102_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0103_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0104_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0105_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0106_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0107_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0108_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0109_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010A_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010B_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010C_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010D_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010E_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_010F_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0110_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0111_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0112_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0113_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0114_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0115_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0116_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0117_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0118_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0119_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011A_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011B_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011C_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011D_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011E_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_011F_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0120_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0121_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0122_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0123_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0124_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0125_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0126_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0127_PID),
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0103_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0104_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0105_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0106_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0107_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0108_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0109_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010A_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010B_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010C_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010D_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010E_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_010F_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0110_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0111_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0112_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0113_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0114_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0115_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0116_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0117_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0118_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0119_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011A_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011B_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011C_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011D_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011E_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_011F_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0120_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0121_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0122_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0123_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0124_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0125_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0126_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0127_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0128_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0129_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012A_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012B_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012C_PID),
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0128_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0129_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012A_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012B_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012C_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012D_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012E_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_012F_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0130_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0131_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0132_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0133_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0134_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0135_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0136_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0137_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0138_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0139_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013A_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013B_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013C_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013D_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013E_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_013F_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0140_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0141_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0142_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0143_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0144_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0145_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0146_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0147_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0148_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0149_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014A_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014B_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014C_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014D_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014E_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_014F_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0150_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0151_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0152_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0153_PID),
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012D_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012E_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_012F_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0130_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0131_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0132_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0133_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0134_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0135_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0136_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0137_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0138_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0139_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013A_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013B_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013C_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013D_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013E_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_013F_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0140_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0141_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0142_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0143_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0144_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0145_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0146_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0147_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0148_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0149_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014A_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014B_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014C_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014D_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014E_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_014F_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0150_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0151_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0152_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0153_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0154_PID),
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0154_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0155_PID),
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0155_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0156_PID),
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0156_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0157_PID),
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0157_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0158_PID),
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0158_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0159_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015A_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015B_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015C_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015D_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015E_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_015F_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0160_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0161_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0162_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0163_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0164_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0165_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0166_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0167_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0168_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0169_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016A_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016B_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016C_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016D_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016E_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_016F_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0170_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0171_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0172_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0173_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0174_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0175_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0176_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0177_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0178_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0179_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017A_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017B_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017C_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017D_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017E_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_017F_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0180_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0181_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0182_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0183_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0184_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0185_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0186_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0187_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0188_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0189_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018A_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018B_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018C_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018D_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018E_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_018F_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0190_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0191_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0192_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0193_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0194_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0195_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0196_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0197_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0198_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_0199_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019A_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019B_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019C_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019D_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019E_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_019F_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A0_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A1_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A2_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A3_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A4_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A5_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A6_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A7_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A8_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01A9_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AA_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AB_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AC_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AD_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AE_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01AF_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B0_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B1_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B2_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B3_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B4_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B5_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B6_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B7_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B8_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01B9_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BA_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BB_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BC_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BD_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BE_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01BF_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C0_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C1_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C2_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C3_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C4_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C5_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C6_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C7_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C8_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01C9_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CA_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CB_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CC_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CD_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CE_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01CF_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D0_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D1_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D2_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D3_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D4_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D5_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D6_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D7_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D8_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01D9_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DA_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DB_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DC_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DD_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DE_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01DF_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E0_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E1_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E2_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E3_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E4_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E5_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E6_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E7_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E8_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01E9_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EA_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EB_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EC_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01ED_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EE_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01EF_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F0_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F1_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F2_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F3_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F4_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F5_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F6_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F7_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F8_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01F9_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FA_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FB_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FC_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FD_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FE_PID) },
-	{ USB_DEVICE(MTXORB_VID,MTXORB_FTDI_RANGE_01FF_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0159_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015A_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015B_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015C_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015D_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015E_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_015F_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0160_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0161_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0162_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0163_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0164_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0165_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0166_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0167_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0168_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0169_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016A_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016B_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016C_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016D_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016E_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_016F_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0170_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0171_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0172_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0173_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0174_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0175_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0176_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0177_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0178_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0179_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017A_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017B_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017C_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017D_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017E_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_017F_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0180_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0181_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0182_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0183_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0184_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0185_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0186_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0187_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0188_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0189_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018A_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018B_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018C_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018D_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018E_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_018F_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0190_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0191_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0192_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0193_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0194_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0195_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0196_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0197_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0198_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0199_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019A_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019B_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019C_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019D_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019E_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_019F_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A0_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A1_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A2_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A3_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A4_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A5_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A6_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A7_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A8_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01A9_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AA_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AB_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AC_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AD_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AE_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01AF_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B0_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B1_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B2_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B3_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B4_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B5_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B6_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B7_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B8_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01B9_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BA_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BB_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BC_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BD_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BE_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01BF_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C0_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C1_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C2_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C3_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C4_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C5_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C6_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C7_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C8_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01C9_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CA_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CB_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CC_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CD_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CE_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01CF_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D0_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D1_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D2_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D3_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D4_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D5_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D6_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D7_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D8_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01D9_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DA_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DB_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DC_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DD_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DE_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01DF_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E0_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E1_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E2_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E3_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E4_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E5_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E6_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E7_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E8_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01E9_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EA_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EB_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EC_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01ED_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EE_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01EF_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F0_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F1_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F2_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F3_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F4_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F5_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F6_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F7_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F8_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01F9_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FA_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FB_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FC_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FD_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FE_PID) },
+	{ USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_01FF_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) },
@@ -642,7 +652,7 @@
 	{ }					/* Terminating entry */
 };
 
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
 
 static struct usb_driver ftdi_driver = {
 	.name =		"ftdi_sio",
@@ -678,30 +688,37 @@
  | ASYNC_SPD_CUST | ASYNC_SPD_SHI | ASYNC_SPD_WARP)
 
 /* function prototypes for a FTDI serial converter */
-static int  ftdi_sio_probe	(struct usb_serial *serial, const struct usb_device_id *id);
-static void ftdi_shutdown		(struct usb_serial *serial);
-static int  ftdi_sio_port_probe	(struct usb_serial_port *port);
-static int  ftdi_sio_port_remove	(struct usb_serial_port *port);
-static int  ftdi_open			(struct usb_serial_port *port, struct file *filp);
-static void ftdi_close			(struct usb_serial_port *port, struct file *filp);
-static int  ftdi_write			(struct usb_serial_port *port, const unsigned char *buf, int count);
-static int  ftdi_write_room		(struct usb_serial_port *port);
-static int  ftdi_chars_in_buffer	(struct usb_serial_port *port);
-static void ftdi_write_bulk_callback	(struct urb *urb);
-static void ftdi_read_bulk_callback	(struct urb *urb);
-static void ftdi_process_read		(struct work_struct *work);
-static void ftdi_set_termios		(struct usb_serial_port *port, struct ktermios * old);
-static int  ftdi_tiocmget               (struct usb_serial_port *port, struct file *file);
-static int  ftdi_tiocmset		(struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear);
-static int  ftdi_ioctl			(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void ftdi_break_ctl		(struct usb_serial_port *port, int break_state );
-static void ftdi_throttle		(struct usb_serial_port *port);
-static void ftdi_unthrottle		(struct usb_serial_port *port);
+static int  ftdi_sio_probe(struct usb_serial *serial,
+					const struct usb_device_id *id);
+static void ftdi_shutdown(struct usb_serial *serial);
+static int  ftdi_sio_port_probe(struct usb_serial_port *port);
+static int  ftdi_sio_port_remove(struct usb_serial_port *port);
+static int  ftdi_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
+static void ftdi_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
+static int  ftdi_write(struct tty_struct *tty, struct usb_serial_port *port,
+			const unsigned char *buf, int count);
+static int  ftdi_write_room(struct tty_struct *tty);
+static int  ftdi_chars_in_buffer(struct tty_struct *tty);
+static void ftdi_write_bulk_callback(struct urb *urb);
+static void ftdi_read_bulk_callback(struct urb *urb);
+static void ftdi_process_read(struct work_struct *work);
+static void ftdi_set_termios(struct tty_struct *tty,
+			struct usb_serial_port *port, struct ktermios *old);
+static int  ftdi_tiocmget(struct tty_struct *tty, struct file *file);
+static int  ftdi_tiocmset(struct tty_struct *tty, struct file *file,
+			unsigned int set, unsigned int clear);
+static int  ftdi_ioctl(struct tty_struct *tty, struct file *file,
+			unsigned int cmd, unsigned long arg);
+static void ftdi_break_ctl(struct tty_struct *tty, int break_state);
+static void ftdi_throttle(struct tty_struct *tty);
+static void ftdi_unthrottle(struct tty_struct *tty);
 
-static unsigned short int ftdi_232am_baud_base_to_divisor (int baud, int base);
-static unsigned short int ftdi_232am_baud_to_divisor (int baud);
-static __u32 ftdi_232bm_baud_base_to_divisor (int baud, int base);
-static __u32 ftdi_232bm_baud_to_divisor (int baud);
+static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base);
+static unsigned short int ftdi_232am_baud_to_divisor(int baud);
+static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base);
+static __u32 ftdi_232bm_baud_to_divisor(int baud);
 
 static struct usb_serial_driver ftdi_sio_device = {
 	.driver = {
@@ -752,44 +769,54 @@
 static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base)
 {
 	unsigned short int divisor;
-	int divisor3 = base / 2 / baud; // divisor shifted 3 bits to the left
-	if ((divisor3 & 0x7) == 7) divisor3 ++; // round x.7/8 up to x+1
+	/* divisor shifted 3 bits to the left */
+	int divisor3 = base / 2 / baud;
+	if ((divisor3 & 0x7) == 7)
+		divisor3++; /* round x.7/8 up to x+1 */
 	divisor = divisor3 >> 3;
 	divisor3 &= 0x7;
-	if (divisor3 == 1) divisor |= 0xc000; else // 0.125
-	if (divisor3 >= 4) divisor |= 0x4000; else // 0.5
-	if (divisor3 != 0) divisor |= 0x8000;      // 0.25
-	if (divisor == 1) divisor = 0;	/* special case for maximum baud rate */
+	if (divisor3 == 1)
+		divisor |= 0xc000;
+	else if (divisor3 >= 4)
+		divisor |= 0x4000;
+	else if (divisor3 != 0)
+		divisor |= 0x8000;
+	else if (divisor == 1)
+		divisor = 0;	/* special case for maximum baud rate */
 	return divisor;
 }
 
 static unsigned short int ftdi_232am_baud_to_divisor(int baud)
 {
-	 return(ftdi_232am_baud_base_to_divisor(baud, 48000000));
+	 return ftdi_232am_baud_base_to_divisor(baud, 48000000);
 }
 
 static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base)
 {
 	static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 };
 	__u32 divisor;
-	int divisor3 = base / 2 / baud; // divisor shifted 3 bits to the left
+	/* divisor shifted 3 bits to the left */
+	int divisor3 = base / 2 / baud;
 	divisor = divisor3 >> 3;
 	divisor |= (__u32)divfrac[divisor3 & 0x7] << 14;
 	/* Deal with special cases for highest baud rates. */
-	if (divisor == 1) divisor = 0; else	// 1.0
-	if (divisor == 0x4001) divisor = 1;	// 1.5
+	if (divisor == 1)
+		divisor = 0;
+	else if (divisor == 0x4001)
+		divisor = 1;
 	return divisor;
 }
 
 static __u32 ftdi_232bm_baud_to_divisor(int baud)
 {
-	 return(ftdi_232bm_baud_base_to_divisor(baud, 48000000));
+	 return ftdi_232bm_baud_base_to_divisor(baud, 48000000);
 }
 
 #define set_mctrl(port, set)		update_mctrl((port), (set), 0)
 #define clear_mctrl(port, clear)	update_mctrl((port), 0, (clear))
 
-static int update_mctrl(struct usb_serial_port *port, unsigned int set, unsigned int clear)
+static int update_mctrl(struct usb_serial_port *port, unsigned int set,
+							unsigned int clear)
 {
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	char *buf;
@@ -843,14 +870,123 @@
 }
 
 
-static __u32 get_ftdi_divisor(struct usb_serial_port * port);
+static __u32 get_ftdi_divisor(struct tty_struct *tty,
+						struct usb_serial_port *port)
+{ /* get_ftdi_divisor */
+	struct ftdi_private *priv = usb_get_serial_port_data(port);
+	__u32 div_value = 0;
+	int div_okay = 1;
+	int baud;
 
+	/*
+	 * The logic involved in setting the baudrate can be cleanly split into
+	 * 3 steps.
+	 * 1. Standard baud rates are set in tty->termios->c_cflag
+	 * 2. If these are not enough, you can set any speed using alt_speed as
+	 * follows:
+	 *    - set tty->termios->c_cflag speed to B38400
+	 *    - set your real speed in tty->alt_speed; it gets ignored when
+	 *      alt_speed==0, (or)
+	 *    - call TIOCSSERIAL ioctl with (struct serial_struct) set as
+	 *	follows:
+	 *      flags & ASYNC_SPD_MASK == ASYNC_SPD_[HI, VHI, SHI, WARP],
+	 *	this just sets alt_speed to (HI: 57600, VHI: 115200,
+	 *	SHI: 230400, WARP: 460800)
+	 * ** Steps 1, 2 are done courtesy of tty_get_baud_rate
+	 * 3. You can also set baud rate by setting custom divisor as follows
+	 *    - set tty->termios->c_cflag speed to B38400
+	 *    - call TIOCSSERIAL ioctl with (struct serial_struct) set as
+	 *	follows:
+	 *      o flags & ASYNC_SPD_MASK == ASYNC_SPD_CUST
+	 *      o custom_divisor set to baud_base / your_new_baudrate
+	 * ** Step 3 is done courtesy of code borrowed from serial.c
+	 *    I should really spend some time and separate + move this common
+	 *    code to serial.c, it is replicated in nearly every serial driver
+	 *    you see.
+	 */
 
-static int change_speed(struct usb_serial_port *port)
+	/* 1. Get the baud rate from the tty settings, this observes
+	      alt_speed hack */
+
+	baud = tty_get_baud_rate(tty);
+	dbg("%s - tty_get_baud_rate reports speed %d", __func__, baud);
+
+	/* 2. Observe async-compatible custom_divisor hack, update baudrate
+	   if needed */
+
+	if (baud == 38400 &&
+	    ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
+	     (priv->custom_divisor)) {
+		baud = priv->baud_base / priv->custom_divisor;
+		dbg("%s - custom divisor %d sets baud rate to %d",
+				__func__, priv->custom_divisor, baud);
+	}
+
+	/* 3. Convert baudrate to device-specific divisor */
+
+	if (!baud)
+		baud = 9600;
+	switch (priv->chip_type) {
+	case SIO: /* SIO chip */
+		switch (baud) {
+		case 300: div_value = ftdi_sio_b300; break;
+		case 600: div_value = ftdi_sio_b600; break;
+		case 1200: div_value = ftdi_sio_b1200; break;
+		case 2400: div_value = ftdi_sio_b2400; break;
+		case 4800: div_value = ftdi_sio_b4800; break;
+		case 9600: div_value = ftdi_sio_b9600; break;
+		case 19200: div_value = ftdi_sio_b19200; break;
+		case 38400: div_value = ftdi_sio_b38400; break;
+		case 57600: div_value = ftdi_sio_b57600;  break;
+		case 115200: div_value = ftdi_sio_b115200; break;
+		} /* baud */
+		if (div_value == 0) {
+			dbg("%s - Baudrate (%d) requested is not supported",
+							__func__,  baud);
+			div_value = ftdi_sio_b9600;
+			baud = 9600;
+			div_okay = 0;
+		}
+		break;
+	case FT8U232AM: /* 8U232AM chip */
+		if (baud <= 3000000) {
+			div_value = ftdi_232am_baud_to_divisor(baud);
+		} else {
+			dbg("%s - Baud rate too high!", __func__);
+			baud = 9600;
+			div_value = ftdi_232am_baud_to_divisor(9600);
+			div_okay = 0;
+		}
+		break;
+	case FT232BM: /* FT232BM chip */
+	case FT2232C: /* FT2232C chip */
+	case FT232RL:
+		if (baud <= 3000000) {
+			div_value = ftdi_232bm_baud_to_divisor(baud);
+		} else {
+			dbg("%s - Baud rate too high!", __func__);
+			div_value = ftdi_232bm_baud_to_divisor(9600);
+			div_okay = 0;
+			baud = 9600;
+		}
+		break;
+	} /* priv->chip_type */
+
+	if (div_okay) {
+		dbg("%s - Baud rate set to %d (divisor 0x%lX) on chip %s",
+			__func__, baud, (unsigned long)div_value,
+			ftdi_chip_name[priv->chip_type]);
+	}
+
+	tty_encode_baud_rate(tty, baud, baud);
+	return div_value;
+}
+
+static int change_speed(struct tty_struct *tty, struct usb_serial_port *port)
 {
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	char *buf;
-        __u16 urb_value;
+	__u16 urb_value;
 	__u16 urb_index;
 	__u32 urb_index_value;
 	int rv;
@@ -859,7 +995,7 @@
 	if (!buf)
 		return -ENOMEM;
 
-	urb_index_value = get_ftdi_divisor(port);
+	urb_index_value = get_ftdi_divisor(tty, port);
 	urb_value = (__u16)urb_index_value;
 	urb_index = (__u16)(urb_index_value >> 16);
 	if (priv->interface) {	/* FT2232C */
@@ -878,110 +1014,9 @@
 }
 
 
-static __u32 get_ftdi_divisor(struct usb_serial_port * port)
-{ /* get_ftdi_divisor */
-	struct ftdi_private *priv = usb_get_serial_port_data(port);
-	__u32 div_value = 0;
-	int div_okay = 1;
-	int baud;
 
-	/*
-	 * The logic involved in setting the baudrate can be cleanly split in 3 steps.
-	 * Obtaining the actual baud rate is a little tricky since unix traditionally
-	 * somehow ignored the possibility to set non-standard baud rates.
-	 * 1. Standard baud rates are set in tty->termios->c_cflag
-	 * 2. If these are not enough, you can set any speed using alt_speed as follows:
-	 *    - set tty->termios->c_cflag speed to B38400
-	 *    - set your real speed in tty->alt_speed; it gets ignored when
-	 *      alt_speed==0, (or)
-	 *    - call TIOCSSERIAL ioctl with (struct serial_struct) set as follows:
-	 *      flags & ASYNC_SPD_MASK == ASYNC_SPD_[HI, VHI, SHI, WARP], this just
-	 *      sets alt_speed to (HI: 57600, VHI: 115200, SHI: 230400, WARP: 460800)
-	 * ** Steps 1, 2 are done courtesy of tty_get_baud_rate
-	 * 3. You can also set baud rate by setting custom divisor as follows
-	 *    - set tty->termios->c_cflag speed to B38400
-	 *    - call TIOCSSERIAL ioctl with (struct serial_struct) set as follows:
-	 *      o flags & ASYNC_SPD_MASK == ASYNC_SPD_CUST
-	 *      o custom_divisor set to baud_base / your_new_baudrate
-	 * ** Step 3 is done courtesy of code borrowed from serial.c - I should really
-	 *    spend some time and separate+move this common code to serial.c, it is
-	 *    replicated in nearly every serial driver you see.
-	 */
-
-	/* 1. Get the baud rate from the tty settings, this observes alt_speed hack */
-
-	baud = tty_get_baud_rate(port->tty);
-	dbg("%s - tty_get_baud_rate reports speed %d", __func__, baud);
-
-	/* 2. Observe async-compatible custom_divisor hack, update baudrate if needed */
-
-	if (baud == 38400 &&
-	    ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
-	     (priv->custom_divisor)) {
-		baud = priv->baud_base / priv->custom_divisor;
-		dbg("%s - custom divisor %d sets baud rate to %d", __func__, priv->custom_divisor, baud);
-	}
-
-	/* 3. Convert baudrate to device-specific divisor */
-
-	if (!baud) baud = 9600;
-	switch(priv->chip_type) {
-	case SIO: /* SIO chip */
-		switch(baud) {
-		case 300: div_value = ftdi_sio_b300; break;
-		case 600: div_value = ftdi_sio_b600; break;
-		case 1200: div_value = ftdi_sio_b1200; break;
-		case 2400: div_value = ftdi_sio_b2400; break;
-		case 4800: div_value = ftdi_sio_b4800; break;
-		case 9600: div_value = ftdi_sio_b9600; break;
-		case 19200: div_value = ftdi_sio_b19200; break;
-		case 38400: div_value = ftdi_sio_b38400; break;
-		case 57600: div_value = ftdi_sio_b57600;  break;
-		case 115200: div_value = ftdi_sio_b115200; break;
-		} /* baud */
-		if (div_value == 0) {
-			dbg("%s - Baudrate (%d) requested is not supported", __func__,  baud);
-			div_value = ftdi_sio_b9600;
-			baud = 9600;
-			div_okay = 0;
-		}
-		break;
-	case FT8U232AM: /* 8U232AM chip */
-		if (baud <= 3000000) {
-			div_value = ftdi_232am_baud_to_divisor(baud);
-		} else {
-	                dbg("%s - Baud rate too high!", __func__);
-			baud = 9600;
-			div_value = ftdi_232am_baud_to_divisor(9600);
-			div_okay = 0;
-		}
-		break;
-	case FT232BM: /* FT232BM chip */
-	case FT2232C: /* FT2232C chip */
-	case FT232RL:
-		if (baud <= 3000000) {
-			div_value = ftdi_232bm_baud_to_divisor(baud);
-		} else {
-	                dbg("%s - Baud rate too high!", __func__);
-			div_value = ftdi_232bm_baud_to_divisor(9600);
-			div_okay = 0;
-			baud = 9600;
-		}
-		break;
-	} /* priv->chip_type */
-
-	if (div_okay) {
-		dbg("%s - Baud rate set to %d (divisor 0x%lX) on chip %s",
-			__func__, baud, (unsigned long)div_value,
-			ftdi_chip_name[priv->chip_type]);
-	}
-
-	tty_encode_baud_rate(port->tty, baud, baud);
-	return(div_value);
-}
-
-
-static int get_serial_info(struct usb_serial_port * port, struct serial_struct __user * retinfo)
+static int get_serial_info(struct usb_serial_port *port,
+				struct serial_struct __user *retinfo)
 {
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	struct serial_struct tmp;
@@ -998,7 +1033,8 @@
 } /* get_serial_info */
 
 
-static int set_serial_info(struct usb_serial_port * port, struct serial_struct __user * newinfo)
+static int set_serial_info(struct tty_struct *tty,
+	struct usb_serial_port *port, struct serial_struct __user *newinfo)
 { /* set_serial_info */
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	struct serial_struct new_serial;
@@ -1006,7 +1042,7 @@
 
 	if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
 		return -EFAULT;
-	old_priv = * priv;
+	old_priv = *priv;
 
 	/* Do error checking and permission checking */
 
@@ -1027,33 +1063,32 @@
 	/* Make the changes - these are privileged changes! */
 
 	priv->flags = ((priv->flags & ~ASYNC_FLAGS) |
-	               (new_serial.flags & ASYNC_FLAGS));
+					(new_serial.flags & ASYNC_FLAGS));
 	priv->custom_divisor = new_serial.custom_divisor;
 
-	port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+	tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
 
 check_and_exit:
 	if ((old_priv.flags & ASYNC_SPD_MASK) !=
 	     (priv->flags & ASYNC_SPD_MASK)) {
 		if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			port->tty->alt_speed = 57600;
+			tty->alt_speed = 57600;
 		else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			port->tty->alt_speed = 115200;
+			tty->alt_speed = 115200;
 		else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-			port->tty->alt_speed = 230400;
+			tty->alt_speed = 230400;
 		else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-			port->tty->alt_speed = 460800;
+			tty->alt_speed = 460800;
 		else
-			port->tty->alt_speed = 0;
+			tty->alt_speed = 0;
 	}
 	if (((old_priv.flags & ASYNC_SPD_MASK) !=
 	     (priv->flags & ASYNC_SPD_MASK)) ||
 	    (((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
 	     (old_priv.custom_divisor != priv->custom_divisor))) {
-		change_speed(port);
+		change_speed(tty, port);
 	}
-
-	return (0);
+	return 0;
 
 } /* set_serial_info */
 
@@ -1082,11 +1117,10 @@
 		priv->chip_type = FT2232C;
 		/* Determine interface code. */
 		inter = serial->interface->altsetting->desc.bInterfaceNumber;
-		if (inter == 0) {
+		if (inter == 0)
 			priv->interface = PIT_SIOA;
-		} else {
+		else
 			priv->interface = PIT_SIOB;
-		}
 		/* BM-type devices have a bug where bcdDevice gets set
 		 * to 0x200 when iSerialNumber is 0.  */
 		if (version < 0x500) {
@@ -1120,7 +1154,8 @@
  * ***************************************************************************
  */
 
-static ssize_t show_latency_timer(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_latency_timer(struct device *dev,
+				struct device_attribute *attr, char *buf)
 {
 	struct usb_serial_port *port = to_usb_serial_port(dev);
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1129,14 +1164,14 @@
 	int rv = 0;
 
 
-	dbg("%s",__func__);
+	dbg("%s", __func__);
 
 	rv = usb_control_msg(udev,
 			     usb_rcvctrlpipe(udev, 0),
 			     FTDI_SIO_GET_LATENCY_TIMER_REQUEST,
 			     FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE,
 			     0, priv->interface,
-			     (char*) &latency, 1, WDR_TIMEOUT);
+			     (char *) &latency, 1, WDR_TIMEOUT);
 
 	if (rv < 0) {
 		dev_err(dev, "Unable to read latency timer: %i\n", rv);
@@ -1146,8 +1181,9 @@
 }
 
 /* Write a new value of the latency timer, in units of milliseconds. */
-static ssize_t store_latency_timer(struct device *dev, struct device_attribute *attr, const char *valbuf,
-				   size_t count)
+static ssize_t store_latency_timer(struct device *dev,
+			struct device_attribute *attr, const char *valbuf,
+			size_t count)
 {
 	struct usb_serial_port *port = to_usb_serial_port(dev);
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1175,8 +1211,8 @@
 
 /* Write an event character directly to the FTDI register.  The ASCII
    value is in the low 8 bits, with the enable bit in the 9th bit. */
-static ssize_t store_event_char(struct device *dev, struct device_attribute *attr, const char *valbuf,
-				size_t count)
+static ssize_t store_event_char(struct device *dev,
+	struct device_attribute *attr, const char *valbuf, size_t count)
 {
 	struct usb_serial_port *port = to_usb_serial_port(dev);
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1202,7 +1238,8 @@
 	return count;
 }
 
-static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer);
+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 int create_sysfs_attrs(struct usb_serial_port *port)
@@ -1210,7 +1247,7 @@
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	int retval = 0;
 
-	dbg("%s",__func__);
+	dbg("%s", __func__);
 
 	/* XXX I've no idea if the original SIO supports the event_char
 	 * sysfs parameter, so I'm playing it safe.  */
@@ -1232,7 +1269,7 @@
 {
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 
-	dbg("%s",__func__);
+	dbg("%s", __func__);
 
 	/* XXX see create_sysfs_attrs */
 	if (priv->chip_type != SIO) {
@@ -1253,9 +1290,11 @@
  */
 
 /* Probe function to check for special devices */
-static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id)
+static int ftdi_sio_probe(struct usb_serial *serial,
+					const struct usb_device_id *id)
 {
-	struct ftdi_sio_quirk *quirk = (struct ftdi_sio_quirk *)id->driver_info;
+	struct ftdi_sio_quirk *quirk =
+				(struct ftdi_sio_quirk *)id->driver_info;
 
 	if (quirk && quirk->probe) {
 		int ret = quirk->probe(serial);
@@ -1274,17 +1313,18 @@
 	struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial);
 
 
-	dbg("%s",__func__);
+	dbg("%s", __func__);
 
 	priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL);
-	if (!priv){
-		err("%s- kmalloc(%Zd) failed.", __func__, sizeof(struct ftdi_private));
+	if (!priv) {
+		err("%s- kmalloc(%Zd) failed.", __func__,
+					sizeof(struct ftdi_private));
 		return -ENOMEM;
 	}
 
 	spin_lock_init(&priv->rx_lock);
 	spin_lock_init(&priv->tx_lock);
-        init_waitqueue_head(&priv->delta_msr_wait);
+	init_waitqueue_head(&priv->delta_msr_wait);
 	/* This will push the characters through immediately rather
 	   than queue a task to deliver them */
 	priv->flags = ASYNC_LOW_LATENCY;
@@ -1294,9 +1334,9 @@
 
 	/* Increase the size of read buffers */
 	kfree(port->bulk_in_buffer);
-	port->bulk_in_buffer = kmalloc (BUFSZ, GFP_KERNEL);
+	port->bulk_in_buffer = kmalloc(BUFSZ, GFP_KERNEL);
 	if (!port->bulk_in_buffer) {
-		kfree (priv);
+		kfree(priv);
 		return -ENOMEM;
 	}
 	if (port->read_urb) {
@@ -1309,7 +1349,7 @@
 
 	/* Free port's existing write urb and transfer buffer. */
 	if (port->write_urb) {
-		usb_free_urb (port->write_urb);
+		usb_free_urb(port->write_urb);
 		port->write_urb = NULL;
 	}
 	kfree(port->bulk_out_buffer);
@@ -1317,7 +1357,7 @@
 
 	usb_set_serial_port_data(port, priv);
 
-	ftdi_determine_type (port);
+	ftdi_determine_type(port);
 	create_sysfs_attrs(port);
 	return 0;
 }
@@ -1325,9 +1365,9 @@
 /* Setup for the USB-UIRT device, which requires hardwired
  * baudrate (38400 gets mapped to 312500) */
 /* Called from usbserial:serial_probe */
-static void ftdi_USB_UIRT_setup (struct ftdi_private *priv)
+static void ftdi_USB_UIRT_setup(struct ftdi_private *priv)
 {
-	dbg("%s",__func__);
+	dbg("%s", __func__);
 
 	priv->flags |= ASYNC_SPD_CUST;
 	priv->custom_divisor = 77;
@@ -1336,9 +1376,10 @@
 
 /* Setup for the HE-TIRA1 device, which requires hardwired
  * baudrate (38400 gets mapped to 100000) and RTS-CTS enabled.  */
-static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv)
+
+static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv)
 {
-	dbg("%s",__func__);
+	dbg("%s", __func__);
 
 	priv->flags |= ASYNC_SPD_CUST;
 	priv->custom_divisor = 240;
@@ -1356,7 +1397,7 @@
 	struct usb_device *udev = serial->dev;
 	struct usb_interface *interface = serial->interface;
 
-	dbg("%s",__func__);
+	dbg("%s", __func__);
 
 	if (interface == udev->actconfig->interface[0]) {
 		info("Ignoring serial port reserved for JTAG");
@@ -1390,7 +1431,7 @@
  *      calls __serial_close for each open of the port
  *      shutdown is called then (ie ftdi_shutdown)
  */
-static void ftdi_shutdown (struct usb_serial *serial)
+static void ftdi_shutdown(struct usb_serial *serial)
 {
 	dbg("%s", __func__);
 }
@@ -1404,7 +1445,7 @@
 	remove_sysfs_attrs(port);
 
 	/* all open ports are closed at this point
-         *    (by usbserial.c:__serial_close, which calls ftdi_close)
+	 *    (by usbserial.c:__serial_close, which calls ftdi_close)
 	 */
 
 	if (priv) {
@@ -1415,7 +1456,8 @@
 	return 0;
 }
 
-static int  ftdi_open (struct usb_serial_port *port, struct file *filp)
+static int ftdi_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 { /* ftdi_open */
 	struct usb_device *dev = port->serial->dev;
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1433,8 +1475,8 @@
 	priv->rx_bytes = 0;
 	spin_unlock_irqrestore(&priv->rx_lock, flags);
 
-	if (port->tty)
-		port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+	if (tty)
+		tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
 
 	/* No error checking for this (will get errors later anyway) */
 	/* See ftdi_sio.h for description of what is reset */
@@ -1448,8 +1490,8 @@
 	   This is same behaviour as serial.c/rs_open() - Kuba */
 
 	/* ftdi_set_termios  will send usb control messages */
-	if (port->tty)
-		ftdi_set_termios(port, port->tty->termios);
+	if (tty)
+		ftdi_set_termios(tty, port, tty->termios);
 
 	/* FIXME: Flow control might be enabled, so it should be checked -
 	   we have no control of defaults! */
@@ -1464,12 +1506,14 @@
 	/* Start reading from the device */
 	priv->rx_processed = 0;
 	usb_fill_bulk_urb(port->read_urb, dev,
-		      usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress),
-		      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
-		      ftdi_read_bulk_callback, port);
+			usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress),
+			port->read_urb->transfer_buffer,
+				port->read_urb->transfer_buffer_length,
+			ftdi_read_bulk_callback, port);
 	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 	if (result)
-		err("%s - failed submitting read urb, error %d", __func__, result);
+		err("%s - failed submitting read urb, error %d",
+							__func__, result);
 
 
 	return result;
@@ -1485,16 +1529,17 @@
  *
  */
 
-static void ftdi_close (struct usb_serial_port *port, struct file *filp)
+static void ftdi_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 { /* ftdi_close */
-	unsigned int c_cflag = port->tty->termios->c_cflag;
+	unsigned int c_cflag = tty->termios->c_cflag;
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	char buf[1];
 
 	dbg("%s", __func__);
 
 	mutex_lock(&port->serial->disc_mutex);
-	if (c_cflag & HUPCL && !port->serial->disconnected){
+	if (c_cflag & HUPCL && !port->serial->disconnected) {
 		/* Disable flow control */
 		if (usb_control_msg(port->serial->dev,
 				    usb_sndctrlpipe(port->serial->dev, 0),
@@ -1527,7 +1572,7 @@
  *
  * The new devices do not require this byte
  */
-static int ftdi_write (struct usb_serial_port *port,
+static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port,
 			   const unsigned char *buf, int count)
 { /* ftdi_write */
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1554,7 +1599,7 @@
 	spin_unlock_irqrestore(&priv->tx_lock, flags);
 
 	data_offset = priv->write_offset;
-        dbg("data_offset set to %d",data_offset);
+	dbg("data_offset set to %d", data_offset);
 
 	/* Determine total transfer size */
 	transfer_size = count;
@@ -1565,7 +1610,7 @@
 				 (PKTSZ - data_offset)));
 	}
 
-	buffer = kmalloc (transfer_size, GFP_ATOMIC);
+	buffer = kmalloc(transfer_size, GFP_ATOMIC);
 	if (!buffer) {
 		err("%s ran out of kernel memory for urb ...", __func__);
 		count = -ENOMEM;
@@ -1581,20 +1626,20 @@
 
 	/* Copy data */
 	if (data_offset > 0) {
-		/* Original sio requires control byte at start of each packet. */
+		/* Original sio requires control byte at start of
+		   each packet. */
 		int user_pktsz = PKTSZ - data_offset;
 		int todo = count;
 		unsigned char *first_byte = buffer;
 		const unsigned char *current_position = buf;
 
 		while (todo > 0) {
-			if (user_pktsz > todo) {
+			if (user_pktsz > todo)
 				user_pktsz = todo;
-			}
 			/* Write the control byte at the front of the packet*/
 			*first_byte = 1 | ((user_pktsz) << 2);
 			/* Copy data for packet */
-			memcpy (first_byte + data_offset,
+			memcpy(first_byte + data_offset,
 				current_position, user_pktsz);
 			first_byte += user_pktsz + data_offset;
 			current_position += user_pktsz;
@@ -1603,20 +1648,23 @@
 	} else {
 		/* No control byte required. */
 		/* Copy in the data to send */
-		memcpy (buffer, buf, count);
+		memcpy(buffer, buf, count);
 	}
 
-	usb_serial_debug_data(debug, &port->dev, __func__, transfer_size, buffer);
+	usb_serial_debug_data(debug, &port->dev, __func__,
+						transfer_size, buffer);
 
 	/* fill the buffer and send it */
 	usb_fill_bulk_urb(urb, port->serial->dev,
-		      usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress),
-		      buffer, transfer_size,
-		      ftdi_write_bulk_callback, port);
+			usb_sndbulkpipe(port->serial->dev,
+					port->bulk_out_endpointAddress),
+			buffer, transfer_size,
+			ftdi_write_bulk_callback, port);
 
 	status = usb_submit_urb(urb, GFP_ATOMIC);
 	if (status) {
-		err("%s - failed submitting write urb, error %d", __func__, status);
+		err("%s - failed submitting write urb, error %d",
+							__func__, status);
 		count = status;
 		goto error;
 	} else {
@@ -1635,7 +1683,7 @@
 error:
 	usb_free_urb(urb);
 error_no_urb:
-	kfree (buffer);
+	kfree(buffer);
 error_no_buffer:
 	spin_lock_irqsave(&priv->tx_lock, flags);
 	priv->tx_outstanding_urbs--;
@@ -1646,7 +1694,7 @@
 
 /* This function may get called when the device is closed */
 
-static void ftdi_write_bulk_callback (struct urb *urb)
+static void ftdi_write_bulk_callback(struct urb *urb)
 {
 	unsigned long flags;
 	struct usb_serial_port *port = urb->context;
@@ -1656,7 +1704,7 @@
 	int status = urb->status;
 
 	/* free up the transfer buffer, as usb_free_urb() does not do this */
-	kfree (urb->transfer_buffer);
+	kfree(urb->transfer_buffer);
 
 	dbg("%s - port %d", __func__, port->number);
 
@@ -1686,8 +1734,9 @@
 } /* ftdi_write_bulk_callback */
 
 
-static int ftdi_write_room( struct usb_serial_port *port )
+static int ftdi_write_room(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	int room;
 	unsigned long flags;
@@ -1707,11 +1756,11 @@
 	}
 	spin_unlock_irqrestore(&priv->tx_lock, flags);
 	return room;
-} /* ftdi_write_room */
+}
 
-
-static int ftdi_chars_in_buffer (struct usb_serial_port *port)
-{ /* ftdi_chars_in_buffer */
+static int ftdi_chars_in_buffer(struct tty_struct *tty)
+{
+	struct usb_serial_port *port = tty->driver_data;
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	int buffered;
 	unsigned long flags;
@@ -1726,12 +1775,10 @@
 		buffered = 0;
 	}
 	return buffered;
-} /* ftdi_chars_in_buffer */
+}
 
-
-
-static void ftdi_read_bulk_callback (struct urb *urb)
-{ /* ftdi_read_bulk_callback */
+static void ftdi_read_bulk_callback(struct urb *urb)
+{
 	struct usb_serial_port *port = urb->context;
 	struct tty_struct *tty;
 	struct ftdi_private *priv;
@@ -1740,19 +1787,21 @@
 	int status = urb->status;
 
 	if (urb->number_of_packets > 0) {
-		err("%s transfer_buffer_length %d actual_length %d number of packets %d",__func__,
-		    urb->transfer_buffer_length, urb->actual_length, urb->number_of_packets );
-		err("%s transfer_flags %x ", __func__,urb->transfer_flags );
+		err("%s transfer_buffer_length %d actual_length %d number of packets %d",
+				__func__,
+				urb->transfer_buffer_length,
+				urb->actual_length, urb->number_of_packets);
+		err("%s transfer_flags %x ", __func__, urb->transfer_flags);
 	}
 
 	dbg("%s - port %d", __func__, port->number);
 
-	if (port->open_count <= 0)
+	if (port->port.count <= 0)
 		return;
 
-	tty = port->tty;
+	tty = port->port.tty;
 	if (!tty) {
-		dbg("%s - bad tty pointer - exiting",__func__);
+		dbg("%s - bad tty pointer - exiting", __func__);
 		return;
 	}
 
@@ -1762,14 +1811,13 @@
 		return;
 	}
 
-	if (urb != port->read_urb) {
+	if (urb != port->read_urb)
 		err("%s - Not my urb!", __func__);
-	}
 
 	if (status) {
-		/* This will happen at close every time so it is a dbg not an err */
-		dbg("(this is ok on close) nonzero read bulk status received: "
-		    "%d", status);
+		/* This will happen at close every time so it is a dbg not an
+		   err */
+		dbg("(this is ok on close) nonzero read bulk status received: %d", status);
 		return;
 	}
 
@@ -1785,7 +1833,7 @@
 } /* ftdi_read_bulk_callback */
 
 
-static void ftdi_process_read (struct work_struct *work)
+static void ftdi_process_read(struct work_struct *work)
 { /* ftdi_process_read */
 	struct ftdi_private *priv =
 		container_of(work, struct ftdi_private, rx_work.work);
@@ -1803,12 +1851,12 @@
 
 	dbg("%s - port %d", __func__, port->number);
 
-	if (port->open_count <= 0)
+	if (port->port.count <= 0)
 		return;
 
-	tty = port->tty;
+	tty = port->port.tty;
 	if (!tty) {
-		dbg("%s - bad tty pointer - exiting",__func__);
+		dbg("%s - bad tty pointer - exiting", __func__);
 		return;
 	}
 
@@ -1832,11 +1880,11 @@
 				urb->actual_length - priv->rx_processed);
 	} else {
 		/* The first two bytes of every read packet are status */
-		if (urb->actual_length > 2) {
-			usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
-		} else {
-			dbg("Status only: %03oo %03oo",data[0],data[1]);
-		}
+		if (urb->actual_length > 2)
+			usb_serial_debug_data(debug, &port->dev, __func__,
+						urb->actual_length, data);
+		else
+			dbg("Status only: %03oo %03oo", data[0], data[1]);
 	}
 
 
@@ -1846,16 +1894,19 @@
 	/* if CD is dropped and the line is not CLOCAL then we should hangup */
 
 	need_flip = 0;
-	for (packet_offset = priv->rx_processed; packet_offset < urb->actual_length; packet_offset += PKTSZ) {
+	for (packet_offset = priv->rx_processed;
+		packet_offset < urb->actual_length; packet_offset += PKTSZ) {
 		int length;
 
-		/* Compare new line status to the old one, signal if different */
-		/* N.B. packet may be processed more than once, but differences
-		 * are only processed once.  */
+		/* Compare new line status to the old one, signal if different/
+		   N.B. packet may be processed more than once, but differences
+		   are only processed once.  */
 		if (priv != NULL) {
-			char new_status = data[packet_offset+0] & FTDI_STATUS_B0_MASK;
+			char new_status = data[packet_offset + 0] &
+							FTDI_STATUS_B0_MASK;
 			if (new_status != priv->prev_status) {
-				priv->diff_status |= new_status ^ priv->prev_status;
+				priv->diff_status |=
+					new_status ^ priv->prev_status;
 				wake_up_interruptible(&priv->delta_msr_wait);
 				priv->prev_status = new_status;
 			}
@@ -1872,30 +1923,31 @@
 			break;
 		}
 		if (tty_buffer_request_room(tty, length) < length) {
-			/* break out & wait for throttling/unthrottling to happen */
+			/* break out & wait for throttling/unthrottling to
+			   happen */
 			dbg("%s - receive room low", __func__);
 			break;
 		}
 
 		/* Handle errors and break */
 		error_flag = TTY_NORMAL;
-		/* Although the device uses a bitmask and hence can have multiple */
-		/* errors on a packet - the order here sets the priority the */
-		/* error is returned to the tty layer  */
+		/* Although the device uses a bitmask and hence can have
+		   multiple errors on a packet - the order here sets the
+		   priority the error is returned to the tty layer  */
 
-		if ( data[packet_offset+1] & FTDI_RS_OE ) {
+		if (data[packet_offset+1] & FTDI_RS_OE) {
 			error_flag = TTY_OVERRUN;
 			dbg("OVERRRUN error");
 		}
-		if ( data[packet_offset+1] & FTDI_RS_BI ) {
+		if (data[packet_offset+1] & FTDI_RS_BI) {
 			error_flag = TTY_BREAK;
 			dbg("BREAK received");
 		}
-		if ( data[packet_offset+1] & FTDI_RS_PE ) {
+		if (data[packet_offset+1] & FTDI_RS_PE) {
 			error_flag = TTY_PARITY;
 			dbg("PARITY error");
 		}
-		if ( data[packet_offset+1] & FTDI_RS_FE ) {
+		if (data[packet_offset+1] & FTDI_RS_FE) {
 			error_flag = TTY_FRAME;
 			dbg("FRAMING error");
 		}
@@ -1904,7 +1956,8 @@
 				/* Note that the error flag is duplicated for
 				   every character received since we don't know
 				   which character it applied to */
-				tty_insert_flip_char(tty, data[packet_offset+i], error_flag);
+				tty_insert_flip_char(tty,
+					data[packet_offset + i], error_flag);
 			}
 			need_flip = 1;
 		}
@@ -1912,19 +1965,19 @@
 #ifdef NOT_CORRECT_BUT_KEEPING_IT_FOR_NOW
 		/* if a parity error is detected you get status packets forever
 		   until a character is sent without a parity error.
-		   This doesn't work well since the application receives a never
-		   ending stream of bad data - even though new data hasn't been sent.
-		   Therefore I (bill) have taken this out.
+		   This doesn't work well since the application receives a
+		   never ending stream of bad data - even though new data
+		   hasn't been sent. Therefore I (bill) have taken this out.
 		   However - this might make sense for framing errors and so on
 		   so I am leaving the code in for now.
 		*/
 		else {
-			if (error_flag != TTY_NORMAL){
+			if (error_flag != TTY_NORMAL) {
 				dbg("error_flag is not normal");
-				/* In this case it is just status - if that is an error send a bad character */
-				if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
+				/* In this case it is just status - if that is
+				   an error send a bad character */
+				if (tty->flip.count >= TTY_FLIPBUF_SIZE)
 					tty_flip_buffer_push(tty);
-				}
 				tty_insert_flip_char(tty, 0xff, error_flag);
 				need_flip = 1;
 			}
@@ -1933,9 +1986,8 @@
 	} /* "for(packet_offset=0..." */
 
 	/* Low latency */
-	if (need_flip) {
+	if (need_flip)
 		tty_flip_buffer_push(tty);
-	}
 
 	if (packet_offset < urb->actual_length) {
 		/* not completely processed - record progress */
@@ -1954,12 +2006,11 @@
 		}
 		spin_unlock_irqrestore(&priv->rx_lock, flags);
 		/* if the port is closed stop trying to read */
-		if (port->open_count > 0){
+		if (port->port.count > 0)
 			/* delay processing of remainder */
 			schedule_delayed_work(&priv->rx_work, 1);
-		} else {
+		else
 			dbg("%s - port is closed", __func__);
-		}
 		return;
 	}
 
@@ -1967,24 +2018,26 @@
 	priv->rx_processed = 0;
 
 	/* if the port is closed stop trying to read */
-	if (port->open_count > 0){
+	if (port->port.count > 0) {
 		/* Continue trying to always read  */
 		usb_fill_bulk_urb(port->read_urb, port->serial->dev,
-			      usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress),
-			      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
-			      ftdi_read_bulk_callback, port);
+			usb_rcvbulkpipe(port->serial->dev,
+					port->bulk_in_endpointAddress),
+			port->read_urb->transfer_buffer,
+			port->read_urb->transfer_buffer_length,
+			ftdi_read_bulk_callback, port);
 
 		result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 		if (result)
-			err("%s - failed resubmitting read urb, error %d", __func__, result);
+			err("%s - failed resubmitting read urb, error %d",
+							__func__, result);
 	}
-
-	return;
 } /* ftdi_process_read */
 
 
-static void ftdi_break_ctl( struct usb_serial_port *port, int break_state )
+static void ftdi_break_ctl(struct tty_struct *tty, int break_state)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	__u16 urb_value = 0;
 	char buf[1];
@@ -1993,22 +2046,23 @@
 	/* see drivers/char/tty_io.c to see it used */
 	/* last_set_data_urb_value NEVER has the break bit set in it */
 
-	if (break_state) {
+	if (break_state)
 		urb_value = priv->last_set_data_urb_value | FTDI_SIO_SET_BREAK;
-	} else {
+	else
 		urb_value = priv->last_set_data_urb_value;
+
+	if (usb_control_msg(port->serial->dev,
+			usb_sndctrlpipe(port->serial->dev, 0),
+			FTDI_SIO_SET_DATA_REQUEST,
+			FTDI_SIO_SET_DATA_REQUEST_TYPE,
+			urb_value , priv->interface,
+			buf, 0, WDR_TIMEOUT) < 0) {
+		err("%s FAILED to enable/disable break state (state was %d)",
+							__func__, break_state);
 	}
 
-
-	if (usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0),
-			    FTDI_SIO_SET_DATA_REQUEST,
-			    FTDI_SIO_SET_DATA_REQUEST_TYPE,
-			    urb_value , priv->interface,
-			    buf, 0, WDR_TIMEOUT) < 0) {
-		err("%s FAILED to enable/disable break state (state was %d)", __func__,break_state);
-	}
-
-	dbg("%s break state is %d - urb is %d", __func__,break_state, urb_value);
+	dbg("%s break state is %d - urb is %d", __func__,
+						break_state, urb_value);
 
 }
 
@@ -2018,26 +2072,28 @@
  * WARNING: set_termios calls this with old_termios in kernel space
  */
 
-static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
+static void ftdi_set_termios(struct tty_struct *tty,
+		struct usb_serial_port *port, struct ktermios *old_termios)
 { /* ftdi_termios */
 	struct usb_device *dev = port->serial->dev;
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
-	struct ktermios *termios = port->tty->termios;
+	struct ktermios *termios = tty->termios;
 	unsigned int cflag = termios->c_cflag;
 	__u16 urb_value; /* will hold the new flags */
 	char buf[1]; /* Perhaps I should dynamically alloc this? */
 
-	// Added for xon/xoff support
+	/* Added for xon/xoff support */
 	unsigned int iflag = termios->c_iflag;
 	unsigned char vstop;
 	unsigned char vstart;
 
 	dbg("%s", __func__);
 
-	/* Force baud rate if this device requires it, unless it is set to B0. */
+	/* Force baud rate if this device requires it, unless it is set to
+	   B0. */
 	if (priv->force_baud && ((termios->c_cflag & CBAUD) != B0)) {
 		dbg("%s: forcing baud rate for this device", __func__);
-		tty_encode_baud_rate(port->tty, priv->force_baud,
+		tty_encode_baud_rate(tty, priv->force_baud,
 					priv->force_baud);
 	}
 
@@ -2053,8 +2109,8 @@
 	   not  - so just do the change regardless  - should be able to
 	   compare old_termios and tty->termios */
 	/* NOTE These routines can get interrupted by
-	   ftdi_sio_read_bulk_callback  - need to examine what this
-           means - don't see any problems yet */
+	   ftdi_sio_read_bulk_callback  - need to examine what this means -
+	   don't see any problems yet */
 
 	/* Set number of data bits, parity, stop bits */
 
@@ -2078,8 +2134,8 @@
 		}
 	}
 
-	/* This is needed by the break command since it uses the same command - but is
-	 *  or'ed with this value  */
+	/* This is needed by the break command since it uses the same command
+	   - but is or'ed with this value  */
 	priv->last_set_data_urb_value = urb_value;
 
 	if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
@@ -2091,7 +2147,7 @@
 	}
 
 	/* Now do the baudrate */
-	if ((cflag & CBAUD) == B0 ) {
+	if ((cflag & CBAUD) == B0) {
 		/* Disable flow control */
 		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST,
@@ -2104,13 +2160,11 @@
 		clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
 	} else {
 		/* set the baudrate determined before */
-		if (change_speed(port)) {
+		if (change_speed(tty, port))
 			err("%s urb failed to set baudrate", __func__);
-		}
 		/* Ensure RTS and DTR are raised when baudrate changed from 0 */
-		if (!old_termios || (old_termios->c_cflag & CBAUD) == B0) {
+		if (!old_termios || (old_termios->c_cflag & CBAUD) == B0)
 			set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
-		}
 	}
 
 	/* Set flow control */
@@ -2130,18 +2184,22 @@
 		/*
 		 * Xon/Xoff code
 		 *
-		 * Check the IXOFF status in the iflag component of the termios structure
-		 * if IXOFF is not set, the pre-xon/xoff code is executed.
-		*/
+		 * Check the IXOFF status in the iflag component of the
+		 * termios structure. If IXOFF is not set, the pre-xon/xoff
+		 * code is executed.
+		 */
 		if (iflag & IXOFF) {
-			dbg("%s  request to enable xonxoff iflag=%04x",__func__,iflag);
-			// Try to enable the XON/XOFF on the ftdi_sio
-			// Set the vstart and vstop -- could have been done up above where
-			// a lot of other dereferencing is done but that would be very
-			// inefficient as vstart and vstop are not always needed
+			dbg("%s  request to enable xonxoff iflag=%04x",
+							__func__, iflag);
+			/* Try to enable the XON/XOFF on the ftdi_sio
+			 * Set the vstart and vstop -- could have been done up
+			 * above where a lot of other dereferencing is done but
+			 * that would be very inefficient as vstart and vstop
+			 * are not always needed.
+			 */
 			vstart = termios->c_cc[VSTART];
 			vstop = termios->c_cc[VSTOP];
-			urb_value=(vstop << 8) | (vstart);
+			urb_value = (vstop << 8) | (vstart);
 
 			if (usb_control_msg(dev,
 					    usb_sndctrlpipe(dev, 0),
@@ -2153,8 +2211,9 @@
 				err("urb failed to set to xon/xoff flow control");
 			}
 		} else {
-			/* else clause to only run if cfag ! CRTSCTS and iflag ! XOFF */
-			/* CHECKME Assuming XON/XOFF handled by tty stack - not by device */
+			/* else clause to only run if cflag ! CRTSCTS and iflag
+			 * ! XOFF. CHECKME Assuming XON/XOFF handled by tty
+			 * stack - not by device */
 			dbg("%s Turning off hardware flow control", __func__);
 			if (usb_control_msg(dev,
 					    usb_sndctrlpipe(dev, 0),
@@ -2168,11 +2227,11 @@
 
 	}
 	return;
-} /* ftdi_termios */
+}
 
-
-static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file)
+static int ftdi_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	unsigned char buf[2];
 	int ret;
@@ -2181,32 +2240,35 @@
 	switch (priv->chip_type) {
 	case SIO:
 		/* Request the status from the device */
-		if ((ret = usb_control_msg(port->serial->dev,
-					   usb_rcvctrlpipe(port->serial->dev, 0),
-					   FTDI_SIO_GET_MODEM_STATUS_REQUEST,
-					   FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
-					   0, 0,
-					   buf, 1, WDR_TIMEOUT)) < 0 ) {
+		ret = usb_control_msg(port->serial->dev,
+			   usb_rcvctrlpipe(port->serial->dev, 0),
+			   FTDI_SIO_GET_MODEM_STATUS_REQUEST,
+			   FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+			   0, 0,
+			   buf, 1, WDR_TIMEOUT);
+		if (ret < 0) {
 			err("%s Could not get modem status of device - err: %d", __func__,
 			    ret);
-			return(ret);
+			return ret;
 		}
 		break;
 	case FT8U232AM:
 	case FT232BM:
 	case FT2232C:
 	case FT232RL:
-		/* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same
-		   format as the data returned from the in point */
-		if ((ret = usb_control_msg(port->serial->dev,
-					   usb_rcvctrlpipe(port->serial->dev, 0),
-					   FTDI_SIO_GET_MODEM_STATUS_REQUEST,
-					   FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
-					   0, priv->interface,
-					   buf, 2, WDR_TIMEOUT)) < 0 ) {
+		/* the 8U232AM returns a two byte value (the sio is a 1 byte
+		   value) - in the same format as the data returned from the in
+		   point */
+		ret = usb_control_msg(port->serial->dev,
+				   usb_rcvctrlpipe(port->serial->dev, 0),
+				   FTDI_SIO_GET_MODEM_STATUS_REQUEST,
+				   FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+				   0, priv->interface,
+				   buf, 2, WDR_TIMEOUT);
+		if (ret < 0) {
 			err("%s Could not get modem status of device - err: %d", __func__,
 			    ret);
-			return(ret);
+			return ret;
 		}
 		break;
 	default:
@@ -2221,15 +2283,19 @@
 		priv->last_dtr_rts;
 }
 
-static int ftdi_tiocmset(struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear)
+static int ftdi_tiocmset(struct tty_struct *tty, struct file *file,
+			unsigned int set, unsigned int clear)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	dbg("%s TIOCMSET", __func__);
 	return update_mctrl(port, set, clear);
 }
 
 
-static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+static int ftdi_ioctl(struct tty_struct *tty, struct file *file,
+					unsigned int cmd, unsigned long arg)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 
 	dbg("%s cmd 0x%04x", __func__, cmd);
@@ -2238,10 +2304,12 @@
 	switch (cmd) {
 
 	case TIOCGSERIAL: /* gets serial port data */
-		return get_serial_info(port, (struct serial_struct __user *) arg);
+		return get_serial_info(port,
+					(struct serial_struct __user *) arg);
 
 	case TIOCSSERIAL: /* sets serial port data */
-		return set_serial_info(port, (struct serial_struct __user *) arg);
+		return set_serial_info(tty, port,
+					(struct serial_struct __user *) arg);
 
 	/*
 	 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
@@ -2260,45 +2328,41 @@
 			else {
 				char diff = priv->diff_status;
 
-				if (diff == 0) {
+				if (diff == 0)
 					return -EIO; /* no change => error */
-				}
 
 				/* Consume all events */
 				priv->diff_status = 0;
 
-				/* Return 0 if caller wanted to know about these bits */
-				if ( ((arg & TIOCM_RNG) && (diff & FTDI_RS0_RI)) ||
-				     ((arg & TIOCM_DSR) && (diff & FTDI_RS0_DSR)) ||
-				     ((arg & TIOCM_CD)  && (diff & FTDI_RS0_RLSD)) ||
-				     ((arg & TIOCM_CTS) && (diff & FTDI_RS0_CTS)) ) {
+				/* Return 0 if caller wanted to know about
+				   these bits */
+				if (((arg & TIOCM_RNG) && (diff & FTDI_RS0_RI)) ||
+				    ((arg & TIOCM_DSR) && (diff & FTDI_RS0_DSR)) ||
+				    ((arg & TIOCM_CD)  && (diff & FTDI_RS0_RLSD)) ||
+				    ((arg & TIOCM_CTS) && (diff & FTDI_RS0_CTS))) {
 					return 0;
 				}
 				/*
-				 * Otherwise caller can't care less about what happened,
-				 * and so we continue to wait for more events.
+				 * Otherwise caller can't care less about what
+				 * happened,and so we continue to wait for more
+				 * events.
 				 */
 			}
 		}
-		return(0);
-		break;
+		return 0;
 	default:
 		break;
-
 	}
-
-
-	/* This is not necessarily an error - turns out the higher layers will do
-	 *  some ioctls itself (see comment above)
+	/* This is not necessarily an error - turns out the higher layers
+	 * will do some ioctls themselves (see comment above)
 	 */
 	dbg("%s arg not supported - it was 0x%04x - check /usr/include/asm/ioctls.h", __func__, cmd);
+	return -ENOIOCTLCMD;
+}
 
-	return(-ENOIOCTLCMD);
-} /* ftdi_ioctl */
-
-
-static void ftdi_throttle (struct usb_serial_port *port)
+static void ftdi_throttle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 
@@ -2310,8 +2374,9 @@
 }
 
 
-static void ftdi_unthrottle (struct usb_serial_port *port)
+static void ftdi_unthrottle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	int actually_throttled;
 	unsigned long flags;
@@ -2327,7 +2392,7 @@
 		schedule_delayed_work(&priv->rx_work, 0);
 }
 
-static int __init ftdi_init (void)
+static int __init ftdi_init(void)
 {
 	int retval;
 
@@ -2357,13 +2422,13 @@
 }
 
 
-static void __exit ftdi_exit (void)
+static void __exit ftdi_exit(void)
 {
 
 	dbg("%s", __func__);
 
-	usb_deregister (&ftdi_driver);
-	usb_serial_deregister (&ftdi_sio_device);
+	usb_deregister(&ftdi_driver);
+	usb_serial_deregister(&ftdi_sio_device);
 
 }
 
@@ -2371,8 +2436,8 @@
 module_init(ftdi_init);
 module_exit(ftdi_exit);
 
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 8302eca..a577ea4 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -1,20 +1,20 @@
 /*
- * Definitions for the FTDI USB Single Port Serial Converter - 
- * known as FTDI_SIO (Serial Input/Output application of the chipset) 
+ * Definitions for the FTDI USB Single Port Serial Converter -
+ * known as FTDI_SIO (Serial Input/Output application of the chipset)
  *
  * The example I have is known as the USC-1000 which is available from
  * http://www.dse.co.nz - cat no XH4214 It looks similar to this:
  * http://www.dansdata.com/usbser.htm but I can't be sure There are other
  * USC-1000s which don't look like my device though so beware!
  *
- * The device is based on the FTDI FT8U100AX chip. It has a DB25 on one side, 
+ * The device is based on the FTDI FT8U100AX chip. It has a DB25 on one side,
  * USB on the other.
  *
  * Thanx to FTDI (http://www.ftdi.co.uk) for so kindly providing details
  * of the protocol required to talk to the device and ongoing assistence
  * during development.
  *
- * Bill Ryder - bryder@sgi.com formerly of Silicon Graphics, Inc.- wrote the 
+ * Bill Ryder - bryder@sgi.com formerly of Silicon Graphics, Inc.- wrote the
  * FTDI_SIO implementation.
  *
  * Philipp Gühring - pg@futureware.at - added the Device ID of the USB relais
@@ -472,7 +472,7 @@
 /*
  * DSS-20 Sync Station for Sony Ericsson P800
  */
-#define FTDI_DSS20_PID          0xFC82  
+#define FTDI_DSS20_PID          0xFC82
 
 /*
  * Home Electronics (www.home-electro.com) USB gadgets
@@ -884,7 +884,7 @@
 /*
  * BmRequestType:  0100 0000B
  * bRequest:       FTDI_SIO_RESET
- * wValue:         Control Value 
+ * wValue:         Control Value
  *                   0 = Reset SIO
  *                   1 = Purge RX buffer
  *                   2 = Purge TX buffer
@@ -952,7 +952,7 @@
  *   101 - add .625 to divisor
  *   110 - add .750 to divisor
  *   111 - add .875 to divisor
- * Bits 15 to 0 of the 17-bit divisor are placed in the urb value.  Bit 16 is 
+ * Bits 15 to 0 of the 17-bit divisor are placed in the urb value.  Bit 16 is
  * placed in bit 0 of the urb index.
  *
  * Note that there are a couple of special cases to support the highest baud
@@ -971,8 +971,8 @@
 } ftdi_chip_type_t;
 
 typedef enum {
- ftdi_sio_b300 = 0, 
- ftdi_sio_b600 = 1, 
+ ftdi_sio_b300 = 0,
+ ftdi_sio_b600 = 1,
  ftdi_sio_b1200 = 2,
  ftdi_sio_b2400 = 3,
  ftdi_sio_b4800 = 4,
@@ -981,7 +981,7 @@
  ftdi_sio_b38400 = 7,
  ftdi_sio_b57600 = 8,
  ftdi_sio_b115200 = 9
-} FTDI_SIO_baudrate_t ;
+} FTDI_SIO_baudrate_t;
 
 /*
  * The ftdi_8U232AM_xxMHz_byyy constants have been removed. The encoded divisor values
@@ -990,19 +990,19 @@
 
 #define FTDI_SIO_SET_DATA_REQUEST FTDI_SIO_SET_DATA
 #define FTDI_SIO_SET_DATA_REQUEST_TYPE 0x40
-#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8 )
-#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8 )
-#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8 )
-#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8 )
-#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8 )
-#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11 )
-#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11 )
-#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11 )
+#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8)
+#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8)
+#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8)
+#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8)
+#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8)
+#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11)
+#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11)
+#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11)
 #define FTDI_SIO_SET_BREAK (0x1 << 14)
 /* FTDI_SIO_SET_DATA */
 
 /*
- * BmRequestType:  0100 0000B 
+ * BmRequestType:  0100 0000B
  * bRequest:       FTDI_SIO_SET_DATA
  * wValue:         Data characteristics (see below)
  * wIndex:         Port
@@ -1035,7 +1035,7 @@
 #define FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE 0x40
 #define FTDI_SIO_SET_MODEM_CTRL_REQUEST FTDI_SIO_MODEM_CTRL
 
-/* 
+/*
  * BmRequestType:   0100 0000B
  * bRequest:        FTDI_SIO_MODEM_CTRL
  * wValue:          ControlValue (see below)
@@ -1049,11 +1049,11 @@
  */
 
 #define FTDI_SIO_SET_DTR_MASK 0x1
-#define FTDI_SIO_SET_DTR_HIGH ( 1 | ( FTDI_SIO_SET_DTR_MASK  << 8))
-#define FTDI_SIO_SET_DTR_LOW  ( 0 | ( FTDI_SIO_SET_DTR_MASK  << 8))
+#define FTDI_SIO_SET_DTR_HIGH (1 | (FTDI_SIO_SET_DTR_MASK  << 8))
+#define FTDI_SIO_SET_DTR_LOW  (0 | (FTDI_SIO_SET_DTR_MASK  << 8))
 #define FTDI_SIO_SET_RTS_MASK 0x2
-#define FTDI_SIO_SET_RTS_HIGH ( 2 | ( FTDI_SIO_SET_RTS_MASK << 8 ))
-#define FTDI_SIO_SET_RTS_LOW ( 0 | ( FTDI_SIO_SET_RTS_MASK << 8 ))
+#define FTDI_SIO_SET_RTS_HIGH (2 | (FTDI_SIO_SET_RTS_MASK << 8))
+#define FTDI_SIO_SET_RTS_LOW (0 | (FTDI_SIO_SET_RTS_MASK << 8))
 
 /*
  * ControlValue
@@ -1076,7 +1076,7 @@
 /* FTDI_SIO_SET_FLOW_CTRL */
 #define FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE 0x40
 #define FTDI_SIO_SET_FLOW_CTRL_REQUEST FTDI_SIO_SET_FLOW_CTRL
-#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0 
+#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0
 #define FTDI_SIO_RTS_CTS_HS (0x1 << 8)
 #define FTDI_SIO_DTR_DSR_HS (0x2 << 8)
 #define FTDI_SIO_XON_XOFF_HS (0x4 << 8)
@@ -1085,7 +1085,7 @@
  *   bRequest:       FTDI_SIO_SET_FLOW_CTRL
  *   wValue:         Xoff/Xon
  *   wIndex:         Protocol/Port - hIndex is protocl / lIndex is port
- *   wLength:        0 
+ *   wLength:        0
  *   Data:           None
  *
  * hIndex protocol is:
@@ -1101,10 +1101,10 @@
  *
  * A value of zero in the hIndex field disables handshaking
  *
- * If Xon/Xoff handshaking is specified, the hValue field should contain the XOFF character 
+ * If Xon/Xoff handshaking is specified, the hValue field should contain the XOFF character
  * and the lValue field contains the XON character.
- */  
- 
+ */
+
 /*
  * FTDI_SIO_GET_LATENCY_TIMER
  *
@@ -1118,7 +1118,7 @@
 #define  FTDI_SIO_GET_LATENCY_TIMER_REQUEST FTDI_SIO_GET_LATENCY_TIMER
 #define  FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE 0xC0
 
-/* 
+/*
  *  BmRequestType:   1100 0000b
  *  bRequest:        FTDI_SIO_GET_LATENCY_TIMER
  *  wValue:          0
@@ -1127,7 +1127,7 @@
  *  Data:            latency (on return)
  */
 
-/* 
+/*
  * FTDI_SIO_SET_LATENCY_TIMER
  *
  * Set the timeout interval. The FTDI collects data from the slave
@@ -1140,7 +1140,7 @@
 #define  FTDI_SIO_SET_LATENCY_TIMER_REQUEST FTDI_SIO_SET_LATENCY_TIMER
 #define  FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE 0x40
 
-/* 
+/*
  *  BmRequestType:   0100 0000b
  *  bRequest:        FTDI_SIO_SET_LATENCY_TIMER
  *  wValue:          Latency (milliseconds)
@@ -1155,7 +1155,7 @@
  */
 
 /*
- * FTDI_SIO_SET_EVENT_CHAR 
+ * FTDI_SIO_SET_EVENT_CHAR
  *
  * Set the special event character for the specified communications port.
  * If the device sees this character it will immediately return the
@@ -1168,7 +1168,7 @@
 #define  FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE 0x40
 
 
-/* 
+/*
  *  BmRequestType:   0100 0000b
  *  bRequest:        FTDI_SIO_SET_EVENT_CHAR
  *  wValue:          EventChar
@@ -1184,12 +1184,12 @@
  *   B9..15  Reserved
  *
  */
-          
+
 /* FTDI_SIO_SET_ERROR_CHAR */
 
 /* Set the parity error replacement character for the specified communications port */
 
-/* 
+/*
  *  BmRequestType:  0100 0000b
  *  bRequest:       FTDI_SIO_SET_EVENT_CHAR
  *  wValue:         Error Char
@@ -1215,15 +1215,15 @@
 #define FTDI_SIO_DSR_MASK 0x20
 #define FTDI_SIO_RI_MASK  0x40
 #define FTDI_SIO_RLSD_MASK 0x80
-/* 
+/*
  *   BmRequestType:   1100 0000b
  *   bRequest:        FTDI_SIO_GET_MODEM_STATUS
  *   wValue:          zero
  *   wIndex:          Port
  *   wLength:         1
  *   Data:            Status
- * 
- * One byte of data is returned 
+ *
+ * One byte of data is returned
  * B0..3 0
  * B4    CTS
  *         0 = inactive
@@ -1236,15 +1236,15 @@
  *         1 = active
  * B7    Receive Line Signal Detect (RLSD)
  *         0 = inactive
- *         1 = active 
+ *         1 = active
  */
 
 
 
-/* Descriptors returned by the device 
- * 
+/* Descriptors returned by the device
+ *
  *  Device Descriptor
- * 
+ *
  * Offset	Field		Size	Value	Description
  * 0	bLength		1	0x12	Size of descriptor in bytes
  * 1	bDescriptorType	1	0x01	DEVICE Descriptor Type
@@ -1260,9 +1260,9 @@
  * 15	iProduct	1	0x02	Index of prod string desc
  * 16	iSerialNumber	1	0x02	Index of serial nmr string desc
  * 17	bNumConfigurations 1    0x01	Number of possible configurations
- * 
+ *
  * Configuration Descriptor
- * 
+ *
  * Offset	Field			Size	Value
  * 0	bLength			1	0x09	Size of descriptor in bytes
  * 1	bDescriptorType		1	0x02	CONFIGURATION Descriptor Type
@@ -1272,9 +1272,9 @@
  * 6	iConfiguration		1	0x02	Index of config string descriptor
  * 7	bmAttributes		1	0x20	Config characteristics Remote Wakeup
  * 8	MaxPower		1	0x1E	Max power consumption
- * 
+ *
  * Interface Descriptor
- * 
+ *
  * Offset	Field			Size	Value
  * 0	bLength			1	0x09	Size of descriptor in bytes
  * 1	bDescriptorType		1	0x04	INTERFACE Descriptor Type
@@ -1285,9 +1285,9 @@
  * 6	bInterfaceSubClass	1	0xFF	Subclass Code
  * 7	bInterfaceProtocol	1	0xFF	Protocol Code
  * 8	iInterface		1	0x02	Index of interface string description
- * 
+ *
  * IN Endpoint Descriptor
- * 
+ *
  * Offset	Field			Size	Value
  * 0	bLength			1	0x07	Size of descriptor in bytes
  * 1	bDescriptorType		1	0x05	ENDPOINT descriptor type
@@ -1295,9 +1295,9 @@
  * 3	bmAttributes		1	0x02	Endpoint attributes - Bulk
  * 4	bNumEndpoints		2	0x0040	maximum packet size
  * 5	bInterval		1	0x00	Interval for polling endpoint
- * 
+ *
  * OUT Endpoint Descriptor
- * 
+ *
  * Offset	Field			Size	Value
  * 0	bLength			1	0x07	Size of descriptor in bytes
  * 1	bDescriptorType		1	0x05	ENDPOINT descriptor type
@@ -1305,17 +1305,17 @@
  * 3	bmAttributes		1	0x02	Endpoint attributes - Bulk
  * 4	bNumEndpoints		2	0x0040	maximum packet size
  * 5	bInterval		1	0x00	Interval for polling endpoint
- *     
+ *
  * DATA FORMAT
- * 
+ *
  * IN Endpoint
- * 
+ *
  * The device reserves the first two bytes of data on this endpoint to contain the current
  * values of the modem and line status registers. In the absence of data, the device 
  * generates a message consisting of these two status bytes every 40 ms
- * 
+ *
  * Byte 0: Modem Status
- * 
+ *
  * Offset	Description
  * B0	Reserved - must be 1
  * B1	Reserved - must be 0
@@ -1325,9 +1325,9 @@
  * B5	Data Set Ready (DSR)
  * B6	Ring Indicator (RI)
  * B7	Receive Line Signal Detect (RLSD)
- * 
+ *
  * Byte 1: Line Status
- * 
+ *
  * Offset	Description
  * B0	Data Ready (DR)
  * B1	Overrun Error (OE)
@@ -1337,7 +1337,7 @@
  * B5	Transmitter Holding Register (THRE)
  * B6	Transmitter Empty (TEMT)
  * B7	Error in RCVR FIFO
- * 
+ *
  */
 #define FTDI_RS0_CTS	(1 << 4)
 #define FTDI_RS0_DSR	(1 << 5)
@@ -1355,17 +1355,17 @@
 
 /*
  * OUT Endpoint
- * 
+ *
  * This device reserves the first bytes of data on this endpoint contain the length
  * and port identifier of the message. For the FTDI USB Serial converter the port 
  * identifier is always 1.
- * 
+ *
  * Byte 0: Line Status
- * 
+ *
  * Offset	Description
  * B0	Reserved - must be 1
  * B1	Reserved - must be 0
  * B2..7	Length of message - (not including Byte 0)
- * 
+ *
  */
 
diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c
index e8ba2cb..d30f736 100644
--- a/drivers/usb/serial/funsoft.c
+++ b/drivers/usb/serial/funsoft.c
@@ -14,7 +14,7 @@
 #include <linux/module.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 static int debug;
 
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 8ce5a56..2e663f1 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -33,7 +33,7 @@
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/atomic.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
@@ -44,7 +44,7 @@
 static int initial_mode = 1;
 
 /* debug flag */
-static int debug = 0;
+static int debug;
 
 #define GARMIN_VENDOR_ID             0x091E
 
@@ -56,7 +56,7 @@
 #define VERSION_MINOR	31
 
 #define _STR(s) #s
-#define _DRIVER_VERSION(a,b) "v" _STR(a) "." _STR(b)
+#define _DRIVER_VERSION(a, b) "v" _STR(a) "." _STR(b)
 #define DRIVER_VERSION _DRIVER_VERSION(VERSION_MAJOR, VERSION_MINOR)
 #define DRIVER_AUTHOR "hermann kneissel"
 #define DRIVER_DESC "garmin gps driver"
@@ -65,37 +65,37 @@
 #define EINVPKT	1000	/* invalid packet structure */
 
 
-// size of the header of a packet using the usb protocol
+/* size of the header of a packet using the usb protocol */
 #define GARMIN_PKTHDR_LENGTH	12
 
-// max. possible size of a packet using the serial protocol 
-#define MAX_SERIAL_PKT_SIZ (3+255+3)
+/* max. possible size of a packet using the serial protocol */
+#define MAX_SERIAL_PKT_SIZ (3 + 255 + 3)
 
-// max. possible size of a packet with worst case stuffing
-#define MAX_SERIAL_PKT_SIZ_STUFFED MAX_SERIAL_PKT_SIZ+256
+/*  max. possible size of a packet with worst case stuffing */
+#define MAX_SERIAL_PKT_SIZ_STUFFED (MAX_SERIAL_PKT_SIZ + 256)
 
-// size of a buffer able to hold a complete (no stuffing) packet
-// (the document protocol does not contain packets with a larger
-//  size, but in theory a packet may be 64k+12 bytes - if in
-//  later protocol versions larger packet sizes occur, this value
-//  should be increased accordingly, so the input buffer is always 
-//  large enough the store a complete packet inclusive header)
-#define GPS_IN_BUFSIZ  (GARMIN_PKTHDR_LENGTH+MAX_SERIAL_PKT_SIZ) 
+/* size of a buffer able to hold a complete (no stuffing) packet
+ * (the document protocol does not contain packets with a larger
+ *  size, but in theory a packet may be 64k+12 bytes - if in
+ *  later protocol versions larger packet sizes occur, this value
+ *  should be increased accordingly, so the input buffer is always
+ *  large enough the store a complete packet inclusive header) */
+#define GPS_IN_BUFSIZ  (GARMIN_PKTHDR_LENGTH+MAX_SERIAL_PKT_SIZ)
 
-// size of a buffer able to hold a complete (incl. stuffing) packet
-#define GPS_OUT_BUFSIZ (GARMIN_PKTHDR_LENGTH+MAX_SERIAL_PKT_SIZ_STUFFED) 
+/* size of a buffer able to hold a complete (incl. stuffing) packet */
+#define GPS_OUT_BUFSIZ (GARMIN_PKTHDR_LENGTH+MAX_SERIAL_PKT_SIZ_STUFFED)
 
-// where to place the packet id of a serial packet, so we can
-// prepend the usb-packet header without the need to move the
-// packets data
+/* where to place the packet id of a serial packet, so we can
+ * prepend the usb-packet header without the need to move the
+ * packets data */
 #define GSP_INITIAL_OFFSET (GARMIN_PKTHDR_LENGTH-2)
 
-// max. size of incoming private packets (header+1 param)
+/* max. size of incoming private packets (header+1 param) */
 #define PRIVPKTSIZ (GARMIN_PKTHDR_LENGTH+4)
 
 #define GARMIN_LAYERID_TRANSPORT  0
 #define GARMIN_LAYERID_APPL      20
-// our own layer-id to use for some control mechanisms
+/* our own layer-id to use for some control mechanisms */
 #define GARMIN_LAYERID_PRIVATE	0x01106E4B
 
 #define GARMIN_PKTID_PVT_DATA	51
@@ -103,7 +103,7 @@
 
 #define CMND_ABORT_TRANSFER 0
 
-// packet ids used in private layer
+/* packet ids used in private layer */
 #define PRIV_PKTID_SET_DEBUG	1
 #define PRIV_PKTID_SET_MODE	2
 #define PRIV_PKTID_INFO_REQ	3
@@ -121,7 +121,8 @@
 struct garmin_packet {
 	struct list_head  list;
 	int               seq;
-	int               size; // the real size of the data array, always > 0
+	/* the real size of the data array, always > 0 */
+	int               size;
 	__u8              data[1];
 };
 
@@ -164,7 +165,7 @@
 #define MODE_NATIVE          0
 #define MODE_GARMIN_SERIAL   1
 
-// Flags used in garmin_data.flags:
+/* Flags used in garmin_data.flags: */
 #define FLAGS_SESSION_REPLY_MASK  0x00C0
 #define FLAGS_SESSION_REPLY1_SEEN 0x0080
 #define FLAGS_SESSION_REPLY2_SEEN 0x0040
@@ -185,7 +186,7 @@
 
 
 /* function prototypes */
-static void gsp_next_packet(struct garmin_data * garmin_data_p);
+static void gsp_next_packet(struct garmin_data *garmin_data_p);
 static int  garmin_write_bulk(struct usb_serial_port *port,
 			     const unsigned char *buf, int count,
 			     int dismiss_ack);
@@ -217,12 +218,13 @@
 
 
 static struct usb_device_id id_table [] = {
-	/* the same device id seems to be used by all usb enabled gps devices */
-	{ USB_DEVICE(GARMIN_VENDOR_ID, 3 ) },
+	/* the same device id seems to be used by all
+	   usb enabled GPS devices */
+	{ USB_DEVICE(GARMIN_VENDOR_ID, 3) },
 	{ }					/* Terminating entry */
 };
 
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
 
 static struct usb_driver garmin_driver = {
 	.name =		"garmin_gps",
@@ -233,9 +235,10 @@
 };
 
 
-static inline int noResponseFromAppLayer(struct garmin_data * garmin_data_p)
+static inline int noResponseFromAppLayer(struct garmin_data *garmin_data_p)
 {
-	return atomic_read(&garmin_data_p->req_count) == atomic_read(&garmin_data_p->resp_count);
+	return atomic_read(&garmin_data_p->req_count) ==
+				atomic_read(&garmin_data_p->resp_count);
 }
 
 
@@ -261,10 +264,10 @@
  */
 static inline int isAbortTrfCmnd(const unsigned char *buf)
 {
-	if (0 == memcmp(buf, GARMIN_STOP_TRANSFER_REQ, 
-	                sizeof(GARMIN_STOP_TRANSFER_REQ)) ||
-	    0 == memcmp(buf, GARMIN_STOP_TRANSFER_REQ_V2, 
-	                sizeof(GARMIN_STOP_TRANSFER_REQ_V2)))
+	if (0 == memcmp(buf, GARMIN_STOP_TRANSFER_REQ,
+					sizeof(GARMIN_STOP_TRANSFER_REQ)) ||
+	    0 == memcmp(buf, GARMIN_STOP_TRANSFER_REQ_V2,
+					sizeof(GARMIN_STOP_TRANSFER_REQ_V2)))
 		return 1;
 	else
 		return 0;
@@ -275,11 +278,11 @@
 static void send_to_tty(struct usb_serial_port *port,
 			char *data, unsigned int actual_length)
 {
-	struct tty_struct *tty = port->tty;
+	struct tty_struct *tty = port->port.tty;
 
 	if (tty && actual_length) {
 
-		usb_serial_debug_data(debug, &port->dev, 
+		usb_serial_debug_data(debug, &port->dev,
 					__func__, actual_length, data);
 
 		tty_buffer_request_room(tty, actual_length);
@@ -296,7 +299,7 @@
 /*
  * queue a received (usb-)packet for later processing
  */
-static int pkt_add(struct garmin_data * garmin_data_p,
+static int pkt_add(struct garmin_data *garmin_data_p,
 		   unsigned char *data, unsigned int data_length)
 {
 	int state = 0;
@@ -307,7 +310,7 @@
 	/* process only packets containg data ... */
 	if (data_length) {
 		pkt = kmalloc(sizeof(struct garmin_packet)+data_length,
-		              GFP_ATOMIC);
+								GFP_ATOMIC);
 		if (pkt == NULL) {
 			dev_err(&garmin_data_p->port->dev, "out of memory\n");
 			return 0;
@@ -325,16 +328,15 @@
 
 		/* in serial mode, if someone is waiting for data from
 		   the device, iconvert and send the next packet to tty. */
-		if (result && (state == STATE_GSP_WAIT_DATA)) {
+		if (result && (state == STATE_GSP_WAIT_DATA))
 			gsp_next_packet(garmin_data_p);
-		}
 	}
 	return result;
 }
 
 
 /* get the next pending packet */
-static struct garmin_packet *pkt_pop(struct garmin_data * garmin_data_p)
+static struct garmin_packet *pkt_pop(struct garmin_data *garmin_data_p)
 {
 	unsigned long flags;
 	struct garmin_packet *result = NULL;
@@ -350,7 +352,7 @@
 
 
 /* free up all queued data */
-static void pkt_clear(struct garmin_data * garmin_data_p)
+static void pkt_clear(struct garmin_data *garmin_data_p)
 {
 	unsigned long flags;
 	struct garmin_packet *result = NULL;
@@ -372,7 +374,7 @@
  ******************************************************************************/
 
 /* send an ack packet back to the tty */
-static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id)
+static int gsp_send_ack(struct garmin_data *garmin_data_p, __u8 pkt_id)
 {
 	__u8 pkt[10];
 	__u8 cksum = 0;
@@ -391,9 +393,8 @@
 	*ptr++ = pkt_id;
 	cksum += pkt_id;
 
-	if (pkt_id == DLE) {
+	if (pkt_id == DLE)
 		*ptr++ = DLE;
-	}
 
 	*ptr++ = 0;
 	*ptr++ = 0xFF & (-cksum);
@@ -415,12 +416,12 @@
  * at GSP_INITIAL_OFFSET.
  *
  * count - number of bytes in the input buffer including space reserved for
- *         the usb header: GSP_INITIAL_OFFSET + number of bytes in packet 
+ *         the usb header: GSP_INITIAL_OFFSET + number of bytes in packet
  *         (including pkt-id, data-length a. cksum)
  */
-static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
+static int gsp_rec_packet(struct garmin_data *garmin_data_p, int count)
 {
-	const __u8* recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET;
+	const __u8 *recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET;
 	__le32 *usbdata = (__le32 *) garmin_data_p->inbuffer;
 
 	int cksum = 0;
@@ -440,8 +441,8 @@
 	cksum += *recpkt++;
 	cksum += *recpkt++;
 
-	// sanity check, remove after test ...
-	if ((__u8*)&(usbdata[3]) != recpkt) {
+	/* sanity check, remove after test ... */
+	if ((__u8 *)&(usbdata[3]) != recpkt) {
 		dbg("%s - ptr mismatch %p - %p",
 			__func__, &(usbdata[4]), recpkt);
 		return -EINVPKT;
@@ -462,7 +463,7 @@
 	usbdata[1] = __cpu_to_le32(pktid);
 	usbdata[2] = __cpu_to_le32(size);
 
-	garmin_write_bulk (garmin_data_p->port, garmin_data_p->inbuffer,
+	garmin_write_bulk(garmin_data_p->port, garmin_data_p->inbuffer,
 			   GARMIN_PKTHDR_LENGTH+size, 0);
 
 	/* if this was an abort-transfer command, flush all
@@ -495,7 +496,7 @@
  * if the input is an abort command, drop all queued data.
  */
 
-static int gsp_receive(struct garmin_data * garmin_data_p,
+static int gsp_receive(struct garmin_data *garmin_data_p,
 		       const unsigned char *buf, int count)
 {
 	unsigned long flags;
@@ -504,10 +505,11 @@
 	int i = 0;
 	__u8 *dest;
 	int size;
-	// dleSeen: set if last byte read was a DLE
+	/* dleSeen: set if last byte read was a DLE */
 	int dleSeen;
-	// skip: if set, skip incoming data until possible start of
-	//       new packet
+	/* skip: if set, skip incoming data until possible start of
+	 *       new packet
+	 */
 	int skip;
 	__u8 data;
 
@@ -521,14 +523,13 @@
 	dbg("%s - dle=%d skip=%d size=%d count=%d",
 		__func__, dleSeen, skip, size, count);
 
-	if (size == 0) {
+	if (size == 0)
 		size = GSP_INITIAL_OFFSET;
-	}
 
 	while (offs < count) {
 
 		data = *(buf+offs);
-		offs ++;
+		offs++;
 
 		if (data == DLE) {
 			if (skip) { /* start of a new pkt */
@@ -554,9 +555,8 @@
 					ack_or_nak_seen = NAK;
 					dbg("NAK packet complete.");
 				} else {
-					dbg("packet complete "
-						        "- id=0x%X.",
-						        0xFF & data);
+					dbg("packet complete - id=0x%X.",
+						0xFF & data);
 					gsp_rec_packet(garmin_data_p, size);
 				}
 
@@ -589,7 +589,7 @@
 
 	garmin_data_p->insize = size;
 
-	// copy flags back to structure
+	/* copy flags back to structure */
 	if (skip)
 		garmin_data_p->flags |= FLAGS_GSP_SKIP;
 	else
@@ -600,16 +600,13 @@
 	else
 		garmin_data_p->flags &= ~FLAGS_GSP_DLESEEN;
 
-	if (ack_or_nak_seen) {
+	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) {
+	if (ack_or_nak_seen)
 		gsp_next_packet(garmin_data_p);
-	}
-
 	return count;
 }
 
@@ -623,7 +620,7 @@
  *
  * return <0 on error, 0 if packet is incomplete or > 0 if packet was sent
  */
-static int gsp_send(struct garmin_data * garmin_data_p,
+static int gsp_send(struct garmin_data *garmin_data_p,
 		    const unsigned char *buf, int count)
 {
 	const unsigned char *src;
@@ -631,11 +628,11 @@
 	int pktid = 0;
 	int datalen = 0;
 	int cksum = 0;
-	int i=0;
+	int i = 0;
 	int k;
 
 	dbg("%s - state %d - %d bytes.", __func__,
-	         garmin_data_p->state, count);
+					garmin_data_p->state, count);
 
 	k = garmin_data_p->outsize;
 	if ((k+count) > GPS_OUT_BUFSIZ) {
@@ -650,7 +647,7 @@
 
 	if (k >= GARMIN_PKTHDR_LENGTH) {
 		pktid  = getPacketId(garmin_data_p->outbuffer);
-		datalen= getDataLength(garmin_data_p->outbuffer);
+		datalen = getDataLength(garmin_data_p->outbuffer);
 		i = GARMIN_PKTHDR_LENGTH + datalen;
 		if (k < i)
 			return 0;
@@ -658,19 +655,18 @@
 		return 0;
 	}
 
-	dbg("%s - %d bytes in buffer, %d bytes in pkt.", __func__,
-	         k, i);
+	dbg("%s - %d bytes in buffer, %d bytes in pkt.", __func__, k, i);
 
 	/* garmin_data_p->outbuffer now contains a complete packet */
 
 	usb_serial_debug_data(debug, &garmin_data_p->port->dev,
-		                   __func__, k, garmin_data_p->outbuffer);
+				__func__, k, garmin_data_p->outbuffer);
 
 	garmin_data_p->outsize = 0;
 
 	if (GARMIN_LAYERID_APPL != getLayerId(garmin_data_p->outbuffer)) {
-		dbg("not an application packet (%d)", 
-		        getLayerId(garmin_data_p->outbuffer));
+		dbg("not an application packet (%d)",
+				getLayerId(garmin_data_p->outbuffer));
 		return -1;
 	}
 
@@ -688,14 +684,14 @@
 
 	k = 0;
 	src = garmin_data_p->outbuffer+GARMIN_PKTHDR_LENGTH;
-	for (i=0; i<datalen; i++) {
+	for (i = 0; i < datalen; i++) {
 		if (*src++ == DLE)
 			k++;
 	}
 
 	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 
+		/* can't add stuffing DLEs in place, move data to end
 		   of buffer ... */
 		dst = garmin_data_p->outbuffer+GPS_OUT_BUFSIZ-datalen;
 		memcpy(dst, src, datalen);
@@ -712,14 +708,14 @@
 	if (datalen == DLE)
 		*dst++ = DLE;
 
-	for (i=0; i<datalen; i++) {
+	for (i = 0; i < datalen; i++) {
 		__u8 c = *src++;
 		*dst++ = c;
 		cksum += c;
 		if (c == DLE)
 			*dst++ = DLE;
 	}
-		
+
 	cksum = 0xFF & -cksum;
 	*dst++ = cksum;
 	if (cksum == DLE)
@@ -744,7 +740,7 @@
 /*
  * Process the next pending data packet - if there is one
  */
-static void gsp_next_packet(struct garmin_data * garmin_data_p)
+static void gsp_next_packet(struct garmin_data *garmin_data_p)
 {
 	struct garmin_packet *pkt = NULL;
 
@@ -774,17 +770,17 @@
  * buf contains the data read, it may span more than one packet
  * or even incomplete packets
  */
-static int nat_receive(struct garmin_data * garmin_data_p,
+static int nat_receive(struct garmin_data *garmin_data_p,
 		       const unsigned char *buf, int count)
 {
 	unsigned long flags;
-	__u8 * dest;
+	__u8 *dest;
 	int offs = 0;
 	int result = count;
 	int len;
 
 	while (offs < count) {
-		// if buffer contains header, copy rest of data
+		/* if buffer contains header, copy rest of data */
 		if (garmin_data_p->insize >= GARMIN_PKTHDR_LENGTH)
 			len = GARMIN_PKTHDR_LENGTH
 			      +getDataLength(garmin_data_p->inbuffer);
@@ -792,9 +788,9 @@
 			len = GARMIN_PKTHDR_LENGTH;
 
 		if (len >= GPS_IN_BUFSIZ) {
-			/* seem to be an invalid packet, ignore rest of input */
-			dbg("%s - packet size too large: %d",
-			        __func__, len);
+			/* seems to be an invalid packet, ignore rest
+			   of input */
+			dbg("%s - packet size too large: %d", __func__, len);
 			garmin_data_p->insize = 0;
 			count = 0;
 			result = -EINVPKT;
@@ -804,7 +800,7 @@
 				len = (count-offs);
 			if (len > 0) {
 				dest = garmin_data_p->inbuffer
-				       	+garmin_data_p->insize;
+						+ garmin_data_p->insize;
 				memcpy(dest, buf+offs, len);
 				garmin_data_p->insize += len;
 				offs += len;
@@ -816,17 +812,19 @@
 			len = GARMIN_PKTHDR_LENGTH+
 			   getDataLength(garmin_data_p->inbuffer);
 			if (garmin_data_p->insize >= len) {
-				garmin_write_bulk (garmin_data_p->port,
-				                   garmin_data_p->inbuffer,
-				                   len, 0);
+				garmin_write_bulk(garmin_data_p->port,
+						   garmin_data_p->inbuffer,
+						   len, 0);
 				garmin_data_p->insize = 0;
 
 				/* 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);
+					spin_lock_irqsave(&garmin_data_p->lock,
+									flags);
 					garmin_data_p->flags |= FLAGS_DROP_DATA;
-					spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+					spin_unlock_irqrestore(
+						&garmin_data_p->lock, flags);
 					pkt_clear(garmin_data_p);
 				}
 			}
@@ -842,7 +840,7 @@
 
 static void priv_status_resp(struct usb_serial_port *port)
 {
-	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
 	__le32 *pkt = (__le32 *)garmin_data_p->privpkt;
 
 	pkt[0] = __cpu_to_le32(GARMIN_LAYERID_PRIVATE);
@@ -852,7 +850,7 @@
 	pkt[4] = __cpu_to_le32(garmin_data_p->mode);
 	pkt[5] = __cpu_to_le32(garmin_data_p->serial_num);
 
-	send_to_tty(port, (__u8*)pkt, 6*4);
+	send_to_tty(port, (__u8 *)pkt, 6 * 4);
 }
 
 
@@ -864,7 +862,7 @@
 {
 	unsigned long flags;
 	int status;
-	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+	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);
@@ -872,8 +870,8 @@
 	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", __func__ );
+	usb_kill_urb(port->interrupt_in_urb);
+	dbg("%s - usb_reset_device", __func__);
 	status = usb_reset_device(port->serial->dev);
 	if (status)
 		dbg("%s - usb_reset_device failed: %d",
@@ -886,7 +884,7 @@
 /*
  * clear all cached data
  */
-static int garmin_clear(struct garmin_data * garmin_data_p)
+static int garmin_clear(struct garmin_data *garmin_data_p)
 {
 	unsigned long flags;
 	int status = 0;
@@ -896,8 +894,7 @@
 	if (port != NULL && atomic_read(&garmin_data_p->resp_count)) {
 		/* send a terminate command */
 		status = garmin_write_bulk(port, GARMIN_STOP_TRANSFER_REQ,
-		                           sizeof(GARMIN_STOP_TRANSFER_REQ),
-					   1);
+					sizeof(GARMIN_STOP_TRANSFER_REQ), 1);
 	}
 
 	/* flush all queued data */
@@ -920,28 +917,26 @@
 {
 	unsigned long flags;
 	struct usb_serial *serial = port->serial;
-	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
 	int status = 0;
 
 	if (status == 0) {
-		usb_kill_urb (port->interrupt_in_urb);
+		usb_kill_urb(port->interrupt_in_urb);
 
 		dbg("%s - adding interrupt input", __func__);
 		port->interrupt_in_urb->dev = serial->dev;
 		status = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
 		if (status)
 			dev_err(&serial->dev->dev,
-			        "%s - failed submitting interrupt urb,"
-				" error %d\n",
-			        __func__, status);
+			  "%s - failed submitting interrupt urb, error %d\n",
+							__func__, status);
 	}
 
 	if (status == 0) {
 		dbg("%s - starting session ...", __func__);
 		garmin_data_p->state = STATE_ACTIVE;
 		status = garmin_write_bulk(port, GARMIN_START_SESSION_REQ,
-		                           sizeof(GARMIN_START_SESSION_REQ),
-					   0);
+					sizeof(GARMIN_START_SESSION_REQ), 0);
 
 		if (status >= 0) {
 
@@ -951,14 +946,14 @@
 
 			/* not needed, but the win32 driver does it too ... */
 			status = garmin_write_bulk(port,
-						   GARMIN_START_SESSION_REQ2,
-			                           sizeof(GARMIN_START_SESSION_REQ2),
-						   0);
+					GARMIN_START_SESSION_REQ2,
+					sizeof(GARMIN_START_SESSION_REQ2), 0);
 			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);
+				spin_unlock_irqrestore(&garmin_data_p->lock,
+									flags);
 			}
 		}
 	}
@@ -970,11 +965,12 @@
 
 
 
-static int garmin_open (struct usb_serial_port *port, struct file *filp)
+static int garmin_open(struct tty_struct *tty,
+			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);
+	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
 
 	dbg("%s - port %d", __func__, port->number);
 
@@ -983,8 +979,8 @@
 	 * 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;
+	if (tty)
+		tty->low_latency = 1;
 
 	spin_lock_irqsave(&garmin_data_p->lock, flags);
 	garmin_data_p->mode  = initial_mode;
@@ -995,23 +991,22 @@
 	spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
 	/* shutdown any bulk reads that might be going on */
-	usb_kill_urb (port->write_urb);
-	usb_kill_urb (port->read_urb);
+	usb_kill_urb(port->write_urb);
+	usb_kill_urb(port->read_urb);
 
-	if (garmin_data_p->state == STATE_RESET) {
+	if (garmin_data_p->state == STATE_RESET)
 		status = garmin_init_session(port);
-	}
 
 	garmin_data_p->state = STATE_ACTIVE;
-
 	return status;
 }
 
 
-static void garmin_close (struct usb_serial_port *port, struct file * filp)
+static void garmin_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct usb_serial *serial = port->serial;
-	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
 
 	dbg("%s - port %d - mode=%d state=%d flags=0x%X", __func__,
 		port->number, garmin_data_p->mode,
@@ -1025,8 +1020,8 @@
 		garmin_clear(garmin_data_p);
 
 	/* shutdown our urbs */
-	usb_kill_urb (port->read_urb);
-	usb_kill_urb (port->write_urb);
+	usb_kill_urb(port->read_urb);
+	usb_kill_urb(port->write_urb);
 
 	if (!port->serial->disconnected) {
 		if (noResponseFromAppLayer(garmin_data_p) ||
@@ -1042,21 +1037,22 @@
 	mutex_unlock(&port->serial->disc_mutex);
 }
 
-
-static void garmin_write_bulk_callback (struct urb *urb)
+static void garmin_write_bulk_callback(struct urb *urb)
 {
 	unsigned long flags;
 	struct usb_serial_port *port = urb->context;
 	int status = urb->status;
 
 	if (port) {
-		struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+		struct garmin_data *garmin_data_p =
+					usb_get_serial_port_data(port);
 
 		dbg("%s - port %d", __func__, port->number);
 
 		if (GARMIN_LAYERID_APPL == getLayerId(urb->transfer_buffer)
 		    && (garmin_data_p->mode == MODE_GARMIN_SERIAL))  {
-			gsp_send_ack(garmin_data_p, ((__u8 *)urb->transfer_buffer)[4]);
+			gsp_send_ack(garmin_data_p,
+					((__u8 *)urb->transfer_buffer)[4]);
 		}
 
 		if (status) {
@@ -1070,20 +1066,21 @@
 		usb_serial_port_softint(port);
 	}
 
-	/* Ignore errors that resulted from garmin_write_bulk with dismiss_ack=1 */
+	/* Ignore errors that resulted from garmin_write_bulk with
+	   dismiss_ack = 1 */
 
 	/* free up the transfer buffer, as usb_free_urb() does not do this */
-	kfree (urb->transfer_buffer);
+	kfree(urb->transfer_buffer);
 }
 
 
-static int garmin_write_bulk (struct usb_serial_port *port,
+static int garmin_write_bulk(struct usb_serial_port *port,
 			      const unsigned char *buf, int count,
 			      int dismiss_ack)
 {
 	unsigned long flags;
 	struct usb_serial *serial = port->serial;
-	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
 	struct urb *urb;
 	unsigned char *buffer;
 	int status;
@@ -1095,7 +1092,7 @@
 	garmin_data_p->flags &= ~FLAGS_DROP_DATA;
 	spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
-	buffer = kmalloc (count, GFP_ATOMIC);
+	buffer = kmalloc(count, GFP_ATOMIC);
 	if (!buffer) {
 		dev_err(&port->dev, "out of memory\n");
 		return -ENOMEM;
@@ -1104,17 +1101,17 @@
 	urb = usb_alloc_urb(0, GFP_ATOMIC);
 	if (!urb) {
 		dev_err(&port->dev, "no more free urbs\n");
-		kfree (buffer);
+		kfree(buffer);
 		return -ENOMEM;
 	}
 
-	memcpy (buffer, buf, count);
+	memcpy(buffer, buf, count);
 
 	usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
 
-	usb_fill_bulk_urb (urb, serial->dev,
-			 	usb_sndbulkpipe (serial->dev,
-				port->bulk_out_endpointAddress),
+	usb_fill_bulk_urb(urb, serial->dev,
+				usb_sndbulkpipe(serial->dev,
+					port->bulk_out_endpointAddress),
 				buffer, count,
 				garmin_write_bulk_callback,
 				dismiss_ack ? NULL : port);
@@ -1132,33 +1129,29 @@
 	status = usb_submit_urb(urb, GFP_ATOMIC);
 	if (status) {
 		dev_err(&port->dev,
-		        "%s - usb_submit_urb(write bulk) "
-		        "failed with status = %d\n",
+		   "%s - usb_submit_urb(write bulk) failed with status = %d\n",
 				__func__, status);
 		count = status;
 	}
 
 	/* we are done with this urb, so let the host driver
 	 * really free it when it is finished with it */
-	usb_free_urb (urb);
+	usb_free_urb(urb);
 
 	return count;
 }
 
-
-
-static int garmin_write (struct usb_serial_port *port,
-			 const unsigned char *buf, int count)
+static int garmin_write(struct tty_struct *tty, struct usb_serial_port *port,
+					 const unsigned char *buf, int count)
 {
 	int pktid, pktsiz, len;
-	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
 	__le32 *privpkt = (__le32 *)garmin_data_p->privpkt;
 
 	usb_serial_debug_data(debug, &port->dev, __func__, count, buf);
 
 	/* check for our private packets */
 	if (count >= GARMIN_PKTHDR_LENGTH) {
-
 		len = PRIVPKTSIZ;
 		if (count < len)
 			len = count;
@@ -1169,15 +1162,16 @@
 		pktid  = getPacketId(garmin_data_p->privpkt);
 
 		if (count == (GARMIN_PKTHDR_LENGTH+pktsiz)
-		    && GARMIN_LAYERID_PRIVATE == getLayerId(garmin_data_p->privpkt)) {
+		    && GARMIN_LAYERID_PRIVATE ==
+				getLayerId(garmin_data_p->privpkt)) {
 
 			dbg("%s - processing private request %d",
 				__func__, pktid);
 
-			// drop all unfinished transfers
+			/* drop all unfinished transfers */
 			garmin_clear(garmin_data_p);
 
-			switch(pktid) {
+			switch (pktid) {
 
 			case PRIV_PKTID_SET_DEBUG:
 				if (pktsiz != 4)
@@ -1226,44 +1220,31 @@
 }
 
 
-static int garmin_write_room (struct usb_serial_port *port)
+static int garmin_write_room(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	/*
 	 * Report back the bytes currently available in the output buffer.
 	 */
-	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
 	return GPS_OUT_BUFSIZ-garmin_data_p->outsize;
 }
 
 
-static int garmin_chars_in_buffer (struct usb_serial_port *port)
-{
-	/*
-	 * 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 ?
-	 */
-	//struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
-	//return garmin_data_p->insize;
-	return 0;
-}
-
-
-static void garmin_read_process(struct garmin_data * garmin_data_p,
+static void garmin_read_process(struct garmin_data *garmin_data_p,
 				 unsigned char *data, unsigned data_length)
 {
 	if (garmin_data_p->flags & FLAGS_DROP_DATA) {
 		/* abort-transfer cmd is actice */
 		dbg("%s - pkt dropped", __func__);
 	} else if (garmin_data_p->state != STATE_DISCONNECTED &&
-	           garmin_data_p->state != STATE_RESET ) {
+		garmin_data_p->state != STATE_RESET) {
 
 		/* remember any appl.layer packets, so we know
 		   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))) {
 			atomic_inc(&garmin_data_p->resp_count);
 		}
 
@@ -1273,9 +1254,8 @@
 		if (garmin_data_p->flags & FLAGS_QUEUING) {
 			pkt_add(garmin_data_p, data, data_length);
 		} else if (garmin_data_p->mode == MODE_GARMIN_SERIAL) {
-			if (getLayerId(data) == GARMIN_LAYERID_APPL) {
+			if (getLayerId(data) == GARMIN_LAYERID_APPL)
 				pkt_add(garmin_data_p, data, data_length);
-			}
 		} else {
 			send_to_tty(garmin_data_p->port, data, data_length);
 		}
@@ -1283,12 +1263,12 @@
 }
 
 
-static void garmin_read_bulk_callback (struct urb *urb)
+static void garmin_read_bulk_callback(struct urb *urb)
 {
 	unsigned long flags;
 	struct usb_serial_port *port = urb->context;
 	struct usb_serial *serial =  port->serial;
-	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
 	unsigned char *data = urb->transfer_buffer;
 	int status = urb->status;
 	int retval;
@@ -1306,7 +1286,7 @@
 		return;
 	}
 
-	usb_serial_debug_data(debug, &port->dev, 
+	usb_serial_debug_data(debug, &port->dev,
 				__func__, urb->actual_length, data);
 
 	garmin_read_process(garmin_data_p, data, urb->actual_length);
@@ -1340,13 +1320,13 @@
 }
 
 
-static void garmin_read_int_callback (struct urb *urb)
+static void garmin_read_int_callback(struct urb *urb)
 {
 	unsigned long flags;
 	int retval;
 	struct usb_serial_port *port = urb->context;
 	struct usb_serial *serial = port->serial;
-	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
 	unsigned char *data = urb->transfer_buffer;
 	int status = urb->status;
 
@@ -1372,30 +1352,31 @@
 
 	if (urb->actual_length == sizeof(GARMIN_BULK_IN_AVAIL_REPLY) &&
 	    0 == memcmp(data, GARMIN_BULK_IN_AVAIL_REPLY,
-		        sizeof(GARMIN_BULK_IN_AVAIL_REPLY))) {
+				sizeof(GARMIN_BULK_IN_AVAIL_REPLY))) {
 
 		dbg("%s - bulk data available.", __func__);
 
 		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),
+			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);
 			retval = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 			if (retval) {
 				dev_err(&port->dev,
-					"%s - failed submitting read urb, error %d\n",
-				__func__, retval);
+				 "%s - failed submitting read urb, error %d\n",
+							__func__, retval);
 			} 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);
+				spin_unlock_irqrestore(&garmin_data_p->lock,
+									flags);
 			}
 		} else {
 			/* bulk-in transfer still active */
@@ -1406,15 +1387,15 @@
 
 	} else if (urb->actual_length == (4+sizeof(GARMIN_START_SESSION_REPLY))
 			 && 0 == memcmp(data, GARMIN_START_SESSION_REPLY,
-			                sizeof(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 
-			= __le32_to_cpup((__le32*)(data+GARMIN_PKTHDR_LENGTH));
+		garmin_data_p->serial_num = __le32_to_cpup(
+					(__le32 *)(data+GARMIN_PKTHDR_LENGTH));
 
 		dbg("%s - start-of-session reply seen - serial %u.",
 			__func__, garmin_data_p->serial_num);
@@ -1433,7 +1414,7 @@
 	}
 
 	port->interrupt_in_urb->dev = port->serial->dev;
-	retval = usb_submit_urb (urb, GFP_ATOMIC);
+	retval = usb_submit_urb(urb, GFP_ATOMIC);
 	if (retval)
 		dev_err(&urb->dev->dev,
 			"%s - Error %d submitting interrupt urb\n",
@@ -1446,7 +1427,7 @@
  * and then sets a timer to call itself again until all queued data
  * is sent.
  */
-static int garmin_flush_queue(struct garmin_data * garmin_data_p)
+static int garmin_flush_queue(struct garmin_data *garmin_data_p)
 {
 	unsigned long flags;
 	struct garmin_packet *pkt;
@@ -1468,10 +1449,11 @@
 }
 
 
-static void garmin_throttle (struct usb_serial_port *port)
+static void garmin_throttle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
+	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
 	unsigned long flags;
-	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 
 	dbg("%s - port %d", __func__, port->number);
 	/* set flag, data received will be put into a queue
@@ -1482,10 +1464,11 @@
 }
 
 
-static void garmin_unthrottle (struct usb_serial_port *port)
+static void garmin_unthrottle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
+	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
 	unsigned long flags;
-	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 	int status;
 
 	dbg("%s - port %d", __func__, port->number);
@@ -1507,8 +1490,6 @@
 	}
 }
 
-
-
 /*
  * The timer is currently only used to send queued packets to
  * the tty in cases where the protocol provides no own handshaking
@@ -1526,11 +1507,11 @@
 
 
 
-static int garmin_attach (struct usb_serial *serial)
+static int garmin_attach(struct usb_serial *serial)
 {
 	int status = 0;
 	struct usb_serial_port *port = serial->port[0];
-	struct garmin_data * garmin_data_p = NULL;
+	struct garmin_data *garmin_data_p = NULL;
 
 	dbg("%s", __func__);
 
@@ -1542,7 +1523,7 @@
 	init_timer(&garmin_data_p->timer);
 	spin_lock_init(&garmin_data_p->lock);
 	INIT_LIST_HEAD(&garmin_data_p->pktlist);
-	//garmin_data_p->timer.expires = jiffies + session_timeout;
+	/* garmin_data_p->timer.expires = jiffies + session_timeout; */
 	garmin_data_p->timer.data = (unsigned long)garmin_data_p;
 	garmin_data_p->timer.function = timeout_handler;
 	garmin_data_p->port = port;
@@ -1556,16 +1537,16 @@
 }
 
 
-static void garmin_shutdown (struct usb_serial *serial)
+static void garmin_shutdown(struct usb_serial *serial)
 {
 	struct usb_serial_port *port = serial->port[0];
-	struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+	struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
 
 	dbg("%s", __func__);
 
-	usb_kill_urb (port->interrupt_in_urb);
+	usb_kill_urb(port->interrupt_in_urb);
 	del_timer_sync(&garmin_data_p->timer);
-	kfree (garmin_data_p);
+	kfree(garmin_data_p);
 	usb_set_serial_port_data(port, NULL);
 }
 
@@ -1588,7 +1569,6 @@
 	.shutdown            = garmin_shutdown,
 	.write               = garmin_write,
 	.write_room          = garmin_write_room,
-	.chars_in_buffer     = garmin_chars_in_buffer,
 	.write_bulk_callback = garmin_write_bulk_callback,
 	.read_bulk_callback  = garmin_read_bulk_callback,
 	.read_int_callback   = garmin_read_int_callback,
@@ -1596,7 +1576,7 @@
 
 
 
-static int __init garmin_init (void)
+static int __init garmin_init(void)
 {
 	int retval;
 
@@ -1616,10 +1596,10 @@
 }
 
 
-static void __exit garmin_exit (void)
+static void __exit garmin_exit(void)
 {
-	usb_deregister (&garmin_driver);
-	usb_serial_deregister (&garmin_device);
+	usb_deregister(&garmin_driver);
+	usb_serial_deregister(&garmin_device);
 }
 
 
@@ -1628,8 +1608,8 @@
 module_init(garmin_init);
 module_exit(garmin_exit);
 
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IWUSR | S_IRUGO);
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 537f12a..fe84c88 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -18,7 +18,7 @@
 #include <linux/moduleparam.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 
 static int debug;
@@ -81,7 +81,7 @@
 }
 #endif
 
-int usb_serial_generic_register (int _debug)
+int usb_serial_generic_register(int _debug)
 {
 	int retval = 0;
 
@@ -89,10 +89,11 @@
 #ifdef CONFIG_USB_SERIAL_GENERIC
 	generic_device_ids[0].idVendor = vendor;
 	generic_device_ids[0].idProduct = product;
-	generic_device_ids[0].match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT;
+	generic_device_ids[0].match_flags =
+		USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT;
 
 	/* register our generic driver with ourselves */
-	retval = usb_serial_register (&usb_serial_generic_device);
+	retval = usb_serial_register(&usb_serial_generic_device);
 	if (retval)
 		goto exit;
 	retval = usb_register(&generic_driver);
@@ -103,16 +104,17 @@
 	return retval;
 }
 
-void usb_serial_generic_deregister (void)
+void usb_serial_generic_deregister(void)
 {
 #ifdef CONFIG_USB_SERIAL_GENERIC
 	/* remove our generic driver */
 	usb_deregister(&generic_driver);
-	usb_serial_deregister (&usb_serial_generic_device);
+	usb_serial_deregister(&usb_serial_generic_device);
 #endif
 }
 
-int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
+int usb_serial_generic_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct usb_serial *serial = port->serial;
 	int result = 0;
@@ -120,11 +122,11 @@
 
 	dbg("%s - port %d", __func__, port->number);
 
-	/* 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;
+	/* 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 (tty)
+		tty->low_latency = 1;
 
 	/* clear the throttle flags */
 	spin_lock_irqsave(&port->lock, flags);
@@ -135,8 +137,9 @@
 	/* if we have a bulk endpoint, start reading from it */
 	if (serial->num_bulk_in) {
 		/* Start reading from the device */
-		usb_fill_bulk_urb (port->read_urb, serial->dev,
-				   usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+		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,
 				   ((serial->type->read_bulk_callback) ?
@@ -145,14 +148,16 @@
 				   port);
 		result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 		if (result)
-			dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
+			dev_err(&port->dev,
+			    "%s - failed resubmitting read urb, error %d\n",
+							__func__, result);
 	}
 
 	return result;
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_open);
 
-static void generic_cleanup (struct usb_serial_port *port)
+static void generic_cleanup(struct usb_serial_port *port)
 {
 	struct usb_serial *serial = port->serial;
 
@@ -182,7 +187,7 @@
 #endif
 	for (i = 0; i < serial->num_ports; i++) {
 		port = serial->port[i];
-		if (port->open_count && port->read_urb) {
+		if (port->port.count && port->read_urb) {
 			r = usb_submit_urb(port->read_urb, GFP_NOIO);
 			if (r < 0)
 				c++;
@@ -192,13 +197,15 @@
 	return c ? -EIO : 0;
 }
 
-void usb_serial_generic_close (struct usb_serial_port *port, struct file * filp)
+void usb_serial_generic_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	dbg("%s - port %d", __func__, port->number);
-	generic_cleanup (port);
+	generic_cleanup(port);
 }
 
-int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *buf, int count)
+int usb_serial_generic_write(struct tty_struct *tty,
+	struct usb_serial_port *port, const unsigned char *buf, int count)
 {
 	struct usb_serial *serial = port->serial;
 	int result;
@@ -208,7 +215,7 @@
 
 	if (count == 0) {
 		dbg("%s - write request of 0 bytes", __func__);
-		return (0);
+		return 0;
 	}
 
 	/* only do something if we have a bulk out endpoint */
@@ -223,27 +230,32 @@
 		port->write_urb_busy = 1;
 		spin_unlock_irqrestore(&port->lock, flags);
 
-		count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
+		count = (count > port->bulk_out_size) ?
+					port->bulk_out_size : count;
 
-		memcpy (port->write_urb->transfer_buffer, buf, count);
+		memcpy(port->write_urb->transfer_buffer, buf, count);
 		data = port->write_urb->transfer_buffer;
 		usb_serial_debug_data(debug, &port->dev, __func__, count, data);
 
 		/* set up our urb */
-		usb_fill_bulk_urb (port->write_urb, serial->dev,
-				   usb_sndbulkpipe (serial->dev,
-						    port->bulk_out_endpointAddress),
+		usb_fill_bulk_urb(port->write_urb, serial->dev,
+				   usb_sndbulkpipe(serial->dev,
+					port->bulk_out_endpointAddress),
 				   port->write_urb->transfer_buffer, count,
-				   ((serial->type->write_bulk_callback) ? 
+				   ((serial->type->write_bulk_callback) ?
 				     serial->type->write_bulk_callback :
-				     usb_serial_generic_write_bulk_callback), port);
+				     usb_serial_generic_write_bulk_callback),
+				   port);
 
 		/* send the data out the bulk port */
 		port->write_urb_busy = 1;
 		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
 		if (result) {
-			dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result);
-			/* don't have to grab the lock here, as we will retry if != 0 */
+			dev_err(&port->dev,
+				"%s - failed submitting write urb, error %d\n",
+							__func__, result);
+			/* don't have to grab the lock here, as we will
+			   retry if != 0 */
 			port->write_urb_busy = 0;
 		} else
 			result = count;
@@ -255,8 +267,9 @@
 	return 0;
 }
 
-int usb_serial_generic_write_room (struct usb_serial_port *port)
+int usb_serial_generic_write_room(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct usb_serial *serial = port->serial;
 	int room = 0;
 
@@ -272,8 +285,9 @@
 	return room;
 }
 
-int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port)
+int usb_serial_generic_chars_in_buffer(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct usb_serial *serial = port->serial;
 	int chars = 0;
 
@@ -286,7 +300,7 @@
 	}
 
 	dbg("%s - returns %d", __func__, chars);
-	return (chars);
+	return chars;
 }
 
 
@@ -297,24 +311,26 @@
 	int result;
 
 	/* Continue reading from device */
-	usb_fill_bulk_urb (urb, serial->dev,
-			   usb_rcvbulkpipe (serial->dev,
-				   	    port->bulk_in_endpointAddress),
+	usb_fill_bulk_urb(urb, serial->dev,
+			   usb_rcvbulkpipe(serial->dev,
+					port->bulk_in_endpointAddress),
 			   urb->transfer_buffer,
 			   urb->transfer_buffer_length,
-			   ((serial->type->read_bulk_callback) ? 
-			     serial->type->read_bulk_callback : 
+			   ((serial->type->read_bulk_callback) ?
+			     serial->type->read_bulk_callback :
 			     usb_serial_generic_read_bulk_callback), port);
 	result = usb_submit_urb(urb, mem_flags);
 	if (result)
-		dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
+		dev_err(&port->dev,
+			"%s - failed resubmitting read urb, error %d\n",
+							__func__, result);
 }
 
 /* Push data to tty layer and resubmit the bulk read URB */
-static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
+static void flush_and_resubmit_read_urb(struct usb_serial_port *port)
 {
 	struct urb *urb = port->read_urb;
-	struct tty_struct *tty = port->tty;
+	struct tty_struct *tty = port->port.tty;
 	int room;
 
 	/* Push data to tty */
@@ -329,7 +345,7 @@
 	resubmit_read_urb(port, GFP_ATOMIC);
 }
 
-void usb_serial_generic_read_bulk_callback (struct urb *urb)
+void usb_serial_generic_read_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 	unsigned char *data = urb->transfer_buffer;
@@ -344,20 +360,21 @@
 		return;
 	}
 
-	usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+	usb_serial_debug_data(debug, &port->dev, __func__,
+						urb->actual_length, data);
 
 	/* Throttle the device if requested by tty */
 	spin_lock_irqsave(&port->lock, flags);
-	if (!(port->throttled = port->throttle_req)) {
+	port->throttled = port->throttle_req;
+	if (!port->throttled) {
 		spin_unlock_irqrestore(&port->lock, flags);
 		flush_and_resubmit_read_urb(port);
-	} else {
+	} else
 		spin_unlock_irqrestore(&port->lock, flags);
-	}
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
 
-void usb_serial_generic_write_bulk_callback (struct urb *urb)
+void usb_serial_generic_write_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 	int status = urb->status;
@@ -374,8 +391,9 @@
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback);
 
-void usb_serial_generic_throttle (struct usb_serial_port *port)
+void usb_serial_generic_throttle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	unsigned long flags;
 
 	dbg("%s - port %d", __func__, port->number);
@@ -387,8 +405,9 @@
 	spin_unlock_irqrestore(&port->lock, flags);
 }
 
-void usb_serial_generic_unthrottle (struct usb_serial_port *port)
+void usb_serial_generic_unthrottle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	int was_throttled;
 	unsigned long flags;
 
@@ -406,15 +425,14 @@
 	}
 }
 
-void usb_serial_generic_shutdown (struct usb_serial *serial)
+void usb_serial_generic_shutdown(struct usb_serial *serial)
 {
 	int i;
 
 	dbg("%s", __func__);
 
 	/* stop reads and writes on all ports */
-	for (i=0; i < serial->num_ports; ++i) {
+	for (i = 0; i < serial->num_ports; ++i)
 		generic_cleanup(serial->port[i]);
-	}
 }
 
diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c
index 75b88b3..ab90586 100644
--- a/drivers/usb/serial/hp4x.c
+++ b/drivers/usb/serial/hp4x.c
@@ -9,7 +9,8 @@
  *	the Free Software Foundation; either version 2 of the License, or
  *	(at your option) any later version.
  *
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
  */
 
 #include <linux/kernel.h>
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 2fd449b..bfa508d 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -44,7 +44,7 @@
 #include <linux/wait.h>
 #include <linux/firmware.h>
 #include <linux/ihex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 #include "io_edgeport.h"
@@ -66,16 +66,16 @@
 
 /* receive port state */
 enum RXSTATE {
-	EXPECT_HDR1 = 0,	/* Expect header byte 1 */
-	EXPECT_HDR2 = 1,	/* Expect header byte 2 */
-	EXPECT_DATA = 2,	/* Expect 'RxBytesRemaining' data */
-	EXPECT_HDR3 = 3,	/* Expect header byte 3 (for status hdrs only) */
+	EXPECT_HDR1 = 0,    /* Expect header byte 1 */
+	EXPECT_HDR2 = 1,    /* Expect header byte 2 */
+	EXPECT_DATA = 2,    /* Expect 'RxBytesRemaining' data */
+	EXPECT_HDR3 = 3,    /* Expect header byte 3 (for status hdrs only) */
 };
 
 
-/* Transmit Fifo 
- * This Transmit queue is an extension of the edgeport Rx buffer. 
- * The maximum amount of data buffered in both the edgeport 
+/* Transmit Fifo
+ * This Transmit queue is an extension of the edgeport Rx buffer.
+ * The maximum amount of data buffered in both the edgeport
  * Rx buffer (maxTxCredits) and this buffer will never exceed maxTxCredits.
  */
 struct TxFifo {
@@ -132,12 +132,12 @@
 	int			is_epic;			/* flag if EPiC device or not */
 
 	__u8			interrupt_in_endpoint;		/* the interrupt endpoint handle */
-	unsigned char *		interrupt_in_buffer;		/* the buffer we use for the interrupt endpoint */
-	struct urb *		interrupt_read_urb;		/* our interrupt urb */
+	unsigned char		*interrupt_in_buffer;		/* the buffer we use for the interrupt endpoint */
+	struct urb		*interrupt_read_urb;		/* our interrupt urb */
 
 	__u8			bulk_in_endpoint;		/* the bulk in endpoint handle */
-	unsigned char *		bulk_in_buffer;			/* the buffer we use for the bulk in endpoint */
-	struct urb *		read_urb;			/* our bulk read urb */
+	unsigned char		*bulk_in_buffer;		/* the buffer we use for the bulk in endpoint */
+	struct urb		*read_urb;			/* our bulk read urb */
 	bool			read_in_progress;
 	spinlock_t		es_lock;
 
@@ -162,16 +162,17 @@
 	__u16  Divisor;
 };
 
-//
-// Define table of divisors for Rev A EdgePort/4 hardware
-// These assume a 3.6864MHz crystal, the standard /16, and
-// MCR.7 = 0.
-//
+/*
+ * Define table of divisors for Rev A EdgePort/4 hardware
+ * These assume a 3.6864MHz crystal, the standard /16, and
+ * MCR.7 = 0.
+ */
+
 static const struct divisor_table_entry divisor_table[] = {
-	{   50,		4608},  
-	{   75,		3072},  
-	{   110,	2095},		/* 2094.545455 => 230450   => .0217 % over */
-	{   134,	1713},		/* 1713.011152 => 230398.5 => .00065% under */
+	{   50,		4608},
+	{   75,		3072},
+	{   110,	2095},	/* 2094.545455 => 230450   => .0217 % over */
+	{   134,	1713},	/* 1713.011152 => 230398.5 => .00065% under */
 	{   150,	1536},
 	{   300,	768},
 	{   600,	384},
@@ -194,64 +195,86 @@
 
 static int low_latency = 1;	/* tty low latency flag, on by default */
 
-static atomic_t CmdUrbs;		/* Number of outstanding Command Write Urbs */
+static atomic_t CmdUrbs;	/* Number of outstanding Command Write Urbs */
 
 
 /* local function prototypes */
 
 /* function prototypes for all URB callbacks */
-static void edge_interrupt_callback	(struct urb *urb);
-static void edge_bulk_in_callback	(struct urb *urb);
-static void edge_bulk_out_data_callback	(struct urb *urb);
-static void edge_bulk_out_cmd_callback	(struct urb *urb);
+static void edge_interrupt_callback(struct urb *urb);
+static void edge_bulk_in_callback(struct urb *urb);
+static void edge_bulk_out_data_callback(struct urb *urb);
+static void edge_bulk_out_cmd_callback(struct urb *urb);
 
 /* function prototypes for the usbserial callbacks */
-static int  edge_open			(struct usb_serial_port *port, struct file *filp);
-static void edge_close			(struct usb_serial_port *port, struct file *filp);
-static int  edge_write			(struct usb_serial_port *port, const unsigned char *buf, int count);
-static int  edge_write_room		(struct usb_serial_port *port);
-static int  edge_chars_in_buffer	(struct usb_serial_port *port);
-static void edge_throttle		(struct usb_serial_port *port);
-static void edge_unthrottle		(struct usb_serial_port *port);
-static void edge_set_termios		(struct usb_serial_port *port, struct ktermios *old_termios);
-static int  edge_ioctl			(struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg);
-static void edge_break			(struct usb_serial_port *port, int break_state);
-static int  edge_tiocmget		(struct usb_serial_port *port, struct file *file);
-static int  edge_tiocmset		(struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
-static int  edge_startup		(struct usb_serial *serial);
-static void edge_shutdown		(struct usb_serial *serial);
-
+static int edge_open(struct tty_struct *tty, struct usb_serial_port *port,
+					struct file *filp);
+static void edge_close(struct tty_struct *tty, struct usb_serial_port *port,
+					struct file *filp);
+static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
+					const unsigned char *buf, int count);
+static int edge_write_room(struct tty_struct *tty);
+static int edge_chars_in_buffer(struct tty_struct *tty);
+static void edge_throttle(struct tty_struct *tty);
+static void edge_unthrottle(struct tty_struct *tty);
+static void edge_set_termios(struct tty_struct *tty,
+					struct usb_serial_port *port,
+					struct ktermios *old_termios);
+static int  edge_ioctl(struct tty_struct *tty, struct file *file,
+					unsigned int cmd, unsigned long arg);
+static void edge_break(struct tty_struct *tty, int break_state);
+static int  edge_tiocmget(struct tty_struct *tty, struct file *file);
+static int  edge_tiocmset(struct tty_struct *tty, struct file *file,
+					unsigned int set, unsigned int clear);
+static int  edge_startup(struct usb_serial *serial);
+static void edge_shutdown(struct usb_serial *serial);
 
 #include "io_tables.h"	/* all of the devices that this driver supports */
 
 /* function prototypes for all of our local functions */
-static void  process_rcvd_data		(struct edgeport_serial *edge_serial, unsigned char *buffer, __u16 bufferLength);
-static void process_rcvd_status		(struct edgeport_serial *edge_serial, __u8 byte2, __u8 byte3);
-static void edge_tty_recv			(struct device *dev, struct tty_struct *tty, unsigned char *data, int length);
-static void handle_new_msr		(struct edgeport_port *edge_port, __u8 newMsr);
-static void handle_new_lsr		(struct edgeport_port *edge_port, __u8 lsrData, __u8 lsr, __u8 data);
-static int  send_iosp_ext_cmd		(struct edgeport_port *edge_port, __u8 command, __u8 param);
-static int  calc_baud_rate_divisor	(int baud_rate, int *divisor);
-static int  send_cmd_write_baud_rate	(struct edgeport_port *edge_port, int baudRate);
-static void change_port_settings	(struct edgeport_port *edge_port, struct ktermios *old_termios);
-static int  send_cmd_write_uart_register	(struct edgeport_port *edge_port, __u8 regNum, __u8 regValue);
-static int  write_cmd_usb		(struct edgeport_port *edge_port, unsigned char *buffer, int writeLength);
-static void send_more_port_data		(struct edgeport_serial *edge_serial, struct edgeport_port *edge_port);
 
-static int  sram_write			(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, const __u8 *data);
-static int  rom_read			(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data);
-static int  rom_write			(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, const __u8 *data);
-static void get_manufacturing_desc	(struct edgeport_serial *edge_serial);
-static void get_boot_desc		(struct edgeport_serial *edge_serial);
-static void load_application_firmware	(struct edgeport_serial *edge_serial);
+static void  process_rcvd_data(struct edgeport_serial *edge_serial,
+				unsigned char *buffer, __u16 bufferLength);
+static void process_rcvd_status(struct edgeport_serial *edge_serial,
+				__u8 byte2, __u8 byte3);
+static void edge_tty_recv(struct device *dev, struct tty_struct *tty,
+				unsigned char *data, int length);
+static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr);
+static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData,
+				__u8 lsr, __u8 data);
+static int  send_iosp_ext_cmd(struct edgeport_port *edge_port, __u8 command,
+				__u8 param);
+static int  calc_baud_rate_divisor(int baud_rate, int *divisor);
+static int  send_cmd_write_baud_rate(struct edgeport_port *edge_port,
+				int baudRate);
+static void change_port_settings(struct tty_struct *tty,
+				struct edgeport_port *edge_port,
+				struct ktermios *old_termios);
+static int  send_cmd_write_uart_register(struct edgeport_port *edge_port,
+				__u8 regNum, __u8 regValue);
+static int  write_cmd_usb(struct edgeport_port *edge_port,
+				unsigned char *buffer, int writeLength);
+static void send_more_port_data(struct edgeport_serial *edge_serial,
+				struct edgeport_port *edge_port);
 
-static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unicode_size);
+static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr,
+					__u16 length, const __u8 *data);
+static int rom_read(struct usb_serial *serial, __u16 extAddr, __u16 addr,
+						__u16 length, __u8 *data);
+static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr,
+					__u16 length, const __u8 *data);
+static void get_manufacturing_desc(struct edgeport_serial *edge_serial);
+static void get_boot_desc(struct edgeport_serial *edge_serial);
+static void load_application_firmware(struct edgeport_serial *edge_serial);
+
+static void unicode_to_ascii(char *string, int buflen,
+				__le16 *unicode, int unicode_size);
 
 
-// ************************************************************************
-// ************************************************************************
-// ************************************************************************
-// ************************************************************************
+/* ************************************************************************ */
+/* ************************************************************************ */
+/* ************************************************************************ */
+/* ************************************************************************ */
 
 /************************************************************************
  *									*
@@ -261,7 +284,7 @@
  *				embedded in this driver			*
  *									*
  ************************************************************************/
-static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial)
+static void update_edgeport_E2PROM(struct edgeport_serial *edge_serial)
 {
 	__u32 BootCurVer;
 	__u32 BootNewVer;
@@ -275,16 +298,14 @@
 	int response;
 
 	switch (edge_serial->product_info.iDownloadFile) {
-		case EDGE_DOWNLOAD_FILE_I930:
-			fw_name	= "edgeport/boot.fw";
-			break;
-
-		case EDGE_DOWNLOAD_FILE_80251:
-			fw_name	= "edgeport/boot2.fw";
-			break;
-
-		default:
-			return;
+	case EDGE_DOWNLOAD_FILE_I930:
+		fw_name	= "edgeport/boot.fw";
+		break;
+	case EDGE_DOWNLOAD_FILE_80251:
+		fw_name	= "edgeport/boot2.fw";
+		break;
+	default:
+		return;
 	}
 
 	response = request_ihex_firmware(&fw, fw_name,
@@ -300,7 +321,7 @@
 	BootMinorVersion = rec->data[1];
 	BootBuildNumber = (rec->data[2] << 8) | rec->data[3];
 
-	// Check Boot Image Version
+	/* Check Boot Image Version */
 	BootCurVer = (edge_serial->boot_descriptor.MajorVersion << 24) +
 		     (edge_serial->boot_descriptor.MinorVersion << 16) +
 		      le16_to_cpu(edge_serial->boot_descriptor.BuildNumber);
@@ -352,29 +373,29 @@
  *  Get string descriptor from device					*
  *									*
  ************************************************************************/
-static int get_string (struct usb_device *dev, int Id, char *string, int buflen)
+static int get_string(struct usb_device *dev, int Id, char *string, int buflen)
 {
 	struct usb_string_descriptor StringDesc;
 	struct usb_string_descriptor *pStringDesc;
 
-	dbg("%s - USB String ID = %d", __func__, Id );
+	dbg("%s - USB String ID = %d", __func__, Id);
 
-	if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc, sizeof(StringDesc))) {
+	if (!usb_get_descriptor(dev, USB_DT_STRING, Id,
+					&StringDesc, sizeof(StringDesc)))
 		return 0;
-	}
 
-	pStringDesc = kmalloc (StringDesc.bLength, GFP_KERNEL);
-
-	if (!pStringDesc) {
+	pStringDesc = kmalloc(StringDesc.bLength, GFP_KERNEL);
+	if (!pStringDesc)
 		return 0;
-	}
 
-	if (!usb_get_descriptor(dev, USB_DT_STRING, Id, pStringDesc, StringDesc.bLength )) {
+	if (!usb_get_descriptor(dev, USB_DT_STRING, Id,
+					pStringDesc, StringDesc.bLength)) {
 		kfree(pStringDesc);
 		return 0;
 	}
 
-	unicode_to_ascii(string, buflen, pStringDesc->wData, pStringDesc->bLength/2);
+	unicode_to_ascii(string, buflen,
+				pStringDesc->wData, pStringDesc->bLength/2);
 
 	kfree(pStringDesc);
 	dbg("%s - USB String %s", __func__, string);
@@ -388,24 +409,24 @@
  *  Get string descriptor from device
  *
  ************************************************************************/
-static int get_string_desc (struct usb_device *dev, int Id, struct usb_string_descriptor **pRetDesc)
+static int get_string_desc(struct usb_device *dev, int Id,
+				struct usb_string_descriptor **pRetDesc)
 {
 	struct usb_string_descriptor StringDesc;
 	struct usb_string_descriptor *pStringDesc;
 
-	dbg("%s - USB String ID = %d", __func__, Id );
+	dbg("%s - USB String ID = %d", __func__, Id);
 
-	if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc, sizeof(StringDesc))) {
+	if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc,
+						sizeof(StringDesc)))
 		return 0;
-	}
 
-	pStringDesc = kmalloc (StringDesc.bLength, GFP_KERNEL);
-
-	if (!pStringDesc) {
+	pStringDesc = kmalloc(StringDesc.bLength, GFP_KERNEL);
+	if (!pStringDesc)
 		return -1;
-	}
 
-	if (!usb_get_descriptor(dev, USB_DT_STRING, Id, pStringDesc, StringDesc.bLength )) {
+	if (!usb_get_descriptor(dev, USB_DT_STRING, Id, pStringDesc,
+							StringDesc.bLength)) {
 		kfree(pStringDesc);
 		return -1;
 	}
@@ -417,25 +438,30 @@
 
 static void dump_product_info(struct edgeport_product_info *product_info)
 {
-	// Dump Product Info structure
+	/* Dump Product Info structure */
 	dbg("**Product Information:");
-	dbg("  ProductId             %x", product_info->ProductId );
-	dbg("  NumPorts              %d", product_info->NumPorts );
-	dbg("  ProdInfoVer           %d", product_info->ProdInfoVer );
+	dbg("  ProductId             %x", product_info->ProductId);
+	dbg("  NumPorts              %d", product_info->NumPorts);
+	dbg("  ProdInfoVer           %d", product_info->ProdInfoVer);
 	dbg("  IsServer              %d", product_info->IsServer);
-	dbg("  IsRS232               %d", product_info->IsRS232 );
-	dbg("  IsRS422               %d", product_info->IsRS422 );
-	dbg("  IsRS485               %d", product_info->IsRS485 );
-	dbg("  RomSize               %d", product_info->RomSize );
-	dbg("  RamSize               %d", product_info->RamSize );
-	dbg("  CpuRev                %x", product_info->CpuRev  );
+	dbg("  IsRS232               %d", product_info->IsRS232);
+	dbg("  IsRS422               %d", product_info->IsRS422);
+	dbg("  IsRS485               %d", product_info->IsRS485);
+	dbg("  RomSize               %d", product_info->RomSize);
+	dbg("  RamSize               %d", product_info->RamSize);
+	dbg("  CpuRev                %x", product_info->CpuRev);
 	dbg("  BoardRev              %x", product_info->BoardRev);
 	dbg("  BootMajorVersion      %d.%d.%d", product_info->BootMajorVersion,
 	    product_info->BootMinorVersion,
 	    le16_to_cpu(product_info->BootBuildNumber));
-	dbg("  ManufactureDescDate   %d/%d/%d", product_info->ManufactureDescDate[0],
-	    product_info->ManufactureDescDate[1],
-	    product_info->ManufactureDescDate[2]+1900);
+	dbg("  FirmwareMajorVersion  %d.%d.%d",
+			product_info->FirmwareMajorVersion,
+			product_info->FirmwareMinorVersion,
+			le16_to_cpu(product_info->FirmwareBuildNumber));
+	dbg("  ManufactureDescDate   %d/%d/%d",
+			product_info->ManufactureDescDate[0],
+			product_info->ManufactureDescDate[1],
+			product_info->ManufactureDescDate[2]+1900);
 	dbg("  iDownloadFile         0x%x", product_info->iDownloadFile);
 	dbg("  EpicVer               %d", product_info->EpicVer);
 }
@@ -444,55 +470,60 @@
 {
 	struct edgeport_product_info *product_info = &edge_serial->product_info;
 
-	memset (product_info, 0, sizeof(struct edgeport_product_info));
+	memset(product_info, 0, sizeof(struct edgeport_product_info));
 
-	product_info->ProductId		= (__u16)(le16_to_cpu(edge_serial->serial->dev->descriptor.idProduct) & ~ION_DEVICE_ID_80251_NETCHIP);
-	product_info->NumPorts		= edge_serial->manuf_descriptor.NumPorts;
-	product_info->ProdInfoVer	= 0;
+	product_info->ProductId = (__u16)(le16_to_cpu(edge_serial->serial->dev->descriptor.idProduct) & ~ION_DEVICE_ID_80251_NETCHIP);
+	product_info->NumPorts = edge_serial->manuf_descriptor.NumPorts;
+	product_info->ProdInfoVer = 0;
 
-	product_info->RomSize		= edge_serial->manuf_descriptor.RomSize;
-	product_info->RamSize		= edge_serial->manuf_descriptor.RamSize;
-	product_info->CpuRev		= edge_serial->manuf_descriptor.CpuRev;
-	product_info->BoardRev		= edge_serial->manuf_descriptor.BoardRev;
+	product_info->RomSize = edge_serial->manuf_descriptor.RomSize;
+	product_info->RamSize = edge_serial->manuf_descriptor.RamSize;
+	product_info->CpuRev = edge_serial->manuf_descriptor.CpuRev;
+	product_info->BoardRev = edge_serial->manuf_descriptor.BoardRev;
 
-	product_info->BootMajorVersion	= edge_serial->boot_descriptor.MajorVersion;
-	product_info->BootMinorVersion	= edge_serial->boot_descriptor.MinorVersion;
-	product_info->BootBuildNumber	= edge_serial->boot_descriptor.BuildNumber;
+	product_info->BootMajorVersion =
+				edge_serial->boot_descriptor.MajorVersion;
+	product_info->BootMinorVersion =
+				edge_serial->boot_descriptor.MinorVersion;
+	product_info->BootBuildNumber =
+				edge_serial->boot_descriptor.BuildNumber;
 
-	memcpy(product_info->ManufactureDescDate, edge_serial->manuf_descriptor.DescDate, sizeof(edge_serial->manuf_descriptor.DescDate));
+	memcpy(product_info->ManufactureDescDate,
+			edge_serial->manuf_descriptor.DescDate,
+			sizeof(edge_serial->manuf_descriptor.DescDate));
 
-	// check if this is 2nd generation hardware
-	if (le16_to_cpu(edge_serial->serial->dev->descriptor.idProduct) & ION_DEVICE_ID_80251_NETCHIP) {
-		product_info->iDownloadFile		= EDGE_DOWNLOAD_FILE_80251;
-	} else {
-		product_info->iDownloadFile		= EDGE_DOWNLOAD_FILE_I930;
-	}
-
-	// Determine Product type and set appropriate flags
+	/* check if this is 2nd generation hardware */
+	if (le16_to_cpu(edge_serial->serial->dev->descriptor.idProduct)
+					    & ION_DEVICE_ID_80251_NETCHIP)
+		product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_80251;
+	else
+		product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_I930;
+ 
+	/* Determine Product type and set appropriate flags */
 	switch (DEVICE_ID_FROM_USB_PRODUCT_ID(product_info->ProductId)) {
-		case ION_DEVICE_ID_EDGEPORT_COMPATIBLE:
-		case ION_DEVICE_ID_EDGEPORT_4T:
-		case ION_DEVICE_ID_EDGEPORT_4:
-		case ION_DEVICE_ID_EDGEPORT_2:
-		case ION_DEVICE_ID_EDGEPORT_8_DUAL_CPU:
-		case ION_DEVICE_ID_EDGEPORT_8:
-		case ION_DEVICE_ID_EDGEPORT_421:
-		case ION_DEVICE_ID_EDGEPORT_21:
-		case ION_DEVICE_ID_EDGEPORT_2_DIN:
-		case ION_DEVICE_ID_EDGEPORT_4_DIN:
-		case ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU:
-			product_info->IsRS232 = 1;
-			break;
+	case ION_DEVICE_ID_EDGEPORT_COMPATIBLE:
+	case ION_DEVICE_ID_EDGEPORT_4T:
+	case ION_DEVICE_ID_EDGEPORT_4:
+	case ION_DEVICE_ID_EDGEPORT_2:
+	case ION_DEVICE_ID_EDGEPORT_8_DUAL_CPU:
+	case ION_DEVICE_ID_EDGEPORT_8:
+	case ION_DEVICE_ID_EDGEPORT_421:
+	case ION_DEVICE_ID_EDGEPORT_21:
+	case ION_DEVICE_ID_EDGEPORT_2_DIN:
+	case ION_DEVICE_ID_EDGEPORT_4_DIN:
+	case ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU:
+		product_info->IsRS232 = 1;
+		break;
 
-		case ION_DEVICE_ID_EDGEPORT_2I:				   // Edgeport/2 RS422/RS485
-			product_info->IsRS422 = 1;
-			product_info->IsRS485 = 1;
-			break;
+	case ION_DEVICE_ID_EDGEPORT_2I:	/* Edgeport/2 RS422/RS485 */
+		product_info->IsRS422 = 1;
+		product_info->IsRS485 = 1;
+		break;
 
-		case ION_DEVICE_ID_EDGEPORT_8I:				   // Edgeport/4 RS422
-		case ION_DEVICE_ID_EDGEPORT_4I:				   // Edgeport/4 RS422
-			product_info->IsRS422 = 1;
-			break;
+	case ION_DEVICE_ID_EDGEPORT_8I:	/* Edgeport/4 RS422 */
+	case ION_DEVICE_ID_EDGEPORT_4I:	/* Edgeport/4 RS422 */
+		product_info->IsRS422 = 1;
+		break;
 	}
 
 	dump_product_info(product_info);
@@ -520,32 +551,32 @@
 		ep->is_epic = 1;
 		memset(product_info, 0, sizeof(struct edgeport_product_info));
 
-		product_info->NumPorts			= epic->NumPorts;
-		product_info->ProdInfoVer		= 0;
-		product_info->FirmwareMajorVersion	= epic->MajorVersion;
-		product_info->FirmwareMinorVersion	= epic->MinorVersion;
-		product_info->FirmwareBuildNumber	= epic->BuildNumber;
-		product_info->iDownloadFile		= epic->iDownloadFile;
-		product_info->EpicVer			= epic->EpicVer;
-		product_info->Epic			= epic->Supports;
-		product_info->ProductId			= ION_DEVICE_ID_EDGEPORT_COMPATIBLE;
+		product_info->NumPorts = epic->NumPorts;
+		product_info->ProdInfoVer = 0;
+		product_info->FirmwareMajorVersion = epic->MajorVersion;
+		product_info->FirmwareMinorVersion = epic->MinorVersion;
+		product_info->FirmwareBuildNumber = epic->BuildNumber;
+		product_info->iDownloadFile = epic->iDownloadFile;
+		product_info->EpicVer = epic->EpicVer;
+		product_info->Epic = epic->Supports;
+		product_info->ProductId = ION_DEVICE_ID_EDGEPORT_COMPATIBLE;
 		dump_product_info(product_info);
 
 		bits = &ep->epic_descriptor.Supports;
 		dbg("**EPIC descriptor:");
 		dbg("  VendEnableSuspend: %s", bits->VendEnableSuspend	? "TRUE": "FALSE");
-		dbg("  IOSPOpen         : %s", bits->IOSPOpen		? "TRUE": "FALSE" );
-		dbg("  IOSPClose        : %s", bits->IOSPClose		? "TRUE": "FALSE" );
-		dbg("  IOSPChase        : %s", bits->IOSPChase		? "TRUE": "FALSE" );
-		dbg("  IOSPSetRxFlow    : %s", bits->IOSPSetRxFlow	? "TRUE": "FALSE" );
-		dbg("  IOSPSetTxFlow    : %s", bits->IOSPSetTxFlow	? "TRUE": "FALSE" );
-		dbg("  IOSPSetXChar     : %s", bits->IOSPSetXChar	? "TRUE": "FALSE" );
-		dbg("  IOSPRxCheck      : %s", bits->IOSPRxCheck	? "TRUE": "FALSE" );
-		dbg("  IOSPSetClrBreak  : %s", bits->IOSPSetClrBreak	? "TRUE": "FALSE" );
-		dbg("  IOSPWriteMCR     : %s", bits->IOSPWriteMCR	? "TRUE": "FALSE" );
-		dbg("  IOSPWriteLCR     : %s", bits->IOSPWriteLCR	? "TRUE": "FALSE" );
-		dbg("  IOSPSetBaudRate  : %s", bits->IOSPSetBaudRate	? "TRUE": "FALSE" );
-		dbg("  TrueEdgeport     : %s", bits->TrueEdgeport	? "TRUE": "FALSE" );
+		dbg("  IOSPOpen         : %s", bits->IOSPOpen		? "TRUE": "FALSE");
+		dbg("  IOSPClose        : %s", bits->IOSPClose		? "TRUE": "FALSE");
+		dbg("  IOSPChase        : %s", bits->IOSPChase		? "TRUE": "FALSE");
+		dbg("  IOSPSetRxFlow    : %s", bits->IOSPSetRxFlow	? "TRUE": "FALSE");
+		dbg("  IOSPSetTxFlow    : %s", bits->IOSPSetTxFlow	? "TRUE": "FALSE");
+		dbg("  IOSPSetXChar     : %s", bits->IOSPSetXChar	? "TRUE": "FALSE");
+		dbg("  IOSPRxCheck      : %s", bits->IOSPRxCheck	? "TRUE": "FALSE");
+		dbg("  IOSPSetClrBreak  : %s", bits->IOSPSetClrBreak	? "TRUE": "FALSE");
+		dbg("  IOSPWriteMCR     : %s", bits->IOSPWriteMCR	? "TRUE": "FALSE");
+		dbg("  IOSPWriteLCR     : %s", bits->IOSPWriteLCR	? "TRUE": "FALSE");
+		dbg("  IOSPSetBaudRate  : %s", bits->IOSPSetBaudRate	? "TRUE": "FALSE");
+		dbg("  TrueEdgeport     : %s", bits->TrueEdgeport	? "TRUE": "FALSE");
 	}
 
 	return result;
@@ -561,10 +592,10 @@
 
 /*****************************************************************************
  * edge_interrupt_callback
- *	this is the callback function for when we have received data on the 
+ *	this is the callback function for when we have received data on the
  *	interrupt endpoint.
  *****************************************************************************/
-static void edge_interrupt_callback (struct urb *urb)
+static void edge_interrupt_callback(struct urb *urb)
 {
 	struct edgeport_serial	*edge_serial = urb->context;
 	struct edgeport_port *edge_port;
@@ -589,17 +620,17 @@
 	case -ESHUTDOWN:
 		/* this urb is terminated, clean up */
 		dbg("%s - urb shutting down with status: %d",
-		    __func__, status);
+						__func__, status);
 		return;
 	default:
-		dbg("%s - nonzero urb status received: %d",
-		    __func__, status);
+		dbg("%s - nonzero urb status received: %d", __func__, status);
 		goto exit;
 	}
 
-	// process this interrupt-read even if there are no ports open
+	/* process this interrupt-read even if there are no ports open */
 	if (length) {
-		usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __func__, length, data);
+		usb_serial_debug_data(debug, &edge_serial->serial->dev->dev,
+						__func__, length, data);
 
 		if (length > 1) {
 			bytes_avail = data[0] | (data[1] << 8);
@@ -613,7 +644,8 @@
 					dbg("%s - posting a read", __func__);
 					edge_serial->read_in_progress = true;
 
-					/* we have pending bytes on the bulk in pipe, send a request */
+					/* we have pending bytes on the
+					   bulk in pipe, send a request */
 					edge_serial->read_urb->dev = edge_serial->serial->dev;
 					result = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
 					if (result) {
@@ -627,7 +659,8 @@
 		/* grab the txcredits for the ports if available */
 		position = 2;
 		portNumber = 0;
-		while ((position < length) && (portNumber < edge_serial->serial->num_ports)) {
+		while ((position < length) &&
+				(portNumber < edge_serial->serial->num_ports)) {
 			txCredits = data[position] | (data[position+1] << 8);
 			if (txCredits) {
 				port = edge_serial->serial->port[portNumber];
@@ -636,14 +669,19 @@
 					spin_lock(&edge_port->ep_lock);
 					edge_port->txCredits += txCredits;
 					spin_unlock(&edge_port->ep_lock);
-					dbg("%s - txcredits for port%d = %d", __func__, portNumber, edge_port->txCredits);
+					dbg("%s - txcredits for port%d = %d",
+							__func__, portNumber,
+							edge_port->txCredits);
 
-					/* tell the tty driver that something has changed */
-					if (edge_port->port->tty)
-						tty_wakeup(edge_port->port->tty);
+					/* tell the tty driver that something
+					   has changed */
+					if (edge_port->port->port.tty)
+						tty_wakeup(edge_port->port->port.tty);
 
-					// Since we have more credit, check if more data can be sent
-					send_more_port_data(edge_serial, edge_port);
+					/* Since we have more credit, check
+					   if more data can be sent */
+					send_more_port_data(edge_serial,
+								edge_port);
 				}
 			}
 			position += 2;
@@ -652,19 +690,20 @@
 	}
 
 exit:
-	result = usb_submit_urb (urb, GFP_ATOMIC);
-	if (result) {
-		dev_err(&urb->dev->dev, "%s - Error %d submitting control urb\n", __func__, result);
-	}
+	result = usb_submit_urb(urb, GFP_ATOMIC);
+	if (result)
+		dev_err(&urb->dev->dev,
+			"%s - Error %d submitting control urb\n",
+						__func__, result);
 }
 
 
 /*****************************************************************************
  * edge_bulk_in_callback
- *	this is the callback function for when we have received data on the 
+ *	this is the callback function for when we have received data on the
  *	bulk in endpoint.
  *****************************************************************************/
-static void edge_bulk_in_callback (struct urb *urb)
+static void edge_bulk_in_callback(struct urb *urb)
 {
 	struct edgeport_serial	*edge_serial = urb->context;
 	unsigned char		*data = urb->transfer_buffer;
@@ -689,16 +728,18 @@
 
 	raw_data_length = urb->actual_length;
 
-	usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __func__, raw_data_length, data);
+	usb_serial_debug_data(debug, &edge_serial->serial->dev->dev,
+					__func__, raw_data_length, data);
 
 	spin_lock(&edge_serial->es_lock);
 
 	/* decrement our rxBytes available by the number that we just got */
 	edge_serial->rxBytesAvail -= raw_data_length;
 
-	dbg("%s - Received = %d, rxBytesAvail %d", __func__, raw_data_length, edge_serial->rxBytesAvail);
+	dbg("%s - Received = %d, rxBytesAvail %d", __func__,
+				raw_data_length, edge_serial->rxBytesAvail);
 
-	process_rcvd_data (edge_serial, data, urb->actual_length);
+	process_rcvd_data(edge_serial, data, urb->actual_length);
 
 	/* check to see if there's any more data for us to read */
 	if (edge_serial->rxBytesAvail > 0) {
@@ -721,10 +762,10 @@
 
 /*****************************************************************************
  * edge_bulk_out_data_callback
- *	this is the callback function for when we have finished sending serial data
- *	on the bulk out endpoint.
+ *	this is the callback function for when we have finished sending
+ *	serial data on the bulk out endpoint.
  *****************************************************************************/
-static void edge_bulk_out_data_callback (struct urb *urb)
+static void edge_bulk_out_data_callback(struct urb *urb)
 {
 	struct edgeport_port *edge_port = urb->context;
 	struct tty_struct *tty;
@@ -737,27 +778,29 @@
 		    __func__, status);
 	}
 
-	tty = edge_port->port->tty;
+	tty = edge_port->port->port.tty;
 
 	if (tty && edge_port->open) {
-		/* let the tty driver wakeup if it has a special write_wakeup function */
+		/* let the tty driver wakeup if it has a special
+		   write_wakeup function */
 		tty_wakeup(tty);
 	}
 
-	// Release the Write URB
+	/* Release the Write URB */
 	edge_port->write_in_progress = false;
 
-	// Check if more data needs to be sent
-	send_more_port_data((struct edgeport_serial *)(usb_get_serial_data(edge_port->port->serial)), edge_port);
+	/* Check if more data needs to be sent */
+	send_more_port_data((struct edgeport_serial *)
+		(usb_get_serial_data(edge_port->port->serial)), edge_port);
 }
 
 
 /*****************************************************************************
  * BulkOutCmdCallback
- *	this is the callback function for when we have finished sending a command
- *	on the bulk out endpoint.
+ *	this is the callback function for when we have finished sending a
+ *	command	on the bulk out endpoint.
  *****************************************************************************/
-static void edge_bulk_out_cmd_callback (struct urb *urb)
+static void edge_bulk_out_cmd_callback(struct urb *urb)
 {
 	struct edgeport_port *edge_port = urb->context;
 	struct tty_struct *tty;
@@ -766,22 +809,24 @@
 	dbg("%s", __func__);
 
 	atomic_dec(&CmdUrbs);
-	dbg("%s - FREE URB %p (outstanding %d)", __func__, urb, atomic_read(&CmdUrbs));
+	dbg("%s - FREE URB %p (outstanding %d)", __func__,
+					urb, atomic_read(&CmdUrbs));
 
 
 	/* clean up the transfer buffer */
 	kfree(urb->transfer_buffer);
 
 	/* Free the command urb */
-	usb_free_urb (urb);
+	usb_free_urb(urb);
 
 	if (status) {
-		dbg("%s - nonzero write bulk status received: %d", __func__, status);
+		dbg("%s - nonzero write bulk status received: %d",
+							__func__, status);
 		return;
 	}
 
 	/* Get pointer to tty */
-	tty = edge_port->port->tty;
+	tty = edge_port->port->port.tty;
 
 	/* tell the tty driver that something has changed */
 	if (tty && edge_port->open)
@@ -803,7 +848,8 @@
  *	If successful, we return 0
  *	Otherwise we return a negative error number.
  *****************************************************************************/
-static int edge_open (struct usb_serial_port *port, struct file * filp)
+static int edge_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
 	struct usb_serial *serial;
@@ -815,55 +861,62 @@
 	if (edge_port == NULL)
 		return -ENODEV;
 
-	if (port->tty)
-		port->tty->low_latency = low_latency;
+	if (tty)
+		tty->low_latency = low_latency;
 
-	/* see if we've set up our endpoint info yet (can't set it up in edge_startup
-	   as the structures were not set up at that time.) */
+	/* see if we've set up our endpoint info yet (can't set it up
+	   in edge_startup as the structures were not set up at that time.) */
 	serial = port->serial;
 	edge_serial = usb_get_serial_data(serial);
-	if (edge_serial == NULL) {
+	if (edge_serial == NULL)
 		return -ENODEV;
-	}
 	if (edge_serial->interrupt_in_buffer == NULL) {
 		struct usb_serial_port *port0 = serial->port[0];
-		
+
 		/* not set up yet, so do it now */
-		edge_serial->interrupt_in_buffer = port0->interrupt_in_buffer;
-		edge_serial->interrupt_in_endpoint = port0->interrupt_in_endpointAddress;
+		edge_serial->interrupt_in_buffer =
+					port0->interrupt_in_buffer;
+		edge_serial->interrupt_in_endpoint =
+					port0->interrupt_in_endpointAddress;
 		edge_serial->interrupt_read_urb = port0->interrupt_in_urb;
 		edge_serial->bulk_in_buffer = port0->bulk_in_buffer;
-		edge_serial->bulk_in_endpoint = port0->bulk_in_endpointAddress;
+		edge_serial->bulk_in_endpoint =
+					port0->bulk_in_endpointAddress;
 		edge_serial->read_urb = port0->read_urb;
-		edge_serial->bulk_out_endpoint = port0->bulk_out_endpointAddress;
-	
+		edge_serial->bulk_out_endpoint =
+					port0->bulk_out_endpointAddress;
+
 		/* set up our interrupt urb */
 		usb_fill_int_urb(edge_serial->interrupt_read_urb,
-				 serial->dev,
-				 usb_rcvintpipe(serial->dev,
-					        port0->interrupt_in_endpointAddress),
-				 port0->interrupt_in_buffer,
-				 edge_serial->interrupt_read_urb->transfer_buffer_length,
-				 edge_interrupt_callback, edge_serial,
-				 edge_serial->interrupt_read_urb->interval);
-		
+		      serial->dev,
+		      usb_rcvintpipe(serial->dev,
+				port0->interrupt_in_endpointAddress),
+		      port0->interrupt_in_buffer,
+		      edge_serial->interrupt_read_urb->transfer_buffer_length,
+		      edge_interrupt_callback, edge_serial,
+		      edge_serial->interrupt_read_urb->interval);
+
 		/* set up our bulk in urb */
 		usb_fill_bulk_urb(edge_serial->read_urb, serial->dev,
-				  usb_rcvbulkpipe(serial->dev,
-					  	  port0->bulk_in_endpointAddress),
-				  port0->bulk_in_buffer,
-				  edge_serial->read_urb->transfer_buffer_length,
-				  edge_bulk_in_callback, edge_serial);
+			usb_rcvbulkpipe(serial->dev,
+				port0->bulk_in_endpointAddress),
+			port0->bulk_in_buffer,
+			edge_serial->read_urb->transfer_buffer_length,
+			edge_bulk_in_callback, edge_serial);
 		edge_serial->read_in_progress = false;
 
 		/* start interrupt read for this edgeport
-		 * this interrupt will continue as long as the edgeport is connected */
-		response = usb_submit_urb (edge_serial->interrupt_read_urb, GFP_KERNEL);
+		 * this interrupt will continue as long
+		 * as the edgeport is connected */
+		response = usb_submit_urb(edge_serial->interrupt_read_urb,
+								GFP_KERNEL);
 		if (response) {
-			dev_err(&port->dev, "%s - Error %d submitting control urb\n", __func__, response);
+			dev_err(&port->dev,
+				"%s - Error %d submitting control urb\n",
+							__func__, response);
 		}
 	}
-	
+
 	/* initialize our wait queues */
 	init_waitqueue_head(&edge_port->wait_open);
 	init_waitqueue_head(&edge_port->wait_chase);
@@ -871,26 +924,29 @@
 	init_waitqueue_head(&edge_port->wait_command);
 
 	/* initialize our icount structure */
-	memset (&(edge_port->icount), 0x00, sizeof(edge_port->icount));
+	memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount));
 
 	/* initialize our port settings */
-	edge_port->txCredits            = 0;			/* Can't send any data yet */
-	edge_port->shadowMCR            = MCR_MASTER_IE;	/* Must always set this bit to enable ints! */
+	edge_port->txCredits = 0;	/* Can't send any data yet */
+	/* Must always set this bit to enable ints! */
+	edge_port->shadowMCR = MCR_MASTER_IE;
 	edge_port->chaseResponsePending = false;
 
 	/* send a open port command */
 	edge_port->openPending = true;
 	edge_port->open        = false;
-	response = send_iosp_ext_cmd (edge_port, IOSP_CMD_OPEN_PORT, 0);
+	response = send_iosp_ext_cmd(edge_port, IOSP_CMD_OPEN_PORT, 0);
 
 	if (response < 0) {
-		dev_err(&port->dev, "%s - error sending open port command\n", __func__);
+		dev_err(&port->dev, "%s - error sending open port command\n",
+								__func__);
 		edge_port->openPending = false;
 		return -ENODEV;
 	}
 
 	/* now wait for the port to be completely opened */
-	wait_event_timeout(edge_port->wait_open, !edge_port->openPending, OPEN_TIMEOUT);
+	wait_event_timeout(edge_port->wait_open, !edge_port->openPending,
+								OPEN_TIMEOUT);
 
 	if (!edge_port->open) {
 		/* open timed out */
@@ -904,25 +960,26 @@
 	edge_port->txfifo.tail	= 0;
 	edge_port->txfifo.count	= 0;
 	edge_port->txfifo.size	= edge_port->maxTxCredits;
-	edge_port->txfifo.fifo	= kmalloc (edge_port->maxTxCredits, GFP_KERNEL);
+	edge_port->txfifo.fifo	= kmalloc(edge_port->maxTxCredits, GFP_KERNEL);
 
 	if (!edge_port->txfifo.fifo) {
 		dbg("%s - no memory", __func__);
-		edge_close (port, filp);
+		edge_close(tty, port, filp);
 		return -ENOMEM;
 	}
 
 	/* Allocate a URB for the write */
-	edge_port->write_urb = usb_alloc_urb (0, GFP_KERNEL);
+	edge_port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
 	edge_port->write_in_progress = false;
 
 	if (!edge_port->write_urb) {
 		dbg("%s - no memory", __func__);
-		edge_close (port, filp);
+		edge_close(tty, port, filp);
 		return -ENOMEM;
 	}
 
-	dbg("%s(%d) - Initialize TX fifo to %d bytes", __func__, port->number, edge_port->maxTxCredits);
+	dbg("%s(%d) - Initialize TX fifo to %d bytes",
+			__func__, port->number, edge_port->maxTxCredits);
 
 	dbg("%s exited", __func__);
 
@@ -948,27 +1005,28 @@
 	int loop = 10;
 
 	while (1) {
-		// Save Last credits
+		/* Save Last credits */
 		lastCredits = edge_port->txCredits;
 
-		// Did we get our Chase response
+		/* Did we get our Chase response */
 		if (!edge_port->chaseResponsePending) {
 			dbg("%s - Got Chase Response", __func__);
 
-			// did we get all of our credit back?
-			if (edge_port->txCredits == edge_port->maxTxCredits ) {
+			/* did we get all of our credit back? */
+			if (edge_port->txCredits == edge_port->maxTxCredits) {
 				dbg("%s - Got all credits", __func__);
 				return;
 			}
 		}
 
-		// Block the thread for a while
-		prepare_to_wait(&edge_port->wait_chase, &wait, TASK_UNINTERRUPTIBLE);
+		/* Block the thread for a while */
+		prepare_to_wait(&edge_port->wait_chase, &wait,
+						TASK_UNINTERRUPTIBLE);
 		schedule_timeout(timeout);
 		finish_wait(&edge_port->wait_chase, &wait);
 
 		if (lastCredits == edge_port->txCredits) {
-			// No activity.. count down.
+			/* No activity.. count down. */
 			loop--;
 			if (loop == 0) {
 				edge_port->chaseResponsePending = false;
@@ -976,8 +1034,9 @@
 				return;
 			}
 		} else {
-			// Reset timeout value back to 10 seconds
-			dbg("%s - Last %d, Current %d", __func__, lastCredits, edge_port->txCredits);
+			/* Reset timeout value back to 10 seconds */
+			dbg("%s - Last %d, Current %d", __func__,
+					lastCredits, edge_port->txCredits);
 			loop = 10;
 		}
 	}
@@ -994,7 +1053,7 @@
  *		3. A timeout of 3 seconds without activity has expired
  *
  ************************************************************************/
-static void block_until_tx_empty (struct edgeport_port *edge_port)
+static void block_until_tx_empty(struct edgeport_port *edge_port)
 {
 	DEFINE_WAIT(wait);
 	struct TxFifo *fifo = &edge_port->txfifo;
@@ -1003,31 +1062,32 @@
 	int loop = 30;
 
 	while (1) {
-		// Save Last count
+		/* Save Last count */
 		lastCount = fifo->count;
 
-		// Is the Edgeport Buffer empty?
+		/* Is the Edgeport Buffer empty? */
 		if (lastCount == 0) {
 			dbg("%s - TX Buffer Empty", __func__);
 			return;
 		}
 
-		// Block the thread for a while
-		prepare_to_wait (&edge_port->wait_chase, &wait, TASK_UNINTERRUPTIBLE);
+		/* Block the thread for a while */
+		prepare_to_wait(&edge_port->wait_chase, &wait,
+						TASK_UNINTERRUPTIBLE);
 		schedule_timeout(timeout);
 		finish_wait(&edge_port->wait_chase, &wait);
 
 		dbg("%s wait", __func__);
 
 		if (lastCount == fifo->count) {
-			// No activity.. count down.
+			/* No activity.. count down. */
 			loop--;
 			if (loop == 0) {
 				dbg("%s - TIMEOUT", __func__);
 				return;
 			}
 		} else {
-			// Reset timeout value back to seconds
+			/* Reset timeout value back to seconds */
 			loop = 30;
 		}
 	}
@@ -1038,20 +1098,21 @@
  * edge_close
  *	this function is called by the tty driver when a port is closed
  *****************************************************************************/
-static void edge_close (struct usb_serial_port *port, struct file * filp)
+static void edge_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct edgeport_serial *edge_serial;
 	struct edgeport_port *edge_port;
 	int status;
 
 	dbg("%s - port %d", __func__, port->number);
-			 
+
 	edge_serial = usb_get_serial_data(port->serial);
 	edge_port = usb_get_serial_port_data(port);
-	if ((edge_serial == NULL) || (edge_port == NULL))
+	if (edge_serial == NULL || edge_port == NULL)
 		return;
-	
-	// block until tx is empty
+
+	/* block until tx is empty */
 	block_until_tx_empty(edge_port);
 
 	edge_port->closePending = true;
@@ -1063,13 +1124,12 @@
 		edge_port->chaseResponsePending = true;
 
 		dbg("%s - Sending IOSP_CMD_CHASE_PORT", __func__);
-		status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
-		if (status == 0) {
-			// block until chase finished
+		status = send_iosp_ext_cmd(edge_port, IOSP_CMD_CHASE_PORT, 0);
+		if (status == 0)
+			/* block until chase finished */
 			block_until_chase_response(edge_port);
-		} else {
+		else
 			edge_port->chaseResponsePending = false;
-		}
 	}
 
 	if ((!edge_serial->is_epic) ||
@@ -1077,10 +1137,10 @@
 	     (edge_serial->epic_descriptor.Supports.IOSPClose))) {
 	       /* close the port */
 		dbg("%s - Sending IOSP_CMD_CLOSE_PORT", __func__);
-		send_iosp_ext_cmd (edge_port, IOSP_CMD_CLOSE_PORT, 0);
+		send_iosp_ext_cmd(edge_port, IOSP_CMD_CLOSE_PORT, 0);
 	}
 
-	//port->close = true;
+	/* port->close = true; */
 	edge_port->closePending = false;
 	edge_port->open = false;
 	edge_port->openPending = false;
@@ -1088,7 +1148,8 @@
 	usb_kill_urb(edge_port->write_urb);
 
 	if (edge_port->write_urb) {
-		/* if this urb had a transfer buffer already (old transfer) free it */
+		/* if this urb had a transfer buffer already
+				(old transfer) free it */
 		kfree(edge_port->write_urb->transfer_buffer);
 		usb_free_urb(edge_port->write_urb);
 		edge_port->write_urb = NULL;
@@ -1097,16 +1158,17 @@
 	edge_port->txfifo.fifo = NULL;
 
 	dbg("%s exited", __func__);
-}   
+}
 
 /*****************************************************************************
  * SerialWrite
- *	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.
+ *	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 edge_write (struct usb_serial_port *port, const unsigned char *data, int count)
+static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
+					const unsigned char *data, int count)
 {
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
 	struct TxFifo *fifo;
@@ -1121,66 +1183,76 @@
 	if (edge_port == NULL)
 		return -ENODEV;
 
-	// get a pointer to the Tx fifo
+	/* get a pointer to the Tx fifo */
 	fifo = &edge_port->txfifo;
 
 	spin_lock_irqsave(&edge_port->ep_lock, flags);
 
-	// calculate number of bytes to put in fifo
-	copySize = min ((unsigned int)count, (edge_port->txCredits - fifo->count));
+	/* calculate number of bytes to put in fifo */
+	copySize = min((unsigned int)count,
+				(edge_port->txCredits - fifo->count));
 
-	dbg("%s(%d) of %d byte(s) Fifo room  %d -- will copy %d bytes", __func__,
-	    port->number, count, edge_port->txCredits - fifo->count, copySize);
+	dbg("%s(%d) of %d byte(s) Fifo room  %d -- will copy %d bytes",
+			__func__, port->number, count,
+			edge_port->txCredits - fifo->count, copySize);
 
-	/* catch writes of 0 bytes which the tty driver likes to give us, and when txCredits is empty */
+	/* catch writes of 0 bytes which the tty driver likes to give us,
+	   and when txCredits is empty */
 	if (copySize == 0) {
 		dbg("%s - copySize = Zero", __func__);
 		goto finish_write;
 	}
 
-	// queue the data	
-	// since we can never overflow the buffer we do not have to check for full condition
-
-	// the copy is done is two parts -- first fill to the end of the buffer
-	// then copy the reset from the start of the buffer 
-
+	/* queue the data
+	 * since we can never overflow the buffer we do not have to check for a
+	 * full condition
+	 *
+	 * the copy is done is two parts -- first fill to the end of the buffer
+	 * then copy the reset from the start of the buffer
+	 */
 	bytesleft = fifo->size - fifo->head;
-	firsthalf = min (bytesleft, copySize);
-	dbg("%s - copy %d bytes of %d into fifo ", __func__, firsthalf, bytesleft);
+	firsthalf = min(bytesleft, copySize);
+	dbg("%s - copy %d bytes of %d into fifo ", __func__,
+					firsthalf, bytesleft);
 
 	/* now copy our data */
 	memcpy(&fifo->fifo[fifo->head], data, firsthalf);
-	usb_serial_debug_data(debug, &port->dev, __func__, firsthalf, &fifo->fifo[fifo->head]);
+	usb_serial_debug_data(debug, &port->dev, __func__,
+					firsthalf, &fifo->fifo[fifo->head]);
 
-	// update the index and size
+	/* update the index and size */
 	fifo->head  += firsthalf;
 	fifo->count += firsthalf;
 
-	// wrap the index
-	if (fifo->head == fifo->size) {
+	/* wrap the index */
+	if (fifo->head == fifo->size)
 		fifo->head = 0;
-	}
 
 	secondhalf = copySize-firsthalf;
 
 	if (secondhalf) {
 		dbg("%s - copy rest of data %d", __func__, secondhalf);
 		memcpy(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf);
-		usb_serial_debug_data(debug, &port->dev, __func__, secondhalf, &fifo->fifo[fifo->head]);
-		// update the index and size
+		usb_serial_debug_data(debug, &port->dev, __func__,
+					secondhalf, &fifo->fifo[fifo->head]);
+		/* update the index and size */
 		fifo->count += secondhalf;
 		fifo->head  += secondhalf;
-		// No need to check for wrap since we can not get to end of fifo in this part
+		/* No need to check for wrap since we can not get to end of
+		 * the fifo in this part
+		 */
 	}
 
 finish_write:
 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
 
-	send_more_port_data((struct edgeport_serial *)usb_get_serial_data(port->serial), edge_port);
+	send_more_port_data((struct edgeport_serial *)
+			usb_get_serial_data(port->serial), edge_port);
 
-	dbg("%s wrote %d byte(s) TxCredits %d, Fifo %d", __func__, copySize, edge_port->txCredits, fifo->count);
+	dbg("%s wrote %d byte(s) TxCredits %d, Fifo %d", __func__,
+				copySize, edge_port->txCredits, fifo->count);
 
-	return copySize;   
+	return copySize;
 }
 
 
@@ -1197,7 +1269,8 @@
  *	can transmit more.
  *
  ************************************************************************/
-static void send_more_port_data(struct edgeport_serial *edge_serial, struct edgeport_port *edge_port)
+static void send_more_port_data(struct edgeport_serial *edge_serial,
+					struct edgeport_port *edge_port)
 {
 	struct TxFifo	*fifo = &edge_port->txfifo;
 	struct urb	*urb;
@@ -1216,67 +1289,78 @@
 	if (edge_port->write_in_progress ||
 	    !edge_port->open             ||
 	    (fifo->count == 0)) {
-		dbg("%s(%d) EXIT - fifo %d, PendingWrite = %d", __func__, edge_port->port->number, fifo->count, edge_port->write_in_progress);
+		dbg("%s(%d) EXIT - fifo %d, PendingWrite = %d",
+				__func__, edge_port->port->number,
+				fifo->count, edge_port->write_in_progress);
 		goto exit_send;
 	}
 
-	// since the amount of data in the fifo will always fit into the
-	// edgeport buffer we do not need to check the write length
-
-	//	Do we have enough credits for this port to make it worthwhile
-	//	to bother queueing a write. If it's too small, say a few bytes,
-	//	it's better to wait for more credits so we can do a larger
-	//	write.
-	if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits,EDGE_FW_BULK_MAX_PACKET_SIZE)) {
-		dbg("%s(%d) Not enough credit - fifo %d TxCredit %d", __func__, edge_port->port->number, fifo->count, edge_port->txCredits );
+	/* since the amount of data in the fifo will always fit into the
+	 * edgeport buffer we do not need to check the write length
+	 *
+	 * Do we have enough credits for this port to make it worthwhile
+	 * to bother queueing a write. If it's too small, say a few bytes,
+	 * it's better to wait for more credits so we can do a larger write.
+	 */
+	if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits, EDGE_FW_BULK_MAX_PACKET_SIZE)) {
+		dbg("%s(%d) Not enough credit - fifo %d TxCredit %d",
+			__func__, edge_port->port->number, fifo->count,
+			edge_port->txCredits);
 		goto exit_send;
 	}
 
-	// lock this write
+	/* lock this write */
 	edge_port->write_in_progress = true;
 
-	// get a pointer to the write_urb
+	/* get a pointer to the write_urb */
 	urb = edge_port->write_urb;
 
 	/* make sure transfer buffer is freed */
 	kfree(urb->transfer_buffer);
 	urb->transfer_buffer = NULL;
 
-	/* build the data header for the buffer and port that we are about to send out */
+	/* build the data header for the buffer and port that we are about
+	   to send out */
 	count = fifo->count;
-	buffer = kmalloc (count+2, GFP_ATOMIC);
+	buffer = kmalloc(count+2, GFP_ATOMIC);
 	if (buffer == NULL) {
-		dev_err(&edge_port->port->dev, "%s - no more kernel memory...\n", __func__);
+		dev_err(&edge_port->port->dev,
+				"%s - no more kernel memory...\n", __func__);
 		edge_port->write_in_progress = false;
 		goto exit_send;
 	}
-	buffer[0] = IOSP_BUILD_DATA_HDR1 (edge_port->port->number - edge_port->port->serial->minor, count);
-	buffer[1] = IOSP_BUILD_DATA_HDR2 (edge_port->port->number - edge_port->port->serial->minor, count);
+	buffer[0] = IOSP_BUILD_DATA_HDR1(edge_port->port->number
+				- edge_port->port->serial->minor, count);
+	buffer[1] = IOSP_BUILD_DATA_HDR2(edge_port->port->number
+				- edge_port->port->serial->minor, count);
 
 	/* now copy our data */
 	bytesleft =  fifo->size - fifo->tail;
-	firsthalf = min (bytesleft, count);
+	firsthalf = min(bytesleft, count);
 	memcpy(&buffer[2], &fifo->fifo[fifo->tail], firsthalf);
 	fifo->tail  += firsthalf;
 	fifo->count -= firsthalf;
-	if (fifo->tail == fifo->size) {
+	if (fifo->tail == fifo->size)
 		fifo->tail = 0;
-	}
 
 	secondhalf = count-firsthalf;
 	if (secondhalf) {
-		memcpy(&buffer[2+firsthalf], &fifo->fifo[fifo->tail], secondhalf);
+		memcpy(&buffer[2+firsthalf], &fifo->fifo[fifo->tail],
+								secondhalf);
 		fifo->tail  += secondhalf;
 		fifo->count -= secondhalf;
 	}
 
 	if (count)
-		usb_serial_debug_data(debug, &edge_port->port->dev, __func__, count, &buffer[2]);
+		usb_serial_debug_data(debug, &edge_port->port->dev,
+						__func__, count, &buffer[2]);
 
 	/* fill up the urb with all of our data and submit it */
-	usb_fill_bulk_urb (urb, edge_serial->serial->dev, 
-		       usb_sndbulkpipe(edge_serial->serial->dev, edge_serial->bulk_out_endpoint),
-		       buffer, count+2, edge_bulk_out_data_callback, edge_port);
+	usb_fill_bulk_urb(urb, edge_serial->serial->dev,
+			usb_sndbulkpipe(edge_serial->serial->dev,
+					edge_serial->bulk_out_endpoint),
+			buffer, count+2,
+			edge_bulk_out_data_callback, edge_port);
 
 	/* decrement the number of credits we have by the number we just sent */
 	edge_port->txCredits -= count;
@@ -1286,14 +1370,17 @@
 	status = usb_submit_urb(urb, GFP_ATOMIC);
 	if (status) {
 		/* something went wrong */
-		dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write bulk) failed, status = %d, data lost\n", __func__, status);
+		dev_err(&edge_port->port->dev,
+			"%s - usb_submit_urb(write bulk) failed, status = %d, data lost\n",
+				__func__, status);
 		edge_port->write_in_progress = false;
 
 		/* revert the credits as something bad happened. */
 		edge_port->txCredits += count;
 		edge_port->icount.tx -= count;
 	}
-	dbg("%s wrote %d byte(s) TxCredit %d, Fifo %d", __func__, count, edge_port->txCredits, fifo->count);
+	dbg("%s wrote %d byte(s) TxCredit %d, Fifo %d",
+			__func__, count, edge_port->txCredits, fifo->count);
 
 exit_send:
 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
@@ -1302,14 +1389,14 @@
 
 /*****************************************************************************
  * edge_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
- *	(the txCredits), 
- *	Otherwise we return a negative error number.
+ *	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	(the txCredits)
+ *	otherwise we return a negative error number.
  *****************************************************************************/
-static int edge_write_room (struct usb_serial_port *port)
+static int edge_write_room(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
 	int room;
 	unsigned long flags;
@@ -1317,18 +1404,18 @@
 	dbg("%s", __func__);
 
 	if (edge_port == NULL)
-		return -ENODEV;
+		return 0;
 	if (edge_port->closePending)
-		return -ENODEV;
+		return 0;
 
 	dbg("%s - port %d", __func__, port->number);
 
 	if (!edge_port->open) {
 		dbg("%s - port not opened", __func__);
-		return -EINVAL;
+		return 0;
 	}
 
-	// total of both buffers is still txCredit
+	/* total of both buffers is still txCredit */
 	spin_lock_irqsave(&edge_port->ep_lock, flags);
 	room = edge_port->txCredits - edge_port->txfifo.count;
 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
@@ -1340,15 +1427,16 @@
 
 /*****************************************************************************
  * edge_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, 
+ *	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 edge_chars_in_buffer (struct usb_serial_port *port)
+static int edge_chars_in_buffer(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
 	int num_chars;
 	unsigned long flags;
@@ -1356,20 +1444,22 @@
 	dbg("%s", __func__);
 
 	if (edge_port == NULL)
-		return -ENODEV;
+		return 0;
 	if (edge_port->closePending)
-		return -ENODEV;
+		return 0;
 
 	if (!edge_port->open) {
 		dbg("%s - port not opened", __func__);
-		return -EINVAL;
+		return 0;
 	}
 
 	spin_lock_irqsave(&edge_port->ep_lock, flags);
-	num_chars = edge_port->maxTxCredits - edge_port->txCredits + edge_port->txfifo.count;
+	num_chars = edge_port->maxTxCredits - edge_port->txCredits +
+						edge_port->txfifo.count;
 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
 	if (num_chars) {
-		dbg("%s(port %d) - returns %d", __func__, port->number, num_chars);
+		dbg("%s(port %d) - returns %d", __func__,
+						port->number, num_chars);
 	}
 
 	return num_chars;
@@ -1381,10 +1471,10 @@
  *	this function is called by the tty driver when it wants to stop the data
  *	being read from the port.
  *****************************************************************************/
-static void edge_throttle (struct usb_serial_port *port)
+static void edge_throttle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
-	struct tty_struct *tty;
 	int status;
 
 	dbg("%s - port %d", __func__, port->number);
@@ -1397,28 +1487,21 @@
 		return;
 	}
 
-	tty = port->tty;
-	if (!tty) {
-		dbg ("%s - no tty available", __func__);
-		return;
-	}
-
 	/* if we are implementing XON/XOFF, send the stop character */
 	if (I_IXOFF(tty)) {
 		unsigned char stop_char = STOP_CHAR(tty);
-		status = edge_write (port, &stop_char, 1);
-		if (status <= 0) {
+		status = edge_write(tty, port, &stop_char, 1);
+		if (status <= 0)
 			return;
-		}
 	}
 
 	/* if we are implementing RTS/CTS, toggle that line */
 	if (tty->termios->c_cflag & CRTSCTS) {
 		edge_port->shadowMCR &= ~MCR_RTS;
-		status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR);
-		if (status != 0) {
+		status = send_cmd_write_uart_register(edge_port, MCR,
+							edge_port->shadowMCR);
+		if (status != 0)
 			return;
-		}
 	}
 
 	return;
@@ -1427,13 +1510,13 @@
 
 /*****************************************************************************
  * edge_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)
+ *	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 edge_unthrottle (struct usb_serial_port *port)
+static void edge_unthrottle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
-	struct tty_struct *tty;
 	int status;
 
 	dbg("%s - port %d", __func__, port->number);
@@ -1446,43 +1529,31 @@
 		return;
 	}
 
-	tty = port->tty;
-	if (!tty) {
-		dbg ("%s - no tty available", __func__);
-		return;
-	}
-
 	/* if we are implementing XON/XOFF, send the start character */
 	if (I_IXOFF(tty)) {
 		unsigned char start_char = START_CHAR(tty);
-		status = edge_write (port, &start_char, 1);
-		if (status <= 0) {
+		status = edge_write(tty, port, &start_char, 1);
+		if (status <= 0)
 			return;
-		}
 	}
-
 	/* if we are implementing RTS/CTS, toggle that line */
 	if (tty->termios->c_cflag & CRTSCTS) {
 		edge_port->shadowMCR |= MCR_RTS;
-		status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR);
-		if (status != 0) {
-			return;
-		}
+		send_cmd_write_uart_register(edge_port, MCR,
+						edge_port->shadowMCR);
 	}
-
-	return;
 }
 
 
 /*****************************************************************************
  * SerialSetTermios
- *	this function is called by the tty driver when it wants to change the termios structure
+ *	this function is called by the tty driver when it wants to change
+ * the termios structure
  *****************************************************************************/
-static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
+static void edge_set_termios(struct tty_struct *tty,
+	struct usb_serial_port *port, struct ktermios *old_termios)
 {
-	/* FIXME: This function appears unused ?? */
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
-	struct tty_struct *tty = port->tty;
 	unsigned int cflag;
 
 	cflag = tty->termios->c_cflag;
@@ -1502,9 +1573,7 @@
 	}
 
 	/* change the port settings to the new ones specified */
-	change_port_settings (edge_port, old_termios);
-
-	return;
+	change_port_settings(tty, edge_port, old_termios);
 }
 
 
@@ -1516,9 +1585,10 @@
  * 	    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. 
+ * 	    allows an RS485 driver to be written in user space.
  *****************************************************************************/
-static int get_lsr_info(struct edgeport_port *edge_port, unsigned int __user *value)
+static int get_lsr_info(struct edgeport_port *edge_port,
+						unsigned int __user *value)
 {
 	unsigned int result = 0;
 	unsigned long flags;
@@ -1536,25 +1606,10 @@
 	return 0;
 }
 
-static int get_number_bytes_avail(struct edgeport_port *edge_port, unsigned int __user *value)
+static int edge_tiocmset(struct tty_struct *tty, struct file *file,
+					unsigned int set, unsigned int clear)
 {
-	unsigned int result = 0;
-	struct tty_struct *tty = edge_port->port->tty;
-
-	if (!tty)
-		return -ENOIOCTLCMD;
-
-	result = tty->read_cnt;
-
-	dbg("%s(%d) = %d", __func__,  edge_port->port->number, result);
-	if (copy_to_user(value, &result, sizeof(int)))
-		return -EFAULT;
-	//return 0;
-	return -ENOIOCTLCMD;
-}
-
-static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear)
-{
+	struct usb_serial_port *port = tty->driver_data;
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
 	unsigned int mcr;
 
@@ -1582,8 +1637,9 @@
 	return 0;
 }
 
-static int edge_tiocmget(struct usb_serial_port *port, struct file *file)
+static int edge_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
 	unsigned int result = 0;
 	unsigned int msr;
@@ -1606,7 +1662,8 @@
 	return result;
 }
 
-static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct __user *retinfo)
+static int get_serial_info(struct edgeport_port *edge_port,
+				struct serial_struct __user *retinfo)
 {
 	struct serial_struct tmp;
 
@@ -1624,9 +1681,6 @@
 	tmp.baud_base		= 9600;
 	tmp.close_delay		= 5*HZ;
 	tmp.closing_wait	= 30*HZ;
-//	tmp.custom_divisor	= state->custom_divisor;
-//	tmp.hub6		= state->hub6;
-//	tmp.io_type		= state->io_type;
 
 	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
 		return -EFAULT;
@@ -1639,8 +1693,10 @@
  * SerialIoctl
  *	this function handles any ioctl calls to the driver
  *****************************************************************************/
-static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg)
+static int edge_ioctl(struct tty_struct *tty, struct file *file,
+					unsigned int cmd, unsigned long arg)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	DEFINE_WAIT(wait);
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
 	struct async_icount cnow;
@@ -1650,71 +1706,61 @@
 	dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
 
 	switch (cmd) {
-		// return number of bytes available
-		case TIOCINQ:
-			dbg("%s (%d) TIOCINQ", __func__,  port->number);
-			return get_number_bytes_avail(edge_port, (unsigned int __user *) arg);
-			break;
+	case TIOCSERGETLSR:
+		dbg("%s (%d) TIOCSERGETLSR", __func__,  port->number);
+		return get_lsr_info(edge_port, (unsigned int __user *) arg);
 
-		case TIOCSERGETLSR:
-			dbg("%s (%d) TIOCSERGETLSR", __func__,  port->number);
-			return get_lsr_info(edge_port, (unsigned int __user *) arg);
-			return 0;
+	case TIOCGSERIAL:
+		dbg("%s (%d) TIOCGSERIAL", __func__,  port->number);
+		return get_serial_info(edge_port, (struct serial_struct __user *) arg);
 
-		case TIOCGSERIAL:
-			dbg("%s (%d) TIOCGSERIAL", __func__,  port->number);
-			return get_serial_info(edge_port, (struct serial_struct __user *) arg);
-
-		case TIOCSSERIAL:
-			dbg("%s (%d) TIOCSSERIAL", __func__,  port->number);
-			break;
-
-		case TIOCMIWAIT:
-			dbg("%s (%d) TIOCMIWAIT", __func__,  port->number);
-			cprev = edge_port->icount;
-			while (1) {
-				prepare_to_wait(&edge_port->delta_msr_wait, &wait, TASK_INTERRUPTIBLE);
-				schedule();
-				finish_wait(&edge_port->delta_msr_wait, &wait);
-				/* see if a signal did it */
-				if (signal_pending(current))
-					return -ERESTARTSYS;
-				cnow = edge_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:
+	case TIOCMIWAIT:
+		dbg("%s (%d) TIOCMIWAIT", __func__,  port->number);
+		cprev = edge_port->icount;
+		while (1) {
+			prepare_to_wait(&edge_port->delta_msr_wait,
+						&wait, TASK_INTERRUPTIBLE);
+			schedule();
+			finish_wait(&edge_port->delta_msr_wait, &wait);
+			/* see if a signal did it */
+			if (signal_pending(current))
+				return -ERESTARTSYS;
 			cnow = edge_port->icount;
-			memset(&icount, 0, sizeof(icount));
-			icount.cts = cnow.cts;
-			icount.dsr = cnow.dsr;
-			icount.rng = cnow.rng;
-			icount.dcd = cnow.dcd;
-			icount.rx = cnow.rx;
-			icount.tx = cnow.tx;
-			icount.frame = cnow.frame;
-			icount.overrun = cnow.overrun;
-			icount.parity = cnow.parity;
-			icount.brk = cnow.brk;
-			icount.buf_overrun = cnow.buf_overrun;
+			if (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;
 
-			dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,  port->number, icount.rx, icount.tx );
-			if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))
-				return -EFAULT;
-			return 0;
+	case TIOCGICOUNT:
+		cnow = edge_port->icount;
+		memset(&icount, 0, sizeof(icount));
+		icount.cts = cnow.cts;
+		icount.dsr = cnow.dsr;
+		icount.rng = cnow.rng;
+		icount.dcd = cnow.dcd;
+		icount.rx = cnow.rx;
+		icount.tx = cnow.tx;
+		icount.frame = cnow.frame;
+		icount.overrun = cnow.overrun;
+		icount.parity = cnow.parity;
+		icount.brk = cnow.brk;
+		icount.buf_overrun = cnow.buf_overrun;
+
+		dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d",
+				__func__,  port->number, icount.rx, icount.tx);
+		if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))
+			return -EFAULT;
+		return 0;
 	}
-
 	return -ENOIOCTLCMD;
 }
 
@@ -1723,8 +1769,9 @@
  * SerialBreak
  *	this function sends a break to the port
  *****************************************************************************/
-static void edge_break (struct usb_serial_port *port, int break_state)
+static void edge_break(struct tty_struct *tty, int break_state)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
 	struct edgeport_serial *edge_serial = usb_get_serial_data(port->serial);
 	int status;
@@ -1736,9 +1783,9 @@
 		edge_port->chaseResponsePending = true;
 
 		dbg("%s - Sending IOSP_CMD_CHASE_PORT", __func__);
-		status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
+		status = send_iosp_ext_cmd(edge_port, IOSP_CMD_CHASE_PORT, 0);
 		if (status == 0) {
-			// block until chase finished
+			/* block until chase finished */
 			block_until_chase_response(edge_port);
 		} else {
 			edge_port->chaseResponsePending = false;
@@ -1750,14 +1797,16 @@
 	     (edge_serial->epic_descriptor.Supports.IOSPSetClrBreak))) {
 		if (break_state == -1) {
 			dbg("%s - Sending IOSP_CMD_SET_BREAK", __func__);
-			status = send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_BREAK, 0);
+			status = send_iosp_ext_cmd(edge_port,
+						IOSP_CMD_SET_BREAK, 0);
 		} else {
 			dbg("%s - Sending IOSP_CMD_CLEAR_BREAK", __func__);
-			status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CLEAR_BREAK, 0);
+			status = send_iosp_ext_cmd(edge_port,
+						IOSP_CMD_CLEAR_BREAK, 0);
 		}
-		if (status) {
-			dbg("%s - error sending break set/clear command.", __func__);
-		}
+		if (status)
+			dbg("%s - error sending break set/clear command.",
+				__func__);
 	}
 
 	return;
@@ -1768,7 +1817,8 @@
  * process_rcvd_data
  *	this function handles the data received on the bulk in pipe.
  *****************************************************************************/
-static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned char * buffer, __u16 bufferLength)
+static void process_rcvd_data(struct edgeport_serial *edge_serial,
+				unsigned char *buffer, __u16 bufferLength)
 {
 	struct usb_serial_port *port;
 	struct edgeport_port *edge_port;
@@ -1789,105 +1839,123 @@
 		lastBufferLength = bufferLength;
 
 		switch (edge_serial->rxState) {
-			case EXPECT_HDR1:
-				edge_serial->rxHeader1 = *buffer;
-				++buffer;
-				--bufferLength;
+		case EXPECT_HDR1:
+			edge_serial->rxHeader1 = *buffer;
+			++buffer;
+			--bufferLength;
 
-				if (bufferLength == 0) {
-					edge_serial->rxState = EXPECT_HDR2;
-					break;
-				}
-				/* otherwise, drop on through */
-
-			case EXPECT_HDR2:
-				edge_serial->rxHeader2 = *buffer;
-				++buffer;
-				--bufferLength;
-
-				dbg("%s - Hdr1=%02X Hdr2=%02X", __func__, edge_serial->rxHeader1, edge_serial->rxHeader2);
-
-				// Process depending on whether this header is
-				// data or status
-
-				if (IS_CMD_STAT_HDR(edge_serial->rxHeader1)) {
-					// Decode this status header and goto EXPECT_HDR1 (if we
-					// can process the status with only 2 bytes), or goto
-					// EXPECT_HDR3 to get the third byte.
-
-					edge_serial->rxPort       = IOSP_GET_HDR_PORT(edge_serial->rxHeader1);
-					edge_serial->rxStatusCode = IOSP_GET_STATUS_CODE(edge_serial->rxHeader1);
-
-					if (!IOSP_STATUS_IS_2BYTE(edge_serial->rxStatusCode)) {
-						// This status needs additional bytes. Save what we have
-						// and then wait for more data.
-						edge_serial->rxStatusParam = edge_serial->rxHeader2;
-
-						edge_serial->rxState = EXPECT_HDR3;
-						break;
-					}
-
-					// We have all the header bytes, process the status now
-					process_rcvd_status (edge_serial, edge_serial->rxHeader2, 0);
-					edge_serial->rxState = EXPECT_HDR1;
-					break;
-				} else {
-					edge_serial->rxPort = IOSP_GET_HDR_PORT(edge_serial->rxHeader1);
-					edge_serial->rxBytesRemaining = IOSP_GET_HDR_DATA_LEN(edge_serial->rxHeader1, edge_serial->rxHeader2);
-
-					dbg("%s - Data for Port %u Len %u", __func__, edge_serial->rxPort, edge_serial->rxBytesRemaining);
-
-					//ASSERT( DevExt->RxPort < DevExt->NumPorts );
-					//ASSERT( DevExt->RxBytesRemaining < IOSP_MAX_DATA_LENGTH );
-
-					if (bufferLength == 0 ) {
-						edge_serial->rxState = EXPECT_DATA;
-						break;
-					}
-					// Else, drop through
-				}
-
-			case EXPECT_DATA:	// Expect data
-
-				if (bufferLength < edge_serial->rxBytesRemaining) {
-					rxLen = bufferLength;
-					edge_serial->rxState = EXPECT_DATA;	// Expect data to start next buffer
-				} else {
-					// BufLen >= RxBytesRemaining
-					rxLen = edge_serial->rxBytesRemaining;
-					edge_serial->rxState = EXPECT_HDR1;	// Start another header next time
-				}
-
-				bufferLength -= rxLen;
-				edge_serial->rxBytesRemaining -= rxLen;
-
-				/* spit this data back into the tty driver if this port is open */
-				if (rxLen) {
-					port = edge_serial->serial->port[edge_serial->rxPort];
-					edge_port = usb_get_serial_port_data(port);
-					if (edge_port->open) {
-						tty = edge_port->port->tty;
-						if (tty) {
-							dbg("%s - Sending %d bytes to TTY for port %d", __func__, rxLen, edge_serial->rxPort);
-							edge_tty_recv(&edge_serial->serial->dev->dev, tty, buffer, rxLen);
-						}
-						edge_port->icount.rx += rxLen;
-					}
-					buffer += rxLen;
-				}
-
+			if (bufferLength == 0) {
+				edge_serial->rxState = EXPECT_HDR2;
 				break;
+			}
+			/* otherwise, drop on through */
+		case EXPECT_HDR2:
+			edge_serial->rxHeader2 = *buffer;
+			++buffer;
+			--bufferLength;
 
-			case EXPECT_HDR3:			// Expect 3rd byte of status header
-				edge_serial->rxHeader3 = *buffer;
-				++buffer;
-				--bufferLength;
+			dbg("%s - Hdr1=%02X Hdr2=%02X", __func__,
+			    edge_serial->rxHeader1, edge_serial->rxHeader2);
+			/* Process depending on whether this header is
+			 * data or status */
 
-				// We have all the header bytes, process the status now
-				process_rcvd_status (edge_serial, edge_serial->rxStatusParam, edge_serial->rxHeader3);
+			if (IS_CMD_STAT_HDR(edge_serial->rxHeader1)) {
+				/* Decode this status header and go to
+				 * EXPECT_HDR1 (if we can process the status
+				 * with only 2 bytes), or go to EXPECT_HDR3 to
+				 * get the third byte. */
+				edge_serial->rxPort =
+				    IOSP_GET_HDR_PORT(edge_serial->rxHeader1);
+				edge_serial->rxStatusCode =
+				    IOSP_GET_STATUS_CODE(
+						edge_serial->rxHeader1);
+
+				if (!IOSP_STATUS_IS_2BYTE(
+						edge_serial->rxStatusCode)) {
+					/* This status needs additional bytes.
+					 * Save what we have and then wait for
+					 * more data.
+					 */
+					edge_serial->rxStatusParam
+						= edge_serial->rxHeader2;
+					edge_serial->rxState = EXPECT_HDR3;
+					break;
+				}
+				/* We have all the header bytes, process the
+				   status now */
+				process_rcvd_status(edge_serial,
+						edge_serial->rxHeader2, 0);
 				edge_serial->rxState = EXPECT_HDR1;
 				break;
+			} else {
+				edge_serial->rxPort =
+				    IOSP_GET_HDR_PORT(edge_serial->rxHeader1);
+				edge_serial->rxBytesRemaining =
+				    IOSP_GET_HDR_DATA_LEN(
+						edge_serial->rxHeader1,
+						edge_serial->rxHeader2);
+				dbg("%s - Data for Port %u Len %u",
+						__func__,
+						edge_serial->rxPort,
+						edge_serial->rxBytesRemaining);
 
+				/* ASSERT(DevExt->RxPort < DevExt->NumPorts);
+				 * ASSERT(DevExt->RxBytesRemaining <
+				 *		IOSP_MAX_DATA_LENGTH);
+				 */
+
+				if (bufferLength == 0) {
+					edge_serial->rxState = EXPECT_DATA;
+					break;
+				}
+				/* Else, drop through */
+			}
+		case EXPECT_DATA: /* Expect data */
+			if (bufferLength < edge_serial->rxBytesRemaining) {
+				rxLen = bufferLength;
+				/* Expect data to start next buffer */
+				edge_serial->rxState = EXPECT_DATA;
+			} else {
+				/* BufLen >= RxBytesRemaining */
+				rxLen = edge_serial->rxBytesRemaining;
+				/* Start another header next time */
+				edge_serial->rxState = EXPECT_HDR1;
+			}
+
+			bufferLength -= rxLen;
+			edge_serial->rxBytesRemaining -= rxLen;
+
+			/* spit this data back into the tty driver if this
+			   port is open */
+			if (rxLen) {
+				port = edge_serial->serial->port[
+							edge_serial->rxPort];
+				edge_port = usb_get_serial_port_data(port);
+				if (edge_port->open) {
+					tty = edge_port->port->port.tty;
+					if (tty) {
+						dbg("%s - Sending %d bytes to TTY for port %d",
+							__func__, rxLen, edge_serial->rxPort);
+						edge_tty_recv(&edge_serial->serial->dev->dev, tty, buffer, rxLen);
+					}
+					edge_port->icount.rx += rxLen;
+				}
+				buffer += rxLen;
+			}
+			break;
+
+		case EXPECT_HDR3:	/* Expect 3rd byte of status header */
+			edge_serial->rxHeader3 = *buffer;
+			++buffer;
+			--bufferLength;
+
+			/* We have all the header bytes, process the
+			   status now */
+			process_rcvd_status(edge_serial,
+				edge_serial->rxStatusParam,
+				edge_serial->rxHeader3);
+			edge_serial->rxState = EXPECT_HDR1;
+			break;
 		}
 	}
 }
@@ -1895,9 +1963,11 @@
 
 /*****************************************************************************
  * process_rcvd_status
- *	this function handles the any status messages received on the bulk in pipe.
+ *	this function handles the any status messages received on the
+ *	bulk in pipe.
  *****************************************************************************/
-static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2, __u8 byte3)
+static void process_rcvd_status(struct edgeport_serial *edge_serial,
+						__u8 byte2, __u8 byte3)
 {
 	struct usb_serial_port *port;
 	struct edgeport_port *edge_port;
@@ -1907,7 +1977,9 @@
 	port = edge_serial->serial->port[edge_serial->rxPort];
 	edge_port = usb_get_serial_port_data(port);
 	if (edge_port == NULL) {
-		dev_err(&edge_serial->serial->dev->dev, "%s - edge_port == NULL for port %d\n", __func__, edge_serial->rxPort);
+		dev_err(&edge_serial->serial->dev->dev,
+			"%s - edge_port == NULL for port %d\n",
+					__func__, edge_serial->rxPort);
 		return;
 	}
 
@@ -1915,22 +1987,28 @@
 
 	if (code == IOSP_EXT_STATUS) {
 		switch (byte2) {
-			case IOSP_EXT_STATUS_CHASE_RSP:
-				// we want to do EXT status regardless of port open/closed 
-				dbg("%s - Port %u EXT CHASE_RSP Data = %02x", __func__, edge_serial->rxPort, byte3 );
-				// Currently, the only EXT_STATUS is Chase, so process here instead of one more call
-				// to one more subroutine. If/when more EXT_STATUS, there'll be more work to do.
-				// Also, we currently clear flag and close the port regardless of content of above's Byte3.
-				// We could choose to do something else when Byte3 says Timeout on Chase from Edgeport,
-				// like wait longer in block_until_chase_response, but for now we don't. 
-				edge_port->chaseResponsePending = false;
-				wake_up (&edge_port->wait_chase);
-				return;
+		case IOSP_EXT_STATUS_CHASE_RSP:
+			/* we want to do EXT status regardless of port
+			 * open/closed */
+			dbg("%s - Port %u EXT CHASE_RSP Data = %02x",
+					__func__, edge_serial->rxPort, byte3);
+			/* Currently, the only EXT_STATUS is Chase, so process
+			 * here instead of one more call to one more subroutine
+			 * If/when more EXT_STATUS, there'll be more work to do
+			 * Also, we currently clear flag and close the port
+			 * regardless of content of above's Byte3.
+			 * We could choose to do something else when Byte3 says
+			 * Timeout on Chase from Edgeport, like wait longer in
+			 * block_until_chase_response, but for now we don't.
+			 */
+			edge_port->chaseResponsePending = false;
+			wake_up(&edge_port->wait_chase);
+			return;
 
-			case IOSP_EXT_STATUS_RX_CHECK_RSP:
-				dbg("%s ========== Port %u CHECK_RSP Sequence = %02x =============\n", __func__, edge_serial->rxPort, byte3 );
-				//Port->RxCheckRsp = true;
-				return;
+		case IOSP_EXT_STATUS_RX_CHECK_RSP:
+			dbg("%s ========== Port %u CHECK_RSP Sequence = %02x =============\n", __func__, edge_serial->rxPort, byte3);
+			/* Port->RxCheckRsp = true; */
+			return;
 		}
 	}
 
@@ -1938,11 +2016,14 @@
 		edge_port->txCredits = GET_TX_BUFFER_SIZE(byte3);
 		edge_port->maxTxCredits = edge_port->txCredits;
 		dbg("%s - Port %u Open Response Inital MSR = %02x TxBufferSize = %d", __func__, edge_serial->rxPort, byte2, edge_port->txCredits);
-		handle_new_msr (edge_port, byte2);
+		handle_new_msr(edge_port, byte2);
 
-		/* send the current line settings to the port so we are in sync with any further termios calls */
-		if (edge_port->port->tty)
-			change_port_settings (edge_port, edge_port->port->tty->termios);
+		/* send the current line settings to the port so we are
+		   in sync with any further termios calls */
+		/* FIXME: locking on tty */
+		if (edge_port->port->port.tty)
+			change_port_settings(edge_port->port->port.tty,
+				edge_port, edge_port->port->port.tty->termios);
 
 		/* we have completed the open */
 		edge_port->openPending = false;
@@ -1951,45 +2032,49 @@
 		return;
 	}
 
-	// If port is closed, silently discard all rcvd status. We can
-	// have cases where buffered status is received AFTER the close
-	// port command is sent to the Edgeport.
-	if (!edge_port->open || edge_port->closePending) {
+	/* If port is closed, silently discard all rcvd status. We can
+	 * have cases where buffered status is received AFTER the close
+	 * port command is sent to the Edgeport.
+	 */
+	if (!edge_port->open || edge_port->closePending)
 		return;
-	}
 
 	switch (code) {
-		// Not currently sent by Edgeport
-		case IOSP_STATUS_LSR:
-			dbg("%s - Port %u LSR Status = %02x", __func__, edge_serial->rxPort, byte2);
-			handle_new_lsr(edge_port, false, byte2, 0);
-			break;
+	/* Not currently sent by Edgeport */
+	case IOSP_STATUS_LSR:
+		dbg("%s - Port %u LSR Status = %02x",
+					__func__, edge_serial->rxPort, byte2);
+		handle_new_lsr(edge_port, false, byte2, 0);
+		break;
 
-		case IOSP_STATUS_LSR_DATA:
-			dbg("%s - Port %u LSR Status = %02x, Data = %02x", __func__, edge_serial->rxPort, byte2, byte3);
-			// byte2 is LSR Register
-			// byte3 is broken data byte
-			handle_new_lsr(edge_port, true, byte2, byte3);
-			break;
-			//
-			//	case IOSP_EXT_4_STATUS:
-			//		dbg("%s - Port %u LSR Status = %02x Data = %02x", __func__, edge_serial->rxPort, byte2, byte3);
-			//		break;
-			//
-		case IOSP_STATUS_MSR:
-			dbg("%s - Port %u MSR Status = %02x", __func__, edge_serial->rxPort, byte2);
+	case IOSP_STATUS_LSR_DATA:
+		dbg("%s - Port %u LSR Status = %02x, Data = %02x",
+				__func__, edge_serial->rxPort, byte2, byte3);
+		/* byte2 is LSR Register */
+		/* byte3 is broken data byte */
+		handle_new_lsr(edge_port, true, byte2, byte3);
+		break;
+	/*
+	 *	case IOSP_EXT_4_STATUS:
+	 *		dbg("%s - Port %u LSR Status = %02x Data = %02x",
+	 *			__func__, edge_serial->rxPort, byte2, byte3);
+	 *		break;
+	 */
+	case IOSP_STATUS_MSR:
+		dbg("%s - Port %u MSR Status = %02x",
+					__func__, edge_serial->rxPort, byte2);
+		/*
+		 * Process this new modem status and generate appropriate
+		 * events, etc, based on the new status. This routine
+		 * also saves the MSR in Port->ShadowMsr.
+		 */
+		handle_new_msr(edge_port, byte2);
+		break;
 
-			// Process this new modem status and generate appropriate
-			// events, etc, based on the new status. This routine
-			// also saves the MSR in Port->ShadowMsr.
-			handle_new_msr(edge_port, byte2);
-			break;
-
-		default:
-			dbg("%s - Unrecognized IOSP status code %u\n", __func__, code);
-			break;
+	default:
+		dbg("%s - Unrecognized IOSP status code %u\n", __func__, code);
+		break;
 	}
-
 	return;
 }
 
@@ -1998,7 +2083,8 @@
  * edge_tty_recv
  *	this function passes data on to the tty flip buffer
  *****************************************************************************/
-static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length)
+static void edge_tty_recv(struct device *dev, struct tty_struct *tty,
+					unsigned char *data, int length)
 {
 	int cnt;
 
@@ -2007,7 +2093,7 @@
 		if (cnt < length) {
 			dev_err(dev, "%s - dropping data, %d bytes lost\n",
 					__func__, length - cnt);
-			if(cnt == 0)
+			if (cnt == 0)
 				break;
 		}
 		tty_insert_flip_string(tty, data, cnt);
@@ -2029,22 +2115,19 @@
 
 	dbg("%s %02x", __func__, newMsr);
 
-	if (newMsr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
+	if (newMsr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR |
+			EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
 		icount = &edge_port->icount;
 
 		/* update input line counters */
-		if (newMsr & EDGEPORT_MSR_DELTA_CTS) {
+		if (newMsr & EDGEPORT_MSR_DELTA_CTS)
 			icount->cts++;
-		}
-		if (newMsr & EDGEPORT_MSR_DELTA_DSR) {
+		if (newMsr & EDGEPORT_MSR_DELTA_DSR)
 			icount->dsr++;
-		}
-		if (newMsr & EDGEPORT_MSR_DELTA_CD) {
+		if (newMsr & EDGEPORT_MSR_DELTA_CD)
 			icount->dcd++;
-		}
-		if (newMsr & EDGEPORT_MSR_DELTA_RI) {
+		if (newMsr & EDGEPORT_MSR_DELTA_RI)
 			icount->rng++;
-		}
 		wake_up_interruptible(&edge_port->delta_msr_wait);
 	}
 
@@ -2059,42 +2142,41 @@
  * handle_new_lsr
  *	this function handles any change to the lsr register for a port.
  *****************************************************************************/
-static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, __u8 lsr, __u8 data)
+static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData,
+							__u8 lsr, __u8 data)
 {
-	__u8    newLsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK));
-	struct  async_icount *icount;
+	__u8 newLsr = (__u8) (lsr & (__u8)
+		(LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK));
+	struct async_icount *icount;
 
 	dbg("%s - %02x", __func__, newLsr);
 
 	edge_port->shadowLSR = lsr;
 
 	if (newLsr & LSR_BREAK) {
-		//
-		// Parity and Framing errors only count if they
-		// occur exclusive of a break being
-		// received.
-		//
+		/*
+		 * Parity and Framing errors only count if they
+		 * occur exclusive of a break being
+		 * received.
+		 */
 		newLsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK);
 	}
 
 	/* Place LSR data byte into Rx buffer */
-	if (lsrData && edge_port->port->tty)
-		edge_tty_recv(&edge_port->port->dev, edge_port->port->tty, &data, 1);
+	if (lsrData && edge_port->port->port.tty)
+		edge_tty_recv(&edge_port->port->dev,
+					edge_port->port->port.tty, &data, 1);
 
 	/* update input line counters */
 	icount = &edge_port->icount;
-	if (newLsr & LSR_BREAK) {
+	if (newLsr & LSR_BREAK)
 		icount->brk++;
-	}
-	if (newLsr & LSR_OVER_ERR) {
+	if (newLsr & LSR_OVER_ERR)
 		icount->overrun++;
-	}
-	if (newLsr & LSR_PAR_ERR) {
+	if (newLsr & LSR_PAR_ERR)
 		icount->parity++;
-	}
-	if (newLsr & LSR_FRM_ERR) {
+	if (newLsr & LSR_FRM_ERR)
 		icount->frame++;
-	}
 
 	return;
 }
@@ -2102,12 +2184,13 @@
 
 /****************************************************************************
  * sram_write
- *	writes a number of bytes to the Edgeport device's sram starting at the 
+ *	writes a number of bytes to the Edgeport device's sram starting at the
  *	given address.
  *	If successful returns the number of bytes written, otherwise it returns
  *	a negative error number of the problem.
  ****************************************************************************/
-static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, const __u8 *data)
+static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr,
+					__u16 length, const __u8 *data)
 {
 	int result;
 	__u16 current_length;
@@ -2115,32 +2198,37 @@
 
 	dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
 
-	transfer_buffer =  kmalloc (64, GFP_KERNEL);
+	transfer_buffer =  kmalloc(64, GFP_KERNEL);
 	if (!transfer_buffer) {
-		dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, 64);
+		dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n",
+							__func__, 64);
 		return -ENOMEM;
 	}
 
 	/* need to split these writes up into 64 byte chunks */
 	result = 0;
 	while (length > 0) {
-		if (length > 64) {
+		if (length > 64)
 			current_length = 64;
-		} else {
+		else
 			current_length = length;
-		}
-//		dbg("%s - writing %x, %x, %d", __func__, extAddr, addr, current_length);
-		memcpy (transfer_buffer, data, current_length);
-		result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), USB_REQUEST_ION_WRITE_RAM, 
-					  0x40, addr, extAddr, transfer_buffer, current_length, 300);
+
+/*		dbg("%s - writing %x, %x, %d", __func__,
+					extAddr, addr, current_length); */
+		memcpy(transfer_buffer, data, current_length);
+		result = usb_control_msg(serial->dev,
+					usb_sndctrlpipe(serial->dev, 0),
+					USB_REQUEST_ION_WRITE_RAM,
+					0x40, addr, extAddr, transfer_buffer,
+					current_length, 300);
 		if (result < 0)
 			break;
 		length -= current_length;
 		addr += current_length;
 		data += current_length;
-	}       
+	}
 
-	kfree (transfer_buffer);
+	kfree(transfer_buffer);
 	return result;
 }
 
@@ -2152,40 +2240,45 @@
  *	If successful returns the number of bytes written, otherwise it returns
  *	a negative error number of the problem.
  ****************************************************************************/
-static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, const __u8 *data)
+static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr,
+					__u16 length, const __u8 *data)
 {
 	int result;
 	__u16 current_length;
 	unsigned char *transfer_buffer;
 
-//	dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
+/*	dbg("%s - %x, %x, %d", __func__, extAddr, addr, length); */
 
-	transfer_buffer =  kmalloc (64, GFP_KERNEL);
+	transfer_buffer =  kmalloc(64, GFP_KERNEL);
 	if (!transfer_buffer) {
-		dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, 64);
+		dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n",
+								__func__, 64);
 		return -ENOMEM;
 	}
 
 	/* need to split these writes up into 64 byte chunks */
 	result = 0;
 	while (length > 0) {
-		if (length > 64) {
+		if (length > 64)
 			current_length = 64;
-		} else {
+		else
 			current_length = length;
-		}
-//		dbg("%s - writing %x, %x, %d", __func__, extAddr, addr, current_length);
-		memcpy (transfer_buffer, data, current_length);
-		result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), USB_REQUEST_ION_WRITE_ROM, 
-					  0x40, addr, extAddr, transfer_buffer, current_length, 300);
+/*		dbg("%s - writing %x, %x, %d", __func__,
+					extAddr, addr, current_length); */
+		memcpy(transfer_buffer, data, current_length);
+		result = usb_control_msg(serial->dev,
+					usb_sndctrlpipe(serial->dev, 0),
+					USB_REQUEST_ION_WRITE_ROM, 0x40,
+					addr, extAddr,
+					transfer_buffer, current_length, 300);
 		if (result < 0)
 			break;
 		length -= current_length;
 		addr += current_length;
 		data += current_length;
-	}       
+	}
 
-	kfree (transfer_buffer);
+	kfree(transfer_buffer);
 	return result;
 }
 
@@ -2197,7 +2290,8 @@
  *	If successful returns the number of bytes read, otherwise it returns
  *	a negative error number of the problem.
  ****************************************************************************/
-static int rom_read (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 length, __u8 *data)
+static int rom_read(struct usb_serial *serial, __u16 extAddr,
+					__u16 addr, __u16 length, __u8 *data)
 {
 	int result;
 	__u16 current_length;
@@ -2205,32 +2299,36 @@
 
 	dbg("%s - %x, %x, %d", __func__, extAddr, addr, length);
 
-	transfer_buffer =  kmalloc (64, GFP_KERNEL);
+	transfer_buffer =  kmalloc(64, GFP_KERNEL);
 	if (!transfer_buffer) {
-		dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __func__, 64);
+		dev_err(&serial->dev->dev,
+			"%s - kmalloc(%d) failed.\n", __func__, 64);
 		return -ENOMEM;
 	}
 
 	/* need to split these reads up into 64 byte chunks */
 	result = 0;
 	while (length > 0) {
-		if (length > 64) {
+		if (length > 64)
 			current_length = 64;
-		} else {
+		else
 			current_length = length;
-		}
-//		dbg("%s - %x, %x, %d", __func__, extAddr, addr, current_length);
-		result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), USB_REQUEST_ION_READ_ROM, 
-					  0xC0, addr, extAddr, transfer_buffer, current_length, 300);
+/*		dbg("%s - %x, %x, %d", __func__,
+				extAddr, addr, current_length); */
+		result = usb_control_msg(serial->dev,
+					usb_rcvctrlpipe(serial->dev, 0),
+					USB_REQUEST_ION_READ_ROM,
+					0xC0, addr, extAddr, transfer_buffer,
+					current_length, 300);
 		if (result < 0)
 			break;
-		memcpy (data, transfer_buffer, current_length);
+		memcpy(data, transfer_buffer, current_length);
 		length -= current_length;
 		addr += current_length;
 		data += current_length;
-	}       
+	}
 
-	kfree (transfer_buffer);
+	kfree(transfer_buffer);
 	return result;
 }
 
@@ -2239,7 +2337,8 @@
  * send_iosp_ext_cmd
  *	Is used to send a IOSP message to the Edgeport device
  ****************************************************************************/
-static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u8 param)
+static int send_iosp_ext_cmd(struct edgeport_port *edge_port,
+						__u8 command, __u8 param)
 {
 	unsigned char   *buffer;
 	unsigned char   *currentCommand;
@@ -2248,19 +2347,20 @@
 
 	dbg("%s - %d, %d", __func__, command, param);
 
-	buffer =  kmalloc (10, GFP_ATOMIC);
+	buffer = kmalloc(10, GFP_ATOMIC);
 	if (!buffer) {
-		dev_err(&edge_port->port->dev, "%s - kmalloc(%d) failed.\n", __func__, 10);
+		dev_err(&edge_port->port->dev,
+				"%s - kmalloc(%d) failed.\n", __func__, 10);
 		return -ENOMEM;
 	}
 
 	currentCommand = buffer;
 
-	MAKE_CMD_EXT_CMD (&currentCommand, &length,
-			  edge_port->port->number - edge_port->port->serial->minor,
-			  command, param);
+	MAKE_CMD_EXT_CMD(&currentCommand, &length,
+		edge_port->port->number - edge_port->port->serial->minor,
+		command, param);
 
-	status = write_cmd_usb (edge_port, buffer, length);
+	status = write_cmd_usb(edge_port, buffer, length);
 	if (status) {
 		/* something bad happened, let's free up the memory */
 		kfree(buffer);
@@ -2274,43 +2374,50 @@
  * write_cmd_usb
  *	this function writes the given buffer out to the bulk write endpoint.
  *****************************************************************************/
-static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer, int length)
+static int write_cmd_usb(struct edgeport_port *edge_port,
+					unsigned char *buffer, int length)
 {
-	struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial);
+	struct edgeport_serial *edge_serial =
+				usb_get_serial_data(edge_port->port->serial);
 	int status = 0;
 	struct urb *urb;
 	int timeout;
 
-	usb_serial_debug_data(debug, &edge_port->port->dev, __func__, length, buffer);
+	usb_serial_debug_data(debug, &edge_port->port->dev,
+						__func__, length, buffer);
 
 	/* Allocate our next urb */
-	urb = usb_alloc_urb (0, GFP_ATOMIC);
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
 	if (!urb)
 		return -ENOMEM;
 
 	atomic_inc(&CmdUrbs);
-	dbg("%s - ALLOCATE URB %p (outstanding %d)", __func__, urb, atomic_read(&CmdUrbs));
+	dbg("%s - ALLOCATE URB %p (outstanding %d)",
+				__func__, urb, atomic_read(&CmdUrbs));
 
-	usb_fill_bulk_urb (urb, edge_serial->serial->dev, 
-		       usb_sndbulkpipe(edge_serial->serial->dev, edge_serial->bulk_out_endpoint),
-		       buffer, length, edge_bulk_out_cmd_callback, edge_port);
+	usb_fill_bulk_urb(urb, edge_serial->serial->dev,
+			usb_sndbulkpipe(edge_serial->serial->dev,
+					edge_serial->bulk_out_endpoint),
+			buffer, length, edge_bulk_out_cmd_callback, edge_port);
 
 	edge_port->commandPending = true;
 	status = usb_submit_urb(urb, GFP_ATOMIC);
 
 	if (status) {
 		/* something went wrong */
-		dev_err(&edge_port->port->dev, "%s - usb_submit_urb(write command) failed, status = %d\n", __func__, status);
+		dev_err(&edge_port->port->dev,
+		    "%s - usb_submit_urb(write command) failed, status = %d\n",
+							__func__, status);
 		usb_kill_urb(urb);
 		usb_free_urb(urb);
 		atomic_dec(&CmdUrbs);
 		return status;
 	}
 
-	// wait for command to finish
+	/* wait for command to finish */
 	timeout = COMMAND_TIMEOUT;
 #if 0
-	wait_event (&edge_port->wait_command, !edge_port->commandPending);
+	wait_event(&edge_port->wait_command, !edge_port->commandPending);
 
 	if (edge_port->commandPending) {
 		/* command timed out */
@@ -2327,15 +2434,18 @@
  *	this function sends the proper command to change the baud rate of the
  *	specified port.
  *****************************************************************************/
-static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRate)
+static int send_cmd_write_baud_rate(struct edgeport_port *edge_port,
+								int baudRate)
 {
-	struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial);
+	struct edgeport_serial *edge_serial =
+				usb_get_serial_data(edge_port->port->serial);
 	unsigned char *cmdBuffer;
 	unsigned char *currCmd;
 	int cmdLen = 0;
 	int divisor;
 	int status;
-	unsigned char number = edge_port->port->number - edge_port->port->serial->minor;
+	unsigned char number =
+		edge_port->port->number - edge_port->port->serial->minor;
 
 	if (edge_serial->is_epic &&
 	    !edge_serial->epic_descriptor.Supports.IOSPSetBaudRate) {
@@ -2344,36 +2454,40 @@
 		return 0;
 	}
 
-	dbg("%s - port = %d, baud = %d", __func__, edge_port->port->number, baudRate);
+	dbg("%s - port = %d, baud = %d", __func__,
+					edge_port->port->number, baudRate);
 
-	status = calc_baud_rate_divisor (baudRate, &divisor);
+	status = calc_baud_rate_divisor(baudRate, &divisor);
 	if (status) {
-		dev_err(&edge_port->port->dev, "%s - bad baud rate\n", __func__);
+		dev_err(&edge_port->port->dev, "%s - bad baud rate\n",
+								__func__);
 		return status;
 	}
 
-	// Alloc memory for the string of commands.
-	cmdBuffer =  kmalloc (0x100, GFP_ATOMIC);
+	/* Alloc memory for the string of commands. */
+	cmdBuffer =  kmalloc(0x100, GFP_ATOMIC);
 	if (!cmdBuffer) {
-		dev_err(&edge_port->port->dev, "%s - kmalloc(%d) failed.\n", __func__, 0x100);
+		dev_err(&edge_port->port->dev,
+			"%s - kmalloc(%d) failed.\n", __func__, 0x100);
 		return -ENOMEM;
 	}
 	currCmd = cmdBuffer;
 
-	// Enable access to divisor latch
-	MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, LCR, LCR_DL_ENABLE );
+	/* Enable access to divisor latch */
+	MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, number, LCR, LCR_DL_ENABLE);
 
-	// Write the divisor itself
-	MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, DLL, LOW8 (divisor) );
-	MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, DLM, HIGH8(divisor) );
+	/* Write the divisor itself */
+	MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, number, DLL, LOW8(divisor));
+	MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, number, DLM, HIGH8(divisor));
 
-	// Restore original value to disable access to divisor latch
-	MAKE_CMD_WRITE_REG( &currCmd, &cmdLen, number, LCR, edge_port->shadowLCR);
+	/* Restore original value to disable access to divisor latch */
+	MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, number, LCR,
+						edge_port->shadowLCR);
 
-	status = write_cmd_usb(edge_port, cmdBuffer, cmdLen );
+	status = write_cmd_usb(edge_port, cmdBuffer, cmdLen);
 	if (status) {
 		/* something bad happened, let's free up the memory */
-		kfree (cmdBuffer);
+		kfree(cmdBuffer);
 	}
 
 	return status;
@@ -2385,7 +2499,7 @@
  *	this function calculates the proper baud rate divisor for the specified
  *	baud rate.
  *****************************************************************************/
-static int calc_baud_rate_divisor (int baudrate, int *divisor)
+static int calc_baud_rate_divisor(int baudrate, int *divisor)
 {
 	int i;
 	__u16 custom;
@@ -2394,17 +2508,17 @@
 	dbg("%s - %d", __func__, baudrate);
 
 	for (i = 0; i < ARRAY_SIZE(divisor_table); i++) {
-		if ( divisor_table[i].BaudRate == baudrate ) {
+		if (divisor_table[i].BaudRate == baudrate) {
 			*divisor = divisor_table[i].Divisor;
 			return 0;
 		}
 	}
 
-	// We have tried all of the standard baud rates
-	// lets try to calculate the divisor for this baud rate
-	// Make sure the baud rate is reasonable
+	/* We have tried all of the standard baud rates
+	 * lets try to calculate the divisor for this baud rate
+	 * Make sure the baud rate is reasonable */
 	if (baudrate > 50 && baudrate < 230400) {
-		// get divisor
+		/* get divisor */
 		custom = (__u16)((230400L + baudrate/2) / baudrate);
 
 		*divisor = custom;
@@ -2419,17 +2533,20 @@
 
 /*****************************************************************************
  * send_cmd_write_uart_register
- *	this function builds up a uart register message and sends to to the device.
+ *  this function builds up a uart register message and sends to to the device.
  *****************************************************************************/
-static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 regNum, __u8 regValue)
+static int send_cmd_write_uart_register(struct edgeport_port *edge_port,
+						__u8 regNum, __u8 regValue)
 {
-	struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial);
+	struct edgeport_serial *edge_serial =
+				usb_get_serial_data(edge_port->port->serial);
 	unsigned char *cmdBuffer;
 	unsigned char *currCmd;
 	unsigned long cmdLen = 0;
 	int status;
 
-	dbg("%s - write to %s register 0x%02x", (regNum == MCR) ? "MCR" : "LCR", __func__, regValue);
+	dbg("%s - write to %s register 0x%02x",
+			(regNum == MCR) ? "MCR" : "LCR", __func__, regValue);
 
 	if (edge_serial->is_epic &&
 	    !edge_serial->epic_descriptor.Supports.IOSPWriteMCR &&
@@ -2441,27 +2558,26 @@
 	if (edge_serial->is_epic &&
 	    !edge_serial->epic_descriptor.Supports.IOSPWriteLCR &&
 	    regNum == LCR) {
-		dbg ("SendCmdWriteUartReg - Not writing to LCR Register");
+		dbg("SendCmdWriteUartReg - Not writing to LCR Register");
 		return 0;
 	}
 
-	// Alloc memory for the string of commands.
-	cmdBuffer = kmalloc (0x10, GFP_ATOMIC);
-	if (cmdBuffer == NULL ) {
+	/* Alloc memory for the string of commands. */
+	cmdBuffer = kmalloc(0x10, GFP_ATOMIC);
+	if (cmdBuffer == NULL)
 		return -ENOMEM;
-	}
 
 	currCmd = cmdBuffer;
 
-	// Build a cmd in the buffer to write the given register
-	MAKE_CMD_WRITE_REG (&currCmd, &cmdLen,
-			    edge_port->port->number - edge_port->port->serial->minor,
-			    regNum, regValue);
+	/* Build a cmd in the buffer to write the given register */
+	MAKE_CMD_WRITE_REG(&currCmd, &cmdLen,
+		edge_port->port->number - edge_port->port->serial->minor,
+		regNum, regValue);
 
 	status = write_cmd_usb(edge_port, cmdBuffer, cmdLen);
 	if (status) {
 		/* something bad happened, let's free up the memory */
-		kfree (cmdBuffer);
+		kfree(cmdBuffer);
 	}
 
 	return status;
@@ -2470,16 +2586,15 @@
 
 /*****************************************************************************
  * change_port_settings
- *	This routine is called to set the UART on the device to match the specified
- *	new settings.
+ *	This routine is called to set the UART on the device to match the
+ *	specified new settings.
  *****************************************************************************/
-#ifndef CMSPAR
-#define CMSPAR 0
-#endif
-static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios)
+
+static void change_port_settings(struct tty_struct *tty,
+	struct edgeport_port *edge_port, struct ktermios *old_termios)
 {
-	struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial);
-	struct tty_struct *tty;
+	struct edgeport_serial *edge_serial =
+			usb_get_serial_data(edge_port->port->serial);
 	int baud;
 	unsigned cflag;
 	__u8 mask = 0xff;
@@ -2498,21 +2613,26 @@
 		return;
 	}
 
-	tty = edge_port->port->tty;
-	if ((!tty) ||
-	    (!tty->termios)) {
-		dbg("%s - no tty structures", __func__);
-		return;
-	}
-
 	cflag = tty->termios->c_cflag;
 
 	switch (cflag & CSIZE) {
-		case CS5:   lData = LCR_BITS_5; mask = 0x1f;    dbg("%s - data bits = 5", __func__);   break;
-		case CS6:   lData = LCR_BITS_6; mask = 0x3f;    dbg("%s - data bits = 6", __func__);   break;
-		case CS7:   lData = LCR_BITS_7; mask = 0x7f;    dbg("%s - data bits = 7", __func__);   break;
-		default:
-		case CS8:   lData = LCR_BITS_8;                 dbg("%s - data bits = 8", __func__);   break;
+	case CS5:
+		lData = LCR_BITS_5; mask = 0x1f;
+		dbg("%s - data bits = 5", __func__);
+		break;
+	case CS6:
+		lData = LCR_BITS_6; mask = 0x3f;
+		dbg("%s - data bits = 6", __func__);
+		break;
+	case CS7:
+		lData = LCR_BITS_7; mask = 0x7f;
+		dbg("%s - data bits = 7", __func__);
+		break;
+	default:
+	case CS8:
+		lData = LCR_BITS_8;
+		dbg("%s - data bits = 8", __func__);
+		break;
 	}
 
 	lParity = LCR_PAR_NONE;
@@ -2554,7 +2674,8 @@
 		dbg("%s - RTS/CTS is disabled", __func__);
 	}
 
-	/* if we are implementing XON/XOFF, set the start and stop character in the device */
+	/* if we are implementing XON/XOFF, set the start and stop character
+	   in the device */
 	if (I_IXOFF(tty) || I_IXON(tty)) {
 		unsigned char stop_char  = STOP_CHAR(tty);
 		unsigned char start_char = START_CHAR(tty);
@@ -2562,14 +2683,17 @@
 		if ((!edge_serial->is_epic) ||
 		    ((edge_serial->is_epic) &&
 		     (edge_serial->epic_descriptor.Supports.IOSPSetXChar))) {
-			send_iosp_ext_cmd(edge_port, IOSP_CMD_SET_XON_CHAR, start_char);
-			send_iosp_ext_cmd(edge_port, IOSP_CMD_SET_XOFF_CHAR, stop_char);
+			send_iosp_ext_cmd(edge_port,
+					IOSP_CMD_SET_XON_CHAR, start_char);
+			send_iosp_ext_cmd(edge_port,
+					IOSP_CMD_SET_XOFF_CHAR, stop_char);
 		}
 
 		/* if we are implementing INBOUND XON/XOFF */
 		if (I_IXOFF(tty)) {
 			rxFlow |= IOSP_RX_FLOW_XON_XOFF;
-			dbg("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", __func__, start_char, stop_char);
+			dbg("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
+					__func__, start_char, stop_char);
 		} else {
 			dbg("%s - INBOUND XON/XOFF is disabled", __func__);
 		}
@@ -2577,7 +2701,8 @@
 		/* if we are implementing OUTBOUND XON/XOFF */
 		if (I_IXON(tty)) {
 			txFlow |= IOSP_TX_FLOW_XON_XOFF;
-			dbg("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", __func__, start_char, stop_char);
+			dbg("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
+					__func__, start_char, stop_char);
 		} else {
 			dbg("%s - OUTBOUND XON/XOFF is disabled", __func__);
 		}
@@ -2600,20 +2725,20 @@
 	edge_port->validDataMask = mask;
 
 	/* Send the updated LCR value to the EdgePort */
-	status = send_cmd_write_uart_register(edge_port, LCR, edge_port->shadowLCR);
-	if (status != 0) {
+	status = send_cmd_write_uart_register(edge_port, LCR,
+							edge_port->shadowLCR);
+	if (status != 0)
 		return;
-	}
 
 	/* set up the MCR register and send it to the EdgePort */
 	edge_port->shadowMCR = MCR_MASTER_IE;
-	if (cflag & CBAUD) {
+	if (cflag & CBAUD)
 		edge_port->shadowMCR |= (MCR_DTR | MCR_RTS);
-	}
-	status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR);
-	if (status != 0) {
+
+	status = send_cmd_write_uart_register(edge_port, MCR,
+						edge_port->shadowMCR);
+	if (status != 0)
 		return;
-	}
 
 	/* Determine divisor based on baud rate */
 	baud = tty_get_baud_rate(tty);
@@ -2623,7 +2748,7 @@
 	}
 
 	dbg("%s - baud rate = %d", __func__, baud);
-	status = send_cmd_write_baud_rate (edge_port, baud);
+	status = send_cmd_write_baud_rate(edge_port, baud);
 	if (status == -1) {
 		/* Speed change was not possible - put back the old speed */
 		baud = tty_termios_baud_rate(old_termios);
@@ -2640,7 +2765,8 @@
  *	ASCII range, but it's only for debugging...
  *	NOTE: expects the unicode in LE format
  ****************************************************************************/
-static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unicode_size)
+static void unicode_to_ascii(char *string, int buflen,
+					__le16 *unicode, int unicode_size)
 {
 	int i;
 
@@ -2659,75 +2785,99 @@
 
 /****************************************************************************
  * get_manufacturing_desc
- *	reads in the manufacturing descriptor and stores it into the serial 
+ *	reads in the manufacturing descriptor and stores it into the serial
  *	structure.
  ****************************************************************************/
-static void get_manufacturing_desc (struct edgeport_serial *edge_serial)
+static void get_manufacturing_desc(struct edgeport_serial *edge_serial)
 {
 	int response;
 
 	dbg("getting manufacturer descriptor");
 
-	response = rom_read (edge_serial->serial, (EDGE_MANUF_DESC_ADDR & 0xffff0000) >> 16, 
-			    (__u16)(EDGE_MANUF_DESC_ADDR & 0x0000ffff), EDGE_MANUF_DESC_LEN,
-			    (__u8 *)(&edge_serial->manuf_descriptor));
+	response = rom_read(edge_serial->serial,
+				(EDGE_MANUF_DESC_ADDR & 0xffff0000) >> 16,
+				(__u16)(EDGE_MANUF_DESC_ADDR & 0x0000ffff),
+				EDGE_MANUF_DESC_LEN,
+				(__u8 *)(&edge_serial->manuf_descriptor));
 
-	if (response < 1) {
-		dev_err(&edge_serial->serial->dev->dev, "error in getting manufacturer descriptor\n");
-	} else {
+	if (response < 1)
+		dev_err(&edge_serial->serial->dev->dev,
+			"error in getting manufacturer descriptor\n");
+	else {
 		char string[30];
 		dbg("**Manufacturer Descriptor");
-		dbg("  RomSize:        %dK", edge_serial->manuf_descriptor.RomSize);
-		dbg("  RamSize:        %dK", edge_serial->manuf_descriptor.RamSize);
-		dbg("  CpuRev:         %d", edge_serial->manuf_descriptor.CpuRev);
-		dbg("  BoardRev:       %d", edge_serial->manuf_descriptor.BoardRev);
-		dbg("  NumPorts:       %d", edge_serial->manuf_descriptor.NumPorts);
-		dbg("  DescDate:       %d/%d/%d", edge_serial->manuf_descriptor.DescDate[0], edge_serial->manuf_descriptor.DescDate[1], edge_serial->manuf_descriptor.DescDate[2]+1900);
+		dbg("  RomSize:        %dK",
+			edge_serial->manuf_descriptor.RomSize);
+		dbg("  RamSize:        %dK",
+			edge_serial->manuf_descriptor.RamSize);
+		dbg("  CpuRev:         %d",
+			edge_serial->manuf_descriptor.CpuRev);
+		dbg("  BoardRev:       %d",
+			edge_serial->manuf_descriptor.BoardRev);
+		dbg("  NumPorts:       %d",
+			edge_serial->manuf_descriptor.NumPorts);
+		dbg("  DescDate:       %d/%d/%d",
+			edge_serial->manuf_descriptor.DescDate[0],
+			edge_serial->manuf_descriptor.DescDate[1],
+			edge_serial->manuf_descriptor.DescDate[2]+1900);
 		unicode_to_ascii(string, sizeof(string),
-		    edge_serial->manuf_descriptor.SerialNumber,
-		    edge_serial->manuf_descriptor.SerNumLength/2);
+			edge_serial->manuf_descriptor.SerialNumber,
+			edge_serial->manuf_descriptor.SerNumLength/2);
 		dbg("  SerialNumber: %s", string);
 		unicode_to_ascii(string, sizeof(string),
-		    edge_serial->manuf_descriptor.AssemblyNumber,
-		    edge_serial->manuf_descriptor.AssemblyNumLength/2);
+			edge_serial->manuf_descriptor.AssemblyNumber,
+			edge_serial->manuf_descriptor.AssemblyNumLength/2);
 		dbg("  AssemblyNumber: %s", string);
 		unicode_to_ascii(string, sizeof(string),
 		    edge_serial->manuf_descriptor.OemAssyNumber,
 		    edge_serial->manuf_descriptor.OemAssyNumLength/2);
 		dbg("  OemAssyNumber:  %s", string);
-		dbg("  UartType:       %d", edge_serial->manuf_descriptor.UartType);
-		dbg("  IonPid:         %d", edge_serial->manuf_descriptor.IonPid);
-		dbg("  IonConfig:      %d", edge_serial->manuf_descriptor.IonConfig);
+		dbg("  UartType:       %d",
+			edge_serial->manuf_descriptor.UartType);
+		dbg("  IonPid:         %d",
+			edge_serial->manuf_descriptor.IonPid);
+		dbg("  IonConfig:      %d",
+			edge_serial->manuf_descriptor.IonConfig);
 	}
 }
 
 
 /****************************************************************************
  * get_boot_desc
- *	reads in the bootloader descriptor and stores it into the serial 
+ *	reads in the bootloader descriptor and stores it into the serial
  *	structure.
  ****************************************************************************/
-static void get_boot_desc (struct edgeport_serial *edge_serial)
+static void get_boot_desc(struct edgeport_serial *edge_serial)
 {
 	int response;
 
 	dbg("getting boot descriptor");
 
-	response = rom_read (edge_serial->serial, (EDGE_BOOT_DESC_ADDR & 0xffff0000) >> 16, 
-			    (__u16)(EDGE_BOOT_DESC_ADDR & 0x0000ffff), EDGE_BOOT_DESC_LEN,
-			    (__u8 *)(&edge_serial->boot_descriptor));
+	response = rom_read(edge_serial->serial,
+				(EDGE_BOOT_DESC_ADDR & 0xffff0000) >> 16,
+				(__u16)(EDGE_BOOT_DESC_ADDR & 0x0000ffff),
+				EDGE_BOOT_DESC_LEN,
+				(__u8 *)(&edge_serial->boot_descriptor));
 
-	if (response < 1) {
-		dev_err(&edge_serial->serial->dev->dev, "error in getting boot descriptor\n");
-	} else {
+	if (response < 1)
+		dev_err(&edge_serial->serial->dev->dev,
+				"error in getting boot descriptor\n");
+	else {
 		dbg("**Boot Descriptor:");
-		dbg("  BootCodeLength: %d", le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength));
-		dbg("  MajorVersion:   %d", edge_serial->boot_descriptor.MajorVersion);
-		dbg("  MinorVersion:   %d", edge_serial->boot_descriptor.MinorVersion);
-		dbg("  BuildNumber:    %d", le16_to_cpu(edge_serial->boot_descriptor.BuildNumber));
-		dbg("  Capabilities:   0x%x", le16_to_cpu(edge_serial->boot_descriptor.Capabilities));
-		dbg("  UConfig0:       %d", edge_serial->boot_descriptor.UConfig0);
-		dbg("  UConfig1:       %d", edge_serial->boot_descriptor.UConfig1);
+		dbg("  BootCodeLength: %d",
+		    le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength));
+		dbg("  MajorVersion:   %d",
+			edge_serial->boot_descriptor.MajorVersion);
+		dbg("  MinorVersion:   %d",
+			edge_serial->boot_descriptor.MinorVersion);
+		dbg("  BuildNumber:    %d",
+			le16_to_cpu(edge_serial->boot_descriptor.BuildNumber));
+		dbg("  Capabilities:   0x%x",
+		      le16_to_cpu(edge_serial->boot_descriptor.Capabilities));
+		dbg("  UConfig0:       %d",
+			edge_serial->boot_descriptor.UConfig0);
+		dbg("  UConfig1:       %d",
+			edge_serial->boot_descriptor.UConfig1);
 	}
 }
 
@@ -2736,7 +2886,7 @@
  * load_application_firmware
  *	This is called to load the application firmware to the device
  ****************************************************************************/
-static void load_application_firmware (struct edgeport_serial *edge_serial)
+static void load_application_firmware(struct edgeport_serial *edge_serial)
 {
 	const struct ihex_binrec *rec;
 	const struct firmware *fw;
@@ -2813,7 +2963,7 @@
 /****************************************************************************
  * edge_startup
  ****************************************************************************/
-static int edge_startup (struct usb_serial *serial)
+static int edge_startup(struct usb_serial *serial)
 {
 	struct edgeport_serial *edge_serial;
 	struct edgeport_port *edge_port;
@@ -2855,10 +3005,10 @@
 		       sizeof(struct edge_compatibility_bits));
 
 		/* get the manufacturing descriptor for this device */
-		get_manufacturing_desc (edge_serial);
+		get_manufacturing_desc(edge_serial);
 
 		/* get the boot descriptor */
-		get_boot_desc (edge_serial);
+		get_boot_desc(edge_serial);
 
 		get_product_info(edge_serial);
 	}
@@ -2879,41 +3029,43 @@
 	/* If not an EPiC device */
 	if (!edge_serial->is_epic) {
 		/* now load the application firmware into this device */
-		load_application_firmware (edge_serial);
+		load_application_firmware(edge_serial);
 
 		dbg("%s - time 2 %ld", __func__, jiffies);
 
 		/* Check current Edgeport EEPROM and update if necessary */
-		update_edgeport_E2PROM (edge_serial);
+		update_edgeport_E2PROM(edge_serial);
 
 		dbg("%s - time 3 %ld", __func__, jiffies);
 
 		/* set the configuration to use #1 */
-//		dbg("set_configuration 1");
-//		usb_set_configuration (dev, 1);
+/*		dbg("set_configuration 1"); */
+/*		usb_set_configuration (dev, 1); */
 	}
 	dbg("  FirmwareMajorVersion  %d.%d.%d",
 	    edge_serial->product_info.FirmwareMajorVersion,
 	    edge_serial->product_info.FirmwareMinorVersion,
 	    le16_to_cpu(edge_serial->product_info.FirmwareBuildNumber));
 
-	/* we set up the pointers to the endpoints in the edge_open function, 
+	/* we set up the pointers to the endpoints in the edge_open function,
 	 * as the structures aren't created yet. */
 
 	/* set up our port private structures */
 	for (i = 0; i < serial->num_ports; ++i) {
-		edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL);
+		edge_port = kmalloc(sizeof(struct edgeport_port), GFP_KERNEL);
 		if (edge_port == NULL) {
-			dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
+			dev_err(&serial->dev->dev, "%s - Out of memory\n",
+								   __func__);
 			for (j = 0; j < i; ++j) {
-				kfree (usb_get_serial_port_data(serial->port[j]));
-				usb_set_serial_port_data(serial->port[j],  NULL);
+				kfree(usb_get_serial_port_data(serial->port[j]));
+				usb_set_serial_port_data(serial->port[j],
+									NULL);
 			}
 			usb_set_serial_data(serial, NULL);
 			kfree(edge_serial);
 			return -ENOMEM;
 		}
-		memset (edge_port, 0, sizeof(struct edgeport_port));
+		memset(edge_port, 0, sizeof(struct edgeport_port));
 		spin_lock_init(&edge_port->ep_lock);
 		edge_port->port = serial->port[i];
 		usb_set_serial_port_data(serial->port[i], edge_port);
@@ -2922,14 +3074,16 @@
 	response = 0;
 
 	if (edge_serial->is_epic) {
-		/* EPIC thing, set up our interrupt polling now and our read urb, so
-		 * that the device knows it really is connected. */
+		/* EPIC thing, set up our interrupt polling now and our read
+		 * urb, so that the device knows it really is connected. */
 		interrupt_in_found = bulk_in_found = bulk_out_found = false;
-		for (i = 0; i < serial->interface->altsetting[0].desc.bNumEndpoints; ++i) {
+		for (i = 0; i < serial->interface->altsetting[0]
+						.desc.bNumEndpoints; ++i) {
 			struct usb_endpoint_descriptor *endpoint;
 			int buffer_size;
 
-			endpoint = &serial->interface->altsetting[0].endpoint[i].desc;
+			endpoint = &serial->interface->altsetting[0].
+							endpoint[i].desc;
 			buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
 			if (!interrupt_in_found &&
 			    (usb_endpoint_is_int_in(endpoint))) {
@@ -2937,58 +3091,67 @@
 				dbg("found interrupt in");
 
 				/* not set up yet, so do it now */
-				edge_serial->interrupt_read_urb = usb_alloc_urb(0, GFP_KERNEL);
+				edge_serial->interrupt_read_urb =
+						usb_alloc_urb(0, GFP_KERNEL);
 				if (!edge_serial->interrupt_read_urb) {
 					err("out of memory");
 					return -ENOMEM;
 				}
-				edge_serial->interrupt_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
+				edge_serial->interrupt_in_buffer =
+					kmalloc(buffer_size, GFP_KERNEL);
 				if (!edge_serial->interrupt_in_buffer) {
 					err("out of memory");
 					usb_free_urb(edge_serial->interrupt_read_urb);
 					return -ENOMEM;
 				}
-				edge_serial->interrupt_in_endpoint = endpoint->bEndpointAddress;
+				edge_serial->interrupt_in_endpoint =
+						endpoint->bEndpointAddress;
 
 				/* set up our interrupt urb */
-				usb_fill_int_urb(edge_serial->interrupt_read_urb,
-						 dev,
-						 usb_rcvintpipe(dev, endpoint->bEndpointAddress),
-						 edge_serial->interrupt_in_buffer,
-						 buffer_size,
-						 edge_interrupt_callback,
-						 edge_serial,
-						 endpoint->bInterval);
+				usb_fill_int_urb(
+					edge_serial->interrupt_read_urb,
+					dev,
+					usb_rcvintpipe(dev,
+						endpoint->bEndpointAddress),
+					edge_serial->interrupt_in_buffer,
+					buffer_size,
+					edge_interrupt_callback,
+					edge_serial,
+					endpoint->bInterval);
 
 				interrupt_in_found = true;
 			}
 
 			if (!bulk_in_found &&
-			    (usb_endpoint_is_bulk_in(endpoint))) {
+				(usb_endpoint_is_bulk_in(endpoint))) {
 				/* we found a bulk in endpoint */
 				dbg("found bulk in");
 
 				/* not set up yet, so do it now */
-				edge_serial->read_urb = usb_alloc_urb(0, GFP_KERNEL);
+				edge_serial->read_urb =
+						usb_alloc_urb(0, GFP_KERNEL);
 				if (!edge_serial->read_urb) {
 					err("out of memory");
 					return -ENOMEM;
 				}
-				edge_serial->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
+				edge_serial->bulk_in_buffer =
+					kmalloc(buffer_size, GFP_KERNEL);
 				if (!edge_serial->bulk_in_buffer) {
-					err ("out of memory");
+					err("out of memory");
 					usb_free_urb(edge_serial->read_urb);
 					return -ENOMEM;
 				}
-				edge_serial->bulk_in_endpoint = endpoint->bEndpointAddress;
+				edge_serial->bulk_in_endpoint =
+						endpoint->bEndpointAddress;
 
 				/* set up our bulk in urb */
 				usb_fill_bulk_urb(edge_serial->read_urb, dev,
-						  usb_rcvbulkpipe(dev, endpoint->bEndpointAddress),
-						  edge_serial->bulk_in_buffer,
-						  le16_to_cpu(endpoint->wMaxPacketSize),
-						  edge_bulk_in_callback,
-						  edge_serial);
+					usb_rcvbulkpipe(dev,
+						endpoint->bEndpointAddress),
+					edge_serial->bulk_in_buffer,
+					le16_to_cpu(endpoint->wMaxPacketSize),
+					edge_bulk_in_callback,
+					edge_serial);
 				bulk_in_found = true;
 			}
 
@@ -2996,21 +3159,24 @@
 			    (usb_endpoint_is_bulk_out(endpoint))) {
 				/* we found a bulk out endpoint */
 				dbg("found bulk out");
-				edge_serial->bulk_out_endpoint = endpoint->bEndpointAddress;
+				edge_serial->bulk_out_endpoint =
+						endpoint->bEndpointAddress;
 				bulk_out_found = true;
 			}
 		}
 
 		if (!interrupt_in_found || !bulk_in_found || !bulk_out_found) {
-			err ("Error - the proper endpoints were not found!");
+			err("Error - the proper endpoints were not found!");
 			return -ENODEV;
 		}
 
 		/* start interrupt read for this edgeport this interrupt will
 		 * continue as long as the edgeport is connected */
-		response = usb_submit_urb(edge_serial->interrupt_read_urb, GFP_KERNEL);
+		response = usb_submit_urb(edge_serial->interrupt_read_urb,
+								GFP_KERNEL);
 		if (response)
-			err("%s - Error %d submitting control urb", __func__, response);
+			err("%s - Error %d submitting control urb",
+							__func__, response);
 	}
 	return response;
 }
@@ -3020,7 +3186,7 @@
  * edge_shutdown
  *	This function is called whenever the device is removed from the usb bus.
  ****************************************************************************/
-static void edge_shutdown (struct usb_serial *serial)
+static void edge_shutdown(struct usb_serial *serial)
 {
 	struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
 	int i;
@@ -3028,8 +3194,8 @@
 	dbg("%s", __func__);
 
 	/* stop reads and writes on all ports */
-	for (i=0; i < serial->num_ports; ++i) {
-		kfree (usb_get_serial_port_data(serial->port[i]));
+	for (i = 0; i < serial->num_ports; ++i) {
+		kfree(usb_get_serial_port_data(serial->port[i]));
 		usb_set_serial_port_data(serial->port[i],  NULL);
 	}
 	/* free up our endpoint stuff */
@@ -3069,7 +3235,7 @@
 	if (retval)
 		goto failed_epic_device_register;
 	retval = usb_register(&io_driver);
-	if (retval) 
+	if (retval)
 		goto failed_usb_register;
 	atomic_set(&CmdUrbs, 0);
 	info(DRIVER_DESC " " DRIVER_VERSION);
@@ -3094,19 +3260,19 @@
  ****************************************************************************/
 static void __exit edgeport_exit (void)
 {
-	usb_deregister (&io_driver);
-	usb_serial_deregister (&edgeport_2port_device);
-	usb_serial_deregister (&edgeport_4port_device);
-	usb_serial_deregister (&edgeport_8port_device);
-	usb_serial_deregister (&epic_device);
+	usb_deregister(&io_driver);
+	usb_serial_deregister(&edgeport_2port_device);
+	usb_serial_deregister(&edgeport_4port_device);
+	usb_serial_deregister(&edgeport_8port_device);
+	usb_serial_deregister(&epic_device);
 }
 
 module_init(edgeport_init);
 module_exit(edgeport_exit);
 
 /* Module information */
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 MODULE_FIRMWARE("edgeport/boot.fw");
 MODULE_FIRMWARE("edgeport/boot2.fw");
diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
index 2ec8589..7eb9d67 100644
--- a/drivers/usb/serial/io_tables.h
+++ b/drivers/usb/serial/io_tables.h
@@ -8,7 +8,7 @@
  *	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 IO_TABLES_H
@@ -90,10 +90,10 @@
 	{ USB_DEVICE(USB_VENDOR_ID_AXIOHM, AXIOHM_DEVICE_ID_EPIC_A758) },
 	{ USB_DEVICE(USB_VENDOR_ID_AXIOHM, AXIOHM_DEVICE_ID_EPIC_A794) },
 	{ USB_DEVICE(USB_VENDOR_ID_AXIOHM, AXIOHM_DEVICE_ID_EPIC_A225) },
-	{ }							/* Terminating entry */
+	{ } /* Terminating entry */
 };
 
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
 
 static struct usb_driver io_driver = {
 	.name =		"io_edgeport",
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 61daea3..cb4c543 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -18,8 +18,8 @@
  *
  * Version history:
  *
- *	July 11, 2002 	Removed 4 port device structure since all TI UMP 
- *			chips have only 2 ports 
+ *	July 11, 2002 	Removed 4 port device structure since all TI UMP
+ *			chips have only 2 ports
  *			David Iacovelli (davidi@ionetworks.com)
  *
  */
@@ -38,7 +38,7 @@
 #include <linux/serial.h>
 #include <linux/ioctl.h>
 #include <linux/firmware.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
@@ -57,18 +57,19 @@
 
 
 struct edgeport_uart_buf_desc {
-	__u32 count;		// Number of bytes currently in buffer
+	__u32 count;		/* Number of bytes currently in buffer */
 };
 
 /* different hardware types */
 #define HARDWARE_TYPE_930	0
 #define HARDWARE_TYPE_TIUMP	1
 
-// IOCTL_PRIVATE_TI_GET_MODE Definitions
-#define	TI_MODE_CONFIGURING	0   // Device has not entered start device 
-#define	TI_MODE_BOOT		1   // Staying in boot mode
-#define TI_MODE_DOWNLOAD	2   // Made it to download mode
-#define TI_MODE_TRANSITIONING	3   // Currently in boot mode but transitioning to download mode
+/* IOCTL_PRIVATE_TI_GET_MODE Definitions */
+#define	TI_MODE_CONFIGURING	0   /* Device has not entered start device */
+#define	TI_MODE_BOOT		1   /* Staying in boot mode		   */
+#define TI_MODE_DOWNLOAD	2   /* Made it to download mode		   */
+#define TI_MODE_TRANSITIONING	3   /* Currently in boot mode but
+				       transitioning to download mode	   */
 
 /* read urb state */
 #define EDGE_READ_URB_RUNNING	0
@@ -82,10 +83,9 @@
 
 
 /* Product information read from the Edgeport */
-struct product_info
-{
-	int	TiMode;			// Current TI Mode
-	__u8	hardware_type;		// Type of hardware
+struct product_info {
+	int	TiMode;			/* Current TI Mode  */
+	__u8	hardware_type;		/* Type of hardware */
 } __attribute__((packed));
 
 /* circular buffer */
@@ -116,7 +116,7 @@
 						   happen */
 	struct edgeport_serial	*edge_serial;
 	struct usb_serial_port	*port;
-	__u8 bUartMode;		/* Port type, 0: RS232, etc. */ 
+	__u8 bUartMode;		/* Port type, 0: RS232, etc. */
 	spinlock_t ep_lock;
 	int ep_read_urb_state;
 	int ep_write_urb_in_use;
@@ -125,8 +125,9 @@
 
 struct edgeport_serial {
 	struct product_info product_info;
-	u8 TI_I2C_Type;			// Type of I2C in UMP
-	u8 TiReadI2C;			// Set to TRUE if we have read the I2c in Boot Mode
+	u8 TI_I2C_Type;			/* Type of I2C in UMP */
+	u8 TiReadI2C;			/* Set to TRUE if we have read the
+					   I2c in Boot Mode */
 	struct mutex es_lock;
 	int num_ports_open;
 	struct usb_serial *serial;
@@ -214,7 +215,7 @@
 	{ }
 };
 
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
 
 static struct usb_driver io_driver = {
 	.name =		"io_ti",
@@ -231,20 +232,20 @@
 
 static int debug;
 
-static int TIStayInBootMode = 0;
 static int low_latency = EDGE_LOW_LATENCY;
 static int closing_wait = EDGE_CLOSING_WAIT;
-static int ignore_cpu_rev = 0;
-static int default_uart_mode = 0;	/* RS232 */
+static int ignore_cpu_rev;
+static int default_uart_mode;		/* RS232 */
 
-
-static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length);
+static void edge_tty_recv(struct device *dev, struct tty_struct *tty,
+			  unsigned char *data, int length);
 
 static void stop_read(struct edgeport_port *edge_port);
 static int restart_read(struct edgeport_port *edge_port);
 
-static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
-static void edge_send(struct usb_serial_port *port);
+static void edge_set_termios(struct tty_struct *tty,
+		struct usb_serial_port *port, struct ktermios *old_termios);
+static void edge_send(struct tty_struct *tty);
 
 /* sysfs attributes */
 static int edge_create_sysfs_attrs(struct usb_serial_port *port);
@@ -262,87 +263,57 @@
 	unsigned int count);
 
 
-static int TIReadVendorRequestSync (struct usb_device *dev,
-				__u8		request,
-				__u16		value,
-				__u16		index,
-				u8 		*data,
-				int		size)
+static int ti_vread_sync(struct usb_device *dev, __u8 request,
+				__u16 value, __u16 index, u8 *data, int size)
 {
 	int status;
 
-	status = usb_control_msg (dev,
-				usb_rcvctrlpipe(dev, 0),
-				request,
-				(USB_TYPE_VENDOR | 
-				 USB_RECIP_DEVICE | 
-				 USB_DIR_IN),
-				value,
-				index,
-				data,
-				size,
-				1000);
+	status = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), request,
+			(USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN),
+			value, index, data, size, 1000);
 	if (status < 0)
 		return status;
 	if (status != size) {
-		dbg ("%s - wanted to write %d, but only wrote %d",
+		dbg("%s - wanted to write %d, but only wrote %d",
+					     __func__, size, status);
+		return -ECOMM;
+	}
+	return 0;
+}
+
+static int ti_vsend_sync(struct usb_device *dev, __u8 request,
+				__u16 value, __u16 index, u8 *data, int size)
+{
+	int status;
+
+	status = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request,
+			(USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT),
+			value, index, data, size, 1000);
+	if (status < 0)
+		return status;
+	if (status != size) {
+		dbg("%s - wanted to write %d, but only wrote %d",
 		     __func__, size, status);
 		return -ECOMM;
 	}
 	return 0;
 }
 
-static int TISendVendorRequestSync (struct usb_device *dev,
-				__u8		request,
-				__u16		value,
-				__u16		index,
-				u8 		*data,
-				int		size)
-{
-	int status;
-
-	status = usb_control_msg (dev,
-				usb_sndctrlpipe(dev, 0),
-				request,
-				(USB_TYPE_VENDOR | 
-				 USB_RECIP_DEVICE | 
-				 USB_DIR_OUT),
-				value,
-				index,
-				data,
-				size,
-				1000);
-	if (status < 0)
-		return status;
-	if (status != size) {
-		dbg ("%s - wanted to write %d, but only wrote %d",
-		     __func__, size, status);
-		return -ECOMM;
-	}
-	return 0;
-}
-
-static int TIWriteCommandSync (struct usb_device *dev, __u8 command,
+static int send_cmd(struct usb_device *dev, __u8 command,
 				__u8 moduleid, __u16 value, u8 *data,
 				int size)
 {
-	return TISendVendorRequestSync (dev,
-					  command,	  		// Request
-					  value,			// wValue 
-					  moduleid,			// wIndex
-					  data,				// TransferBuffer
-					  size);			// TransferBufferLength
-
+	return ti_vsend_sync(dev, command, value, moduleid, data, size);
 }
 
 /* clear tx/rx buffers and fifo in TI UMP */
-static int TIPurgeDataSync (struct usb_serial_port *port, __u16 mask)
+static int purge_port(struct usb_serial_port *port, __u16 mask)
 {
 	int port_number = port->number - port->serial->minor;
 
-	dbg ("%s - port %d, mask %x", __func__, port_number, mask);
+	dbg("%s - port %d, mask %x", __func__, port_number, mask);
 
-	return TIWriteCommandSync (port->serial->dev,
+	return send_cmd(port->serial->dev,
 					UMPC_PURGE_PORT,
 					(__u8)(UMPM_UART1_PORT + port_number),
 					mask,
@@ -351,92 +322,87 @@
 }
 
 /**
- * TIReadDownloadMemory - Read edgeport memory from TI chip
+ * read_download_mem - Read edgeport memory from TI chip
  * @dev: usb device pointer
  * @start_address: Device CPU address at which to read
  * @length: Length of above data
  * @address_type: Can read both XDATA and I2C
  * @buffer: pointer to input data buffer
  */
-static int TIReadDownloadMemory(struct usb_device *dev, int start_address,
+static int read_download_mem(struct usb_device *dev, int start_address,
 				int length, __u8 address_type, __u8 *buffer)
 {
 	int status = 0;
 	__u8 read_length;
 	__be16 be_start_address;
-	
-	dbg ("%s - @ %x for %d", __func__, start_address, length);
+
+	dbg("%s - @ %x for %d", __func__, start_address, length);
 
 	/* Read in blocks of 64 bytes
 	 * (TI firmware can't handle more than 64 byte reads)
 	 */
 	while (length) {
 		if (length > 64)
-			read_length= 64;
+			read_length = 64;
 		else
 			read_length = (__u8)length;
 
 		if (read_length > 1) {
-			dbg ("%s - @ %x for %d", __func__,
+			dbg("%s - @ %x for %d", __func__,
 			     start_address, read_length);
 		}
-		be_start_address = cpu_to_be16 (start_address);
-		status = TIReadVendorRequestSync (dev,
-						  UMPC_MEMORY_READ,	// Request
-						  (__u16)address_type,	// wValue (Address type)
-						  (__force __u16)be_start_address,	// wIndex (Address to read)
-						  buffer,		// TransferBuffer
-						  read_length);	// TransferBufferLength
+		be_start_address = cpu_to_be16(start_address);
+		status = ti_vread_sync(dev, UMPC_MEMORY_READ,
+					(__u16)address_type,
+					(__force __u16)be_start_address,
+					buffer, read_length);
 
 		if (status) {
-			dbg ("%s - ERROR %x", __func__, status);
+			dbg("%s - ERROR %x", __func__, status);
 			return status;
 		}
 
-		if (read_length > 1) {
+		if (read_length > 1)
 			usb_serial_debug_data(debug, &dev->dev, __func__,
 					      read_length, buffer);
-		}
 
 		/* Update pointers/length */
 		start_address += read_length;
 		buffer += read_length;
 		length -= read_length;
 	}
-	
+
 	return status;
 }
 
-static int TIReadRam (struct usb_device *dev, int start_address, int length, __u8 *buffer)
+static int read_ram(struct usb_device *dev, int start_address,
+						int length, __u8 *buffer)
 {
-	return TIReadDownloadMemory (dev,
-				     start_address,
-				     length,
-				     DTK_ADDR_SPACE_XDATA,
-				     buffer);
+	return read_download_mem(dev, start_address, length,
+					DTK_ADDR_SPACE_XDATA, buffer);
 }
 
 /* Read edgeport memory to a given block */
-static int TIReadBootMemory (struct edgeport_serial *serial, int start_address, int length, __u8 * buffer)
+static int read_boot_mem(struct edgeport_serial *serial,
+				int start_address, int length, __u8 *buffer)
 {
 	int status = 0;
 	int i;
 
-	for (i=0; i< length; i++) {
-		status = TIReadVendorRequestSync (serial->serial->dev,
-					UMPC_MEMORY_READ,		// Request
-					serial->TI_I2C_Type,		// wValue (Address type)
-					(__u16)(start_address+i),	// wIndex
-					&buffer[i],			// TransferBuffer
-					0x01);				// TransferBufferLength
+	for (i = 0; i < length; i++) {
+		status = ti_vread_sync(serial->serial->dev,
+				UMPC_MEMORY_READ, serial->TI_I2C_Type,
+				(__u16)(start_address+i), &buffer[i], 0x01);
 		if (status) {
-			dbg ("%s - ERROR %x", __func__, status);
+			dbg("%s - ERROR %x", __func__, status);
 			return status;
 		}
 	}
 
-	dbg ("%s - start_address = %x, length = %d", __func__, start_address, length);
-	usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, length, buffer);
+	dbg("%s - start_address = %x, length = %d",
+					__func__, start_address, length);
+	usb_serial_debug_data(debug, &serial->serial->dev->dev,
+					__func__, length, buffer);
 
 	serial->TiReadI2C = 1;
 
@@ -444,7 +410,8 @@
 }
 
 /* Write given block to TI EPROM memory */
-static int TIWriteBootMemory (struct edgeport_serial *serial, int start_address, int length, __u8 *buffer)
+static int write_boot_mem(struct edgeport_serial *serial,
+				int start_address, int length, __u8 *buffer)
 {
 	int status = 0;
 	int i;
@@ -452,57 +419,58 @@
 
 	/* Must do a read before write */
 	if (!serial->TiReadI2C) {
-		status = TIReadBootMemory(serial, 0, 1, &temp);
+		status = read_boot_mem(serial, 0, 1, &temp);
 		if (status)
 			return status;
 	}
 
-	for (i=0; i < length; ++i) {
-		status = TISendVendorRequestSync (serial->serial->dev,
-						UMPC_MEMORY_WRITE,		// Request
-						buffer[i],			// wValue
-						(__u16)(i+start_address),	// wIndex
-						NULL,				// TransferBuffer
-						0);				// TransferBufferLength
+	for (i = 0; i < length; ++i) {
+		status = ti_vsend_sync(serial->serial->dev,
+				UMPC_MEMORY_WRITE, buffer[i],
+				(__u16)(i + start_address), NULL, 0);
 		if (status)
 			return status;
 	}
 
-  	dbg ("%s - start_sddr = %x, length = %d", __func__, start_address, length);
-	usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, length, buffer);
+	dbg("%s - start_sddr = %x, length = %d",
+					__func__, start_address, length);
+	usb_serial_debug_data(debug, &serial->serial->dev->dev,
+					__func__, length, buffer);
 
 	return status;
 }
 
 
 /* Write edgeport I2C memory to TI chip	*/
-static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address, int length, __u8 address_type, __u8 *buffer)
+static int write_i2c_mem(struct edgeport_serial *serial,
+		int start_address, int length, __u8 address_type, __u8 *buffer)
 {
 	int status = 0;
 	int write_length;
 	__be16 be_start_address;
 
 	/* We can only send a maximum of 1 aligned byte page at a time */
-	
+
 	/* calulate the number of bytes left in the first page */
-	write_length = EPROM_PAGE_SIZE - (start_address & (EPROM_PAGE_SIZE - 1));
+	write_length = EPROM_PAGE_SIZE -
+				(start_address & (EPROM_PAGE_SIZE - 1));
 
 	if (write_length > length)
 		write_length = length;
 
-	dbg ("%s - BytesInFirstPage Addr = %x, length = %d", __func__, start_address, write_length);
-	usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, write_length, buffer);
+	dbg("%s - BytesInFirstPage Addr = %x, length = %d",
+					__func__, start_address, write_length);
+	usb_serial_debug_data(debug, &serial->serial->dev->dev,
+						__func__, write_length, buffer);
 
 	/* Write first page */
-	be_start_address = cpu_to_be16 (start_address);
-	status = TISendVendorRequestSync (serial->serial->dev,
-					UMPC_MEMORY_WRITE,	// Request
-					(__u16)address_type,	// wValue
-					(__force __u16)be_start_address,	// wIndex
-					buffer,			// TransferBuffer
-					write_length);
+	be_start_address = cpu_to_be16(start_address);
+	status = ti_vsend_sync(serial->serial->dev,
+				UMPC_MEMORY_WRITE, (__u16)address_type,
+				(__force __u16)be_start_address,
+				buffer,	write_length);
 	if (status) {
-		dbg ("%s - ERROR %d", __func__, status);
+		dbg("%s - ERROR %d", __func__, status);
 		return status;
 	}
 
@@ -510,29 +478,31 @@
 	start_address	+= write_length;
 	buffer		+= write_length;
 
-	/* We should be aligned now -- can write max page size bytes at a time */
+	/* We should be aligned now -- can write
+	   max page size bytes at a time */
 	while (length) {
 		if (length > EPROM_PAGE_SIZE)
 			write_length = EPROM_PAGE_SIZE;
 		else
 			write_length = length;
 
-		dbg ("%s - Page Write Addr = %x, length = %d", __func__, start_address, write_length);
-		usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, write_length, buffer);
+		dbg("%s - Page Write Addr = %x, length = %d",
+					__func__, start_address, write_length);
+		usb_serial_debug_data(debug, &serial->serial->dev->dev,
+					__func__, write_length, buffer);
 
 		/* Write next page */
-		be_start_address = cpu_to_be16 (start_address);
-		status = TISendVendorRequestSync (serial->serial->dev,
-						UMPC_MEMORY_WRITE,	// Request
-						(__u16)address_type,	// wValue
-						(__force __u16)be_start_address,	// wIndex
-						buffer,	  		// TransferBuffer
-						write_length);		// TransferBufferLength
+		be_start_address = cpu_to_be16(start_address);
+		status = ti_vsend_sync(serial->serial->dev, UMPC_MEMORY_WRITE,
+				(__u16)address_type,
+				(__force __u16)be_start_address,
+				buffer, write_length);
 		if (status) {
-			dev_err (&serial->serial->dev->dev, "%s - ERROR %d\n", __func__, status);
+			dev_err(&serial->serial->dev->dev, "%s - ERROR %d\n",
+					__func__, status);
 			return status;
 		}
-		
+
 		length		-= write_length;
 		start_address	+= write_length;
 		buffer		+= write_length;
@@ -541,25 +511,25 @@
 }
 
 /* Examine the UMP DMA registers and LSR
- * 
+ *
  * Check the MSBit of the X and Y DMA byte count registers.
  * A zero in this bit indicates that the TX DMA buffers are empty
  * then check the TX Empty bit in the UART.
  */
-static int TIIsTxActive (struct edgeport_port *port)
+static int tx_active(struct edgeport_port *port)
 {
 	int status;
 	struct out_endpoint_desc_block *oedb;
 	__u8 *lsr;
 	int bytes_left = 0;
 
-	oedb = kmalloc (sizeof (* oedb), GFP_KERNEL);
+	oedb = kmalloc(sizeof(*oedb), GFP_KERNEL);
 	if (!oedb) {
-		dev_err (&port->port->dev, "%s - out of memory\n", __func__);
+		dev_err(&port->port->dev, "%s - out of memory\n", __func__);
 		return -ENOMEM;
 	}
 
-	lsr = kmalloc (1, GFP_KERNEL);	/* Sigh, that's right, just one byte,
+	lsr = kmalloc(1, GFP_KERNEL);	/* Sigh, that's right, just one byte,
 					   as not all platforms can do DMA
 					   from stack */
 	if (!lsr) {
@@ -567,51 +537,47 @@
 		return -ENOMEM;
 	}
 	/* Read the DMA Count Registers */
-	status = TIReadRam (port->port->serial->dev,
-			    port->dma_address,
-			    sizeof( *oedb),
-			    (void *)oedb);
-
+	status = read_ram(port->port->serial->dev, port->dma_address,
+						sizeof(*oedb), (void *)oedb);
 	if (status)
 		goto exit_is_tx_active;
 
-	dbg ("%s - XByteCount    0x%X", __func__, oedb->XByteCount);
+	dbg("%s - XByteCount    0x%X", __func__, oedb->XByteCount);
 
 	/* and the LSR */
-	status = TIReadRam (port->port->serial->dev, 
-			    port->uart_base + UMPMEM_OFFS_UART_LSR,
-			    1,
-			    lsr);
+	status = read_ram(port->port->serial->dev,
+			port->uart_base + UMPMEM_OFFS_UART_LSR, 1, lsr);
 
 	if (status)
 		goto exit_is_tx_active;
-	dbg ("%s - LSR = 0x%X", __func__, *lsr);
-	
+	dbg("%s - LSR = 0x%X", __func__, *lsr);
+
 	/* If either buffer has data or we are transmitting then return TRUE */
-	if ((oedb->XByteCount & 0x80 ) != 0 )
+	if ((oedb->XByteCount & 0x80) != 0)
 		bytes_left += 64;
 
-	if ((*lsr & UMP_UART_LSR_TX_MASK ) == 0 )
+	if ((*lsr & UMP_UART_LSR_TX_MASK) == 0)
 		bytes_left += 1;
 
 	/* We return Not Active if we get any kind of error */
 exit_is_tx_active:
-	dbg ("%s - return %d", __func__, bytes_left );
+	dbg("%s - return %d", __func__, bytes_left);
 
 	kfree(lsr);
 	kfree(oedb);
 	return bytes_left;
 }
 
-static void TIChasePort(struct edgeport_port *port, unsigned long timeout, int flush)
+static void chase_port(struct edgeport_port *port, unsigned long timeout,
+								int flush)
 {
 	int baud_rate;
-	struct tty_struct *tty = port->port->tty;
+	struct tty_struct *tty = port->port->port.tty;
 	wait_queue_t wait;
 	unsigned long flags;
 
 	if (!timeout)
-		timeout = (HZ*EDGE_CLOSING_WAIT)/100;
+		timeout = (HZ * EDGE_CLOSING_WAIT)/100;
 
 	/* wait for data to drain from the buffer */
 	spin_lock_irqsave(&port->ep_lock, flags);
@@ -621,7 +587,8 @@
 		set_current_state(TASK_INTERRUPTIBLE);
 		if (edge_buf_data_avail(port->ep_out_buf) == 0
 		|| timeout == 0 || signal_pending(current)
-		|| !usb_get_intfdata(port->port->serial->interface))  /* disconnect */
+		|| !usb_get_intfdata(port->port->serial->interface))
+			/* disconnect */
 			break;
 		spin_unlock_irqrestore(&port->ep_lock, flags);
 		timeout = schedule_timeout(timeout);
@@ -636,8 +603,9 @@
 	/* wait for data to drain from the device */
 	timeout += jiffies;
 	while ((long)(jiffies - timeout) < 0 && !signal_pending(current)
-	&& usb_get_intfdata(port->port->serial->interface)) {  /* not disconnected */
-		if (!TIIsTxActive(port))
+	&& usb_get_intfdata(port->port->serial->interface)) {
+		/* not disconnected */
+		if (!tx_active(port))
 			break;
 		msleep(10);
 	}
@@ -647,72 +615,72 @@
 		return;
 
 	/* wait one more character time, based on baud rate */
-	/* (TIIsTxActive doesn't seem to wait for the last byte) */
-	if ((baud_rate=port->baud_rate) == 0)
+	/* (tx_active doesn't seem to wait for the last byte) */
+	baud_rate = port->baud_rate;
+	if (baud_rate == 0)
 		baud_rate = 50;
 	msleep(max(1, DIV_ROUND_UP(10000, baud_rate)));
 }
 
-static int TIChooseConfiguration (struct usb_device *dev)
+static int choose_config(struct usb_device *dev)
 {
-	// There may be multiple configurations on this device, in which case
-	// we would need to read and parse all of them to find out which one
-	// we want. However, we just support one config at this point,
-	// configuration # 1, which is Config Descriptor 0.
+	/*
+	 * There may be multiple configurations on this device, in which case
+	 * we would need to read and parse all of them to find out which one
+	 * we want. However, we just support one config at this point,
+	 * configuration # 1, which is Config Descriptor 0.
+	 */
 
-	dbg ("%s - Number of Interfaces = %d", __func__, dev->config->desc.bNumInterfaces);
-	dbg ("%s - MAX Power            = %d", __func__, dev->config->desc.bMaxPower*2);
+	dbg("%s - Number of Interfaces = %d",
+				__func__, dev->config->desc.bNumInterfaces);
+	dbg("%s - MAX Power            = %d",
+				__func__, dev->config->desc.bMaxPower * 2);
 
 	if (dev->config->desc.bNumInterfaces != 1) {
-		dev_err (&dev->dev, "%s - bNumInterfaces is not 1, ERROR!\n", __func__);
+		dev_err(&dev->dev, "%s - bNumInterfaces is not 1, ERROR!\n",
+								__func__);
 		return -ENODEV;
 	}
 
 	return 0;
 }
 
-static int TIReadRom (struct edgeport_serial *serial, int start_address, int length, __u8 *buffer)
+static int read_rom(struct edgeport_serial *serial,
+				int start_address, int length, __u8 *buffer)
 {
 	int status;
 
 	if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) {
-		status = TIReadDownloadMemory (serial->serial->dev,
+		status = read_download_mem(serial->serial->dev,
 					       start_address,
 					       length,
 					       serial->TI_I2C_Type,
 					       buffer);
 	} else {
-		status = TIReadBootMemory (serial,
-					   start_address,
-					   length,
-					   buffer);
+		status = read_boot_mem(serial, start_address, length,
+								buffer);
 	}
-
 	return status;
 }
 
-static int TIWriteRom (struct edgeport_serial *serial, int start_address, int length, __u8 *buffer)
+static int write_rom(struct edgeport_serial *serial, int start_address,
+						int length, __u8 *buffer)
 {
 	if (serial->product_info.TiMode == TI_MODE_BOOT)
-		return TIWriteBootMemory (serial,
-					  start_address,
-					  length,
-					  buffer);
+		return write_boot_mem(serial, start_address, length,
+								buffer);
 
 	if (serial->product_info.TiMode == TI_MODE_DOWNLOAD)
-		return TIWriteDownloadI2C (serial,
-					   start_address,
-					   length,
-					   serial->TI_I2C_Type,
-					   buffer);
-
+		return write_i2c_mem(serial, start_address, length,
+						serial->TI_I2C_Type, buffer);
 	return -EINVAL;
 }
 
 
 
 /* Read a descriptor header from I2C based on type */
-static int TIGetDescriptorAddress (struct edgeport_serial *serial, int desc_type, struct ti_i2c_desc *rom_desc)
+static int get_descriptor_addr(struct edgeport_serial *serial,
+				int desc_type, struct ti_i2c_desc *rom_desc)
 {
 	int start_address;
 	int status;
@@ -720,41 +688,42 @@
 	/* Search for requested descriptor in I2C */
 	start_address = 2;
 	do {
-		status = TIReadRom (serial,
+		status = read_rom(serial,
 				   start_address,
 				   sizeof(struct ti_i2c_desc),
-				   (__u8 *)rom_desc );
+				   (__u8 *)rom_desc);
 		if (status)
 			return 0;
 
 		if (rom_desc->Type == desc_type)
 			return start_address;
 
-		start_address = start_address + sizeof(struct ti_i2c_desc) +  rom_desc->Size;
+		start_address = start_address + sizeof(struct ti_i2c_desc)
+							+ rom_desc->Size;
 
 	} while ((start_address < TI_MAX_I2C_SIZE) && rom_desc->Type);
-	
+
 	return 0;
 }
 
 /* Validate descriptor checksum */
-static int ValidChecksum(struct ti_i2c_desc *rom_desc, __u8 *buffer)
+static int valid_csum(struct ti_i2c_desc *rom_desc, __u8 *buffer)
 {
 	__u16 i;
 	__u8 cs = 0;
 
-	for (i=0; i < rom_desc->Size; i++) {
+	for (i = 0; i < rom_desc->Size; i++)
 		cs = (__u8)(cs + buffer[i]);
-	}
+
 	if (cs != rom_desc->CheckSum) {
-		dbg ("%s - Mismatch %x - %x", __func__, rom_desc->CheckSum, cs);
+		dbg("%s - Mismatch %x - %x", __func__, rom_desc->CheckSum, cs);
 		return -EINVAL;
 	}
 	return 0;
 }
 
 /* Make sure that the I2C image is good */
-static int TiValidateI2cImage (struct edgeport_serial *serial)
+static int check_i2c_image(struct edgeport_serial *serial)
 {
 	struct device *dev = &serial->serial->dev->dev;
 	int status = 0;
@@ -763,120 +732,124 @@
 	__u8 *buffer;
 	__u16 ttype;
 
-	rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL);
+	rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL);
 	if (!rom_desc) {
-		dev_err (dev, "%s - out of memory\n", __func__);
+		dev_err(dev, "%s - out of memory\n", __func__);
 		return -ENOMEM;
 	}
-	buffer = kmalloc (TI_MAX_I2C_SIZE, GFP_KERNEL);
+	buffer = kmalloc(TI_MAX_I2C_SIZE, GFP_KERNEL);
 	if (!buffer) {
-		dev_err (dev, "%s - out of memory when allocating buffer\n", __func__);
-		kfree (rom_desc);
+		dev_err(dev, "%s - out of memory when allocating buffer\n",
+								__func__);
+		kfree(rom_desc);
 		return -ENOMEM;
 	}
 
-	// Read the first byte (Signature0) must be 0x52 or 0x10
-	status = TIReadRom (serial, 0, 1, buffer);
+	/* Read the first byte (Signature0) must be 0x52 or 0x10 */
+	status = read_rom(serial, 0, 1, buffer);
 	if (status)
-		goto ExitTiValidateI2cImage; 
+		goto out;
 
 	if (*buffer != UMP5152 && *buffer != UMP3410) {
-		dev_err (dev, "%s - invalid buffer signature\n", __func__);
+		dev_err(dev, "%s - invalid buffer signature\n", __func__);
 		status = -ENODEV;
-		goto ExitTiValidateI2cImage;
+		goto out;
 	}
 
 	do {
-		// Validate the I2C
-		status = TIReadRom (serial,
+		/* Validate the I2C */
+		status = read_rom(serial,
 				start_address,
 				sizeof(struct ti_i2c_desc),
 				(__u8 *)rom_desc);
 		if (status)
 			break;
 
-		if ((start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size) > TI_MAX_I2C_SIZE) {
+		if ((start_address + sizeof(struct ti_i2c_desc) +
+					rom_desc->Size) > TI_MAX_I2C_SIZE) {
 			status = -ENODEV;
-			dbg ("%s - structure too big, erroring out.", __func__);
+			dbg("%s - structure too big, erroring out.", __func__);
 			break;
 		}
 
-		dbg ("%s Type = 0x%x", __func__, rom_desc->Type);
+		dbg("%s Type = 0x%x", __func__, rom_desc->Type);
 
-		// Skip type 2 record
+		/* Skip type 2 record */
 		ttype = rom_desc->Type & 0x0f;
-		if ( ttype != I2C_DESC_TYPE_FIRMWARE_BASIC
-			&& ttype != I2C_DESC_TYPE_FIRMWARE_AUTO ) {
-			// Read the descriptor data
-			status = TIReadRom(serial,
-						start_address+sizeof(struct ti_i2c_desc),
-						rom_desc->Size,
-						buffer);
+		if (ttype != I2C_DESC_TYPE_FIRMWARE_BASIC
+			&& ttype != I2C_DESC_TYPE_FIRMWARE_AUTO) {
+			/* Read the descriptor data */
+			status = read_rom(serial, start_address +
+						sizeof(struct ti_i2c_desc),
+						rom_desc->Size, buffer);
 			if (status)
 				break;
 
-			status = ValidChecksum(rom_desc, buffer);
+			status = valid_csum(rom_desc, buffer);
 			if (status)
 				break;
 		}
-		start_address = start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size;
+		start_address = start_address + sizeof(struct ti_i2c_desc) +
+								rom_desc->Size;
 
-	} while ((rom_desc->Type != I2C_DESC_TYPE_ION) && (start_address < TI_MAX_I2C_SIZE));
+	} while ((rom_desc->Type != I2C_DESC_TYPE_ION) &&
+				(start_address < TI_MAX_I2C_SIZE));
 
-	if ((rom_desc->Type != I2C_DESC_TYPE_ION) || (start_address > TI_MAX_I2C_SIZE))
+	if ((rom_desc->Type != I2C_DESC_TYPE_ION) ||
+				(start_address > TI_MAX_I2C_SIZE))
 		status = -ENODEV;
 
-ExitTiValidateI2cImage:	
-	kfree (buffer);
-	kfree (rom_desc);
+out:
+	kfree(buffer);
+	kfree(rom_desc);
 	return status;
 }
 
-static int TIReadManufDescriptor (struct edgeport_serial *serial, __u8 *buffer)
+static int get_manuf_info(struct edgeport_serial *serial, __u8 *buffer)
 {
 	int status;
 	int start_address;
 	struct ti_i2c_desc *rom_desc;
 	struct edge_ti_manuf_descriptor *desc;
 
-	rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL);
+	rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL);
 	if (!rom_desc) {
-		dev_err (&serial->serial->dev->dev, "%s - out of memory\n", __func__);
+		dev_err(&serial->serial->dev->dev, "%s - out of memory\n",
+								__func__);
 		return -ENOMEM;
 	}
-	start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_ION, rom_desc);
+	start_address = get_descriptor_addr(serial, I2C_DESC_TYPE_ION,
+								rom_desc);
 
 	if (!start_address) {
-		dbg ("%s - Edge Descriptor not found in I2C", __func__);
+		dbg("%s - Edge Descriptor not found in I2C", __func__);
 		status = -ENODEV;
 		goto exit;
 	}
 
-	// Read the descriptor data
-	status = TIReadRom (serial,
-				start_address+sizeof(struct ti_i2c_desc),
-				rom_desc->Size,
-				buffer);
+	/* Read the descriptor data */
+	status = read_rom(serial, start_address+sizeof(struct ti_i2c_desc),
+						rom_desc->Size, buffer);
 	if (status)
 		goto exit;
-	
-	status = ValidChecksum(rom_desc, buffer);
-	
+
+	status = valid_csum(rom_desc, buffer);
+
 	desc = (struct edge_ti_manuf_descriptor *)buffer;
-	dbg ( "%s - IonConfig      0x%x", __func__, desc->IonConfig 	);
-	dbg ( "%s - Version          %d", __func__, desc->Version	  	);
-	dbg ( "%s - Cpu/Board      0x%x", __func__, desc->CpuRev_BoardRev	);
-	dbg ( "%s - NumPorts         %d", __func__, desc->NumPorts  	);
-	dbg ( "%s - NumVirtualPorts  %d", __func__, desc->NumVirtualPorts	);
-	dbg ( "%s - TotalPorts       %d", __func__, desc->TotalPorts  	);
+	dbg("%s - IonConfig      0x%x", __func__, desc->IonConfig);
+	dbg("%s - Version          %d", __func__, desc->Version);
+	dbg("%s - Cpu/Board      0x%x", __func__, desc->CpuRev_BoardRev);
+	dbg("%s - NumPorts         %d", __func__, desc->NumPorts);
+	dbg("%s - NumVirtualPorts  %d", __func__, desc->NumVirtualPorts);
+	dbg("%s - TotalPorts       %d", __func__, desc->TotalPorts);
 
 exit:
-	kfree (rom_desc);
+	kfree(rom_desc);
 	return status;
 }
 
 /* Build firmware header used for firmware update */
-static int BuildI2CFirmwareHeader (__u8 *header, struct device *dev)
+static int build_i2c_fw_hdr(__u8 *header, struct device *dev)
 {
 	__u8 *buffer;
 	int buffer_size;
@@ -889,24 +862,28 @@
 	const struct firmware *fw;
 	const char *fw_name = "edgeport/down3.bin";
 
-	// In order to update the I2C firmware we must change the type 2 record to type 0xF2.
-	// This will force the UMP to come up in Boot Mode.  Then while in boot mode, the driver 
-	// will download the latest firmware (padded to 15.5k) into the UMP ram. 
-	// And finally when the device comes back up in download mode the driver will cause 
-	// the new firmware to be copied from the UMP Ram to I2C and the firmware will update
-	// the record type from 0xf2 to 0x02.
-	
-	// Allocate a 15.5k buffer + 2 bytes for version number (Firmware Record)
-	buffer_size = (((1024 * 16) - 512 )+ sizeof(struct ti_i2c_firmware_rec));
+	/* In order to update the I2C firmware we must change the type 2 record
+	 * to type 0xF2.  This will force the UMP to come up in Boot Mode.
+	 * Then while in boot mode, the driver will download the latest
+	 * firmware (padded to 15.5k) into the UMP ram.  And finally when the
+	 * device comes back up in download mode the driver will cause the new
+	 * firmware to be copied from the UMP Ram to I2C and the firmware will
+	 * update the record type from 0xf2 to 0x02.
+	 */
 
-	buffer = kmalloc (buffer_size, GFP_KERNEL);
+	/* Allocate a 15.5k buffer + 2 bytes for version number
+	 * (Firmware Record) */
+	buffer_size = (((1024 * 16) - 512 ) +
+			sizeof(struct ti_i2c_firmware_rec));
+
+	buffer = kmalloc(buffer_size, GFP_KERNEL);
 	if (!buffer) {
-		dev_err (dev, "%s - out of memory\n", __func__);
+		dev_err(dev, "%s - out of memory\n", __func__);
 		return -ENOMEM;
 	}
-	
+
 	// Set entire image of 0xffs
-	memset (buffer, 0xff, buffer_size);
+	memset(buffer, 0xff, buffer_size);
 
 	err = request_firmware(&fw, fw_name, dev);
 	if (err) {
@@ -921,16 +898,16 @@
 	OperationalMinorVersion = fw->data[1];
 	OperationalBuildNumber = fw->data[2] | (fw->data[3] << 8);
 
-	// Copy version number into firmware record
+	/* Copy version number into firmware record */
 	firmware_rec = (struct ti_i2c_firmware_rec *)buffer;
 
 	firmware_rec->Ver_Major	= OperationalMajorVersion;
 	firmware_rec->Ver_Minor	= OperationalMinorVersion;
 
-	// Pointer to fw_down memory image
+	/* Pointer to fw_down memory image */
 	img_header = (struct ti_i2c_image_header *)&fw->data[4];
 
-	memcpy (buffer + sizeof(struct ti_i2c_firmware_rec),
+	memcpy(buffer + sizeof(struct ti_i2c_firmware_rec),
 		&fw->data[4 + sizeof(struct ti_i2c_image_header)],
 		le16_to_cpu(img_header->Length));
 
@@ -940,12 +917,12 @@
 		cs = (__u8)(cs + buffer[i]);
 	}
 
-	kfree (buffer);
+	kfree(buffer);
 
-	// Build new header
+	/* Build new header */
 	i2c_header =  (struct ti_i2c_desc *)header;
 	firmware_rec =  (struct ti_i2c_firmware_rec*)i2c_header->Data;
-	
+
 	i2c_header->Type	= I2C_DESC_TYPE_FIRMWARE_BLANK;
 	i2c_header->Size	= (__u16)buffer_size;
 	i2c_header->CheckSum	= cs;
@@ -956,103 +933,100 @@
 }
 
 /* Try to figure out what type of I2c we have */
-static int TIGetI2cTypeInBootMode (struct edgeport_serial *serial)
+static int i2c_type_bootmode(struct edgeport_serial *serial)
 {
 	int status;
 	__u8 data;
-		
-	// Try to read type 2
-	status = TIReadVendorRequestSync (serial->serial->dev,
-					UMPC_MEMORY_READ,		// Request
-					DTK_ADDR_SPACE_I2C_TYPE_II,	// wValue (Address type)
-					0,		 		// wIndex
-					&data,				// TransferBuffer
-					0x01);				// TransferBufferLength
+
+	/* Try to read type 2 */
+	status = ti_vread_sync(serial->serial->dev, UMPC_MEMORY_READ,
+				DTK_ADDR_SPACE_I2C_TYPE_II, 0, &data, 0x01);
 	if (status)
-		dbg ("%s - read 2 status error = %d", __func__, status);
+		dbg("%s - read 2 status error = %d", __func__, status);
 	else
-		dbg ("%s - read 2 data = 0x%x", __func__, data);
+		dbg("%s - read 2 data = 0x%x", __func__, data);
 	if ((!status) && (data == UMP5152 || data == UMP3410)) {
-		dbg ("%s - ROM_TYPE_II", __func__);
+		dbg("%s - ROM_TYPE_II", __func__);
 		serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
 		return 0;
 	}
 
-	// Try to read type 3
-	status = TIReadVendorRequestSync (serial->serial->dev,
-					UMPC_MEMORY_READ,		// Request
-					DTK_ADDR_SPACE_I2C_TYPE_III,	// wValue (Address type)
-					0,				// wIndex
-					&data,				// TransferBuffer
-					0x01);				// TransferBufferLength
+	/* Try to read type 3 */
+	status = ti_vread_sync(serial->serial->dev, UMPC_MEMORY_READ,
+				DTK_ADDR_SPACE_I2C_TYPE_III, 0,	&data, 0x01);
 	if (status)
-		dbg ("%s - read 3 status error = %d", __func__, status);
+		dbg("%s - read 3 status error = %d", __func__, status);
 	else
-		dbg ("%s - read 2 data = 0x%x", __func__, data);
+		dbg("%s - read 2 data = 0x%x", __func__, data);
 	if ((!status) && (data == UMP5152 || data == UMP3410)) {
-		dbg ("%s - ROM_TYPE_III", __func__);
+		dbg("%s - ROM_TYPE_III", __func__);
 		serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_III;
 		return 0;
 	}
 
-	dbg ("%s - Unknown", __func__);
+	dbg("%s - Unknown", __func__);
 	serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
 	return -ENODEV;
 }
 
-static int TISendBulkTransferSync (struct usb_serial *serial, void *buffer, int length, int *num_sent)
+static int bulk_xfer(struct usb_serial *serial, void *buffer,
+						int length, int *num_sent)
 {
 	int status;
 
-	status = usb_bulk_msg (serial->dev,
-				usb_sndbulkpipe(serial->dev,
-						serial->port[0]->bulk_out_endpointAddress),
-				buffer,
-				length,
-				num_sent,
-				1000);
+	status = usb_bulk_msg(serial->dev,
+			usb_sndbulkpipe(serial->dev,
+				serial->port[0]->bulk_out_endpointAddress),
+			buffer, length, num_sent, 1000);
 	return status;
 }
 
 /* Download given firmware image to the device (IN BOOT MODE) */
-static int TIDownloadCodeImage (struct edgeport_serial *serial, __u8 *image, int image_length)
+static int download_code(struct edgeport_serial *serial, __u8 *image,
+							int image_length)
 {
 	int status = 0;
 	int pos;
 	int transfer;
 	int done;
 
-	// Transfer firmware image
+	/* Transfer firmware image */
 	for (pos = 0; pos < image_length; ) {
-		// Read the next buffer from file
+		/* Read the next buffer from file */
 		transfer = image_length - pos;
 		if (transfer > EDGE_FW_BULK_MAX_PACKET_SIZE)
 			transfer = EDGE_FW_BULK_MAX_PACKET_SIZE;
 
-		// Transfer data
-		status = TISendBulkTransferSync (serial->serial, &image[pos], transfer, &done);
+		/* Transfer data */
+		status = bulk_xfer(serial->serial, &image[pos],
+							transfer, &done);
 		if (status)
 			break;
-		// Advance buffer pointer
+		/* Advance buffer pointer */
 		pos += done;
 	}
 
 	return status;
 }
 
-// FIXME!!!
-static int TIConfigureBootDevice (struct usb_device *dev)
+/* FIXME!!! */
+static int config_boot_dev(struct usb_device *dev)
 {
 	return 0;
 }
 
+static int ti_cpu_rev(struct edge_ti_manuf_descriptor *desc)
+{
+	return TI_GET_CPU_REVISION(desc->CpuRev_BoardRev);
+}
+
 /**
  * DownloadTIFirmware - Download run-time operating firmware to the TI5052
- * 
+ *
  * This routine downloads the main operating code into the TI5052, using the
  * boot code already burned into E2PROM or ROM.
  */
-static int TIDownloadFirmware (struct edgeport_serial *serial)
+static int download_fw(struct edgeport_serial *serial)
 {
 	struct device *dev = &serial->serial->dev->dev;
 	int status = 0;
@@ -1071,22 +1045,25 @@
 	/* Default to type 2 i2c */
 	serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
 
-	status = TIChooseConfiguration (serial->serial->dev);
+	status = choose_config(serial->serial->dev);
 	if (status)
 		return status;
 
 	interface = &serial->serial->interface->cur_altsetting->desc;
 	if (!interface) {
-		dev_err (dev, "%s - no interface set, error!\n", __func__);
+		dev_err(dev, "%s - no interface set, error!\n", __func__);
 		return -ENODEV;
 	}
 
-	// Setup initial mode -- the default mode 0 is TI_MODE_CONFIGURING
-	// if we have more than one endpoint we are definitely in download mode
+	/*
+	 * Setup initial mode -- the default mode 0 is TI_MODE_CONFIGURING
+	 * if we have more than one endpoint we are definitely in download
+	 * mode
+	 */
 	if (interface->bNumEndpoints > 1)
 		serial->product_info.TiMode = TI_MODE_DOWNLOAD;
 	else
-		// Otherwise we will remain in configuring mode
+		/* Otherwise we will remain in configuring mode */
 		serial->product_info.TiMode = TI_MODE_CONFIGURING;
 
 	/********************************************************************/
@@ -1097,256 +1074,273 @@
 
 		dbg("%s - RUNNING IN DOWNLOAD MODE", __func__);
 
-		status = TiValidateI2cImage (serial);
+		status = check_i2c_image(serial);
 		if (status) {
 			dbg("%s - DOWNLOAD MODE -- BAD I2C", __func__);
 			return status;
 		}
-		
+
 		/* Validate Hardware version number
 		 * Read Manufacturing Descriptor from TI Based Edgeport
 		 */
-		ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL);
+		ti_manuf_desc = kmalloc(sizeof(*ti_manuf_desc), GFP_KERNEL);
 		if (!ti_manuf_desc) {
-			dev_err (dev, "%s - out of memory.\n", __func__);
+			dev_err(dev, "%s - out of memory.\n", __func__);
 			return -ENOMEM;
 		}
-		status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc);
+		status = get_manuf_info(serial, (__u8 *)ti_manuf_desc);
 		if (status) {
-			kfree (ti_manuf_desc);
+			kfree(ti_manuf_desc);
 			return status;
 		}
 
-		// Check version number of ION descriptor
-		if (!ignore_cpu_rev && TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev) < 2) {
-			dbg ( "%s - Wrong CPU Rev %d (Must be 2)", __func__,
-			     TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev));
-			kfree (ti_manuf_desc);
-		   	return -EINVAL;
-		}
+		/* Check version number of ION descriptor */
+		if (!ignore_cpu_rev && ti_cpu_rev(ti_manuf_desc) < 2) {
+			dbg("%s - Wrong CPU Rev %d (Must be 2)",
+				__func__, ti_cpu_rev(ti_manuf_desc));
+			kfree(ti_manuf_desc);
+			return -EINVAL;
+  		}
 
-		rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL);
+		rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL);
 		if (!rom_desc) {
-			dev_err (dev, "%s - out of memory.\n", __func__);
-			kfree (ti_manuf_desc);
+			dev_err(dev, "%s - out of memory.\n", __func__);
+			kfree(ti_manuf_desc);
 			return -ENOMEM;
 		}
 
-		// Search for type 2 record (firmware record)
-		if ((start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_FIRMWARE_BASIC, rom_desc)) != 0) {
+		/* Search for type 2 record (firmware record) */
+		start_address = get_descriptor_addr(serial,
+				I2C_DESC_TYPE_FIRMWARE_BASIC, rom_desc);
+		if (start_address != 0) {
 			struct ti_i2c_firmware_rec *firmware_version;
 			__u8 record;
 
-			dbg ("%s - Found Type FIRMWARE (Type 2) record", __func__);
+			dbg("%s - Found Type FIRMWARE (Type 2) record",
+								__func__);
 
-			firmware_version = kmalloc (sizeof (*firmware_version), GFP_KERNEL);
+			firmware_version = kmalloc(sizeof(*firmware_version),
+								GFP_KERNEL);
 			if (!firmware_version) {
-				dev_err (dev, "%s - out of memory.\n", __func__);
-				kfree (rom_desc);
-				kfree (ti_manuf_desc);
+				dev_err(dev, "%s - out of memory.\n", __func__);
+				kfree(rom_desc);
+				kfree(ti_manuf_desc);
 				return -ENOMEM;
 			}
 
-			// Validate version number				
-			// Read the descriptor data
-			status = TIReadRom (serial,
-					start_address+sizeof(struct ti_i2c_desc),
+			/* Validate version number
+			 * Read the descriptor data
+			 */
+			status = read_rom(serial, start_address +
+					sizeof(struct ti_i2c_desc),
 					sizeof(struct ti_i2c_firmware_rec),
 					(__u8 *)firmware_version);
 			if (status) {
-				kfree (firmware_version);
-				kfree (rom_desc);
-				kfree (ti_manuf_desc);
+				kfree(firmware_version);
+				kfree(rom_desc);
+				kfree(ti_manuf_desc);
 				return status;
 			}
 
-			// Check version number of download with current version in I2c
-			download_cur_ver = (firmware_version->Ver_Major << 8) + 
+			/* Check version number of download with current
+			   version in I2c */
+			download_cur_ver = (firmware_version->Ver_Major << 8) +
 					   (firmware_version->Ver_Minor);
 			download_new_ver = (OperationalMajorVersion << 8) +
 					   (OperationalMinorVersion);
 
-			dbg ("%s - >>>Firmware Versions Device %d.%d  Driver %d.%d",
-			     __func__,
-			     firmware_version->Ver_Major,
-			     firmware_version->Ver_Minor,
-			     OperationalMajorVersion,
-			     OperationalMinorVersion);
+			dbg("%s - >> FW Versions Device %d.%d  Driver %d.%d",
+			    __func__,
+			    firmware_version->Ver_Major,
+			    firmware_version->Ver_Minor,
+			    OperationalMajorVersion,
+			    OperationalMinorVersion);
 
-			// Check if we have an old version in the I2C and update if necessary
+			/* Check if we have an old version in the I2C and
+			   update if necessary */
 			if (download_cur_ver != download_new_ver) {
-				dbg ("%s - Update I2C Download from %d.%d to %d.%d",
-				     __func__,
-				     firmware_version->Ver_Major,
-				     firmware_version->Ver_Minor,
-				     OperationalMajorVersion,
-				     OperationalMinorVersion);
+				dbg("%s - Update I2C dld from %d.%d to %d.%d",
+				    __func__,
+				    firmware_version->Ver_Major,
+				    firmware_version->Ver_Minor,
+				    OperationalMajorVersion,
+				    OperationalMinorVersion);
 
-				// In order to update the I2C firmware we must change the type 2 record to type 0xF2.
-				// This will force the UMP to come up in Boot Mode.  Then while in boot mode, the driver 
-				// will download the latest firmware (padded to 15.5k) into the UMP ram. 
-				// And finally when the device comes back up in download mode the driver will cause 
-				// the new firmware to be copied from the UMP Ram to I2C and the firmware will update
-				// the record type from 0xf2 to 0x02.
-
+				/* In order to update the I2C firmware we must
+				 * change the type 2 record to type 0xF2. This
+				 * will force the UMP to come up in Boot Mode.
+				 * Then while in boot mode, the driver will
+				 * download the latest firmware (padded to
+				 * 15.5k) into the UMP ram. Finally when the
+				 * device comes back up in download mode the
+				 * driver will cause the new firmware to be
+				 * copied from the UMP Ram to I2C and the
+				 * firmware will update the record type from
+				 * 0xf2 to 0x02.
+				 */
 				record = I2C_DESC_TYPE_FIRMWARE_BLANK;
 
-				// Change the I2C Firmware record type to 0xf2 to trigger an update
-				status = TIWriteRom (serial,
-							start_address,
-							sizeof(record),
-							&record);
+				/* Change the I2C Firmware record type to
+				   0xf2 to trigger an update */
+				status = write_rom(serial, start_address,
+						sizeof(record),	&record);
 				if (status) {
-					kfree (firmware_version);
-					kfree (rom_desc);
-					kfree (ti_manuf_desc);
+					kfree(firmware_version);
+					kfree(rom_desc);
+					kfree(ti_manuf_desc);
 					return status;
 				}
 
-				// verify the write -- must do this in order for write to 
-				// complete before we do the hardware reset
-				status = TIReadRom (serial,
+				/* verify the write -- must do this in order
+				 * for write to complete before we do the
+				 * hardware reset
+				 */
+				status = read_rom(serial,
 							start_address,
 							sizeof(record),
 							&record);
-
 				if (status) {
-					kfree (firmware_version);
-					kfree (rom_desc);
-					kfree (ti_manuf_desc);
+					kfree(firmware_version);
+					kfree(rom_desc);
+					kfree(ti_manuf_desc);
 					return status;
 				}
 
 				if (record != I2C_DESC_TYPE_FIRMWARE_BLANK) {
-					dev_err (dev, "%s - error resetting device\n", __func__);
-					kfree (firmware_version);
-					kfree (rom_desc);
-					kfree (ti_manuf_desc);
+					dev_err(dev,
+						"%s - error resetting device\n",
+						__func__);
+					kfree(firmware_version);
+					kfree(rom_desc);
+					kfree(ti_manuf_desc);
 					return -ENODEV;
 				}
 
-				dbg ("%s - HARDWARE RESET", __func__);
+				dbg("%s - HARDWARE RESET", __func__);
 
-				// Reset UMP -- Back to BOOT MODE
-				status = TISendVendorRequestSync (serial->serial->dev,
-								UMPC_HARDWARE_RESET,	// Request
-								0,			// wValue
-								0,			// wIndex
-								NULL,			// TransferBuffer
-								0);			// TransferBufferLength
+				/* Reset UMP -- Back to BOOT MODE */
+				status = ti_vsend_sync(serial->serial->dev,
+						UMPC_HARDWARE_RESET,
+						0, 0, NULL, 0);
 
-				dbg ( "%s - HARDWARE RESET return %d", __func__, status);
+				dbg("%s - HARDWARE RESET return %d",
+						__func__, status);
 
 				/* return an error on purpose. */
-				kfree (firmware_version);
-				kfree (rom_desc);
-				kfree (ti_manuf_desc);
+				kfree(firmware_version);
+				kfree(rom_desc);
+				kfree(ti_manuf_desc);
 				return -ENODEV;
 			}
-			kfree (firmware_version);
+			kfree(firmware_version);
 		}
-		// Search for type 0xF2 record (firmware blank record)
-		else if ((start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_FIRMWARE_BLANK, rom_desc)) != 0) {
-			#define HEADER_SIZE	(sizeof(struct ti_i2c_desc) + sizeof(struct ti_i2c_firmware_rec))
+		/* Search for type 0xF2 record (firmware blank record) */
+		else if ((start_address = get_descriptor_addr(serial, I2C_DESC_TYPE_FIRMWARE_BLANK, rom_desc)) != 0) {
+#define HEADER_SIZE	(sizeof(struct ti_i2c_desc) + \
+					sizeof(struct ti_i2c_firmware_rec))
 			__u8 *header;
 			__u8 *vheader;
 
-			header  = kmalloc (HEADER_SIZE, GFP_KERNEL);
+			header = kmalloc(HEADER_SIZE, GFP_KERNEL);
 			if (!header) {
-				dev_err (dev, "%s - out of memory.\n", __func__);
-				kfree (rom_desc);
-				kfree (ti_manuf_desc);
+				dev_err(dev, "%s - out of memory.\n", __func__);
+				kfree(rom_desc);
+				kfree(ti_manuf_desc);
 				return -ENOMEM;
 			}
-				
-			vheader = kmalloc (HEADER_SIZE, GFP_KERNEL);
-			if (!vheader) {
-				dev_err (dev, "%s - out of memory.\n", __func__);
-				kfree (header);
-				kfree (rom_desc);
-				kfree (ti_manuf_desc);
-				return -ENOMEM;
-			}
-			
-			dbg ("%s - Found Type BLANK FIRMWARE (Type F2) record", __func__);
 
-			// In order to update the I2C firmware we must change the type 2 record to type 0xF2.
-			// This will force the UMP to come up in Boot Mode.  Then while in boot mode, the driver 
-			// will download the latest firmware (padded to 15.5k) into the UMP ram. 
-			// And finally when the device comes back up in download mode the driver will cause 
-			// the new firmware to be copied from the UMP Ram to I2C and the firmware will update
-			// the record type from 0xf2 to 0x02.
-			status = BuildI2CFirmwareHeader(header, dev);
+			vheader = kmalloc(HEADER_SIZE, GFP_KERNEL);
+			if (!vheader) {
+				dev_err(dev, "%s - out of memory.\n", __func__);
+				kfree(header);
+				kfree(rom_desc);
+				kfree(ti_manuf_desc);
+				return -ENOMEM;
+			}
+
+			dbg("%s - Found Type BLANK FIRMWARE (Type F2) record",
+								__func__);
+
+			/*
+			 * In order to update the I2C firmware we must change
+			 * the type 2 record to type 0xF2. This will force the
+			 * UMP to come up in Boot Mode.  Then while in boot
+			 * mode, the driver will download the latest firmware
+			 * (padded to 15.5k) into the UMP ram. Finally when the
+			 * device comes back up in download mode the driver
+			 * will cause the new firmware to be copied from the
+			 * UMP Ram to I2C and the firmware will update the
+			 * record type from 0xf2 to 0x02.
+			 */
+			status = build_i2c_fw_hdr(header, dev);
 			if (status) {
-				kfree (vheader);
-				kfree (header);
-				kfree (rom_desc);
-				kfree (ti_manuf_desc);
+				kfree(vheader);
+				kfree(header);
+				kfree(rom_desc);
+				kfree(ti_manuf_desc);
 				return status;
 			}
 
-			// Update I2C with type 0xf2 record with correct size and checksum
-			status = TIWriteRom (serial,
+			/* Update I2C with type 0xf2 record with correct
+			   size and checksum */
+			status = write_rom(serial,
 						start_address,
 						HEADER_SIZE,
 						header);
 			if (status) {
-				kfree (vheader);
-				kfree (header);
-				kfree (rom_desc);
-				kfree (ti_manuf_desc);
+				kfree(vheader);
+				kfree(header);
+				kfree(rom_desc);
+				kfree(ti_manuf_desc);
 				return status;
 			}
 
-			// verify the write -- must do this in order for write to 
-			// complete before we do the hardware reset
-			status = TIReadRom (serial,
-						start_address,
-						HEADER_SIZE,
-						vheader);
+			/* verify the write -- must do this in order for
+			   write to complete before we do the hardware reset */
+			status = read_rom(serial, start_address,
+							HEADER_SIZE, vheader);
 
 			if (status) {
-				dbg ("%s - can't read header back", __func__);
-				kfree (vheader);
-				kfree (header);
-				kfree (rom_desc);
-				kfree (ti_manuf_desc);
+				dbg("%s - can't read header back", __func__);
+				kfree(vheader);
+				kfree(header);
+				kfree(rom_desc);
+				kfree(ti_manuf_desc);
 				return status;
 			}
 			if (memcmp(vheader, header, HEADER_SIZE)) {
-				dbg ("%s - write download record failed", __func__);
-				kfree (vheader);
-				kfree (header);
-				kfree (rom_desc);
-				kfree (ti_manuf_desc);
+				dbg("%s - write download record failed",
+					__func__);
+				kfree(vheader);
+				kfree(header);
+				kfree(rom_desc);
+				kfree(ti_manuf_desc);
 				return status;
 			}
 
-			kfree (vheader);
-			kfree (header);
+			kfree(vheader);
+			kfree(header);
 
-			dbg ("%s - Start firmware update", __func__);
+			dbg("%s - Start firmware update", __func__);
 
-			// Tell firmware to copy download image into I2C 
-			status = TISendVendorRequestSync (serial->serial->dev,
-						UMPC_COPY_DNLD_TO_I2C,	// Request
-						0,			// wValue 
-						0,			// wIndex
-						NULL,			// TransferBuffer
-						0);			// TransferBufferLength
+			/* Tell firmware to copy download image into I2C */
+			status = ti_vsend_sync(serial->serial->dev,
+					UMPC_COPY_DNLD_TO_I2C, 0, 0, NULL, 0);
 
-		  	dbg ("%s - Update complete 0x%x", __func__, status);
+		  	dbg("%s - Update complete 0x%x", __func__, status);
 			if (status) {
-				dev_err (dev, "%s - UMPC_COPY_DNLD_TO_I2C failed\n", __func__);
-				kfree (rom_desc);
-				kfree (ti_manuf_desc);
+				dev_err(dev,
+					"%s - UMPC_COPY_DNLD_TO_I2C failed\n",
+								__func__);
+				kfree(rom_desc);
+				kfree(ti_manuf_desc);
 				return status;
 			}
 		}
 
 		// The device is running the download code
-		kfree (rom_desc);
-		kfree (ti_manuf_desc);
+		kfree(rom_desc);
+		kfree(ti_manuf_desc);
 		return 0;
 	}
 
@@ -1355,32 +1349,26 @@
 	/********************************************************************/
 	dbg("%s - RUNNING IN BOOT MODE", __func__);
 
-	// Configure the TI device so we can use the BULK pipes for download
-	status = TIConfigureBootDevice (serial->serial->dev);
+	/* Configure the TI device so we can use the BULK pipes for download */
+	status = config_boot_dev(serial->serial->dev);
 	if (status)
 		return status;
 
-	if (le16_to_cpu(serial->serial->dev->descriptor.idVendor) != USB_VENDOR_ID_ION) {
-		dbg ("%s - VID = 0x%x", __func__,
+	if (le16_to_cpu(serial->serial->dev->descriptor.idVendor)
+							!= USB_VENDOR_ID_ION) {
+		dbg("%s - VID = 0x%x", __func__,
 		     le16_to_cpu(serial->serial->dev->descriptor.idVendor));
 		serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
-		goto StayInBootMode;
+		goto stayinbootmode;
 	}
 
-	// We have an ION device (I2c Must be programmed)
-	// Determine I2C image type
-	if (TIGetI2cTypeInBootMode(serial)) {
-		goto StayInBootMode;
-	}
+	/* We have an ION device (I2c Must be programmed)
+	   Determine I2C image type */
+	if (i2c_type_bootmode(serial))
+		goto stayinbootmode;
 
-	// Registry variable set?
-	if (TIStayInBootMode) {
-		dbg ("%s - TIStayInBootMode", __func__);
-		goto StayInBootMode;
-	}
-
-	// Check for ION Vendor ID and that the I2C is valid
-	if (!TiValidateI2cImage(serial)) {
+	/* Check for ION Vendor ID and that the I2C is valid */
+	if (!check_i2c_image(serial)) {
 		struct ti_i2c_image_header *header;
 		int i;
 		__u8 cs = 0;
@@ -1393,49 +1381,52 @@
 		/* Validate Hardware version number
 		 * Read Manufacturing Descriptor from TI Based Edgeport
 		 */
-		ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL);
+		ti_manuf_desc = kmalloc(sizeof(*ti_manuf_desc), GFP_KERNEL);
 		if (!ti_manuf_desc) {
-			dev_err (dev, "%s - out of memory.\n", __func__);
+			dev_err(dev, "%s - out of memory.\n", __func__);
 			return -ENOMEM;
 		}
-		status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc);
+		status = get_manuf_info(serial, (__u8 *)ti_manuf_desc);
 		if (status) {
-			kfree (ti_manuf_desc);
-			goto StayInBootMode;
+			kfree(ti_manuf_desc);
+			goto stayinbootmode;
 		}
 
-		// Check for version 2
-		if (!ignore_cpu_rev && TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev) < 2) {
-			dbg ("%s - Wrong CPU Rev %d (Must be 2)", __func__,
-			     TI_GET_CPU_REVISION(ti_manuf_desc->CpuRev_BoardRev));
-			kfree (ti_manuf_desc);
-			goto StayInBootMode;
+		/* Check for version 2 */
+		if (!ignore_cpu_rev && ti_cpu_rev(ti_manuf_desc) < 2) {
+			dbg("%s - Wrong CPU Rev %d (Must be 2)",
+					__func__, ti_cpu_rev(ti_manuf_desc));
+			kfree(ti_manuf_desc);
+			goto stayinbootmode;
 		}
 
-		kfree (ti_manuf_desc);
+		kfree(ti_manuf_desc);
 
-		// In order to update the I2C firmware we must change the type 2 record to type 0xF2.
-		// This will force the UMP to come up in Boot Mode.  Then while in boot mode, the driver 
-		// will download the latest firmware (padded to 15.5k) into the UMP ram. 
-		// And finally when the device comes back up in download mode the driver will cause 
-		// the new firmware to be copied from the UMP Ram to I2C and the firmware will update
-		// the record type from 0xf2 to 0x02.
-		
 		/*
+		 * In order to update the I2C firmware we must change the type
+		 * 2 record to type 0xF2. This will force the UMP to come up
+		 * in Boot Mode.  Then while in boot mode, the driver will
+		 * download the latest firmware (padded to 15.5k) into the
+		 * UMP ram. Finally when the device comes back up in download
+		 * mode the driver will cause the new firmware to be copied
+		 * from the UMP Ram to I2C and the firmware will update the
+		 * record type from 0xf2 to 0x02.
+		 *
 		 * Do we really have to copy the whole firmware image,
 		 * or could we do this in place!
 		 */
 
-		// Allocate a 15.5k buffer + 3 byte header
-		buffer_size = (((1024 * 16) - 512) + sizeof(struct ti_i2c_image_header));
-		buffer = kmalloc (buffer_size, GFP_KERNEL);
+		/* Allocate a 15.5k buffer + 3 byte header */
+		buffer_size = (((1024 * 16) - 512) +
+					sizeof(struct ti_i2c_image_header));
+		buffer = kmalloc(buffer_size, GFP_KERNEL);
 		if (!buffer) {
-			dev_err (dev, "%s - out of memory\n", __func__);
+			dev_err(dev, "%s - out of memory\n", __func__);
 			return -ENOMEM;
 		}
-		
-		// Initialize the buffer to 0xff (pad the buffer)
-		memset (buffer, 0xff, buffer_size);
+
+		/* Initialize the buffer to 0xff (pad the buffer) */
+		memset(buffer, 0xff, buffer_size);
 
 		err = request_firmware(&fw, fw_name, dev);
 		if (err) {
@@ -1447,38 +1438,43 @@
 		memcpy(buffer, &fw->data[4], fw->size - 4);
 		release_firmware(fw);
 
-		for(i = sizeof(struct ti_i2c_image_header); i < buffer_size; i++) {
+		for (i = sizeof(struct ti_i2c_image_header);
+				i < buffer_size; i++) {
 			cs = (__u8)(cs + buffer[i]);
 		}
-		
+
 		header = (struct ti_i2c_image_header *)buffer;
-		
-		// update length and checksum after padding
-		header->Length 	 = cpu_to_le16((__u16)(buffer_size - sizeof(struct ti_i2c_image_header)));
+
+		/* update length and checksum after padding */
+		header->Length 	 = cpu_to_le16((__u16)(buffer_size -
+					sizeof(struct ti_i2c_image_header)));
 		header->CheckSum = cs;
 
-		// Download the operational code 
-		dbg ("%s - Downloading operational code image (TI UMP)", __func__);
-		status = TIDownloadCodeImage (serial, buffer, buffer_size);
+		/* Download the operational code  */
+		dbg("%s - Downloading operational code image (TI UMP)",
+								__func__);
+		status = download_code(serial, buffer, buffer_size);
 
-		kfree (buffer);
+		kfree(buffer);
 
 		if (status) {
-	  		dbg ("%s - Error downloading operational code image", __func__);
+			dbg("%s - Error downloading operational code image",
+								__func__);
 			return status;
 		}
 
-		// Device will reboot
+		/* Device will reboot */
 		serial->product_info.TiMode = TI_MODE_TRANSITIONING;
 
-  		dbg ("%s - Download successful -- Device rebooting...", __func__);
+		dbg("%s - Download successful -- Device rebooting...",
+								__func__);
 
 		/* return an error on purpose */
 		return -ENODEV;
 	}
 
-StayInBootMode:
-	// Eprom is invalid or blank stay in boot mode
+stayinbootmode:
+	/* Eprom is invalid or blank stay in boot mode */
 	dbg("%s - STAYING IN BOOT MODE", __func__);
 	serial->product_info.TiMode = TI_MODE_BOOT;
 
@@ -1486,156 +1482,33 @@
 }
 
 
-static int TISetDtr (struct edgeport_port *port)
+static int ti_do_config(struct edgeport_port *port, int feature, int on)
 {
 	int port_number = port->port->number - port->port->serial->minor;
-
-	dbg ("%s", __func__);
-	port->shadow_mcr |= MCR_DTR;
-
-	return TIWriteCommandSync (port->port->serial->dev,
-				UMPC_SET_CLR_DTR,
-				(__u8)(UMPM_UART1_PORT + port_number),
-				1,	/* set */
-				NULL,
-				0);
+	on = !!on;	/* 1 or 0 not bitmask */
+	return send_cmd(port->port->serial->dev,
+			feature, (__u8)(UMPM_UART1_PORT + port_number),
+			on, NULL, 0);
 }
 
-static int TIClearDtr (struct edgeport_port *port)
-{
-	int port_number = port->port->number - port->port->serial->minor;
 
-	dbg ("%s", __func__);
-	port->shadow_mcr &= ~MCR_DTR;
-
-	return TIWriteCommandSync (port->port->serial->dev,
-				UMPC_SET_CLR_DTR,
-				(__u8)(UMPM_UART1_PORT + port_number),
-				0,	/* clear */
-				NULL,
-				0);
-}
-
-static int TISetRts (struct edgeport_port *port)
-{
-	int port_number = port->port->number - port->port->serial->minor;
-
-	dbg ("%s", __func__);
-	port->shadow_mcr |= MCR_RTS;
-
-	return TIWriteCommandSync (port->port->serial->dev,
-				UMPC_SET_CLR_RTS,
-				(__u8)(UMPM_UART1_PORT + port_number),
-				1,	/* set */
-				NULL,
-				0);
-}
-
-static int TIClearRts (struct edgeport_port *port)
-{
-	int port_number = port->port->number - port->port->serial->minor;
-
-	dbg ("%s", __func__);
-	port->shadow_mcr &= ~MCR_RTS;
-
-	return TIWriteCommandSync (port->port->serial->dev,
-				UMPC_SET_CLR_RTS,
-				(__u8)(UMPM_UART1_PORT + port_number),
-				0,	/* clear */
-				NULL,
-				0);
-}
-
-static int TISetLoopBack (struct edgeport_port *port)
-{
-	int port_number = port->port->number - port->port->serial->minor;
-
-	dbg ("%s", __func__);
-
-	return TIWriteCommandSync (port->port->serial->dev,
-				UMPC_SET_CLR_LOOPBACK,
-				(__u8)(UMPM_UART1_PORT + port_number),
-				1,	/* set */
-				NULL,
-				0);
-}
-
-static int TIClearLoopBack (struct edgeport_port *port)
-{
-	int port_number = port->port->number - port->port->serial->minor;
-
-	dbg ("%s", __func__);
-
-	return TIWriteCommandSync (port->port->serial->dev,
-				UMPC_SET_CLR_LOOPBACK,
-				(__u8)(UMPM_UART1_PORT + port_number),
-				0,	/* clear */
-				NULL,
-				0);
-}
-
-static int TISetBreak (struct edgeport_port *port)
-{
-	int port_number = port->port->number - port->port->serial->minor;
-
-	dbg ("%s", __func__);
-
-	return TIWriteCommandSync (port->port->serial->dev,
-				UMPC_SET_CLR_BREAK,
-				(__u8)(UMPM_UART1_PORT + port_number),
-				1,	/* set */
-				NULL,
-				0);
-}
-
-static int TIClearBreak (struct edgeport_port *port)
-{
-	int port_number = port->port->number - port->port->serial->minor;
-
-	dbg ("%s", __func__);
-
-	return TIWriteCommandSync (port->port->serial->dev,
-				UMPC_SET_CLR_BREAK,
-				(__u8)(UMPM_UART1_PORT + port_number),
-				0,	/* clear */
-				NULL,
-				0);
-}
-
-static int TIRestoreMCR (struct edgeport_port *port, __u8 mcr)
+static int restore_mcr(struct edgeport_port *port, __u8 mcr)
 {
 	int status = 0;
 
-	dbg ("%s - %x", __func__, mcr);
+	dbg("%s - %x", __func__, mcr);
 
-	if (mcr & MCR_DTR)
-		status = TISetDtr (port);
-	else
-		status = TIClearDtr (port);
-
+	status = ti_do_config(port, UMPC_SET_CLR_DTR, mcr & MCR_DTR);
 	if (status)
 		return status;
-
-	if (mcr & MCR_RTS)
-		status = TISetRts (port);
-	else
-		status = TIClearRts (port);
-
+	status = ti_do_config(port, UMPC_SET_CLR_RTS, mcr & MCR_RTS);
 	if (status)
 		return status;
-
-	if (mcr & MCR_LOOPBACK)
-		status = TISetLoopBack (port);
-	else
-		status = TIClearLoopBack (port);
-
-	return status;
+	return ti_do_config(port, UMPC_SET_CLR_LOOPBACK, mcr & MCR_LOOPBACK);
 }
 
-
-
 /* Convert TI LSR to standard UART flags */
-static __u8 MapLineStatus (__u8 ti_lsr)
+static __u8 map_line_status(__u8 ti_lsr)
 {
 	__u8 lsr = 0;
 
@@ -1647,22 +1520,23 @@
 	MAP_FLAG(UMP_UART_LSR_PE_MASK, LSR_PAR_ERR)	/* parity error */
 	MAP_FLAG(UMP_UART_LSR_FE_MASK, LSR_FRM_ERR)	/* framing error */
 	MAP_FLAG(UMP_UART_LSR_BR_MASK, LSR_BREAK)	/* break detected */
-	MAP_FLAG(UMP_UART_LSR_RX_MASK, LSR_RX_AVAIL)	/* receive data available */
-	MAP_FLAG(UMP_UART_LSR_TX_MASK, LSR_TX_EMPTY)	/* transmit holding register empty */
+	MAP_FLAG(UMP_UART_LSR_RX_MASK, LSR_RX_AVAIL)	/* rx data available */
+	MAP_FLAG(UMP_UART_LSR_TX_MASK, LSR_TX_EMPTY)	/* tx hold reg empty */
 
 #undef MAP_FLAG
 
 	return lsr;
 }
 
-static void handle_new_msr (struct edgeport_port *edge_port, __u8 msr)
+static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)
 {
 	struct async_icount *icount;
 	struct tty_struct *tty;
 
-	dbg ("%s - %02x", __func__, msr);
+	dbg("%s - %02x", __func__, msr);
 
-	if (msr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
+	if (msr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR |
+			EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
 		icount = &edge_port->icount;
 
 		/* update input line counters */
@@ -1674,13 +1548,13 @@
 			icount->dcd++;
 		if (msr & EDGEPORT_MSR_DELTA_RI)
 			icount->rng++;
-		wake_up_interruptible (&edge_port->delta_msr_wait);
+		wake_up_interruptible(&edge_port->delta_msr_wait);
 	}
 
 	/* Save the new modem status */
 	edge_port->shadow_msr = msr & 0xf0;
 
-	tty = edge_port->port->tty;
+	tty = edge_port->port->port.tty;
 	/* handle CTS flow control */
 	if (tty && C_CRTSCTS(tty)) {
 		if (msr & EDGEPORT_MSR_CTS) {
@@ -1694,26 +1568,27 @@
 	return;
 }
 
-static void handle_new_lsr (struct edgeport_port *edge_port, int lsr_data, __u8 lsr, __u8 data)
+static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data,
+							__u8 lsr, __u8 data)
 {
 	struct async_icount *icount;
-	__u8 new_lsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK));
+	__u8 new_lsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR |
+						LSR_FRM_ERR | LSR_BREAK));
 
-	dbg ("%s - %02x", __func__, new_lsr);
+	dbg("%s - %02x", __func__, new_lsr);
 
 	edge_port->shadow_lsr = lsr;
 
-	if (new_lsr & LSR_BREAK) {
+	if (new_lsr & LSR_BREAK)
 		/*
 		 * Parity and Framing errors only count if they
 		 * occur exclusive of a break being received.
 		 */
 		new_lsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK);
-	}
 
 	/* Place LSR data byte into Rx buffer */
-	if (lsr_data && edge_port->port->tty)
-		edge_tty_recv(&edge_port->port->dev, edge_port->port->tty, &data, 1);
+	if (lsr_data && edge_port->port->port.tty)
+		edge_tty_recv(&edge_port->port->dev, edge_port->port->port.tty, &data, 1);
 
 	/* update input line counters */
 	icount = &edge_port->icount;
@@ -1728,7 +1603,7 @@
 }
 
 
-static void edge_interrupt_callback (struct urb *urb)
+static void edge_interrupt_callback(struct urb *urb)
 {
 	struct edgeport_serial *edge_serial = urb->context;
 	struct usb_serial_port *port;
@@ -1762,66 +1637,71 @@
 	}
 
 	if (!length) {
-		dbg ("%s - no data in urb", __func__);
-		goto exit;
-	}
-		
-	usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, __func__, length, data);
-		
-	if (length != 2) {
-		dbg ("%s - expecting packet of size 2, got %d", __func__, length);
+		dbg("%s - no data in urb", __func__);
 		goto exit;
 	}
 
-	port_number = TIUMP_GET_PORT_FROM_CODE (data[0]);
-	function    = TIUMP_GET_FUNC_FROM_CODE (data[0]);
-	dbg ("%s - port_number %d, function %d, info 0x%x",
+	usb_serial_debug_data(debug, &edge_serial->serial->dev->dev,
+						__func__, length, data);
+
+	if (length != 2) {
+		dbg("%s - expecting packet of size 2, got %d",
+							__func__, length);
+		goto exit;
+	}
+
+	port_number = TIUMP_GET_PORT_FROM_CODE(data[0]);
+	function    = TIUMP_GET_FUNC_FROM_CODE(data[0]);
+	dbg("%s - port_number %d, function %d, info 0x%x",
 	     __func__, port_number, function, data[1]);
 	port = edge_serial->serial->port[port_number];
 	edge_port = usb_get_serial_port_data(port);
 	if (!edge_port) {
-		dbg ("%s - edge_port not found", __func__);
+		dbg("%s - edge_port not found", __func__);
 		return;
 	}
 	switch (function) {
 	case TIUMP_INTERRUPT_CODE_LSR:
-		lsr = MapLineStatus(data[1]);
+		lsr = map_line_status(data[1]);
 		if (lsr & UMP_UART_LSR_DATA_MASK) {
-			/* Save the LSR event for bulk read completion routine */
-			dbg ("%s - LSR Event Port %u LSR Status = %02x",
+			/* Save the LSR event for bulk read
+			   completion routine */
+			dbg("%s - LSR Event Port %u LSR Status = %02x",
 			     __func__, port_number, lsr);
 			edge_port->lsr_event = 1;
 			edge_port->lsr_mask = lsr;
 		} else {
-			dbg ("%s - ===== Port %d LSR Status = %02x ======",
+			dbg("%s - ===== Port %d LSR Status = %02x ======",
 			     __func__, port_number, lsr);
-			handle_new_lsr (edge_port, 0, lsr, 0);
+			handle_new_lsr(edge_port, 0, lsr, 0);
 		}
 		break;
 
-	case TIUMP_INTERRUPT_CODE_MSR:	// MSR
+	case TIUMP_INTERRUPT_CODE_MSR:	/* MSR */
 		/* Copy MSR from UMP */
 		msr = data[1];
-		dbg ("%s - ===== Port %u MSR Status = %02x ======\n",
+		dbg("%s - ===== Port %u MSR Status = %02x ======\n",
 		     __func__, port_number, msr);
-		handle_new_msr (edge_port, msr);
+		handle_new_msr(edge_port, msr);
 		break;
 
 	default:
-		dev_err (&urb->dev->dev, "%s - Unknown Interrupt code from UMP %x\n",
-			 __func__, data[1]);
+		dev_err(&urb->dev->dev,
+			"%s - Unknown Interrupt code from UMP %x\n",
+			__func__, data[1]);
 		break;
-		
+
 	}
 
 exit:
-	retval = usb_submit_urb (urb, GFP_ATOMIC);
+	retval = usb_submit_urb(urb, GFP_ATOMIC);
 	if (retval)
-		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",
 			 __func__, retval);
 }
 
-static void edge_bulk_in_callback (struct urb *urb)
+static void edge_bulk_in_callback(struct urb *urb)
 {
 	struct edgeport_port *edge_port = urb->context;
 	unsigned char *data = urb->transfer_buffer;
@@ -1844,15 +1724,16 @@
 		    __func__, status);
 		return;
 	default:
-		dev_err (&urb->dev->dev,"%s - nonzero read bulk status received: %d\n",
-		     __func__, status);
+		dev_err(&urb->dev->dev,
+			"%s - nonzero read bulk status received: %d\n",
+			     __func__, status);
 	}
 
 	if (status == -EPIPE)
 		goto exit;
 
 	if (status) {
-		dev_err(&urb->dev->dev,"%s - stopping read!\n", __func__);
+		dev_err(&urb->dev->dev, "%s - stopping read!\n", __func__);
 		return;
 	}
 
@@ -1860,23 +1741,24 @@
 
 	if (edge_port->lsr_event) {
 		edge_port->lsr_event = 0;
-		dbg ("%s ===== Port %u LSR Status = %02x, Data = %02x ======",
+		dbg("%s ===== Port %u LSR Status = %02x, Data = %02x ======",
 		     __func__, port_number, edge_port->lsr_mask, *data);
-		handle_new_lsr (edge_port, 1, edge_port->lsr_mask, *data);
+		handle_new_lsr(edge_port, 1, edge_port->lsr_mask, *data);
 		/* Adjust buffer length/pointer */
 		--urb->actual_length;
 		++data;
 	}
 
-	tty = edge_port->port->tty;
+	tty = edge_port->port->port.tty;
 	if (tty && urb->actual_length) {
-		usb_serial_debug_data(debug, &edge_port->port->dev, __func__, urb->actual_length, data);
-
-		if (edge_port->close_pending) {
-			dbg ("%s - close is pending, dropping data on the floor.", __func__);
-		} else {
-			edge_tty_recv(&edge_port->port->dev, tty, data, urb->actual_length);
-		}
+		usb_serial_debug_data(debug, &edge_port->port->dev,
+					__func__, urb->actual_length, data);
+		if (edge_port->close_pending)
+			dbg("%s - close pending, dropping data on the floor",
+								__func__);
+		else
+			edge_tty_recv(&edge_port->port->dev, tty, data,
+							urb->actual_length);
 		edge_port->icount.rx += urb->actual_length;
 	}
 
@@ -1891,37 +1773,31 @@
 	}
 	spin_unlock(&edge_port->ep_lock);
 	if (retval)
-		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",
 			 __func__, retval);
 }
 
-static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length)
+static void edge_tty_recv(struct device *dev, struct tty_struct *tty,
+					unsigned char *data, int length)
 {
-	int cnt;
+	int queued;
 
-	do {
-		cnt = tty_buffer_request_room(tty, length);
-		if (cnt < length) {
-			dev_err(dev, "%s - dropping data, %d bytes lost\n",
-				__func__, length - cnt);
-			if(cnt == 0)
-				break;
-		}
-		tty_insert_flip_string(tty, data, cnt);
-		data += cnt;
-		length -= cnt;
-	} while (length > 0);
-
+	tty_buffer_request_room(tty, length);
+	queued = tty_insert_flip_string(tty, data, length);
+	if (queued < length)
+		dev_err(dev, "%s - dropping data, %d bytes lost\n",
+			__func__, length - queued);
 	tty_flip_buffer_push(tty);
 }
 
-static void edge_bulk_out_callback (struct urb *urb)
+static void edge_bulk_out_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
 	int status = urb->status;
 
-	dbg ("%s - port %d", __func__, port->number);
+	dbg("%s - port %d", __func__, port->number);
 
 	edge_port->ep_write_urb_in_use = 0;
 
@@ -1942,10 +1818,11 @@
 	}
 
 	/* send any buffered data */
-	edge_send(port);
+	edge_send(port->port.tty);
 }
 
-static int edge_open (struct usb_serial_port *port, struct file * filp)
+static int edge_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
 	struct edgeport_serial *edge_serial;
@@ -1961,122 +1838,125 @@
 	if (edge_port == NULL)
 		return -ENODEV;
 
-	port->tty->low_latency = low_latency;
+	if (tty)
+		tty->low_latency = low_latency;
 
 	port_number = port->number - port->serial->minor;
 	switch (port_number) {
-		case 0:
-			edge_port->uart_base = UMPMEM_BASE_UART1;
-			edge_port->dma_address = UMPD_OEDB1_ADDRESS;
-			break;
-		case 1:
-			edge_port->uart_base = UMPMEM_BASE_UART2;
-			edge_port->dma_address = UMPD_OEDB2_ADDRESS;
-			break;
-		default:
-			dev_err (&port->dev, "Unknown port number!!!\n");
-			return -ENODEV;
+	case 0:
+		edge_port->uart_base = UMPMEM_BASE_UART1;
+		edge_port->dma_address = UMPD_OEDB1_ADDRESS;
+		break;
+	case 1:
+		edge_port->uart_base = UMPMEM_BASE_UART2;
+		edge_port->dma_address = UMPD_OEDB2_ADDRESS;
+		break;
+	default:
+		dev_err(&port->dev, "Unknown port number!!!\n");
+		return -ENODEV;
 	}
 
-	dbg ("%s - port_number = %d, uart_base = %04x, dma_address = %04x",
-	     __func__, port_number, edge_port->uart_base, edge_port->dma_address);
+	dbg("%s - port_number = %d, uart_base = %04x, dma_address = %04x",
+				__func__, port_number, edge_port->uart_base,
+				edge_port->dma_address);
 
 	dev = port->serial->dev;
 
-	memset (&(edge_port->icount), 0x00, sizeof(edge_port->icount));
-	init_waitqueue_head (&edge_port->delta_msr_wait);
+	memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount));
+	init_waitqueue_head(&edge_port->delta_msr_wait);
 
 	/* turn off loopback */
-	status = TIClearLoopBack (edge_port);
+	status = ti_do_config(edge_port, UMPC_SET_CLR_LOOPBACK, 0);
 	if (status) {
-		dev_err(&port->dev,"%s - cannot send clear loopback command, %d\n",
+		dev_err(&port->dev,
+				"%s - cannot send clear loopback command, %d\n",
 			__func__, status);
 		return status;
 	}
-	
+
 	/* set up the port settings */
-	edge_set_termios (port, port->tty->termios);
+	if (tty)
+		edge_set_termios(tty, port, port->port.tty->termios);
 
 	/* open up the port */
 
 	/* milliseconds to timeout for DMA transfer */
 	transaction_timeout = 2;
 
-	edge_port->ump_read_timeout = max (20, ((transaction_timeout * 3) / 2) );
+	edge_port->ump_read_timeout =
+				max(20, ((transaction_timeout * 3) / 2));
 
-	// milliseconds to timeout for DMA transfer
-	open_settings = (u8)(UMP_DMA_MODE_CONTINOUS | 
-			     UMP_PIPE_TRANS_TIMEOUT_ENA | 
+	/* milliseconds to timeout for DMA transfer */
+	open_settings = (u8)(UMP_DMA_MODE_CONTINOUS |
+			     UMP_PIPE_TRANS_TIMEOUT_ENA |
 			     (transaction_timeout << 2));
 
-	dbg ("%s - Sending UMPC_OPEN_PORT", __func__);
+	dbg("%s - Sending UMPC_OPEN_PORT", __func__);
 
 	/* Tell TI to open and start the port */
-	status = TIWriteCommandSync (dev,
-					UMPC_OPEN_PORT,
-					(u8)(UMPM_UART1_PORT + port_number),
-					open_settings,
-					NULL,
-					0);
+	status = send_cmd(dev, UMPC_OPEN_PORT,
+		(u8)(UMPM_UART1_PORT + port_number), open_settings, NULL, 0);
 	if (status) {
-		dev_err(&port->dev,"%s - cannot send open command, %d\n", __func__, status);
+		dev_err(&port->dev, "%s - cannot send open command, %d\n",
+							__func__, status);
 		return status;
 	}
 
 	/* Start the DMA? */
-	status = TIWriteCommandSync (dev,
-					UMPC_START_PORT,
-					(u8)(UMPM_UART1_PORT + port_number),
-					0,
-					NULL,
-					0);
+	status = send_cmd(dev, UMPC_START_PORT,
+		(u8)(UMPM_UART1_PORT + port_number), 0, NULL, 0);
 	if (status) {
-		dev_err(&port->dev,"%s - cannot send start DMA command, %d\n", __func__, status);
+		dev_err(&port->dev, "%s - cannot send start DMA command, %d\n",
+							__func__, status);
 		return status;
 	}
 
 	/* Clear TX and RX buffers in UMP */
-	status = TIPurgeDataSync (port, UMP_PORT_DIR_OUT | UMP_PORT_DIR_IN);
+	status = purge_port(port, UMP_PORT_DIR_OUT | UMP_PORT_DIR_IN);
 	if (status) {
-		dev_err(&port->dev,"%s - cannot send clear buffers command, %d\n", __func__, status);
+		dev_err(&port->dev,
+			"%s - cannot send clear buffers command, %d\n",
+			__func__, status);
 		return status;
 	}
 
 	/* Read Initial MSR */
-	status = TIReadVendorRequestSync (dev,
-					UMPC_READ_MSR,	// Request
-					0,		// wValue
-					(__u16)(UMPM_UART1_PORT + port_number),	// wIndex (Address)
-					&edge_port->shadow_msr,			// TransferBuffer
-					1);					// TransferBufferLength
+	status = ti_vread_sync(dev, UMPC_READ_MSR, 0,
+				(__u16)(UMPM_UART1_PORT + port_number),
+				&edge_port->shadow_msr, 1);
 	if (status) {
- 		dev_err(&port->dev,"%s - cannot send read MSR command, %d\n", __func__, status);
+		dev_err(&port->dev, "%s - cannot send read MSR command, %d\n",
+							__func__, status);
 		return status;
 	}
 
-	dbg ("ShadowMSR 0x%X", edge_port->shadow_msr);
- 
+	dbg("ShadowMSR 0x%X", edge_port->shadow_msr);
+
 	/* Set Initial MCR */
 	edge_port->shadow_mcr = MCR_RTS | MCR_DTR;
-	dbg ("ShadowMCR 0x%X", edge_port->shadow_mcr);
+	dbg("ShadowMCR 0x%X", edge_port->shadow_mcr);
 
 	edge_serial = edge_port->edge_serial;
 	if (mutex_lock_interruptible(&edge_serial->es_lock))
 		return -ERESTARTSYS;
 	if (edge_serial->num_ports_open == 0) {
-		/* we are the first port to be opened, let's post the interrupt urb */
+		/* we are the first port to open, post the interrupt urb */
 		urb = edge_serial->serial->port[0]->interrupt_in_urb;
 		if (!urb) {
-			dev_err (&port->dev, "%s - no interrupt urb present, exiting\n", __func__);
+			dev_err(&port->dev,
+				"%s - no interrupt urb present, exiting\n",
+				__func__);
 			status = -EINVAL;
 			goto release_es_lock;
 		}
 		urb->complete = edge_interrupt_callback;
 		urb->context = edge_serial;
 		urb->dev = dev;
-		status = usb_submit_urb (urb, GFP_KERNEL);
+		status = usb_submit_urb(urb, GFP_KERNEL);
 		if (status) {
-			dev_err (&port->dev, "%s - usb_submit_urb failed with value %d\n", __func__, status);
+			dev_err(&port->dev,
+				"%s - usb_submit_urb failed with value %d\n",
+					__func__, status);
 			goto release_es_lock;
 		}
 	}
@@ -2085,13 +1965,14 @@
 	 * reset the data toggle on the bulk endpoints to work around bug in
 	 * host controllers where things get out of sync some times
 	 */
-	usb_clear_halt (dev, port->write_urb->pipe);
-	usb_clear_halt (dev, port->read_urb->pipe);
+	usb_clear_halt(dev, port->write_urb->pipe);
+	usb_clear_halt(dev, port->read_urb->pipe);
 
 	/* start up our bulk read urb */
 	urb = port->read_urb;
 	if (!urb) {
-		dev_err (&port->dev, "%s - no read urb present, exiting\n", __func__);
+		dev_err(&port->dev, "%s - no read urb present, exiting\n",
+								__func__);
 		status = -EINVAL;
 		goto unlink_int_urb;
 	}
@@ -2099,9 +1980,11 @@
 	urb->complete = edge_bulk_in_callback;
 	urb->context = edge_port;
 	urb->dev = dev;
-	status = usb_submit_urb (urb, GFP_KERNEL);
+	status = usb_submit_urb(urb, GFP_KERNEL);
 	if (status) {
-		dev_err (&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __func__, status);
+		dev_err(&port->dev,
+			"%s - read bulk usb_submit_urb failed with value %d\n",
+				__func__, status);
 		goto unlink_int_urb;
 	}
 
@@ -2119,7 +2002,8 @@
 	return status;
 }
 
-static void edge_close (struct usb_serial_port *port, struct file *filp)
+static void edge_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct edgeport_serial *edge_serial;
 	struct edgeport_port *edge_port;
@@ -2127,18 +2011,18 @@
 	int status;
 
 	dbg("%s - port %d", __func__, port->number);
-			 
+
 	edge_serial = usb_get_serial_data(port->serial);
 	edge_port = usb_get_serial_port_data(port);
-	if ((edge_serial == NULL) || (edge_port == NULL))
+	if (edge_serial == NULL || edge_port == NULL)
 		return;
-	
-	/* The bulkreadcompletion routine will check 
+
+	/* The bulkreadcompletion routine will check
 	 * this flag and dump add read data */
 	edge_port->close_pending = 1;
 
 	/* chase the port close and flush */
-	TIChasePort (edge_port, (HZ*closing_wait)/100, 1);
+	chase_port(edge_port, (HZ * closing_wait) / 100, 1);
 
 	usb_kill_urb(port->read_urb);
 	usb_kill_urb(port->write_urb);
@@ -2148,7 +2032,7 @@
 	 * send a close port command to it */
 	dbg("%s - send umpc_close_port", __func__);
 	port_number = port->number - port->serial->minor;
-	status = TIWriteCommandSync (port->serial->dev,
+	status = send_cmd(port->serial->dev,
 				     UMPC_CLOSE_PORT,
 				     (__u8)(UMPM_UART1_PORT + port_number),
 				     0,
@@ -2167,7 +2051,8 @@
 	dbg("%s - exited", __func__);
 }
 
-static int edge_write (struct usb_serial_port *port, const unsigned char *data, int count)
+static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
+				const unsigned char *data, int count)
 {
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
 	unsigned long flags;
@@ -2188,16 +2073,16 @@
 	count = edge_buf_put(edge_port->ep_out_buf, data, count);
 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
 
-	edge_send(port);
+	edge_send(tty);
 
 	return count;
 }
 
-static void edge_send(struct usb_serial_port *port)
+static void edge_send(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	int count, result;
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
-	struct tty_struct *tty = port->tty;
 	unsigned long flags;
 
 
@@ -2223,11 +2108,12 @@
 
 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
 
-	usb_serial_debug_data(debug, &port->dev, __func__, count, port->write_urb->transfer_buffer);
+	usb_serial_debug_data(debug, &port->dev, __func__, count,
+				port->write_urb->transfer_buffer);
 
 	/* set up our urb */
-	usb_fill_bulk_urb (port->write_urb, port->serial->dev,
-			   usb_sndbulkpipe (port->serial->dev,
+	usb_fill_bulk_urb(port->write_urb, port->serial->dev,
+			   usb_sndbulkpipe(port->serial->dev,
 					    port->bulk_out_endpointAddress),
 			   port->write_urb->transfer_buffer, count,
 			   edge_bulk_out_callback,
@@ -2236,23 +2122,23 @@
 	/* send the data out the bulk port */
 	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
 	if (result) {
-		dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result);
+		dev_err(&port->dev,
+			"%s - failed submitting write urb, error %d\n",
+				__func__, result);
 		edge_port->ep_write_urb_in_use = 0;
-		// TODO: reschedule edge_send
-	} else {
+		/* TODO: reschedule edge_send */
+	} else
 		edge_port->icount.tx += count;
-	}
 
 	/* wakeup any process waiting for writes to complete */
 	/* there is now more room in the buffer for new writes */
-	if (tty) {
-		/* let the tty driver wakeup if it has a special write_wakeup function */
+	if (tty)
 		tty_wakeup(tty);
-	}
 }
 
-static int edge_write_room (struct usb_serial_port *port)
+static int edge_write_room(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
 	int room = 0;
 	unsigned long flags;
@@ -2260,9 +2146,9 @@
 	dbg("%s - port %d", __func__, port->number);
 
 	if (edge_port == NULL)
-		return -ENODEV;
+		return 0;
 	if (edge_port->close_pending == 1)
-		return -ENODEV;
+		return 0;
 
 	spin_lock_irqsave(&edge_port->ep_lock, flags);
 	room = edge_buf_space_avail(edge_port->ep_out_buf);
@@ -2272,8 +2158,9 @@
 	return room;
 }
 
-static int edge_chars_in_buffer (struct usb_serial_port *port)
+static int edge_chars_in_buffer(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
 	int chars = 0;
 	unsigned long flags;
@@ -2281,22 +2168,22 @@
 	dbg("%s - port %d", __func__, port->number);
 
 	if (edge_port == NULL)
-		return -ENODEV;
+		return 0;
 	if (edge_port->close_pending == 1)
-		return -ENODEV;
+		return 0;
 
 	spin_lock_irqsave(&edge_port->ep_lock, flags);
 	chars = edge_buf_data_avail(edge_port->ep_out_buf);
 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
 
-	dbg ("%s - returns %d", __func__, chars);
+	dbg("%s - returns %d", __func__, chars);
 	return chars;
 }
 
-static void edge_throttle (struct usb_serial_port *port)
+static void edge_throttle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
-	struct tty_struct *tty;
 	int status;
 
 	dbg("%s - port %d", __func__, port->number);
@@ -2304,16 +2191,10 @@
 	if (edge_port == NULL)
 		return;
 
-	tty = port->tty;
-	if (!tty) {
-		dbg ("%s - no tty available", __func__);
-		return;
-	}
-
 	/* if we are implementing XON/XOFF, send the stop character */
 	if (I_IXOFF(tty)) {
 		unsigned char stop_char = STOP_CHAR(tty);
-		status = edge_write (port, &stop_char, 1);
+		status = edge_write(tty, port, &stop_char, 1);
 		if (status <= 0) {
 			dev_err(&port->dev, "%s - failed to write stop character, %d\n", __func__, status);
 		}
@@ -2326,10 +2207,10 @@
 
 }
 
-static void edge_unthrottle (struct usb_serial_port *port)
+static void edge_unthrottle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
-	struct tty_struct *tty;
 	int status;
 
 	dbg("%s - port %d", __func__, port->number);
@@ -2337,27 +2218,22 @@
 	if (edge_port == NULL)
 		return;
 
-	tty = port->tty;
-	if (!tty) {
-		dbg ("%s - no tty available", __func__);
-		return;
-	}
-
 	/* if we are implementing XON/XOFF, send the start character */
 	if (I_IXOFF(tty)) {
 		unsigned char start_char = START_CHAR(tty);
-		status = edge_write (port, &start_char, 1);
+		status = edge_write(tty, port, &start_char, 1);
 		if (status <= 0) {
 			dev_err(&port->dev, "%s - failed to write start character, %d\n", __func__, status);
 		}
 	}
-
 	/* if we are implementing RTS/CTS, restart reads */
 	/* are the Edgeport will assert the RTS line */
 	if (C_CRTSCTS(tty)) {
 		status = restart_read(edge_port);
 		if (status)
-			dev_err(&port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __func__, status);
+			dev_err(&port->dev,
+				"%s - read bulk usb_submit_urb failed: %d\n",
+							__func__, status);
 	}
 
 }
@@ -2398,22 +2274,23 @@
 	return status;
 }
 
-static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios)
+static void change_port_settings(struct tty_struct *tty,
+		struct edgeport_port *edge_port, struct ktermios *old_termios)
 {
 	struct ump_uart_config *config;
-	struct tty_struct *tty;
 	int baud;
 	unsigned cflag;
 	int status;
-	int port_number = edge_port->port->number - edge_port->port->serial->minor;
+	int port_number = edge_port->port->number -
+					edge_port->port->serial->minor;
 
 	dbg("%s - port %d", __func__, edge_port->port->number);
 
-	tty = edge_port->port->tty;
-
 	config = kmalloc (sizeof (*config), GFP_KERNEL);
 	if (!config) {
-		dev_err (&edge_port->port->dev, "%s - out of memory\n", __func__);
+		*tty->termios = *old_termios;
+		dev_err(&edge_port->port->dev, "%s - out of memory\n",
+								__func__);
 		return;
 	}
 
@@ -2427,22 +2304,22 @@
 	config->bUartMode = (__u8)(edge_port->bUartMode);
 
 	switch (cflag & CSIZE) {
-		case CS5:
-			    config->bDataBits = UMP_UART_CHAR5BITS;
-			    dbg ("%s - data bits = 5", __func__);
-			    break;
-		case CS6:
-			    config->bDataBits = UMP_UART_CHAR6BITS;
-			    dbg ("%s - data bits = 6", __func__);
-			    break;
-		case CS7:
-			    config->bDataBits = UMP_UART_CHAR7BITS;
-			    dbg ("%s - data bits = 7", __func__);
-			    break;
-		default:
-		case CS8:
-			    config->bDataBits = UMP_UART_CHAR8BITS;
-			    dbg ("%s - data bits = 8", __func__);
+	case CS5:
+		    config->bDataBits = UMP_UART_CHAR5BITS;
+		    dbg("%s - data bits = 5", __func__);
+		    break;
+	case CS6:
+		    config->bDataBits = UMP_UART_CHAR6BITS;
+		    dbg("%s - data bits = 6", __func__);
+		    break;
+	case CS7:
+		    config->bDataBits = UMP_UART_CHAR7BITS;
+		    dbg("%s - data bits = 7", __func__);
+		    break;
+	default:
+	case CS8:
+		    config->bDataBits = UMP_UART_CHAR8BITS;
+		    dbg("%s - data bits = 8", __func__);
 			    break;
 	}
 
@@ -2457,7 +2334,7 @@
 			dbg("%s - parity = even", __func__);
 		}
 	} else {
-		config->bParity = UMP_UART_NOPARITY; 	
+		config->bParity = UMP_UART_NOPARITY;
 		dbg("%s - parity = none", __func__);
 	}
 
@@ -2480,29 +2357,26 @@
 		restart_read(edge_port);
 	}
 
-	/* if we are implementing XON/XOFF, set the start and stop character in the device */
-	if (I_IXOFF(tty) || I_IXON(tty)) {
-		config->cXon  = START_CHAR(tty);
-		config->cXoff = STOP_CHAR(tty);
+	/* if we are implementing XON/XOFF, set the start and stop
+	   character in the device */
+	config->cXon  = START_CHAR(tty);
+	config->cXoff = STOP_CHAR(tty);
 
-		/* if we are implementing INBOUND XON/XOFF */
-		if (I_IXOFF(tty)) {
-			config->wFlags |= UMP_MASK_UART_FLAGS_IN_X;
-			dbg ("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
-			     __func__, config->cXon, config->cXoff);
-		} else {
-			dbg ("%s - INBOUND XON/XOFF is disabled", __func__);
-		}
+	/* if we are implementing INBOUND XON/XOFF */
+	if (I_IXOFF(tty)) {
+		config->wFlags |= UMP_MASK_UART_FLAGS_IN_X;
+		dbg("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
+		     __func__, config->cXon, config->cXoff);
+	} else
+		dbg("%s - INBOUND XON/XOFF is disabled", __func__);
 
-		/* if we are implementing OUTBOUND XON/XOFF */
-		if (I_IXON(tty)) {
-			config->wFlags |= UMP_MASK_UART_FLAGS_OUT_X;
-			dbg ("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
-			     __func__, config->cXon, config->cXoff);
-		} else {
-			dbg ("%s - OUTBOUND XON/XOFF is disabled", __func__);
-		}
-	}
+	/* if we are implementing OUTBOUND XON/XOFF */
+	if (I_IXON(tty)) {
+		config->wFlags |= UMP_MASK_UART_FLAGS_OUT_X;
+		dbg("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x",
+		     __func__, config->cXon, config->cXoff);
+	} else
+		dbg("%s - OUTBOUND XON/XOFF is disabled", __func__);
 
 	tty->termios->c_cflag &= ~CMSPAR;
 
@@ -2519,41 +2393,36 @@
 
 	/* FIXME: Recompute actual baud from divisor here */
 
-	dbg ("%s - baud rate = %d, wBaudRate = %d", __func__, baud, config->wBaudRate);
+	dbg("%s - baud rate = %d, wBaudRate = %d", __func__, baud,
+							config->wBaudRate);
 
-	dbg ("wBaudRate:   %d", (int)(461550L / config->wBaudRate));
-	dbg ("wFlags:    0x%x", config->wFlags);
-	dbg ("bDataBits:   %d", config->bDataBits);
-	dbg ("bParity:     %d", config->bParity);
-	dbg ("bStopBits:   %d", config->bStopBits);
-	dbg ("cXon:        %d", config->cXon);
-	dbg ("cXoff:       %d", config->cXoff);
-	dbg ("bUartMode:   %d", config->bUartMode);
+	dbg("wBaudRate:   %d", (int)(461550L / config->wBaudRate));
+	dbg("wFlags:    0x%x", config->wFlags);
+	dbg("bDataBits:   %d", config->bDataBits);
+	dbg("bParity:     %d", config->bParity);
+	dbg("bStopBits:   %d", config->bStopBits);
+	dbg("cXon:        %d", config->cXon);
+	dbg("cXoff:       %d", config->cXoff);
+	dbg("bUartMode:   %d", config->bUartMode);
 
 	/* move the word values into big endian mode */
-	cpu_to_be16s (&config->wFlags);
-	cpu_to_be16s (&config->wBaudRate);
+	cpu_to_be16s(&config->wFlags);
+	cpu_to_be16s(&config->wBaudRate);
 
-	status = TIWriteCommandSync (edge_port->port->serial->dev,
-				UMPC_SET_CONFIG,
+	status = send_cmd(edge_port->port->serial->dev, UMPC_SET_CONFIG,
 				(__u8)(UMPM_UART1_PORT + port_number),
-				0,
-				(__u8 *)config,
-				sizeof(*config));
-	if (status) {
-		dbg ("%s - error %d when trying to write config to device",
+				0, (__u8 *)config, sizeof(*config));
+	if (status)
+		dbg("%s - error %d when trying to write config to device",
 		     __func__, status);
-	}
-
-	kfree (config);
-	
+	kfree(config);
 	return;
 }
 
-static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
+static void edge_set_termios(struct tty_struct *tty,
+		struct usb_serial_port *port, struct ktermios *old_termios)
 {
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
-	struct tty_struct *tty = port->tty;
 	unsigned int cflag;
 
 	cflag = tty->termios->c_cflag;
@@ -2562,20 +2431,19 @@
 	    tty->termios->c_cflag, tty->termios->c_iflag);
 	dbg("%s - old clfag %08x old iflag %08x", __func__,
 	    old_termios->c_cflag, old_termios->c_iflag);
-
 	dbg("%s - port %d", __func__, port->number);
 
 	if (edge_port == NULL)
 		return;
-
 	/* change the port settings to the new ones specified */
-	change_port_settings (edge_port, old_termios);
-
+	change_port_settings(tty, edge_port, old_termios);
 	return;
 }
 
-static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear)
+static int edge_tiocmset(struct tty_struct *tty, struct file *file,
+					unsigned int set, unsigned int clear)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
 	unsigned int mcr;
 	unsigned long flags;
@@ -2601,13 +2469,13 @@
 	edge_port->shadow_mcr = mcr;
 	spin_unlock_irqrestore(&edge_port->ep_lock, flags);
 
-	TIRestoreMCR (edge_port, mcr);
-
+	restore_mcr(edge_port, mcr);
 	return 0;
 }
 
-static int edge_tiocmget(struct usb_serial_port *port, struct file *file)
+static int edge_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
 	unsigned int result = 0;
 	unsigned int msr;
@@ -2634,7 +2502,8 @@
 	return result;
 }
 
-static int get_serial_info (struct edgeport_port *edge_port, struct serial_struct __user *retinfo)
+static int get_serial_info(struct edgeport_port *edge_port,
+				struct serial_struct __user *retinfo)
 {
 	struct serial_struct tmp;
 
@@ -2652,18 +2521,16 @@
 	tmp.baud_base		= 9600;
 	tmp.close_delay		= 5*HZ;
 	tmp.closing_wait	= closing_wait;
-//	tmp.custom_divisor	= state->custom_divisor;
-//	tmp.hub6		= state->hub6;
-//	tmp.io_type		= state->io_type;
-
 
 	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
 		return -EFAULT;
 	return 0;
 }
 
-static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg)
+static int edge_ioctl(struct tty_struct *tty, struct file *file,
+					unsigned int cmd, unsigned long arg)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
 	struct async_icount cnow;
 	struct async_icount cprev;
@@ -2671,81 +2538,64 @@
 	dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
 
 	switch (cmd) {
-		case TIOCINQ:
-			dbg("%s - (%d) TIOCINQ", __func__, port->number);
-//			return get_number_bytes_avail(edge_port, (unsigned int *) arg);
-			break;
-
-		case TIOCSERGETLSR:
-			dbg("%s - (%d) TIOCSERGETLSR", __func__, port->number);
-//			return get_lsr_info(edge_port, (unsigned int *) arg);
-			break;
-
-		case TIOCGSERIAL:
-			dbg("%s - (%d) TIOCGSERIAL", __func__, port->number);
-			return get_serial_info(edge_port, (struct serial_struct __user *) arg);
-			break;
-
-		case TIOCSSERIAL:
-			dbg("%s - (%d) TIOCSSERIAL", __func__, port->number);
-			break;
-
-		case TIOCMIWAIT:
-			dbg("%s - (%d) TIOCMIWAIT", __func__, port->number);
-			cprev = edge_port->icount;
-			while (1) {
-				interruptible_sleep_on(&edge_port->delta_msr_wait);
-				/* see if a signal did it */
-				if (signal_pending(current))
-					return -ERESTARTSYS;
-				cnow = edge_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;
+	case TIOCGSERIAL:
+		dbg("%s - (%d) TIOCGSERIAL", __func__, port->number);
+		return get_serial_info(edge_port,
+				(struct serial_struct __user *) arg);
+	case TIOCMIWAIT:
+		dbg("%s - (%d) TIOCMIWAIT", __func__, port->number);
+		cprev = edge_port->icount;
+		while (1) {
+			interruptible_sleep_on(&edge_port->delta_msr_wait);
+			/* see if a signal did it */
+			if (signal_pending(current))
+				return -ERESTARTSYS;
+			cnow = edge_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;
 			}
-			/* not reached */
-			break;
-
-		case TIOCGICOUNT:
-			dbg ("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
-			     port->number, edge_port->icount.rx, edge_port->icount.tx);
-			if (copy_to_user((void __user *)arg, &edge_port->icount, sizeof(edge_port->icount)))
-				return -EFAULT;
-			return 0;
+			cprev = cnow;
+		}
+		/* not reached */
+		break;
+	case TIOCGICOUNT:
+		dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
+		     port->number, edge_port->icount.rx, edge_port->icount.tx);
+		if (copy_to_user((void __user *)arg, &edge_port->icount,
+				sizeof(edge_port->icount)))
+			return -EFAULT;
+		return 0;
 	}
-
 	return -ENOIOCTLCMD;
 }
 
-static void edge_break (struct usb_serial_port *port, int break_state)
+static void edge_break(struct tty_struct *tty, int break_state)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
 	int status;
+	int bv = 0;	/* Off */
 
-	dbg ("%s - state = %d", __func__, break_state);
+	dbg("%s - state = %d", __func__, break_state);
 
 	/* chase the port close */
-	TIChasePort (edge_port, 0, 0);
+	chase_port(edge_port, 0, 0);
 
-	if (break_state == -1) {
-		status = TISetBreak (edge_port);
-	} else {
-		status = TIClearBreak (edge_port);
-	}
-	if (status) {
-		dbg ("%s - error %d sending break set/clear command.",
+	if (break_state == -1)
+		bv = 1;	/* On */
+	status = ti_do_config(edge_port, UMPC_SET_CLR_BREAK, bv);
+	if (status)
+		dbg("%s - error %d sending break set/clear command.",
 		     __func__, status);
-	}
 }
 
-static int edge_startup (struct usb_serial *serial)
+static int edge_startup(struct usb_serial *serial)
 {
 	struct edgeport_serial *edge_serial;
 	struct edgeport_port *edge_port;
@@ -2765,9 +2615,9 @@
 	edge_serial->serial = serial;
 	usb_set_serial_data(serial, edge_serial);
 
-	status = TIDownloadFirmware (edge_serial);
+	status = download_fw(edge_serial);
 	if (status) {
-		kfree (edge_serial);
+		kfree(edge_serial);
 		return status;
 	}
 
@@ -2775,13 +2625,15 @@
 	for (i = 0; i < serial->num_ports; ++i) {
 		edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL);
 		if (edge_port == NULL) {
-			dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
+			dev_err(&serial->dev->dev, "%s - Out of memory\n",
+								__func__);
 			goto cleanup;
 		}
 		spin_lock_init(&edge_port->ep_lock);
 		edge_port->ep_out_buf = edge_buf_alloc(EDGE_OUT_BUF_SIZE);
 		if (edge_port->ep_out_buf == NULL) {
-			dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
+			dev_err(&serial->dev->dev, "%s - Out of memory\n",
+								__func__);
 			kfree(edge_port);
 			goto cleanup;
 		}
@@ -2790,27 +2642,27 @@
 		usb_set_serial_port_data(serial->port[i], edge_port);
 		edge_port->bUartMode = default_uart_mode;
 	}
-	
+
 	return 0;
 
 cleanup:
-	for (--i; i>=0; --i) {
+	for (--i; i >= 0; --i) {
 		edge_port = usb_get_serial_port_data(serial->port[i]);
 		edge_buf_free(edge_port->ep_out_buf);
 		kfree(edge_port);
 		usb_set_serial_port_data(serial->port[i], NULL);
 	}
-	kfree (edge_serial);
+	kfree(edge_serial);
 	usb_set_serial_data(serial, NULL);
 	return -ENOMEM;
 }
 
-static void edge_shutdown (struct usb_serial *serial)
+static void edge_shutdown(struct usb_serial *serial)
 {
 	int i;
 	struct edgeport_port *edge_port;
 
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 
 	for (i = 0; i < serial->num_ports; ++i) {
 		edge_port = usb_get_serial_port_data(serial->port[i]);
@@ -2852,7 +2704,8 @@
 	return count;
 }
 
-static DEVICE_ATTR(uart_mode, S_IWUSR | S_IRUGO, show_uart_mode, store_uart_mode);
+static DEVICE_ATTR(uart_mode, S_IWUSR | S_IRUGO, show_uart_mode,
+							store_uart_mode);
 
 static int edge_create_sysfs_attrs(struct usb_serial_port *port)
 {
@@ -2922,9 +2775,9 @@
 
 static void edge_buf_clear(struct edge_buf *eb)
 {
-        if (eb != NULL)
-                eb->buf_get = eb->buf_put;
-                /* equivalent to a get of all data available */
+	if (eb != NULL)
+		eb->buf_get = eb->buf_put;
+	/* equivalent to a get of all data available */
 }
 
 
@@ -2937,10 +2790,9 @@
 
 static unsigned int edge_buf_data_avail(struct edge_buf *eb)
 {
-	if (eb != NULL)
-		return ((eb->buf_size + eb->buf_put - eb->buf_get) % eb->buf_size);
-	else
+	if (eb == NULL)
 		return 0;
+	return ((eb->buf_size + eb->buf_put - eb->buf_get) % eb->buf_size);
 }
 
 
@@ -2953,10 +2805,9 @@
 
 static unsigned int edge_buf_space_avail(struct edge_buf *eb)
 {
-	if (eb != NULL)
-		return ((eb->buf_size + eb->buf_get - eb->buf_put - 1) % eb->buf_size);
-	else
+	if (eb == NULL)
 		return 0;
+	return ((eb->buf_size + eb->buf_get - eb->buf_put - 1) % eb->buf_size);
 }
 
 
@@ -3113,7 +2964,7 @@
 	if (retval)
 		goto failed_2port_device_register;
 	retval = usb_register(&io_driver);
-	if (retval) 
+	if (retval)
 		goto failed_usb_register;
 	info(DRIVER_DESC " " DRIVER_VERSION);
 	return 0;
@@ -3125,11 +2976,11 @@
 	return retval;
 }
 
-static void __exit edgeport_exit (void)
+static void __exit edgeport_exit(void)
 {
-	usb_deregister (&io_driver);
-	usb_serial_deregister (&edgeport_1port_device);
-	usb_serial_deregister (&edgeport_2port_device);
+	usb_deregister(&io_driver);
+	usb_serial_deregister(&edgeport_1port_device);
+	usb_serial_deregister(&edgeport_2port_device);
 }
 
 module_init(edgeport_init);
@@ -3151,8 +3002,8 @@
 MODULE_PARM_DESC(closing_wait, "Maximum wait for data to drain, in .01 secs");
 
 module_param(ignore_cpu_rev, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(ignore_cpu_rev, "Ignore the cpu revision when connecting to a device");
+MODULE_PARM_DESC(ignore_cpu_rev,
+			"Ignore the cpu revision when connecting to a device");
 
 module_param(default_uart_mode, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(default_uart_mode, "Default uart_mode, 0=RS232, ...");
-
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index d9fb376..832a5a4 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -53,7 +53,7 @@
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 #include "ipaq.h"
@@ -74,19 +74,21 @@
 static int initial_wait;
 
 /* Function prototypes for an ipaq */
-static int  ipaq_open (struct usb_serial_port *port, struct file *filp);
-static void ipaq_close (struct usb_serial_port *port, struct file *filp);
-static int  ipaq_startup (struct usb_serial *serial);
-static void ipaq_shutdown (struct usb_serial *serial);
-static int ipaq_write(struct usb_serial_port *port, const unsigned char *buf,
-		       int count);
-static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *buf,
-			   int count);
+static int  ipaq_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
+static void ipaq_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
+static int  ipaq_startup(struct usb_serial *serial);
+static void ipaq_shutdown(struct usb_serial *serial);
+static int ipaq_write(struct tty_struct *tty, struct usb_serial_port *port,
+			const unsigned char *buf, int count);
+static int ipaq_write_bulk(struct usb_serial_port *port,
+				const unsigned char *buf, int count);
 static void ipaq_write_gather(struct usb_serial_port *port);
-static void ipaq_read_bulk_callback (struct urb *urb);
+static void ipaq_read_bulk_callback(struct urb *urb);
 static void ipaq_write_bulk_callback(struct urb *urb);
-static int ipaq_write_room(struct usb_serial_port *port);
-static int ipaq_chars_in_buffer(struct usb_serial_port *port);
+static int ipaq_write_room(struct tty_struct *tty);
+static int ipaq_chars_in_buffer(struct tty_struct *tty);
 static void ipaq_destroy_lists(struct usb_serial_port *port);
 
 
@@ -550,7 +552,7 @@
 	{ }                             /* Terminating entry */
 };
 
-MODULE_DEVICE_TABLE (usb, ipaq_id_table);
+MODULE_DEVICE_TABLE(usb, ipaq_id_table);
 
 static struct usb_driver ipaq_driver = {
 	.name =		"ipaq",
@@ -591,7 +593,8 @@
 static int		bytes_in;
 static int		bytes_out;
 
-static int ipaq_open(struct usb_serial_port *port, struct file *filp)
+static int ipaq_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct usb_serial	*serial = port->serial;
 	struct ipaq_private	*priv;
@@ -617,9 +620,9 @@
 
 	for (i = 0; i < URBDATA_QUEUE_MAX / PACKET_SIZE; i++) {
 		pkt = kmalloc(sizeof(struct ipaq_packet), GFP_KERNEL);
-		if (pkt == NULL) {
+		if (pkt == NULL)
 			goto enomem;
-		}
+
 		pkt->data = kmalloc(PACKET_SIZE, GFP_KERNEL);
 		if (pkt->data == NULL) {
 			kfree(pkt);
@@ -637,21 +640,24 @@
 	 * discipline instead of queueing.
 	 */
 
-	port->tty->low_latency = 1;
-	port->tty->raw = 1;
-	port->tty->real_raw = 1;
-
+	if (tty) {
+		tty->low_latency = 1;
+		/* FIXME: These two are bogus */
+		tty->raw = 1;
+		tty->real_raw = 1;
+	}
 	/*
 	 * Lose the small buffers usbserial provides. Make larger ones.
 	 */
 
 	kfree(port->bulk_in_buffer);
-	kfree(port->bulk_out_buffer);
 	port->bulk_in_buffer = kmalloc(URBDATA_SIZE, GFP_KERNEL);
 	if (port->bulk_in_buffer == NULL) {
 		port->bulk_out_buffer = NULL; /* prevent double free */
 		goto enomem;
 	}
+
+	kfree(port->bulk_out_buffer);
 	port->bulk_out_buffer = kmalloc(URBDATA_SIZE, GFP_KERNEL);
 	if (port->bulk_out_buffer == NULL) {
 		kfree(port->bulk_in_buffer);
@@ -661,8 +667,9 @@
 	port->read_urb->transfer_buffer = port->bulk_in_buffer;
 	port->write_urb->transfer_buffer = port->bulk_out_buffer;
 	port->read_urb->transfer_buffer_length = URBDATA_SIZE;
-	port->bulk_out_size = port->write_urb->transfer_buffer_length = URBDATA_SIZE;
-	
+	port->bulk_out_size = port->write_urb->transfer_buffer_length
+							= URBDATA_SIZE;
+
 	msleep(1000*initial_wait);
 
 	/*
@@ -691,13 +698,15 @@
 
 	/* 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);
+		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", __func__, result);
+		err("%s - failed submitting read urb, error %d",
+						__func__, result);
 		goto error;
 	}
 
@@ -713,12 +722,13 @@
 }
 
 
-static void ipaq_close(struct usb_serial_port *port, struct file *filp)
+static void ipaq_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct ipaq_private	*priv = usb_get_serial_port_data(port);
 
 	dbg("%s - port %d", __func__, port->number);
-			 
+
 	/*
 	 * shut down bulk read and write
 	 */
@@ -728,7 +738,8 @@
 	kfree(priv);
 	usb_set_serial_port_data(port, NULL);
 
-	/* Uncomment the following line if you want to see some statistics in your syslog */
+	/* Uncomment the following line if you want to see some statistics
+	 * in your syslog */
 	/* info ("Bytes In = %d  Bytes Out = %d", bytes_in, bytes_out); */
 }
 
@@ -748,9 +759,10 @@
 		return;
 	}
 
-	usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+	usb_serial_debug_data(debug, &port->dev, __func__,
+						urb->actual_length, data);
 
-	tty = port->tty;
+	tty = port->port.tty;
 	if (tty && urb->actual_length) {
 		tty_buffer_request_room(tty, urb->actual_length);
 		tty_insert_flip_string(tty, data, urb->actual_length);
@@ -759,18 +771,20 @@
 	}
 
 	/* Continue trying to always read  */
-	usb_fill_bulk_urb(port->read_urb, port->serial->dev, 
-		      usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress),
-		      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
-		      ipaq_read_bulk_callback, port);
+	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,
+	    ipaq_read_bulk_callback, port);
 	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 	if (result)
-		err("%s - failed resubmitting read urb, error %d", __func__, result);
+		err("%s - failed resubmitting read urb, error %d",
+							__func__, result);
 	return;
 }
 
-static int ipaq_write(struct usb_serial_port *port, const unsigned char *buf,
-		       int count)
+static int ipaq_write(struct tty_struct *tty, struct usb_serial_port *port,
+			const unsigned char *buf, int count)
 {
 	const unsigned char	*current_position = buf;
 	int			bytes_sent = 0;
@@ -780,9 +794,8 @@
 
 	while (count > 0) {
 		transfer_size = min(count, PACKET_SIZE);
-		if (ipaq_write_bulk(port, current_position, transfer_size)) {
+		if (ipaq_write_bulk(port, current_position, transfer_size))
 			break;
-		}
 		current_position += transfer_size;
 		bytes_sent += transfer_size;
 		count -= transfer_size;
@@ -790,10 +803,10 @@
 	}
 
 	return bytes_sent;
-} 
+}
 
-static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *buf,
-			   int count)
+static int ipaq_write_bulk(struct usb_serial_port *port,
+					const unsigned char *buf, int count)
 {
 	struct ipaq_private	*priv = usb_get_serial_port_data(port);
 	struct ipaq_packet	*pkt = NULL;
@@ -830,9 +843,9 @@
 		ipaq_write_gather(port);
 		spin_unlock_irqrestore(&write_list_lock, flags);
 		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
-		if (result) {
-			err("%s - failed submitting write urb, error %d", __func__, result);
-		}
+		if (result)
+			err("%s - failed submitting write urb, error %d",
+				__func__, result);
 	} else {
 		spin_unlock_irqrestore(&write_list_lock, flags);
 	}
@@ -859,16 +872,15 @@
 			list_move(&pkt->list, &priv->freelist);
 			priv->free_len += PACKET_SIZE;
 		}
-		if (room == 0) {
+		if (room == 0)
 			break;
-		}
 	}
 
 	count = URBDATA_SIZE - room;
-	usb_fill_bulk_urb(port->write_urb, serial->dev, 
-		      usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
-		      port->write_urb->transfer_buffer, count, ipaq_write_bulk_callback,
-		      port);
+	usb_fill_bulk_urb(port->write_urb, serial->dev,
+		usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
+		port->write_urb->transfer_buffer, count,
+		ipaq_write_bulk_callback, port);
 	return;
 }
 
@@ -893,9 +905,9 @@
 		ipaq_write_gather(port);
 		spin_unlock_irqrestore(&write_list_lock, flags);
 		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
-		if (result) {
-			err("%s - failed submitting write urb, error %d", __func__, result);
-		}
+		if (result)
+			err("%s - failed submitting write urb, error %d",
+					__func__, result);
 	} else {
 		priv->active = 0;
 		spin_unlock_irqrestore(&write_list_lock, flags);
@@ -904,16 +916,18 @@
 	usb_serial_port_softint(port);
 }
 
-static int ipaq_write_room(struct usb_serial_port *port)
+static int ipaq_write_room(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct ipaq_private	*priv = usb_get_serial_port_data(port);
 
 	dbg("%s - freelen %d", __func__, priv->free_len);
 	return priv->free_len;
 }
 
-static int ipaq_chars_in_buffer(struct usb_serial_port *port)
+static int ipaq_chars_in_buffer(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct ipaq_private	*priv = usb_get_serial_port_data(port);
 
 	dbg("%s - queuelen %d", __func__, priv->queue_len);
@@ -944,7 +958,7 @@
 			serial->dev->actconfig->desc.bConfigurationValue);
 		return -ENODEV;
 	}
-	return usb_reset_configuration (serial->dev);
+	return usb_reset_configuration(serial->dev);
 }
 
 static void ipaq_shutdown(struct usb_serial *serial)
@@ -957,7 +971,7 @@
 	int retval;
 	spin_lock_init(&write_list_lock);
 	retval = usb_serial_register(&ipaq_device);
-	if (retval) 
+	if (retval)
 		goto failed_usb_serial_register;
 	info(DRIVER_DESC " " DRIVER_VERSION);
 	if (vendor) {
@@ -967,7 +981,7 @@
 	retval = usb_register(&ipaq_driver);
 	if (retval)
 		goto failed_usb_register;
-		  
+
 	return 0;
 failed_usb_register:
 	usb_serial_deregister(&ipaq_device);
@@ -986,8 +1000,8 @@
 module_init(ipaq_init);
 module_exit(ipaq_exit);
 
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
@@ -1000,7 +1014,9 @@
 MODULE_PARM_DESC(product, "User specified USB idProduct");
 
 module_param(connect_retries, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(connect_retries, "Maximum number of connect retries (one second each)");
+MODULE_PARM_DESC(connect_retries,
+		"Maximum number of connect retries (one second each)");
 
 module_param(initial_wait, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(initial_wait, "Time to wait before attempting a connection (in seconds)");
+MODULE_PARM_DESC(initial_wait,
+		"Time to wait before attempting a connection (in seconds)");
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index bc85ca5..a842025 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -10,27 +10,27 @@
  *   (at your option) any later version.
  *
  * All information about the device was acquired using SnoopyPro
- * on MSFT's O/S, and examing the MSFT drivers' debug output 
+ * on MSFT's O/S, and examing the MSFT drivers' debug output
  * (insanely left _on_ in the enduser version)
  *
  * It was written out of frustration with the IPWireless USB modem
  * supplied by Axity3G/Sentech South Africa not supporting
  * Linux whatsoever.
  *
- * Nobody provided any proprietary information that was not already 
+ * Nobody provided any proprietary information that was not already
  * available for this device.
- * 
- * The modem adheres to the "3GPP TS  27.007 AT command set for 3G 
- * User Equipment (UE)" standard, available from 
+ *
+ * The modem adheres to the "3GPP TS  27.007 AT command set for 3G
+ * User Equipment (UE)" standard, available from
  * http://www.3gpp.org/ftp/Specs/html-info/27007.htm
  *
  * The code was only tested the IPWireless handheld modem distributed
  * in South Africa by Sentech.
- * 
+ *
  * It may work for Woosh Inc in .nz too, as it appears they use the
  * same kit.
  *
- * There is still some work to be done in terms of handling 
+ * There is still some work to be done in terms of handling
  * DCD, DTR, RTS, CTS which are currently faked.
  * It's good enough for PPP at this point. It's based off all kinds of
  * code found in usb/serial and usb/class
@@ -47,7 +47,7 @@
 #include <linux/spinlock.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /*
  * Version Information
@@ -64,7 +64,7 @@
 
 /* Message sizes */
 #define EVENT_BUFFER_SIZE	0xFF
-#define CHAR2INT16(c1,c0)	(((u32)((c1) & 0xff) << 8) + (u32)((c0) & 0xff))
+#define CHAR2INT16(c1, c0)	(((u32)((c1) & 0xff) << 8) + (u32)((c0) & 0xff))
 #define NUM_BULK_URBS		24
 #define NUM_CONTROL_URBS	16
 
@@ -94,33 +94,34 @@
 
 /* data bits */
 #define ipw_dtb_7		0x700
-#define ipw_dtb_8		0x810	// ok so the define is misleading, I know, but forces 8,n,1
-					// I mean, is there a point to any other setting these days? :)	
+#define ipw_dtb_8		0x810	/* ok so the define is misleading, I know, but forces 8,n,1 */
+					/* I mean, is there a point to any other setting these days? :) */
 
 /* usb control request types : */
-#define IPW_SIO_RXCTL		0x00	// control bulk rx channel transmissions, value=1/0 (on/off)
-#define IPW_SIO_SET_BAUD	0x01	// set baud, value=requested ipw_sio_bxxxx
-#define IPW_SIO_SET_LINE	0x03	// set databits, parity. value=ipw_dtb_x
-#define IPW_SIO_SET_PIN		0x03	// set/clear dtr/rts value=ipw_pin_xxx
-#define IPW_SIO_POLL		0x08	// get serial port status byte, call with value=0
-#define IPW_SIO_INIT		0x11	// initializes ? value=0 (appears as first thing todo on open)
-#define IPW_SIO_PURGE		0x12	// purge all transmissions?, call with value=numchar_to_purge
-#define IPW_SIO_HANDFLOW	0x13	// set xon/xoff limits value=0, and a buffer of 0x10 bytes
-#define IPW_SIO_SETCHARS	0x13	// set the flowcontrol special chars, value=0, buf=6 bytes, 
-					// last 2 bytes contain flowcontrol chars e.g. 00 00 00 00 11 13
+#define IPW_SIO_RXCTL		0x00	/* control bulk rx channel transmissions, value=1/0 (on/off) */
+#define IPW_SIO_SET_BAUD	0x01	/* set baud, value=requested ipw_sio_bxxxx */
+#define IPW_SIO_SET_LINE	0x03	/* set databits, parity. value=ipw_dtb_x */
+#define IPW_SIO_SET_PIN		0x03	/* set/clear dtr/rts value=ipw_pin_xxx */
+#define IPW_SIO_POLL		0x08	/* get serial port status byte, call with value=0 */
+#define IPW_SIO_INIT		0x11	/* initializes ? value=0 (appears as first thing todo on open) */
+#define IPW_SIO_PURGE		0x12	/* purge all transmissions?, call with value=numchar_to_purge */
+#define IPW_SIO_HANDFLOW	0x13	/* set xon/xoff limits value=0, and a buffer of 0x10 bytes */
+#define IPW_SIO_SETCHARS	0x13	/* set the flowcontrol special chars, value=0, buf=6 bytes, */
+					/* last 2 bytes contain flowcontrol chars e.g. 00 00 00 00 11 13 */
 
 /* values used for request IPW_SIO_SET_PIN */
 #define IPW_PIN_SETDTR		0x101
 #define IPW_PIN_SETRTS		0x202
 #define IPW_PIN_CLRDTR		0x100
-#define IPW_PIN_CLRRTS		0x200 // unconfirmed
+#define IPW_PIN_CLRRTS		0x200 /* unconfirmed */
 
 /* values used for request IPW_SIO_RXCTL */
 #define IPW_RXBULK_ON		1
 #define IPW_RXBULK_OFF		0
 
 /* various 16 byte hardcoded transferbuffers used by flow control */
-#define IPW_BYTES_FLOWINIT	{ 0x01, 0, 0, 0, 0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+#define IPW_BYTES_FLOWINIT	{ 0x01, 0, 0, 0, 0x40, 0, 0, 0, \
+					0, 0, 0, 0, 0, 0, 0, 0 }
 
 /* Interpretation of modem status lines */
 /* These need sorting out by individually connecting pins and checking
@@ -132,17 +133,6 @@
 #define IPW_CTS			((1<<5) | (1<<4))
 
 #define IPW_WANTS_TO_SEND	0x30
-//#define IPW_DTR			/* Data Terminal Ready */
-//#define IPW_CTS			/* Clear To Send */
-//#define IPW_CD			/* Carrier Detect */
-//#define IPW_DSR			/* Data Set Ready */
-//#define IPW_RxD			/* Receive pin */
-
-//#define IPW_LE
-//#define IPW_RTS		
-//#define IPW_ST		
-//#define IPW_SR		
-//#define IPW_RI			/* Ring Indicator */
 
 static struct usb_device_id usb_ipw_ids[] = {
 	{ USB_DEVICE(IPW_VID, IPW_PID) },
@@ -177,9 +167,10 @@
 		return;
 	}
 
-	usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+	usb_serial_debug_data(debug, &port->dev, __func__,
+					urb->actual_length, data);
 
-	tty = port->tty;
+	tty = port->port.tty;
 	if (tty && urb->actual_length) {
 		tty_buffer_request_room(tty, urb->actual_length);
 		tty_insert_flip_string(tty, data, urb->actual_length);
@@ -187,19 +178,22 @@
 	}
 
 	/* Continue trying to always read  */
-	usb_fill_bulk_urb (port->read_urb, port->serial->dev,
-			   usb_rcvbulkpipe(port->serial->dev,
+	usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+			  usb_rcvbulkpipe(port->serial->dev,
 					   port->bulk_in_endpointAddress),
-			   port->read_urb->transfer_buffer,
-			   port->read_urb->transfer_buffer_length,
-			   ipw_read_bulk_callback, port);
+			  port->read_urb->transfer_buffer,
+			  port->read_urb->transfer_buffer_length,
+			  ipw_read_bulk_callback, port);
 	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 	if (result)
-		dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
+		dev_err(&port->dev,
+			"%s - failed resubmitting read urb, error %d\n",
+							__func__, result);
 	return;
 }
 
-static int ipw_open(struct usb_serial_port *port, struct file *filp)
+static int ipw_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct usb_device *dev = port->serial->dev;
 	u8 buf_flow_static[16] = IPW_BYTES_FLOWINIT;
@@ -212,29 +206,33 @@
 	if (!buf_flow_init)
 		return -ENOMEM;
 
-	if (port->tty)
-		port->tty->low_latency = 1;
+	if (tty)
+		tty->low_latency = 1;
 
-	/* --1: Tell the modem to initialize (we think) From sniffs this is always the
-	 * first thing that gets sent to the modem during opening of the device */
-	dbg("%s: Sending SIO_INIT (we guess)",__func__);
-	result = usb_control_msg(dev, usb_sndctrlpipe(dev,0),
-				 IPW_SIO_INIT,
-				 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
-				 0,
-				 0, /* index */
-				 NULL,
-				 0,
-				 100000);
+	/* --1: Tell the modem to initialize (we think) From sniffs this is
+	 *	always the first thing that gets sent to the modem during
+	 *	opening of the device */
+	dbg("%s: Sending SIO_INIT (we guess)", __func__);
+	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+			 IPW_SIO_INIT,
+			 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+			 0,
+			 0, /* index */
+			 NULL,
+			 0,
+			 100000);
 	if (result < 0)
-		dev_err(&port->dev, "Init of modem failed (error = %d)\n", result);
+		dev_err(&port->dev,
+			"Init of modem failed (error = %d)\n", result);
 
 	/* reset the bulk pipes */
-	usb_clear_halt(dev, usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress));
-	usb_clear_halt(dev, usb_sndbulkpipe(dev, port->bulk_out_endpointAddress));
+	usb_clear_halt(dev,
+			usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress));
+	usb_clear_halt(dev,
+			usb_sndbulkpipe(dev, port->bulk_out_endpointAddress));
 
-	/*--2: Start reading from the device */	
-	dbg("%s: setting up bulk read callback",__func__);
+	/*--2: Start reading from the device */
+	dbg("%s: setting up bulk read callback", __func__);
 	usb_fill_bulk_urb(port->read_urb, dev,
 			  usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress),
 			  port->bulk_in_buffer,
@@ -242,66 +240,72 @@
 			  ipw_read_bulk_callback, port);
 	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 	if (result < 0)
-		dbg("%s - usb_submit_urb(read bulk) failed with status %d", __func__, result);
+		dbg("%s - usb_submit_urb(read bulk) failed with status %d",
+							__func__, result);
 
 	/*--3: Tell the modem to open the floodgates on the rx bulk channel */
-	dbg("%s:asking modem for RxRead (RXBULK_ON)",__func__);
+	dbg("%s:asking modem for RxRead (RXBULK_ON)", __func__);
 	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-				 IPW_SIO_RXCTL,
-				 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
-				 IPW_RXBULK_ON,
-				 0, /* index */
-				 NULL,
-				 0,
-				 100000);
-	if (result < 0) 
-		dev_err(&port->dev, "Enabling bulk RxRead failed (error = %d)\n", result);
+			 IPW_SIO_RXCTL,
+			 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+			 IPW_RXBULK_ON,
+			 0, /* index */
+			 NULL,
+			 0,
+			 100000);
+	if (result < 0)
+		dev_err(&port->dev,
+			"Enabling bulk RxRead failed (error = %d)\n", result);
 
 	/*--4: setup the initial flowcontrol */
-	dbg("%s:setting init flowcontrol (%s)",__func__,buf_flow_init);
+	dbg("%s:setting init flowcontrol (%s)", __func__, buf_flow_init);
 	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-				 IPW_SIO_HANDFLOW,
-				 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
-				 0,
-				 0,
-				 buf_flow_init,
-				 0x10,
-				 200000);
+			 IPW_SIO_HANDFLOW,
+			 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+			 0,
+			 0,
+			 buf_flow_init,
+			 0x10,
+			 200000);
 	if (result < 0)
-		dev_err(&port->dev, "initial flowcontrol failed (error = %d)\n", result);
+		dev_err(&port->dev,
+			"initial flowcontrol failed (error = %d)\n", result);
 
 
 	/*--5: raise the dtr */
-	dbg("%s:raising dtr",__func__);
+	dbg("%s:raising dtr", __func__);
 	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-				 IPW_SIO_SET_PIN,
-				 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
-				 IPW_PIN_SETDTR,
-				 0,
-				 NULL,
-				 0,
-				 200000);
+			 IPW_SIO_SET_PIN,
+			 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+			 IPW_PIN_SETDTR,
+			 0,
+			 NULL,
+			 0,
+			 200000);
 	if (result < 0)
-		dev_err(&port->dev, "setting dtr failed (error = %d)\n", result);
+		dev_err(&port->dev,
+				"setting dtr failed (error = %d)\n", result);
 
 	/*--6: raise the rts */
-	dbg("%s:raising rts",__func__);
+	dbg("%s:raising rts", __func__);
 	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-				 IPW_SIO_SET_PIN,
-				 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
-				 IPW_PIN_SETRTS,
-				 0,
-				 NULL,
-				 0,
-				 200000);
+			 IPW_SIO_SET_PIN,
+			 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+			 IPW_PIN_SETRTS,
+			 0,
+			 NULL,
+			 0,
+			 200000);
 	if (result < 0)
-		dev_err(&port->dev, "setting dtr failed (error = %d)\n", result);
-	
+		dev_err(&port->dev,
+				"setting dtr failed (error = %d)\n", result);
+
 	kfree(buf_flow_init);
 	return 0;
 }
 
-static void ipw_close(struct usb_serial_port *port, struct file * filp)
+static void ipw_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct usb_device *dev = port->serial->dev;
 	int result;
@@ -312,56 +316,62 @@
 	}
 
 	/*--1: drop the dtr */
-	dbg("%s:dropping dtr",__func__);
+	dbg("%s:dropping dtr", __func__);
 	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-				 IPW_SIO_SET_PIN,
-				 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
-				 IPW_PIN_CLRDTR,
-				 0,
-				 NULL,
-				 0,
-				 200000);
+			 IPW_SIO_SET_PIN,
+			 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+			 IPW_PIN_CLRDTR,
+			 0,
+			 NULL,
+			 0,
+			 200000);
 	if (result < 0)
-		dev_err(&port->dev, "dropping dtr failed (error = %d)\n", result);
+		dev_err(&port->dev, "dropping dtr failed (error = %d)\n",
+								result);
 
 	/*--2: drop the rts */
-	dbg("%s:dropping rts",__func__);
+	dbg("%s:dropping rts", __func__);
 	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-				 IPW_SIO_SET_PIN, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
-				 IPW_PIN_CLRRTS,
-				 0,
-				 NULL,
-				 0,
-				 200000);
+			 IPW_SIO_SET_PIN, USB_TYPE_VENDOR |
+			 		USB_RECIP_INTERFACE | USB_DIR_OUT,
+			 IPW_PIN_CLRRTS,
+			 0,
+			 NULL,
+			 0,
+			 200000);
 	if (result < 0)
-		dev_err(&port->dev, "dropping rts failed (error = %d)\n", result);
+		dev_err(&port->dev,
+				"dropping rts failed (error = %d)\n", result);
 
 
 	/*--3: purge */
-	dbg("%s:sending purge",__func__);
+	dbg("%s:sending purge", __func__);
 	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-				 IPW_SIO_PURGE, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
-				 0x03,
-				 0,
-				 NULL,
-				 0,
-				 200000);
+			 IPW_SIO_PURGE, USB_TYPE_VENDOR |
+			 		USB_RECIP_INTERFACE | USB_DIR_OUT,
+			 0x03,
+			 0,
+			 NULL,
+			 0,
+			 200000);
 	if (result < 0)
 		dev_err(&port->dev, "purge failed (error = %d)\n", result);
 
 
-	/* send RXBULK_off (tell modem to stop transmitting bulk data on rx chan) */
+	/* send RXBULK_off (tell modem to stop transmitting bulk data on
+	   rx chan) */
 	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-				 IPW_SIO_RXCTL,
-				 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
-				 IPW_RXBULK_OFF,
-				 0, /* index */
-				 NULL,
-				 0,
-				 100000);
+			 IPW_SIO_RXCTL,
+			 USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+			 IPW_RXBULK_OFF,
+			 0, /* index */
+			 NULL,
+			 0,
+			 100000);
 
 	if (result < 0)
-		dev_err(&port->dev, "Disabling bulk RxRead failed (error = %d)\n", result);
+		dev_err(&port->dev,
+			"Disabling bulk RxRead failed (error = %d)\n", result);
 
 	/* shutdown any in-flight urbs that we know about */
 	usb_kill_urb(port->read_urb);
@@ -384,13 +394,14 @@
 	usb_serial_port_softint(port);
 }
 
-static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int count)
+static int ipw_write(struct tty_struct *tty, struct usb_serial_port *port,
+					const unsigned char *buf, int count)
 {
 	struct usb_device *dev = port->serial->dev;
 	int ret;
 
 	dbg("%s: TOP: count=%d, in_interrupt=%ld", __func__,
-		count, in_interrupt() );
+		count, in_interrupt());
 
 	if (count == 0) {
 		dbg("%s - write request of 0 bytes", __func__);
@@ -421,13 +432,14 @@
 	ret = usb_submit_urb(port->write_urb, GFP_ATOMIC);
 	if (ret != 0) {
 		port->write_urb_busy = 0;
-		dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __func__, ret);
+		dbg("%s - usb_submit_urb(write bulk) failed with error = %d",
+								__func__, ret);
 		return ret;
 	}
 
 	dbg("%s returning %d", __func__, count);
 	return count;
-} 
+}
 
 static int ipw_probe(struct usb_serial_port *port)
 {
@@ -486,8 +498,8 @@
 module_exit(usb_ipw_exit);
 
 /* Module information */
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 004d573..e59155c 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -19,7 +19,12 @@
  * was written by Roman Weissgaerber <weissg@vienna.at>, Dag Brattli
  * <dag@brattli.net>, and Jean Tourrilhes <jt@hpl.hp.com>
  *
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
+ *
+ * 2008_Jun_02  Felipe Balbi <me@felipebalbi.com>
+ *	Introduced common header to be used also in USB Gadget Framework.
+ *	Still needs some other style fixes.
  *
  * 2007_Jun_21  Alan Cox <alan@redhat.com>
  *	Minimal cleanups for some of the driver problens and tty layer abuse.
@@ -59,9 +64,10 @@
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
+#include <linux/usb/irda.h>
 
 /*
  * Version Information
@@ -70,100 +76,77 @@
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
 #define DRIVER_DESC "USB IR Dongle driver"
 
-/* USB IrDA class spec information */
-#define USB_CLASS_IRDA		0x02
-#define USB_DT_IRDA		0x21
-#define IU_REQ_GET_CLASS_DESC	0x06
-#define SPEED_2400		0x01
-#define SPEED_9600		0x02
-#define SPEED_19200		0x03
-#define SPEED_38400		0x04
-#define SPEED_57600		0x05
-#define SPEED_115200		0x06
-#define SPEED_576000		0x07
-#define SPEED_1152000		0x08
-#define SPEED_4000000		0x09
-
-struct irda_class_desc {
-	u8	bLength;
-	u8	bDescriptorType;
-	u16	bcdSpecRevision;
-	u8	bmDataSize;
-	u8	bmWindowSize;
-	u8	bmMinTurnaroundTime;
-	u16	wBaudRate;
-	u8	bmAdditionalBOFs;
-	u8	bIrdaRateSniff;
-	u8	bMaxUnicastList;
-} __attribute__ ((packed));
-
 static int debug;
 
 /* if overridden by the user, then use their value for the size of the read and
  * write urbs */
 static int buffer_size;
+
 /* if overridden by the user, then use the specified number of XBOFs */
 static int xbof = -1;
 
 static int  ir_startup (struct usb_serial *serial);
-static int  ir_open (struct usb_serial_port *port, struct file *filep);
-static void ir_close (struct usb_serial_port *port, struct file *filep);
-static int  ir_write (struct usb_serial_port *port, const unsigned char *buf, int count);
+static int  ir_open(struct tty_struct *tty, struct usb_serial_port *port,
+					struct file *filep);
+static void ir_close(struct tty_struct *tty, struct usb_serial_port *port,
+					struct file *filep);
+static int  ir_write(struct tty_struct *tty, struct usb_serial_port *port,
+					const unsigned char *buf, int count);
 static void ir_write_bulk_callback (struct urb *urb);
 static void ir_read_bulk_callback (struct urb *urb);
-static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
+static void ir_set_termios(struct tty_struct *tty,
+		struct usb_serial_port *port, struct ktermios *old_termios);
 
 /* Not that this lot means you can only have one per system */
-static u8 ir_baud = 0;
-static u8 ir_xbof = 0;
-static u8 ir_add_bof = 0;
+static u8 ir_baud;
+static u8 ir_xbof;
+static u8 ir_add_bof;
 
-static struct usb_device_id id_table [] = {
+static struct usb_device_id ir_id_table[] = {
 	{ USB_DEVICE(0x050f, 0x0180) },		/* KC Technology, KC-180 */
 	{ USB_DEVICE(0x08e9, 0x0100) },		/* XTNDAccess */
 	{ USB_DEVICE(0x09c4, 0x0011) },		/* ACTiSys ACT-IR2000U */
-	{ USB_INTERFACE_INFO (USB_CLASS_APP_SPEC, USB_CLASS_IRDA, 0) },
+	{ USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, USB_SUBCLASS_IRDA, 0) },
 	{ }					/* Terminating entry */
 };
 
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, ir_id_table);
 
 static struct usb_driver ir_driver = {
-	.name =		"ir-usb",
-	.probe =	usb_serial_probe,
-	.disconnect =	usb_serial_disconnect,
-	.id_table =	id_table,
-	.no_dynamic_id = 	1,
+	.name		= "ir-usb",
+	.probe		= usb_serial_probe,
+	.disconnect	= usb_serial_disconnect,
+	.id_table	= ir_id_table,
+	.no_dynamic_id	= 1,
 };
 
-
 static struct usb_serial_driver ir_device = {
-	.driver = {
-		.owner =	THIS_MODULE,
-		.name =		"ir-usb",
+	.driver	= {
+		.owner	= THIS_MODULE,
+		.name	= "ir-usb",
 	},
-	.description =		"IR Dongle",
-	.usb_driver = 		&ir_driver,
-	.id_table =		id_table,
-	.num_ports =		1,
-	.set_termios =		ir_set_termios,
-	.attach =		ir_startup,
-	.open =			ir_open,
-	.close =		ir_close,
-	.write =		ir_write,
-	.write_bulk_callback =	ir_write_bulk_callback,
-	.read_bulk_callback =	ir_read_bulk_callback,
+	.description		= "IR Dongle",
+	.usb_driver		= &ir_driver,
+	.id_table		= ir_id_table,
+	.num_ports		= 1,
+	.set_termios		= ir_set_termios,
+	.attach			= ir_startup,
+	.open			= ir_open,
+	.close			= ir_close,
+	.write			= ir_write,
+	.write_bulk_callback	= ir_write_bulk_callback,
+	.read_bulk_callback	= ir_read_bulk_callback,
 };
 
-static inline void irda_usb_dump_class_desc(struct irda_class_desc *desc)
+static inline void irda_usb_dump_class_desc(struct usb_irda_cs_descriptor *desc)
 {
 	dbg("bLength=%x", desc->bLength);
 	dbg("bDescriptorType=%x", desc->bDescriptorType);
-	dbg("bcdSpecRevision=%x", desc->bcdSpecRevision); 
+	dbg("bcdSpecRevision=%x", __le16_to_cpu(desc->bcdSpecRevision));
 	dbg("bmDataSize=%x", desc->bmDataSize);
 	dbg("bmWindowSize=%x", desc->bmWindowSize);
 	dbg("bmMinTurnaroundTime=%d", desc->bmMinTurnaroundTime);
-	dbg("wBaudRate=%x", desc->wBaudRate);
+	dbg("wBaudRate=%x", __le16_to_cpu(desc->wBaudRate));
 	dbg("bmAdditionalBOFs=%x", desc->bmAdditionalBOFs);
 	dbg("bIrdaRateSniff=%x", desc->bIrdaRateSniff);
 	dbg("bMaxUnicastList=%x", desc->bMaxUnicastList);
@@ -181,35 +164,37 @@
  *
  * Based on the same function in drivers/net/irda/irda-usb.c
  */
-static struct irda_class_desc *irda_usb_find_class_desc(struct usb_device *dev, unsigned int ifnum)
+static struct usb_irda_cs_descriptor *
+irda_usb_find_class_desc(struct usb_device *dev, unsigned int ifnum)
 {
-	struct irda_class_desc *desc;
+	struct usb_irda_cs_descriptor *desc;
 	int ret;
-		
-	desc = kzalloc(sizeof (struct irda_class_desc), GFP_KERNEL);
-	if (desc == NULL) 
+
+	desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+	if (!desc)
 		return NULL;
-	
-	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
-			IU_REQ_GET_CLASS_DESC,
+
+	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+			USB_REQ_CS_IRDA_GET_CLASS_DESC,
 			USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
 			0, ifnum, desc, sizeof(*desc), 1000);
-	
+
 	dbg("%s -  ret=%d", __func__, ret);
 	if (ret < sizeof(*desc)) {
 		dbg("%s - class descriptor read %s (%d)",
 				__func__,
-				(ret<0) ? "failed" : "too short",
+				(ret < 0) ? "failed" : "too short",
 				ret);
 		goto error;
 	}
-	if (desc->bDescriptorType != USB_DT_IRDA) {
+	if (desc->bDescriptorType != USB_DT_CS_IRDA) {
 		dbg("%s - bad class descriptor type", __func__);
 		goto error;
 	}
-	
+
 	irda_usb_dump_class_desc(desc);
 	return desc;
+
 error:
 	kfree(desc);
 	return NULL;
@@ -219,64 +204,101 @@
 static u8 ir_xbof_change(u8 xbof)
 {
 	u8 result;
+
 	/* reference irda-usb.c */
-	switch(xbof) {
-		case 48: result = 0x10; break;
-		case 28:
-		case 24: result = 0x20; break;
-		default:
-		case 12: result = 0x30; break;
-		case  5:
-		case  6: result = 0x40; break;
-		case  3: result = 0x50; break;
-		case  2: result = 0x60; break;
-		case  1: result = 0x70; break;
-		case  0: result = 0x80; break;
+	switch (xbof) {
+	case 48:
+		result = 0x10;
+		break;
+	case 28:
+	case 24:
+		result = 0x20;
+		break;
+	default:
+	case 12:
+		result = 0x30;
+		break;
+	case  5:
+	case  6:
+		result = 0x40;
+		break;
+	case  3:
+		result = 0x50;
+		break;
+	case  2:
+		result = 0x60;
+		break;
+	case  1:
+		result = 0x70;
+		break;
+	case  0:
+		result = 0x80;
+		break;
 	}
+
 	return(result);
 }
 
 
-static int ir_startup (struct usb_serial *serial)
+static int ir_startup(struct usb_serial *serial)
 {
-	struct irda_class_desc *irda_desc;
+	struct usb_irda_cs_descriptor *irda_desc;
 
-	irda_desc = irda_usb_find_class_desc (serial->dev, 0);
-	if (irda_desc == NULL) {
-		dev_err (&serial->dev->dev, "IRDA class descriptor not found, device not bound\n");
+	irda_desc = irda_usb_find_class_desc(serial->dev, 0);
+	if (!irda_desc) {
+		dev_err(&serial->dev->dev,
+			"IRDA class descriptor not found, device not bound\n");
 		return -ENODEV;
 	}
 
-	dbg ("%s - Baud rates supported:%s%s%s%s%s%s%s%s%s",
+	dbg("%s - Baud rates supported:%s%s%s%s%s%s%s%s%s",
 		__func__,
-		(irda_desc->wBaudRate & 0x0001) ? " 2400"    : "",
-		(irda_desc->wBaudRate & 0x0002) ? " 9600"    : "",
-		(irda_desc->wBaudRate & 0x0004) ? " 19200"   : "",
-		(irda_desc->wBaudRate & 0x0008) ? " 38400"   : "",
-		(irda_desc->wBaudRate & 0x0010) ? " 57600"   : "",
-		(irda_desc->wBaudRate & 0x0020) ? " 115200"  : "",
-		(irda_desc->wBaudRate & 0x0040) ? " 576000"  : "",
-		(irda_desc->wBaudRate & 0x0080) ? " 1152000" : "",
-		(irda_desc->wBaudRate & 0x0100) ? " 4000000" : "");
+		(irda_desc->wBaudRate & USB_IRDA_BR_2400) ? " 2400" : "",
+		(irda_desc->wBaudRate & USB_IRDA_BR_9600) ? " 9600" : "",
+		(irda_desc->wBaudRate & USB_IRDA_BR_19200) ? " 19200" : "",
+		(irda_desc->wBaudRate & USB_IRDA_BR_38400) ? " 38400" : "",
+		(irda_desc->wBaudRate & USB_IRDA_BR_57600) ? " 57600" : "",
+		(irda_desc->wBaudRate & USB_IRDA_BR_115200) ? " 115200" : "",
+		(irda_desc->wBaudRate & USB_IRDA_BR_576000) ? " 576000" : "",
+		(irda_desc->wBaudRate & USB_IRDA_BR_1152000) ? " 1152000" : "",
+		(irda_desc->wBaudRate & USB_IRDA_BR_4000000) ? " 4000000" : "");
 
-	switch( irda_desc->bmAdditionalBOFs ) {
-		case 0x01: ir_add_bof = 48; break;
-		case 0x02: ir_add_bof = 24; break;
-		case 0x04: ir_add_bof = 12; break;
-		case 0x08: ir_add_bof =  6; break;
-		case 0x10: ir_add_bof =  3; break;
-		case 0x20: ir_add_bof =  2; break;
-		case 0x40: ir_add_bof =  1; break;
-		case 0x80: ir_add_bof =  0; break;
-		default:;
+	switch (irda_desc->bmAdditionalBOFs) {
+	case USB_IRDA_AB_48:
+		ir_add_bof = 48;
+		break;
+	case USB_IRDA_AB_24:
+		ir_add_bof = 24;
+		break;
+	case USB_IRDA_AB_12:
+		ir_add_bof = 12;
+		break;
+	case USB_IRDA_AB_6:
+		ir_add_bof = 6;
+		break;
+	case USB_IRDA_AB_3:
+		ir_add_bof = 3;
+		break;
+	case USB_IRDA_AB_2:
+		ir_add_bof = 2;
+		break;
+	case USB_IRDA_AB_1:
+		ir_add_bof = 1;
+		break;
+	case USB_IRDA_AB_0:
+		ir_add_bof = 0;
+		break;
+	default:
+		break;
 	}
 
-	kfree (irda_desc);
+	kfree(irda_desc);
 
-	return 0;		
+	return 0;
 }
 
-static int ir_open (struct usb_serial_port *port, struct file *filp)
+static int ir_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	char *buffer;
 	int result = 0;
@@ -285,51 +307,56 @@
 
 	if (buffer_size) {
 		/* override the default buffer sizes */
-		buffer = kmalloc (buffer_size, GFP_KERNEL);
+		buffer = kmalloc(buffer_size, GFP_KERNEL);
 		if (!buffer) {
-			dev_err (&port->dev, "%s - out of memory.\n", __func__);
+			dev_err(&port->dev, "%s - out of memory.\n", __func__);
 			return -ENOMEM;
 		}
-		kfree (port->read_urb->transfer_buffer);
+		kfree(port->read_urb->transfer_buffer);
 		port->read_urb->transfer_buffer = buffer;
 		port->read_urb->transfer_buffer_length = buffer_size;
 
-		buffer = kmalloc (buffer_size, GFP_KERNEL);
+		buffer = kmalloc(buffer_size, GFP_KERNEL);
 		if (!buffer) {
-			dev_err (&port->dev, "%s - out of memory.\n", __func__);
+			dev_err(&port->dev, "%s - out of memory.\n", __func__);
 			return -ENOMEM;
 		}
-		kfree (port->write_urb->transfer_buffer);
+		kfree(port->write_urb->transfer_buffer);
 		port->write_urb->transfer_buffer = buffer;
 		port->write_urb->transfer_buffer_length = buffer_size;
 		port->bulk_out_size = buffer_size;
 	}
 
 	/* Start reading from the device */
-	usb_fill_bulk_urb (
+	usb_fill_bulk_urb(
 		port->read_urb,
-		port->serial->dev, 
-		usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress),
+		port->serial->dev,
+		usb_rcvbulkpipe(port->serial->dev,
+			port->bulk_in_endpointAddress),
 		port->read_urb->transfer_buffer,
 		port->read_urb->transfer_buffer_length,
 		ir_read_bulk_callback,
 		port);
 	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 	if (result)
-		dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
+		dev_err(&port->dev,
+			"%s - failed submitting read urb, error %d\n",
+			__func__, result);
 
 	return result;
 }
 
-static void ir_close (struct usb_serial_port *port, struct file * filp)
+static void ir_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file * filp)
 {
 	dbg("%s - port %d", __func__, port->number);
-			 
+
 	/* shutdown our bulk read */
 	usb_kill_urb(port->read_urb);
 }
 
-static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int count)
+static int ir_write(struct tty_struct *tty, struct usb_serial_port *port,
+					const unsigned char *buf, int count)
 {
 	unsigned char *transfer_buffer;
 	int result;
@@ -337,11 +364,6 @@
 
 	dbg("%s - port = %d, count = %d", __func__, port->number, count);
 
-	if (!port->tty) {
-		dev_err (&port->dev, "%s - no tty???\n", __func__);
-		return 0;
-	}
-
 	if (count == 0)
 		return 0;
 
@@ -359,7 +381,7 @@
 
 	/*
 	 * The first byte of the packet we send to the device contains an
-	 * inband header which indicates an additional number of BOFs and
+	 * inbound header which indicates an additional number of BOFs and
 	 * a baud rate change.
 	 *
 	 * See section 5.4.2.2 of the USB IrDA spec.
@@ -367,9 +389,9 @@
 	*transfer_buffer = ir_xbof | ir_baud;
 	++transfer_buffer;
 
-	memcpy (transfer_buffer, buf, transfer_size);
+	memcpy(transfer_buffer, buf, transfer_size);
 
-	usb_fill_bulk_urb (
+	usb_fill_bulk_urb(
 		port->write_urb,
 		port->serial->dev,
 		usb_sndbulkpipe(port->serial->dev,
@@ -381,17 +403,19 @@
 
 	port->write_urb->transfer_flags = URB_ZERO_PACKET;
 
-	result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
+	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
 	if (result) {
 		port->write_urb_busy = 0;
-		dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result);
+		dev_err(&port->dev,
+			"%s - failed submitting write urb, error %d\n",
+			__func__, result);
 	} else
 		result = transfer_size;
 
 	return result;
 }
 
-static void ir_write_bulk_callback (struct urb *urb)
+static void ir_write_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 	int status = urb->status;
@@ -405,7 +429,7 @@
 		return;
 	}
 
-	usb_serial_debug_data (
+	usb_serial_debug_data(
 		debug,
 		&port->dev,
 		__func__,
@@ -415,7 +439,7 @@
 	usb_serial_port_softint(port);
 }
 
-static void ir_read_bulk_callback (struct urb *urb)
+static void ir_read_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 	struct tty_struct *tty;
@@ -425,74 +449,61 @@
 
 	dbg("%s - port %d", __func__, port->number);
 
-	if (!port->open_count) {
+	if (!port->port.count) {
 		dbg("%s - port closed.", __func__);
 		return;
 	}
 
 	switch (status) {
-		case 0: /* Successful */
+	case 0: /* Successful */
+		/*
+		 * The first byte of the packet we get from the device
+		 * contains a busy indicator and baud rate change.
+		 * See section 5.4.1.2 of the USB IrDA spec.
+		 */
+		if ((*data & 0x0f) > 0)
+			ir_baud = *data & 0x0f;
+		usb_serial_debug_data(debug, &port->dev, __func__,
+						urb->actual_length, data);
+ 		tty = port->port.tty;
+		if (tty_buffer_request_room(tty, urb->actual_length - 1)) {
+			tty_insert_flip_string(tty, data+1, urb->actual_length - 1);
+			tty_flip_buffer_push(tty);
+		}
 
-			/*
-			 * The first byte of the packet we get from the device
-			 * contains a busy indicator and baud rate change.
-			 * See section 5.4.1.2 of the USB IrDA spec.
-			 */
-			if ((*data & 0x0f) > 0)
-				ir_baud = *data & 0x0f;
+		/*
+		 * No break here.
+		 * We want to resubmit the urb so we can read
+		 * again.
+		 */
 
-			usb_serial_debug_data (
-				debug,
-				&port->dev,
-				__func__,
-				urb->actual_length,
-				data);
-
-			tty = port->tty;
-
-			if (tty_buffer_request_room(tty, urb->actual_length - 1)) {
-				tty_insert_flip_string(tty, data+1, urb->actual_length - 1);
-				tty_flip_buffer_push(tty);
-			}
-
-			/*
-			 * No break here.
-			 * We want to resubmit the urb so we can read
-			 * again.
-			 */
-
-		case -EPROTO: /* taking inspiration from pl2303.c */
-
+	case -EPROTO: /* taking inspiration from pl2303.c */
 			/* Continue trying to always read */
-			usb_fill_bulk_urb (
-				port->read_urb,
-				port->serial->dev, 
-				usb_rcvbulkpipe(port->serial->dev,
-					port->bulk_in_endpointAddress),
-				port->read_urb->transfer_buffer,
-				port->read_urb->transfer_buffer_length,
-				ir_read_bulk_callback,
-				port);
+		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,
+			ir_read_bulk_callback,
+			port);
 
-			result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
-			if (result)
-				dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n",
-					__func__, result);
-
+		result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+		if (result)
+			dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n",
+				__func__, result);
 			break ;
-
-		default:
-			dbg("%s - nonzero read bulk status received: %d",
-				__func__,
-				status);
-			break ;
-
+	default:
+		dbg("%s - nonzero read bulk status received: %d",
+			__func__, status);
+		break ;
 	}
-
 	return;
 }
 
-static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
+static void ir_set_termios(struct tty_struct *tty,
+		struct usb_serial_port *port, struct ktermios *old_termios)
 {
 	unsigned char *transfer_buffer;
 	int result;
@@ -501,7 +512,7 @@
 
 	dbg("%s - port %d", __func__, port->number);
 
-	baud = tty_get_baud_rate(port->tty);
+	baud = tty_get_baud_rate(tty);
 
 	/*
 	 * FIXME, we should compare the baud request against the
@@ -510,19 +521,36 @@
 	 */
 
 	switch (baud) {
-		case 2400:	ir_baud = SPEED_2400; break;
-		case 9600:	ir_baud = SPEED_9600; break;
-		case 19200:	ir_baud = SPEED_19200; break;
-		case 38400:	ir_baud = SPEED_38400; break;
-		case 57600:	ir_baud = SPEED_57600; break;
-		case 115200:	ir_baud = SPEED_115200; break;
-		case 576000:	ir_baud = SPEED_576000; break;
-		case 1152000:	ir_baud = SPEED_1152000; break;
-		case 4000000:	ir_baud = SPEED_4000000; break;
-			break;
-		default:
-			ir_baud = SPEED_9600;
-			baud = 9600;
+	case 2400:
+		ir_baud = USB_IRDA_BR_2400;
+		break;
+	case 9600:
+		ir_baud = USB_IRDA_BR_9600;
+		break;
+	case 19200:
+		ir_baud = USB_IRDA_BR_19200;
+		break;
+	case 38400:
+		ir_baud = USB_IRDA_BR_38400;
+		break;
+	case 57600:
+		ir_baud = USB_IRDA_BR_57600;
+		break;
+	case 115200:
+		ir_baud = USB_IRDA_BR_115200;
+		break;
+	case 576000:
+		ir_baud = USB_IRDA_BR_576000;
+		break;
+	case 1152000:
+		ir_baud = USB_IRDA_BR_1152000;
+		break;
+	case 4000000:
+		ir_baud = USB_IRDA_BR_4000000;
+		break;
+	default:
+		ir_baud = USB_IRDA_BR_9600;
+		baud = 9600;
 	}
 
 	if (xbof == -1)
@@ -538,10 +566,11 @@
 	transfer_buffer = port->write_urb->transfer_buffer;
 	*transfer_buffer = ir_xbof | ir_baud;
 
-	usb_fill_bulk_urb (
+	usb_fill_bulk_urb(
 		port->write_urb,
 		port->serial->dev,
-		usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress),
+		usb_sndbulkpipe(port->serial->dev,
+			port->bulk_out_endpointAddress),
 		port->write_urb->transfer_buffer,
 		1,
 		ir_write_bulk_callback,
@@ -549,38 +578,44 @@
 
 	port->write_urb->transfer_flags = URB_ZERO_PACKET;
 
-	result = usb_submit_urb (port->write_urb, GFP_KERNEL);
+	result = usb_submit_urb(port->write_urb, GFP_KERNEL);
 	if (result)
-		dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __func__, result);
+		dev_err(&port->dev,
+				"%s - failed submitting write urb, error %d\n",
+				__func__, result);
 
 	/* Only speed changes are supported */
-	tty_termios_copy_hw(port->tty->termios, old_termios);
-	tty_encode_baud_rate(port->tty, baud, baud);
+	tty_termios_copy_hw(tty->termios, old_termios);
+	tty_encode_baud_rate(tty, baud, baud);
 }
 
-
-static int __init ir_init (void)
+static int __init ir_init(void)
 {
 	int retval;
+
 	retval = usb_serial_register(&ir_device);
 	if (retval)
 		goto failed_usb_serial_register;
+
 	retval = usb_register(&ir_driver);
-	if (retval) 
+	if (retval)
 		goto failed_usb_register;
+
 	info(DRIVER_DESC " " DRIVER_VERSION);
+
 	return 0;
+
 failed_usb_register:
 	usb_serial_deregister(&ir_device);
+
 failed_usb_serial_register:
 	return retval;
 }
 
-
-static void __exit ir_exit (void)
+static void __exit ir_exit(void)
 {
-	usb_deregister (&ir_driver);
-	usb_serial_deregister (&ir_device);
+	usb_deregister(&ir_driver);
+	usb_serial_deregister(&ir_device);
 }
 
 
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
index a01e987..ddff37f 100644
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -144,9 +144,10 @@
 	}
 }
 
-static int iuu_tiocmset(struct usb_serial_port *port, struct file *file,
+static int iuu_tiocmset(struct tty_struct *tty, struct file *file,
 			unsigned int set, unsigned int clear)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct iuu_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 
@@ -171,8 +172,9 @@
  * When no card , the reader respond with TIOCM_CD
  * This is known as CD autodetect mechanism
  */
-static int iuu_tiocmget(struct usb_serial_port *port, struct file *file)
+static int iuu_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct iuu_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	int rc;
@@ -316,11 +318,10 @@
 					 port->bulk_out_endpointAddress), buf,
 			 count, &actual, HZ * 1);
 
-	if (status != IUU_OPERATION_OK) {
+	if (status != IUU_OPERATION_OK)
 		dbg("%s - error = %2x", __func__, status);
-	} else {
+	else
 		dbg("%s - write OK !", __func__);
-	}
 	return status;
 }
 
@@ -340,12 +341,10 @@
 					 port->bulk_in_endpointAddress), buf,
 			 count, &actual, HZ * 1);
 
-	if (status != IUU_OPERATION_OK) {
+	if (status != IUU_OPERATION_OK)
 		dbg("%s - error = %2x", __func__, status);
-	} else {
+	else
 		dbg("%s - read OK !", __func__);
-	}
-
 	return status;
 }
 
@@ -630,7 +629,7 @@
 	}
 
 	dbg("%s - %i chars to write", __func__, urb->actual_length);
-	tty = port->tty;
+	tty = port->port.tty;
 	if (data == NULL)
 		dbg("%s - data is NULL !!!", __func__);
 	if (tty && urb->actual_length && data) {
@@ -752,11 +751,10 @@
 	/* if nothing to write call again rxcmd */
 	dbg("%s - rxcmd recall", __func__);
 	iuu_led_activity_off(urb);
-	return;
 }
 
-static int iuu_uart_write(struct usb_serial_port *port, const u8 *buf,
-			  int count)
+static int iuu_uart_write(struct tty_struct *tty, struct usb_serial_port *port,
+			  const u8 *buf, int count)
 {
 	struct iuu_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
@@ -769,14 +767,14 @@
 	if (priv->writelen > 0) {
 		/* buffer already filled but not commited */
 		spin_unlock_irqrestore(&priv->lock, flags);
-		return (0);
+		return 0;
 	}
 	/* fill the buffer */
 	memcpy(priv->writebuf, buf, count);
 	priv->writelen = count;
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	return (count);
+	return count;
 }
 
 static void read_rxcmd_callback(struct urb *urb)
@@ -948,7 +946,8 @@
 	return 0;
 }
 
-static void iuu_close(struct usb_serial_port *port, struct file *filp)
+static void iuu_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	/* iuu_led (port,255,0,0,0); */
 	struct usb_serial *serial;
@@ -964,8 +963,8 @@
 
 	iuu_uart_off(port);
 	if (serial->dev) {
-		if (port->tty) {
-			c_cflag = port->tty->termios->c_cflag;
+		if (tty) {
+			c_cflag = tty->termios->c_cflag;
 			if (c_cflag & HUPCL) {
 				/* drop DTR and RTS */
 				priv = usb_get_serial_port_data(port);
@@ -989,7 +988,8 @@
 	}
 }
 
-static int iuu_open(struct usb_serial_port *port, struct file *filp)
+static int iuu_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct usb_serial *serial = port->serial;
 	u8 *buf;
@@ -1036,15 +1036,17 @@
 
 	/* set the termios structure */
 	spin_lock_irqsave(&priv->lock, flags);
-	if (!priv->termios_initialized) {
-		*(port->tty->termios) = tty_std_termios;
-		port->tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600
-						| TIOCM_CTS | CSTOPB | PARENB;
-		port->tty->termios->c_lflag = 0;
-		port->tty->termios->c_oflag = 0;
-		port->tty->termios->c_iflag = 0;
+	if (tty && !priv->termios_initialized) {
+		*(tty->termios) = tty_std_termios;
+		tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600
+					| TIOCM_CTS | CSTOPB | PARENB;
+		tty->termios->c_ispeed = 9600;
+		tty->termios->c_ospeed = 9600;
+		tty->termios->c_lflag = 0;
+		tty->termios->c_oflag = 0;
+		tty->termios->c_iflag = 0;
 		priv->termios_initialized = 1;
-		port->tty->low_latency = 1;
+		tty->low_latency = 1;
 		priv->poll = 0;
 	 }
 	spin_unlock_irqrestore(&priv->lock, flags);
@@ -1148,7 +1150,7 @@
 	if (result) {
 		dev_err(&port->dev, "%s - failed submitting read urb,"
 			" error %d\n", __func__, result);
-		iuu_close(port, NULL);
+		iuu_close(tty, port, NULL);
 		return -EPROTO;
 	} else {
 		dbg("%s - rxcmd OK", __func__);
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 11e439b..704716f 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -1,29 +1,29 @@
 /*
   Keyspan USB to Serial Converter driver
- 
+
   (C) Copyright (C) 2000-2001	Hugh Blemings <hugh@blemings.org>
   (C) Copyright (C) 2002	Greg Kroah-Hartman <greg@kroah.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.
 
   See http://misc.nu/hugh/keyspan.html for more information.
-  
+
   Code in this driver inspired by and in a number of places taken
   from Brian Warner's original Keyspan-PDA driver.
 
   This driver has been put together with the support of Innosys, Inc.
   and Keyspan, Inc the manufacturers of the Keyspan USB-serial products.
   Thanks Guys :)
-  
+
   Thanks to Paulus for miscellaneous tidy ups, some largish chunks
   of much nicer and/or completely new code and (perhaps most uniquely)
   having the patience to sit down and explain why and where he'd changed
-  stuff. 
-  
-  Tip 'o the hat to IBM (and previously Linuxcare :) for supporting 
+  stuff.
+
+  Tip 'o the hat to IBM (and previously Linuxcare :) for supporting
   staff in their work on open source projects.
 
   Change History
@@ -70,21 +70,21 @@
 
     Thu May 31 11:56:42 PDT 2001 gkh
       switched from using spinlock to a semaphore
-   
+
     (04/08/2001) gb
 	Identify version on module load.
-   
+
     (11/01/2000) Adam J. Richter
 	usb_device_id table support.
-   
+
     Tue Oct 10 23:15:33 EST 2000 Hugh
       Merged Paul's changes with my USA-49W mods.  Work in progress
       still...
-  
+
     Wed Jul 19 14:00:42 EST 2000 gkh
       Added module_init and module_exit functions to handle the fact that
       this driver is a loadable module now.
- 
+
     Tue Jul 18 16:14:52 EST 2000 Hugh
       Basic character input/output for USA-19 now mostly works,
       fixed at 9600 baud for the moment.
@@ -107,7 +107,7 @@
 #include <linux/spinlock.h>
 #include <linux/firmware.h>
 #include <linux/ihex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 #include "keyspan.h"
@@ -132,15 +132,15 @@
 	struct urb	*instat_urb;
 	char		instat_buf[INSTAT_BUFLEN];
 
-	/* added to support 49wg, where data from all 4 ports comes in on 1 EP */
-	/* and high-speed supported */
+	/* added to support 49wg, where data from all 4 ports comes in
+	   on 1 EP and high-speed supported */
 	struct urb	*indat_urb;
 	char		indat_buf[INDAT49W_BUFLEN];
 
 	/* XXX this one probably will need a lock */
 	struct urb	*glocont_urb;
 	char		glocont_buf[GLOCONT_BUFLEN];
-	char		ctrl_buf[8];			// for EP0 control message
+	char		ctrl_buf[8];	/* for EP0 control message */
 };
 
 struct keyspan_port_private {
@@ -186,19 +186,19 @@
 	int		resend_cont;	/* need to resend control packet */
 };
 
-	
 /* Include Keyspan message headers.  All current Keyspan Adapters
    make use of one of five message formats which are referred
-   to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and within this driver. */
+   to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and
+   within this driver. */
 #include "keyspan_usa26msg.h"
 #include "keyspan_usa28msg.h"
 #include "keyspan_usa49msg.h"
 #include "keyspan_usa90msg.h"
 #include "keyspan_usa67msg.h"
-	
+
 
 /* Functions used by new usb-serial code. */
-static int __init keyspan_init (void)
+static int __init keyspan_init(void)
 {
 	int retval;
 	retval = usb_serial_register(&keyspan_pre_device);
@@ -214,7 +214,7 @@
 	if (retval)
 		goto failed_4port_device_register;
 	retval = usb_register(&keyspan_driver);
-	if (retval) 
+	if (retval)
 		goto failed_usb_register;
 
 	info(DRIVER_VERSION ":" DRIVER_DESC);
@@ -232,35 +232,24 @@
 	return retval;
 }
 
-static void __exit keyspan_exit (void)
+static void __exit keyspan_exit(void)
 {
-	usb_deregister (&keyspan_driver);
-	usb_serial_deregister (&keyspan_pre_device);
-	usb_serial_deregister (&keyspan_1port_device);
-	usb_serial_deregister (&keyspan_2port_device);
-	usb_serial_deregister (&keyspan_4port_device);
+	usb_deregister(&keyspan_driver);
+	usb_serial_deregister(&keyspan_pre_device);
+	usb_serial_deregister(&keyspan_1port_device);
+	usb_serial_deregister(&keyspan_2port_device);
+	usb_serial_deregister(&keyspan_4port_device);
 }
 
 module_init(keyspan_init);
 module_exit(keyspan_exit);
 
-static void keyspan_rx_throttle (struct usb_serial_port *port)
+static void keyspan_break_ctl(struct tty_struct *tty, int break_state)
 {
-	dbg("%s - port %d", __func__, port->number);
-}
-
-
-static void keyspan_rx_unthrottle (struct usb_serial_port *port)
-{
-	dbg("%s - port %d", __func__, port->number);
-}
-
-
-static void keyspan_break_ctl (struct usb_serial_port *port, int break_state)
-{
+	struct usb_serial_port *port = tty->driver_data;
 	struct keyspan_port_private 	*p_priv;
 
- 	dbg("%s", __func__);
+	dbg("%s", __func__);
 
 	p_priv = usb_get_serial_port_data(port);
 
@@ -273,14 +262,13 @@
 }
 
 
-static void keyspan_set_termios (struct usb_serial_port *port, 
-				     struct ktermios *old_termios)
+static void keyspan_set_termios(struct tty_struct *tty,
+		struct usb_serial_port *port, struct ktermios *old_termios)
 {
 	int				baud_rate, device_port;
 	struct keyspan_port_private 	*p_priv;
 	const struct keyspan_device_details	*d_details;
 	unsigned int 			cflag;
-	struct tty_struct		*tty = port->tty;
 
 	dbg("%s", __func__);
 
@@ -292,7 +280,7 @@
 	/* Baud rate calculation takes baud rate as an integer
 	   so other rates can be generated if desired. */
 	baud_rate = tty_get_baud_rate(tty);
-	/* If no match or invalid, don't change */		
+	/* If no match or invalid, don't change */
 	if (d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
 				NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
 		/* FIXME - more to do here to ensure rate changes cleanly */
@@ -312,35 +300,32 @@
 	keyspan_send_setup(port, 0);
 }
 
-static int keyspan_tiocmget(struct usb_serial_port *port, struct file *file)
+static int keyspan_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct usb_serial_port *port = tty->driver_data;
+	struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
 	unsigned int			value;
-	struct keyspan_port_private 	*p_priv;
 
-	p_priv = usb_get_serial_port_data(port);
-	
 	value = ((p_priv->rts_state) ? TIOCM_RTS : 0) |
 		((p_priv->dtr_state) ? TIOCM_DTR : 0) |
 		((p_priv->cts_state) ? TIOCM_CTS : 0) |
 		((p_priv->dsr_state) ? TIOCM_DSR : 0) |
 		((p_priv->dcd_state) ? TIOCM_CAR : 0) |
-		((p_priv->ri_state) ? TIOCM_RNG : 0); 
+		((p_priv->ri_state) ? TIOCM_RNG : 0);
 
 	return value;
 }
 
-static int keyspan_tiocmset(struct usb_serial_port *port, struct file *file,
+static int keyspan_tiocmset(struct tty_struct *tty, struct file *file,
 			    unsigned int set, unsigned int clear)
 {
-	struct keyspan_port_private 	*p_priv;
+	struct usb_serial_port *port = tty->driver_data;
+	struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
 
-	p_priv = usb_get_serial_port_data(port);
-	
 	if (set & TIOCM_RTS)
 		p_priv->rts_state = 1;
 	if (set & TIOCM_DTR)
 		p_priv->dtr_state = 1;
-
 	if (clear & TIOCM_RTS)
 		p_priv->rts_state = 0;
 	if (clear & TIOCM_DTR)
@@ -349,35 +334,29 @@
 	return 0;
 }
 
-static int keyspan_ioctl(struct usb_serial_port *port, struct file *file,
-			     unsigned int cmd, unsigned long arg)
-{
-	return -ENOIOCTLCMD;
-}
-
-	/* Write function is similar for the four protocols used
-	   with only a minor change for usa90 (usa19hs) required */
-static int keyspan_write(struct usb_serial_port *port, 
-			 const unsigned char *buf, int count)
+/* Write function is similar for the four protocols used
+   with only a minor change for usa90 (usa19hs) required */
+static int keyspan_write(struct tty_struct *tty,
+	struct usb_serial_port *port, const unsigned char *buf, int count)
 {
 	struct keyspan_port_private 	*p_priv;
 	const struct keyspan_device_details	*d_details;
 	int				flip;
 	int 				left, todo;
 	struct urb			*this_urb;
- 	int 				err, maxDataLen, dataOffset;
+	int 				err, maxDataLen, dataOffset;
 
 	p_priv = usb_get_serial_port_data(port);
 	d_details = p_priv->device_details;
 
 	if (d_details->msg_format == msg_usa90) {
-   		maxDataLen = 64;
+		maxDataLen = 64;
 		dataOffset = 0;
 	} else {
 		maxDataLen = 63;
 		dataOffset = 1;
 	}
-	
+
 	dbg("%s - for port %d (%d chars), flip=%d",
 	    __func__, port->number, count, p_priv->out_flip);
 
@@ -387,37 +366,40 @@
 			todo = maxDataLen;
 
 		flip = p_priv->out_flip;
-	
+
 		/* Check we have a valid urb/endpoint before we use it... */
-		if ((this_urb = p_priv->out_urbs[flip]) == NULL) {
+		this_urb = p_priv->out_urbs[flip];
+		if (this_urb == NULL) {
 			/* no bulk out, so return 0 bytes written */
 			dbg("%s - no output urb :(", __func__);
 			return count;
 		}
 
-		dbg("%s - endpoint %d flip %d", __func__, usb_pipeendpoint(this_urb->pipe), flip);
+		dbg("%s - endpoint %d flip %d",
+			__func__, usb_pipeendpoint(this_urb->pipe), flip);
 
 		if (this_urb->status == -EINPROGRESS) {
-			if (time_before(jiffies, p_priv->tx_start_time[flip] + 10 * HZ))
+			if (time_before(jiffies,
+					p_priv->tx_start_time[flip] + 10 * HZ))
 				break;
 			usb_unlink_urb(this_urb);
 			break;
 		}
 
-		/* First byte in buffer is "last flag" (except for usa19hx) - unused so
-		   for now so set to zero */
+		/* First byte in buffer is "last flag" (except for usa19hx)
+		   - unused so for now so set to zero */
 		((char *)this_urb->transfer_buffer)[0] = 0;
 
-		memcpy (this_urb->transfer_buffer + dataOffset, buf, todo);
+		memcpy(this_urb->transfer_buffer + dataOffset, buf, todo);
 		buf += todo;
 
 		/* send the data out the bulk port */
 		this_urb->transfer_buffer_length = todo + dataOffset;
 
 		this_urb->dev = port->serial->dev;
-		if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
+		err = usb_submit_urb(this_urb, GFP_ATOMIC);
+		if (err != 0)
 			dbg("usb_submit_urb(write bulk) failed (%d)", err);
-		}
 		p_priv->tx_start_time[flip] = jiffies;
 
 		/* Flip for next time if usa26 or usa28 interface
@@ -437,7 +419,7 @@
 	unsigned char 		*data = urb->transfer_buffer;
 	int status = urb->status;
 
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 
 	endpoint = usb_pipeendpoint(urb->pipe);
 
@@ -448,17 +430,18 @@
 	}
 
 	port =  urb->context;
-	tty = port->tty;
+	tty = port->port.tty;
 	if (tty && urb->actual_length) {
 		/* 0x80 bit is error flag */
 		if ((data[0] & 0x80) == 0) {
-			/* no errors on individual bytes, only possible overrun err*/
+			/* no errors on individual bytes, only
+			   possible overrun err */
 			if (data[0] & RXERROR_OVERRUN)
-					err = TTY_OVERRUN;
-			else err = 0;
-			for (i = 1; i < urb->actual_length ; ++i) {
+				err = TTY_OVERRUN;
+			else
+				err = 0;
+			for (i = 1; i < urb->actual_length ; ++i)
 				tty_insert_flip_char(tty, data[i], err);
-			}
 		} else {
 			/* some bytes had errors, every byte has status */
 			dbg("%s - RX error!!!!", __func__);
@@ -476,17 +459,19 @@
 		}
 		tty_flip_buffer_push(tty);
 	}
-				
-		/* Resubmit urb so we continue receiving */
+
+	/* Resubmit urb so we continue receiving */
 	urb->dev = port->serial->dev;
-	if (port->open_count)
-		if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
-			dbg("%s - resubmit read urb failed. (%d)", __func__, err);
-		}
+	if (port->port.count) {
+		err = usb_submit_urb(urb, GFP_ATOMIC);
+		if (err != 0)
+			dbg("%s - resubmit read urb failed. (%d)",
+					__func__, err);
+	}
 	return;
 }
 
- 	/* Outdat handling is common for all devices */
+/* Outdat handling is common for all devices */
 static void	usa2x_outdat_callback(struct urb *urb)
 {
 	struct usb_serial_port *port;
@@ -494,16 +479,16 @@
 
 	port =  urb->context;
 	p_priv = usb_get_serial_port_data(port);
-	dbg ("%s - urb %d", __func__, urb == p_priv->out_urbs[1]);
+	dbg("%s - urb %d", __func__, urb == p_priv->out_urbs[1]);
 
-	if (port->open_count)
+	if (port->port.count)
 		usb_serial_port_softint(port);
 }
 
 static void	usa26_inack_callback(struct urb *urb)
 {
-	dbg ("%s", __func__);
-	
+	dbg("%s", __func__);
+
 }
 
 static void	usa26_outcont_callback(struct urb *urb)
@@ -515,8 +500,9 @@
 	p_priv = usb_get_serial_port_data(port);
 
 	if (p_priv->resend_cont) {
-		dbg ("%s - sending setup", __func__);
-		keyspan_usa26_send_setup(port->serial, port, p_priv->resend_cont - 1);
+		dbg("%s - sending setup", __func__);
+		keyspan_usa26_send_setup(port->serial, port,
+						p_priv->resend_cont - 1);
 	}
 }
 
@@ -552,14 +538,14 @@
 	/* Now do something useful with the data */
 
 
-	/* Check port number from message and retrieve private data */	
+	/* Check port number from message and retrieve private data */
 	if (msg->port >= serial->num_ports) {
-		dbg ("%s - Unexpected port number %d", __func__, msg->port);
+		dbg("%s - Unexpected port number %d", __func__, msg->port);
 		goto exit;
 	}
 	port = serial->port[msg->port];
 	p_priv = usb_get_serial_port_data(port);
-	
+
 	/* Update handshaking pin state information */
 	old_dcd_state = p_priv->dcd_state;
 	p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
@@ -567,39 +553,38 @@
 	p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
 	p_priv->ri_state = ((msg->ri) ? 1 : 0);
 
-	if (port->tty && !C_CLOCAL(port->tty)
+	if (port->port.tty && !C_CLOCAL(port->port.tty)
 	    && old_dcd_state != p_priv->dcd_state) {
 		if (old_dcd_state)
-			tty_hangup(port->tty);
+			tty_hangup(port->port.tty);
 		/*  else */
 		/*	wake_up_interruptible(&p_priv->open_wait); */
 	}
-	
+
 	/* Resubmit urb so we continue receiving */
 	urb->dev = serial->dev;
-	if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (err != 0)
 		dbg("%s - resubmit read urb failed. (%d)", __func__, err);
-	}
 exit: ;
 }
 
 static void	usa26_glocont_callback(struct urb *urb)
 {
-	dbg ("%s", __func__);
-	
+	dbg("%s", __func__);
 }
 
 
 static void usa28_indat_callback(struct urb *urb)
 {
-	int                     i, err;
+	int                     err;
 	struct usb_serial_port  *port;
 	struct tty_struct       *tty;
 	unsigned char           *data;
 	struct keyspan_port_private             *p_priv;
 	int status = urb->status;
 
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 
 	port =  urb->context;
 	p_priv = usb_get_serial_port_data(port);
@@ -619,20 +604,20 @@
 		p_priv = usb_get_serial_port_data(port);
 		data = urb->transfer_buffer;
 
-		tty = port->tty;
+		tty = port->port.tty;
 		if (urb->actual_length) {
-			for (i = 0; i < urb->actual_length ; ++i) {
-				tty_insert_flip_char(tty, data[i], 0);
-			}
+			tty_insert_flip_string(tty, data, urb->actual_length);
 			tty_flip_buffer_push(tty);
 		}
 
 		/* Resubmit urb so we continue receiving */
 		urb->dev = port->serial->dev;
-		if (port->open_count)
-			if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
-				dbg("%s - resubmit read urb failed. (%d)", __func__, err);
-			}
+		if (port->port.count) {
+			err = usb_submit_urb(urb, GFP_ATOMIC);
+			if (err != 0)
+				dbg("%s - resubmit read urb failed. (%d)",
+								__func__, err);
+		}
 		p_priv->in_flip ^= 1;
 
 		urb = p_priv->in_urbs[p_priv->in_flip];
@@ -641,7 +626,7 @@
 
 static void	usa28_inack_callback(struct urb *urb)
 {
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 }
 
 static void	usa28_outcont_callback(struct urb *urb)
@@ -653,8 +638,9 @@
 	p_priv = usb_get_serial_port_data(port);
 
 	if (p_priv->resend_cont) {
-		dbg ("%s - sending setup", __func__);
-		keyspan_usa28_send_setup(port->serial, port, p_priv->resend_cont - 1);
+		dbg("%s - sending setup", __func__);
+		keyspan_usa28_send_setup(port->serial, port,
+						p_priv->resend_cont - 1);
 	}
 }
 
@@ -684,19 +670,18 @@
 	/*dbg("%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__
 	    data[0], data[1], data[2], data[3], data[4], data[5],
 	    data[6], data[7], data[8], data[9], data[10], data[11]);*/
-	
-		/* Now do something useful with the data */
+
+	/* Now do something useful with the data */
 	msg = (struct keyspan_usa28_portStatusMessage *)data;
 
-
-		/* Check port number from message and retrieve private data */	
+	/* Check port number from message and retrieve private data */
 	if (msg->port >= serial->num_ports) {
-		dbg ("%s - Unexpected port number %d", __func__, msg->port);
+		dbg("%s - Unexpected port number %d", __func__, msg->port);
 		goto exit;
 	}
 	port = serial->port[msg->port];
 	p_priv = usb_get_serial_port_data(port);
-	
+
 	/* Update handshaking pin state information */
 	old_dcd_state = p_priv->dcd_state;
 	p_priv->cts_state = ((msg->cts) ? 1 : 0);
@@ -704,25 +689,25 @@
 	p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
 	p_priv->ri_state = ((msg->ri) ? 1 : 0);
 
-	if (port->tty && !C_CLOCAL(port->tty)
+	if (port->port.tty && !C_CLOCAL(port->port.tty)
 	    && old_dcd_state != p_priv->dcd_state) {
 		if (old_dcd_state)
-			tty_hangup(port->tty);
+			tty_hangup(port->port.tty);
 		/*  else */
 		/*	wake_up_interruptible(&p_priv->open_wait); */
 	}
 
 		/* Resubmit urb so we continue receiving */
 	urb->dev = serial->dev;
-	if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (err != 0)
 		dbg("%s - resubmit read urb failed. (%d)", __func__, err);
-	}
 exit: ;
 }
 
 static void	usa28_glocont_callback(struct urb *urb)
 {
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 }
 
 
@@ -733,7 +718,7 @@
 	struct keyspan_port_private *p_priv;
 	int i;
 
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 
 	serial =  urb->context;
 	for (i = 0; i < serial->num_ports; ++i) {
@@ -741,8 +726,9 @@
 		p_priv = usb_get_serial_port_data(port);
 
 		if (p_priv->resend_cont) {
-			dbg ("%s - sending setup", __func__);
-			keyspan_usa49_send_setup(serial, port, p_priv->resend_cont - 1);
+			dbg("%s - sending setup", __func__);
+			keyspan_usa49_send_setup(serial, port,
+						p_priv->resend_cont - 1);
 			break;
 		}
 	}
@@ -761,7 +747,7 @@
 	int old_dcd_state;
 	int status = urb->status;
 
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 
 	serial =  urb->context;
 
@@ -770,7 +756,8 @@
 		return;
 	}
 
-	if (urb->actual_length != sizeof(struct keyspan_usa49_portStatusMessage)) {
+	if (urb->actual_length !=
+			sizeof(struct keyspan_usa49_portStatusMessage)) {
 		dbg("%s - bad length %d", __func__, urb->actual_length);
 		goto exit;
 	}
@@ -778,18 +765,19 @@
 	/*dbg(" %x %x %x %x %x %x %x %x %x %x %x", __func__,
 	    data[0], data[1], data[2], data[3], data[4], data[5],
 	    data[6], data[7], data[8], data[9], data[10]);*/
-	
-		/* Now do something useful with the data */
+
+	/* Now do something useful with the data */
 	msg = (struct keyspan_usa49_portStatusMessage *)data;
 
-		/* Check port number from message and retrieve private data */	
+	/* Check port number from message and retrieve private data */
 	if (msg->portNumber >= serial->num_ports) {
-		dbg ("%s - Unexpected port number %d", __func__, msg->portNumber);
+		dbg("%s - Unexpected port number %d",
+					__func__, msg->portNumber);
 		goto exit;
 	}
 	port = serial->port[msg->portNumber];
 	p_priv = usb_get_serial_port_data(port);
-	
+
 	/* Update handshaking pin state information */
 	old_dcd_state = p_priv->dcd_state;
 	p_priv->cts_state = ((msg->cts) ? 1 : 0);
@@ -797,26 +785,26 @@
 	p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
 	p_priv->ri_state = ((msg->ri) ? 1 : 0);
 
-	if (port->tty && !C_CLOCAL(port->tty)
+	if (port->port.tty && !C_CLOCAL(port->port.tty)
 	    && old_dcd_state != p_priv->dcd_state) {
 		if (old_dcd_state)
-			tty_hangup(port->tty);
+			tty_hangup(port->port.tty);
 		/*  else */
 		/*	wake_up_interruptible(&p_priv->open_wait); */
 	}
 
-		/* Resubmit urb so we continue receiving */
+	/* Resubmit urb so we continue receiving */
 	urb->dev = serial->dev;
 
-	if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (err != 0)
 		dbg("%s - resubmit read urb failed. (%d)", __func__, err);
-	}
 exit:	;
 }
 
 static void	usa49_inack_callback(struct urb *urb)
 {
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 }
 
 static void	usa49_indat_callback(struct urb *urb)
@@ -828,7 +816,7 @@
 	unsigned char 		*data = urb->transfer_buffer;
 	int status = urb->status;
 
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 
 	endpoint = usb_pipeendpoint(urb->pipe);
 
@@ -839,14 +827,13 @@
 	}
 
 	port =  urb->context;
-	tty = port->tty;
+	tty = port->port.tty;
 	if (tty && urb->actual_length) {
 		/* 0x80 bit is error flag */
 		if ((data[0] & 0x80) == 0) {
 			/* no error on any byte */
-			for (i = 1; i < urb->actual_length ; ++i) {
-				tty_insert_flip_char(tty, data[i], 0);
-			}
+			tty_insert_flip_string(tty, data + 1,
+						urb->actual_length - 1);
 		} else {
 			/* some bytes had errors, every byte has status */
 			for (i = 0; i + 1 < urb->actual_length; i += 2) {
@@ -863,13 +850,15 @@
 		}
 		tty_flip_buffer_push(tty);
 	}
-				
-		/* Resubmit urb so we continue receiving */
+
+	/* Resubmit urb so we continue receiving */
 	urb->dev = port->serial->dev;
-	if (port->open_count)
-		if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
-			dbg("%s - resubmit read urb failed. (%d)", __func__, err);
-		}
+	if (port->port.count) {
+		err = usb_submit_urb(urb, GFP_ATOMIC);
+		if (err != 0)
+			dbg("%s - resubmit read urb failed. (%d)",
+							__func__, err);
+	}
 }
 
 static void usa49wg_indat_callback(struct urb *urb)
@@ -881,7 +870,7 @@
 	unsigned char 		*data = urb->transfer_buffer;
 	int status = urb->status;
 
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 
 	serial = urb->context;
 
@@ -899,12 +888,12 @@
 
 			/* Check port number from message*/
 			if (data[i] >= serial->num_ports) {
-				dbg ("%s - Unexpected port number %d",
+				dbg("%s - Unexpected port number %d",
 					__func__, data[i]);
 				return;
 			}
 			port = serial->port[data[i++]];
-			tty = port->tty;
+			tty = port->port.tty;
 			len = data[i++];
 
 			/* 0x80 bit is error flag */
@@ -912,7 +901,7 @@
 				/* no error on any byte */
 				i++;
 				for (x = 1; x < len ; ++x)
-					if (port->open_count)
+					if (port->port.count)
 						tty_insert_flip_char(tty,
 								data[i++], 0);
 					else
@@ -930,13 +919,13 @@
 					if (stat & RXERROR_PARITY)
 						flag |= TTY_PARITY;
 					/* XXX should handle break (0x10) */
-					if (port->open_count)
+					if (port->port.count)
 						tty_insert_flip_char(tty,
 							data[i+1], flag);
 					i += 2;
 				}
 			}
-			if (port->open_count)
+			if (port->port.count)
 				tty_flip_buffer_push(tty);
 		}
 	}
@@ -952,7 +941,7 @@
 /* not used, usa-49 doesn't have per-port control endpoints */
 static void usa49_outcont_callback(struct urb *urb)
 {
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 }
 
 static void usa90_indat_callback(struct urb *urb)
@@ -965,7 +954,7 @@
 	unsigned char 		*data = urb->transfer_buffer;
 	int status = urb->status;
 
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 
 	endpoint = usb_pipeendpoint(urb->pipe);
 
@@ -978,29 +967,26 @@
 	port =  urb->context;
 	p_priv = usb_get_serial_port_data(port);
 
-	tty = port->tty;
+	tty = port->port.tty;
 	if (urb->actual_length) {
-	
 		/* if current mode is DMA, looks like usa28 format
-	   		otherwise looks like usa26 data format */
+		   otherwise looks like usa26 data format */
 
-		if (p_priv->baud > 57600) {
-			for (i = 0; i < urb->actual_length ; ++i) 
-				tty_insert_flip_char(tty, data[i], 0);
-		}
+		if (p_priv->baud > 57600)
+			tty_insert_flip_string(tty, data, urb->actual_length);
 		else {
-			
 			/* 0x80 bit is error flag */
 			if ((data[0] & 0x80) == 0) {
-				/* no errors on individual bytes, only possible overrun err*/
+				/* no errors on individual bytes, only
+				   possible overrun err*/
 				if (data[0] & RXERROR_OVERRUN)
-						err = TTY_OVERRUN;
-				else err = 0;
-				for (i = 1; i < urb->actual_length ; ++i) 
-					tty_insert_flip_char(tty, data[i], err);
-			
-			} 
-			else {
+					err = TTY_OVERRUN;
+				else
+					err = 0;
+				for (i = 1; i < urb->actual_length ; ++i)
+					tty_insert_flip_char(tty, data[i],
+									err);
+			}  else {
 			/* some bytes had errors, every byte has status */
 				dbg("%s - RX error!!!!", __func__);
 				for (i = 0; i + 1 < urb->actual_length; i += 2) {
@@ -1012,19 +998,22 @@
 					if (stat & RXERROR_PARITY)
 						flag |= TTY_PARITY;
 					/* XXX should handle break (0x10) */
-					tty_insert_flip_char(tty, data[i+1], flag);
+					tty_insert_flip_char(tty, data[i+1],
+									flag);
 				}
 			}
 		}
 		tty_flip_buffer_push(tty);
 	}
-				
+
 	/* Resubmit urb so we continue receiving */
 	urb->dev = port->serial->dev;
-	if (port->open_count)
-		if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
-			dbg("%s - resubmit read urb failed. (%d)", __func__, err);
-		}
+	if (port->port.count) {
+		err = usb_submit_urb(urb, GFP_ATOMIC);
+		if (err != 0)
+			dbg("%s - resubmit read urb failed. (%d)",
+							__func__, err);
+	}
 	return;
 }
 
@@ -1056,7 +1045,7 @@
 
 	port = serial->port[0];
 	p_priv = usb_get_serial_port_data(port);
-	
+
 	/* Update handshaking pin state information */
 	old_dcd_state = p_priv->dcd_state;
 	p_priv->cts_state = ((msg->cts) ? 1 : 0);
@@ -1064,19 +1053,19 @@
 	p_priv->dcd_state = ((msg->dcd) ? 1 : 0);
 	p_priv->ri_state = ((msg->ri) ? 1 : 0);
 
-	if (port->tty && !C_CLOCAL(port->tty)
+	if (port->port.tty && !C_CLOCAL(port->port.tty)
 	    && old_dcd_state != p_priv->dcd_state) {
 		if (old_dcd_state)
-			tty_hangup(port->tty);
+			tty_hangup(port->port.tty);
 		/*  else */
 		/*	wake_up_interruptible(&p_priv->open_wait); */
 	}
-	
+
 	/* Resubmit urb so we continue receiving */
 	urb->dev = serial->dev;
-	if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (err != 0)
 		dbg("%s - resubmit read urb failed. (%d)", __func__, err);
-	}
 exit:
 	;
 }
@@ -1090,8 +1079,9 @@
 	p_priv = usb_get_serial_port_data(port);
 
 	if (p_priv->resend_cont) {
-		dbg ("%s - sending setup", __func__);
-		keyspan_usa90_send_setup(port->serial, port, p_priv->resend_cont - 1);
+		dbg("%s - sending setup", __func__);
+		keyspan_usa90_send_setup(port->serial, port,
+						p_priv->resend_cont - 1);
 	}
 }
 
@@ -1107,7 +1097,7 @@
 	int old_dcd_state;
 	int status = urb->status;
 
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 
 	serial = urb->context;
 
@@ -1116,7 +1106,8 @@
 		return;
 	}
 
-	if (urb->actual_length != sizeof(struct keyspan_usa67_portStatusMessage)) {
+	if (urb->actual_length !=
+			sizeof(struct keyspan_usa67_portStatusMessage)) {
 		dbg("%s - bad length %d", __func__, urb->actual_length);
 		return;
 	}
@@ -1127,7 +1118,7 @@
 
 	/* Check port number from message and retrieve private data */
 	if (msg->port >= serial->num_ports) {
-		dbg ("%s - Unexpected port number %d", __func__, msg->port);
+		dbg("%s - Unexpected port number %d", __func__, msg->port);
 		return;
 	}
 
@@ -1139,10 +1130,10 @@
 	p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
 	p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
 
-	if (port->tty && !C_CLOCAL(port->tty)
+	if (port->port.tty && !C_CLOCAL(port->port.tty)
 	    && old_dcd_state != p_priv->dcd_state) {
 		if (old_dcd_state)
-			tty_hangup(port->tty);
+			tty_hangup(port->port.tty);
 		/*  else */
 		/*	wake_up_interruptible(&p_priv->open_wait); */
 	}
@@ -1161,7 +1152,7 @@
 	struct keyspan_port_private *p_priv;
 	int i;
 
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 
 	serial = urb->context;
 	for (i = 0; i < serial->num_ports; ++i) {
@@ -1169,7 +1160,7 @@
 		p_priv = usb_get_serial_port_data(port);
 
 		if (p_priv->resend_cont) {
-			dbg ("%s - sending setup", __func__);
+			dbg("%s - sending setup", __func__);
 			keyspan_usa67_send_setup(serial, port,
 						p_priv->resend_cont - 1);
 			break;
@@ -1177,8 +1168,9 @@
 	}
 }
 
-static int keyspan_write_room (struct usb_serial_port *port)
+static int keyspan_write_room(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct keyspan_port_private	*p_priv;
 	const struct keyspan_device_details	*d_details;
 	int				flip;
@@ -1191,32 +1183,30 @@
 
 	/* FIXME: locking */
 	if (d_details->msg_format == msg_usa90)
-   		data_len = 64;
+		data_len = 64;
 	else
 		data_len = 63;
 
 	flip = p_priv->out_flip;
 
 	/* Check both endpoints to see if any are available. */
-	if ((this_urb = p_priv->out_urbs[flip]) != NULL) {
+	this_urb = p_priv->out_urbs[flip];
+	if (this_urb != NULL) {
 		if (this_urb->status != -EINPROGRESS)
-			return (data_len);
-		flip = (flip + 1) & d_details->outdat_endp_flip;        
-		if ((this_urb = p_priv->out_urbs[flip]) != NULL) 
+			return data_len;
+		flip = (flip + 1) & d_details->outdat_endp_flip;
+		this_urb = p_priv->out_urbs[flip];
+		if (this_urb != NULL) {
 			if (this_urb->status != -EINPROGRESS)
-				return (data_len);
+				return data_len;
+		}
 	}
 	return 0;
 }
 
 
-static int keyspan_chars_in_buffer (struct usb_serial_port *port)
-{
-	return 0;
-}
-
-
-static int keyspan_open (struct usb_serial_port *port, struct file *filp)
+static int keyspan_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct keyspan_port_private 	*p_priv;
 	struct keyspan_serial_private 	*s_priv;
@@ -1225,7 +1215,7 @@
 	int				i, err;
 	int				baud_rate, device_port;
 	struct urb			*urb;
-	unsigned int			cflag;
+	unsigned int			cflag = 0;
 
 	s_priv = usb_get_serial_data(serial);
 	p_priv = usb_get_serial_port_data(port);
@@ -1247,50 +1237,53 @@
 
 	/* Reset low level data toggle and start reading from endpoints */
 	for (i = 0; i < 2; i++) {
-		if ((urb = p_priv->in_urbs[i]) == NULL)
+		urb = p_priv->in_urbs[i];
+		if (urb == NULL)
 			continue;
 		urb->dev = serial->dev;
 
-		/* make sure endpoint data toggle is synchronized with the device */
-
+		/* make sure endpoint data toggle is synchronized
+		   with the device */
 		usb_clear_halt(urb->dev, urb->pipe);
-
-		if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
-			dbg("%s - submit urb %d failed (%d)", __func__, i, err);
-		}
+		err = usb_submit_urb(urb, GFP_KERNEL);
+		if (err != 0)
+			dbg("%s - submit urb %d failed (%d)",
+							__func__, i, err);
 	}
 
 	/* Reset low level data toggle on out endpoints */
 	for (i = 0; i < 2; i++) {
-		if ((urb = p_priv->out_urbs[i]) == NULL)
+		urb = p_priv->out_urbs[i];
+		if (urb == NULL)
 			continue;
 		urb->dev = serial->dev;
-		/* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); */
+		/* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+						usb_pipeout(urb->pipe), 0); */
 	}
 
 	/* get the terminal config for the setup message now so we don't
 	 * need to send 2 of them */
 
-	cflag = port->tty->termios->c_cflag;
 	device_port = port->number - port->serial->minor;
-
-	/* Baud rate calculation takes baud rate as an integer
-	   so other rates can be generated if desired. */
-	baud_rate = tty_get_baud_rate(port->tty);
-	/* If no match or invalid, leave as default */
-	if (baud_rate >= 0
-	    && d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
-				NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
-		p_priv->baud = baud_rate;
+	if (tty) {
+		cflag = tty->termios->c_cflag;
+		/* Baud rate calculation takes baud rate as an integer
+		   so other rates can be generated if desired. */
+		baud_rate = tty_get_baud_rate(tty);
+		/* If no match or invalid, leave as default */
+		if (baud_rate >= 0
+		    && d_details->calculate_baud_rate(baud_rate, d_details->baudclk,
+					NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) {
+			p_priv->baud = baud_rate;
+		}
 	}
-
 	/* set CTS/RTS handshake etc. */
 	p_priv->cflag = cflag;
 	p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none;
 
 	keyspan_send_setup(port, 1);
-	//mdelay(100);
-	//keyspan_set_termios(port, NULL);
+	/* mdelay(100); */
+	/* keyspan_set_termios(port, NULL); */
 
 	return 0;
 }
@@ -1301,7 +1294,8 @@
 		usb_kill_urb(urb);
 }
 
-static void keyspan_close(struct usb_serial_port *port, struct file *filp)
+static void keyspan_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	int			i;
 	struct usb_serial	*serial = port->serial;
@@ -1311,15 +1305,15 @@
 	dbg("%s", __func__);
 	s_priv = usb_get_serial_data(serial);
 	p_priv = usb_get_serial_port_data(port);
-	
+
 	p_priv->rts_state = 0;
 	p_priv->dtr_state = 0;
-	
+
 	if (serial->dev) {
 		keyspan_send_setup(port, 2);
 		/* pilot-xfer seems to work best with this delay */
 		mdelay(100);
-		// keyspan_set_termios(port, NULL);
+		/* keyspan_set_termios(port, NULL); */
 	}
 
 	/*while (p_priv->outcont_urb->status == -EINPROGRESS) {
@@ -1338,11 +1332,11 @@
 			stop_urb(p_priv->out_urbs[i]);
 		}
 	}
-	port->tty = NULL;
+	port->port.tty = NULL;
 }
 
-	/* download the firmware to a pre-renumeration device */
-static int keyspan_fake_startup (struct usb_serial *serial)
+/* download the firmware to a pre-renumeration device */
+static int keyspan_fake_startup(struct usb_serial *serial)
 {
 	int 				response;
 	const struct ihex_binrec 	*record;
@@ -1352,10 +1346,11 @@
 	dbg("Keyspan startup version %04x product %04x",
 	    le16_to_cpu(serial->dev->descriptor.bcdDevice),
 	    le16_to_cpu(serial->dev->descriptor.idProduct));
-	
-	if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000) != 0x8000) {
+
+	if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000)
+								!= 0x8000) {
 		dbg("Firmware already loaded.  Quitting.");
-		return(1);
+		return 1;
 	}
 
 		/* Select firmware image on the basis of idProduct */
@@ -1379,11 +1374,11 @@
 	case keyspan_usa19_pre_product_id:
 		fw_name = "keyspan/usa19.fw";
 		break;
-			     
+
 	case keyspan_usa19qi_pre_product_id:
 		fw_name = "keyspan/usa19qi.fw";
 		break;
-			     
+
 	case keyspan_mpr_pre_product_id:
 		fw_name = "keyspan/mpr.fw";
 		break;
@@ -1391,15 +1386,15 @@
 	case keyspan_usa19qw_pre_product_id:
 		fw_name = "keyspan/usa19qw.fw";
 		break;
-			     
+
 	case keyspan_usa18x_pre_product_id:
 		fw_name = "keyspan/usa18x.fw";
 		break;
-			     
+
 	case keyspan_usa19w_pre_product_id:
 		fw_name = "keyspan/usa19w.fw";
 		break;
-		
+
 	case keyspan_usa49w_pre_product_id:
 		fw_name = "keyspan/usa49w.fw";
 		break;
@@ -1431,8 +1426,7 @@
 					     (unsigned char *)record->data,
 					     be16_to_cpu(record->len), 0xa0);
 		if (response < 0) {
-			dev_err(&serial->dev->dev, "ezusb_writememory failed for Keyspan"
-				"firmware (%d %04X %p %d)\n",
+			dev_err(&serial->dev->dev, "ezusb_writememory failed for Keyspan firmware (%d %04X %p %d)\n",
 				response, be32_to_cpu(record->addr),
 				record->data, be16_to_cpu(record->len));
 			break;
@@ -1445,7 +1439,7 @@
 	response = ezusb_set_reset(serial, 0);
 
 	/* we don't want this device to have a driver assigned to it. */
-	return (1);
+	return 1;
 }
 
 /* Helper functions used by keyspan_setup_urbs */
@@ -1467,7 +1461,7 @@
 	return NULL;
 }
 
-static struct urb *keyspan_setup_urb (struct usb_serial *serial, int endpoint,
+static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
 				      int dir, void *ctx, char *buf, int len,
 				      void (*callback)(struct urb *))
 {
@@ -1478,10 +1472,10 @@
 	if (endpoint == -1)
 		return NULL;		/* endpoint not needed */
 
-	dbg ("%s - alloc for endpoint %d.", __func__, endpoint);
+	dbg("%s - alloc for endpoint %d.", __func__, endpoint);
 	urb = usb_alloc_urb(0, GFP_KERNEL);		/* No ISO */
 	if (urb == NULL) {
-		dbg ("%s - alloc for endpoint %d failed.", __func__, endpoint);
+		dbg("%s - alloc for endpoint %d failed.", __func__, endpoint);
 		return NULL;
 	}
 
@@ -1554,7 +1548,7 @@
 	}, {
 		/* msg_usa90 callbacks */
 		.instat_callback =	usa90_instat_callback,
-		.glocont_callback =	usa28_glocont_callback,		
+		.glocont_callback =	usa28_glocont_callback,
 		.indat_callback =	usa90_indat_callback,
 		.outdat_callback =	usa2x_outdat_callback,
 		.inack_callback =	usa28_inack_callback,
@@ -1582,16 +1576,16 @@
 	struct callbacks		*cback;
 	int				endp;
 
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 
 	s_priv = usb_get_serial_data(serial);
 	d_details = s_priv->device_details;
 
-		/* Setup values for the various callback routines */
+	/* Setup values for the various callback routines */
 	cback = &keyspan_callbacks[d_details->msg_format];
 
-		/* Allocate and set up urbs for each one that is in use, 
-		   starting with instat endpoints */
+	/* Allocate and set up urbs for each one that is in use,
+	   starting with instat endpoints */
 	s_priv->instat_urb = keyspan_setup_urb
 		(serial, d_details->instat_endpoint, USB_DIR_IN,
 		 serial, s_priv->instat_buf, INSTAT_BUFLEN,
@@ -1607,8 +1601,8 @@
 		 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
 		 cback->glocont_callback);
 
-		/* Setup endpoints for each port specific thing */
-	for (i = 0; i < d_details->num_ports; i ++) {
+	/* Setup endpoints for each port specific thing */
+	for (i = 0; i < d_details->num_ports; i++) {
 		port = serial->port[i];
 		p_priv = usb_get_serial_port_data(port);
 
@@ -1644,8 +1638,7 @@
 			(serial, d_details->outcont_endpoints[i], USB_DIR_OUT,
 			 port, p_priv->outcont_buffer, 64,
 			 cback->outcont_callback);
-	}	
-
+	}
 }
 
 /* usa19 function doesn't require prescaler */
@@ -1653,46 +1646,39 @@
 				   u8 *rate_low, u8 *prescaler, int portnum)
 {
 	u32 	b16,	/* baud rate times 16 (actual rate used internally) */
-		div,	/* divisor */	
+		div,	/* divisor */
 		cnt;	/* inverse of divisor (programmed into 8051) */
-		
-	dbg ("%s - %d.", __func__, baud_rate);
 
-		/* prevent divide by zero...  */
-	if( (b16 = (baud_rate * 16L)) == 0) {
-		return (KEYSPAN_INVALID_BAUD_RATE);
-	}
+	dbg("%s - %d.", __func__, baud_rate);
 
-		/* Any "standard" rate over 57k6 is marginal on the USA-19
-		   as we run out of divisor resolution. */
-	if (baud_rate > 57600) {
-		return (KEYSPAN_INVALID_BAUD_RATE);
-	}
+	/* prevent divide by zero...  */
+	b16 = baud_rate * 16L;
+	if (b16 == 0)
+		return KEYSPAN_INVALID_BAUD_RATE;
+	/* Any "standard" rate over 57k6 is marginal on the USA-19
+	   as we run out of divisor resolution. */
+	if (baud_rate > 57600)
+		return KEYSPAN_INVALID_BAUD_RATE;
 
-		/* calculate the divisor and the counter (its inverse) */
-	if( (div = (baudclk / b16)) == 0) {
-		return (KEYSPAN_INVALID_BAUD_RATE);
-	}
-	else {
+	/* calculate the divisor and the counter (its inverse) */
+	div = baudclk / b16;
+	if (div == 0)
+		return KEYSPAN_INVALID_BAUD_RATE;
+	else
 		cnt = 0 - div;
-	}
 
-	if(div > 0xffff) {
-		return (KEYSPAN_INVALID_BAUD_RATE);
-	}
+	if (div > 0xffff)
+		return KEYSPAN_INVALID_BAUD_RATE;
 
-		/* return the counter values if non-null */
-	if (rate_low) {
+	/* return the counter values if non-null */
+	if (rate_low)
 		*rate_low = (u8) (cnt & 0xff);
-	}
-	if (rate_hi) {
+	if (rate_hi)
 		*rate_hi = (u8) ((cnt >> 8) & 0xff);
-	}
-	if (rate_low && rate_hi) {
-		dbg ("%s - %d %02x %02x.", __func__, baud_rate, *rate_hi, *rate_low);
-	}
-	
-	return (KEYSPAN_BAUD_RATE_OK);
+	if (rate_low && rate_hi)
+		dbg("%s - %d %02x %02x.",
+				__func__, baud_rate, *rate_hi, *rate_low);
+	return KEYSPAN_BAUD_RATE_OK;
 }
 
 /* usa19hs function doesn't require prescaler */
@@ -1700,34 +1686,35 @@
 				   u8 *rate_low, u8 *prescaler, int portnum)
 {
 	u32 	b16,	/* baud rate times 16 (actual rate used internally) */
-			div;	/* divisor */	
-		
-	dbg ("%s - %d.", __func__, baud_rate);
+			div;	/* divisor */
 
-		/* prevent divide by zero...  */
-	if( (b16 = (baud_rate * 16L)) == 0) 
-		return (KEYSPAN_INVALID_BAUD_RATE);
-	
+	dbg("%s - %d.", __func__, baud_rate);
 
+	/* prevent divide by zero...  */
+	b16 = baud_rate * 16L;
+	if (b16 == 0)
+		return KEYSPAN_INVALID_BAUD_RATE;
 
-		/* calculate the divisor */
-	if( (div = (baudclk / b16)) == 0) 
-		return (KEYSPAN_INVALID_BAUD_RATE);
+	/* calculate the divisor */
+	div = baudclk / b16;
+	if (div == 0)
+		return KEYSPAN_INVALID_BAUD_RATE;
 
-	if(div > 0xffff) 
-		return (KEYSPAN_INVALID_BAUD_RATE);
+	if (div > 0xffff)
+		return KEYSPAN_INVALID_BAUD_RATE;
 
-		/* return the counter values if non-null */
-	if (rate_low) 
+	/* return the counter values if non-null */
+	if (rate_low)
 		*rate_low = (u8) (div & 0xff);
-	
-	if (rate_hi) 
+
+	if (rate_hi)
 		*rate_hi = (u8) ((div >> 8) & 0xff);
-	
-	if (rate_low && rate_hi) 
-		dbg ("%s - %d %02x %02x.", __func__, baud_rate, *rate_hi, *rate_low);
-	
-	return (KEYSPAN_BAUD_RATE_OK);
+
+	if (rate_low && rate_hi)
+		dbg("%s - %d %02x %02x.",
+			__func__, baud_rate, *rate_hi, *rate_low);
+
+	return KEYSPAN_BAUD_RATE_OK;
 }
 
 static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi,
@@ -1735,64 +1722,61 @@
 {
 	u32 	b16,	/* baud rate times 16 (actual rate used internally) */
 		clk,	/* clock with 13/8 prescaler */
-		div,	/* divisor using 13/8 prescaler */	
+		div,	/* divisor using 13/8 prescaler */
 		res,	/* resulting baud rate using 13/8 prescaler */
 		diff,	/* error using 13/8 prescaler */
 		smallest_diff;
 	u8	best_prescaler;
 	int	i;
 
-	dbg ("%s - %d.", __func__, baud_rate);
+	dbg("%s - %d.", __func__, baud_rate);
 
-		/* prevent divide by zero */
-	if( (b16 = baud_rate * 16L) == 0) {
-		return (KEYSPAN_INVALID_BAUD_RATE);
-	}
+	/* prevent divide by zero */
+	b16 = baud_rate * 16L;
+	if (b16 == 0)
+		return KEYSPAN_INVALID_BAUD_RATE;
 
-		/* Calculate prescaler by trying them all and looking
-		   for best fit */
-		
-		/* start with largest possible difference */
+	/* Calculate prescaler by trying them all and looking
+	   for best fit */
+
+	/* start with largest possible difference */
 	smallest_diff = 0xffffffff;
 
 		/* 0 is an invalid prescaler, used as a flag */
 	best_prescaler = 0;
 
-	for(i = 8; i <= 0xff; ++i) {
+	for (i = 8; i <= 0xff; ++i) {
 		clk = (baudclk * 8) / (u32) i;
-		
-		if( (div = clk / b16) == 0) {
+
+		div = clk / b16;
+		if (div == 0)
 			continue;
-		}
 
 		res = clk / div;
-		diff= (res > b16) ? (res-b16) : (b16-res);
+		diff = (res > b16) ? (res-b16) : (b16-res);
 
-		if(diff < smallest_diff) {
+		if (diff < smallest_diff) {
 			best_prescaler = i;
 			smallest_diff = diff;
 		}
 	}
 
-	if(best_prescaler == 0) {
-		return (KEYSPAN_INVALID_BAUD_RATE);
-	}
+	if (best_prescaler == 0)
+		return KEYSPAN_INVALID_BAUD_RATE;
 
 	clk = (baudclk * 8) / (u32) best_prescaler;
 	div = clk / b16;
 
-		/* return the divisor and prescaler if non-null */
-	if (rate_low) {
+	/* return the divisor and prescaler if non-null */
+	if (rate_low)
 		*rate_low = (u8) (div & 0xff);
-	}
-	if (rate_hi) {
+	if (rate_hi)
 		*rate_hi = (u8) ((div >> 8) & 0xff);
-	}
 	if (prescaler) {
 		*prescaler = best_prescaler;
 		/*  dbg("%s - %d %d", __func__, *prescaler, div); */
 	}
-	return (KEYSPAN_BAUD_RATE_OK);
+	return KEYSPAN_BAUD_RATE_OK;
 }
 
 	/* USA-28 supports different maximum baud rates on each port */
@@ -1800,57 +1784,51 @@
 				    u8 *rate_low, u8 *prescaler, int portnum)
 {
 	u32 	b16,	/* baud rate times 16 (actual rate used internally) */
-		div,	/* divisor */	
+		div,	/* divisor */
 		cnt;	/* inverse of divisor (programmed into 8051) */
 
-	dbg ("%s - %d.", __func__, baud_rate);
+	dbg("%s - %d.", __func__, baud_rate);
 
 		/* prevent divide by zero */
-	if ((b16 = baud_rate * 16L) == 0)
-		return (KEYSPAN_INVALID_BAUD_RATE);
+	b16 = baud_rate * 16L;
+	if (b16 == 0)
+		return KEYSPAN_INVALID_BAUD_RATE;
 
-		/* calculate the divisor and the counter (its inverse) */
-	if ((div = (KEYSPAN_USA28_BAUDCLK / b16)) == 0) {
-		return (KEYSPAN_INVALID_BAUD_RATE);
-	}
-	else {
+	/* calculate the divisor and the counter (its inverse) */
+	div = KEYSPAN_USA28_BAUDCLK / b16;
+	if (div == 0)
+		return KEYSPAN_INVALID_BAUD_RATE;
+	else
 		cnt = 0 - div;
-	}
 
-		/* check for out of range, based on portnum, 
-		   and return result */
-	if(portnum == 0) {
-		if(div > 0xffff)
-			return (KEYSPAN_INVALID_BAUD_RATE);
-	}
-	else {
-		if(portnum == 1) {
-			if(div > 0xff) {
-				return (KEYSPAN_INVALID_BAUD_RATE);
-			}
-		}
-		else {
-			return (KEYSPAN_INVALID_BAUD_RATE);
-		}
+	/* check for out of range, based on portnum,
+	   and return result */
+	if (portnum == 0) {
+		if (div > 0xffff)
+			return KEYSPAN_INVALID_BAUD_RATE;
+	} else {
+		if (portnum == 1) {
+			if (div > 0xff)
+				return KEYSPAN_INVALID_BAUD_RATE;
+		} else
+			return KEYSPAN_INVALID_BAUD_RATE;
 	}
 
 		/* return the counter values if not NULL
 		   (port 1 will ignore retHi) */
-	if (rate_low) {
+	if (rate_low)
 		*rate_low = (u8) (cnt & 0xff);
-	}
-	if (rate_hi) {
+	if (rate_hi)
 		*rate_hi = (u8) ((cnt >> 8) & 0xff);
-	}
-	dbg ("%s - %d OK.", __func__, baud_rate);
-	return (KEYSPAN_BAUD_RATE_OK);
+	dbg("%s - %d OK.", __func__, baud_rate);
+	return KEYSPAN_BAUD_RATE_OK;
 }
 
 static int keyspan_usa26_send_setup(struct usb_serial *serial,
 				    struct usb_serial_port *port,
 				    int reset_port)
 {
-	struct keyspan_usa26_portControlMessage	msg;		
+	struct keyspan_usa26_portControlMessage	msg;
 	struct keyspan_serial_private 		*s_priv;
 	struct keyspan_port_private 		*p_priv;
 	const struct keyspan_device_details	*d_details;
@@ -1858,7 +1836,7 @@
 	struct urb				*this_urb;
 	int 					device_port, err;
 
-	dbg ("%s reset=%d", __func__, reset_port);
+	dbg("%s reset=%d", __func__, reset_port);
 
 	s_priv = usb_get_serial_data(serial);
 	p_priv = usb_get_serial_port_data(port);
@@ -1881,22 +1859,22 @@
 	if ((reset_port + 1) > p_priv->resend_cont)
 		p_priv->resend_cont = reset_port + 1;
 	if (this_urb->status == -EINPROGRESS) {
-		/*  dbg ("%s - already writing", __func__); */
+		/*  dbg("%s - already writing", __func__); */
 		mdelay(5);
-		return(-1);
+		return -1;
 	}
 
-	memset(&msg, 0, sizeof (struct keyspan_usa26_portControlMessage));
-	
-		/* Only set baud rate if it's changed */	
+	memset(&msg, 0, sizeof(struct keyspan_usa26_portControlMessage));
+
+	/* Only set baud rate if it's changed */
 	if (p_priv->old_baud != p_priv->baud) {
 		p_priv->old_baud = p_priv->baud;
 		msg.setClocking = 0xff;
 		if (d_details->calculate_baud_rate
 		    (p_priv->baud, d_details->baudclk, &msg.baudHi,
-		     &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
-			dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
-			    p_priv->baud);
+		     &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
+			dbg("%s - Invalid baud rate %d requested, using 9600.",
+						__func__, p_priv->baud);
 			msg.baudLo = 0;
 			msg.baudHi = 125;	/* Values for 9600 baud */
 			msg.prescaler = 10;
@@ -1922,7 +1900,7 @@
 	if (p_priv->cflag & PARENB) {
 		/* note USA_PARITY_NONE == 0 */
 		msg.lcr |= (p_priv->cflag & PARODD)?
-			USA_PARITY_ODD: USA_PARITY_EVEN;
+			USA_PARITY_ODD : USA_PARITY_EVEN;
 	}
 	msg.setLcr = 0xff;
 
@@ -1963,7 +1941,7 @@
 
 	/* Sending intermediate configs */
 	else {
-		msg._txOn = (! p_priv->break_on);
+		msg._txOn = (!p_priv->break_on);
 		msg._txOff = 0;
 		msg.txFlush = 0;
 		msg.txBreak = (p_priv->break_on);
@@ -1975,23 +1953,23 @@
 		msg.resetDataToggle = 0x0;
 	}
 
-		/* Do handshaking outputs */	
+	/* Do handshaking outputs */
 	msg.setTxTriState_setRts = 0xff;
 	msg.txTriState_rts = p_priv->rts_state;
 
 	msg.setHskoa_setDtr = 0xff;
 	msg.hskoa_dtr = p_priv->dtr_state;
-		
+
 	p_priv->resend_cont = 0;
-	memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
-	
+	memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
+
 	/* send the data out the device on control endpoint */
 	this_urb->transfer_buffer_length = sizeof(msg);
 
 	this_urb->dev = serial->dev;
-	if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
+	err = usb_submit_urb(this_urb, GFP_ATOMIC);
+	if (err != 0)
 		dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
-	}
 #if 0
 	else {
 		dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__
@@ -2007,14 +1985,14 @@
 				    struct usb_serial_port *port,
 				    int reset_port)
 {
-	struct keyspan_usa28_portControlMessage	msg;		
+	struct keyspan_usa28_portControlMessage	msg;
 	struct keyspan_serial_private	 	*s_priv;
 	struct keyspan_port_private 		*p_priv;
 	const struct keyspan_device_details	*d_details;
 	struct urb				*this_urb;
 	int 					device_port, err;
 
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 
 	s_priv = usb_get_serial_data(serial);
 	p_priv = usb_get_serial_port_data(port);
@@ -2022,7 +2000,8 @@
 	device_port = port->number - port->serial->minor;
 
 	/* only do something if we have a bulk out endpoint */
-	if ((this_urb = p_priv->outcont_urb) == NULL) {
+	this_urb = p_priv->outcont_urb;
+	if (this_urb == NULL) {
 		dbg("%s - oops no urb.", __func__);
 		return -1;
 	}
@@ -2032,17 +2011,18 @@
 	if ((reset_port + 1) > p_priv->resend_cont)
 		p_priv->resend_cont = reset_port + 1;
 	if (this_urb->status == -EINPROGRESS) {
-		dbg ("%s already writing", __func__);
+		dbg("%s already writing", __func__);
 		mdelay(5);
-		return(-1);
+		return -1;
 	}
 
-	memset(&msg, 0, sizeof (struct keyspan_usa28_portControlMessage));
+	memset(&msg, 0, sizeof(struct keyspan_usa28_portControlMessage));
 
 	msg.setBaudRate = 1;
 	if (d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk,
-		&msg.baudHi, &msg.baudLo, NULL, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
-		dbg("%s - Invalid baud rate requested %d.", __func__, p_priv->baud);
+		&msg.baudHi, &msg.baudLo, NULL, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
+		dbg("%s - Invalid baud rate requested %d.",
+						__func__, p_priv->baud);
 		msg.baudLo = 0xff;
 		msg.baudHi = 0xb2;	/* Values for 9600 baud */
 	}
@@ -2053,7 +2033,7 @@
 	msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
 	msg.xonFlowControl = 0;
 
-	/* Do handshaking outputs, DTR is inverted relative to RTS */	
+	/* Do handshaking outputs, DTR is inverted relative to RTS */
 	msg.rts = p_priv->rts_state;
 	msg.dtr = p_priv->dtr_state;
 
@@ -2095,7 +2075,7 @@
 	}
 	/* Sending intermediate configs */
 	else {
-		msg._txOn = (! p_priv->break_on);
+		msg._txOn = (!p_priv->break_on);
 		msg._txOff = 0;
 		msg.txFlush = 0;
 		msg.txForceXoff = 0;
@@ -2109,15 +2089,15 @@
 	}
 
 	p_priv->resend_cont = 0;
-	memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
+	memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
 
 	/* send the data out the device on control endpoint */
 	this_urb->transfer_buffer_length = sizeof(msg);
 
 	this_urb->dev = serial->dev;
-	if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
+	err = usb_submit_urb(this_urb, GFP_ATOMIC);
+	if (err != 0)
 		dbg("%s - usb_submit_urb(setup) failed", __func__);
-	}
 #if 0
 	else {
 		dbg("%s - usb_submit_urb(setup) OK %d bytes", __func__,
@@ -2140,7 +2120,7 @@
 	struct urb				*this_urb;
 	int 					err, device_port;
 
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 
 	s_priv = usb_get_serial_data(serial);
 	p_priv = usb_get_serial_port_data(port);
@@ -2151,7 +2131,9 @@
 	/* Work out which port within the device is being setup */
 	device_port = port->number - port->serial->minor;
 
-	dbg("%s - endpoint %d port %d (%d)",__func__, usb_pipeendpoint(this_urb->pipe), port->number, device_port);
+	dbg("%s - endpoint %d port %d (%d)",
+			__func__, usb_pipeendpoint(this_urb->pipe),
+			port->number, device_port);
 
 		/* Make sure we have an urb then send the message */
 	if (this_urb == NULL) {
@@ -2165,30 +2147,30 @@
 		p_priv->resend_cont = reset_port + 1;
 
 	if (this_urb->status == -EINPROGRESS) {
-		/*  dbg ("%s - already writing", __func__); */
+		/*  dbg("%s - already writing", __func__); */
 		mdelay(5);
-		return(-1);
+		return -1;
 	}
 
-	memset(&msg, 0, sizeof (struct keyspan_usa49_portControlMessage));
+	memset(&msg, 0, sizeof(struct keyspan_usa49_portControlMessage));
 
 	/*msg.portNumber = port->number;*/
 	msg.portNumber = device_port;
-	
-		/* Only set baud rate if it's changed */	
+
+	/* Only set baud rate if it's changed */
 	if (p_priv->old_baud != p_priv->baud) {
 		p_priv->old_baud = p_priv->baud;
 		msg.setClocking = 0xff;
 		if (d_details->calculate_baud_rate
 		    (p_priv->baud, d_details->baudclk, &msg.baudHi,
-		     &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
-			dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
-			    p_priv->baud);
+		     &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
+			dbg("%s - Invalid baud rate %d requested, using 9600.",
+						__func__, p_priv->baud);
 			msg.baudLo = 0;
 			msg.baudHi = 125;	/* Values for 9600 baud */
 			msg.prescaler = 10;
 		}
-		//msg.setPrescaler = 0xff;
+		/* msg.setPrescaler = 0xff; */
 	}
 
 	msg.lcr = (p_priv->cflag & CSTOPB)? STOPBITS_678_2: STOPBITS_5678_1;
@@ -2209,19 +2191,19 @@
 	if (p_priv->cflag & PARENB) {
 		/* note USA_PARITY_NONE == 0 */
 		msg.lcr |= (p_priv->cflag & PARODD)?
-			USA_PARITY_ODD: USA_PARITY_EVEN;
+			USA_PARITY_ODD : USA_PARITY_EVEN;
 	}
 	msg.setLcr = 0xff;
 
 	msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
 	msg.xonFlowControl = 0;
 	msg.setFlowControl = 0xff;
-	
+
 	msg.forwardingLength = 16;
 	msg.xonChar = 17;
 	msg.xoffChar = 19;
 
-	/* Opening port */ 
+	/* Opening port */
 	if (reset_port == 1) {
 		msg._txOn = 1;
 		msg._txOff = 0;
@@ -2253,7 +2235,7 @@
 	}
 	/* Sending intermediate configs */
 	else {
-		msg._txOn = (! p_priv->break_on);
+		msg._txOn = (!p_priv->break_on);
 		msg._txOff = 0;
 		msg.txFlush = 0;
 		msg.txBreak = (p_priv->break_on);
@@ -2267,16 +2249,17 @@
 		msg.disablePort = 0;
 	}
 
-		/* Do handshaking outputs */	
+	/* Do handshaking outputs */
 	msg.setRts = 0xff;
 	msg.rts = p_priv->rts_state;
 
 	msg.setDtr = 0xff;
 	msg.dtr = p_priv->dtr_state;
-		
+
 	p_priv->resend_cont = 0;
 
-	/* if the device is a 49wg, we send control message on usb control EP 0 */
+	/* if the device is a 49wg, we send control message on usb
+	   control EP 0 */
 
 	if (d_details->product_id == keyspan_usa49wg_product_id) {
 		dr = (void *)(s_priv->ctrl_buf);
@@ -2286,23 +2269,24 @@
 		dr->wIndex = 0;
 		dr->wLength = cpu_to_le16(sizeof(msg));
 
-		memcpy (s_priv->glocont_buf, &msg, sizeof(msg));
+		memcpy(s_priv->glocont_buf, &msg, sizeof(msg));
 
-		usb_fill_control_urb(this_urb, serial->dev, usb_sndctrlpipe(serial->dev, 0),
-			     (unsigned char *)dr, s_priv->glocont_buf, sizeof(msg),
-			     usa49_glocont_callback, serial);
+		usb_fill_control_urb(this_urb, serial->dev,
+				usb_sndctrlpipe(serial->dev, 0),
+				(unsigned char *)dr, s_priv->glocont_buf,
+				sizeof(msg), usa49_glocont_callback, serial);
 
 	} else {
 		memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
-	
+
 		/* send the data out the device on control endpoint */
 		this_urb->transfer_buffer_length = sizeof(msg);
 
 		this_urb->dev = serial->dev;
 	}
-	if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
+	err = usb_submit_urb(this_urb, GFP_ATOMIC);
+	if (err != 0)
 		dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
-	}
 #if 0
 	else {
 		dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__,
@@ -2318,7 +2302,7 @@
 				    struct usb_serial_port *port,
 				    int reset_port)
 {
-	struct keyspan_usa90_portControlMessage	msg;		
+	struct keyspan_usa90_portControlMessage	msg;
 	struct keyspan_serial_private 		*s_priv;
 	struct keyspan_port_private 		*p_priv;
 	const struct keyspan_device_details	*d_details;
@@ -2326,14 +2310,15 @@
 	int 					err;
 	u8						prescaler;
 
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 
 	s_priv = usb_get_serial_data(serial);
 	p_priv = usb_get_serial_port_data(port);
 	d_details = s_priv->device_details;
 
 	/* only do something if we have a bulk out endpoint */
-	if ((this_urb = p_priv->outcont_urb) == NULL) {
+	this_urb = p_priv->outcont_urb;
+	if (this_urb == NULL) {
 		dbg("%s - oops no urb.", __func__);
 		return -1;
 	}
@@ -2343,24 +2328,24 @@
 	if ((reset_port + 1) > p_priv->resend_cont)
 		p_priv->resend_cont = reset_port + 1;
 	if (this_urb->status == -EINPROGRESS) {
-		dbg ("%s already writing", __func__);
+		dbg("%s already writing", __func__);
 		mdelay(5);
-		return(-1);
+		return -1;
 	}
 
-	memset(&msg, 0, sizeof (struct keyspan_usa90_portControlMessage));
+	memset(&msg, 0, sizeof(struct keyspan_usa90_portControlMessage));
 
-	/* Only set baud rate if it's changed */	
+	/* Only set baud rate if it's changed */
 	if (p_priv->old_baud != p_priv->baud) {
 		p_priv->old_baud = p_priv->baud;
 		msg.setClocking = 0x01;
 		if (d_details->calculate_baud_rate
 		    (p_priv->baud, d_details->baudclk, &msg.baudHi,
-		     &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE ) {
-			dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
-			    p_priv->baud);
+		     &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) {
+			dbg("%s - Invalid baud rate %d requested, using 9600.",
+						__func__, p_priv->baud);
 			p_priv->baud = 9600;
-			d_details->calculate_baud_rate (p_priv->baud, d_details->baudclk, 
+			d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk,
 				&msg.baudHi, &msg.baudLo, &prescaler, 0);
 		}
 		msg.setRxMode = 1;
@@ -2368,13 +2353,10 @@
 	}
 
 	/* modes must always be correctly specified */
-	if (p_priv->baud > 57600)
-	{
+	if (p_priv->baud > 57600) {
 		msg.rxMode = RXMODE_DMA;
 		msg.txMode = TXMODE_DMA;
-	}
-	else
-	{
+	} else {
 		msg.rxMode = RXMODE_BYHAND;
 		msg.txMode = TXMODE_BYHAND;
 	}
@@ -2397,7 +2379,7 @@
 	if (p_priv->cflag & PARENB) {
 		/* note USA_PARITY_NONE == 0 */
 		msg.lcr |= (p_priv->cflag & PARODD)?
-			USA_PARITY_ODD: USA_PARITY_EVEN;
+			USA_PARITY_ODD : USA_PARITY_EVEN;
 	}
 	if (p_priv->old_cflag != p_priv->cflag) {
 		p_priv->old_cflag = p_priv->cflag;
@@ -2408,47 +2390,46 @@
 		msg.txFlowControl = TXFLOW_CTS;
 	msg.setTxFlowControl = 0x01;
 	msg.setRxFlowControl = 0x01;
-	
+
 	msg.rxForwardingLength = 16;
-	msg.rxForwardingTimeout = 16;	
+	msg.rxForwardingTimeout = 16;
 	msg.txAckSetting = 0;
 	msg.xonChar = 17;
 	msg.xoffChar = 19;
 
-	/* Opening port */ 
+	/* Opening port */
 	if (reset_port == 1) {
 		msg.portEnabled = 1;
 		msg.rxFlush = 1;
 		msg.txBreak = (p_priv->break_on);
 	}
 	/* Closing port */
-	else if (reset_port == 2) {
+	else if (reset_port == 2)
 		msg.portEnabled = 0;
-	}
 	/* Sending intermediate configs */
 	else {
-		if (port->open_count)
+		if (port->port.count)
 			msg.portEnabled = 1;
 		msg.txBreak = (p_priv->break_on);
 	}
 
-	/* Do handshaking outputs */	
+	/* Do handshaking outputs */
 	msg.setRts = 0x01;
 	msg.rts = p_priv->rts_state;
 
 	msg.setDtr = 0x01;
 	msg.dtr = p_priv->dtr_state;
-		
+
 	p_priv->resend_cont = 0;
-	memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
-	
+	memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
+
 	/* send the data out the device on control endpoint */
 	this_urb->transfer_buffer_length = sizeof(msg);
 
 	this_urb->dev = serial->dev;
-	if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
+	err = usb_submit_urb(this_urb, GFP_ATOMIC);
+	if (err != 0)
 		dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
-	}
 	return 0;
 }
 
@@ -2463,7 +2444,7 @@
 	struct urb				*this_urb;
 	int 					err, device_port;
 
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 
 	s_priv = usb_get_serial_data(serial);
 	p_priv = usb_get_serial_port_data(port);
@@ -2486,9 +2467,9 @@
 	if ((reset_port + 1) > p_priv->resend_cont)
 		p_priv->resend_cont = reset_port + 1;
 	if (this_urb->status == -EINPROGRESS) {
-		/*  dbg ("%s - already writing", __func__); */
+		/*  dbg("%s - already writing", __func__); */
 		mdelay(5);
-		return(-1);
+		return -1;
 	}
 
 	memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
@@ -2501,9 +2482,9 @@
 		msg.setClocking = 0xff;
 		if (d_details->calculate_baud_rate
 		    (p_priv->baud, d_details->baudclk, &msg.baudHi,
-		     &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
-			dbg("%s - Invalid baud rate %d requested, using 9600.", __func__,
-			    p_priv->baud);
+		     &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) {
+			dbg("%s - Invalid baud rate %d requested, using 9600.",
+						__func__, p_priv->baud);
 			msg.baudLo = 0;
 			msg.baudHi = 125;	/* Values for 9600 baud */
 			msg.prescaler = 10;
@@ -2529,7 +2510,7 @@
 	if (p_priv->cflag & PARENB) {
 		/* note USA_PARITY_NONE == 0 */
 		msg.lcr |= (p_priv->cflag & PARODD)?
-			USA_PARITY_ODD: USA_PARITY_EVEN;
+					USA_PARITY_ODD : USA_PARITY_EVEN;
 	}
 	msg.setLcr = 0xff;
 
@@ -2566,7 +2547,7 @@
 		msg.resetDataToggle = 0;
 	} else {
 		/* Sending intermediate configs */
-		msg._txOn = (! p_priv->break_on);
+		msg._txOn = (!p_priv->break_on);
 		msg._txOff = 0;
 		msg.txFlush = 0;
 		msg.txBreak = (p_priv->break_on);
@@ -2606,7 +2587,7 @@
 	struct keyspan_serial_private *s_priv;
 	const struct keyspan_device_details *d_details;
 
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 
 	s_priv = usb_get_serial_data(serial);
 	d_details = s_priv->device_details;
@@ -2633,7 +2614,7 @@
 
 /* Gets called by the "real" driver (ie once firmware is loaded
    and renumeration has taken place. */
-static int keyspan_startup (struct usb_serial *serial)
+static int keyspan_startup(struct usb_serial *serial)
 {
 	int				i, err;
 	struct usb_serial_port		*port;
@@ -2644,17 +2625,20 @@
 	dbg("%s", __func__);
 
 	for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
-		if (d_details->product_id == le16_to_cpu(serial->dev->descriptor.idProduct))
+		if (d_details->product_id ==
+				le16_to_cpu(serial->dev->descriptor.idProduct))
 			break;
 	if (d_details == NULL) {
-		dev_err(&serial->dev->dev, "%s - unknown product id %x\n", __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
+		dev_err(&serial->dev->dev, "%s - unknown product id %x\n",
+		    __func__, le16_to_cpu(serial->dev->descriptor.idProduct));
 		return 1;
 	}
 
 	/* Setup private data for serial driver */
 	s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
 	if (!s_priv) {
-		dbg("%s - kmalloc for keyspan_serial_private failed.", __func__);
+		dbg("%s - kmalloc for keyspan_serial_private failed.",
+								__func__);
 		return -ENOMEM;
 	}
 
@@ -2664,10 +2648,11 @@
 	/* Now setup per port private data */
 	for (i = 0; i < serial->num_ports; i++) {
 		port = serial->port[i];
-		p_priv = kzalloc(sizeof(struct keyspan_port_private), GFP_KERNEL);
+		p_priv = kzalloc(sizeof(struct keyspan_port_private),
+								GFP_KERNEL);
 		if (!p_priv) {
 			dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __func__, i);
-			return (1);
+			return 1;
 		}
 		p_priv->device_details = d_details;
 		usb_set_serial_port_data(port, p_priv);
@@ -2689,11 +2674,11 @@
 			dbg("%s - submit indat urb failed %d", __func__,
 				err);
 	}
-			
+
 	return 0;
 }
 
-static void keyspan_shutdown (struct usb_serial *serial)
+static void keyspan_shutdown(struct usb_serial *serial)
 {
 	int				i, j;
 	struct usb_serial_port		*port;
@@ -2745,8 +2730,8 @@
 	}
 }
 
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 MODULE_FIRMWARE("keyspan/usa28.fw");
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index b52fb65..38b4582 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -35,17 +35,18 @@
 
 
 /* Function prototypes for Keyspan serial converter */
-static int  keyspan_open		(struct usb_serial_port *port,
+static int  keyspan_open		(struct tty_struct *tty,
+					 struct usb_serial_port *port,
 					 struct file *filp);
-static void keyspan_close		(struct usb_serial_port *port,
+static void keyspan_close		(struct tty_struct *tty,
+					 struct usb_serial_port *port,
 					 struct file *filp);
 static int  keyspan_startup		(struct usb_serial *serial);
 static void keyspan_shutdown		(struct usb_serial *serial);
-static void keyspan_rx_throttle		(struct usb_serial_port *port);
-static void keyspan_rx_unthrottle	(struct usb_serial_port *port);
-static int  keyspan_write_room		(struct usb_serial_port *port);
+static int  keyspan_write_room		(struct tty_struct *tty);
 
-static int  keyspan_write		(struct usb_serial_port *port,
+static int  keyspan_write		(struct tty_struct *tty,
+					 struct usb_serial_port *port,
 					 const unsigned char *buf,
 					 int count);
 
@@ -53,18 +54,14 @@
 					 int reset_port);
 
 
-static int  keyspan_chars_in_buffer 	(struct usb_serial_port *port);
-static int  keyspan_ioctl		(struct usb_serial_port *port,
-					 struct file *file,
-					 unsigned int cmd,
-					 unsigned long arg);
-static void keyspan_set_termios		(struct usb_serial_port *port,
+static void keyspan_set_termios		(struct tty_struct *tty,
+					 struct usb_serial_port *port,
 					 struct ktermios *old);
-static void keyspan_break_ctl		(struct usb_serial_port *port,
+static void keyspan_break_ctl		(struct tty_struct *tty,
 					 int break_state);
-static int  keyspan_tiocmget		(struct usb_serial_port *port,
+static int  keyspan_tiocmget		(struct tty_struct *tty,
 					 struct file *file);
-static int  keyspan_tiocmset		(struct usb_serial_port *port,
+static int  keyspan_tiocmset		(struct tty_struct *tty,
 					 struct file *file, unsigned int set,
 					 unsigned int clear);
 static int  keyspan_fake_startup	(struct usb_serial *serial);
@@ -138,7 +135,8 @@
 
 /* Product IDs post-renumeration.  Note that the 28x and 28xb
    have the same id's post-renumeration but behave identically
-   so it's not an issue. */
+   so it's not an issue. As such, the 28xb is not listed in any
+   of the device tables. */
 #define	keyspan_usa18x_product_id		0x0112
 #define	keyspan_usa19_product_id		0x0107
 #define	keyspan_usa19qi_product_id		0x010c
@@ -482,7 +480,6 @@
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) },
-	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) },
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xg_product_id) },
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id)},
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)},
@@ -532,7 +529,6 @@
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) },
-	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) },
 	{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xg_product_id) },
 	{ } /* Terminating entry */
 };
@@ -568,10 +564,6 @@
 	.close			= keyspan_close,
 	.write			= keyspan_write,
 	.write_room		= keyspan_write_room,
-	.chars_in_buffer	= keyspan_chars_in_buffer,
-	.throttle		= keyspan_rx_throttle,
-	.unthrottle		= keyspan_rx_unthrottle,
-	.ioctl			= keyspan_ioctl,
 	.set_termios		= keyspan_set_termios,
 	.break_ctl		= keyspan_break_ctl,
 	.tiocmget		= keyspan_tiocmget,
@@ -592,10 +584,6 @@
 	.close			= keyspan_close,
 	.write			= keyspan_write,
 	.write_room		= keyspan_write_room,
-	.chars_in_buffer	= keyspan_chars_in_buffer,
-	.throttle		= keyspan_rx_throttle,
-	.unthrottle		= keyspan_rx_unthrottle,
-	.ioctl			= keyspan_ioctl,
 	.set_termios		= keyspan_set_termios,
 	.break_ctl		= keyspan_break_ctl,
 	.tiocmget		= keyspan_tiocmget,
@@ -616,10 +604,6 @@
 	.close			= keyspan_close,
 	.write			= keyspan_write,
 	.write_room		= keyspan_write_room,
-	.chars_in_buffer	= keyspan_chars_in_buffer,
-	.throttle		= keyspan_rx_throttle,
-	.unthrottle		= keyspan_rx_unthrottle,
-	.ioctl			= keyspan_ioctl,
 	.set_termios		= keyspan_set_termios,
 	.break_ctl		= keyspan_break_ctl,
 	.tiocmget		= keyspan_tiocmget,
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 644a1ea..040040a 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -10,8 +10,9 @@
  *	the Free Software Foundation; either version 2 of the License, or
  *	(at your option) any later version.
  *
- * See Documentation/usb/usb-serial.txt for more information on using this driver
- * 
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
+ *
  * (09/07/2001) gkh
  *	cleaned up the Xircom support.  Added ids for Entregra device which is
  *	the same as the Xircom device.  Enabled the code to be compiled for
@@ -21,23 +22,24 @@
  *	support for Xircom PGSDB9
  *
  * (05/31/2001) gkh
- *	switched from using spinlock to a semaphore, which fixes lots of problems.
+ *	switched from using spinlock to a semaphore, which fixes lots of
+ *	problems.
  *
  * (04/08/2001) gb
  *	Identify version on module load.
- * 
+ *
  * (11/01/2000) Adam J. Richter
  *	usb_device_id table support
- * 
+ *
  * (10/05/2000) gkh
  *	Fixed bug with urb->dev not being set properly, now that the usb
  *	core needs it.
- * 
+ *
  * (08/28/2000) gkh
  *	Added locks for SMP safeness.
- *	Fixed MOD_INC and MOD_DEC logic and the ability to open a port more 
+ *	Fixed MOD_INC and MOD_DEC logic and the ability to open a port more
  *	than once.
- * 
+ *
  * (07/20/2000) borchers
  *	- keyspan_pda_write no longer sleeps if it is called on interrupt time;
  *	  PPP and the line discipline with stty echo on can call write on
@@ -55,14 +57,14 @@
  *	  than done directly from the callback to avoid the race in write_chan
  *	- keyspan_pda_chars_in_buffer also indicates its buffer is full if the
  *	  urb status is -EINPROGRESS, meaning it cannot write at the moment
- *      
+ *
  * (07/19/2000) gkh
  *	Added module_init and module_exit functions to handle the fact that this
  *	driver is a loadable module now.
  *
  * (03/26/2000) gkh
  *	Split driver up into device specific pieces.
- * 
+ *
  */
 
 
@@ -78,7 +80,7 @@
 #include <linux/workqueue.h>
 #include <linux/firmware.h>
 #include <linux/ihex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
@@ -135,7 +137,7 @@
 	{ }						/* Terminating entry */
 };
 
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
 
 static struct usb_driver keyspan_pda_driver = {
 	.name =		"keyspan_pda",
@@ -159,9 +161,9 @@
 
 #ifdef XIRCOM
 static struct usb_device_id id_table_fake_xircom [] = {
-        { USB_DEVICE(XIRCOM_VENDOR_ID, XIRCOM_FAKE_ID) },
-        { USB_DEVICE(ENTREGRA_VENDOR_ID, ENTREGRA_FAKE_ID) },
-        { }                                             
+	{ USB_DEVICE(XIRCOM_VENDOR_ID, XIRCOM_FAKE_ID) },
+	{ USB_DEVICE(ENTREGRA_VENDOR_ID, ENTREGRA_FAKE_ID) },
+	{ }
 };
 #endif
 
@@ -171,7 +173,7 @@
 		container_of(work, struct keyspan_pda_private, wakeup_work);
 	struct usb_serial_port *port = priv->port;
 
-	tty_wakeup(port->tty);
+	tty_wakeup(port->port.tty);
 }
 
 static void keyspan_pda_request_unthrottle(struct work_struct *work)
@@ -184,7 +186,7 @@
 	dbg(" request_unthrottle");
 	/* ask the device to tell us when the tx buffer becomes
 	   sufficiently empty */
-	result = usb_control_msg(serial->dev, 
+	result = usb_control_msg(serial->dev,
 				 usb_sndctrlpipe(serial->dev, 0),
 				 7, /* request_unthrottle */
 				 USB_TYPE_VENDOR | USB_RECIP_INTERFACE
@@ -195,17 +197,16 @@
 				 0,
 				 2000);
 	if (result < 0)
-		dbg("%s - error %d from usb_control_msg", 
+		dbg("%s - error %d from usb_control_msg",
 		    __func__, result);
 }
 
 
-static void keyspan_pda_rx_interrupt (struct urb *urb)
+static void keyspan_pda_rx_interrupt(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
-       	struct tty_struct *tty = port->tty;
+	struct tty_struct *tty = port->port.tty;
 	unsigned char *data = urb->transfer_buffer;
-	int i;
 	int retval;
 	int status = urb->status;
 	struct keyspan_pda_private *priv;
@@ -228,14 +229,13 @@
 		goto exit;
 	}
 
- 	/* see if the message is data or a status interrupt */
+	/* see if the message is data or a status interrupt */
 	switch (data[0]) {
 	case 0:
 		/* rest of message is rx data */
 		if (urb->actual_length) {
-			for (i = 1; i < urb->actual_length ; ++i) {
-				tty_insert_flip_char(tty, data[i], 0);
-			}
+			tty_insert_flip_string(tty, data + 1,
+						urb->actual_length - 1);
 			tty_flip_buffer_push(tty);
 		}
 		break;
@@ -259,14 +259,14 @@
 	}
 
 exit:
-	retval = usb_submit_urb (urb, GFP_ATOMIC);
+	retval = usb_submit_urb(urb, GFP_ATOMIC);
 	if (retval)
-		err ("%s - usb_submit_urb failed with result %d",
+		err("%s - usb_submit_urb failed with result %d",
 		     __func__, retval);
 }
 
 
-static void keyspan_pda_rx_throttle (struct usb_serial_port *port)
+static void keyspan_pda_rx_throttle(struct tty_struct *tty)
 {
 	/* stop receiving characters. We just turn off the URB request, and
 	   let chars pile up in the device. If we're doing hardware
@@ -274,14 +274,15 @@
 	   fills up. If we're doing XON/XOFF, this would be a good time to
 	   send an XOFF, although it might make sense to foist that off
 	   upon the device too. */
-
+	struct usb_serial_port *port = tty->driver_data;
 	dbg("keyspan_pda_rx_throttle port %d", port->number);
 	usb_kill_urb(port->interrupt_in_urb);
 }
 
 
-static void keyspan_pda_rx_unthrottle (struct usb_serial_port *port)
+static void keyspan_pda_rx_unthrottle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	/* just restart the receive interrupt URB */
 	dbg("keyspan_pda_rx_unthrottle port %d", port->number);
 	port->interrupt_in_urb->dev = port->serial->dev;
@@ -291,32 +292,52 @@
 }
 
 
-static speed_t keyspan_pda_setbaud (struct usb_serial *serial, speed_t baud)
+static speed_t keyspan_pda_setbaud(struct usb_serial *serial, speed_t baud)
 {
 	int rc;
 	int bindex;
 
-	switch(baud) {
-		case 110: bindex = 0; break;
-		case 300: bindex = 1; break;
-		case 1200: bindex = 2; break;
-		case 2400: bindex = 3; break;
-		case 4800: bindex = 4; break;
-		case 9600: bindex = 5; break;
-		case 19200: bindex = 6; break;
-		case 38400: bindex = 7; break;
-		case 57600: bindex = 8; break;
-		case 115200: bindex = 9; break;
-		default:
-			bindex = 5;	/* Default to 9600 */
-			baud = 9600;
+	switch (baud) {
+	case 110:
+		bindex = 0;
+		break;
+	case 300:
+		bindex = 1;
+		break;
+	case 1200:
+		bindex = 2;
+		break;
+	case 2400:
+		bindex = 3;
+		break;
+	case 4800:
+		bindex = 4;
+		break;
+	case 9600:
+		bindex = 5;
+		break;
+	case 19200:
+		bindex = 6;
+		break;
+	case 38400:
+		bindex = 7;
+		break;
+	case 57600:
+		bindex = 8;
+		break;
+	case 115200:
+		bindex = 9;
+		break;
+	default:
+		bindex = 5;	/* Default to 9600 */
+		baud = 9600;
 	}
 
 	/* rather than figure out how to sleep while waiting for this
 	   to complete, I just use the "legacy" API. */
 	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
 			     0, /* set baud */
-			     USB_TYPE_VENDOR 
+			     USB_TYPE_VENDOR
 			     | USB_RECIP_INTERFACE
 			     | USB_DIR_OUT, /* type */
 			     bindex, /* value */
@@ -330,8 +351,9 @@
 }
 
 
-static void keyspan_pda_break_ctl (struct usb_serial_port *port, int break_state)
+static void keyspan_pda_break_ctl(struct tty_struct *tty, int break_state)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct usb_serial *serial = port->serial;
 	int value;
 	int result;
@@ -341,11 +363,11 @@
 	else
 		value = 0; /* clear break */
 	result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-				4, /* set break */
-				USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
-				value, 0, NULL, 0, 2000);
+			4, /* set break */
+			USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+			value, 0, NULL, 0, 2000);
 	if (result < 0)
-		dbg("%s - error %d from usb_control_msg", 
+		dbg("%s - error %d from usb_control_msg",
 		    __func__, result);
 	/* there is something funky about this.. the TCSBRK that 'cu' performs
 	   ought to translate into a break_ctl(-1),break_ctl(0) pair HZ/4
@@ -354,8 +376,8 @@
 }
 
 
-static void keyspan_pda_set_termios (struct usb_serial_port *port, 
-				     struct ktermios *old_termios)
+static void keyspan_pda_set_termios(struct tty_struct *tty,
+		struct usb_serial_port *port, struct ktermios *old_termios)
 {
 	struct usb_serial *serial = port->serial;
 	speed_t speed;
@@ -380,7 +402,7 @@
 
 	   For now, just do baud. */
 
-	speed = tty_get_baud_rate(port->tty);
+	speed = tty_get_baud_rate(tty);
 	speed = keyspan_pda_setbaud(serial, speed);
 
 	if (speed == 0) {
@@ -390,8 +412,8 @@
 	}
 	/* Only speed can change so copy the old h/w parameters
 	   then encode the new speed */
-	tty_termios_copy_hw(port->tty->termios, old_termios);
-	tty_encode_baud_rate(port->tty, speed, speed);
+	tty_termios_copy_hw(tty->termios, old_termios);
+	tty_encode_baud_rate(tty, speed, speed);
 }
 
 
@@ -408,7 +430,7 @@
 			     3, /* get pins */
 			     USB_TYPE_VENDOR|USB_RECIP_INTERFACE|USB_DIR_IN,
 			     0, 0, &data, 1, 2000);
-	if (rc > 0)
+	if (rc >= 0)
 		*value = data;
 	return rc;
 }
@@ -425,8 +447,9 @@
 	return rc;
 }
 
-static int keyspan_pda_tiocmget(struct usb_serial_port *port, struct file *file)
+static int keyspan_pda_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct usb_serial *serial = port->serial;
 	int rc;
 	unsigned char status;
@@ -445,9 +468,10 @@
 	return value;
 }
 
-static int keyspan_pda_tiocmset(struct usb_serial_port *port, struct file *file,
+static int keyspan_pda_tiocmset(struct tty_struct *tty, struct file *file,
 				unsigned int set, unsigned int clear)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct usb_serial *serial = port->serial;
 	int rc;
 	unsigned char status;
@@ -469,23 +493,8 @@
 	return rc;
 }
 
-static int keyspan_pda_ioctl(struct usb_serial_port *port, struct file *file,
-			     unsigned int cmd, unsigned long arg)
-{
-	switch (cmd) {
-	case TIOCMIWAIT:
-		/* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
-		/* TODO */
-	case TIOCGICOUNT:
-		/* return count of modemline transitions */
-		return 0; /* TODO */
-	}
-	
-	return -ENOIOCTLCMD;
-}
-
-static int keyspan_pda_write(struct usb_serial_port *port, 
-			     const unsigned char *buf, int count)
+static int keyspan_pda_write(struct tty_struct *tty,
+	struct usb_serial_port *port, const unsigned char *buf, int count)
 {
 	struct usb_serial *serial = port->serial;
 	int request_unthrottle = 0;
@@ -501,10 +510,10 @@
 	   select() or poll() too) until we receive that unthrottle interrupt.
 	   Block if we can't write anything at all, otherwise write as much as
 	   we can. */
-	dbg("keyspan_pda_write(%d)",count);
+	dbg("keyspan_pda_write(%d)", count);
 	if (count == 0) {
 		dbg(" write request of 0 bytes");
-		return (0);
+		return 0;
 	}
 
 	/* we might block because of:
@@ -531,7 +540,7 @@
 	   scheduler time, since usb_control_msg() sleeps. */
 	if (count > priv->tx_room && !in_interrupt()) {
 		unsigned char room;
-		rc = usb_control_msg(serial->dev, 
+		rc = usb_control_msg(serial->dev,
 				     usb_rcvctrlpipe(serial->dev, 0),
 				     6, /* write_room */
 				     USB_TYPE_VENDOR | USB_RECIP_INTERFACE
@@ -562,7 +571,7 @@
 
 	if (count) {
 		/* now transfer data */
-		memcpy (port->write_urb->transfer_buffer, buf, count);
+		memcpy(port->write_urb->transfer_buffer, buf, count);
 		/* send the data out the bulk port */
 		port->write_urb->transfer_buffer_length = count;
 
@@ -574,8 +583,7 @@
 			dbg(" usb_submit_urb(write bulk) failed");
 			goto exit;
 		}
-	}
-	else {
+	} else {
 		/* There wasn't any room left, so we are throttled until
 		   the buffer empties a bit */
 		request_unthrottle = 1;
@@ -594,7 +602,7 @@
 }
 
 
-static void keyspan_pda_write_bulk_callback (struct urb *urb)
+static void keyspan_pda_write_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 	struct keyspan_pda_private *priv;
@@ -607,22 +615,21 @@
 }
 
 
-static int keyspan_pda_write_room (struct usb_serial_port *port)
+static int keyspan_pda_write_room(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct keyspan_pda_private *priv;
-
 	priv = usb_get_serial_port_data(port);
-
 	/* used by n_tty.c for processing of tabs and such. Giving it our
 	   conservative guess is probably good enough, but needs testing by
 	   running a console through the device. */
-
-	return (priv->tx_room);
+	return priv->tx_room;
 }
 
 
-static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port)
+static int keyspan_pda_chars_in_buffer(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct keyspan_pda_private *priv;
 	unsigned long flags;
 	int ret = 0;
@@ -640,7 +647,8 @@
 }
 
 
-static int keyspan_pda_open (struct usb_serial_port *port, struct file *filp)
+static int keyspan_pda_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct usb_serial *serial = port->serial;
 	unsigned char room;
@@ -672,8 +680,8 @@
 
 	/* the normal serial device seems to always turn on DTR and RTS here,
 	   so do the same */
-	if (port->tty->termios->c_cflag & CBAUD)
-		keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2) );
+	if (tty && (tty->termios->c_cflag & CBAUD))
+		keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2));
 	else
 		keyspan_pda_set_modem_info(serial, 0);
 
@@ -690,13 +698,15 @@
 }
 
 
-static void keyspan_pda_close(struct usb_serial_port *port, struct file *filp)
+static void keyspan_pda_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct usb_serial *serial = port->serial;
 
 	if (serial->dev) {
-		/* the normal serial device seems to always shut off DTR and RTS now */
-		if (port->tty->termios->c_cflag & HUPCL)
+		/* the normal serial device seems to always shut
+		   off DTR and RTS now */
+		if (tty->termios->c_cflag & HUPCL)
 			keyspan_pda_set_modem_info(serial, 0);
 
 		/* shutdown our bulk reads and writes */
@@ -707,7 +717,7 @@
 
 
 /* download the firmware to a "fake" device (pre-renumeration) */
-static int keyspan_pda_fake_startup (struct usb_serial *serial)
+static int keyspan_pda_fake_startup(struct usb_serial *serial)
 {
 	int response;
 	const char *fw_name;
@@ -756,10 +766,10 @@
 	response = ezusb_set_reset(serial, 0);
 
 	/* we want this device to fail to have a driver assigned to it. */
-	return (1);
+	return 1;
 }
 
-static int keyspan_pda_startup (struct usb_serial *serial)
+static int keyspan_pda_startup(struct usb_serial *serial)
 {
 
 	struct keyspan_pda_private *priv;
@@ -769,20 +779,20 @@
 
 	priv = kmalloc(sizeof(struct keyspan_pda_private), GFP_KERNEL);
 	if (!priv)
-		return (1); /* error */
+		return 1; /* error */
 	usb_set_serial_port_data(serial->port[0], priv);
 	init_waitqueue_head(&serial->port[0]->write_wait);
 	INIT_WORK(&priv->wakeup_work, keyspan_pda_wakeup_write);
 	INIT_WORK(&priv->unthrottle_work, keyspan_pda_request_unthrottle);
 	priv->serial = serial;
 	priv->port = serial->port[0];
-	return (0);
+	return 0;
 }
 
-static void keyspan_pda_shutdown (struct usb_serial *serial)
+static void keyspan_pda_shutdown(struct usb_serial *serial)
 {
 	dbg("%s", __func__);
-	
+
 	kfree(usb_get_serial_port_data(serial->port[0]));
 }
 
@@ -832,7 +842,6 @@
 	.chars_in_buffer =	keyspan_pda_chars_in_buffer,
 	.throttle =		keyspan_pda_rx_throttle,
 	.unthrottle =		keyspan_pda_rx_unthrottle,
-	.ioctl =		keyspan_pda_ioctl,
 	.set_termios =		keyspan_pda_set_termios,
 	.break_ctl =		keyspan_pda_break_ctl,
 	.tiocmget =		keyspan_pda_tiocmget,
@@ -842,7 +851,7 @@
 };
 
 
-static int __init keyspan_pda_init (void)
+static int __init keyspan_pda_init(void)
 {
 	int retval;
 	retval = usb_serial_register(&keyspan_pda_device);
@@ -863,7 +872,7 @@
 		goto failed_usb_register;
 	info(DRIVER_DESC " " DRIVER_VERSION);
 	return 0;
-failed_usb_register:	
+failed_usb_register:
 #ifdef XIRCOM
 	usb_serial_deregister(&xircom_pgs_fake_device);
 failed_xircom_register:
@@ -880,15 +889,15 @@
 }
 
 
-static void __exit keyspan_pda_exit (void)
+static void __exit keyspan_pda_exit(void)
 {
-	usb_deregister (&keyspan_pda_driver);
-	usb_serial_deregister (&keyspan_pda_device);
+	usb_deregister(&keyspan_pda_driver);
+	usb_serial_deregister(&keyspan_pda_device);
 #ifdef KEYSPAN
-	usb_serial_deregister (&keyspan_pda_fake_device);
+	usb_serial_deregister(&keyspan_pda_fake_device);
 #endif
 #ifdef XIRCOM
-	usb_serial_deregister (&xircom_pgs_fake_device);
+	usb_serial_deregister(&xircom_pgs_fake_device);
 #endif
 }
 
@@ -896,8 +905,8 @@
 module_init(keyspan_pda_init);
 module_exit(keyspan_pda_exit);
 
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index f328948..b84dddc 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -15,12 +15,12 @@
  * Neither Palm, nor their contractor (MCCI) or their supplier (KLSI) provided
  * information that was not already available.
  *
- * It seems that KLSI bought some silicon-design information from ScanLogic, 
+ * It seems that KLSI bought some silicon-design information from ScanLogic,
  * whose SL11R processor is at the core of the KL5KUSB chipset from KLSI.
  * KLSI has firmware available for their devices; it is probable that the
  * firmware differs from that used by KLSI in their products. If you have an
- * original KLSI device and can provide some information on it, I would be 
- * most interested in adding support for it here. If you have any information 
+ * original KLSI device and can provide some information on it, I would be
+ * most interested in adding support for it here. If you have any information
  * on the protocol used (or find errors in my reverse-engineered stuff), please
  * let me know.
  *
@@ -40,7 +40,7 @@
  *   0.2  - TIOCMGET works, so autopilot(1) can be used!
  *   0.1  - can be used to to pilot-xfer -p /dev/ttyUSB0 -l
  *
- *   The driver skeleton is mainly based on mct_u232.c and various other 
+ *   The driver skeleton is mainly based on mct_u232.c and various other
  *   pieces of code shamelessly copied from the drivers/usb/serial/ directory.
  */
 
@@ -53,7 +53,7 @@
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
 #include <linux/module.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/unaligned.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
@@ -72,33 +72,25 @@
 /*
  * Function prototypes
  */
-static int  klsi_105_startup	         (struct usb_serial *serial);
-static void klsi_105_shutdown	         (struct usb_serial *serial);
-static int  klsi_105_open	         (struct usb_serial_port *port,
-					  struct file *filp);
-static void klsi_105_close	         (struct usb_serial_port *port,
-					  struct file *filp);
-static int  klsi_105_write	         (struct usb_serial_port *port,
-					  const unsigned char *buf,
-					  int count);
-static void klsi_105_write_bulk_callback (struct urb *urb);
-static int  klsi_105_chars_in_buffer     (struct usb_serial_port *port);
-static int  klsi_105_write_room          (struct usb_serial_port *port);
-
-static void klsi_105_read_bulk_callback  (struct urb *urb);
-static void klsi_105_set_termios         (struct usb_serial_port *port,
-					  struct ktermios *old);
-static void klsi_105_throttle		 (struct usb_serial_port *port);
-static void klsi_105_unthrottle		 (struct usb_serial_port *port);
-/*
-static void klsi_105_break_ctl	         (struct usb_serial_port *port,
-					  int break_state );
- */
-static int  klsi_105_tiocmget	         (struct usb_serial_port *port,
-					  struct file *file);
-static int  klsi_105_tiocmset	         (struct usb_serial_port *port,
-					  struct file *file, unsigned int set,
-					  unsigned int clear);
+static int  klsi_105_startup(struct usb_serial *serial);
+static void klsi_105_shutdown(struct usb_serial *serial);
+static int  klsi_105_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
+static void klsi_105_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
+static int  klsi_105_write(struct tty_struct *tty,
+	struct usb_serial_port *port, const unsigned char *buf, int count);
+static void klsi_105_write_bulk_callback(struct urb *urb);
+static int  klsi_105_chars_in_buffer(struct tty_struct *tty);
+static int  klsi_105_write_room(struct tty_struct *tty);
+static void klsi_105_read_bulk_callback(struct urb *urb);
+static void klsi_105_set_termios(struct tty_struct *tty,
+			struct usb_serial_port *port, struct ktermios *old);
+static void klsi_105_throttle(struct tty_struct *tty);
+static void klsi_105_unthrottle(struct tty_struct *tty);
+static int  klsi_105_tiocmget(struct tty_struct *tty, struct file *file);
+static int  klsi_105_tiocmset(struct tty_struct *tty, struct file *file,
+			unsigned int set, unsigned int clear);
 
 /*
  * All of the device info needed for the KLSI converters.
@@ -109,7 +101,7 @@
 	{ }		/* Terminating entry */
 };
 
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
 
 static struct usb_driver kl5kusb105d_driver = {
 	.name =		"kl5kusb105d",
@@ -134,7 +126,7 @@
 	.write_bulk_callback = klsi_105_write_bulk_callback,
 	.chars_in_buffer =   klsi_105_chars_in_buffer,
 	.write_room =        klsi_105_write_room,
-	.read_bulk_callback =klsi_105_read_bulk_callback,
+	.read_bulk_callback = klsi_105_read_bulk_callback,
 	.set_termios =	     klsi_105_set_termios,
 	/*.break_ctl =	     klsi_105_break_ctl,*/
 	.tiocmget =          klsi_105_tiocmget,
@@ -161,7 +153,7 @@
 	struct ktermios			termios;
 	unsigned long			line_state; /* modem line settings */
 	/* write pool */
-	struct urb *			write_urb_pool[NUM_URBS];
+	struct urb			*write_urb_pool[NUM_URBS];
 	spinlock_t			lock;
 	unsigned long			bytes_in;
 	unsigned long			bytes_out;
@@ -180,15 +172,15 @@
 {
 	int rc;
 
-        rc = usb_control_msg(port->serial->dev,
-			     usb_sndctrlpipe(port->serial->dev, 0),
-			     KL5KUSB105A_SIO_SET_DATA,
-                             USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_INTERFACE,
-			     0, /* value */
-			     0, /* index */
-			     settings,
-			     sizeof(struct klsi_105_port_settings),
-			     KLSI_TIMEOUT);
+	rc = usb_control_msg(port->serial->dev,
+			usb_sndctrlpipe(port->serial->dev, 0),
+			KL5KUSB105A_SIO_SET_DATA,
+			USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_INTERFACE,
+			0, /* value */
+			0, /* index */
+			settings,
+			sizeof(struct klsi_105_port_settings),
+			KLSI_TIMEOUT);
 	if (rc < 0)
 		err("Change port settings failed (error = %d)", rc);
 	info("%s - %d byte block, baudrate %x, databits %d, u1 %d, u2 %d",
@@ -196,7 +188,7 @@
 	    settings->pktlen,
 	    settings->baudrate, settings->databits,
 	    settings->unknown1, settings->unknown2);
-        return rc;
+	return rc;
 } /* klsi_105_chg_port_settings */
 
 /* translate a 16-bit status value from the device to linux's TIO bits */
@@ -210,9 +202,9 @@
 
 	return res;
 }
-/* 
+/*
  * Read line control via vendor command and return result through
- * *line_state_p 
+ * *line_state_p
  */
 /* It seems that the status buffer has always only 2 bytes length */
 #define KLSI_STATUSBUF_LEN	2
@@ -220,14 +212,14 @@
 				   unsigned long *line_state_p)
 {
 	int rc;
-	__u8 status_buf[KLSI_STATUSBUF_LEN] = { -1,-1};
+	__u8 status_buf[KLSI_STATUSBUF_LEN] = { -1, -1};
 	__u16 status;
 
 	info("%s - sending SIO Poll request", __func__);
-        rc = usb_control_msg(port->serial->dev,
+	rc = usb_control_msg(port->serial->dev,
 			     usb_rcvctrlpipe(port->serial->dev, 0),
 			     KL5KUSB105A_SIO_POLL,
-                             USB_TYPE_VENDOR | USB_DIR_IN,
+			     USB_TYPE_VENDOR | USB_DIR_IN,
 			     0, /* value */
 			     0, /* index */
 			     status_buf, KLSI_STATUSBUF_LEN,
@@ -236,15 +228,14 @@
 	if (rc < 0)
 		err("Reading line status failed (error = %d)", rc);
 	else {
-		status = le16_to_cpu(get_unaligned((__le16 *)status_buf));
+		status = get_unaligned_le16(status_buf);
 
 		info("%s - read status %x %x", __func__,
 		     status_buf[0], status_buf[1]);
 
 		*line_state_p = klsi_105_status2linestate(status);
 	}
-
-        return rc;
+	return rc;
 }
 
 
@@ -252,7 +243,7 @@
  * Driver's tty interface functions
  */
 
-static int klsi_105_startup (struct usb_serial *serial)
+static int klsi_105_startup(struct usb_serial *serial)
 {
 	struct klsi_105_private *priv;
 	int i, j;
@@ -262,7 +253,7 @@
 	 */
 
 	/* allocate the private data structure */
-	for (i=0; i<serial->num_ports; i++) {
+	for (i = 0; i < serial->num_ports; i++) {
 		priv = kmalloc(sizeof(struct klsi_105_private),
 						   GFP_KERNEL);
 		if (!priv) {
@@ -283,9 +274,9 @@
 		priv->bytes_out	    = 0;
 		usb_set_serial_port_data(serial->port[i], priv);
 
-		spin_lock_init (&priv->lock);
-		for (j=0; j<NUM_URBS; j++) {
-			struct urb* urb = usb_alloc_urb(0, GFP_KERNEL);
+		spin_lock_init(&priv->lock);
+		for (j = 0; j < NUM_URBS; j++) {
+			struct urb *urb = usb_alloc_urb(0, GFP_KERNEL);
 
 			priv->write_urb_pool[j] = urb;
 			if (urb == NULL) {
@@ -293,10 +284,11 @@
 				goto err_cleanup;
 			}
 
-			urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE,
-							GFP_KERNEL);
+			urb->transfer_buffer =
+				kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
 			if (!urb->transfer_buffer) {
-				err("%s - out of memory for urb buffers.", __func__);
+				err("%s - out of memory for urb buffers.",
+								__func__);
 				goto err_cleanup;
 			}
 		}
@@ -304,13 +296,13 @@
 		/* priv->termios is left uninitalized until port opening */
 		init_waitqueue_head(&serial->port[i]->write_wait);
 	}
-	
+
 	return 0;
 
 err_cleanup:
 	for (; i >= 0; i--) {
 		priv = usb_get_serial_port_data(serial->port[i]);
-		for (j=0; j < NUM_URBS; j++) {
+		for (j = 0; j < NUM_URBS; j++) {
 			if (priv->write_urb_pool[j]) {
 				kfree(priv->write_urb_pool[j]->transfer_buffer);
 				usb_free_urb(priv->write_urb_pool[j]);
@@ -322,22 +314,23 @@
 } /* klsi_105_startup */
 
 
-static void klsi_105_shutdown (struct usb_serial *serial)
+static void klsi_105_shutdown(struct usb_serial *serial)
 {
 	int i;
-	
+
 	dbg("%s", __func__);
 
 	/* stop reads and writes on all ports */
-	for (i=0; i < serial->num_ports; ++i) {
-		struct klsi_105_private *priv = usb_get_serial_port_data(serial->port[i]);
+	for (i = 0; i < serial->num_ports; ++i) {
+		struct klsi_105_private *priv =
+				usb_get_serial_port_data(serial->port[i]);
 		unsigned long flags;
 
 		if (priv) {
 			/* kill our write urb pool */
 			int j;
 			struct urb **write_urbs = priv->write_urb_pool;
-			spin_lock_irqsave(&priv->lock,flags);
+			spin_lock_irqsave(&priv->lock, flags);
 
 			for (j = 0; j < NUM_URBS; j++) {
 				if (write_urbs[j]) {
@@ -349,19 +342,18 @@
 					 * oopses. */
 					/* usb_kill_urb(write_urbs[j]); */
 					kfree(write_urbs[j]->transfer_buffer);
-					usb_free_urb (write_urbs[j]);
+					usb_free_urb(write_urbs[j]);
 				}
 			}
-
-			spin_unlock_irqrestore (&priv->lock, flags);
-
+			spin_unlock_irqrestore(&priv->lock, flags);
 			kfree(priv);
 			usb_set_serial_port_data(serial->port[i], NULL);
 		}
 	}
 } /* klsi_105_shutdown */
 
-static int  klsi_105_open (struct usb_serial_port *port, struct file *filp)
+static int  klsi_105_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct klsi_105_private *priv = usb_get_serial_port_data(port);
 	int retval = 0;
@@ -375,11 +367,11 @@
 
 	/* force low_latency on so that our tty_push actually forces
 	 * the data through
-	 * port->tty->low_latency = 1; */
+	 * tty->low_latency = 1; */
 
 	/* Do a defined restart:
 	 * Set up sane default baud rate and send the 'READ_ON'
-	 * vendor command. 
+	 * vendor command.
 	 * FIXME: set modem line control (how?)
 	 * Then read the modem line control and store values in
 	 * priv->line_state.
@@ -390,24 +382,24 @@
 	cfg.unknown1 = 0;
 	cfg.unknown2 = 1;
 	klsi_105_chg_port_settings(port, &cfg);
-	
+
 	/* set up termios structure */
-	spin_lock_irqsave (&priv->lock, flags);
-	priv->termios.c_iflag = port->tty->termios->c_iflag;
-	priv->termios.c_oflag = port->tty->termios->c_oflag;
-	priv->termios.c_cflag = port->tty->termios->c_cflag;
-	priv->termios.c_lflag = port->tty->termios->c_lflag;
-	for (i=0; i<NCCS; i++)
-		priv->termios.c_cc[i] = port->tty->termios->c_cc[i];
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->termios.c_iflag = tty->termios->c_iflag;
+	priv->termios.c_oflag = tty->termios->c_oflag;
+	priv->termios.c_cflag = tty->termios->c_cflag;
+	priv->termios.c_lflag = tty->termios->c_lflag;
+	for (i = 0; i < NCCS; i++)
+		priv->termios.c_cc[i] = tty->termios->c_cc[i];
 	priv->cfg.pktlen   = cfg.pktlen;
 	priv->cfg.baudrate = cfg.baudrate;
 	priv->cfg.databits = cfg.databits;
 	priv->cfg.unknown1 = cfg.unknown1;
 	priv->cfg.unknown2 = cfg.unknown2;
-	spin_unlock_irqrestore (&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->lock, flags);
 
 	/* READ_ON and urb submission */
-	usb_fill_bulk_urb(port->read_urb, port->serial->dev, 
+	usb_fill_bulk_urb(port->read_urb, port->serial->dev,
 		      usb_rcvbulkpipe(port->serial->dev,
 				      port->bulk_in_endpointAddress),
 		      port->read_urb->transfer_buffer,
@@ -423,7 +415,7 @@
 	}
 
 	rc = usb_control_msg(port->serial->dev,
-			     usb_sndctrlpipe(port->serial->dev,0),
+			     usb_sndctrlpipe(port->serial->dev, 0),
 			     KL5KUSB105A_SIO_CONFIGURE,
 			     USB_TYPE_VENDOR|USB_DIR_OUT|USB_RECIP_INTERFACE,
 			     KL5KUSB105A_SIO_CONFIGURE_READ_ON,
@@ -434,14 +426,14 @@
 	if (rc < 0) {
 		err("Enabling read failed (error = %d)", rc);
 		retval = rc;
-	} else 
+	} else
 		dbg("%s - enabled reading", __func__);
 
 	rc = klsi_105_get_line_state(port, &line_state);
 	if (rc >= 0) {
-		spin_lock_irqsave (&priv->lock, flags);
+		spin_lock_irqsave(&priv->lock, flags);
 		priv->line_state = line_state;
-		spin_unlock_irqrestore (&priv->lock, flags);
+		spin_unlock_irqrestore(&priv->lock, flags);
 		dbg("%s - read line state 0x%lx", __func__, line_state);
 		retval = 0;
 	} else
@@ -452,7 +444,8 @@
 } /* klsi_105_open */
 
 
-static void klsi_105_close (struct usb_serial_port *port, struct file *filp)
+static void klsi_105_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct klsi_105_private *priv = usb_get_serial_port_data(port);
 	int rc;
@@ -462,14 +455,14 @@
 	mutex_lock(&port->serial->disc_mutex);
 	if (!port->serial->disconnected) {
 		/* send READ_OFF */
-		rc = usb_control_msg (port->serial->dev,
-				      usb_sndctrlpipe(port->serial->dev, 0),
-				      KL5KUSB105A_SIO_CONFIGURE,
-				      USB_TYPE_VENDOR | USB_DIR_OUT,
-				      KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
-				      0, /* index */
-				      NULL, 0,
-				      KLSI_TIMEOUT);
+		rc = usb_control_msg(port->serial->dev,
+				     usb_sndctrlpipe(port->serial->dev, 0),
+				     KL5KUSB105A_SIO_CONFIGURE,
+				     USB_TYPE_VENDOR | USB_DIR_OUT,
+				     KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
+				     0, /* index */
+				     NULL, 0,
+				     KLSI_TIMEOUT);
 		if (rc < 0)
 			err("Disabling read failed (error = %d)", rc);
 	}
@@ -482,23 +475,24 @@
 	/* FIXME */
 	/* wgg - do I need this? I think so. */
 	usb_kill_urb(port->interrupt_in_urb);
-	info("kl5kusb105 port stats: %ld bytes in, %ld bytes out", priv->bytes_in, priv->bytes_out);
+	info("kl5kusb105 port stats: %ld bytes in, %ld bytes out",
+					priv->bytes_in, priv->bytes_out);
 } /* klsi_105_close */
 
 
 /* We need to write a complete 64-byte data block and encode the
- * number actually sent in the first double-byte, LSB-order. That 
+ * number actually sent in the first double-byte, LSB-order. That
  * leaves at most 62 bytes of payload.
  */
 #define KLSI_105_DATA_OFFSET	2   /* in the bulk urb data block */
 
 
-static int klsi_105_write (struct usb_serial_port *port,
-			   const unsigned char *buf, int count)
+static int klsi_105_write(struct tty_struct *tty,
+	struct usb_serial_port *port, const unsigned char *buf, int count)
 {
 	struct klsi_105_private *priv = usb_get_serial_port_data(port);
 	int result, size;
-	int bytes_sent=0;
+	int bytes_sent = 0;
 
 	dbg("%s - port %d", __func__, port->number);
 
@@ -507,34 +501,37 @@
 		struct urb *urb = NULL;
 		unsigned long flags;
 		int i;
-		/* since the pool is per-port we might not need the spin lock !? */
-		spin_lock_irqsave (&priv->lock, flags);
-		for (i=0; i<NUM_URBS; i++) {
+		/* since the pool is per-port we might not need
+		   the spin lock !? */
+		spin_lock_irqsave(&priv->lock, flags);
+		for (i = 0; i < NUM_URBS; i++) {
 			if (priv->write_urb_pool[i]->status != -EINPROGRESS) {
 				urb = priv->write_urb_pool[i];
 				dbg("%s - using pool URB %d", __func__, i);
 				break;
 			}
 		}
-		spin_unlock_irqrestore (&priv->lock, flags);
+		spin_unlock_irqrestore(&priv->lock, flags);
 
-		if (urb==NULL) {
+		if (urb == NULL) {
 			dbg("%s - no more free urbs", __func__);
 			goto exit;
 		}
 
 		if (urb->transfer_buffer == NULL) {
-			urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
+			urb->transfer_buffer =
+				kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
 			if (urb->transfer_buffer == NULL) {
 				err("%s - no more kernel memory...", __func__);
 				goto exit;
 			}
 		}
 
-		size = min (count, port->bulk_out_size - KLSI_105_DATA_OFFSET);
-		size = min (size, URB_TRANSFER_BUFFER_SIZE - KLSI_105_DATA_OFFSET);
+		size = min(count, port->bulk_out_size - KLSI_105_DATA_OFFSET);
+		size = min(size, URB_TRANSFER_BUFFER_SIZE -
+							KLSI_105_DATA_OFFSET);
 
-		memcpy (urb->transfer_buffer + KLSI_105_DATA_OFFSET, buf, size);
+		memcpy(urb->transfer_buffer + KLSI_105_DATA_OFFSET, buf, size);
 
 		/* write payload size into transfer buffer */
 		((__u8 *)urb->transfer_buffer)[0] = (__u8) (size & 0xFF);
@@ -552,7 +549,8 @@
 		/* send the data out the bulk port */
 		result = usb_submit_urb(urb, GFP_ATOMIC);
 		if (result) {
-			err("%s - failed submitting write urb, error %d", __func__, result);
+			err("%s - failed submitting write urb, error %d",
+							__func__, result);
 			goto exit;
 		}
 		buf += size;
@@ -561,12 +559,12 @@
 	}
 exit:
 	/* lockless, but it's for debug info only... */
-	priv->bytes_out+=bytes_sent;
+	priv->bytes_out += bytes_sent;
 
 	return bytes_sent;	/* that's how much we wrote */
 } /* klsi_105_write */
 
-static void klsi_105_write_bulk_callback ( struct urb *urb)
+static void klsi_105_write_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 	int status = urb->status;
@@ -584,50 +582,50 @@
 
 
 /* return number of characters currently in the writing process */
-static int klsi_105_chars_in_buffer (struct usb_serial_port *port)
+static int klsi_105_chars_in_buffer(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	int chars = 0;
 	int i;
 	unsigned long flags;
 	struct klsi_105_private *priv = usb_get_serial_port_data(port);
 
-	spin_lock_irqsave (&priv->lock, flags);
+	spin_lock_irqsave(&priv->lock, flags);
 
 	for (i = 0; i < NUM_URBS; ++i) {
-		if (priv->write_urb_pool[i]->status == -EINPROGRESS) {
+		if (priv->write_urb_pool[i]->status == -EINPROGRESS)
 			chars += URB_TRANSFER_BUFFER_SIZE;
-		}
 	}
 
-	spin_unlock_irqrestore (&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->lock, flags);
 
 	dbg("%s - returns %d", __func__, chars);
-	return (chars);
+	return chars;
 }
 
-static int klsi_105_write_room (struct usb_serial_port *port)
+static int klsi_105_write_room(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	unsigned long flags;
 	int i;
 	int room = 0;
 	struct klsi_105_private *priv = usb_get_serial_port_data(port);
 
-	spin_lock_irqsave (&priv->lock, flags);
+	spin_lock_irqsave(&priv->lock, flags);
 	for (i = 0; i < NUM_URBS; ++i) {
-		if (priv->write_urb_pool[i]->status != -EINPROGRESS) {
+		if (priv->write_urb_pool[i]->status != -EINPROGRESS)
 			room += URB_TRANSFER_BUFFER_SIZE;
-		}
 	}
 
-	spin_unlock_irqrestore (&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->lock, flags);
 
 	dbg("%s - returns %d", __func__, room);
-	return (room);
+	return room;
 }
 
 
 
-static void klsi_105_read_bulk_callback (struct urb *urb)
+static void klsi_105_read_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 	struct klsi_105_private *priv = usb_get_serial_port_data(port);
@@ -660,13 +658,13 @@
 	} else {
 		int bytes_sent = ((__u8 *) data)[0] +
 				 ((unsigned int) ((__u8 *) data)[1] << 8);
-		tty = port->tty;
+		tty = port->port.tty;
 		/* we should immediately resubmit the URB, before attempting
 		 * to pass the data on to the tty layer. But that needs locking
 		 * against re-entry an then mixed-up data because of
 		 * intermixed tty_flip_buffer_push()s
 		 * FIXME
-		 */ 
+		 */
 		usb_serial_debug_data(debug, &port->dev, __func__,
 				      urb->actual_length, data);
 
@@ -686,7 +684,7 @@
 		priv->bytes_in += bytes_sent;
 	}
 	/* Continue trying to always read  */
-	usb_fill_bulk_urb(port->read_urb, port->serial->dev, 
+	usb_fill_bulk_urb(port->read_urb, port->serial->dev,
 		      usb_rcvbulkpipe(port->serial->dev,
 				      port->bulk_in_endpointAddress),
 		      port->read_urb->transfer_buffer,
@@ -695,15 +693,16 @@
 		      port);
 	rc = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 	if (rc)
-		err("%s - failed resubmitting read urb, error %d", __func__, rc);
+		err("%s - failed resubmitting read urb, error %d",
+							__func__, rc);
 } /* klsi_105_read_bulk_callback */
 
 
-static void klsi_105_set_termios (struct usb_serial_port *port,
-				  struct ktermios *old_termios)
+static void klsi_105_set_termios(struct tty_struct *tty,
+				 struct usb_serial_port *port,
+				 struct ktermios *old_termios)
 {
 	struct klsi_105_private *priv = usb_get_serial_port_data(port);
-	struct tty_struct *tty = port->tty;
 	unsigned int iflag = tty->termios->c_iflag;
 	unsigned int old_iflag = old_termios->c_iflag;
 	unsigned int cflag = tty->termios->c_cflag;
@@ -711,65 +710,63 @@
 	struct klsi_105_port_settings cfg;
 	unsigned long flags;
 	speed_t baud;
-	
+
 	/* lock while we are modifying the settings */
-	spin_lock_irqsave (&priv->lock, flags);
-	
+	spin_lock_irqsave(&priv->lock, flags);
+
 	/*
 	 * Update baud rate
 	 */
 	baud = tty_get_baud_rate(tty);
 
-	if( (cflag & CBAUD) != (old_cflag & CBAUD) ) {
-	        /* reassert DTR and (maybe) RTS on transition from B0 */
-		if( (old_cflag & CBAUD) == B0 ) {
+	if ((cflag & CBAUD) != (old_cflag & CBAUD)) {
+		/* reassert DTR and (maybe) RTS on transition from B0 */
+		if ((old_cflag & CBAUD) == B0) {
 			dbg("%s: baud was B0", __func__);
 #if 0
 			priv->control_state |= TIOCM_DTR;
 			/* don't set RTS if using hardware flow control */
-			if (!(old_cflag & CRTSCTS)) {
+			if (!(old_cflag & CRTSCTS))
 				priv->control_state |= TIOCM_RTS;
-			}
 			mct_u232_set_modem_ctrl(serial, priv->control_state);
 #endif
 		}
 	}
-	switch(baud) {
-		case 0: /* handled below */
-			break;
-		case 1200:
-			priv->cfg.baudrate = kl5kusb105a_sio_b1200;
-			break;
-		case 2400:
-			priv->cfg.baudrate = kl5kusb105a_sio_b2400;
-			break;
-		case 4800:
-			priv->cfg.baudrate = kl5kusb105a_sio_b4800;
-			break;
-		case 9600:
+	switch (baud) {
+	case 0: /* handled below */
+		break;
+	case 1200:
+		priv->cfg.baudrate = kl5kusb105a_sio_b1200;
+		break;
+	case 2400:
+		priv->cfg.baudrate = kl5kusb105a_sio_b2400;
+		break;
+	case 4800:
+		priv->cfg.baudrate = kl5kusb105a_sio_b4800;
+		break;
+	case 9600:
+		priv->cfg.baudrate = kl5kusb105a_sio_b9600;
+		break;
+	case 19200:
+		priv->cfg.baudrate = kl5kusb105a_sio_b19200;
+		break;
+	case 38400:
+		priv->cfg.baudrate = kl5kusb105a_sio_b38400;
+		break;
+	case 57600:
+		priv->cfg.baudrate = kl5kusb105a_sio_b57600;
+		break;
+	case 115200:
+		priv->cfg.baudrate = kl5kusb105a_sio_b115200;
+		break;
+	default:
+		dbg("KLSI USB->Serial converter:"
+		    " unsupported baudrate request, using default of 9600");
 			priv->cfg.baudrate = kl5kusb105a_sio_b9600;
-			break;
-		case 19200:
-			priv->cfg.baudrate = kl5kusb105a_sio_b19200;
-			break;
-		case 38400:
-			priv->cfg.baudrate = kl5kusb105a_sio_b38400;
-			break;
-		case 57600:
-			priv->cfg.baudrate = kl5kusb105a_sio_b57600;
-			break;
-		case 115200:
-			priv->cfg.baudrate = kl5kusb105a_sio_b115200;
-			break;
-		default:
-			dbg("KLSI USB->Serial converter:"
-			    " unsupported baudrate request, using default"
-			    " of 9600");
-			priv->cfg.baudrate = kl5kusb105a_sio_b9600;
-			baud = 9600;
-			break;
+		baud = 9600;
+		break;
 	}
-	if ((cflag & CBAUD) == B0 ) {
+	if ((cflag & CBAUD) == B0) {
 		dbg("%s: baud is B0", __func__);
 		/* Drop RTS and DTR */
 		/* maybe this should be simulated by sending read
@@ -778,7 +775,7 @@
 		;
 #if 0
 		priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
-       		mct_u232_set_modem_ctrl(serial, priv->control_state);
+		mct_u232_set_modem_ctrl(serial, priv->control_state);
 #endif
 	}
 	tty_encode_baud_rate(tty, baud, baud);
@@ -788,11 +785,11 @@
 		switch (cflag & CSIZE) {
 		case CS5:
 			dbg("%s - 5 bits/byte not supported", __func__);
-			spin_unlock_irqrestore (&priv->lock, flags);
+			spin_unlock_irqrestore(&priv->lock, flags);
 			return ;
 		case CS6:
 			dbg("%s - 6 bits/byte not supported", __func__);
-			spin_unlock_irqrestore (&priv->lock, flags);
+			spin_unlock_irqrestore(&priv->lock, flags);
 			return ;
 		case CS7:
 			priv->cfg.databits = kl5kusb105a_dtb_7;
@@ -811,8 +808,7 @@
 	 * Update line control register (LCR)
 	 */
 	if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))
-	    || (cflag & CSTOPB) != (old_cflag & CSTOPB) ) {
-		
+	    || (cflag & CSTOPB) != (old_cflag & CSTOPB)) {
 		/* Not currently supported */
 		tty->termios->c_cflag &= ~(PARENB|PARODD|CSTOPB);
 #if 0
@@ -833,20 +829,18 @@
 #endif
 		;
 	}
-	
 	/*
 	 * Set flow control: well, I do not really now how to handle DTR/RTS.
 	 * Just do what we have seen with SniffUSB on Win98.
 	 */
-	if( (iflag & IXOFF) != (old_iflag & IXOFF)
+	if ((iflag & IXOFF) != (old_iflag & IXOFF)
 	    || (iflag & IXON) != (old_iflag & IXON)
-	    ||  (cflag & CRTSCTS) != (old_cflag & CRTSCTS) ) {
-		
+	    ||  (cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
 		/* Not currently supported */
 		tty->termios->c_cflag &= ~CRTSCTS;
 		/* Drop DTR/RTS if no flow control otherwise assert */
 #if 0
-		if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS) )
+		if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS))
 			priv->control_state |= TIOCM_DTR | TIOCM_RTS;
 		else
 			priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
@@ -854,19 +848,21 @@
 #endif
 		;
 	}
-	memcpy (&cfg, &priv->cfg, sizeof(cfg));
-	spin_unlock_irqrestore (&priv->lock, flags);
-	
+	memcpy(&cfg, &priv->cfg, sizeof(cfg));
+	spin_unlock_irqrestore(&priv->lock, flags);
+
 	/* now commit changes to device */
 	klsi_105_chg_port_settings(port, &cfg);
 } /* klsi_105_set_termios */
 
 
 #if 0
-static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
+static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct usb_serial *serial = port->serial;
-	struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
+	struct mct_u232_private *priv =
+				(struct mct_u232_private *)port->private;
 	unsigned char lcr = priv->last_lcr;
 
 	dbg("%sstate=%d", __func__, break_state);
@@ -878,8 +874,9 @@
 } /* mct_u232_break_ctl */
 #endif
 
-static int klsi_105_tiocmget (struct usb_serial_port *port, struct file *file)
+static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct klsi_105_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	int rc;
@@ -893,18 +890,18 @@
 		return rc;
 	}
 
-	spin_lock_irqsave (&priv->lock, flags);
+	spin_lock_irqsave(&priv->lock, flags);
 	priv->line_state = line_state;
-	spin_unlock_irqrestore (&priv->lock, flags);
+	spin_unlock_irqrestore(&priv->lock, flags);
 	dbg("%s - read line state 0x%lx", __func__, line_state);
 	return (int)line_state;
 }
 
-static int klsi_105_tiocmset (struct usb_serial_port *port, struct file *file,
-			      unsigned int set, unsigned int clear)
+static int klsi_105_tiocmset(struct tty_struct *tty, struct file *file,
+			     unsigned int set, unsigned int clear)
 {
 	int retval = -EINVAL;
-	
+
 	dbg("%s", __func__);
 
 /* if this ever gets implemented, it should be done something like this:
@@ -929,14 +926,16 @@
 	return retval;
 }
 
-static void klsi_105_throttle (struct usb_serial_port *port)
+static void klsi_105_throttle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	dbg("%s - port %d", __func__, port->number);
 	usb_kill_urb(port->read_urb);
 }
 
-static void klsi_105_unthrottle (struct usb_serial_port *port)
+static void klsi_105_unthrottle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	int result;
 
 	dbg("%s - port %d", __func__, port->number);
@@ -950,7 +949,7 @@
 
 
 
-static int __init klsi_105_init (void)
+static int __init klsi_105_init(void)
 {
 	int retval;
 	retval = usb_serial_register(&kl5kusb105d_device);
@@ -969,19 +968,19 @@
 }
 
 
-static void __exit klsi_105_exit (void)
+static void __exit klsi_105_exit(void)
 {
-	usb_deregister (&kl5kusb105d_driver);
-	usb_serial_deregister (&kl5kusb105d_device);
+	usb_deregister(&kl5kusb105d_driver);
+	usb_serial_deregister(&kl5kusb105d_device);
 }
 
 
-module_init (klsi_105_init);
-module_exit (klsi_105_exit);
+module_init(klsi_105_init);
+module_exit(klsi_105_exit);
 
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL"); 
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
 
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index 693f00d..deba28ec 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -1,7 +1,7 @@
 /*
  *  KOBIL USB Smart Card Terminal Driver
  *
- *  Copyright (C) 2002  KOBIL Systems GmbH 
+ *  Copyright (C) 2002  KOBIL Systems GmbH
  *  Author: Thomas Wahrenbruch
  *
  *  Contact: linuxusb@kobil.de
@@ -20,7 +20,7 @@
  *
  * Supported readers: USB TWIN, KAAN Standard Plus and SecOVID Reader Plus
  * (Adapter K), B1 Professional and KAAN Professional (Adapter B)
- * 
+ *
  * (21/05/2004) tw
  *      Fix bug with P'n'P readers
  *
@@ -44,7 +44,7 @@
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 #include <linux/ioctl.h>
@@ -68,21 +68,24 @@
 
 
 /* Function prototypes */
-static int  kobil_startup (struct usb_serial *serial);
-static void kobil_shutdown (struct usb_serial *serial);
-static int  kobil_open (struct usb_serial_port *port, struct file *filp);
-static void kobil_close (struct usb_serial_port *port, struct file *filp);
-static int  kobil_write (struct usb_serial_port *port, 
+static int  kobil_startup(struct usb_serial *serial);
+static void kobil_shutdown(struct usb_serial *serial);
+static int  kobil_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
+static void kobil_close(struct tty_struct *tty, struct usb_serial_port *port,
+			struct file *filp);
+static int  kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
 			 const unsigned char *buf, int count);
-static int  kobil_write_room(struct usb_serial_port *port);
-static int  kobil_ioctl(struct usb_serial_port *port, struct file *file,
+static int  kobil_write_room(struct tty_struct *tty);
+static int  kobil_ioctl(struct tty_struct *tty, struct file *file,
 			unsigned int cmd, unsigned long arg);
-static int  kobil_tiocmget(struct usb_serial_port *port, struct file *file);
-static int  kobil_tiocmset(struct usb_serial_port *port, struct file *file,
+static int  kobil_tiocmget(struct tty_struct *tty, struct file *file);
+static int  kobil_tiocmset(struct tty_struct *tty, struct file *file,
 			   unsigned int set, unsigned int clear);
-static void kobil_read_int_callback( struct urb *urb );
-static void kobil_write_callback( struct urb *purb );
-static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old);
+static void kobil_read_int_callback(struct urb *urb);
+static void kobil_write_callback(struct urb *purb);
+static void kobil_set_termios(struct tty_struct *tty,
+			struct usb_serial_port *port, struct ktermios *old);
 
 
 static struct usb_device_id id_table [] = {
@@ -94,7 +97,7 @@
 };
 
 
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
 
 static struct usb_driver kobil_driver = {
 	.name =		"kobil",
@@ -131,14 +134,14 @@
 struct kobil_private {
 	int write_int_endpoint_address;
 	int read_int_endpoint_address;
-	unsigned char buf[KOBIL_BUF_LENGTH]; // buffer for the APDU to send
-	int filled;  // index of the last char in buf
-	int cur_pos; // index of the next char to send in buf
+	unsigned char buf[KOBIL_BUF_LENGTH]; /* buffer for the APDU to send */
+	int filled;  /* index of the last char in buf */
+	int cur_pos; /* index of the next char to send in buf */
 	__u16 device_type;
 };
 
 
-static int kobil_startup (struct usb_serial *serial)
+static int kobil_startup(struct usb_serial *serial)
 {
 	int i;
 	struct kobil_private *priv;
@@ -149,20 +152,20 @@
 	struct usb_host_endpoint *endpoint;
 
 	priv = kmalloc(sizeof(struct kobil_private), GFP_KERNEL);
-	if (!priv){
+	if (!priv)
 		return -ENOMEM;
-	}
 
 	priv->filled = 0;
 	priv->cur_pos = 0;
 	priv->device_type = le16_to_cpu(serial->dev->descriptor.idProduct);
 
-	switch (priv->device_type){
+	switch (priv->device_type) {
 	case KOBIL_ADAPTER_B_PRODUCT_ID:
 		printk(KERN_DEBUG "KOBIL B1 PRO / KAAN PRO detected\n");
 		break;
 	case KOBIL_ADAPTER_K_PRODUCT_ID:
-		printk(KERN_DEBUG "KOBIL KAAN Standard Plus / SecOVID Reader Plus detected\n");
+		printk(KERN_DEBUG
+		  "KOBIL KAAN Standard Plus / SecOVID Reader Plus detected\n");
 		break;
 	case KOBIL_USBTWIN_PRODUCT_ID:
 		printk(KERN_DEBUG "KOBIL USBTWIN detected\n");
@@ -173,44 +176,48 @@
 	}
 	usb_set_serial_port_data(serial->port[0], priv);
 
-	// search for the necessary endpoints
+	/* search for the necessary endpoints */
 	pdev = serial->dev;
- 	actconfig = pdev->actconfig;
- 	interface = actconfig->interface[0];
+	actconfig = pdev->actconfig;
+	interface = actconfig->interface[0];
 	altsetting = interface->cur_altsetting;
- 	endpoint = altsetting->endpoint;
-  
- 	for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
+	endpoint = altsetting->endpoint;
+
+	for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
 		endpoint = &altsetting->endpoint[i];
 		if (usb_endpoint_is_int_out(&endpoint->desc)) {
-		 	dbg("%s Found interrupt out endpoint. Address: %d", __func__, endpoint->desc.bEndpointAddress);
-		 	priv->write_int_endpoint_address = endpoint->desc.bEndpointAddress;
- 		}
+			dbg("%s Found interrupt out endpoint. Address: %d",
+				__func__, endpoint->desc.bEndpointAddress);
+			priv->write_int_endpoint_address =
+				endpoint->desc.bEndpointAddress;
+		}
 		if (usb_endpoint_is_int_in(&endpoint->desc)) {
-		 	dbg("%s Found interrupt in  endpoint. Address: %d", __func__, endpoint->desc.bEndpointAddress);
-		 	priv->read_int_endpoint_address = endpoint->desc.bEndpointAddress;
-	 	}
+			dbg("%s Found interrupt in  endpoint. Address: %d",
+				__func__, endpoint->desc.bEndpointAddress);
+			priv->read_int_endpoint_address =
+				endpoint->desc.bEndpointAddress;
+		}
 	}
 	return 0;
 }
 
 
-static void kobil_shutdown (struct usb_serial *serial)
+static void kobil_shutdown(struct usb_serial *serial)
 {
 	int i;
 	dbg("%s - port %d", __func__, serial->port[0]->number);
 
-	for (i=0; i < serial->num_ports; ++i) {
-		while (serial->port[i]->open_count > 0) {
-			kobil_close (serial->port[i], NULL);
-		}
+	for (i = 0; i < serial->num_ports; ++i) {
+		while (serial->port[i]->port.count > 0)
+			kobil_close(NULL, serial->port[i], NULL);
 		kfree(usb_get_serial_port_data(serial->port[i]));
 		usb_set_serial_port_data(serial->port[i], NULL);
 	}
 }
 
 
-static int kobil_open (struct usb_serial_port *port, struct file *filp)
+static int kobil_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	int result = 0;
 	struct kobil_private *priv;
@@ -221,7 +228,7 @@
 	dbg("%s - port %d", __func__, port->number);
 	priv = usb_get_serial_port_data(port);
 
-	// someone sets the dev to 0 if the close method has been called
+	/* someone sets the dev to 0 if the close method has been called */
 	port->interrupt_in_urb->dev = port->serial->dev;
 
 
@@ -229,100 +236,115 @@
 	 * the data through, otherwise it is scheduled, and with high
 	 * data rates (like with OHCI) data can get lost.
 	 */
-	port->tty->low_latency = 1;
+	if (tty) {
+		tty->low_latency = 1;
 
-	// without this, every push_tty_char is echoed :-(  
-	port->tty->termios->c_lflag = 0;
-	port->tty->termios->c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN | XCASE);
-	port->tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF;
-	port->tty->termios->c_oflag &= ~ONLCR; // do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D)
-	
-	// allocate memory for transfer buffer
-	transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
-	if (! transfer_buffer) {
-		return -ENOMEM;
+		/* Default to echo off and other sane device settings */
+		tty->termios->c_lflag = 0;
+		tty->termios->c_lflag &= ~(ISIG | ICANON | ECHO | IEXTEN |
+								 XCASE);
+		tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF;
+		/* do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D) */
+		tty->termios->c_oflag &= ~ONLCR;
 	}
-	
-	// allocate write_urb
-	if (!port->write_urb) { 
-		dbg("%s - port %d  Allocating port->write_urb", __func__, port->number);
-		port->write_urb = usb_alloc_urb(0, GFP_KERNEL);  
+	/* allocate memory for transfer buffer */
+	transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
+	if (!transfer_buffer)
+		return -ENOMEM;
+
+	/* allocate write_urb */
+	if (!port->write_urb) {
+		dbg("%s - port %d  Allocating port->write_urb",
+						__func__, port->number);
+		port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
 		if (!port->write_urb) {
-			dbg("%s - port %d usb_alloc_urb failed", __func__, port->number);
+			dbg("%s - port %d usb_alloc_urb failed",
+						__func__, port->number);
 			kfree(transfer_buffer);
 			return -ENOMEM;
 		}
 	}
 
-	// allocate memory for write_urb transfer buffer
-	port->write_urb->transfer_buffer = kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL);
-	if (! port->write_urb->transfer_buffer) {
+	/* allocate memory for write_urb transfer buffer */
+	port->write_urb->transfer_buffer =
+			kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL);
+	if (!port->write_urb->transfer_buffer) {
 		kfree(transfer_buffer);
 		usb_free_urb(port->write_urb);
 		port->write_urb = NULL;
 		return -ENOMEM;
-	} 
-
-	// get hardware version
-	result = usb_control_msg( port->serial->dev, 
-				  usb_rcvctrlpipe(port->serial->dev, 0 ), 
-				  SUSBCRequest_GetMisc,
-				  USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
-				  SUSBCR_MSC_GetHWVersion,
-				  0,
-				  transfer_buffer,
-				  transfer_buffer_length,
-				  KOBIL_TIMEOUT
-		);
-	dbg("%s - port %d Send get_HW_version URB returns: %i", __func__, port->number, result);
-	dbg("Harware version: %i.%i.%i", transfer_buffer[0], transfer_buffer[1], transfer_buffer[2] );
-	
-	// get firmware version
-	result = usb_control_msg( port->serial->dev, 
-				  usb_rcvctrlpipe(port->serial->dev, 0 ), 
-				  SUSBCRequest_GetMisc,
-				  USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
-				  SUSBCR_MSC_GetFWVersion,
-				  0,
-				  transfer_buffer,
-				  transfer_buffer_length,
-				  KOBIL_TIMEOUT
-		);
-	dbg("%s - port %d Send get_FW_version URB returns: %i", __func__, port->number, result);
-	dbg("Firmware version: %i.%i.%i", transfer_buffer[0], transfer_buffer[1], transfer_buffer[2] );
-
-	if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) {
-		// Setting Baudrate, Parity and Stopbits
-		result = usb_control_msg( port->serial->dev, 
-					  usb_rcvctrlpipe(port->serial->dev, 0 ), 
-					  SUSBCRequest_SetBaudRateParityAndStopBits,
-					  USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
-					  SUSBCR_SBR_9600 | SUSBCR_SPASB_EvenParity | SUSBCR_SPASB_1StopBit,
-					  0,
-					  transfer_buffer,
-					  0,
-					  KOBIL_TIMEOUT
-			);
-		dbg("%s - port %d Send set_baudrate URB returns: %i", __func__, port->number, result);
-		
-		// reset all queues
-		result = usb_control_msg( port->serial->dev, 
-					  usb_rcvctrlpipe(port->serial->dev, 0 ), 
-					  SUSBCRequest_Misc,
-					  USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
-					  SUSBCR_MSC_ResetAllQueues,
-					  0,
-					  transfer_buffer,
-					  0,
-					  KOBIL_TIMEOUT
-			);
-		dbg("%s - port %d Send reset_all_queues URB returns: %i", __func__, port->number, result);
 	}
-	if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
+
+	/* get hardware version */
+	result = usb_control_msg(port->serial->dev,
+			  usb_rcvctrlpipe(port->serial->dev, 0),
+			  SUSBCRequest_GetMisc,
+			  USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
+			  SUSBCR_MSC_GetHWVersion,
+			  0,
+			  transfer_buffer,
+			  transfer_buffer_length,
+			  KOBIL_TIMEOUT
+	);
+	dbg("%s - port %d Send get_HW_version URB returns: %i",
+		__func__, port->number, result);
+	dbg("Harware version: %i.%i.%i",
+		transfer_buffer[0], transfer_buffer[1], transfer_buffer[2]);
+
+	/* get firmware version */
+	result = usb_control_msg(port->serial->dev,
+			  usb_rcvctrlpipe(port->serial->dev, 0),
+			  SUSBCRequest_GetMisc,
+			  USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
+			  SUSBCR_MSC_GetFWVersion,
+			  0,
+			  transfer_buffer,
+			  transfer_buffer_length,
+			  KOBIL_TIMEOUT
+	);
+	dbg("%s - port %d Send get_FW_version URB returns: %i",
+					__func__, port->number, result);
+	dbg("Firmware version: %i.%i.%i",
+		transfer_buffer[0], transfer_buffer[1], transfer_buffer[2]);
+
+	if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
+			priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) {
+		/* Setting Baudrate, Parity and Stopbits */
+		result = usb_control_msg(port->serial->dev,
+			  usb_rcvctrlpipe(port->serial->dev, 0),
+			  SUSBCRequest_SetBaudRateParityAndStopBits,
+			  USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
+			  SUSBCR_SBR_9600 | SUSBCR_SPASB_EvenParity |
+							SUSBCR_SPASB_1StopBit,
+			  0,
+			  transfer_buffer,
+			  0,
+			  KOBIL_TIMEOUT
+		);
+		dbg("%s - port %d Send set_baudrate URB returns: %i",
+					__func__, port->number, result);
+
+		/* reset all queues */
+		result = usb_control_msg(port->serial->dev,
+			  usb_rcvctrlpipe(port->serial->dev, 0),
+			  SUSBCRequest_Misc,
+			  USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
+			  SUSBCR_MSC_ResetAllQueues,
+			  0,
+			  transfer_buffer,
+			  0,
+			  KOBIL_TIMEOUT
+		);
+		dbg("%s - port %d Send reset_all_queues URB returns: %i",
+					__func__, port->number, result);
+	}
+	if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID ||
+	    priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
 	    priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
-		// start reading (Adapter B 'cause PNP string)
-		result = usb_submit_urb( port->interrupt_in_urb, GFP_ATOMIC  ); 
-		dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result);
+		/* start reading (Adapter B 'cause PNP string) */
+		result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+		dbg("%s - port %d Send read URB returns: %i",
+					__func__, port->number, result);
 	}
 
 	kfree(transfer_buffer);
@@ -330,13 +352,14 @@
 }
 
 
-static void kobil_close (struct usb_serial_port *port, struct file *filp)
+static void kobil_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	dbg("%s - port %d", __func__, port->number);
 
 	if (port->write_urb) {
 		usb_kill_urb(port->write_urb);
-		usb_free_urb( port->write_urb );
+		usb_free_urb(port->write_urb);
 		port->write_urb = NULL;
 	}
 	usb_kill_urb(port->interrupt_in_urb);
@@ -350,7 +373,7 @@
 	struct tty_struct *tty;
 	unsigned char *data = urb->transfer_buffer;
 	int status = urb->status;
-//	char *dbg_data;
+/*	char *dbg_data; */
 
 	dbg("%s - port %d", __func__, port->number);
 
@@ -360,51 +383,53 @@
 		return;
 	}
 
-	tty = port->tty;
+	tty = port->port.tty;
 	if (urb->actual_length) {
 
-		// BEGIN DEBUG
+		/* BEGIN DEBUG */
 		/*
-		  dbg_data = kzalloc((3 *  purb->actual_length + 10) * sizeof(char), GFP_KERNEL);
+		  dbg_data = kzalloc((3 *  purb->actual_length + 10)
+						* sizeof(char), GFP_KERNEL);
 		  if (! dbg_data) {
-		  return;
+			  return;
 		  }
-		  for (i = 0; i < purb->actual_length; i++) { 
-		  sprintf(dbg_data +3*i, "%02X ", data[i]); 
+		  for (i = 0; i < purb->actual_length; i++) {
+			  sprintf(dbg_data +3*i, "%02X ", data[i]);
 		  }
-		  dbg(" <-- %s", dbg_data );
+		  dbg(" <-- %s", dbg_data);
 		  kfree(dbg_data);
 		*/
-		// END DEBUG
+		/* END DEBUG */
 
 		tty_buffer_request_room(tty, urb->actual_length);
 		tty_insert_flip_string(tty, data, urb->actual_length);
 		tty_flip_buffer_push(tty);
 	}
-
-	// someone sets the dev to 0 if the close method has been called
+	/* someone sets the dev to 0 if the close method has been called */
 	port->interrupt_in_urb->dev = port->serial->dev;
 
 	result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
-	dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result);
+	dbg("%s - port %d Send read URB returns: %i",
+			__func__, port->number, result);
 }
 
 
-static void kobil_write_callback( struct urb *purb )
+static void kobil_write_callback(struct urb *purb)
 {
 }
 
 
-static int kobil_write (struct usb_serial_port *port, 
+static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
 			const unsigned char *buf, int count)
 {
 	int length = 0;
 	int result = 0;
 	int todo = 0;
-	struct kobil_private * priv;
+	struct kobil_private *priv;
 
 	if (count == 0) {
-		dbg("%s - port %d write request of 0 bytes", __func__, port->number);
+		dbg("%s - port %d write request of 0 bytes",
+						__func__, port->number);
 		return 0;
 	}
 
@@ -415,106 +440,113 @@
 		return -ENOMEM;
 	}
 
-	// Copy data to buffer
-	memcpy (priv->buf + priv->filled, buf, count);
-
-	usb_serial_debug_data(debug, &port->dev, __func__, count, priv->buf + priv->filled);
-
+	/* Copy data to buffer */
+	memcpy(priv->buf + priv->filled, buf, count);
+	usb_serial_debug_data(debug, &port->dev, __func__, count,
+						priv->buf + priv->filled);
 	priv->filled = priv->filled + count;
 
-
-	// only send complete block. TWIN, KAAN SIM and adapter K use the same protocol.
-	if ( ((priv->device_type != KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 2) && (priv->filled >= (priv->buf[1] + 3))) || 
-	     ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 3) && (priv->filled >= (priv->buf[2] + 4))) ) {
-		
-		// stop reading (except TWIN and KAAN SIM)
-		if ( (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) || (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) )
+	/* only send complete block. TWIN, KAAN SIM and adapter K
+	   use the same protocol. */
+	if (((priv->device_type != KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 2) && (priv->filled >= (priv->buf[1] + 3))) ||
+	     ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 3) && (priv->filled >= (priv->buf[2] + 4)))) {
+		/* stop reading (except TWIN and KAAN SIM) */
+		if ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID)
+			|| (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID))
 			usb_kill_urb(port->interrupt_in_urb);
 
 		todo = priv->filled - priv->cur_pos;
 
-		while(todo > 0) {
-			// max 8 byte in one urb (endpoint size)
+		while (todo > 0) {
+			/* max 8 byte in one urb (endpoint size) */
 			length = (todo < 8) ? todo : 8;
-			// copy data to transfer buffer
-			memcpy(port->write_urb->transfer_buffer, priv->buf + priv->cur_pos, length );
-			usb_fill_int_urb( port->write_urb,
-					  port->serial->dev,
-					  usb_sndintpipe(port->serial->dev, priv->write_int_endpoint_address),
-					  port->write_urb->transfer_buffer,
-					  length,
-					  kobil_write_callback,
-					  port,
-					  8
-				);
+			/* copy data to transfer buffer */
+			memcpy(port->write_urb->transfer_buffer,
+					priv->buf + priv->cur_pos, length);
+			usb_fill_int_urb(port->write_urb,
+				  port->serial->dev,
+				  usb_sndintpipe(port->serial->dev,
+					priv->write_int_endpoint_address),
+				  port->write_urb->transfer_buffer,
+				  length,
+				  kobil_write_callback,
+				  port,
+				  8
+			);
 
 			priv->cur_pos = priv->cur_pos + length;
-			result = usb_submit_urb( port->write_urb, GFP_NOIO );
-			dbg("%s - port %d Send write URB returns: %i", __func__, port->number, result);
+			result = usb_submit_urb(port->write_urb, GFP_NOIO);
+			dbg("%s - port %d Send write URB returns: %i",
+					__func__, port->number, result);
 			todo = priv->filled - priv->cur_pos;
 
-			if (todo > 0) {
+			if (todo > 0)
 				msleep(24);
-			}
+		}
 
-		} // end while
-		
 		priv->filled = 0;
 		priv->cur_pos = 0;
 
-		// someone sets the dev to 0 if the close method has been called
+		/* someone sets the dev to 0 if the close method
+		   has been called */
 		port->interrupt_in_urb->dev = port->serial->dev;
-		
-		// start reading (except TWIN and KAAN SIM)
-		if ( (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) || (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) ) {
-			// someone sets the dev to 0 if the close method has been called
+
+		/* start reading (except TWIN and KAAN SIM) */
+		if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
+			priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) {
+			/* someone sets the dev to 0 if the close method has
+			   been called */
 			port->interrupt_in_urb->dev = port->serial->dev;
-			
-			result = usb_submit_urb( port->interrupt_in_urb, GFP_NOIO ); 
-			dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result);
+
+			result = usb_submit_urb(port->interrupt_in_urb,
+								GFP_NOIO);
+			dbg("%s - port %d Send read URB returns: %i",
+					__func__, port->number, result);
 		}
 	}
 	return count;
 }
 
 
-static int kobil_write_room (struct usb_serial_port *port)
+static int kobil_write_room(struct tty_struct *tty)
 {
-	//dbg("%s - port %d", __func__, port->number);
+	/* dbg("%s - port %d", __func__, port->number); */
+	/* FIXME */
 	return 8;
 }
 
 
-static int kobil_tiocmget(struct usb_serial_port *port, struct file *file)
+static int kobil_tiocmget(struct tty_struct *tty, struct file *file)
 {
-	struct kobil_private * priv;
+	struct usb_serial_port *port = tty->driver_data;
+	struct kobil_private *priv;
 	int result;
 	unsigned char *transfer_buffer;
 	int transfer_buffer_length = 8;
 
 	priv = usb_get_serial_port_data(port);
-	if ((priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) || (priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)) {
-		// This device doesn't support ioctl calls
+	if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID
+			|| priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
+		/* This device doesn't support ioctl calls */
 		return -EINVAL;
 	}
 
-	// allocate memory for transfer buffer
+	/* allocate memory for transfer buffer */
 	transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
-	if (!transfer_buffer) {
+	if (!transfer_buffer)
 		return -ENOMEM;
-	}
 
-	result = usb_control_msg( port->serial->dev, 
-				  usb_rcvctrlpipe(port->serial->dev, 0 ), 
-				  SUSBCRequest_GetStatusLineState,
-				  USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
-				  0,
-				  0,
-				  transfer_buffer,
-				  transfer_buffer_length,
-				  KOBIL_TIMEOUT);
+	result = usb_control_msg(port->serial->dev,
+			  usb_rcvctrlpipe(port->serial->dev, 0),
+			  SUSBCRequest_GetStatusLineState,
+			  USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
+			  0,
+			  0,
+			  transfer_buffer,
+			  transfer_buffer_length,
+			  KOBIL_TIMEOUT);
 
-	dbg("%s - port %d Send get_status_line_state URB returns: %i. Statusline: %02x", 
+	dbg("%s - port %d Send get_status_line_state URB returns: %i. Statusline: %02x",
 	    __func__, port->number, result, transfer_buffer[0]);
 
 	result = 0;
@@ -524,10 +556,11 @@
 	return result;
 }
 
-static int  kobil_tiocmset(struct usb_serial_port *port, struct file *file,
+static int kobil_tiocmset(struct tty_struct *tty, struct file *file,
 			   unsigned int set, unsigned int clear)
 {
-	struct kobil_private * priv;
+	struct usb_serial_port *port = tty->driver_data;
+	struct kobil_private *priv;
 	int result;
 	int dtr = 0;
 	int rts = 0;
@@ -536,16 +569,16 @@
 
 	/* FIXME: locking ? */
 	priv = usb_get_serial_port_data(port);
-	if ((priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) || (priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)) {
-		// This device doesn't support ioctl calls
+	if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID
+		|| priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
+		/* This device doesn't support ioctl calls */
 		return -EINVAL;
 	}
 
-	// allocate memory for transfer buffer
+	/* allocate memory for transfer buffer */
 	transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
-	if (! transfer_buffer) {
+	if (!transfer_buffer)
 		return -ENOMEM;
-	}
 
 	if (set & TIOCM_RTS)
 		rts = 1;
@@ -558,66 +591,77 @@
 
 	if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) {
 		if (dtr != 0)
-			dbg("%s - port %d Setting DTR", __func__, port->number);
+			dbg("%s - port %d Setting DTR",
+						__func__, port->number);
 		else
-			dbg("%s - port %d Clearing DTR", __func__, port->number);
-		result = usb_control_msg( port->serial->dev, 
-					  usb_rcvctrlpipe(port->serial->dev, 0 ), 
-					  SUSBCRequest_SetStatusLinesOrQueues,
-					  USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
-					  ((dtr != 0) ? SUSBCR_SSL_SETDTR : SUSBCR_SSL_CLRDTR),
-					  0,
-					  transfer_buffer,
-					  0,
-					  KOBIL_TIMEOUT);
+			dbg("%s - port %d Clearing DTR",
+						__func__, port->number);
+		result = usb_control_msg(port->serial->dev,
+			  usb_rcvctrlpipe(port->serial->dev, 0),
+			  SUSBCRequest_SetStatusLinesOrQueues,
+			  USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
+			  ((dtr != 0) ? SUSBCR_SSL_SETDTR : SUSBCR_SSL_CLRDTR),
+			  0,
+			  transfer_buffer,
+			  0,
+			  KOBIL_TIMEOUT);
 	} else {
 		if (rts != 0)
-			dbg("%s - port %d Setting RTS", __func__, port->number);
+			dbg("%s - port %d Setting RTS",
+						__func__, port->number);
 		else
-			dbg("%s - port %d Clearing RTS", __func__, port->number);
-		result = usb_control_msg( port->serial->dev, 
-					  usb_rcvctrlpipe(port->serial->dev, 0 ), 
-					  SUSBCRequest_SetStatusLinesOrQueues,
-					  USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
-					  ((rts != 0) ? SUSBCR_SSL_SETRTS : SUSBCR_SSL_CLRRTS),
-					  0,
-					  transfer_buffer,
-					  0,
-					  KOBIL_TIMEOUT);
+			dbg("%s - port %d Clearing RTS",
+						__func__, port->number);
+		result = usb_control_msg(port->serial->dev,
+			usb_rcvctrlpipe(port->serial->dev, 0),
+			SUSBCRequest_SetStatusLinesOrQueues,
+			USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
+			((rts != 0) ? SUSBCR_SSL_SETRTS : SUSBCR_SSL_CLRRTS),
+			0,
+			transfer_buffer,
+			0,
+			KOBIL_TIMEOUT);
 	}
-	dbg("%s - port %d Send set_status_line URB returns: %i", __func__, port->number, result);
+	dbg("%s - port %d Send set_status_line URB returns: %i",
+					__func__, port->number, result);
 	kfree(transfer_buffer);
 	return (result < 0) ? result : 0;
 }
 
-static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old)
+static void kobil_set_termios(struct tty_struct *tty,
+			struct usb_serial_port *port, struct ktermios *old)
 {
-	struct kobil_private * priv;
+	struct kobil_private *priv;
 	int result;
 	unsigned short urb_val = 0;
-	int c_cflag = port->tty->termios->c_cflag;
+	int c_cflag = tty->termios->c_cflag;
 	speed_t speed;
-	void * settings;
+	void *settings;
 
 	priv = usb_get_serial_port_data(port);
-	if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)
-		// This device doesn't support ioctl calls
+	if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID ||
+			priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
+		/* This device doesn't support ioctl calls */
+		*tty->termios = *old;
 		return;
-
-	switch (speed = tty_get_baud_rate(port->tty)) {
-		case 1200:
-			urb_val = SUSBCR_SBR_1200;
-			break;
-		default:
-			speed = 9600;
-		case 9600:
-			urb_val = SUSBCR_SBR_9600;
-			break;
 	}
-	urb_val |= (c_cflag & CSTOPB) ? SUSBCR_SPASB_2StopBits : SUSBCR_SPASB_1StopBit;
+
+	speed = tty_get_baud_rate(tty);
+	switch (speed) {
+	case 1200:
+		urb_val = SUSBCR_SBR_1200;
+		break;
+	default:
+		speed = 9600;
+	case 9600:
+		urb_val = SUSBCR_SBR_9600;
+		break;
+	}
+	urb_val |= (c_cflag & CSTOPB) ? SUSBCR_SPASB_2StopBits :
+							SUSBCR_SPASB_1StopBit;
 
 	settings = kzalloc(50, GFP_KERNEL);
-	if (! settings)
+	if (!settings)
 		return;
 
 	sprintf(settings, "%d ", speed);
@@ -634,66 +678,69 @@
 		urb_val |= SUSBCR_SPASB_NoParity;
 		strcat(settings, "No Parity");
 	}
-	port->tty->termios->c_cflag &= ~CMSPAR;
-	tty_encode_baud_rate(port->tty, speed, speed);
+	tty->termios->c_cflag &= ~CMSPAR;
+	tty_encode_baud_rate(tty, speed, speed);
 
-	result = usb_control_msg( port->serial->dev,
-				  usb_rcvctrlpipe(port->serial->dev, 0 ),
-				  SUSBCRequest_SetBaudRateParityAndStopBits,
-				  USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
-				  urb_val,
-				  0,
-				  settings,
-				  0,
-				  KOBIL_TIMEOUT
+	result = usb_control_msg(port->serial->dev,
+		  usb_rcvctrlpipe(port->serial->dev, 0),
+		  SUSBCRequest_SetBaudRateParityAndStopBits,
+		  USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
+		  urb_val,
+		  0,
+		  settings,
+		  0,
+		  KOBIL_TIMEOUT
 		);
 	kfree(settings);
 }
 
-static int kobil_ioctl(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+static int kobil_ioctl(struct tty_struct *tty, struct file *file,
+					unsigned int cmd, unsigned long arg)
 {
-	struct kobil_private * priv = usb_get_serial_port_data(port);
+	struct usb_serial_port *port = tty->driver_data;
+	struct kobil_private *priv = usb_get_serial_port_data(port);
 	unsigned char *transfer_buffer;
 	int transfer_buffer_length = 8;
 	int result;
 
-	if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)
-		// This device doesn't support ioctl calls
-		return 0;
+	if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID ||
+			priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)
+		/* This device doesn't support ioctl calls */
+		return -ENOIOCTLCMD;
 
 	switch (cmd) {
-	case TCFLSH:   // 0x540B
+	case TCFLSH:
 		transfer_buffer = kmalloc(transfer_buffer_length, GFP_KERNEL);
-		if (! transfer_buffer)
-		 	return -ENOBUFS;
+		if (!transfer_buffer)
+			return -ENOBUFS;
 
-		result = usb_control_msg( port->serial->dev, 
-		 			  usb_rcvctrlpipe(port->serial->dev, 0 ), 
-					  SUSBCRequest_Misc,
-					  USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
-					  SUSBCR_MSC_ResetAllQueues,
-					  0,
-					  NULL,//transfer_buffer,
-					  0,
-					  KOBIL_TIMEOUT
+		result = usb_control_msg(port->serial->dev,
+			  usb_rcvctrlpipe(port->serial->dev, 0),
+			  SUSBCRequest_Misc,
+			  USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
+			  SUSBCR_MSC_ResetAllQueues,
+			  0,
+			  NULL, /* transfer_buffer, */
+			  0,
+			  KOBIL_TIMEOUT
 			);
-		
+
 		dbg("%s - port %d Send reset_all_queues (FLUSH) URB returns: %i", __func__, port->number, result);
 		kfree(transfer_buffer);
-		return (result < 0) ? -EFAULT : 0;
+		return (result < 0) ? -EIO: 0;
 	default:
 		return -ENOIOCTLCMD;
 	}
 }
 
-static int __init kobil_init (void)
+static int __init kobil_init(void)
 {
 	int retval;
 	retval = usb_serial_register(&kobil_device);
 	if (retval)
 		goto failed_usb_serial_register;
 	retval = usb_register(&kobil_driver);
-	if (retval) 
+	if (retval)
 		goto failed_usb_register;
 
 	info(DRIVER_VERSION " " DRIVER_AUTHOR);
@@ -707,18 +754,18 @@
 }
 
 
-static void __exit kobil_exit (void)
+static void __exit kobil_exit(void)
 {
-	usb_deregister (&kobil_driver);
-	usb_serial_deregister (&kobil_device);
+	usb_deregister(&kobil_driver);
+	usb_serial_deregister(&kobil_device);
 }
 
 module_init(kobil_init);
 module_exit(kobil_exit);
 
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE( "GPL" );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 5fc2cef..0ded8bd 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -33,10 +33,11 @@
  *   - Fixed an endianess problem with the baudrate selection for PowerPC.
  *
  * 06-Dec-2001 Martin Hamilton <martinh@gnu.org>
- *	Added support for the Belkin F5U109 DB9 adaptor
+ *   - Added support for the Belkin F5U109 DB9 adaptor
  *
  * 30-May-2001 Greg Kroah-Hartman
- *	switched from using spinlock to a semaphore, which fixes lots of problems.
+ *   - switched from using spinlock to a semaphore, which fixes lots of
+ *     problems.
  *
  * 04-May-2001 Stelian Pop
  *   - Set the maximum bulk output size for Sitecom U232-P25 model to 16 bytes
@@ -49,7 +50,7 @@
  * 08-Apr-2001 gb
  *   - Identify version on module load.
  *
- * 06-Jan-2001 Cornel Ciocirlan 
+ * 06-Jan-2001 Cornel Ciocirlan
  *   - Added support for Sitecom U232-P25 model (Product Id 0x0230)
  *   - Added support for D-Link DU-H3SP USB BAY (Product Id 0x0200)
  *
@@ -59,8 +60,8 @@
  *     (lots of things will change if/when the usb-serial core changes to
  *     handle these issues.
  *
- * 27-Nov-2000 Wolfgang Grandegger
- *   A version for kernel 2.4.0-test10 released to the Linux community 
+ * 27-Nov-2000 Wolfgang Grandegge
+ *   A version for kernel 2.4.0-test10 released to the Linux community
  *   (via linux-usb-devel).
  */
 
@@ -73,7 +74,7 @@
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 #include "mct_u232.h"
@@ -90,28 +91,21 @@
 /*
  * Function prototypes
  */
-static int  mct_u232_startup	         (struct usb_serial *serial);
-static void mct_u232_shutdown	         (struct usb_serial *serial);
-static int  mct_u232_open	         (struct usb_serial_port *port,
-					  struct file *filp);
-static void mct_u232_close	         (struct usb_serial_port *port,
-					  struct file *filp);
-static void mct_u232_read_int_callback   (struct urb *urb);
-static void mct_u232_set_termios         (struct usb_serial_port *port,
-					  struct ktermios * old);
-static int  mct_u232_ioctl	         (struct usb_serial_port *port,
-					  struct file * file,
-					  unsigned int cmd,
-					  unsigned long arg);
-static void mct_u232_break_ctl	         (struct usb_serial_port *port,
-					  int break_state );
-static int  mct_u232_tiocmget		 (struct usb_serial_port *port,
-					  struct file *file);
-static int  mct_u232_tiocmset		 (struct usb_serial_port *port,
-					  struct file *file, unsigned int set,
-					  unsigned int clear);
-static void mct_u232_throttle		 (struct usb_serial_port *port);
-static void mct_u232_unthrottle		 (struct usb_serial_port *port);
+static int  mct_u232_startup(struct usb_serial *serial);
+static void mct_u232_shutdown(struct usb_serial *serial);
+static int  mct_u232_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
+static void mct_u232_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
+static void mct_u232_read_int_callback(struct urb *urb);
+static void mct_u232_set_termios(struct tty_struct *tty,
+			struct usb_serial_port *port, struct ktermios *old);
+static void mct_u232_break_ctl(struct tty_struct *tty, int break_state);
+static int  mct_u232_tiocmget(struct tty_struct *tty, struct file *file);
+static int  mct_u232_tiocmset(struct tty_struct *tty, struct file *file,
+			unsigned int set, unsigned int clear);
+static void mct_u232_throttle(struct tty_struct *tty);
+static void mct_u232_unthrottle(struct tty_struct *tty);
 
 
 /*
@@ -125,7 +119,7 @@
 	{ }		/* Terminating entry */
 };
 
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
 
 static struct usb_driver mct_u232_driver = {
 	.name =		"mct_u232",
@@ -149,7 +143,6 @@
 	.throttle =	     mct_u232_throttle,
 	.unthrottle =	     mct_u232_unthrottle,
 	.read_int_callback = mct_u232_read_int_callback,
-	.ioctl =	     mct_u232_ioctl,
 	.set_termios =	     mct_u232_set_termios,
 	.break_ctl =	     mct_u232_break_ctl,
 	.tiocmget =	     mct_u232_tiocmget,
@@ -180,23 +173,34 @@
  * Later day 2.6.0-test kernels have new baud rates like B230400 which
  * we do not know how to support. We ignore them for the moment.
  */
-static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value, speed_t *result)
+static int mct_u232_calculate_baud_rate(struct usb_serial *serial,
+					speed_t value, speed_t *result)
 {
 	*result = value;
 
 	if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID
-	  || le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_BELKIN_F5U109_PID) {
+		|| le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_BELKIN_F5U109_PID) {
 		switch (value) {
-		case    300: return 0x01;
-		case    600: return 0x02; /* this one not tested */
-		case   1200: return 0x03;
-		case   2400: return 0x04;
-		case   4800: return 0x06;
-		case   9600: return 0x08;
-		case  19200: return 0x09;
-		case  38400: return 0x0a;
-		case  57600: return 0x0b;
-		case 115200: return 0x0c;
+		case 300:
+			return 0x01;
+		case 600:
+			return 0x02; /* this one not tested */
+		case 1200:
+			return 0x03;
+		case 2400:
+			return 0x04;
+		case 4800:
+			return 0x06;
+		case 9600:
+			return 0x08;
+		case 19200:
+			return 0x09;
+		case 38400:
+			return 0x0a;
+		case 57600:
+			return 0x0b;
+		case 115200:
+			return 0x0c;
 		default:
 			*result = 9600;
 			return 0x08;
@@ -224,26 +228,27 @@
 	}
 }
 
-static int mct_u232_set_baud_rate(struct usb_serial *serial, struct usb_serial_port *port,
-				  speed_t value)
+static int mct_u232_set_baud_rate(struct tty_struct *tty,
+	struct usb_serial *serial, struct usb_serial_port *port, speed_t value)
 {
 	__le32 divisor;
-        int rc;
-        unsigned char zero_byte = 0;
-        unsigned char cts_enable_byte = 0;
-        speed_t speed;
+	int rc;
+	unsigned char zero_byte = 0;
+	unsigned char cts_enable_byte = 0;
+	speed_t speed;
 
-	divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value, &speed));
+	divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value,
+								&speed));
 
-        rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-                             MCT_U232_SET_BAUD_RATE_REQUEST,
-			     MCT_U232_SET_REQUEST_TYPE,
-                             0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE,
-			     WDR_TIMEOUT);
+	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+				MCT_U232_SET_BAUD_RATE_REQUEST,
+				MCT_U232_SET_REQUEST_TYPE,
+				0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE,
+				WDR_TIMEOUT);
 	if (rc < 0)	/*FIXME: What value speed results */
 		err("Set BAUD RATE %d failed (error = %d)", value, rc);
 	else
-		tty_encode_baud_rate(port->tty, speed, speed);
+		tty_encode_baud_rate(tty, speed, speed);
 	dbg("set_baud_rate: value: 0x%x, divisor: 0x%x", value, divisor);
 
 	/* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which
@@ -258,55 +263,55 @@
 	   whether data will be transmitted to a device which is not asserting
 	   the 'CTS' signal.  If the second message's data byte is zero, data
 	   will be transmitted even if 'CTS' is not asserted (i.e. no hardware
-	   flow control).  if the second message's data byte is nonzero (a value
-	   of 1 is used by this driver), data will not be transmitted to a device
-	   which is not asserting 'CTS'.
+	   flow control).  if the second message's data byte is nonzero (a
+	   value of 1 is used by this driver), data will not be transmitted to
+	   a device which is not asserting 'CTS'.
 	*/
 
 	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-			     MCT_U232_SET_UNKNOWN1_REQUEST, 
-			     MCT_U232_SET_REQUEST_TYPE,
-			     0, 0, &zero_byte, MCT_U232_SET_UNKNOWN1_SIZE, 
-			     WDR_TIMEOUT);
+				MCT_U232_SET_UNKNOWN1_REQUEST,
+				MCT_U232_SET_REQUEST_TYPE,
+				0, 0, &zero_byte, MCT_U232_SET_UNKNOWN1_SIZE,
+				WDR_TIMEOUT);
 	if (rc < 0)
-		err("Sending USB device request code %d failed (error = %d)", 
+		err("Sending USB device request code %d failed (error = %d)",
 		    MCT_U232_SET_UNKNOWN1_REQUEST, rc);
 
-	if (port && C_CRTSCTS(port->tty)) {
+	if (port && C_CRTSCTS(tty))
 	   cts_enable_byte = 1;
-	}
 
-        dbg("set_baud_rate: send second control message, data = %02X", cts_enable_byte);
+	dbg("set_baud_rate: send second control message, data = %02X",
+							cts_enable_byte);
 	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-			     MCT_U232_SET_CTS_REQUEST,
-			     MCT_U232_SET_REQUEST_TYPE,
-			     0, 0, &cts_enable_byte, MCT_U232_SET_CTS_SIZE,
-			     WDR_TIMEOUT);
+			MCT_U232_SET_CTS_REQUEST,
+			MCT_U232_SET_REQUEST_TYPE,
+			0, 0, &cts_enable_byte, MCT_U232_SET_CTS_SIZE,
+			WDR_TIMEOUT);
 	if (rc < 0)
-	  err("Sending USB device request code %d failed (error = %d)",
-	      MCT_U232_SET_CTS_REQUEST, rc);
+		err("Sending USB device request code %d failed (error = %d)",
+					MCT_U232_SET_CTS_REQUEST, rc);
 
-        return rc;
+	return rc;
 } /* mct_u232_set_baud_rate */
 
 static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr)
 {
-        int rc;
-        rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-                             MCT_U232_SET_LINE_CTRL_REQUEST,
-			     MCT_U232_SET_REQUEST_TYPE,
-                             0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE,
-			     WDR_TIMEOUT);
+	int rc;
+	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			MCT_U232_SET_LINE_CTRL_REQUEST,
+			MCT_U232_SET_REQUEST_TYPE,
+			0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE,
+			WDR_TIMEOUT);
 	if (rc < 0)
 		err("Set LINE CTRL 0x%x failed (error = %d)", lcr, rc);
 	dbg("set_line_ctrl: 0x%x", lcr);
-        return rc;
+	return rc;
 } /* mct_u232_set_line_ctrl */
 
 static int mct_u232_set_modem_ctrl(struct usb_serial *serial,
 				   unsigned int control_state)
 {
-        int rc;
+	int rc;
 	unsigned char mcr = MCT_U232_MCR_NONE;
 
 	if (control_state & TIOCM_DTR)
@@ -314,37 +319,39 @@
 	if (control_state & TIOCM_RTS)
 		mcr |= MCT_U232_MCR_RTS;
 
-        rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-                             MCT_U232_SET_MODEM_CTRL_REQUEST,
-			     MCT_U232_SET_REQUEST_TYPE,
-                             0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE,
-			     WDR_TIMEOUT);
+	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			MCT_U232_SET_MODEM_CTRL_REQUEST,
+			MCT_U232_SET_REQUEST_TYPE,
+			0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE,
+			WDR_TIMEOUT);
 	if (rc < 0)
 		err("Set MODEM CTRL 0x%x failed (error = %d)", mcr, rc);
 	dbg("set_modem_ctrl: state=0x%x ==> mcr=0x%x", control_state, mcr);
 
-        return rc;
+	return rc;
 } /* mct_u232_set_modem_ctrl */
 
-static int mct_u232_get_modem_stat(struct usb_serial *serial, unsigned char *msr)
+static int mct_u232_get_modem_stat(struct usb_serial *serial,
+						unsigned char *msr)
 {
-        int rc;
-        rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
-                             MCT_U232_GET_MODEM_STAT_REQUEST,
-			     MCT_U232_GET_REQUEST_TYPE,
-                             0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE,
-			     WDR_TIMEOUT);
+	int rc;
+	rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+			MCT_U232_GET_MODEM_STAT_REQUEST,
+			MCT_U232_GET_REQUEST_TYPE,
+			0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE,
+			WDR_TIMEOUT);
 	if (rc < 0) {
 		err("Get MODEM STATus failed (error = %d)", rc);
 		*msr = 0;
 	}
 	dbg("get_modem_stat: 0x%x", *msr);
-        return rc;
+	return rc;
 } /* mct_u232_get_modem_stat */
 
-static void mct_u232_msr_to_state(unsigned int *control_state, unsigned char msr)
+static void mct_u232_msr_to_state(unsigned int *control_state,
+						unsigned char msr)
 {
- 	/* Translate Control Line states */
+	/* Translate Control Line states */
 	if (msr & MCT_U232_MSR_DSR)
 		*control_state |=  TIOCM_DSR;
 	else
@@ -361,14 +368,14 @@
 		*control_state |=  TIOCM_CD;
 	else
 		*control_state &= ~TIOCM_CD;
- 	dbg("msr_to_state: msr=0x%x ==> state=0x%x", msr, *control_state);
+	dbg("msr_to_state: msr=0x%x ==> state=0x%x", msr, *control_state);
 } /* mct_u232_msr_to_state */
 
 /*
  * Driver's tty interface functions
  */
 
-static int mct_u232_startup (struct usb_serial *serial)
+static int mct_u232_startup(struct usb_serial *serial)
 {
 	struct mct_u232_private *priv;
 	struct usb_serial_port *port, *rport;
@@ -390,18 +397,18 @@
 	rport->interrupt_in_urb = NULL;
 	port->read_urb->context = port;
 
-	return (0);
+	return 0;
 } /* mct_u232_startup */
 
 
-static void mct_u232_shutdown (struct usb_serial *serial)
+static void mct_u232_shutdown(struct usb_serial *serial)
 {
 	struct mct_u232_private *priv;
 	int i;
-	
+
 	dbg("%s", __func__);
 
-	for (i=0; i < serial->num_ports; ++i) {
+	for (i = 0; i < serial->num_ports; ++i) {
 		/* My special items, the standard routines free my urbs */
 		priv = usb_get_serial_port_data(serial->port[i]);
 		if (priv) {
@@ -411,7 +418,8 @@
 	}
 } /* mct_u232_shutdown */
 
-static int  mct_u232_open (struct usb_serial_port *port, struct file *filp)
+static int  mct_u232_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct usb_serial *serial = port->serial;
 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
@@ -428,21 +436,22 @@
 	 * it seems to be able to accept only 16 bytes (and that's what
 	 * SniffUSB says too...)
 	 */
-	if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID)
+	if (le16_to_cpu(serial->dev->descriptor.idProduct)
+						== MCT_U232_SITECOM_PID)
 		port->bulk_out_size = 16;
 
-	/* Do a defined restart: the normal serial device seems to 
+	/* Do a defined restart: the normal serial device seems to
 	 * always turn on DTR and RTS here, so do the same. I'm not
 	 * sure if this is really necessary. But it should not harm
 	 * either.
 	 */
 	spin_lock_irqsave(&priv->lock, flags);
-	if (port->tty->termios->c_cflag & CBAUD)
+	if (tty && (tty->termios->c_cflag & CBAUD))
 		priv->control_state = TIOCM_DTR | TIOCM_RTS;
 	else
 		priv->control_state = 0;
-	
-	priv->last_lcr = (MCT_U232_DATA_BITS_8 | 
+
+	priv->last_lcr = (MCT_U232_DATA_BITS_8 |
 			  MCT_U232_PARITY_NONE |
 			  MCT_U232_STOP_BITS_1);
 	control_state = priv->control_state;
@@ -481,15 +490,16 @@
 } /* mct_u232_open */
 
 
-static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
+static void mct_u232_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	unsigned int c_cflag;
 	unsigned int control_state;
 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
 	dbg("%s port %d", __func__, port->number);
 
-   	if (port->tty) {
-		c_cflag = port->tty->termios->c_cflag;
+	if (tty) {
+		c_cflag = tty->termios->c_cflag;
 		mutex_lock(&port->serial->disc_mutex);
 		if (c_cflag & HUPCL && !port->serial->disconnected) {
 			/* drop DTR and RTS */
@@ -512,7 +522,7 @@
 } /* mct_u232_close */
 
 
-static void mct_u232_read_int_callback (struct urb *urb)
+static void mct_u232_read_int_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
@@ -545,36 +555,34 @@
 		return;
 	}
 
-        dbg("%s - port %d", __func__, port->number);
-	usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+	dbg("%s - port %d", __func__, port->number);
+	usb_serial_debug_data(debug, &port->dev, __func__,
+					urb->actual_length, data);
 
 	/*
 	 * Work-a-round: handle the 'usual' bulk-in pipe here
 	 */
 	if (urb->transfer_buffer_length > 2) {
-		int i;
-		tty = port->tty;
+		tty = port->port.tty;
 		if (urb->actual_length) {
-			for (i = 0; i < urb->actual_length ; ++i) {
-				tty_insert_flip_char(tty, data[i], 0);
-			}
+			tty_insert_flip_string(tty, data, urb->actual_length);
 			tty_flip_buffer_push(tty);
 		}
 		goto exit;
 	}
-	
+
 	/*
 	 * The interrupt-in pipe signals exceptional conditions (modem line
 	 * signal changes and errors). data[0] holds MSR, data[1] holds LSR.
 	 */
 	spin_lock_irqsave(&priv->lock, flags);
 	priv->last_msr = data[MCT_U232_MSR_INDEX];
-	
+
 	/* Record Control Line states */
 	mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
 
 #if 0
-	/* Not yet handled. See belin_sa.c for further information */
+	/* Not yet handled. See belkin_sa.c for further information */
 	/* Now to report any errors */
 	priv->last_lsr = data[MCT_U232_LSR_INDEX];
 	/*
@@ -583,7 +591,7 @@
 	 * to look in to this before committing any code.
 	 */
 	if (priv->last_lsr & MCT_U232_LSR_ERR) {
-		tty = port->tty;
+		tty = port->port.tty;
 		/* Overrun Error */
 		if (priv->last_lsr & MCT_U232_LSR_OE) {
 		}
@@ -600,18 +608,19 @@
 #endif
 	spin_unlock_irqrestore(&priv->lock, flags);
 exit:
-	retval = usb_submit_urb (urb, GFP_ATOMIC);
+	retval = usb_submit_urb(urb, GFP_ATOMIC);
 	if (retval)
-		err ("%s - usb_submit_urb failed with result %d",
+		err("%s - usb_submit_urb failed with result %d",
 		     __func__, retval);
 } /* mct_u232_read_int_callback */
 
-static void mct_u232_set_termios (struct usb_serial_port *port,
-				  struct ktermios *old_termios)
+static void mct_u232_set_termios(struct tty_struct *tty,
+				 struct usb_serial_port *port,
+				 struct ktermios *old_termios)
 {
 	struct usb_serial *serial = port->serial;
 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
-	struct ktermios *termios = port->tty->termios;
+	struct ktermios *termios = tty->termios;
 	unsigned int cflag = termios->c_cflag;
 	unsigned int old_cflag = old_termios->c_cflag;
 	unsigned long flags;
@@ -631,20 +640,20 @@
 	 * Premature optimization is the root of all evil.
 	 */
 
-        /* reassert DTR and RTS on transition from B0 */
+	/* reassert DTR and RTS on transition from B0 */
 	if ((old_cflag & CBAUD) == B0) {
 		dbg("%s: baud was B0", __func__);
 		control_state |= TIOCM_DTR | TIOCM_RTS;
 		mct_u232_set_modem_ctrl(serial, control_state);
 	}
 
-	mct_u232_set_baud_rate(serial, port, tty_get_baud_rate(port->tty));
+	mct_u232_set_baud_rate(tty, serial, port, tty_get_baud_rate(tty));
 
-	if ((cflag & CBAUD) == B0 ) {
+	if ((cflag & CBAUD) == B0) {
 		dbg("%s: baud is B0", __func__);
 		/* Drop RTS and DTR */
 		control_state &= ~(TIOCM_DTR | TIOCM_RTS);
-       		mct_u232_set_modem_ctrl(serial, control_state);
+		mct_u232_set_modem_ctrl(serial, control_state);
 	}
 
 	/*
@@ -689,8 +698,9 @@
 	spin_unlock_irqrestore(&priv->lock, flags);
 } /* mct_u232_set_termios */
 
-static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
+static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct usb_serial *serial = port->serial;
 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
 	unsigned char lcr;
@@ -709,12 +719,13 @@
 } /* mct_u232_break_ctl */
 
 
-static int mct_u232_tiocmget (struct usb_serial_port *port, struct file *file)
+static int mct_u232_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
 	unsigned int control_state;
 	unsigned long flags;
-	
+
 	dbg("%s", __func__);
 
 	spin_lock_irqsave(&priv->lock, flags);
@@ -724,14 +735,15 @@
 	return control_state;
 }
 
-static int mct_u232_tiocmset (struct usb_serial_port *port, struct file *file,
+static int mct_u232_tiocmset(struct tty_struct *tty, struct file *file,
 			      unsigned int set, unsigned int clear)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct usb_serial *serial = port->serial;
 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
 	unsigned int control_state;
 	unsigned long flags;
-	
+
 	dbg("%s", __func__);
 
 	spin_lock_irqsave(&priv->lock, flags);
@@ -751,77 +763,50 @@
 	return mct_u232_set_modem_ctrl(serial, control_state);
 }
 
-static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
-			   unsigned int cmd, unsigned long arg)
+static void mct_u232_throttle(struct tty_struct *tty)
 {
-	dbg("%scmd=0x%x", __func__, cmd);
-
-	/* Based on code from acm.c and others */
-	switch (cmd) {
-	case TIOCMIWAIT:
-		/* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
-		/* TODO */
-		return( 0 );
-
-	case TIOCGICOUNT:
-		/* return count of modemline transitions */
-		/* TODO */
-		return 0;
-
-	default:
-		dbg("%s: arg not supported - 0x%04x", __func__,cmd);
-		return(-ENOIOCTLCMD);
-		break;
-	}
-	return 0;
-} /* mct_u232_ioctl */
-
-static void mct_u232_throttle (struct usb_serial_port *port)
-{
+	struct usb_serial_port *port = tty->driver_data;
 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	unsigned int control_state;
-	struct tty_struct *tty;
 
-	tty = port->tty;
 	dbg("%s - port %d", __func__, port->number);
 
 	spin_lock_irqsave(&priv->lock, flags);
 	priv->rx_flags |= THROTTLED;
 	if (C_CRTSCTS(tty)) {
-	  priv->control_state &= ~TIOCM_RTS;
-	  control_state = priv->control_state;
-	  spin_unlock_irqrestore(&priv->lock, flags);
-	  (void) mct_u232_set_modem_ctrl(port->serial, control_state);
+		priv->control_state &= ~TIOCM_RTS;
+		control_state = priv->control_state;
+		spin_unlock_irqrestore(&priv->lock, flags);
+		(void) mct_u232_set_modem_ctrl(port->serial, control_state);
 	} else {
-	  spin_unlock_irqrestore(&priv->lock, flags);
+		spin_unlock_irqrestore(&priv->lock, flags);
 	}
 }
 
 
-static void mct_u232_unthrottle (struct usb_serial_port *port)
+static void mct_u232_unthrottle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	unsigned int control_state;
-	struct tty_struct *tty;
 
 	dbg("%s - port %d", __func__, port->number);
 
-	tty = port->tty;
 	spin_lock_irqsave(&priv->lock, flags);
 	if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) {
-	  priv->rx_flags &= ~THROTTLED;
-	  priv->control_state |= TIOCM_RTS;
-	  control_state = priv->control_state;
-	  spin_unlock_irqrestore(&priv->lock, flags);
-	  (void) mct_u232_set_modem_ctrl(port->serial, control_state);
+		priv->rx_flags &= ~THROTTLED;
+		priv->control_state |= TIOCM_RTS;
+		control_state = priv->control_state;
+		spin_unlock_irqrestore(&priv->lock, flags);
+		(void) mct_u232_set_modem_ctrl(port->serial, control_state);
 	} else {
-	  spin_unlock_irqrestore(&priv->lock, flags);
+		spin_unlock_irqrestore(&priv->lock, flags);
 	}
 }
 
-static int __init mct_u232_init (void)
+static int __init mct_u232_init(void)
 {
 	int retval;
 	retval = usb_serial_register(&mct_u232_device);
@@ -839,18 +824,17 @@
 }
 
 
-static void __exit mct_u232_exit (void)
+static void __exit mct_u232_exit(void)
 {
-	usb_deregister (&mct_u232_driver);
-	usb_serial_deregister (&mct_u232_device);
+	usb_deregister(&mct_u232_driver);
+	usb_serial_deregister(&mct_u232_device);
 }
 
-
-module_init (mct_u232_init);
+module_init(mct_u232_init);
 module_exit(mct_u232_exit);
 
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 50f1fe2..7c4917d 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -33,7 +33,7 @@
 #include <linux/serial_reg.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 
 /*
@@ -64,8 +64,7 @@
 #define URB_TRANSFER_BUFFER_SIZE	32	/* URB Size */
 
 /* This structure holds all of the local port information */
-struct moschip_port
-{
+struct moschip_port {
 	__u8	shadowLCR;		/* last LCR value received */
 	__u8	shadowMCR;		/* last MCR value received */
 	__u8	shadowMSR;		/* last MSR value received */
@@ -76,8 +75,7 @@
 };
 
 /* This structure holds all of the individual serial device information */
-struct moschip_serial
-{
+struct moschip_serial {
 	int interrupt_started;
 };
 
@@ -88,7 +86,7 @@
 #define MOSCHIP_DEVICE_ID_7715		0x7715
 
 static struct usb_device_id moschip_port_id_table [] = {
-	{ USB_DEVICE(USB_VENDOR_ID_MOSCHIP,MOSCHIP_DEVICE_ID_7720) },
+	{ USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7720) },
 	{ } /* terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, moschip_port_id_table);
@@ -108,7 +106,7 @@
 	__u8 sp1;
 	__u8 sp2;
 
-	dbg("%s"," : Entering\n");
+	dbg("%s", " : Entering\n");
 
 	switch (status) {
 	case 0:
@@ -208,7 +206,7 @@
 
 	mos7720_port = urb->context;
 	if (!mos7720_port) {
-		dbg("%s","NULL mos7720_port pointer \n");
+		dbg("%s", "NULL mos7720_port pointer \n");
 		return ;
 	}
 
@@ -218,7 +216,7 @@
 
 	data = urb->transfer_buffer;
 
-	tty = port->tty;
+	tty = port->port.tty;
 	if (tty && urb->actual_length) {
 		tty_buffer_request_room(tty, urb->actual_length);
 		tty_insert_flip_string(tty, data, urb->actual_length);
@@ -264,7 +262,7 @@
 
 	dbg("Entering .........");
 
-	tty = mos7720_port->port->tty;
+	tty = mos7720_port->port->port.tty;
 
 	if (tty && mos7720_port->open)
 		tty_wakeup(tty);
@@ -284,17 +282,16 @@
 	__u16 size = 0x0000;
 
 	if (value < MOS_MAX_PORT) {
-		if (product == MOSCHIP_DEVICE_ID_7715) {
+		if (product == MOSCHIP_DEVICE_ID_7715)
 			value = value*0x100+0x100;
-		} else {
+		else
 			value = value*0x100+0x200;
-		}
 	} else {
 		value = 0x0000;
 		if ((product == MOSCHIP_DEVICE_ID_7715) &&
 		    (index != 0x08)) {
 			dbg("serial->product== MOSCHIP_DEVICE_ID_7715");
-			//index = 0x01 ;
+			/* index = 0x01 ; */
 		}
 	}
 
@@ -308,19 +305,20 @@
 		request = (__u8)MOS_READ;
 		requesttype = (__u8)0xC0;
 		size = 0x01;
-		pipe = usb_rcvctrlpipe(serial->dev,0);
+		pipe = usb_rcvctrlpipe(serial->dev, 0);
 	}
 
 	status = usb_control_msg(serial->dev, pipe, request, requesttype,
 				 value, index, data, size, MOS_WDR_TIMEOUT);
 
 	if (status < 0)
-		dbg("Command Write failed Value %x index %x\n",value,index);
+		dbg("Command Write failed Value %x index %x\n", value, index);
 
 	return status;
 }
 
-static int mos7720_open(struct usb_serial_port *port, struct file * filp)
+static int mos7720_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct usb_serial *serial;
 	struct usb_serial_port *port0;
@@ -351,7 +349,7 @@
 
 	/* Initialising the write urb pool */
 	for (j = 0; j < NUM_URBS; ++j) {
-		urb = usb_alloc_urb(0,GFP_KERNEL);
+		urb = usb_alloc_urb(0, GFP_KERNEL);
 		mos7720_port->write_urb_pool[j] = urb;
 
 		if (urb == NULL) {
@@ -385,7 +383,7 @@
 	  */
 	port_number = port->number - port->serial->minor;
 	send_mos_cmd(port->serial, MOS_READ, port_number, UART_LSR, &data);
-	dbg("SS::%p LSR:%x\n",mos7720_port, data);
+	dbg("SS::%p LSR:%x\n", mos7720_port, data);
 
 	dbg("Check:Sending Command ..........");
 
@@ -402,10 +400,10 @@
 	data = 0xCF;
 	send_mos_cmd(serial, MOS_WRITE, port_number, 0x02, &data);
 	data = 0x03;
-        mos7720_port->shadowLCR  = data;
+	mos7720_port->shadowLCR  = data;
 	send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
 	data = 0x0b;
-        mos7720_port->shadowMCR  = data;
+	mos7720_port->shadowMCR  = data;
 	send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
 	data = 0x0b;
 	send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
@@ -420,7 +418,8 @@
 	data = 0x03;
 	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data);
 	data = 0x00;
-	send_mos_cmd(port->serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data);
+	send_mos_cmd(port->serial, MOS_WRITE, MOS_MAX_PORT,
+						port_number + 1, &data);
 */
 	data = 0x00;
 	send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data);
@@ -429,28 +428,26 @@
 	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data);
 
 	data = 0x83;
-        mos7720_port->shadowLCR  = data;
+	mos7720_port->shadowLCR  = data;
 	send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
 	data = 0x0c;
 	send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data);
 	data = 0x00;
 	send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
 	data = 0x03;
-        mos7720_port->shadowLCR  = data;
+	mos7720_port->shadowLCR  = data;
 	send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
 	data = 0x0c;
 	send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
 	data = 0x0c;
 	send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
 
-//Matrix
-
 	/* force low_latency on so that our tty_push actually forces *
 	 * the data through,otherwise it is scheduled, and with      *
 	 * high data rates (like with OHCI) data can get lost.       */
 
-	if (port->tty)
-		port->tty->low_latency = 1;
+	if (tty)
+		tty->low_latency = 1;
 
 	/* see if we've set up our endpoint info yet   *
 	 * (can't set it up in mos7720_startup as the  *
@@ -465,15 +462,15 @@
 
 		/* set up our interrupt urb */
 		usb_fill_int_urb(port0->interrupt_in_urb, serial->dev,
-				 usb_rcvintpipe(serial->dev,
-				 		port->interrupt_in_endpointAddress),
-				 port0->interrupt_in_buffer,
-				 port0->interrupt_in_urb->transfer_buffer_length,
-				 mos7720_interrupt_callback, mos7720_port,
-				 port0->interrupt_in_urb->interval);
+			 usb_rcvintpipe(serial->dev,
+				port->interrupt_in_endpointAddress),
+			 port0->interrupt_in_buffer,
+			 port0->interrupt_in_urb->transfer_buffer_length,
+			 mos7720_interrupt_callback, mos7720_port,
+			 port0->interrupt_in_urb->interval);
 
 		/* start interrupt read for this mos7720 this interrupt *
-	         * will continue as long as the mos7720 is connected    */
+		 * will continue as long as the mos7720 is connected    */
 		dbg("Submit URB over !!!");
 		response = usb_submit_urb(port0->interrupt_in_urb, GFP_KERNEL);
 		if (response)
@@ -485,14 +482,14 @@
 	/* set up our bulk in urb */
 	usb_fill_bulk_urb(port->read_urb, serial->dev,
 			  usb_rcvbulkpipe(serial->dev,
-			  		  port->bulk_in_endpointAddress),
+				port->bulk_in_endpointAddress),
 			  port->bulk_in_buffer,
 			  port->read_urb->transfer_buffer_length,
 			  mos7720_bulk_in_callback, mos7720_port);
 	response = usb_submit_urb(port->read_urb, GFP_KERNEL);
 	if (response)
-		dev_err(&port->dev,
-			"%s - Error %d submitting read urb\n", __func__, response);
+		dev_err(&port->dev, "%s - Error %d submitting read urb\n",
+							__func__, response);
 
 	/* initialize our icount structure */
 	memset(&(mos7720_port->icount), 0x00, sizeof(mos7720_port->icount));
@@ -515,8 +512,9 @@
  *	system,
  *	Otherwise we return a negative error number.
  */
-static int mos7720_chars_in_buffer(struct usb_serial_port *port)
+static int mos7720_chars_in_buffer(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	int i;
 	int chars = 0;
 	struct moschip_port *mos7720_port;
@@ -530,14 +528,16 @@
 	}
 
 	for (i = 0; i < NUM_URBS; ++i) {
-		if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status == -EINPROGRESS)
+		if (mos7720_port->write_urb_pool[i] &&
+		    mos7720_port->write_urb_pool[i]->status == -EINPROGRESS)
 			chars += URB_TRANSFER_BUFFER_SIZE;
 	}
 	dbg("%s - returns %d", __func__, chars);
 	return chars;
 }
 
-static void mos7720_close(struct usb_serial_port *port, struct file *filp)
+static void mos7720_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct usb_serial *serial;
 	struct moschip_port *mos7720_port;
@@ -575,12 +575,12 @@
 	 * been disconnected */
 	if (!serial->disconnected) {
 		data = 0x00;
-		send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
-			     0x04, &data);
+		send_mos_cmd(serial, MOS_WRITE,
+			port->number - port->serial->minor, 0x04, &data);
 
 		data = 0x00;
-		send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
-			     0x01, &data);
+		send_mos_cmd(serial, MOS_WRITE,
+			port->number - port->serial->minor, 0x01, &data);
 	}
 	mutex_unlock(&serial->disc_mutex);
 	mos7720_port->open = 0;
@@ -588,9 +588,10 @@
 	dbg("Leaving %s", __func__);
 }
 
-static void mos7720_break(struct usb_serial_port *port, int break_state)
+static void mos7720_break(struct tty_struct *tty, int break_state)
 {
-        unsigned char data;
+	struct usb_serial_port *port = tty->driver_data;
+	unsigned char data;
 	struct usb_serial *serial;
 	struct moschip_port *mos7720_port;
 
@@ -621,8 +622,9 @@
  *	If successful, we return the amount of room that we have for this port
  *	Otherwise we return a negative error number.
  */
-static int mos7720_write_room(struct usb_serial_port *port)
+static int mos7720_write_room(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct moschip_port *mos7720_port;
 	int room = 0;
 	int i;
@@ -637,7 +639,8 @@
 
 	/* FIXME: Locking */
 	for (i = 0; i < NUM_URBS; ++i) {
-		if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status != -EINPROGRESS)
+		if (mos7720_port->write_urb_pool[i] &&
+		    mos7720_port->write_urb_pool[i]->status != -EINPROGRESS)
 			room += URB_TRANSFER_BUFFER_SIZE;
 	}
 
@@ -645,8 +648,8 @@
 	return room;
 }
 
-static int mos7720_write(struct usb_serial_port *port,
-			 const unsigned char *data, int count)
+static int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port,
+				 const unsigned char *data, int count)
 {
 	int status;
 	int i;
@@ -672,9 +675,10 @@
 	urb = NULL;
 
 	for (i = 0; i < NUM_URBS; ++i) {
-		if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status != -EINPROGRESS) {
+		if (mos7720_port->write_urb_pool[i] &&
+		    mos7720_port->write_urb_pool[i]->status != -EINPROGRESS) {
 			urb = mos7720_port->write_urb_pool[i];
-			dbg("URB:%d",i);
+			dbg("URB:%d", i);
 			break;
 		}
 	}
@@ -692,7 +696,7 @@
 			goto exit;
 		}
 	}
-	transfer_size = min (count, URB_TRANSFER_BUFFER_SIZE);
+	transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE);
 
 	memcpy(urb->transfer_buffer, current_position, transfer_size);
 	usb_serial_debug_data(debug, &port->dev, __func__, transfer_size,
@@ -701,12 +705,12 @@
 	/* fill urb with data and submit  */
 	usb_fill_bulk_urb(urb, serial->dev,
 			  usb_sndbulkpipe(serial->dev,
-			  		  port->bulk_out_endpointAddress),
+					port->bulk_out_endpointAddress),
 			  urb->transfer_buffer, transfer_size,
 			  mos7720_bulk_out_data_callback, mos7720_port);
 
 	/* send it down the pipe */
-	status = usb_submit_urb(urb,GFP_ATOMIC);
+	status = usb_submit_urb(urb, GFP_ATOMIC);
 	if (status) {
 		err("%s - usb_submit_urb(write bulk) failed with status = %d",
 		    __func__, status);
@@ -719,10 +723,10 @@
 	return bytes_sent;
 }
 
-static void mos7720_throttle(struct usb_serial_port *port)
+static void mos7720_throttle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct moschip_port *mos7720_port;
-	struct tty_struct *tty;
 	int status;
 
 	dbg("%s- port %d\n", __func__, port->number);
@@ -739,16 +743,10 @@
 
 	dbg("%s: Entering ..........", __func__);
 
-	tty = port->tty;
-	if (!tty) {
-		dbg("%s - no tty available", __func__);
-		return;
-	}
-
 	/* if we are implementing XON/XOFF, send the stop character */
 	if (I_IXOFF(tty)) {
 		unsigned char stop_char = STOP_CHAR(tty);
-		status = mos7720_write(port, &stop_char, 1);
+		status = mos7720_write(tty, port, &stop_char, 1);
 		if (status <= 0)
 			return;
 	}
@@ -764,11 +762,11 @@
 	}
 }
 
-static void mos7720_unthrottle(struct usb_serial_port *port)
+static void mos7720_unthrottle(struct tty_struct *tty)
 {
-	struct tty_struct *tty;
-	int status;
+	struct usb_serial_port *port = tty->driver_data;
 	struct moschip_port *mos7720_port = usb_get_serial_port_data(port);
+	int status;
 
 	if (mos7720_port == NULL)
 		return;
@@ -780,16 +778,10 @@
 
 	dbg("%s: Entering ..........", __func__);
 
-	tty = port->tty;
-	if (!tty) {
-		dbg("%s - no tty available", __func__);
-		return;
-	}
-
 	/* if we are implementing XON/XOFF, send the start character */
 	if (I_IXOFF(tty)) {
 		unsigned char start_char = START_CHAR(tty);
-		status = mos7720_write(port, &start_char, 1);
+		status = mos7720_write(tty, port, &start_char, 1);
 		if (status <= 0)
 			return;
 	}
@@ -819,9 +811,9 @@
 	port = mos7720_port->port;
 	serial = port->serial;
 
-        /***********************************************
-         *      Init Sequence for higher rates
-         ***********************************************/
+	 /***********************************************
+	 *      Init Sequence for higher rates
+	 ***********************************************/
 	dbg("Sending Setting Commands ..........");
 	port_number = port->number - port->serial->minor;
 
@@ -832,7 +824,7 @@
 	data = 0x0CF;
 	send_mos_cmd(serial, MOS_WRITE, port->number, 0x02, &data);
 	data = 0x00b;
-        mos7720_port->shadowMCR  = data;
+	mos7720_port->shadowMCR  = data;
 	send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
 	data = 0x00b;
 	send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
@@ -843,12 +835,12 @@
 	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data);
 
 
-        /***********************************************
-         *              Set for higher rates           *
-         ***********************************************/
+	/***********************************************
+	 *              Set for higher rates           *
+	 ***********************************************/
 
 	data = baud * 0x10;
-	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1,&data);
+	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data);
 
 	data = 0x003;
 	send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data);
@@ -856,34 +848,33 @@
 	send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data);
 
 	data = 0x02b;
-        mos7720_port->shadowMCR  = data;
+	mos7720_port->shadowMCR  = data;
 	send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
 	data = 0x02b;
 	send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
 
-        /***********************************************
-         *              Set DLL/DLM
-         ***********************************************/
+	/***********************************************
+	 *              Set DLL/DLM
+	 ***********************************************/
 
 	data = mos7720_port->shadowLCR | UART_LCR_DLAB;
-        mos7720_port->shadowLCR  = data;
+	mos7720_port->shadowLCR  = data;
 	send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
 
 	data =  0x001; /* DLL */
-        send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data);
+	send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data);
 	data =  0x000; /* DLM */
-        send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
+	send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data);
 
 	data = mos7720_port->shadowLCR & ~UART_LCR_DLAB;
-        mos7720_port->shadowLCR  = data;
+	mos7720_port->shadowLCR  = data;
 	send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data);
 
 	return 0;
 }
 
 /* baud rate information */
-struct divisor_table_entry
-{
+struct divisor_table_entry {
 	__u32  baudrate;
 	__u16  divisor;
 };
@@ -932,8 +923,8 @@
 		}
 	}
 
-        /* After trying for all the standard baud rates    *
-         * Try calculating the divisor for this baud rate  */
+	/* 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);
@@ -945,7 +936,7 @@
 			custom++;
 		*divisor = custom;
 
-		dbg("Baud %d = %d",baudrate, custom);
+		dbg("Baud %d = %d", baudrate, custom);
 		return 0;
 	}
 
@@ -979,29 +970,29 @@
 	number = port->number - port->serial->minor;
 	dbg("%s - port = %d, baud = %d", __func__, port->number, baudrate);
 
-        /* Calculate the Divisor */
+	/* Calculate the Divisor */
 	status = calc_baud_rate_divisor(baudrate, &divisor);
 	if (status) {
 		err("%s - bad baud rate", __func__);
 		return status;
 	}
 
-        /* Enable access to divisor latch */
-        data = mos7720_port->shadowLCR | UART_LCR_DLAB;
-        mos7720_port->shadowLCR  = data;
-        send_mos_cmd(serial, MOS_WRITE, number, UART_LCR, &data);
+	/* Enable access to divisor latch */
+	data = mos7720_port->shadowLCR | UART_LCR_DLAB;
+	mos7720_port->shadowLCR  = data;
+	send_mos_cmd(serial, MOS_WRITE, number, UART_LCR, &data);
 
 	/* Write the divisor */
 	data = ((unsigned char)(divisor & 0xff));
-        send_mos_cmd(serial, MOS_WRITE, number, 0x00, &data);
+	send_mos_cmd(serial, MOS_WRITE, number, 0x00, &data);
 
 	data = ((unsigned char)((divisor & 0xff00) >> 8));
-        send_mos_cmd(serial, MOS_WRITE, number, 0x01, &data);
+	send_mos_cmd(serial, MOS_WRITE, number, 0x01, &data);
 
-        /* Disable access to divisor latch */
-        data = mos7720_port->shadowLCR & ~UART_LCR_DLAB;
-        mos7720_port->shadowLCR = data;
-        send_mos_cmd(serial, MOS_WRITE, number, 0x03, &data);
+	/* Disable access to divisor latch */
+	data = mos7720_port->shadowLCR & ~UART_LCR_DLAB;
+	mos7720_port->shadowLCR = data;
+	send_mos_cmd(serial, MOS_WRITE, number, 0x03, &data);
 
 	return status;
 }
@@ -1011,12 +1002,12 @@
  *	This routine is called to set the UART on the device to match
  *      the specified new settings.
  */
-static void change_port_settings(struct moschip_port *mos7720_port,
+static void change_port_settings(struct tty_struct *tty,
+				 struct moschip_port *mos7720_port,
 				 struct ktermios *old_termios)
 {
 	struct usb_serial_port *port;
 	struct usb_serial *serial;
-	struct tty_struct *tty;
 	int baud;
 	unsigned cflag;
 	unsigned iflag;
@@ -1042,8 +1033,6 @@
 		return;
 	}
 
-	tty = mos7720_port->port->tty;
-
 	dbg("%s: Entering ..........", __func__);
 
 	lData = UART_LCR_WLEN8;
@@ -1106,29 +1095,31 @@
 #define LCR_PAR_MASK		0x38	/* Mask for parity field */
 
 	/* Update the LCR with the correct value */
-	mos7720_port->shadowLCR &= ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK);
+	mos7720_port->shadowLCR &=
+			~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK);
 	mos7720_port->shadowLCR |= (lData | lParity | lStop);
 
 
 	/* Disable Interrupts */
 	data = 0x00;
-        send_mos_cmd(serial,MOS_WRITE,port->number - port->serial->minor, UART_IER, &data);
+	send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor,
+							UART_IER, &data);
 
 	data = 0x00;
-        send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data);
+	send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data);
 
 	data = 0xcf;
-        send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data);
+	send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data);
 
 	/* Send the updated LCR value to the mos7720 */
 	data = mos7720_port->shadowLCR;
-        send_mos_cmd(serial, MOS_WRITE, port_number, UART_LCR, &data);
+	send_mos_cmd(serial, MOS_WRITE, port_number, UART_LCR, &data);
 
-        data = 0x00b;
-        mos7720_port->shadowMCR = data;
-        send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
-        data = 0x00b;
-        send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
+	data = 0x00b;
+	mos7720_port->shadowMCR = data;
+	send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
+	data = 0x00b;
+	send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data);
 
 	/* set up the MCR register and send it to the mos7720 */
 	mos7720_port->shadowMCR = UART_MCR_OUT2;
@@ -1137,9 +1128,8 @@
 
 	if (cflag & CRTSCTS) {
 		mos7720_port->shadowMCR |= (UART_MCR_XONANY);
-
-                /* To set hardware flow control to the specified *
-                 * serial port, in SP1/2_CONTROL_REG             */
+		/* To set hardware flow control to the specified *
+		 * serial port, in SP1/2_CONTROL_REG             */
 		if (port->number) {
 			data = 0x001;
 			send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT,
@@ -1198,14 +1188,13 @@
  *	this function is called by the tty driver when it wants to change the
  *	termios structure.
  */
-static void mos7720_set_termios(struct usb_serial_port *port,
-				struct ktermios *old_termios)
+static void mos7720_set_termios(struct tty_struct *tty,
+		struct usb_serial_port *port, struct ktermios *old_termios)
 {
 	int status;
 	unsigned int cflag;
 	struct usb_serial *serial;
 	struct moschip_port *mos7720_port;
-	struct tty_struct *tty;
 
 	serial = port->serial;
 
@@ -1214,15 +1203,12 @@
 	if (mos7720_port == NULL)
 		return;
 
-	tty = port->tty;
-
-
 	if (!mos7720_port->open) {
 		dbg("%s - port not opened", __func__);
 		return;
 	}
 
-	dbg("%s\n","setting termios - ASPIRE");
+	dbg("%s\n", "setting termios - ASPIRE");
 
 	cflag = tty->termios->c_cflag;
 
@@ -1237,14 +1223,14 @@
 	dbg("%s - port %d", __func__, port->number);
 
 	/* change the port settings to the new ones specified */
-	change_port_settings(mos7720_port, old_termios);
+	change_port_settings(tty, mos7720_port, old_termios);
 
-	if(!port->read_urb) {
-		dbg("%s","URB KILLED !!!!!\n");
+	if (!port->read_urb) {
+		dbg("%s", "URB KILLED !!!!!\n");
 		return;
 	}
 
-	if(port->read_urb->status != -EINPROGRESS) {
+	if (port->read_urb->status != -EINPROGRESS) {
 		port->read_urb->dev = serial->dev;
 		status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 		if (status)
@@ -1264,13 +1250,13 @@
  * 	    transmit holding register is empty.  This functionality
  * 	    allows an RS485 driver to be written in user space.
  */
-static int get_lsr_info(struct moschip_port *mos7720_port,
-			unsigned int __user *value)
+static int get_lsr_info(struct tty_struct *tty,
+		struct moschip_port *mos7720_port, unsigned int __user *value)
 {
 	int count;
 	unsigned int result = 0;
 
-	count = mos7720_chars_in_buffer(mos7720_port->port);
+	count = mos7720_chars_in_buffer(tty);
 	if (count == 0) {
 		dbg("%s -- Empty", __func__);
 		result = TIOCSER_TEMT;
@@ -1290,7 +1276,7 @@
 				  unsigned int __user *value)
 {
 	unsigned int result = 0;
-	struct tty_struct *tty = mos7720_port->port->tty;
+	struct tty_struct *tty = mos7720_port->port->port.tty;
 
 	if (!tty)
 		return -ENOIOCTLCMD;
@@ -1316,7 +1302,7 @@
 	if (mos7720_port == NULL)
 		return -1;
 
-	port = (struct usb_serial_port*)mos7720_port->port;
+	port = (struct usb_serial_port *)mos7720_port->port;
 	mcr = mos7720_port->shadowMCR;
 
 	if (copy_from_user(&arg, value, sizeof(int)))
@@ -1397,7 +1383,7 @@
 	tmp.port		= mos7720_port->port->number;
 	tmp.irq			= 0;
 	tmp.flags		= ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
-        tmp.xmit_fifo_size	= NUM_URBS * URB_TRANSFER_BUFFER_SIZE;
+	tmp.xmit_fifo_size	= NUM_URBS * URB_TRANSFER_BUFFER_SIZE;
 	tmp.baud_base		= 9600;
 	tmp.close_delay		= 5*HZ;
 	tmp.closing_wait	= 30*HZ;
@@ -1407,9 +1393,10 @@
 	return 0;
 }
 
-static int mos7720_ioctl(struct usb_serial_port *port, struct file *file,
+static int mos7720_ioctl(struct tty_struct *tty, struct file *file,
 			 unsigned int cmd, unsigned long arg)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct moschip_port *mos7720_port;
 	struct async_icount cnow;
 	struct async_icount cprev;
@@ -1431,14 +1418,16 @@
 
 	case TIOCSERGETLSR:
 		dbg("%s (%d) TIOCSERGETLSR", __func__,  port->number);
-		return get_lsr_info(mos7720_port, (unsigned int __user *)arg);
+		return get_lsr_info(tty, mos7720_port,
+					(unsigned int __user *)arg);
 		return 0;
 
+	/* FIXME: These should be using the mode methods */
 	case TIOCMBIS:
 	case TIOCMBIC:
 	case TIOCMSET:
-		dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __func__,
-		    port->number);
+		dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET",
+					__func__, port->number);
 		return set_modem_info(mos7720_port, cmd,
 				      (unsigned int __user *)arg);
 
@@ -1452,10 +1441,6 @@
 		return get_serial_info(mos7720_port,
 				       (struct serial_struct __user *)arg);
 
-	case TIOCSSERIAL:
-		dbg("%s (%d) TIOCSSERIAL", __func__,  port->number);
-		break;
-
 	case TIOCMIWAIT:
 		dbg("%s (%d) TIOCMIWAIT", __func__,  port->number);
 		cprev = mos7720_port->icount;
@@ -1469,7 +1454,7 @@
 			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)) ) {
+			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
 				return 0;
 			}
 			cprev = cnow;
@@ -1492,7 +1477,7 @@
 		icount.buf_overrun = cnow.buf_overrun;
 
 		dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
-		    port->number, icount.rx, icount.tx );
+		    port->number, icount.rx, icount.tx);
 		if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))
 			return -EFAULT;
 		return 0;
@@ -1543,7 +1528,8 @@
 		/* Initialize all port interrupt end point to port 0 int
 		 * endpoint.  Our device has only one interrupt endpoint
 		 * comman to all ports */
-		serial->port[i]->interrupt_in_endpointAddress = serial->port[0]->interrupt_in_endpointAddress;
+		serial->port[i]->interrupt_in_endpointAddress =
+				serial->port[0]->interrupt_in_endpointAddress;
 
 		mos7720_port->port = serial->port[i];
 		usb_set_serial_port_data(serial->port[i], mos7720_port);
@@ -1555,13 +1541,15 @@
 
 	/* setting configuration feature to one */
 	usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-			(__u8)0x03, 0x00,0x01,0x00, NULL, 0x00, 5*HZ);
+			(__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5*HZ);
 
-	send_mos_cmd(serial,MOS_READ,0x00, UART_LSR, &data);  // LSR For Port 1
-	dbg("LSR:%x",data);
+	/* LSR For Port 1 */
+	send_mos_cmd(serial, MOS_READ, 0x00, UART_LSR, &data);
+	dbg("LSR:%x", data);
 
-	send_mos_cmd(serial,MOS_READ,0x01, UART_LSR, &data);  // LSR For Port 2
-	dbg("LSR:%x",data);
+	/* LSR For Port 2 */
+	send_mos_cmd(serial, MOS_READ, 0x01, UART_LSR, &data);
+	dbg("LSR:%x", data);
 
 	return 0;
 }
@@ -1571,7 +1559,7 @@
 	int i;
 
 	/* free private structure allocated for serial port */
-	for (i=0; i < serial->num_ports; ++i) {
+	for (i = 0; i < serial->num_ports; ++i) {
 		kfree(usb_get_serial_port_data(serial->port[i]));
 		usb_set_serial_port_data(serial->port[i], NULL);
 	}
@@ -1651,8 +1639,8 @@
 module_exit(moschip7720_exit);
 
 /* Module information */
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 78f2f6d..09d8206 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -33,7 +33,7 @@
 #include <linux/serial.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /*
  * Version Information
@@ -82,8 +82,8 @@
  * 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 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
@@ -102,8 +102,8 @@
 
 #define MAX_NAME_LEN    64
 
-#define ZLP_REG1  0x3A		//Zero_Flag_Reg1    58
-#define ZLP_REG5  0x3E		//Zero_Flag_Reg5    62
+#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
@@ -142,7 +142,7 @@
 #define MOS_MSR_DELTA_RI    0x40
 #define MOS_MSR_DELTA_CD    0x80
 
-// Serial Port register Address
+/* Serial Port register Address */
 #define INTERRUPT_ENABLE_REGISTER  ((__u16)(0x01))
 #define FIFO_CONTROL_REGISTER      ((__u16)(0x02))
 #define LINE_CONTROL_REGISTER      ((__u16)(0x03))
@@ -201,11 +201,11 @@
 	struct async_icount icount;
 	struct usb_serial_port *port;	/* loop back to the owner of this object */
 
-	/*Offsets */
+	/* Offsets */
 	__u8 SpRegOffset;
 	__u8 ControlRegOffset;
 	__u8 DcrRegOffset;
-	//for processing control URBS in interrupt context
+	/* for processing control URBS in interrupt context */
 	struct urb *control_urb;
 	struct usb_ctrlrequest *dr;
 	char *ctrl_buf;
@@ -244,7 +244,7 @@
  */
 
 static int mos7840_get_reg_sync(struct usb_serial_port *port, __u16 reg,
-				__u16 * val)
+				__u16 *val)
 {
 	struct usb_device *dev = port->serial->dev;
 	int ret = 0;
@@ -269,16 +269,15 @@
 
 	struct usb_device *dev = port->serial->dev;
 	val = val & 0x00ff;
-	// For the UART control registers, the application number need to be Or'ed
+	/* For the UART control registers, the application number need
+	   to be Or'ed */
 	if (port->serial->num_ports == 4) {
-		val |=
-		    (((__u16) port->number - (__u16) (port->serial->minor)) +
-		     1) << 8;
+		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 -
+			val |= (((__u16) port->number -
 			      (__u16) (port->serial->minor)) + 1) << 8;
 			dbg("mos7840_set_uart_reg application number is %x\n",
 			    val);
@@ -302,14 +301,15 @@
  *	by passing usb_rcvctrlpipe function as parameter.
  */
 static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg,
-				__u16 * val)
+				__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 */
+	/* dbg("application number is %4x \n",
+	    (((__u16)port->number - (__u16)(port->serial->minor))+1)<<8); */
+	/* Wval  is same as application number */
 	if (port->serial->num_ports == 4) {
 		Wval =
 		    (((__u16) port->number - (__u16) (port->serial->minor)) +
@@ -317,14 +317,12 @@
 		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 -
+			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 -
+			Wval = (((__u16) port->number -
 			      (__u16) (port->serial->minor)) + 2) << 8;
 			dbg("mos7840_get_uart_reg application number is %x\n",
 			    Wval);
@@ -406,11 +404,11 @@
 	dbg("%s - %02x", __func__, new_lsr);
 
 	if (new_lsr & SERIAL_LSR_BI) {
-		//
-		// Parity and Framing errors only count if they
-		// occur exclusive of a break being
-		// received.
-		//
+		/*
+		 * Parity and Framing errors only count if they
+		 * occur exclusive of a break being
+		 * received.
+		 */
 		new_lsr &= (__u8) (SERIAL_LSR_OE | SERIAL_LSR_BI);
 	}
 
@@ -492,7 +490,7 @@
 }
 
 static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
-			   __u16 * val)
+			   __u16 *val)
 {
 	struct usb_device *dev = mcs->port->serial->dev;
 	struct usb_ctrlrequest *dr = mcs->dr;
@@ -501,7 +499,7 @@
 
 	dr->bRequestType = MCS_RD_RTYPE;
 	dr->bRequest = MCS_RDREQ;
-	dr->wValue = cpu_to_le16(Wval);	//0;
+	dr->wValue = cpu_to_le16(Wval);	/* 0 */
 	dr->wIndex = cpu_to_le16(reg);
 	dr->wLength = cpu_to_le16(2);
 
@@ -607,7 +605,8 @@
 			}
 		}
 	}
-	if (!(rv < 0)) /* the completion handler for the control urb will resubmit */
+	if (!(rv < 0))
+		/* the completion handler for the control urb will resubmit */
 		return;
 exit:
 	result = usb_submit_urb(urb, GFP_ATOMIC);
@@ -656,8 +655,8 @@
 	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 */
+		/* then say that we don't have a valid usb_serial thing,
+		 * which will end up genrating -ENODEV return values */
 		return NULL;
 	}
 
@@ -710,7 +709,7 @@
 	dbg("%s", "Entering ........... \n");
 
 	if (urb->actual_length) {
-		tty = mos7840_port->port->tty;
+		tty = mos7840_port->port->port.tty;
 		if (tty) {
 			tty_buffer_request_room(tty, urb->actual_length);
 			tty_insert_flip_string(tty, data, urb->actual_length);
@@ -741,8 +740,8 @@
 
 /*****************************************************************************
  * mos7840_bulk_out_data_callback
- *	this is the callback function for when we have finished sending serial data
- *	on the bulk out endpoint.
+ *	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)
@@ -774,7 +773,7 @@
 
 	dbg("%s \n", "Entering .........");
 
-	tty = mos7840_port->port->tty;
+	tty = mos7840_port->port->port.tty;
 
 	if (tty && mos7840_port->open)
 		tty_wakeup(tty);
@@ -804,7 +803,8 @@
  *	Otherwise we return a negative error number.
  *****************************************************************************/
 
-static int mos7840_open(struct usb_serial_port *port, struct file *filp)
+static int mos7840_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	int response;
 	int j;
@@ -847,7 +847,8 @@
 			continue;
 		}
 
-		urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+		urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE,
+								GFP_KERNEL);
 		if (!urb->transfer_buffer) {
 			usb_free_urb(urb);
 			mos7840_port->write_urb_pool[j] = NULL;
@@ -868,9 +869,8 @@
  * 0x08 : SP1/2 Control Reg
  *****************************************************************************/
 
-//NEED to check the following Block
+	/* NEED to check the following Block */
 
-	status = 0;
 	Data = 0x0;
 	status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data);
 	if (status < 0) {
@@ -890,36 +890,35 @@
 		dbg("writing Spreg failed\n");
 		return -1;
 	}
-//End of block to be checked
+	/* End of block to be checked */
 
-	status = 0;
 	Data = 0x0;
-	status =
-	    mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data);
+	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 = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data);
+	Data |= 0x08;		/* Driver done bit */
+	Data |= 0x20;		/* rx_disable */
+	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.
-	////////////////////////////////////
-
+	/* do register settings here */
+	/* Set all regs to the device default values. */
+	/***********************************
+	 * First Disable all interrupts.
+	 ***********************************/
 	Data = 0x00;
 	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
+	/* Set FIFO_CONTROL_REGISTER to the default value */
 	Data = 0x00;
 	status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
 	if (status < 0) {
@@ -946,90 +945,73 @@
 	status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data);
 	mos7840_port->shadowLCR = Data;
 
-	Data |= SERIAL_LCR_DLAB;	//data latch enable in LCR 0x80
+	Data |= SERIAL_LCR_DLAB;	/* data latch enable in LCR 0x80 */
 	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
+	/* 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;
+	/* Finally enable all interrupts */
 	Data = 0x0c;
-	status = 0;
 	status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
 
-	//clearing rx_disable
+	/* clearing rx_disable */
 	Data = 0x0;
-	status = 0;
-	status =
-	    mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data);
+	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);
+	status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset,
+									Data);
 
-	// rx_negate
+	/* rx_negate */
 	Data = 0x0;
-	status = 0;
-	status =
-	    mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data);
+	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);
+	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 (tty)
+		tty->low_latency = 1;
 
-	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.)                        */
+	/* 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 (port0->open_ports == 1) {
 		if (serial->port[0]->interrupt_in_buffer == NULL) {
-
 			/* set up interrupt urb */
-
 			usb_fill_int_urb(serial->port[0]->interrupt_in_urb,
-					 serial->dev,
-					 usb_rcvintpipe(serial->dev,
-							serial->port[0]->
-							interrupt_in_endpointAddress),
-					 serial->port[0]->interrupt_in_buffer,
-					 serial->port[0]->interrupt_in_urb->
-					 transfer_buffer_length,
-					 mos7840_interrupt_callback,
-					 serial,
-					 serial->port[0]->interrupt_in_urb->
-					 interval);
+				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  */
@@ -1084,14 +1066,16 @@
 	memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount));
 
 	/* initialize our port settings */
-	mos7840_port->shadowMCR = MCR_MASTER_IE;	/* Must set to enable ints! */
+	/* Must set to enable ints! */
+	mos7840_port->shadowMCR = MCR_MASTER_IE;
 	/* send a open port command */
 	mos7840_port->open = 1;
-	//mos7840_change_port_settings(mos7840_port,old_termios);
+	/* mos7840_change_port_settings(mos7840_port,old_termios); */
 	mos7840_port->icount.tx = 0;
 	mos7840_port->icount.rx = 0;
 
-	dbg("\n\nusb_serial serial:%p       mos7840_port:%p\n      usb_serial_port port:%p\n\n", serial, mos7840_port, port);
+	dbg("\n\nusb_serial serial:%p       mos7840_port:%p\n      usb_serial_port port:%p\n\n",
+				serial, mos7840_port, port);
 
 	return 0;
 
@@ -1104,11 +1088,12 @@
  *	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.
+ *	Otherwise we return zero.
  *****************************************************************************/
 
-static int mos7840_chars_in_buffer(struct usb_serial_port *port)
+static int mos7840_chars_in_buffer(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	int i;
 	int chars = 0;
 	unsigned long flags;
@@ -1118,22 +1103,20 @@
 
 	if (mos7840_port_paranoia_check(port, __func__)) {
 		dbg("%s", "Invalid port \n");
-		return -1;
+		return 0;
 	}
 
 	mos7840_port = mos7840_get_port_private(port);
 	if (mos7840_port == NULL) {
 		dbg("%s \n", "mos7840_break:leaving ...........");
-		return -1;
+		return 0;
 	}
 
-	spin_lock_irqsave(&mos7840_port->pool_lock,flags);
-	for (i = 0; i < NUM_URBS; ++i) {
-		if (mos7840_port->busy[i]) {
+	spin_lock_irqsave(&mos7840_port->pool_lock, flags);
+	for (i = 0; i < NUM_URBS; ++i)
+		if (mos7840_port->busy[i])
 			chars += URB_TRANSFER_BUFFER_SIZE;
-		}
-	}
-	spin_unlock_irqrestore(&mos7840_port->pool_lock,flags);
+	spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
 	dbg("%s - returns %d", __func__, chars);
 	return chars;
 
@@ -1149,7 +1132,8 @@
  *		3. A timeout of 3 seconds without activity has expired
  *
  ************************************************************************/
-static void mos7840_block_until_tx_empty(struct moschip_port *mos7840_port)
+static void mos7840_block_until_tx_empty(struct tty_struct *tty,
+				struct moschip_port *mos7840_port)
 {
 	int timeout = HZ / 10;
 	int wait = 30;
@@ -1157,12 +1141,11 @@
 
 	while (1) {
 
-		count = mos7840_chars_in_buffer(mos7840_port->port);
+		count = mos7840_chars_in_buffer(tty);
 
 		/* Check for Buffer status */
-		if (count <= 0) {
+		if (count <= 0)
 			return;
-		}
 
 		/* Block the thread for a while */
 		interruptible_sleep_on_timeout(&mos7840_port->wait_chase,
@@ -1185,7 +1168,8 @@
  *	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)
+static void mos7840_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct usb_serial *serial;
 	struct moschip_port *mos7840_port;
@@ -1226,32 +1210,28 @@
 		}
 	}
 
-	if (serial->dev) {
+	if (serial->dev)
 		/* flush and block until tx is empty */
-		mos7840_block_until_tx_empty(mos7840_port);
-	}
+		mos7840_block_until_tx_empty(tty, 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);
-
+			/*/      usb_kill_urb (mos7840_port->control_urb); */
 		}
 	}
-//              if(mos7840_port->ctrl_buf != NULL)
-//                      kfree(mos7840_port->ctrl_buf);
+/*      if(mos7840_port->ctrl_buf != NULL) */
+/*              kfree(mos7840_port->ctrl_buf); */
 	port0->open_ports--;
 	dbg("mos7840_num_open_ports in close%d:in port%d\n",
 	    port0->open_ports, port->number);
@@ -1264,10 +1244,8 @@
 
 	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) {
+		if (mos7840_port->write_urb->transfer_buffer != NULL)
 			kfree(mos7840_port->write_urb->transfer_buffer);
-		}
 		usb_free_urb(mos7840_port->write_urb);
 	}
 
@@ -1293,20 +1271,19 @@
  *
  ************************************************************************/
 
-static void mos7840_block_until_chase_response(struct moschip_port
-					       *mos7840_port)
+static void mos7840_block_until_chase_response(struct tty_struct *tty,
+					struct moschip_port *mos7840_port)
 {
 	int timeout = 1 * HZ;
 	int wait = 10;
 	int count;
 
 	while (1) {
-		count = mos7840_chars_in_buffer(mos7840_port->port);
+		count = mos7840_chars_in_buffer(tty);
 
 		/* Check for Buffer status */
-		if (count <= 0) {
+		if (count <= 0)
 			return;
-		}
 
 		/* Block the thread for a while */
 		interruptible_sleep_on_timeout(&mos7840_port->wait_chase,
@@ -1328,8 +1305,9 @@
  * mos7840_break
  *	this function sends a break to the port
  *****************************************************************************/
-static void mos7840_break(struct usb_serial_port *port, int break_state)
+static void mos7840_break(struct tty_struct *tty, int break_state)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	unsigned char data;
 	struct usb_serial *serial;
 	struct moschip_port *mos7840_port;
@@ -1350,21 +1328,17 @@
 
 	mos7840_port = mos7840_get_port_private(port);
 
-	if (mos7840_port == NULL) {
+	if (mos7840_port == NULL)
 		return;
-	}
 
-	if (serial->dev) {
-
+	if (serial->dev)
 		/* flush and block until tx is empty */
-		mos7840_block_until_chase_response(mos7840_port);
-	}
+		mos7840_block_until_chase_response(tty, mos7840_port);
 
-	if (break_state == -1) {
+	if (break_state == -1)
 		data = mos7840_port->shadowLCR | LCR_SET_BREAK;
-	} else {
+	else
 		data = mos7840_port->shadowLCR & ~LCR_SET_BREAK;
-	}
 
 	mos7840_port->shadowLCR = data;
 	dbg("mcs7840_break mos7840_port->shadowLCR is %x\n",
@@ -1383,8 +1357,9 @@
  *	Otherwise we return a negative error number.
  *****************************************************************************/
 
-static int mos7840_write_room(struct usb_serial_port *port)
+static int mos7840_write_room(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	int i;
 	int room = 0;
 	unsigned long flags;
@@ -1406,9 +1381,8 @@
 
 	spin_lock_irqsave(&mos7840_port->pool_lock, flags);
 	for (i = 0; i < NUM_URBS; ++i) {
-		if (!mos7840_port->busy[i]) {
+		if (!mos7840_port->busy[i])
 			room += URB_TRANSFER_BUFFER_SIZE;
-		}
 	}
 	spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
 
@@ -1426,7 +1400,7 @@
  *      return a negative error number.
  *****************************************************************************/
 
-static int mos7840_write(struct usb_serial_port *port,
+static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,
 			 const unsigned char *data, int count)
 {
 	int status;
@@ -1438,45 +1412,41 @@
 	struct moschip_port *mos7840_port;
 	struct usb_serial *serial;
 	struct urb *urb;
-	//__u16 Data;
+	/* __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);
+	/* 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 = 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;
+	Data |= SERIAL_LCR_DLAB;	/* data latch enable in LCR 0x80 */
 	status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
 
-	//Data = 0x0c;
-	//status = mos7840_set_uart_reg(port,DIVISOR_LATCH_LSB,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
 
@@ -1555,8 +1525,7 @@
 	mos7840_port->icount.tx += transfer_size;
 	smp_wmb();
 	dbg("mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx);
-      exit:
-
+exit:
 	return bytes_sent;
 
 }
@@ -1567,10 +1536,10 @@
  *	being read from the port.
  *****************************************************************************/
 
-static void mos7840_throttle(struct usb_serial_port *port)
+static void mos7840_throttle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct moschip_port *mos7840_port;
-	struct tty_struct *tty;
 	int status;
 
 	if (mos7840_port_paranoia_check(port, __func__)) {
@@ -1592,32 +1561,20 @@
 
 	dbg("%s", "Entering .......... \n");
 
-	tty = port->tty;
-	if (!tty) {
-		dbg("%s - no tty available", __func__);
-		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) {
+		status = mos7840_write(tty, 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,
+		status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
 					 mos7840_port->shadowMCR);
-
-		if (status < 0) {
+		if (status < 0)
 			return;
-		}
 	}
 
 	return;
@@ -1625,12 +1582,13 @@
 
 /*****************************************************************************
  * 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)
+ *	this function is called by the tty driver when it wants to resume
+ *	the data being read from the port (called after mos7840_throttle is
+ *	called)
  *****************************************************************************/
-static void mos7840_unthrottle(struct usb_serial_port *port)
+static void mos7840_unthrottle(struct tty_struct *tty)
 {
-	struct tty_struct *tty;
+	struct usb_serial_port *port = tty->driver_data;
 	int status;
 	struct moschip_port *mos7840_port = mos7840_get_port_private(port);
 
@@ -1649,43 +1607,32 @@
 
 	dbg("%s", "Entering .......... \n");
 
-	tty = port->tty;
-	if (!tty) {
-		dbg("%s - no tty available", __func__);
-		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) {
+		status = mos7840_write(tty, 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,
+		status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
 					 mos7840_port->shadowMCR);
-		if (status < 0) {
+		if (status < 0)
 			return;
-		}
 	}
-
-	return;
 }
 
-static int mos7840_tiocmget(struct usb_serial_port *port, struct file *file)
+static int mos7840_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct moschip_port *mos7840_port;
 	unsigned int result;
 	__u16 msr;
 	__u16 mcr;
-	int status = 0;
+	int status;
 	mos7840_port = mos7840_get_port_private(port);
 
 	dbg("%s - port %d", __func__, port->number);
@@ -1708,9 +1655,10 @@
 	return result;
 }
 
-static int mos7840_tiocmset(struct usb_serial_port *port, struct file *file,
+static int mos7840_tiocmset(struct tty_struct *tty, struct file *file,
 			    unsigned int set, unsigned int clear)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct moschip_port *mos7840_port;
 	unsigned int mcr;
 	int status;
@@ -1755,7 +1703,7 @@
  *	baud rate.
  *****************************************************************************/
 static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor,
-					  __u16 * clk_sel_val)
+					  __u16 *clk_sel_val)
 {
 
 	dbg("%s - %d", __func__, baudRate);
@@ -1807,9 +1755,8 @@
 		/* Check for round off */
 		round1 = (__u16) (2304000L / baudrate);
 		round = (__u16) (round1 - (custom * 10));
-		if (round > 4) {
+		if (round > 4)
 			custom++;
-		}
 		*divisor = custom;
 
 		dbg(" Baud %d = %d\n", baudrate, custom);
@@ -1857,16 +1804,15 @@
 
 	dbg("%s - port = %d, baud = %d", __func__,
 	    mos7840_port->port->number, baudRate);
-	//reset clk_uart_sel in spregOffset
+	/* 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;
+		/* NOTE: need to see the pther register to modify */
+		/* setting h/w flow control bit to 1 */
 		Data = 0x2b;
 		mos7840_port->shadowMCR = Data;
-		status =
-		    mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, 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;
@@ -1875,12 +1821,11 @@
 
 	} else {
 #ifdef HW_flow_control
-		//setting h/w flow control bit to 0;
-		status = 0;
+		/ *setting h/w flow control bit to 0 */
 		Data = 0xb;
 		mos7840_port->shadowMCR = Data;
-		status =
-		    mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, 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;
@@ -1889,25 +1834,20 @@
 
 	}
 
-	if (1)			//baudRate <= 115200)
-	{
+	if (1) {		/* baudRate <= 115200) */
 		clk_sel_val = 0x0;
 		Data = 0x0;
-		status = 0;
-		status =
-		    mos7840_calc_baud_rate_divisor(baudRate, &divisor,
+		status = mos7840_calc_baud_rate_divisor(baudRate, &divisor,
 						   &clk_sel_val);
-		status =
-		    mos7840_get_reg_sync(port, mos7840_port->SpRegOffset,
-					 &Data);
+		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);
+		status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset,
+								Data);
 		if (status < 0) {
 			dbg("Writing spreg failed in set_serial_baud\n");
 			return -1;
@@ -1939,7 +1879,6 @@
 		mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
 
 	}
-
 	return status;
 }
 
@@ -1949,10 +1888,9 @@
  *      the specified new settings.
  *****************************************************************************/
 
-static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
-					 struct ktermios *old_termios)
+static void mos7840_change_port_settings(struct tty_struct *tty,
+	struct moschip_port *mos7840_port, struct ktermios *old_termios)
 {
-	struct tty_struct *tty;
 	int baud;
 	unsigned cflag;
 	unsigned iflag;
@@ -1988,8 +1926,6 @@
 		return;
 	}
 
-	tty = mos7840_port->port->tty;
-
 	dbg("%s", "Entering .......... \n");
 
 	lData = LCR_BITS_8;
@@ -2033,9 +1969,8 @@
 		dbg("%s - parity = none", __func__);
 	}
 
-	if (cflag & CMSPAR) {
+	if (cflag & CMSPAR)
 		lParity = lParity | 0x20;
-	}
 
 	/* Change the Stop bit */
 	if (cflag & CSTOPB) {
@@ -2077,16 +2012,13 @@
 	/* set up the MCR register and send it to the mos7840 */
 
 	mos7840_port->shadowMCR = MCR_MASTER_IE;
-	if (cflag & CBAUD) {
+	if (cflag & CBAUD)
 		mos7840_port->shadowMCR |= (MCR_DTR | MCR_RTS);
-	}
 
-	if (cflag & CRTSCTS) {
+	if (cflag & CRTSCTS)
 		mos7840_port->shadowMCR |= (MCR_XON_ANY);
-
-	} else {
+	else
 		mos7840_port->shadowMCR &= ~(MCR_XON_ANY);
-	}
 
 	Data = mos7840_port->shadowMCR;
 	mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
@@ -2131,14 +2063,14 @@
  *	the termios structure
  *****************************************************************************/
 
-static void mos7840_set_termios(struct usb_serial_port *port,
+static void mos7840_set_termios(struct tty_struct *tty,
+				struct usb_serial_port *port,
 				struct ktermios *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, __func__)) {
 		dbg("%s", "Invalid port \n");
@@ -2157,8 +2089,6 @@
 	if (mos7840_port == NULL)
 		return;
 
-	tty = port->tty;
-
 	if (!mos7840_port->open) {
 		dbg("%s - port not opened", __func__);
 		return;
@@ -2176,7 +2106,7 @@
 
 	/* change the port settings to the new ones specified */
 
-	mos7840_change_port_settings(mos7840_port, old_termios);
+	mos7840_change_port_settings(tty, mos7840_port, old_termios);
 
 	if (!mos7840_port->read_urb) {
 		dbg("%s", "URB KILLED !!!!!\n");
@@ -2205,13 +2135,13 @@
  * 	    allows an RS485 driver to be written in user space.
  *****************************************************************************/
 
-static int mos7840_get_lsr_info(struct moschip_port *mos7840_port,
+static int mos7840_get_lsr_info(struct tty_struct *tty,
 				unsigned int __user *value)
 {
 	int count;
 	unsigned int result = 0;
 
-	count = mos7840_chars_in_buffer(mos7840_port->port);
+	count = mos7840_chars_in_buffer(tty);
 	if (count == 0) {
 		dbg("%s -- Empty", __func__);
 		result = TIOCSER_TEMT;
@@ -2227,6 +2157,8 @@
  *      function to set modem info
  *****************************************************************************/
 
+/* FIXME: Should be using the model control hooks */
+
 static int mos7840_set_modem_info(struct moschip_port *mos7840_port,
 				  unsigned int cmd, unsigned int __user *value)
 {
@@ -2282,7 +2214,6 @@
 	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");
@@ -2303,10 +2234,8 @@
 	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);
+        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 */
@@ -2359,12 +2288,12 @@
  *	this function handles any ioctl calls to the driver
  *****************************************************************************/
 
-static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
+static int mos7840_ioctl(struct tty_struct *tty, struct file *file,
 			 unsigned int cmd, unsigned long arg)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	void __user *argp = (void __user *)arg;
 	struct moschip_port *mos7840_port;
-	struct tty_struct *tty;
 
 	struct async_icount cnow;
 	struct async_icount cprev;
@@ -2381,8 +2310,6 @@
 	if (mos7840_port == NULL)
 		return -1;
 
-	tty = mos7840_port->port->tty;
-
 	dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
 
 	switch (cmd) {
@@ -2390,9 +2317,10 @@
 
 	case TIOCSERGETLSR:
 		dbg("%s (%d) TIOCSERGETLSR", __func__, port->number);
-		return mos7840_get_lsr_info(mos7840_port, argp);
+		return mos7840_get_lsr_info(tty, argp);
 		return 0;
 
+	/* FIXME: use the modem hooks and remove this */
 	case TIOCMBIS:
 	case TIOCMBIC:
 	case TIOCMSET:
@@ -2418,7 +2346,7 @@
 		dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
 		cprev = mos7840_port->icount;
 		while (1) {
-			//interruptible_sleep_on(&mos7840_port->delta_msr_wait);
+			/* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */
 			mos7840_port->delta_msr_cond = 0;
 			wait_event_interruptible(mos7840_port->delta_msr_wait,
 						 (mos7840_port->
@@ -2463,13 +2391,9 @@
 		if (copy_to_user(argp, &icount, sizeof(icount)))
 			return -EFAULT;
 		return 0;
-
-	case TIOCEXBAUD:
-		return 0;
 	default:
 		break;
 	}
-
 	return -ENOIOCTLCMD;
 }
 
@@ -2527,8 +2451,9 @@
 			goto error;
 		}
 
-		/* Initialize all port interrupt end point to port 0 int endpoint *
-		 * Our device has only one interrupt end point comman to all port */
+		/* Initialize all port interrupt end point to port 0 int
+		 * endpoint. Our device has only one interrupt end point
+		 * common to all port */
 
 		mos7840_port->port = serial->port[i];
 		mos7840_set_port_private(serial->port[i], mos7840_port);
@@ -2564,27 +2489,23 @@
 			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);
+		/* 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 |= 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],
+		/* Data |= 0x20; //rx_disable bit */
+		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);
@@ -2593,13 +2514,11 @@
 			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
+		/* 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);
+		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;
@@ -2607,11 +2526,8 @@
 			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);
+		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;
@@ -2619,22 +2535,17 @@
 			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);
+		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
+		/* write values in clkstart0x0 and clkmulti 0x20 */
 		Data = 0x0;
-		status = 0;
-		status =
-		    mos7840_set_reg_sync(serial->port[i],
+		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);
@@ -2643,9 +2554,8 @@
 			dbg("CLK_START_VALUE_REGISTER Writing success status%d\n", status);
 
 		Data = 0x20;
-		status =
-		    mos7840_set_reg_sync(serial->port[i], CLK_MULTI_REGISTER,
-					 Data);
+		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);
@@ -2654,11 +2564,10 @@
 			dbg("CLK_MULTI_REGISTER Writing success status%d\n",
 			    status);
 
-		//write value 0x0 to scratchpad register
+		/* write value 0x0 to scratchpad register */
 		Data = 0x00;
-		status =
-		    mos7840_set_uart_reg(serial->port[i], SCRATCH_PAD_REGISTER,
-					 Data);
+		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);
@@ -2667,21 +2576,17 @@
 			dbg("SCRATCH_PAD_REGISTER Writing success status%d\n",
 			    status);
 
-		//Zero Length flag register
+		/* Zero Length flag register */
 		if ((mos7840_port->port_num != 1)
 		    && (serial->num_ports == 2)) {
 
 			Data = 0xff;
-			status = 0;
 			status = mos7840_set_reg_sync(serial->port[i],
-						      (__u16) (ZLP_REG1 +
-							       ((__u16)
-								mos7840_port->
-								port_num)),
-						      Data);
+				      (__u16) (ZLP_REG1 +
+				      ((__u16)mos7840_port->port_num)), Data);
 			dbg("ZLIP offset%x\n",
 			    (__u16) (ZLP_REG1 +
-				     ((__u16) mos7840_port->port_num)));
+					((__u16) mos7840_port->port_num)));
 			if (status < 0) {
 				dbg("Writing ZLP_REG%d failed status-0x%x\n",
 				    i + 2, status);
@@ -2691,13 +2596,9 @@
 				    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);
+			      (__u16) (ZLP_REG1 +
+			      ((__u16)mos7840_port->port_num) - 0x1), Data);
 			dbg("ZLIP offset%x\n",
 			    (__u16) (ZLP_REG1 +
 				     ((__u16) mos7840_port->port_num) - 0x1));
@@ -2712,14 +2613,16 @@
 		}
 		mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL);
 		mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL);
-		mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
-		if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf || !mos7840_port->dr) {
+		mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest),
+								GFP_KERNEL);
+		if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf ||
+							!mos7840_port->dr) {
 			status = -ENOMEM;
 			goto error;
 		}
 	}
 
-	//Zero Length flag enable
+	/* Zero Length flag enable */
 	Data = 0x0f;
 	status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data);
 	if (status < 0) {
@@ -2762,7 +2665,7 @@
 		return;
 	}
 
-	/*      check for the ports to be closed,close the ports and disconnect         */
+	/* 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                */
@@ -2843,20 +2746,12 @@
 
 	/* 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:
-
+failed_port_device_register:
 	return retval;
 }
 
diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c
index 43c8894..d673653 100644
--- a/drivers/usb/serial/navman.c
+++ b/drivers/usb/serial/navman.c
@@ -64,7 +64,7 @@
 	usb_serial_debug_data(debug, &port->dev, __func__,
 			      urb->actual_length, data);
 
-	tty = port->tty;
+	tty = port->port.tty;
 	if (tty && urb->actual_length) {
 		tty_buffer_request_room(tty, urb->actual_length);
 		tty_insert_flip_string(tty, data, urb->actual_length);
@@ -79,7 +79,8 @@
 			__func__, result);
 }
 
-static int navman_open(struct usb_serial_port *port, struct file *filp)
+static int navman_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	int result = 0;
 
@@ -96,14 +97,15 @@
 	return result;
 }
 
-static void navman_close(struct usb_serial_port *port, struct file *filp)
+static void navman_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	dbg("%s - port %d", __func__, port->number);
 
 	usb_kill_urb(port->interrupt_in_urb);
 }
 
-static int navman_write(struct usb_serial_port *port,
+static int navman_write(struct tty_struct *tty, struct usb_serial_port *port,
 			const unsigned char *buf, int count)
 {
 	dbg("%s - port %d", __func__, port->number);
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 7b7422f..ae8e227 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -5,26 +5,28 @@
  *	modify it under the terms of the GNU General Public License version
  *	2 as published by the Free Software Foundation.
  *
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
  *
  * Please report both successes and troubles to the author at omninet@kroah.com
- * 
+ *
  * (05/30/2001) gkh
- *	switched from using spinlock to a semaphore, which fixes lots of problems.
+ *	switched from using spinlock to a semaphore, which fixes lots of
+ *	problems.
  *
  * (04/08/2001) gb
  *	Identify version on module load.
  *
  * (11/01/2000) Adam J. Richter
  *	usb_device_id table support
- * 
+ *
  * (10/05/2000) gkh
  *	Fixed bug with urb->dev not being set properly, now that the usb
  *	core needs it.
- * 
+ *
  * (08/28/2000) gkh
  *	Added locks for SMP safeness.
- *	Fixed MOD_INC and MOD_DEC logic and the ability to open a port more 
+ *	Fixed MOD_INC and MOD_DEC logic and the ability to open a port more
  *	than once.
  *	Fixed potential race in omninet_write_bulk_callback
  *
@@ -43,7 +45,7 @@
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
@@ -58,25 +60,29 @@
 
 #define ZYXEL_VENDOR_ID		0x0586
 #define ZYXEL_OMNINET_ID	0x1000
-#define BT_IGNITIONPRO_ID	0x2000  /* This one seems to be a re-branded ZyXEL device */
+/* This one seems to be a re-branded ZyXEL device */
+#define BT_IGNITIONPRO_ID	0x2000
 
 /* function prototypes */
-static int  omninet_open		(struct usb_serial_port *port, struct file *filp);
-static void omninet_close		(struct usb_serial_port *port, struct file *filp);
-static void omninet_read_bulk_callback	(struct urb *urb);
-static void omninet_write_bulk_callback	(struct urb *urb);
-static int  omninet_write		(struct usb_serial_port *port, const unsigned char *buf, int count);
-static int  omninet_write_room		(struct usb_serial_port *port);
-static void omninet_shutdown		(struct usb_serial *serial);
-static int omninet_attach		(struct usb_serial *serial);
+static int  omninet_open(struct tty_struct *tty, struct usb_serial_port *port,
+							struct file *filp);
+static void omninet_close(struct tty_struct *tty, struct usb_serial_port *port,
+							struct file *filp);
+static void omninet_read_bulk_callback(struct urb *urb);
+static void omninet_write_bulk_callback(struct urb *urb);
+static int  omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
+				const unsigned char *buf, int count);
+static int  omninet_write_room(struct tty_struct *tty);
+static void omninet_shutdown(struct usb_serial *serial);
+static int omninet_attach(struct usb_serial *serial);
 
-static struct usb_device_id id_table [] = {
+static struct usb_device_id id_table[] = {
 	{ USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) },
 	{ USB_DEVICE(ZYXEL_VENDOR_ID, BT_IGNITIONPRO_ID) },
 	{ }						/* Terminating entry */
 };
 
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
 
 static struct usb_driver omninet_driver = {
 	.name =		"omninet",
@@ -130,34 +136,34 @@
  *
  */
 
-struct omninet_header
-{
+struct omninet_header {
 	__u8	oh_seq;
 	__u8	oh_len;
 	__u8	oh_xxx;
 	__u8	oh_pad;
 };
 
-struct omninet_data
-{
-	__u8	od_outseq;	// Sequence number for bulk_out URBs
+struct omninet_data {
+	__u8	od_outseq;	/* Sequence number for bulk_out URBs */
 };
 
-static int omninet_attach (struct usb_serial *serial)
+static int omninet_attach(struct usb_serial *serial)
 {
 	struct omninet_data *od;
 	struct usb_serial_port *port = serial->port[0];
 
-	od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL );
-	if( !od ) {
-		err("%s- kmalloc(%Zd) failed.", __func__, sizeof(struct omninet_data));
+	od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL);
+	if (!od) {
+		err("%s- kmalloc(%Zd) failed.",
+				__func__, sizeof(struct omninet_data));
 		return -ENOMEM;
 	}
 	usb_set_serial_port_data(port, od);
 	return 0;
 }
 
-static int omninet_open (struct usb_serial_port *port, struct file *filp)
+static int omninet_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct usb_serial	*serial = port->serial;
 	struct usb_serial_port	*wport;
@@ -166,22 +172,24 @@
 	dbg("%s - port %d", __func__, port->number);
 
 	wport = serial->port[1];
-	wport->tty = port->tty;
+	wport->port.tty = tty;		/* FIXME */
 
 	/* 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,
-		      omninet_read_bulk_callback, port);
+	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,
+			omninet_read_bulk_callback, port);
 	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
-	if (result) {
-		err("%s - failed submitting read urb, error %d", __func__, result);
-	}
-
+	if (result)
+		err("%s - failed submitting read urb, error %d",
+							__func__, result);
 	return result;
 }
 
-static void omninet_close (struct usb_serial_port *port, struct file * filp)
+static void omninet_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	dbg("%s - port %d", __func__, port->number);
 	usb_kill_urb(port->read_urb);
@@ -192,14 +200,14 @@
 #define OMNINET_HEADERLEN	sizeof(struct omninet_header)
 #define OMNINET_BULKOUTSIZE 	(64 - OMNINET_HEADERLEN)
 
-static void omninet_read_bulk_callback (struct urb *urb)
+static void omninet_read_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port 	*port 	= urb->context;
 	unsigned char 		*data 	= urb->transfer_buffer;
 	struct omninet_header 	*header = (struct omninet_header *) &data[0];
 	int status = urb->status;
-	int i;
 	int result;
+	int i;
 
 	dbg("%s - port %d", __func__, port->number);
 
@@ -209,42 +217,46 @@
 		return;
 	}
 
-	if ((debug) && (header->oh_xxx != 0x30)) {
+	if (debug && header->oh_xxx != 0x30) {
 		if (urb->actual_length) {
-			printk (KERN_DEBUG __FILE__ ": omninet_read %d: ", header->oh_len);
-			for (i = 0; i < (header->oh_len + OMNINET_HEADERLEN); i++) {
-				printk ("%.2x ", data[i]);
-			}
-			printk ("\n");
+			printk(KERN_DEBUG __FILE__
+					": omninet_read %d: ", header->oh_len);
+			for (i = 0; i < (header->oh_len +
+						OMNINET_HEADERLEN); i++)
+				printk("%.2x ", data[i]);
+			printk("\n");
 		}
 	}
 
 	if (urb->actual_length && header->oh_len) {
-		for (i = 0; i < header->oh_len; i++) {
-			 tty_insert_flip_char(port->tty, data[OMNINET_DATAOFFSET + i], 0);
-	  	}
-	  	tty_flip_buffer_push(port->tty);
+		tty_insert_flip_string(port->port.tty,
+			data + OMNINET_DATAOFFSET, header->oh_len);
+		tty_flip_buffer_push(port->port.tty);
 	}
 
 	/* Continue trying to always read  */
-	usb_fill_bulk_urb(urb, port->serial->dev, 
-		      usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress),
-		      urb->transfer_buffer, urb->transfer_buffer_length,
-		      omninet_read_bulk_callback, port);
+	usb_fill_bulk_urb(urb, port->serial->dev,
+			usb_rcvbulkpipe(port->serial->dev,
+					port->bulk_in_endpointAddress),
+			urb->transfer_buffer, urb->transfer_buffer_length,
+			omninet_read_bulk_callback, port);
 	result = usb_submit_urb(urb, GFP_ATOMIC);
 	if (result)
-		err("%s - failed resubmitting read urb, error %d", __func__, result);
+		err("%s - failed resubmitting read urb, error %d",
+						__func__, result);
 
 	return;
 }
 
-static int omninet_write (struct usb_serial_port *port, const unsigned char *buf, int count)
+static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
+					const unsigned char *buf, int count)
 {
-	struct usb_serial 	*serial	= port->serial;
-	struct usb_serial_port 	*wport	= serial->port[1];
+	struct usb_serial *serial = port->serial;
+	struct usb_serial_port *wport = serial->port[1];
 
-	struct omninet_data 	*od 	= usb_get_serial_port_data(port);
-	struct omninet_header	*header = (struct omninet_header *) wport->write_urb->transfer_buffer;
+	struct omninet_data *od = usb_get_serial_port_data(port);
+	struct omninet_header *header = (struct omninet_header *)
+					wport->write_urb->transfer_buffer;
 
 	int			result;
 
@@ -252,7 +264,7 @@
 
 	if (count == 0) {
 		dbg("%s - write request of 0 bytes", __func__);
-		return (0);
+		return 0;
 	}
 
 	spin_lock_bh(&wport->lock);
@@ -266,9 +278,11 @@
 
 	count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count;
 
-	memcpy (wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, buf, count);
+	memcpy(wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET,
+								buf, count);
 
-	usb_serial_debug_data(debug, &port->dev, __func__, count, wport->write_urb->transfer_buffer);
+	usb_serial_debug_data(debug, &port->dev, __func__, count,
+					wport->write_urb->transfer_buffer);
 
 	header->oh_seq 	= od->od_outseq++;
 	header->oh_len 	= count;
@@ -282,7 +296,8 @@
 	result = usb_submit_urb(wport->write_urb, GFP_ATOMIC);
 	if (result) {
 		wport->write_urb_busy = 0;
-		err("%s - failed submitting write urb, error %d", __func__, result);
+		err("%s - failed submitting write urb, error %d",
+							__func__, result);
 	} else
 		result = count;
 
@@ -290,8 +305,9 @@
 }
 
 
-static int omninet_write_room (struct usb_serial_port *port)
+static int omninet_write_room(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct usb_serial 	*serial = port->serial;
 	struct usb_serial_port 	*wport 	= serial->port[1];
 
@@ -303,12 +319,13 @@
 
 	dbg("%s - returns %d", __func__, room);
 
-	return (room);
+	return room;
 }
 
-static void omninet_write_bulk_callback (struct urb *urb)
+static void omninet_write_bulk_callback(struct urb *urb)
 {
-/*	struct omninet_header	*header = (struct omninet_header  *) urb->transfer_buffer; */
+/*	struct omninet_header	*header = (struct omninet_header  *)
+						urb->transfer_buffer; */
 	struct usb_serial_port 	*port   =  urb->context;
 	int status = urb->status;
 
@@ -325,18 +342,18 @@
 }
 
 
-static void omninet_shutdown (struct usb_serial *serial)
+static void omninet_shutdown(struct usb_serial *serial)
 {
 	struct usb_serial_port *wport = serial->port[1];
 	struct usb_serial_port *port = serial->port[0];
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 
 	usb_kill_urb(wport->write_urb);
 	kfree(usb_get_serial_port_data(port));
 }
 
 
-static int __init omninet_init (void)
+static int __init omninet_init(void)
 {
 	int retval;
 	retval = usb_serial_register(&zyxel_omninet_device);
@@ -354,18 +371,18 @@
 }
 
 
-static void __exit omninet_exit (void)
+static void __exit omninet_exit(void)
 {
-	usb_deregister (&omninet_driver);
-	usb_serial_deregister (&zyxel_omninet_device);
+	usb_deregister(&omninet_driver);
+	usb_serial_deregister(&zyxel_omninet_device);
 }
 
 
 module_init(omninet_init);
 module_exit(omninet_exit);
 
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index a73420d..e4eca95 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -43,29 +43,25 @@
 #include <linux/usb/serial.h>
 
 /* Function prototypes */
-static int  option_open(struct usb_serial_port *port, struct file *filp);
-static void option_close(struct usb_serial_port *port, struct file *filp);
+static int  option_open(struct tty_struct *tty, struct usb_serial_port *port,
+							struct file *filp);
+static void option_close(struct tty_struct *tty, struct usb_serial_port *port,
+							struct file *filp);
 static int  option_startup(struct usb_serial *serial);
 static void option_shutdown(struct usb_serial *serial);
-static void option_rx_throttle(struct usb_serial_port *port);
-static void option_rx_unthrottle(struct usb_serial_port *port);
-static int  option_write_room(struct usb_serial_port *port);
+static int  option_write_room(struct tty_struct *tty);
 
 static void option_instat_callback(struct urb *urb);
 
-static int option_write(struct usb_serial_port *port,
+static int option_write(struct tty_struct *tty, struct usb_serial_port *port,
 			const unsigned char *buf, int count);
-
-static int  option_chars_in_buffer(struct usb_serial_port *port);
-static int  option_ioctl(struct usb_serial_port *port, struct file *file,
-			unsigned int cmd, unsigned long arg);
-static void option_set_termios(struct usb_serial_port *port,
-				struct ktermios *old);
-static void option_break_ctl(struct usb_serial_port *port, int break_state);
-static int  option_tiocmget(struct usb_serial_port *port, struct file *file);
-static int  option_tiocmset(struct usb_serial_port *port, struct file *file,
+static int  option_chars_in_buffer(struct tty_struct *tty);
+static void option_set_termios(struct tty_struct *tty,
+			struct usb_serial_port *port, struct ktermios *old);
+static int  option_tiocmget(struct tty_struct *tty, struct file *file);
+static int  option_tiocmset(struct tty_struct *tty, struct file *file,
 				unsigned int set, unsigned int clear);
-static int  option_send_setup(struct usb_serial_port *port);
+static int  option_send_setup(struct tty_struct *tty, struct usb_serial_port *port);
 
 /* Vendor and product IDs */
 #define OPTION_VENDOR_ID			0x0AF0
@@ -173,6 +169,7 @@
 #define DELL_VENDOR_ID				0x413C
 
 #define KYOCERA_VENDOR_ID			0x0c88
+#define KYOCERA_PRODUCT_KPC650			0x17da
 #define KYOCERA_PRODUCT_KPC680			0x180a
 
 #define ANYDATA_VENDOR_ID			0x16d5
@@ -305,6 +302,7 @@
 	{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_ET502HS) },
 	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) },
 	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
+	{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC650) },
 	{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },
 	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */
 	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
@@ -340,11 +338,7 @@
 	.write             = option_write,
 	.write_room        = option_write_room,
 	.chars_in_buffer   = option_chars_in_buffer,
-	.throttle          = option_rx_throttle,
-	.unthrottle        = option_rx_unthrottle,
-	.ioctl             = option_ioctl,
 	.set_termios       = option_set_termios,
-	.break_ctl         = option_break_ctl,
 	.tiocmget          = option_tiocmget,
 	.tiocmset          = option_tiocmset,
 	.attach            = option_startup,
@@ -401,47 +395,32 @@
 	return 0;
 
 failed_driver_register:
-	usb_serial_deregister (&option_1port_device);
+	usb_serial_deregister(&option_1port_device);
 failed_1port_device_register:
 	return retval;
 }
 
 static void __exit option_exit(void)
 {
-	usb_deregister (&option_driver);
-	usb_serial_deregister (&option_1port_device);
+	usb_deregister(&option_driver);
+	usb_serial_deregister(&option_1port_device);
 }
 
 module_init(option_init);
 module_exit(option_exit);
 
-static void option_rx_throttle(struct usb_serial_port *port)
-{
-	dbg("%s", __func__);
-}
-
-static void option_rx_unthrottle(struct usb_serial_port *port)
-{
-	dbg("%s", __func__);
-}
-
-static void option_break_ctl(struct usb_serial_port *port, int break_state)
-{
-	/* Unfortunately, I don't know how to send a break */
-	dbg("%s", __func__);
-}
-
-static void option_set_termios(struct usb_serial_port *port,
-			struct ktermios *old_termios)
+static void option_set_termios(struct tty_struct *tty,
+		struct usb_serial_port *port, struct ktermios *old_termios)
 {
 	dbg("%s", __func__);
 	/* Doesn't support option setting */
-	tty_termios_copy_hw(port->tty->termios, old_termios);
-	option_send_setup(port);
+	tty_termios_copy_hw(tty->termios, old_termios);
+	option_send_setup(tty, port);
 }
 
-static int option_tiocmget(struct usb_serial_port *port, struct file *file)
+static int option_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	unsigned int value;
 	struct option_port_private *portdata;
 
@@ -457,9 +436,10 @@
 	return value;
 }
 
-static int option_tiocmset(struct usb_serial_port *port, struct file *file,
+static int option_tiocmset(struct tty_struct *tty, struct file *file,
 			unsigned int set, unsigned int clear)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct option_port_private *portdata;
 
 	portdata = usb_get_serial_port_data(port);
@@ -474,17 +454,11 @@
 		portdata->rts_state = 0;
 	if (clear & TIOCM_DTR)
 		portdata->dtr_state = 0;
-	return option_send_setup(port);
-}
-
-static int option_ioctl(struct usb_serial_port *port, struct file *file,
-			unsigned int cmd, unsigned long arg)
-{
-	return -ENOIOCTLCMD;
+	return option_send_setup(tty, port);
 }
 
 /* Write */
-static int option_write(struct usb_serial_port *port,
+static int option_write(struct tty_struct *tty, struct usb_serial_port *port,
 			const unsigned char *buf, int count)
 {
 	struct option_port_private *portdata;
@@ -499,7 +473,7 @@
 
 	i = 0;
 	left = count;
-	for (i=0; left > 0 && i < N_OUT_URB; i++) {
+	for (i = 0; left > 0 && i < N_OUT_URB; i++) {
 		todo = left;
 		if (todo > OUT_BUFLEN)
 			todo = OUT_BUFLEN;
@@ -520,7 +494,7 @@
 			usb_pipeendpoint(this_urb->pipe), i);
 
 		/* send the data */
-		memcpy (this_urb->transfer_buffer, buf, todo);
+		memcpy(this_urb->transfer_buffer, buf, todo);
 		this_urb->transfer_buffer_length = todo;
 
 		this_urb->dev = port->serial->dev;
@@ -560,7 +534,7 @@
 		dbg("%s: nonzero status: %d on endpoint %02x.",
 		    __func__, status, endpoint);
 	} else {
-		tty = port->tty;
+		tty = port->port.tty;
 		if (urb->actual_length) {
 			tty_buffer_request_room(tty, urb->actual_length);
 			tty_insert_flip_string(tty, data, urb->actual_length);
@@ -570,7 +544,7 @@
 		}
 
 		/* Resubmit urb so we continue receiving */
-		if (port->open_count && status != -ESHUTDOWN) {
+		if (port->port.count && status != -ESHUTDOWN) {
 			err = usb_submit_urb(urb, GFP_ATOMIC);
 			if (err)
 				printk(KERN_ERR "%s: resubmit read urb failed. "
@@ -611,7 +585,7 @@
 	struct usb_serial *serial = port->serial;
 
 	dbg("%s", __func__);
-	dbg("%s: urb %p port %p has data %p", __func__,urb,port,portdata);
+	dbg("%s: urb %p port %p has data %p", __func__, urb, port, portdata);
 
 	if (status == 0) {
 		struct usb_ctrlrequest *req_pkt =
@@ -636,12 +610,12 @@
 			portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
 			portdata->ri_state = ((signals & 0x08) ? 1 : 0);
 
-			if (port->tty && !C_CLOCAL(port->tty) &&
+			if (port->port.tty && !C_CLOCAL(port->port.tty) &&
 					old_dcd_state && !portdata->dcd_state)
-				tty_hangup(port->tty);
+				tty_hangup(port->port.tty);
 		} else {
 			dbg("%s: type %x req %x", __func__,
-				req_pkt->bRequestType,req_pkt->bRequest);
+				req_pkt->bRequestType, req_pkt->bRequest);
 		}
 	} else
 		dbg("%s: error %d", __func__, status);
@@ -656,8 +630,9 @@
 	}
 }
 
-static int option_write_room(struct usb_serial_port *port)
+static int option_write_room(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct option_port_private *portdata;
 	int i;
 	int data_len = 0;
@@ -666,7 +641,7 @@
 	portdata = usb_get_serial_port_data(port);
 
 
-	for (i=0; i < N_OUT_URB; i++) {
+	for (i = 0; i < N_OUT_URB; i++) {
 		this_urb = portdata->out_urbs[i];
 		if (this_urb && !test_bit(i, &portdata->out_busy))
 			data_len += OUT_BUFLEN;
@@ -676,8 +651,9 @@
 	return data_len;
 }
 
-static int option_chars_in_buffer(struct usb_serial_port *port)
+static int option_chars_in_buffer(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct option_port_private *portdata;
 	int i;
 	int data_len = 0;
@@ -685,7 +661,7 @@
 
 	portdata = usb_get_serial_port_data(port);
 
-	for (i=0; i < N_OUT_URB; i++) {
+	for (i = 0; i < N_OUT_URB; i++) {
 		this_urb = portdata->out_urbs[i];
 		/* FIXME: This locking is insufficient as this_urb may
 		   go unused during the test */
@@ -696,7 +672,8 @@
 	return data_len;
 }
 
-static int option_open(struct usb_serial_port *port, struct file *filp)
+static int option_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct option_port_private *portdata;
 	struct usb_serial *serial = port->serial;
@@ -714,7 +691,7 @@
 	/* Reset low level data toggle and start reading from endpoints */
 	for (i = 0; i < N_IN_URB; i++) {
 		urb = portdata->in_urbs[i];
-		if (! urb)
+		if (!urb)
 			continue;
 		if (urb->dev != serial->dev) {
 			dbg("%s: dev %p != %p", __func__,
@@ -739,21 +716,23 @@
 	/* Reset low level data toggle on out endpoints */
 	for (i = 0; i < N_OUT_URB; i++) {
 		urb = portdata->out_urbs[i];
-		if (! urb)
+		if (!urb)
 			continue;
 		urb->dev = serial->dev;
 		/* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
 				usb_pipeout(urb->pipe), 0); */
 	}
 
-	port->tty->low_latency = 1;
+	if (tty)
+		tty->low_latency = 1;
 
-	option_send_setup(port);
+	option_send_setup(tty, port);
 
-	return (0);
+	return 0;
 }
 
-static void option_close(struct usb_serial_port *port, struct file *filp)
+static void option_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	int i;
 	struct usb_serial *serial = port->serial;
@@ -768,7 +747,7 @@
 	if (serial->dev) {
 		mutex_lock(&serial->disc_mutex);
 		if (!serial->disconnected)
-			option_send_setup(port);
+			option_send_setup(tty, port);
 		mutex_unlock(&serial->disc_mutex);
 
 		/* Stop reading/writing urbs */
@@ -777,7 +756,7 @@
 		for (i = 0; i < N_OUT_URB; i++)
 			usb_kill_urb(portdata->out_urbs[i]);
 	}
-	port->tty = NULL;
+	port->port.tty = NULL;	/* FIXME */
 }
 
 /* Helper functions used by option_setup_urbs */
@@ -807,7 +786,7 @@
 /* Setup urbs */
 static void option_setup_urbs(struct usb_serial *serial)
 {
-	int i,j;
+	int i, j;
 	struct usb_serial_port *port;
 	struct option_port_private *portdata;
 
@@ -817,18 +796,22 @@
 		port = serial->port[i];
 		portdata = usb_get_serial_port_data(port);
 
-	/* Do indat endpoints first */
+		/* Do indat endpoints first */
 		for (j = 0; j < N_IN_URB; ++j) {
-			portdata->in_urbs[j] = option_setup_urb (serial,
-                  	port->bulk_in_endpointAddress, USB_DIR_IN, port,
-                  	portdata->in_buffer[j], IN_BUFLEN, option_indat_callback);
+			portdata->in_urbs[j] = option_setup_urb(serial,
+					port->bulk_in_endpointAddress,
+					USB_DIR_IN, port,
+					portdata->in_buffer[j],
+					IN_BUFLEN, option_indat_callback);
 		}
 
 		/* outdat endpoints */
 		for (j = 0; j < N_OUT_URB; ++j) {
-			portdata->out_urbs[j] = option_setup_urb (serial,
-                  	port->bulk_out_endpointAddress, USB_DIR_OUT, port,
-                  	portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback);
+			portdata->out_urbs[j] = option_setup_urb(serial,
+					port->bulk_out_endpointAddress,
+					USB_DIR_OUT, port,
+					portdata->out_buffer[j],
+					OUT_BUFLEN, option_outdat_callback);
 		}
 	}
 }
@@ -839,7 +822,8 @@
  * This is exactly the same as SET_CONTROL_LINE_STATE from the PSTN
  * CDC.
 */
-static int option_send_setup(struct usb_serial_port *port)
+static int option_send_setup(struct tty_struct *tty,
+						struct usb_serial_port *port)
 {
 	struct usb_serial *serial = port->serial;
 	struct option_port_private *portdata;
@@ -848,7 +832,7 @@
 
 	portdata = usb_get_serial_port_data(port);
 
-	if (port->tty) {
+	if (tty) {
 		int val = 0;
 		if (portdata->dtr_state)
 			val |= 0x01;
@@ -856,10 +840,9 @@
 			val |= 0x02;
 
 		return usb_control_msg(serial->dev,
-				usb_rcvctrlpipe(serial->dev, 0),
-				0x22,0x21,val,ifNum,NULL,0,USB_CTRL_SET_TIMEOUT);
+			usb_rcvctrlpipe(serial->dev, 0),
+			0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT);
 	}
-
 	return 0;
 }
 
@@ -879,7 +862,7 @@
 		if (!portdata) {
 			dbg("%s: kmalloc for option_port_private (%d) failed!.",
 					__func__, i);
-			return (1);
+			return 1;
 		}
 
 		for (j = 0; j < N_IN_URB; j++) {
@@ -898,17 +881,15 @@
 
 		usb_set_serial_port_data(port, portdata);
 
-		if (! port->interrupt_in_urb)
+		if (!port->interrupt_in_urb)
 			continue;
 		err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
 		if (err)
 			dbg("%s: submit irq_in urb failed %d",
 				__func__, err);
 	}
-
 	option_setup_urbs(serial);
-
-	return (0);
+	return 0;
 
 bail_out_error2:
 	for (j = 0; j < N_OUT_URB; j++)
@@ -947,7 +928,8 @@
 		for (j = 0; j < N_IN_URB; j++) {
 			if (portdata->in_urbs[j]) {
 				usb_free_urb(portdata->in_urbs[j]);
-				free_page((unsigned long)portdata->in_buffer[j]);
+				free_page((unsigned long)
+					portdata->in_buffer[j]);
 				portdata->in_urbs[j] = NULL;
 			}
 		}
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index a9625c1..81db571 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -25,7 +25,8 @@
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License.
  *
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
  *
  * TODO:
  *  - implement correct flushing for ioctls and oti6858_close()
@@ -49,7 +50,7 @@
 #include <linux/spinlock.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include "oti6858.h"
 
 #define OTI6858_DESCRIPTION \
@@ -135,27 +136,28 @@
 
 #define OTI6858_CTRL_PKT_SIZE	sizeof(struct oti6858_control_pkt)
 #define OTI6858_CTRL_EQUALS_PENDING(a, priv) \
-	(    ((a)->divisor == (priv)->pending_setup.divisor) \
+	(((a)->divisor == (priv)->pending_setup.divisor) \
 	  && ((a)->control == (priv)->pending_setup.control) \
-	  && ((a)->frame_fmt == (priv)->pending_setup.frame_fmt) )
+	  && ((a)->frame_fmt == (priv)->pending_setup.frame_fmt))
 
 /* function prototypes */
-static int oti6858_open(struct usb_serial_port *port, struct file *filp);
-static void oti6858_close(struct usb_serial_port *port, struct file *filp);
-static void oti6858_set_termios(struct usb_serial_port *port,
-				struct ktermios *old);
-static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
+static int oti6858_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
+static void oti6858_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
+static void oti6858_set_termios(struct tty_struct *tty,
+			struct usb_serial_port *port, struct ktermios *old);
+static int oti6858_ioctl(struct tty_struct *tty, struct file *file,
 			unsigned int cmd, unsigned long arg);
 static void oti6858_read_int_callback(struct urb *urb);
 static void oti6858_read_bulk_callback(struct urb *urb);
 static void oti6858_write_bulk_callback(struct urb *urb);
-static int oti6858_write(struct usb_serial_port *port,
+static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port,
 			const unsigned char *buf, int count);
-static int oti6858_write_room(struct usb_serial_port *port);
-static void oti6858_break_ctl(struct usb_serial_port *port, int break_state);
-static int oti6858_chars_in_buffer(struct usb_serial_port *port);
-static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file);
-static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file,
+static int oti6858_write_room(struct tty_struct *tty);
+static int oti6858_chars_in_buffer(struct tty_struct *tty);
+static int oti6858_tiocmget(struct tty_struct *tty, struct file *file);
+static int oti6858_tiocmset(struct tty_struct *tty, struct file *file,
 				unsigned int set, unsigned int clear);
 static int oti6858_startup(struct usb_serial *serial);
 static void oti6858_shutdown(struct usb_serial *serial);
@@ -184,7 +186,6 @@
 	.close =		oti6858_close,
 	.write =		oti6858_write,
 	.ioctl =		oti6858_ioctl,
-	.break_ctl =		oti6858_break_ctl,
 	.set_termios =		oti6858_set_termios,
 	.tiocmget =		oti6858_tiocmget,
 	.tiocmset =		oti6858_tiocmset,
@@ -220,7 +221,7 @@
 	struct delayed_work delayed_setup_work;
 
 	wait_queue_head_t intr_wait;
-        struct usb_serial_port *port;   /* USB port with which associated */
+	struct usb_serial_port *port;   /* USB port with which associated */
 };
 
 #undef dbg
@@ -229,7 +230,8 @@
 
 static void setup_line(struct work_struct *work)
 {
-	struct oti6858_private *priv = container_of(work, struct oti6858_private, delayed_setup_work.work);
+	struct oti6858_private *priv = container_of(work,
+			struct oti6858_private, delayed_setup_work.work);
 	struct usb_serial_port *port = priv->port;
 	struct oti6858_control_pkt *new_setup;
 	unsigned long flags;
@@ -237,10 +239,12 @@
 
 	dbg("%s(port = %d)", __func__, port->number);
 
-	if ((new_setup = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) {
+	new_setup = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL);
+	if (new_setup == NULL) {
 		dev_err(&port->dev, "%s(): out of memory!\n", __func__);
 		/* we will try again */
-		schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2));
+		schedule_delayed_work(&priv->delayed_setup_work,
+						msecs_to_jiffies(2));
 		return;
 	}
 
@@ -256,7 +260,8 @@
 		dev_err(&port->dev, "%s(): error reading status\n", __func__);
 		kfree(new_setup);
 		/* we will try again */
-		schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2));
+		schedule_delayed_work(&priv->delayed_setup_work,
+							msecs_to_jiffies(2));
 		return;
 	}
 
@@ -297,7 +302,8 @@
 
 void send_data(struct work_struct *work)
 {
-	struct oti6858_private *priv = container_of(work, struct oti6858_private, delayed_write_work.work);
+	struct oti6858_private *priv = container_of(work,
+			struct oti6858_private, delayed_write_work.work);
 	struct usb_serial_port *port = priv->port;
 	int count = 0, result;
 	unsigned long flags;
@@ -308,7 +314,8 @@
 	spin_lock_irqsave(&priv->lock, flags);
 	if (priv->flags.write_urb_in_use) {
 		spin_unlock_irqrestore(&priv->lock, flags);
-		schedule_delayed_work(&priv->delayed_write_work, msecs_to_jiffies(2));
+		schedule_delayed_work(&priv->delayed_write_work,
+						msecs_to_jiffies(2));
 		return;
 	}
 	priv->flags.write_urb_in_use = 1;
@@ -359,8 +366,8 @@
 
 static int oti6858_startup(struct usb_serial *serial)
 {
-        struct usb_serial_port *port = serial->port[0];
-        struct oti6858_private *priv;
+	struct usb_serial_port *port = serial->port[0];
+	struct oti6858_private *priv;
 	int i;
 
 	for (i = 0; i < serial->num_ports; ++i) {
@@ -375,8 +382,8 @@
 
 		spin_lock_init(&priv->lock);
 		init_waitqueue_head(&priv->intr_wait);
-//		INIT_WORK(&priv->setup_work, setup_line, serial->port[i]);
-//		INIT_WORK(&priv->write_work, send_data, serial->port[i]);
+/*		INIT_WORK(&priv->setup_work, setup_line, serial->port[i]); */
+/*		INIT_WORK(&priv->write_work, send_data, serial->port[i]); */
 		priv->port = port;
 		INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line);
 		INIT_DELAYED_WORK(&priv->delayed_write_work, send_data);
@@ -395,7 +402,7 @@
 	return -ENOMEM;
 }
 
-static int oti6858_write(struct usb_serial_port *port,
+static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port,
 			const unsigned char *buf, int count)
 {
 	struct oti6858_private *priv = usb_get_serial_port_data(port);
@@ -413,8 +420,9 @@
 	return count;
 }
 
-static int oti6858_write_room(struct usb_serial_port *port)
+static int oti6858_write_room(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct oti6858_private *priv = usb_get_serial_port_data(port);
 	int room = 0;
 	unsigned long flags;
@@ -428,8 +436,9 @@
 	return room;
 }
 
-static int oti6858_chars_in_buffer(struct usb_serial_port *port)
+static int oti6858_chars_in_buffer(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct oti6858_private *priv = usb_get_serial_port_data(port);
 	int chars = 0;
 	unsigned long flags;
@@ -443,8 +452,8 @@
 	return chars;
 }
 
-static void oti6858_set_termios(struct usb_serial_port *port,
-				struct ktermios *old_termios)
+static void oti6858_set_termios(struct tty_struct *tty,
+		struct usb_serial_port *port, struct ktermios *old_termios)
 {
 	struct oti6858_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
@@ -455,22 +464,22 @@
 
 	dbg("%s(port = %d)", __func__, port->number);
 
-	if (!port->tty || !port->tty->termios) {
+	if (!tty) {
 		dbg("%s(): no tty structures", __func__);
 		return;
 	}
 
 	spin_lock_irqsave(&priv->lock, flags);
 	if (!priv->flags.termios_initialized) {
-		*(port->tty->termios) = tty_std_termios;
-		port->tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
+		*(tty->termios) = tty_std_termios;
+		tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
+		tty->termios->c_ispeed = 38400;
+		tty->termios->c_ospeed = 38400;
 		priv->flags.termios_initialized = 1;
-		port->tty->termios->c_ispeed = 38400;
-		port->tty->termios->c_ospeed = 38400;
 	}
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	cflag = port->tty->termios->c_cflag;
+	cflag = tty->termios->c_cflag;
 
 	spin_lock_irqsave(&priv->lock, flags);
 	divisor = priv->pending_setup.divisor;
@@ -480,19 +489,19 @@
 
 	frame_fmt &= ~FMT_DATA_BITS_MASK;
 	switch (cflag & CSIZE) {
-		case CS5:
-			frame_fmt |= FMT_DATA_BITS_5;
-			break;
-		case CS6:
-			frame_fmt |= FMT_DATA_BITS_6;
-			break;
-		case CS7:
-			frame_fmt |= FMT_DATA_BITS_7;
-			break;
-		default:
-		case CS8:
-			frame_fmt |= FMT_DATA_BITS_8;
-			break;
+	case CS5:
+		frame_fmt |= FMT_DATA_BITS_5;
+		break;
+	case CS6:
+		frame_fmt |= FMT_DATA_BITS_6;
+		break;
+	case CS7:
+		frame_fmt |= FMT_DATA_BITS_7;
+		break;
+	default:
+	case CS8:
+		frame_fmt |= FMT_DATA_BITS_8;
+		break;
 	}
 
 	/* manufacturer claims that this device can work with baud rates
@@ -500,7 +509,7 @@
 	 * guarantee that any other baud rate will work (especially
 	 * the higher ones)
 	 */
-	br = tty_get_baud_rate(port->tty);
+	br = tty_get_baud_rate(tty);
 	if (br == 0) {
 		divisor = 0;
 	} else {
@@ -511,23 +520,21 @@
 		new_divisor = (96000000 + 8 * br) / (16 * br);
 		real_br = 96000000 / (16 * new_divisor);
 		divisor = cpu_to_le16(new_divisor);
-		tty_encode_baud_rate(port->tty, real_br, real_br);
+		tty_encode_baud_rate(tty, real_br, real_br);
 	}
 
 	frame_fmt &= ~FMT_STOP_BITS_MASK;
-	if ((cflag & CSTOPB) != 0) {
+	if ((cflag & CSTOPB) != 0)
 		frame_fmt |= FMT_STOP_BITS_2;
-	} else {
+	else
 		frame_fmt |= FMT_STOP_BITS_1;
-	}
 
 	frame_fmt &= ~FMT_PARITY_MASK;
 	if ((cflag & PARENB) != 0) {
-		if ((cflag & PARODD) != 0) {
+		if ((cflag & PARODD) != 0)
 			frame_fmt |= FMT_PARITY_ODD;
-		} else {
+		else
 			frame_fmt |= FMT_PARITY_EVEN;
-		}
 	} else {
 		frame_fmt |= FMT_PARITY_NONE;
 	}
@@ -564,7 +571,8 @@
 	spin_unlock_irqrestore(&priv->lock, flags);
 }
 
-static int oti6858_open(struct usb_serial_port *port, struct file *filp)
+static int oti6858_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct oti6858_private *priv = usb_get_serial_port_data(port);
 	struct ktermios tmp_termios;
@@ -578,10 +586,11 @@
 	usb_clear_halt(serial->dev, port->write_urb->pipe);
 	usb_clear_halt(serial->dev, port->read_urb->pipe);
 
-	if (port->open_count != 1)
+	if (port->port.count != 1)
 		return 0;
 
-	if ((buf = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) {
+	buf = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL);
+	if (buf == NULL) {
 		dev_err(&port->dev, "%s(): out of memory!\n", __func__);
 		return -ENOMEM;
 	}
@@ -617,18 +626,19 @@
 	if (result != 0) {
 		dev_err(&port->dev, "%s(): usb_submit_urb() failed"
 			       " with error %d\n", __func__, result);
-		oti6858_close(port, NULL);
+		oti6858_close(tty, port, NULL);
 		return -EPROTO;
 	}
 
 	/* setup termios */
-	if (port->tty)
-		oti6858_set_termios(port, &tmp_termios);
+	if (tty)
+		oti6858_set_termios(tty, port, &tmp_termios);
 
 	return 0;
 }
 
-static void oti6858_close(struct usb_serial_port *port, struct file *filp)
+static void oti6858_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct oti6858_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
@@ -641,7 +651,7 @@
 	spin_lock_irqsave(&priv->lock, flags);
 	timeout = 30 * HZ;	/* PL2303_CLOSING_WAIT */
 	init_waitqueue_entry(&wait, current);
-	add_wait_queue(&port->tty->write_wait, &wait);
+	add_wait_queue(&tty->write_wait, &wait);
 	dbg("%s(): entering wait loop", __func__);
 	for (;;) {
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -654,7 +664,7 @@
 		spin_lock_irqsave(&priv->lock, flags);
 	}
 	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&port->tty->write_wait, &wait);
+	remove_wait_queue(&tty->write_wait, &wait);
 	dbg("%s(): after wait loop", __func__);
 
 	/* clear out any remaining data in the buffer */
@@ -669,7 +679,7 @@
 	/* data is in the buffer to compute a delay */
 	/* that is not unnecessarily long) */
 	/* FIXME
-	bps = tty_get_baud_rate(port->tty);
+	bps = tty_get_baud_rate(tty);
 	if (bps > 1200)
 		timeout = max((HZ*2560)/bps,HZ/10);
 	else
@@ -690,7 +700,7 @@
 	usb_kill_urb(port->interrupt_in_urb);
 
 	/*
-	if (port->tty && (port->tty->termios->c_cflag) & HUPCL) {
+	if (tty && (tty->termios->c_cflag) & HUPCL) {
 		// drop DTR and RTS
 		spin_lock_irqsave(&priv->lock, flags);
 		priv->pending_setup.control &= ~CONTROL_MASK;
@@ -699,9 +709,10 @@
 	*/
 }
 
-static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file,
+static int oti6858_tiocmset(struct tty_struct *tty, struct file *file,
 				unsigned int set, unsigned int clear)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct oti6858_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	u8 control;
@@ -724,16 +735,16 @@
 	if ((clear & TIOCM_DTR) != 0)
 		control &= ~CONTROL_DTR_HIGH;
 
-	if (control != priv->pending_setup.control) {
+	if (control != priv->pending_setup.control)
 		priv->pending_setup.control = control;
-	}
-	spin_unlock_irqrestore(&priv->lock, flags);
 
+	spin_unlock_irqrestore(&priv->lock, flags);
 	return 0;
 }
 
-static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file)
+static int oti6858_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct oti6858_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	unsigned pin_state;
@@ -779,7 +790,8 @@
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	while (1) {
-		wait_event_interruptible(priv->intr_wait, priv->status.pin_state != prev);
+		wait_event_interruptible(priv->intr_wait,
+					priv->status.pin_state != prev);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 
@@ -789,12 +801,11 @@
 
 		changed = prev ^ status;
 		/* FIXME: check if this is correct (active high/low) */
-		if (	((arg & TIOCM_RNG) && (changed & PIN_RI)) ||
-			((arg & TIOCM_DSR) && (changed & PIN_DSR)) ||
-			((arg & TIOCM_CD)  && (changed & PIN_DCD)) ||
-			((arg & TIOCM_CTS) && (changed & PIN_CTS))) {
-				return 0;
-		}
+		if (((arg & TIOCM_RNG) && (changed & PIN_RI)) ||
+		    ((arg & TIOCM_DSR) && (changed & PIN_DSR)) ||
+		    ((arg & TIOCM_CD)  && (changed & PIN_DCD)) ||
+		    ((arg & TIOCM_CTS) && (changed & PIN_CTS)))
+			return 0;
 		prev = status;
 	}
 
@@ -802,56 +813,25 @@
 	return 0;
 }
 
-static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
+static int oti6858_ioctl(struct tty_struct *tty, struct file *file,
 			unsigned int cmd, unsigned long arg)
 {
-	void __user *user_arg = (void __user *) arg;
-	unsigned int x;
+	struct usb_serial_port *port = tty->driver_data;
 
 	dbg("%s(port = %d, cmd = 0x%04x, arg = 0x%08lx)",
 				__func__, port->number, cmd, arg);
 
 	switch (cmd) {
-		case TIOCMBIS:
-			if (copy_from_user(&x, user_arg, sizeof(x)))
-				return -EFAULT;
-			return oti6858_tiocmset(port, NULL, x, 0);
-
-		case TIOCMBIC:
-			if (copy_from_user(&x, user_arg, sizeof(x)))
-				return -EFAULT;
-			return oti6858_tiocmset(port, NULL, 0, x);
-
-		case TIOCMIWAIT:
-			dbg("%s(): TIOCMIWAIT", __func__);
-			return wait_modem_info(port, arg);
-
-		default:
-			dbg("%s(): 0x%04x not supported", __func__, cmd);
-			break;
+	case TIOCMIWAIT:
+		dbg("%s(): TIOCMIWAIT", __func__);
+		return wait_modem_info(port, arg);
+	default:
+		dbg("%s(): 0x%04x not supported", __func__, cmd);
+		break;
 	}
-
 	return -ENOIOCTLCMD;
 }
 
-static void oti6858_break_ctl(struct usb_serial_port *port, int break_state)
-{
-	int state;
-
-	dbg("%s(port = %d)", __func__, port->number);
-
-	state = (break_state == 0) ? 0 : 1;
-	dbg("%s(): turning break %s", __func__, state ? "on" : "off");
-
-	/* FIXME */
-/*
-	result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),
-				  BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
-				  0, NULL, 0, 100);
-	if (result != 0)
-		dbg("%s(): error sending break", __func__);
- */
-}
 
 static void oti6858_shutdown(struct usb_serial *serial)
 {
@@ -964,7 +944,7 @@
 		spin_lock_irqsave(&priv->lock, flags);
 		if (priv->flags.write_urb_in_use == 0
 				&& oti6858_buf_data_avail(priv->buf) != 0) {
-			schedule_delayed_work(&priv->delayed_write_work,0);
+			schedule_delayed_work(&priv->delayed_write_work, 0);
 			resubmit = 0;
 		}
 		spin_unlock_irqrestore(&priv->lock, flags);
@@ -973,7 +953,7 @@
 	if (resubmit) {
 		int result;
 
-//		dbg("%s(): submitting interrupt urb", __func__);
+/*		dbg("%s(): submitting interrupt urb", __func__); */
 		urb->dev = port->serial->dev;
 		result = usb_submit_urb(urb, GFP_ATOMIC);
 		if (result != 0) {
@@ -1002,14 +982,16 @@
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	if (status != 0) {
-		if (!port->open_count) {
+		if (!port->port.count) {
 			dbg("%s(): port is closed, exiting", __func__);
 			return;
 		}
 		/*
 		if (status == -EPROTO) {
-			// PL2303 mysteriously fails with -EPROTO reschedule the read
-			dbg("%s - caught -EPROTO, resubmitting the urb", __func__);
+			* PL2303 mysteriously fails with -EPROTO reschedule
+			   the read *
+			dbg("%s - caught -EPROTO, resubmitting the urb",
+								__func__);
 			result = usb_submit_urb(urb, GFP_ATOMIC);
 			if (result)
 				dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
@@ -1020,14 +1002,14 @@
 		return;
 	}
 
-	tty = port->tty;
+	tty = port->port.tty;
 	if (tty != NULL && urb->actual_length > 0) {
 		tty_insert_flip_string(tty, data, urb->actual_length);
 		tty_flip_buffer_push(tty);
 	}
 
-	// schedule the interrupt urb if we are still open */
-	if (port->open_count != 0) {
+	/* schedule the interrupt urb if we are still open */
+	if (port->port.count != 0) {
 		port->interrupt_in_urb->dev = port->serial->dev;
 		result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
 		if (result != 0) {
@@ -1078,7 +1060,7 @@
 
 	priv->flags.write_urb_in_use = 0;
 
-	// schedule the interrupt urb if we are still open */
+	/* schedule the interrupt urb if we are still open */
 	port->interrupt_in_urb->dev = port->serial->dev;
 	dbg("%s(): submitting interrupt urb", __func__);
 	result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
@@ -1153,7 +1135,7 @@
 {
 	if (pb == NULL)
 		return 0;
-	return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
+	return (pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size;
 }
 
 /*
@@ -1166,7 +1148,7 @@
 {
 	if (pb == NULL)
 		return 0;
-	return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
+	return (pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size;
 }
 
 /*
@@ -1253,13 +1235,12 @@
 {
 	int retval;
 
-	if ((retval = usb_serial_register(&oti6858_device)) == 0) {
-		if ((retval = usb_register(&oti6858_driver)) != 0)
+	retval = usb_serial_register(&oti6858_device);
+	if (retval == 0) {
+		retval = usb_register(&oti6858_driver);
+		if (retval)
 			usb_serial_deregister(&oti6858_device);
-		else
-			return 0;
 	}
-
 	return retval;
 }
 
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 2a0dd1b..2c9c446 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -10,7 +10,8 @@
  *	modify it under the terms of the GNU General Public License version
  *	2 as published by the Free Software Foundation.
  *
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
  *
  */
 
@@ -25,7 +26,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 #include "pl2303.h"
@@ -116,7 +117,7 @@
 #define CONTROL_RTS			0x02
 
 #define BREAK_REQUEST_TYPE		0x21
-#define BREAK_REQUEST			0x23	
+#define BREAK_REQUEST			0x23
 #define BREAK_ON			0xffff
 #define BREAK_OFF			0x0000
 
@@ -222,7 +223,7 @@
 	if (pb == NULL)
 		return 0;
 
-	return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
+	return (pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size;
 }
 
 /*
@@ -236,7 +237,7 @@
 	if (pb == NULL)
 		return 0;
 
-	return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
+	return (pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size;
 }
 
 /*
@@ -395,7 +396,7 @@
 
 cleanup:
 	kfree(buf);
-	for (--i; i>=0; --i) {
+	for (--i; i >= 0; --i) {
 		priv = usb_get_serial_port_data(serial->port[i]);
 		pl2303_buf_free(priv->buf);
 		kfree(priv);
@@ -407,7 +408,7 @@
 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);
@@ -452,14 +453,14 @@
 		dev_err(&port->dev, "%s - failed submitting write urb,"
 			" error %d\n", __func__, result);
 		priv->write_urb_in_use = 0;
-		// TODO: reschedule pl2303_send
+		/* TODO: reschedule pl2303_send */
 	}
 
 	usb_serial_port_softint(port);
 }
 
-static int pl2303_write(struct usb_serial_port *port, const unsigned char *buf,
-			int count)
+static int pl2303_write(struct tty_struct *tty, struct usb_serial_port *port,
+				const unsigned char *buf, int count)
 {
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
@@ -478,8 +479,9 @@
 	return count;
 }
 
-static int pl2303_write_room(struct usb_serial_port *port)
+static int pl2303_write_room(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
 	int room = 0;
 	unsigned long flags;
@@ -494,8 +496,9 @@
 	return room;
 }
 
-static int pl2303_chars_in_buffer(struct usb_serial_port *port)
+static int pl2303_chars_in_buffer(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
 	int chars = 0;
 	unsigned long flags;
@@ -510,8 +513,8 @@
 	return chars;
 }
 
-static void pl2303_set_termios(struct usb_serial_port *port,
-			       struct ktermios *old_termios)
+static void pl2303_set_termios(struct tty_struct *tty,
+		struct usb_serial_port *port, struct ktermios *old_termios)
 {
 	struct usb_serial *serial = port->serial;
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -526,11 +529,10 @@
 
 	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_ispeed = 9600;
-		port->tty->termios->c_ospeed = 9600;
+		*(tty->termios) = tty_std_termios;
+		tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+		tty->termios->c_ispeed = 9600;
+		tty->termios->c_ospeed = 9600;
 		priv->termios_initialized = 1;
 	}
 	spin_unlock_irqrestore(&priv->lock, flags);
@@ -539,16 +541,16 @@
 	   serial settings even to the same values as before. Thus
 	   we actually need to filter in this specific case */
 
-	if (!tty_termios_hw_change(port->tty->termios, old_termios))
+	if (!tty_termios_hw_change(tty->termios, old_termios))
 		return;
 
-	cflag = port->tty->termios->c_cflag;
+	cflag = tty->termios->c_cflag;
 
 	buf = kzalloc(7, GFP_KERNEL);
 	if (!buf) {
 		dev_err(&port->dev, "%s - out of memory.\n", __func__);
 		/* Report back no change occurred */
-		*port->tty->termios = *old_termios;
+		*tty->termios = *old_termios;
 		return;
 	}
 
@@ -560,16 +562,24 @@
 
 	if (cflag & CSIZE) {
 		switch (cflag & CSIZE) {
-			case CS5:	buf[6] = 5;	break;
-			case CS6:	buf[6] = 6;	break;
-			case CS7:	buf[6] = 7;	break;
-			default:
-			case CS8:	buf[6] = 8;	break;
+		case CS5:
+			buf[6] = 5;
+			break;
+		case CS6:
+			buf[6] = 6;
+			break;
+		case CS7:
+			buf[6] = 7;
+			break;
+		default:
+		case CS8:
+			buf[6] = 8;
+			break;
 		}
 		dbg("%s - data bits = %d", __func__, buf[6]);
 	}
 
-	baud = tty_get_baud_rate(port->tty);;
+	baud = tty_get_baud_rate(tty);
 	dbg("%s - baud = %d", __func__, baud);
 	if (baud) {
 		buf[0] = baud & 0xff;
@@ -646,12 +656,13 @@
 
 	/* FIXME: Need to read back resulting baud rate */
 	if (baud)
-		tty_encode_baud_rate(port->tty, baud, baud);
+		tty_encode_baud_rate(tty, baud, baud);
 
 	kfree(buf);
 }
 
-static void pl2303_close(struct usb_serial_port *port, struct file *filp)
+static void pl2303_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
@@ -666,7 +677,7 @@
 	spin_lock_irqsave(&priv->lock, flags);
 	timeout = PL2303_CLOSING_WAIT;
 	init_waitqueue_entry(&wait, current);
-	add_wait_queue(&port->tty->write_wait, &wait);
+	add_wait_queue(&tty->write_wait, &wait);
 	for (;;) {
 		set_current_state(TASK_INTERRUPTIBLE);
 		if (pl2303_buf_data_avail(priv->buf) == 0 ||
@@ -678,7 +689,7 @@
 		spin_lock_irqsave(&priv->lock, flags);
 	}
 	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&port->tty->write_wait, &wait);
+	remove_wait_queue(&tty->write_wait, &wait);
 	/* clear out any remaining data in the buffer */
 	pl2303_buf_clear(priv->buf);
 	spin_unlock_irqrestore(&priv->lock, flags);
@@ -690,9 +701,9 @@
 	/* 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);
+	bps = tty_get_baud_rate(tty);
 	if (bps > 1200)
-		timeout = max((HZ*2560)/bps,HZ/10);
+		timeout = max((HZ*2560)/bps, HZ/10);
 	else
 		timeout = 2*HZ;
 	schedule_timeout_interruptible(timeout);
@@ -703,8 +714,8 @@
 	usb_kill_urb(port->read_urb);
 	usb_kill_urb(port->interrupt_in_urb);
 
-	if (port->tty) {
-		c_cflag = port->tty->termios->c_cflag;
+	if (tty) {
+		c_cflag = tty->termios->c_cflag;
 		if (c_cflag & HUPCL) {
 			/* drop DTR and RTS */
 			spin_lock_irqsave(&priv->lock, flags);
@@ -715,7 +726,8 @@
 	}
 }
 
-static int pl2303_open(struct usb_serial_port *port, struct file *filp)
+static int pl2303_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct ktermios tmp_termios;
 	struct usb_serial *serial = port->serial;
@@ -734,11 +746,10 @@
 	}
 
 	/* Setup termios */
-	if (port->tty) {
-		pl2303_set_termios(port, &tmp_termios);
-	}
+	if (tty)
+		pl2303_set_termios(tty, port, &tmp_termios);
 
-	//FIXME: need to assert RTS and DTR if CRTSCTS off
+	/* FIXME: need to assert RTS and DTR if CRTSCTS off */
 
 	dbg("%s - submitting read urb", __func__);
 	port->read_urb->dev = serial->dev;
@@ -746,7 +757,7 @@
 	if (result) {
 		dev_err(&port->dev, "%s - failed submitting read urb,"
 			" error %d\n", __func__, result);
-		pl2303_close(port, NULL);
+		pl2303_close(tty, port, NULL);
 		return -EPROTO;
 	}
 
@@ -756,15 +767,16 @@
 	if (result) {
 		dev_err(&port->dev, "%s - failed submitting interrupt urb,"
 			" error %d\n", __func__, result);
-		pl2303_close(port, NULL);
+		pl2303_close(tty, port, NULL);
 		return -EPROTO;
 	}
 	return 0;
 }
 
-static int pl2303_tiocmset(struct usb_serial_port *port, struct file *file,
+static int pl2303_tiocmset(struct tty_struct *tty, struct file *file,
 			   unsigned int set, unsigned int clear)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	u8 control;
@@ -787,8 +799,9 @@
 	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 tty_struct *tty, struct file *file)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	unsigned int mcr;
@@ -839,12 +852,12 @@
 		status = priv->line_status;
 		spin_unlock_irqrestore(&priv->lock, flags);
 
-		changed=prevstatus^status;
+		changed = prevstatus ^ status;
 
 		if (((arg & TIOCM_RNG) && (changed & UART_RING)) ||
 		    ((arg & TIOCM_DSR) && (changed & UART_DSR)) ||
 		    ((arg & TIOCM_CD)  && (changed & UART_DCD)) ||
-		    ((arg & TIOCM_CTS) && (changed & UART_CTS)) ) {
+		    ((arg & TIOCM_CTS) && (changed & UART_CTS))) {
 			return 0;
 		}
 		prevstatus = status;
@@ -853,26 +866,26 @@
 	return 0;
 }
 
-static int pl2303_ioctl(struct usb_serial_port *port, struct file *file,
+static int pl2303_ioctl(struct tty_struct *tty, struct file *file,
 			unsigned int cmd, unsigned long arg)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
 
 	switch (cmd) {
-		case TIOCMIWAIT:
-			dbg("%s (%d) TIOCMIWAIT", __func__,  port->number);
-			return wait_modem_info(port, arg);
-
-		default:
-			dbg("%s not supported = 0x%04x", __func__, cmd);
-			break;
+	case TIOCMIWAIT:
+		dbg("%s (%d) TIOCMIWAIT", __func__,  port->number);
+		return wait_modem_info(port, arg);
+	default:
+		dbg("%s not supported = 0x%04x", __func__, cmd);
+		break;
 	}
-
 	return -ENOIOCTLCMD;
 }
 
-static void pl2303_break_ctl(struct usb_serial_port *port, int break_state)
+static void pl2303_break_ctl(struct tty_struct *tty, int break_state)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct usb_serial *serial = port->serial;
 	u16 state;
 	int result;
@@ -883,7 +896,8 @@
 		state = BREAK_OFF;
 	else
 		state = BREAK_ON;
-	dbg("%s - turning break %s", __func__, state==BREAK_OFF ? "off" : "on");
+	dbg("%s - turning break %s", __func__,
+			state == BREAK_OFF ? "off" : "on");
 
 	result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
 				 BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
@@ -937,7 +951,7 @@
 	if (actual_length < length)
 		return;
 
-        /* Save off the uart status for others to look at */
+	/* 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);
@@ -1001,7 +1015,7 @@
 
 	if (status) {
 		dbg("%s - urb status = %d", __func__, status);
-		if (!port->open_count) {
+		if (!port->port.count) {
 			dbg("%s - port is closed, exiting.", __func__);
 			return;
 		}
@@ -1036,7 +1050,7 @@
 
 	/* break takes precedence over parity, */
 	/* which takes precedence over framing errors */
-	if (line_status & UART_BREAK_ERROR )
+	if (line_status & UART_BREAK_ERROR)
 		tty_flag = TTY_BREAK;
 	else if (line_status & UART_PARITY_ERROR)
 		tty_flag = TTY_PARITY;
@@ -1044,7 +1058,7 @@
 		tty_flag = TTY_FRAME;
 	dbg("%s - tty_flag = %d", __func__, tty_flag);
 
-	tty = port->tty;
+	tty = port->port.tty;
 	if (tty && urb->actual_length) {
 		tty_buffer_request_room(tty, urb->actual_length + 1);
 		/* overrun is special, not associated with a char */
@@ -1056,7 +1070,7 @@
 	}
 
 	/* Schedule the next read _if_ we are still open */
-	if (port->open_count) {
+	if (port->port.count) {
 		urb->dev = port->serial->dev;
 		result = usb_submit_urb(urb, GFP_ATOMIC);
 		if (result)
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
index 94bddf0..def52d0 100644
--- a/drivers/usb/serial/safe_serial.c
+++ b/drivers/usb/serial/safe_serial.c
@@ -13,24 +13,25 @@
  *      Stuart Lynne <sl@lineo.com>, Tom Rushworth <tbr@lineo.com>
  */
 
-/* 
- * The encapsultaion is designed to overcome difficulties with some USB hardware.
+/*
+ * The encapsultaion is designed to overcome difficulties with some USB
+ * hardware.
  *
  * While the USB protocol has a CRC over the data while in transit, i.e. while
- * being carried over the bus, there is no end to end protection. If the hardware
- * has any problems getting the data into or out of the USB transmit and receive
- * FIFO's then data can be lost. 
+ * being carried over the bus, there is no end to end protection. If the
+ * hardware has any problems getting the data into or out of the USB transmit
+ * and receive FIFO's then data can be lost.
  *
- * This protocol adds a two byte trailer to each USB packet to specify the number
- * of bytes of valid data and a 10 bit CRC that will allow the receiver to verify
- * that the entire USB packet was received without error.
+ * This protocol adds a two byte trailer to each USB packet to specify the
+ * number of bytes of valid data and a 10 bit CRC that will allow the receiver
+ * to verify that the entire USB packet was received without error.
  *
- * Because in this case the sender and receiver are the class and function drivers
- * there is now end to end protection.
+ * Because in this case the sender and receiver are the class and function
+ * drivers there is now end to end protection.
  *
- * There is an additional option that can be used to force all transmitted packets
- * to be padded to the maximum packet size. This provides a work around for some
- * devices which have problems with small USB packets.
+ * There is an additional option that can be used to force all transmitted
+ * packets to be padded to the maximum packet size. This provides a work
+ * around for some devices which have problems with small USB packets.
  *
  * Assuming a packetsize of N:
  *
@@ -44,11 +45,12 @@
  *      | Data Length       | 10 bit CRC                                |
  *      + 7 . 6 . 5 . 4 . 3 . 2 . 1 . 0 | 7 . 6 . 5 . 4 . 3 . 2 . 1 . 0 +
  *
- * The 10 bit CRC is computed across the sent data, followed by the trailer with
- * the length set and the CRC set to zero. The CRC is then OR'd into the trailer.
+ * The 10 bit CRC is computed across the sent data, followed by the trailer
+ * with the length set and the CRC set to zero. The CRC is then OR'd into
+ * the trailer.
  *
- * When received a 10 bit CRC is computed over the entire frame including the trailer
- * and should be equal to zero.
+ * When received a 10 bit CRC is computed over the entire frame including
+ * the trailer and should be equal to zero.
  *
  * Two module parameters are used to control the encapsulation, if both are
  * turned of the module works as a simple serial device with NO
@@ -69,7 +71,7 @@
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
@@ -86,12 +88,12 @@
 #define DRIVER_AUTHOR "sl@lineo.com, tbr@lineo.com"
 #define DRIVER_DESC "USB Safe Encapsulated Serial"
 
-MODULE_AUTHOR (DRIVER_AUTHOR);
-MODULE_DESCRIPTION (DRIVER_DESC);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-static __u16 vendor;		// no default
-static __u16 product;		// no default
+static __u16 vendor;		/* no default */
+static __u16 product;		/* no default */
 module_param(vendor, ushort, 0);
 MODULE_PARM_DESC(vendor, "User specified USB idVendor (required)");
 module_param(product, ushort, 0);
@@ -122,30 +124,31 @@
 #define LINEO_SAFESERIAL_CRC_PADDED             0x02
 
 
-#define MY_USB_DEVICE(vend,prod,dc,ic,isc) \
-        .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_CLASS | \
-                USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS, \
-        .idVendor = (vend), \
-        .idProduct = (prod),\
-        .bDeviceClass = (dc),\
-        .bInterfaceClass = (ic), \
-        .bInterfaceSubClass = (isc),
+#define MY_USB_DEVICE(vend, prod, dc, ic, isc) \
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
+		       USB_DEVICE_ID_MATCH_DEV_CLASS | \
+		       USB_DEVICE_ID_MATCH_INT_CLASS | \
+		       USB_DEVICE_ID_MATCH_INT_SUBCLASS, \
+	.idVendor = (vend), \
+	.idProduct = (prod),\
+	.bDeviceClass = (dc),\
+	.bInterfaceClass = (ic), \
+	.bInterfaceSubClass = (isc),
 
 static struct usb_device_id id_table[] = {
-	{MY_USB_DEVICE (0x49f, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	// Itsy
-	{MY_USB_DEVICE (0x3f0, 0x2101, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	// Calypso
-	{MY_USB_DEVICE (0x4dd, 0x8001, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	// Iris 
-	{MY_USB_DEVICE (0x4dd, 0x8002, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	// Collie 
-	{MY_USB_DEVICE (0x4dd, 0x8003, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	// Collie 
-	{MY_USB_DEVICE (0x4dd, 0x8004, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	// Collie 
-	{MY_USB_DEVICE (0x5f9, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	// Sharp tmp
-	// extra null entry for module 
-	// vendor/produc parameters
-	{MY_USB_DEVICE (0, 0, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},
-	{}			// terminating entry 
+	{MY_USB_DEVICE(0x49f, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	/* Itsy */
+	{MY_USB_DEVICE(0x3f0, 0x2101, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	/* Calypso */
+	{MY_USB_DEVICE(0x4dd, 0x8001, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	/* Iris */
+	{MY_USB_DEVICE(0x4dd, 0x8002, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	/* Collie */
+	{MY_USB_DEVICE(0x4dd, 0x8003, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	/* Collie */
+	{MY_USB_DEVICE(0x4dd, 0x8004, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	/* Collie */
+	{MY_USB_DEVICE(0x5f9, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},	/* Sharp tmp */
+	/* extra null entry for module vendor/produc parameters */
+	{MY_USB_DEVICE(0, 0, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)},
+	{}			/* terminating entry  */
 };
 
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
 
 static struct usb_driver safe_driver = {
 	.name =		"safe_serial",
@@ -156,29 +159,45 @@
 };
 
 static const __u16 crc10_table[256] = {
-	0x000, 0x233, 0x255, 0x066, 0x299, 0x0aa, 0x0cc, 0x2ff, 0x301, 0x132, 0x154, 0x367, 0x198, 0x3ab, 0x3cd, 0x1fe,
-	0x031, 0x202, 0x264, 0x057, 0x2a8, 0x09b, 0x0fd, 0x2ce, 0x330, 0x103, 0x165, 0x356, 0x1a9, 0x39a, 0x3fc, 0x1cf,
-	0x062, 0x251, 0x237, 0x004, 0x2fb, 0x0c8, 0x0ae, 0x29d, 0x363, 0x150, 0x136, 0x305, 0x1fa, 0x3c9, 0x3af, 0x19c,
-	0x053, 0x260, 0x206, 0x035, 0x2ca, 0x0f9, 0x09f, 0x2ac, 0x352, 0x161, 0x107, 0x334, 0x1cb, 0x3f8, 0x39e, 0x1ad,
-	0x0c4, 0x2f7, 0x291, 0x0a2, 0x25d, 0x06e, 0x008, 0x23b, 0x3c5, 0x1f6, 0x190, 0x3a3, 0x15c, 0x36f, 0x309, 0x13a,
-	0x0f5, 0x2c6, 0x2a0, 0x093, 0x26c, 0x05f, 0x039, 0x20a, 0x3f4, 0x1c7, 0x1a1, 0x392, 0x16d, 0x35e, 0x338, 0x10b,
-	0x0a6, 0x295, 0x2f3, 0x0c0, 0x23f, 0x00c, 0x06a, 0x259, 0x3a7, 0x194, 0x1f2, 0x3c1, 0x13e, 0x30d, 0x36b, 0x158,
-	0x097, 0x2a4, 0x2c2, 0x0f1, 0x20e, 0x03d, 0x05b, 0x268, 0x396, 0x1a5, 0x1c3, 0x3f0, 0x10f, 0x33c, 0x35a, 0x169,
-	0x188, 0x3bb, 0x3dd, 0x1ee, 0x311, 0x122, 0x144, 0x377, 0x289, 0x0ba, 0x0dc, 0x2ef, 0x010, 0x223, 0x245, 0x076,
-	0x1b9, 0x38a, 0x3ec, 0x1df, 0x320, 0x113, 0x175, 0x346, 0x2b8, 0x08b, 0x0ed, 0x2de, 0x021, 0x212, 0x274, 0x047,
-	0x1ea, 0x3d9, 0x3bf, 0x18c, 0x373, 0x140, 0x126, 0x315, 0x2eb, 0x0d8, 0x0be, 0x28d, 0x072, 0x241, 0x227, 0x014,
-	0x1db, 0x3e8, 0x38e, 0x1bd, 0x342, 0x171, 0x117, 0x324, 0x2da, 0x0e9, 0x08f, 0x2bc, 0x043, 0x270, 0x216, 0x025,
-	0x14c, 0x37f, 0x319, 0x12a, 0x3d5, 0x1e6, 0x180, 0x3b3, 0x24d, 0x07e, 0x018, 0x22b, 0x0d4, 0x2e7, 0x281, 0x0b2,
-	0x17d, 0x34e, 0x328, 0x11b, 0x3e4, 0x1d7, 0x1b1, 0x382, 0x27c, 0x04f, 0x029, 0x21a, 0x0e5, 0x2d6, 0x2b0, 0x083,
-	0x12e, 0x31d, 0x37b, 0x148, 0x3b7, 0x184, 0x1e2, 0x3d1, 0x22f, 0x01c, 0x07a, 0x249, 0x0b6, 0x285, 0x2e3, 0x0d0,
-	0x11f, 0x32c, 0x34a, 0x179, 0x386, 0x1b5, 0x1d3, 0x3e0, 0x21e, 0x02d, 0x04b, 0x278, 0x087, 0x2b4, 0x2d2, 0x0e1,
+	0x000, 0x233, 0x255, 0x066, 0x299, 0x0aa, 0x0cc, 0x2ff,
+	0x301, 0x132, 0x154, 0x367, 0x198, 0x3ab, 0x3cd, 0x1fe,
+	0x031, 0x202, 0x264, 0x057, 0x2a8, 0x09b, 0x0fd, 0x2ce,
+	0x330, 0x103, 0x165, 0x356, 0x1a9, 0x39a, 0x3fc, 0x1cf,
+	0x062, 0x251, 0x237, 0x004, 0x2fb, 0x0c8, 0x0ae, 0x29d,
+	0x363, 0x150, 0x136, 0x305, 0x1fa, 0x3c9, 0x3af, 0x19c,
+	0x053, 0x260, 0x206, 0x035, 0x2ca, 0x0f9, 0x09f, 0x2ac,
+	0x352, 0x161, 0x107, 0x334, 0x1cb, 0x3f8, 0x39e, 0x1ad,
+	0x0c4, 0x2f7, 0x291, 0x0a2, 0x25d, 0x06e, 0x008, 0x23b,
+	0x3c5, 0x1f6, 0x190, 0x3a3, 0x15c, 0x36f, 0x309, 0x13a,
+	0x0f5, 0x2c6, 0x2a0, 0x093, 0x26c, 0x05f, 0x039, 0x20a,
+	0x3f4, 0x1c7, 0x1a1, 0x392, 0x16d, 0x35e, 0x338, 0x10b,
+	0x0a6, 0x295, 0x2f3, 0x0c0, 0x23f, 0x00c, 0x06a, 0x259,
+	0x3a7, 0x194, 0x1f2, 0x3c1, 0x13e, 0x30d, 0x36b, 0x158,
+	0x097, 0x2a4, 0x2c2, 0x0f1, 0x20e, 0x03d, 0x05b, 0x268,
+	0x396, 0x1a5, 0x1c3, 0x3f0, 0x10f, 0x33c, 0x35a, 0x169,
+	0x188, 0x3bb, 0x3dd, 0x1ee, 0x311, 0x122, 0x144, 0x377,
+	0x289, 0x0ba, 0x0dc, 0x2ef, 0x010, 0x223, 0x245, 0x076,
+	0x1b9, 0x38a, 0x3ec, 0x1df, 0x320, 0x113, 0x175, 0x346,
+	0x2b8, 0x08b, 0x0ed, 0x2de, 0x021, 0x212, 0x274, 0x047,
+	0x1ea, 0x3d9, 0x3bf, 0x18c, 0x373, 0x140, 0x126, 0x315,
+	0x2eb, 0x0d8, 0x0be, 0x28d, 0x072, 0x241, 0x227, 0x014,
+	0x1db, 0x3e8, 0x38e, 0x1bd, 0x342, 0x171, 0x117, 0x324,
+	0x2da, 0x0e9, 0x08f, 0x2bc, 0x043, 0x270, 0x216, 0x025,
+	0x14c, 0x37f, 0x319, 0x12a, 0x3d5, 0x1e6, 0x180, 0x3b3,
+	0x24d, 0x07e, 0x018, 0x22b, 0x0d4, 0x2e7, 0x281, 0x0b2,
+	0x17d, 0x34e, 0x328, 0x11b, 0x3e4, 0x1d7, 0x1b1, 0x382,
+	0x27c, 0x04f, 0x029, 0x21a, 0x0e5, 0x2d6, 0x2b0, 0x083,
+	0x12e, 0x31d, 0x37b, 0x148, 0x3b7, 0x184, 0x1e2, 0x3d1,
+	0x22f, 0x01c, 0x07a, 0x249, 0x0b6, 0x285, 0x2e3, 0x0d0,
+	0x11f, 0x32c, 0x34a, 0x179, 0x386, 0x1b5, 0x1d3, 0x3e0,
+	0x21e, 0x02d, 0x04b, 0x278, 0x087, 0x2b4, 0x2d2, 0x0e1,
 };
 
-#define CRC10_INITFCS     0x000	// Initial FCS value
-#define CRC10_GOODFCS     0x000	// Good final FCS value
-#define CRC10_FCS(fcs, c) ( (((fcs) << 8) & 0x3ff) ^ crc10_table[((fcs) >> 2) & 0xff] ^ (c))
+#define CRC10_INITFCS     0x000	/* Initial FCS value */
+#define CRC10_GOODFCS     0x000	/* Good final FCS value */
+#define CRC10_FCS(fcs, c) ((((fcs) << 8) & 0x3ff) ^ crc10_table[((fcs) >> 2) & 0xff] ^ (c))
 
-/**     
+/**
  * fcs_compute10 - memcpy and calculate 10 bit CRC across buffer
  * @sp: pointer to buffer
  * @len: number of bytes
@@ -187,13 +206,13 @@
  * Perform a memcpy and calculate fcs using ppp 10bit CRC algorithm. Return
  * new 10 bit FCS.
  */
-static __u16 __inline__ fcs_compute10 (unsigned char *sp, int len, __u16 fcs)
+static __u16 __inline__ fcs_compute10(unsigned char *sp, int len, __u16 fcs)
 {
-	for (; len-- > 0; fcs = CRC10_FCS (fcs, *sp++));
+	for (; len-- > 0; fcs = CRC10_FCS(fcs, *sp++));
 	return fcs;
 }
 
-static void safe_read_bulk_callback (struct urb *urb)
+static void safe_read_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port =  urb->context;
 	unsigned char *data = urb->transfer_buffer;
@@ -201,7 +220,7 @@
 	int result;
 	int status = urb->status;
 
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 
 	if (status) {
 		dbg("%s - nonzero read bulk status received: %d",
@@ -209,76 +228,82 @@
 		return;
 	}
 
-	dbg ("safe_read_bulk_callback length: %d", port->read_urb->actual_length);
+	dbg("safe_read_bulk_callback length: %d",
+					port->read_urb->actual_length);
 #ifdef ECHO_RCV
 	{
 		int i;
 		unsigned char *cp = port->read_urb->transfer_buffer;
 		for (i = 0; i < port->read_urb->actual_length; i++) {
-			if ((i % 32) == 0) {
-				printk ("\nru[%02x] ", i);
-			}
-			printk ("%02x ", *cp++);
+			if ((i % 32) == 0)
+				printk("\nru[%02x] ", i);
+			printk("%02x ", *cp++);
 		}
-		printk ("\n");
+		printk("\n");
 	}
 #endif
 	if (safe) {
 		__u16 fcs;
-		if (!(fcs = fcs_compute10 (data, length, CRC10_INITFCS))) {
+		fcs = fcs_compute10(data, length, CRC10_INITFCS);
+		if (!fcs) {
 			int actual_length = data[length - 2] >> 2;
 			if (actual_length <= (length - 2)) {
-				info ("%s - actual: %d", __func__, actual_length);
-				tty_insert_flip_string(port->tty, data, actual_length);
-				tty_flip_buffer_push (port->tty);
+				info("%s - actual: %d", __func__,
+							actual_length);
+				tty_insert_flip_string(port->port.tty,
+							data, actual_length);
+				tty_flip_buffer_push(port->port.tty);
 			} else {
-				err ("%s - inconsistent lengths %d:%d", __func__,
-				     actual_length, length);
+				err("%s - inconsistent lengths %d:%d",
+					__func__, actual_length, length);
 			}
 		} else {
-			err ("%s - bad CRC %x", __func__, fcs);
+			err("%s - bad CRC %x", __func__, fcs);
 		}
 	} else {
-		tty_insert_flip_string(port->tty, data, length);
-		tty_flip_buffer_push (port->tty);
+		tty_insert_flip_string(port->port.tty, data, length);
+		tty_flip_buffer_push(port->port.tty);
 	}
 
 	/* Continue trying to always read  */
-	usb_fill_bulk_urb (urb, port->serial->dev,
-		       usb_rcvbulkpipe (port->serial->dev, port->bulk_in_endpointAddress),
-		       urb->transfer_buffer, urb->transfer_buffer_length,
-		       safe_read_bulk_callback, port);
+	usb_fill_bulk_urb(urb, port->serial->dev,
+			usb_rcvbulkpipe(port->serial->dev,
+					port->bulk_in_endpointAddress),
+			urb->transfer_buffer, urb->transfer_buffer_length,
+			safe_read_bulk_callback, port);
 
-	if ((result = usb_submit_urb (urb, GFP_ATOMIC))) {
-		err ("%s - failed resubmitting read urb, error %d", __func__, result);
+	result = usb_submit_urb(urb, GFP_ATOMIC);
+	if (result)
+		err("%s - failed resubmitting read urb, error %d",
+							__func__, result);
 		/* FIXME: Need a mechanism to retry later if this happens */
-	}
 }
 
-static int safe_write (struct usb_serial_port *port, const unsigned char *buf, int count)
+static int safe_write(struct tty_struct *tty, struct usb_serial_port *port,
+					const unsigned char *buf, int count)
 {
 	unsigned char *data;
 	int result;
 	int i;
 	int packet_length;
 
-	dbg ("safe_write port: %p %d urb: %p count: %d", port, port->number, port->write_urb,
-	     count);
+	dbg("safe_write port: %p %d urb: %p count: %d",
+				port, port->number, port->write_urb, count);
 
 	if (!port->write_urb) {
-		dbg ("%s - write urb NULL", __func__);
+		dbg("%s - write urb NULL", __func__);
 		return 0;
 	}
 
-	dbg ("safe_write write_urb: %d transfer_buffer_length",
+	dbg("safe_write write_urb: %d transfer_buffer_length",
 	     port->write_urb->transfer_buffer_length);
 
 	if (!port->write_urb->transfer_buffer_length) {
-		dbg ("%s - write urb transfer_buffer_length zero", __func__);
+		dbg("%s - write urb transfer_buffer_length zero", __func__);
 		return 0;
 	}
 	if (count == 0) {
-		dbg ("%s - write request of 0 bytes", __func__);
+		dbg("%s - write request of 0 bytes", __func__);
 		return 0;
 	}
 	spin_lock_bh(&port->lock);
@@ -290,85 +315,85 @@
 	port->write_urb_busy = 1;
 	spin_unlock_bh(&port->lock);
 
-	packet_length = port->bulk_out_size;	// get max packetsize
+	packet_length = port->bulk_out_size;	/* get max packetsize */
 
-	i = packet_length - (safe ? 2 : 0);	// get bytes to send
+	i = packet_length - (safe ? 2 : 0);	/* get bytes to send */
 	count = (count > i) ? i : count;
 
 
-	// get the data into the transfer buffer
+	/* get the data into the transfer buffer */
 	data = port->write_urb->transfer_buffer;
-	memset (data, '0', packet_length);
+	memset(data, '0', packet_length);
 
-	memcpy (data, buf, count);
+	memcpy(data, buf, count);
 
 	if (safe) {
 		__u16 fcs;
 
-		// pad if necessary
-		if (!padded) {
+		/* pad if necessary */
+		if (!padded)
 			packet_length = count + 2;
-		}
-		// set count
+		/* set count */
 		data[packet_length - 2] = count << 2;
 		data[packet_length - 1] = 0;
 
-		// compute fcs and insert into trailer
-		fcs = fcs_compute10 (data, packet_length, CRC10_INITFCS);
+		/* compute fcs and insert into trailer */
+		fcs = fcs_compute10(data, packet_length, CRC10_INITFCS);
 		data[packet_length - 2] |= fcs >> 8;
 		data[packet_length - 1] |= fcs & 0xff;
 
-		// set length to send
+		/* set length to send */
 		port->write_urb->transfer_buffer_length = packet_length;
 	} else {
 		port->write_urb->transfer_buffer_length = count;
 	}
 
-	usb_serial_debug_data(debug, &port->dev, __func__, count, port->write_urb->transfer_buffer);
+	usb_serial_debug_data(debug, &port->dev, __func__, count,
+					port->write_urb->transfer_buffer);
 #ifdef ECHO_TX
 	{
 		int i;
 		unsigned char *cp = port->write_urb->transfer_buffer;
 		for (i = 0; i < port->write_urb->transfer_buffer_length; i++) {
-			if ((i % 32) == 0) {
-				printk ("\nsu[%02x] ", i);
-			}
-			printk ("%02x ", *cp++);
+			if ((i % 32) == 0)
+				printk("\nsu[%02x] ", i);
+			printk("%02x ", *cp++);
 		}
-		printk ("\n");
+		printk("\n");
 	}
 #endif
 	port->write_urb->dev = port->serial->dev;
-	if ((result = usb_submit_urb (port->write_urb, GFP_KERNEL))) {
+	result = usb_submit_urb(port->write_urb, GFP_KERNEL);
+	if (result) {
 		port->write_urb_busy = 0;
-		err ("%s - failed submitting write urb, error %d", __func__, result);
+		err("%s - failed submitting write urb, error %d",
+							__func__, result);
 		return 0;
 	}
-	dbg ("%s urb: %p submitted", __func__, port->write_urb);
+	dbg("%s urb: %p submitted", __func__, port->write_urb);
 
-	return (count);
+	return count;
 }
 
-static int safe_write_room (struct usb_serial_port *port)
+static int safe_write_room(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	int room = 0;		/* Default: no room */
 	unsigned long flags;
 
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 
 	spin_lock_irqsave(&port->lock, flags);
 	if (port->write_urb_busy)
 		room = port->bulk_out_size - (safe ? 2 : 0);
 	spin_unlock_irqrestore(&port->lock, flags);
 
-	if (room) {
-		dbg ("safe_write_room returns %d", room);
-	}
-
+	if (room)
+		dbg("safe_write_room returns %d", room);
 	return room;
 }
 
-static int safe_startup (struct usb_serial *serial)
+static int safe_startup(struct usb_serial *serial)
 {
 	switch (serial->interface->cur_altsetting->desc.bInterfaceProtocol) {
 	case LINEO_SAFESERIAL_CRC:
@@ -396,17 +421,18 @@
 	.attach =		safe_startup,
 };
 
-static int __init safe_init (void)
+static int __init safe_init(void)
 {
 	int i, retval;
 
-	info (DRIVER_VERSION " " DRIVER_AUTHOR);
-	info (DRIVER_DESC);
-	info ("vendor: %x product: %x safe: %d padded: %d\n", vendor, product, safe, padded);
+	info(DRIVER_VERSION " " DRIVER_AUTHOR);
+	info(DRIVER_DESC);
+	info("vendor: %x product: %x safe: %d padded: %d\n",
+					vendor, product, safe, padded);
 
-	// if we have vendor / product parameters patch them into id list
+	/* if we have vendor / product parameters patch them into id list */
 	if (vendor || product) {
-		info ("vendor: %x product: %x\n", vendor, product);
+		info("vendor: %x product: %x\n", vendor, product);
 
 		for (i = 0; i < ARRAY_SIZE(id_table); i++) {
 			if (!id_table[i].idVendor && !id_table[i].idProduct) {
@@ -431,11 +457,11 @@
 	return retval;
 }
 
-static void __exit safe_exit (void)
+static void __exit safe_exit(void)
 {
-	usb_deregister (&safe_driver);
-	usb_serial_deregister (&safe_device);
+	usb_deregister(&safe_driver);
+	usb_serial_deregister(&safe_device);
 }
 
-module_init (safe_init);
-module_exit (safe_exit);
+module_init(safe_init);
+module_exit(safe_exit);
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 29074c1..2f6f152 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -250,7 +250,8 @@
 	int ri_state;
 };
 
-static int sierra_send_setup(struct usb_serial_port *port)
+static int sierra_send_setup(struct tty_struct *tty,
+						struct usb_serial_port *port)
 {
 	struct usb_serial *serial = port->serial;
 	struct sierra_port_private *portdata;
@@ -260,7 +261,7 @@
 
 	portdata = usb_get_serial_port_data(port);
 
-	if (port->tty) {
+	if (tty) {
 		int val = 0;
 		if (portdata->dtr_state)
 			val |= 0x01;
@@ -284,32 +285,17 @@
 	return 0;
 }
 
-static void sierra_rx_throttle(struct usb_serial_port *port)
+static void sierra_set_termios(struct tty_struct *tty,
+		struct usb_serial_port *port, struct ktermios *old_termios)
 {
 	dbg("%s", __func__);
+	tty_termios_copy_hw(tty->termios, old_termios);
+	sierra_send_setup(tty, port);
 }
 
-static void sierra_rx_unthrottle(struct usb_serial_port *port)
+static int sierra_tiocmget(struct tty_struct *tty, struct file *file)
 {
-	dbg("%s", __func__);
-}
-
-static void sierra_break_ctl(struct usb_serial_port *port, int break_state)
-{
-	/* Unfortunately, I don't know how to send a break */
-	dbg("%s", __func__);
-}
-
-static void sierra_set_termios(struct usb_serial_port *port,
-			struct ktermios *old_termios)
-{
-	dbg("%s", __func__);
-	tty_termios_copy_hw(port->tty->termios, old_termios);
-	sierra_send_setup(port);
-}
-
-static int sierra_tiocmget(struct usb_serial_port *port, struct file *file)
-{
+	struct usb_serial_port *port = tty->driver_data;
 	unsigned int value;
 	struct sierra_port_private *portdata;
 
@@ -325,9 +311,10 @@
 	return value;
 }
 
-static int sierra_tiocmset(struct usb_serial_port *port, struct file *file,
+static int sierra_tiocmset(struct tty_struct *tty, struct file *file,
 			unsigned int set, unsigned int clear)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct sierra_port_private *portdata;
 
 	portdata = usb_get_serial_port_data(port);
@@ -341,13 +328,7 @@
 		portdata->rts_state = 0;
 	if (clear & TIOCM_DTR)
 		portdata->dtr_state = 0;
-	return sierra_send_setup(port);
-}
-
-static int sierra_ioctl(struct usb_serial_port *port, struct file *file,
-			unsigned int cmd, unsigned long arg)
-{
-	return -ENOIOCTLCMD;
+	return sierra_send_setup(tty, port);
 }
 
 static void sierra_outdat_callback(struct urb *urb)
@@ -374,8 +355,8 @@
 }
 
 /* Write */
-static int sierra_write(struct usb_serial_port *port,
-			const unsigned char *buf, int count)
+static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port,
+					const unsigned char *buf, int count)
 {
 	struct sierra_port_private *portdata = usb_get_serial_port_data(port);
 	struct usb_serial *serial = port->serial;
@@ -463,7 +444,7 @@
 		dbg("%s: nonzero status: %d on endpoint %02x.",
 		    __func__, status, endpoint);
 	} else {
-		tty = port->tty;
+		tty = port->port.tty;
 		if (urb->actual_length) {
 			tty_buffer_request_room(tty, urb->actual_length);
 			tty_insert_flip_string(tty, data, urb->actual_length);
@@ -473,7 +454,7 @@
 		}
 
 		/* Resubmit urb so we continue receiving */
-		if (port->open_count && status != -ESHUTDOWN) {
+		if (port->port.count && status != -ESHUTDOWN) {
 			err = usb_submit_urb(urb, GFP_ATOMIC);
 			if (err)
 				dev_err(&port->dev, "resubmit read urb failed."
@@ -517,9 +498,9 @@
 			portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
 			portdata->ri_state = ((signals & 0x08) ? 1 : 0);
 
-			if (port->tty && !C_CLOCAL(port->tty) &&
+			if (port->port.tty && !C_CLOCAL(port->port.tty) &&
 					old_dcd_state && !portdata->dcd_state)
-				tty_hangup(port->tty);
+				tty_hangup(port->port.tty);
 		} else {
 			dbg("%s: type %x req %x", __func__,
 				req_pkt->bRequestType, req_pkt->bRequest);
@@ -537,8 +518,9 @@
 	}
 }
 
-static int sierra_write_room(struct usb_serial_port *port)
+static int sierra_write_room(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct sierra_port_private *portdata = usb_get_serial_port_data(port);
 	unsigned long flags;
 
@@ -557,22 +539,8 @@
 	return 2048;
 }
 
-static int sierra_chars_in_buffer(struct usb_serial_port *port)
-{
-	dbg("%s - port %d", __func__, port->number);
-
-	/*
-	 * We can't really account for how much data we
-	 * have sent out, but hasn't made it through to the
-	 * device as we can't see the backend here, so just
-	 * tell the tty layer that everything is flushed.
-	 *
-	 * FIXME: should walk the outstanding urbs info
-	 */
-	return 0;
-}
-
-static int sierra_open(struct usb_serial_port *port, struct file *filp)
+static int sierra_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct sierra_port_private *portdata;
 	struct usb_serial *serial = port->serial;
@@ -612,9 +580,10 @@
 		}
 	}
 
-	port->tty->low_latency = 1;
+	if (tty)
+		tty->low_latency = 1;
 
-	sierra_send_setup(port);
+	sierra_send_setup(tty, port);
 
 	/* start up the interrupt endpoint if we have one */
 	if (port->interrupt_in_urb) {
@@ -626,7 +595,8 @@
 	return 0;
 }
 
-static void sierra_close(struct usb_serial_port *port, struct file *filp)
+static void sierra_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	int i;
 	struct usb_serial *serial = port->serial;
@@ -641,7 +611,7 @@
 	if (serial->dev) {
 		mutex_lock(&serial->disc_mutex);
 		if (!serial->disconnected)
-			sierra_send_setup(port);
+			sierra_send_setup(tty, port);
 		mutex_unlock(&serial->disc_mutex);
 
 		/* Stop reading/writing urbs */
@@ -651,7 +621,7 @@
 
 	usb_kill_urb(port->interrupt_in_urb);
 
-	port->tty = NULL;
+	port->port.tty = NULL;	/* FIXME */
 }
 
 static int sierra_startup(struct usb_serial *serial)
@@ -754,12 +724,7 @@
 	.close             = sierra_close,
 	.write             = sierra_write,
 	.write_room        = sierra_write_room,
-	.chars_in_buffer   = sierra_chars_in_buffer,
-	.throttle          = sierra_rx_throttle,
-	.unthrottle        = sierra_rx_unthrottle,
-	.ioctl             = sierra_ioctl,
 	.set_termios       = sierra_set_termios,
-	.break_ctl         = sierra_break_ctl,
 	.tiocmget          = sierra_tiocmget,
 	.tiocmset          = sierra_tiocmset,
 	.attach            = sierra_startup,
@@ -792,7 +757,7 @@
 
 static void __exit sierra_exit(void)
 {
-	usb_deregister (&sierra_driver);
+	usb_deregister(&sierra_driver);
 	usb_serial_deregister(&sierra_device);
 }
 
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index 55b2570..283cf6b 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -208,7 +208,7 @@
 {
 	if (pb == NULL)
 		return 0;
-	return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
+	return (pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size;
 }
 
 /* get the number of space in the pipo */
@@ -216,7 +216,7 @@
 {
 	if (pb == NULL)
 		return 0;
-	return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
+	return (pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size;
 }
 
 /* put count data into pipo */
@@ -448,7 +448,8 @@
 
 /* close the serial port. We should wait for data sending to device 1st and
  * then kill all urb. */
-static void spcp8x5_close(struct usb_serial_port *port, struct file *filp)
+static void spcp8x5_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
@@ -464,7 +465,7 @@
 	spin_lock_irqsave(&priv->lock, flags);
 	timeout = SPCP8x5_CLOSING_WAIT;
 	init_waitqueue_entry(&wait, current);
-	add_wait_queue(&port->tty->write_wait, &wait);
+	add_wait_queue(&tty->write_wait, &wait);
 	for (;;) {
 		set_current_state(TASK_INTERRUPTIBLE);
 		if (ringbuf_avail_data(priv->buf) == 0 ||
@@ -475,7 +476,7 @@
 		spin_lock_irqsave(&priv->lock, flags);
 	}
 	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&port->tty->write_wait, &wait);
+	remove_wait_queue(&tty->write_wait, &wait);
 
 	/* clear out any remaining data in the buffer */
 	clear_ringbuf(priv->buf);
@@ -486,7 +487,7 @@
 	 * 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);
+	bps = tty_get_baud_rate(tty);
 	if (bps > 1200)
 		timeout = max((HZ*2560) / bps, HZ/10);
 	else
@@ -495,8 +496,8 @@
 	schedule_timeout(timeout);
 
 	/* clear control lines */
-	if (port->tty) {
-		c_cflag = port->tty->termios->c_cflag;
+	if (tty) {
+		c_cflag = tty->termios->c_cflag;
 		if (c_cflag & HUPCL) {
 			spin_lock_irqsave(&priv->lock, flags);
 			priv->line_control = 0;
@@ -518,14 +519,14 @@
 }
 
 /* set the serial param for transfer. we should check if we really need to
- * transfer. then if be set flow contorl we should do this too. */
-static void spcp8x5_set_termios(struct usb_serial_port *port,
-				struct ktermios *old_termios)
+ * transfer. if we set flow control we should do this too. */
+static void spcp8x5_set_termios(struct tty_struct *tty,
+		struct usb_serial_port *port, struct ktermios *old_termios)
 {
 	struct usb_serial *serial = port->serial;
 	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
-	unsigned int cflag = port->tty->termios->c_cflag;
+	unsigned int cflag = tty->termios->c_cflag;
 	unsigned int old_cflag = old_termios->c_cflag;
 	unsigned short uartdata;
 	unsigned char buf[2] = {0, 0};
@@ -533,21 +534,19 @@
 	int i;
 	u8 control;
 
-	if ((!port->tty) || (!port->tty->termios))
-		return;
-
 	/* for the 1st time call this function */
 	spin_lock_irqsave(&priv->lock, flags);
 	if (!priv->termios_initialized) {
-		*(port->tty->termios) = tty_std_termios;
-		port->tty->termios->c_cflag = B115200 | CS8 | CREAD |
-					      HUPCL | CLOCAL;
+		*(tty->termios) = tty_std_termios;
+		tty->termios->c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
+		tty->termios->c_ispeed = 115200;
+		tty->termios->c_ospeed = 115200;
 		priv->termios_initialized = 1;
 	}
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	/* check that they really want us to change something */
-	if (!tty_termios_hw_change(port->tty->termios, old_termios))
+	if (!tty_termios_hw_change(tty->termios, old_termios))
 		return;
 
 	/* set DTR/RTS active */
@@ -567,7 +566,7 @@
 	}
 
 	/* Set Baud Rate */
-	baud = tty_get_baud_rate(port->tty);;
+	baud = tty_get_baud_rate(tty);;
 	switch (baud) {
 	case 300:	buf[0] = 0x00;	break;
 	case 600:	buf[0] = 0x01;	break;
@@ -643,7 +642,8 @@
 
 /* open the serial port. do some usb system call. set termios and get the line
  * status of the device. then submit the read urb */
-static int spcp8x5_open(struct usb_serial_port *port, struct file *filp)
+static int spcp8x5_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct ktermios tmp_termios;
 	struct usb_serial *serial = port->serial;
@@ -665,7 +665,7 @@
 		return ret;
 
 	spin_lock_irqsave(&priv->lock, flags);
-	if (port->tty->termios->c_cflag & CBAUD)
+	if (tty && (tty->termios->c_cflag & CBAUD))
 		priv->line_control = MCR_DTR | MCR_RTS;
 	else
 		priv->line_control = 0;
@@ -674,8 +674,8 @@
 	spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type);
 
 	/* Setup termios */
-	if (port->tty)
-		spcp8x5_set_termios(port, &tmp_termios);
+	if (tty)
+		spcp8x5_set_termios(tty, port, &tmp_termios);
 
 	spcp8x5_get_msr(serial->dev, &status, priv->type);
 
@@ -690,7 +690,7 @@
 	port->read_urb->dev = serial->dev;
 	ret = usb_submit_urb(port->read_urb, GFP_KERNEL);
 	if (ret) {
-		spcp8x5_close(port, NULL);
+		spcp8x5_close(tty, port, NULL);
 		return -EPROTO;
 	}
 	return 0;
@@ -717,7 +717,7 @@
 
 	/* check the urb status */
 	if (urb->status) {
-		if (!port->open_count)
+		if (!port->port.count)
 			return;
 		if (urb->status == -EPROTO) {
 			/* spcp8x5 mysteriously fails with -EPROTO */
@@ -755,7 +755,7 @@
 		tty_flag = TTY_FRAME;
 	dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag);
 
-	tty = port->tty;
+	tty = port->port.tty;
 	if (tty && urb->actual_length) {
 		tty_buffer_request_room(tty, urb->actual_length + 1);
 		/* overrun is special, not associated with a char */
@@ -767,7 +767,7 @@
 	}
 
 	/* Schedule the next read _if_ we are still open */
-	if (port->open_count) {
+	if (port->port.count) {
 		urb->dev = port->serial->dev;
 		result = usb_submit_urb(urb , GFP_ATOMIC);
 		if (result)
@@ -866,7 +866,7 @@
 }
 
 /* write data to ring buffer. and then start the write transfer */
-static int spcp8x5_write(struct usb_serial_port *port,
+static int spcp8x5_write(struct tty_struct *tty, struct usb_serial_port *port,
 			 const unsigned char *buf, int count)
 {
 	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
@@ -925,9 +925,10 @@
 	return 0;
 }
 
-static int spcp8x5_ioctl(struct usb_serial_port *port, struct file *file,
+static int spcp8x5_ioctl(struct tty_struct *tty, struct file *file,
 			 unsigned int cmd, unsigned long arg)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
 
 	switch (cmd) {
@@ -943,9 +944,10 @@
 	return -ENOIOCTLCMD;
 }
 
-static int spcp8x5_tiocmset(struct usb_serial_port *port, struct file *file,
+static int spcp8x5_tiocmset(struct tty_struct *tty, struct file *file,
 			    unsigned int set, unsigned int clear)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	u8 control;
@@ -965,8 +967,9 @@
 	return spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type);
 }
 
-static int spcp8x5_tiocmget(struct usb_serial_port *port, struct file *file)
+static int spcp8x5_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	unsigned int mcr;
@@ -989,8 +992,9 @@
 }
 
 /* get the avail space room in ring buffer */
-static int spcp8x5_write_room(struct usb_serial_port *port)
+static int spcp8x5_write_room(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
 	int room = 0;
 	unsigned long flags;
@@ -1003,8 +1007,9 @@
 }
 
 /* get the number of avail data in write ring buffer */
-static int spcp8x5_chars_in_buffer(struct usb_serial_port *port)
+static int spcp8x5_chars_in_buffer(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
 	int chars = 0;
 	unsigned long flags;
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index a26a629d..e39c779 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -16,7 +16,7 @@
  * For questions or problems with this driver, contact Texas Instruments
  * technical support, or Al Borchers <alborchers@steinerpoint.com>, or
  * Peter Berger <pberger@brimson.com>.
- * 
+ *
  * This driver needs this hotplug script in /etc/hotplug/usb/ti_usb_3410_5052
  * or in /etc/hotplug.d/usb/ti_usb_3410_5052.hotplug to set the device
  * configuration.
@@ -70,6 +70,7 @@
 
 #include <linux/kernel.h>
 #include <linux/errno.h>
+#include <linux/firmware.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/tty.h>
@@ -81,7 +82,7 @@
 #include <linux/serial.h>
 #include <linux/circ_buf.h>
 #include <linux/mutex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 #include <linux/firmware.h>
@@ -149,21 +150,24 @@
 
 static int ti_startup(struct usb_serial *serial);
 static void ti_shutdown(struct usb_serial *serial);
-static int ti_open(struct usb_serial_port *port, struct file *file);
-static void ti_close(struct usb_serial_port *port, struct file *file);
-static int ti_write(struct usb_serial_port *port, const unsigned char *data,
-	int count);
-static int ti_write_room(struct usb_serial_port *port);
-static int ti_chars_in_buffer(struct usb_serial_port *port);
-static void ti_throttle(struct usb_serial_port *port);
-static void ti_unthrottle(struct usb_serial_port *port);
-static int ti_ioctl(struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg);
-static void ti_set_termios(struct usb_serial_port *port,
-	struct ktermios *old_termios);
-static int ti_tiocmget(struct usb_serial_port *port, struct file *file);
-static int ti_tiocmset(struct usb_serial_port *port, struct file *file,
-	unsigned int set, unsigned int clear);
-static void ti_break(struct usb_serial_port *port, int break_state);
+static int ti_open(struct tty_struct *tty, struct usb_serial_port *port,
+		struct file *file);
+static void ti_close(struct tty_struct *tty, struct usb_serial_port *port,
+		struct file *file);
+static int ti_write(struct tty_struct *tty, struct usb_serial_port *port,
+		const unsigned char *data, int count);
+static int ti_write_room(struct tty_struct *tty);
+static int ti_chars_in_buffer(struct tty_struct *tty);
+static void ti_throttle(struct tty_struct *tty);
+static void ti_unthrottle(struct tty_struct *tty);
+static int ti_ioctl(struct tty_struct *tty, struct file *file,
+		unsigned int cmd, unsigned long arg);
+static void ti_set_termios(struct tty_struct *tty,
+		struct usb_serial_port *port, struct ktermios *old_termios);
+static int ti_tiocmget(struct tty_struct *tty, struct file *file);
+static int ti_tiocmset(struct tty_struct *tty, struct file *file,
+		unsigned int set, unsigned int clear);
+static void ti_break(struct tty_struct *tty, int break_state);
 static void ti_interrupt_callback(struct urb *urb);
 static void ti_bulk_in_callback(struct urb *urb);
 static void ti_bulk_out_callback(struct urb *urb);
@@ -192,8 +196,7 @@
 static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
 	__u8 mask, __u8 byte);
 
-static int ti_download_firmware(struct ti_device *tdev, char *fw_name);
-
+static int ti_download_firmware(struct ti_device *tdev, int type);
 
 /* circular buffer */
 static struct circ_buf *ti_buf_alloc(void);
@@ -325,19 +328,25 @@
 MODULE_PARM_DESC(debug, "Enable debugging, 0=no, 1=yes");
 
 module_param(low_latency, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(low_latency, "TTY low_latency flag, 0=off, 1=on, default is off");
+MODULE_PARM_DESC(low_latency,
+		"TTY low_latency flag, 0=off, 1=on, default is off");
 
 module_param(closing_wait, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(closing_wait, "Maximum wait for data to drain in close, in .01 secs, default is 4000");
+MODULE_PARM_DESC(closing_wait,
+    "Maximum wait for data to drain in close, in .01 secs, default is 4000");
 
 module_param_array(vendor_3410, ushort, &vendor_3410_count, S_IRUGO);
-MODULE_PARM_DESC(vendor_3410, "Vendor ids for 3410 based devices, 1-5 short integers");
+MODULE_PARM_DESC(vendor_3410,
+		"Vendor ids for 3410 based devices, 1-5 short integers");
 module_param_array(product_3410, ushort, &product_3410_count, S_IRUGO);
-MODULE_PARM_DESC(product_3410, "Product ids for 3410 based devices, 1-5 short integers");
+MODULE_PARM_DESC(product_3410,
+		"Product ids for 3410 based devices, 1-5 short integers");
 module_param_array(vendor_5052, ushort, &vendor_5052_count, S_IRUGO);
-MODULE_PARM_DESC(vendor_5052, "Vendor ids for 5052 based devices, 1-5 short integers");
+MODULE_PARM_DESC(vendor_5052,
+		"Vendor ids for 5052 based devices, 1-5 short integers");
 module_param_array(product_5052, ushort, &product_5052_count, S_IRUGO);
-MODULE_PARM_DESC(product_5052, "Product ids for 5052 based devices, 1-5 short integers");
+MODULE_PARM_DESC(product_5052,
+		"Product ids for 5052 based devices, 1-5 short integers");
 
 MODULE_DEVICE_TABLE(usb, ti_id_table_combined);
 
@@ -346,18 +355,18 @@
 
 static int __init ti_init(void)
 {
-	int i,j;
+	int i, j;
 	int ret;
 
 	/* insert extra vendor and product ids */
 	j = ARRAY_SIZE(ti_id_table_3410) - TI_EXTRA_VID_PID_COUNT - 1;
-	for (i=0; i<min(vendor_3410_count,product_3410_count); i++,j++) {
+	for (i = 0; i < min(vendor_3410_count, product_3410_count); i++, j++) {
 		ti_id_table_3410[j].idVendor = vendor_3410[i];
 		ti_id_table_3410[j].idProduct = product_3410[i];
 		ti_id_table_3410[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
 	}
 	j = ARRAY_SIZE(ti_id_table_5052) - TI_EXTRA_VID_PID_COUNT - 1;
-	for (i=0; i<min(vendor_5052_count,product_5052_count); i++,j++) {
+	for (i = 0; i < min(vendor_5052_count, product_5052_count); i++, j++) {
 		ti_id_table_5052[j].idVendor = vendor_5052[i];
 		ti_id_table_5052[j].idProduct = product_5052[i];
 		ti_id_table_5052[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
@@ -426,15 +435,15 @@
 	/* determine device type */
 	if (usb_match_id(serial->interface, ti_id_table_3410))
 		tdev->td_is_3410 = 1;
-	dbg("%s - device type is %s", __func__, tdev->td_is_3410 ? "3410" : "5052");
+	dbg("%s - device type is %s", __func__,
+				tdev->td_is_3410 ? "3410" : "5052");
 
 	/* if we have only 1 configuration, download firmware */
 	if (dev->descriptor.bNumConfigurations == 1) {
-
 		if (tdev->td_is_3410)
-			status = ti_download_firmware(tdev, "ti_3410.fw");
+			status = ti_download_firmware(tdev, 3410);
 		else
-			status = ti_download_firmware(tdev, "ti_5052.fw");
+			status = ti_download_firmware(tdev, 5052);
 		if (status)
 			goto free_tdev;
 
@@ -446,7 +455,7 @@
 
 		status = -ENODEV;
 		goto free_tdev;
-	} 
+	}
 
 	/* the second configuration must be set (in sysfs by hotplug script) */
 	if (dev->actconfig->desc.bConfigurationValue == TI_BOOT_CONFIG) {
@@ -463,7 +472,8 @@
 			goto free_tports;
 		}
 		spin_lock_init(&tport->tp_lock);
-		tport->tp_uart_base_addr = (i == 0 ? TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR);
+		tport->tp_uart_base_addr = (i == 0 ?
+				TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR);
 		tport->tp_flags = low_latency ? ASYNC_LOW_LATENCY : 0;
 		tport->tp_closing_wait = closing_wait;
 		init_waitqueue_head(&tport->tp_msr_wait);
@@ -480,11 +490,11 @@
 		usb_set_serial_port_data(serial->port[i], tport);
 		tport->tp_uart_mode = 0;	/* default is RS232 */
 	}
-	
+
 	return 0;
 
 free_tports:
-	for (--i; i>=0; --i) {
+	for (--i; i >= 0; --i) {
 		tport = usb_get_serial_port_data(serial->port[i]);
 		ti_buf_free(tport->tp_write_buf);
 		kfree(tport);
@@ -505,7 +515,7 @@
 
 	dbg("%s", __func__);
 
-	for (i=0; i < serial->num_ports; ++i) {
+	for (i = 0; i < serial->num_ports; ++i) {
 		tport = usb_get_serial_port_data(serial->port[i]);
 		if (tport) {
 			ti_buf_free(tport->tp_write_buf);
@@ -519,7 +529,8 @@
 }
 
 
-static int ti_open(struct usb_serial_port *port, struct file *file)
+static int ti_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *file)
 {
 	struct ti_port *tport = usb_get_serial_port_data(port);
 	struct ti_device *tdev;
@@ -527,8 +538,8 @@
 	struct urb *urb;
 	int port_number;
 	int status;
-	__u16 open_settings = (__u8)(TI_PIPE_MODE_CONTINOUS | 
-			     TI_PIPE_TIMEOUT_ENABLE | 
+	__u16 open_settings = (__u8)(TI_PIPE_MODE_CONTINOUS |
+			     TI_PIPE_TIMEOUT_ENABLE |
 			     (TI_TRANSFER_TIMEOUT << 2));
 
 	dbg("%s - port %d", __func__, port->number);
@@ -543,9 +554,9 @@
 	if (mutex_lock_interruptible(&tdev->td_open_close_lock))
 		return -ERESTARTSYS;
 
-	if (port->tty)
-		port->tty->low_latency = 
-			(tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+	if (tty)
+		tty->low_latency =
+				(tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0;
 
 	port_number = port->number - port->serial->minor;
 
@@ -559,7 +570,8 @@
 		dbg("%s - start interrupt in urb", __func__);
 		urb = tdev->td_serial->port[0]->interrupt_in_urb;
 		if (!urb) {
-			dev_err(&port->dev, "%s - no interrupt urb\n", __func__);
+			dev_err(&port->dev, "%s - no interrupt urb\n",
+								__func__);
 			status = -EINVAL;
 			goto release_lock;
 		}
@@ -568,18 +580,22 @@
 		urb->dev = dev;
 		status = usb_submit_urb(urb, GFP_KERNEL);
 		if (status) {
-			dev_err(&port->dev, "%s - submit interrupt urb failed, %d\n", __func__, status);
+			dev_err(&port->dev,
+				"%s - submit interrupt urb failed, %d\n",
+					__func__, status);
 			goto release_lock;
 		}
 	}
 
-	ti_set_termios(port, port->tty->termios);
+	if (tty)
+		ti_set_termios(tty, port, tty->termios);
 
 	dbg("%s - sending TI_OPEN_PORT", __func__);
 	status = ti_command_out_sync(tdev, TI_OPEN_PORT,
 		(__u8)(TI_UART1_PORT + port_number), open_settings, NULL, 0);
 	if (status) {
-		dev_err(&port->dev, "%s - cannot send open command, %d\n", __func__, status);
+		dev_err(&port->dev, "%s - cannot send open command, %d\n",
+							__func__, status);
 		goto unlink_int_urb;
 	}
 
@@ -587,7 +603,8 @@
 	status = ti_command_out_sync(tdev, TI_START_PORT,
 		(__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
 	if (status) {
-		dev_err(&port->dev, "%s - cannot send start command, %d\n", __func__, status);
+		dev_err(&port->dev, "%s - cannot send start command, %d\n",
+							__func__, status);
 		goto unlink_int_urb;
 	}
 
@@ -595,13 +612,15 @@
 	status = ti_command_out_sync(tdev, TI_PURGE_PORT,
 		(__u8)(TI_UART1_PORT + port_number), TI_PURGE_INPUT, NULL, 0);
 	if (status) {
-		dev_err(&port->dev, "%s - cannot clear input buffers, %d\n", __func__, status);
+		dev_err(&port->dev, "%s - cannot clear input buffers, %d\n",
+							__func__, status);
 		goto unlink_int_urb;
 	}
 	status = ti_command_out_sync(tdev, TI_PURGE_PORT,
 		(__u8)(TI_UART1_PORT + port_number), TI_PURGE_OUTPUT, NULL, 0);
 	if (status) {
-		dev_err(&port->dev, "%s - cannot clear output buffers, %d\n", __func__, status);
+		dev_err(&port->dev, "%s - cannot clear output buffers, %d\n",
+							__func__, status);
 		goto unlink_int_urb;
 	}
 
@@ -610,13 +629,15 @@
 	usb_clear_halt(dev, port->write_urb->pipe);
 	usb_clear_halt(dev, port->read_urb->pipe);
 
-	ti_set_termios(port, port->tty->termios);
+	if (tty)
+		ti_set_termios(tty, port, tty->termios);
 
 	dbg("%s - sending TI_OPEN_PORT (2)", __func__);
 	status = ti_command_out_sync(tdev, TI_OPEN_PORT,
 		(__u8)(TI_UART1_PORT + port_number), open_settings, NULL, 0);
 	if (status) {
-		dev_err(&port->dev, "%s - cannot send open command (2), %d\n", __func__, status);
+		dev_err(&port->dev, "%s - cannot send open command (2), %d\n",
+							__func__, status);
 		goto unlink_int_urb;
 	}
 
@@ -624,7 +645,8 @@
 	status = ti_command_out_sync(tdev, TI_START_PORT,
 		(__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
 	if (status) {
-		dev_err(&port->dev, "%s - cannot send start command (2), %d\n", __func__, status);
+		dev_err(&port->dev, "%s - cannot send start command (2), %d\n",
+							__func__, status);
 		goto unlink_int_urb;
 	}
 
@@ -642,7 +664,8 @@
 	urb->dev = dev;
 	status = usb_submit_urb(urb, GFP_KERNEL);
 	if (status) {
-		dev_err(&port->dev, "%s - submit read urb failed, %d\n", __func__, status);
+		dev_err(&port->dev, "%s - submit read urb failed, %d\n",
+							__func__, status);
 		goto unlink_int_urb;
 	}
 
@@ -661,7 +684,8 @@
 }
 
 
-static void ti_close(struct usb_serial_port *port, struct file *file)
+static void ti_close(struct tty_struct *tty, struct usb_serial_port *port,
+							struct file *file)
 {
 	struct ti_device *tdev;
 	struct ti_port *tport;
@@ -670,7 +694,7 @@
 	int do_unlock;
 
 	dbg("%s - port %d", __func__, port->number);
-			 
+
 	tdev = usb_get_serial_data(port->serial);
 	tport = usb_get_serial_port_data(port);
 	if (tdev == NULL || tport == NULL)
@@ -690,7 +714,9 @@
 	status = ti_command_out_sync(tdev, TI_CLOSE_PORT,
 		     (__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
 	if (status)
-		dev_err(&port->dev, "%s - cannot send close port command, %d\n" , __func__, status);
+		dev_err(&port->dev,
+			"%s - cannot send close port command, %d\n"
+							, __func__, status);
 
 	/* if mutex_lock is interrupted, continue anyway */
 	do_unlock = !mutex_lock_interruptible(&tdev->td_open_close_lock);
@@ -707,8 +733,8 @@
 }
 
 
-static int ti_write(struct usb_serial_port *port, const unsigned char *data,
-	int count)
+static int ti_write(struct tty_struct *tty, struct usb_serial_port *port,
+			const unsigned char *data, int count)
 {
 	struct ti_port *tport = usb_get_serial_port_data(port);
 	unsigned long flags;
@@ -733,8 +759,9 @@
 }
 
 
-static int ti_write_room(struct usb_serial_port *port)
+static int ti_write_room(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct ti_port *tport = usb_get_serial_port_data(port);
 	int room = 0;
 	unsigned long flags;
@@ -743,7 +770,7 @@
 
 	if (tport == NULL)
 		return -ENODEV;
-	
+
 	spin_lock_irqsave(&tport->tp_lock, flags);
 	room = ti_buf_space_avail(tport->tp_write_buf);
 	spin_unlock_irqrestore(&tport->tp_lock, flags);
@@ -753,8 +780,9 @@
 }
 
 
-static int ti_chars_in_buffer(struct usb_serial_port *port)
+static int ti_chars_in_buffer(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct ti_port *tport = usb_get_serial_port_data(port);
 	int chars = 0;
 	unsigned long flags;
@@ -773,32 +801,26 @@
 }
 
 
-static void ti_throttle(struct usb_serial_port *port)
+static void ti_throttle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct ti_port *tport = usb_get_serial_port_data(port);
-	struct tty_struct *tty;
 
 	dbg("%s - port %d", __func__, port->number);
 
 	if (tport == NULL)
 		return;
 
-	tty = port->tty;
-	if (!tty) {
-		dbg("%s - no tty", __func__);
-		return;
-	}
-
 	if (I_IXOFF(tty) || C_CRTSCTS(tty))
 		ti_stop_read(tport, tty);
 
 }
 
 
-static void ti_unthrottle(struct usb_serial_port *port)
+static void ti_unthrottle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct ti_port *tport = usb_get_serial_port_data(port);
-	struct tty_struct *tty;
 	int status;
 
 	dbg("%s - port %d", __func__, port->number);
@@ -806,23 +828,19 @@
 	if (tport == NULL)
 		return;
 
-	tty = port->tty;
-	if (!tty) {
-		dbg("%s - no tty", __func__);
-		return;
-	}
-
 	if (I_IXOFF(tty) || C_CRTSCTS(tty)) {
 		status = ti_restart_read(tport, tty);
 		if (status)
-			dev_err(&port->dev, "%s - cannot restart read, %d\n", __func__, status);
+			dev_err(&port->dev, "%s - cannot restart read, %d\n",
+							__func__, status);
 	}
 }
 
 
-static int ti_ioctl(struct usb_serial_port *port, struct file *file,
+static int ti_ioctl(struct tty_struct *tty, struct file *file,
 	unsigned int cmd, unsigned long arg)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct ti_port *tport = usb_get_serial_port_data(port);
 	struct async_icount cnow;
 	struct async_icount cprev;
@@ -833,55 +851,52 @@
 		return -ENODEV;
 
 	switch (cmd) {
-		case TIOCGSERIAL:
-			dbg("%s - (%d) TIOCGSERIAL", __func__, port->number);
-			return ti_get_serial_info(tport, (struct serial_struct __user *)arg);
-			break;
-
-		case TIOCSSERIAL:
-			dbg("%s - (%d) TIOCSSERIAL", __func__, port->number);
-			return ti_set_serial_info(tport, (struct serial_struct __user *)arg);
-			break;
-
-		case TIOCMIWAIT:
-			dbg("%s - (%d) TIOCMIWAIT", __func__, port->number);
-			cprev = tport->tp_icount;
-			while (1) {
-				interruptible_sleep_on(&tport->tp_msr_wait);
-				if (signal_pending(current))
-					return -ERESTARTSYS;
-				cnow = tport->tp_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;
-			}
-			break;
-
-		case TIOCGICOUNT:
-			dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, port->number, tport->tp_icount.rx, tport->tp_icount.tx);
-			if (copy_to_user((void __user *)arg, &tport->tp_icount, sizeof(tport->tp_icount)))
-				return -EFAULT;
-			return 0;
+	case TIOCGSERIAL:
+		dbg("%s - (%d) TIOCGSERIAL", __func__, port->number);
+		return ti_get_serial_info(tport,
+				(struct serial_struct __user *)arg);
+	case TIOCSSERIAL:
+		dbg("%s - (%d) TIOCSSERIAL", __func__, port->number);
+		return ti_set_serial_info(tport,
+					(struct serial_struct __user *)arg);
+	case TIOCMIWAIT:
+		dbg("%s - (%d) TIOCMIWAIT", __func__, port->number);
+		cprev = tport->tp_icount;
+		while (1) {
+			interruptible_sleep_on(&tport->tp_msr_wait);
+			if (signal_pending(current))
+				return -ERESTARTSYS;
+			cnow = tport->tp_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;
+		}
+		break;
+	case TIOCGICOUNT:
+		dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d",
+				__func__, port->number,
+				tport->tp_icount.rx, tport->tp_icount.tx);
+		if (copy_to_user((void __user *)arg, &tport->tp_icount,
+					sizeof(tport->tp_icount)))
+			return -EFAULT;
+		return 0;
 	}
-
 	return -ENOIOCTLCMD;
 }
 
 
-static void ti_set_termios(struct usb_serial_port *port,
-	struct ktermios *old_termios)
+static void ti_set_termios(struct tty_struct *tty,
+		struct usb_serial_port *port, struct ktermios *old_termios)
 {
 	struct ti_port *tport = usb_get_serial_port_data(port);
-	struct tty_struct *tty = port->tty;
 	struct ti_uart_config *config;
-	tcflag_t cflag,iflag;
+	tcflag_t cflag, iflag;
 	int baud;
 	int status;
 	int port_number = port->number - port->serial->minor;
@@ -893,7 +908,8 @@
 	iflag = tty->termios->c_iflag;
 
 	dbg("%s - cflag %08x, iflag %08x", __func__, cflag, iflag);
-	dbg("%s - old clfag %08x, old iflag %08x", __func__, old_termios->c_cflag, old_termios->c_iflag);
+	dbg("%s - old clfag %08x, old iflag %08x", __func__,
+				old_termios->c_cflag, old_termios->c_iflag);
 
 	if (tport == NULL)
 		return;
@@ -912,19 +928,19 @@
 	config->bUartMode = (__u8)(tport->tp_uart_mode);
 
 	switch (cflag & CSIZE) {
-		case CS5:
-			    config->bDataBits = TI_UART_5_DATA_BITS;
-			    break;
-		case CS6:
-			    config->bDataBits = TI_UART_6_DATA_BITS;
-			    break;
-		case CS7:
-			    config->bDataBits = TI_UART_7_DATA_BITS;
-			    break;
-		default:
-		case CS8:
-			    config->bDataBits = TI_UART_8_DATA_BITS;
-			    break;
+	case CS5:
+		    config->bDataBits = TI_UART_5_DATA_BITS;
+		    break;
+	case CS6:
+		    config->bDataBits = TI_UART_6_DATA_BITS;
+		    break;
+	case CS7:
+		    config->bDataBits = TI_UART_7_DATA_BITS;
+		    break;
+	default:
+	case CS8:
+		    config->bDataBits = TI_UART_8_DATA_BITS;
+		    break;
 	}
 
 	/* CMSPAR isn't supported by this driver */
@@ -940,7 +956,7 @@
 		}
 	} else {
 		config->wFlags &= ~TI_UART_ENABLE_PARITY_CHECKING;
-		config->bParity = TI_UART_NO_PARITY; 	
+		config->bParity = TI_UART_NO_PARITY;
 	}
 
 	if (cflag & CSTOPB)
@@ -993,7 +1009,8 @@
 		(__u8)(TI_UART1_PORT + port_number), 0, (__u8 *)config,
 		sizeof(*config));
 	if (status)
-		dev_err(&port->dev, "%s - cannot set config on port %d, %d\n", __func__, port_number, status);
+		dev_err(&port->dev, "%s - cannot set config on port %d, %d\n",
+					__func__, port_number, status);
 
 	/* SET_CONFIG asserts RTS and DTR, reset them correctly */
 	mcr = tport->tp_shadow_mcr;
@@ -1002,14 +1019,17 @@
 		mcr &= ~(TI_MCR_DTR | TI_MCR_RTS);
 	status = ti_set_mcr(tport, mcr);
 	if (status)
-		dev_err(&port->dev, "%s - cannot set modem control on port %d, %d\n", __func__, port_number, status);
+		dev_err(&port->dev,
+			"%s - cannot set modem control on port %d, %d\n",
+						__func__, port_number, status);
 
 	kfree(config);
 }
 
 
-static int ti_tiocmget(struct usb_serial_port *port, struct file *file)
+static int ti_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct ti_port *tport = usb_get_serial_port_data(port);
 	unsigned int result;
 	unsigned int msr;
@@ -1040,9 +1060,10 @@
 }
 
 
-static int ti_tiocmset(struct usb_serial_port *port, struct file *file,
+static int ti_tiocmset(struct tty_struct *tty, struct file *file,
 	unsigned int set, unsigned int clear)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct ti_port *tport = usb_get_serial_port_data(port);
 	unsigned int mcr;
 	unsigned long flags;
@@ -1074,8 +1095,9 @@
 }
 
 
-static void ti_break(struct usb_serial_port *port, int break_state)
+static void ti_break(struct tty_struct *tty, int break_state)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct ti_port *tport = usb_get_serial_port_data(port);
 	int status;
 
@@ -1141,10 +1163,12 @@
 	port_number = TI_GET_PORT_FROM_CODE(data[0]);
 	function = TI_GET_FUNC_FROM_CODE(data[0]);
 
-	dbg("%s - port_number %d, function %d, data 0x%02X", __func__, port_number, function, data[1]);
+	dbg("%s - port_number %d, function %d, data 0x%02X",
+				__func__, port_number, function, data[1]);
 
 	if (port_number >= serial->num_ports) {
-		dev_err(dev, "%s - bad port number, %d\n", __func__, port_number);
+		dev_err(dev, "%s - bad port number, %d\n",
+						__func__, port_number);
 		goto exit;
 	}
 
@@ -1156,7 +1180,8 @@
 
 	switch (function) {
 	case TI_CODE_DATA_ERROR:
-		dev_err(dev, "%s - DATA ERROR, port %d, data 0x%02X\n", __func__, port_number, data[1]);
+		dev_err(dev, "%s - DATA ERROR, port %d, data 0x%02X\n",
+					__func__, port_number, data[1]);
 		break;
 
 	case TI_CODE_MODEM_STATUS:
@@ -1166,7 +1191,8 @@
 		break;
 
 	default:
-		dev_err(dev, "%s - unknown interrupt code, 0x%02X\n", __func__, data[1]);
+		dev_err(dev, "%s - unknown interrupt code, 0x%02X\n",
+							__func__, data[1]);
 		break;
 	}
 
@@ -1200,7 +1226,7 @@
 		return;
 	default:
 		dev_err(dev, "%s - nonzero urb status, %d\n",
-			__func__, status );
+			__func__, status);
 		tport->tp_tdev->td_urb_error = 1;
 		wake_up_interruptible(&tport->tp_write_wait);
 	}
@@ -1213,15 +1239,16 @@
 		return;
 	}
 
-	if (port->tty && urb->actual_length) {
+	if (port->port.tty && urb->actual_length) {
 		usb_serial_debug_data(debug, dev, __func__,
 			urb->actual_length, urb->transfer_buffer);
 
 		if (!tport->tp_is_open)
 			dbg("%s - port closed, dropping data", __func__);
 		else
-			ti_recv(&urb->dev->dev, port->tty, urb->transfer_buffer,
-				urb->actual_length);
+			ti_recv(&urb->dev->dev, port->port.tty,
+						urb->transfer_buffer,
+						urb->actual_length);
 
 		spin_lock(&tport->tp_lock);
 		tport->tp_icount.rx += urb->actual_length;
@@ -1285,8 +1312,9 @@
 	do {
 		cnt = tty_buffer_request_room(tty, length);
 		if (cnt < length) {
-			dev_err(dev, "%s - dropping data, %d bytes lost\n", __func__, length - cnt);
-			if(cnt == 0)
+			dev_err(dev, "%s - dropping data, %d bytes lost\n",
+						__func__, length - cnt);
+			if (cnt == 0)
 				break;
 		}
 		tty_insert_flip_string(tty, data, cnt);
@@ -1302,7 +1330,7 @@
 {
 	int count, result;
 	struct usb_serial_port *port = tport->tp_port;
-	struct tty_struct *tty = port->tty;
+	struct tty_struct *tty = port->port.tty;	/* FIXME */
 	unsigned long flags;
 
 
@@ -1328,7 +1356,8 @@
 
 	spin_unlock_irqrestore(&tport->tp_lock, flags);
 
-	usb_serial_debug_data(debug, &port->dev, __func__, count, port->write_urb->transfer_buffer);
+	usb_serial_debug_data(debug, &port->dev, __func__, count,
+					port->write_urb->transfer_buffer);
 
 	usb_fill_bulk_urb(port->write_urb, port->serial->dev,
 			   usb_sndbulkpipe(port->serial->dev,
@@ -1338,8 +1367,9 @@
 
 	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
 	if (result) {
-		dev_err(&port->dev, "%s - submit write urb failed, %d\n", __func__, result);
-		tport->tp_write_urb_in_use = 0; 
+		dev_err(&port->dev, "%s - submit write urb failed, %d\n",
+							__func__, result);
+		tport->tp_write_urb_in_use = 0;
 		/* TODO: reschedule ti_send */
 	} else {
 		spin_lock_irqsave(&tport->tp_lock, flags);
@@ -1374,7 +1404,7 @@
 
 static int ti_get_lsr(struct ti_port *tport)
 {
-	int size,status;
+	int size, status;
 	struct ti_device *tdev = tport->tp_tdev;
 	struct usb_serial_port *port = tport->tp_port;
 	int port_number = port->number - port->serial->minor;
@@ -1392,7 +1422,9 @@
 	status = ti_command_in_sync(tdev, TI_GET_PORT_STATUS,
 		(__u8)(TI_UART1_PORT+port_number), 0, (__u8 *)data, size);
 	if (status) {
-		dev_err(&port->dev, "%s - get port status command failed, %d\n", __func__, status);
+		dev_err(&port->dev,
+			"%s - get port status command failed, %d\n",
+							__func__, status);
 		goto free_data;
 	}
 
@@ -1442,8 +1474,9 @@
 		return -EFAULT;
 
 	tport->tp_flags = new_serial.flags & TI_SET_SERIAL_FLAGS;
-	if (port->tty)
-		port->tty->low_latency =
+	/* FIXME */
+	if (port->port.tty)
+		port->port.tty->low_latency =
 			(tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0;
 	tport->tp_closing_wait = new_serial.closing_wait;
 
@@ -1477,7 +1510,7 @@
 	tport->tp_msr = msr & TI_MSR_MASK;
 
 	/* handle CTS flow control */
-	tty = tport->tp_port->tty;
+	tty = tport->tp_port->port.tty;
 	if (tty && C_CRTSCTS(tty)) {
 		if (msr & TI_MSR_CTS) {
 			tty->hw_stopped = 0;
@@ -1627,7 +1660,8 @@
 	struct ti_write_data_bytes *data;
 	struct device *dev = &tdev->td_serial->dev->dev;
 
-	dbg("%s - addr 0x%08lX, mask 0x%02X, byte 0x%02X", __func__, addr, mask, byte);
+	dbg("%s - addr 0x%08lX, mask 0x%02X, byte 0x%02X",
+					__func__, addr, mask, byte);
 
 	size = sizeof(struct ti_write_data_bytes) + 2;
 	data = kmalloc(size, GFP_KERNEL);
@@ -1655,67 +1689,68 @@
 	return status;
 }
 
-
-static int ti_download_firmware(struct ti_device *tdev,
-				char *fw_name)
+static int ti_do_download(struct usb_device *dev, int pipe,
+						u8 *buffer, int size)
 {
-	const struct firmware *fw;
-	int status = 0;
-	int buffer_size;
 	int pos;
-	int len;
+	u8 cs = 0;
 	int done;
-	__u8 cs = 0;
-	__u8 *buffer;
-	struct usb_device *dev = tdev->td_serial->dev;
 	struct ti_firmware_header *header;
-	unsigned int pipe = usb_sndbulkpipe(dev,
-		tdev->td_serial->port[0]->bulk_out_endpointAddress);
+	int status;
+	int len;
 
-	buffer_size = TI_FIRMWARE_BUF_SIZE + sizeof(struct ti_firmware_header);
-
-	if (request_firmware(&fw, fw_name, &dev->dev)) {
-		dev_err(&dev->dev, "%s - failed to load firmware \"%s\"\n",
-			__func__, fw_name);
-		return -ENOENT;
-	}
-	if (fw->size > buffer_size) {
-		dev_err(&dev->dev, "%s - firmware \"%s\" is too large\n",
-			__func__, fw_name);
-		release_firmware(fw);
-		return -EINVAL;
-	}
-
-	buffer = kmalloc(buffer_size, GFP_KERNEL);
-	if (!buffer) {
-		dev_err(&dev->dev, "%s - out of memory\n", __func__);
-		release_firmware(fw);
-		return -ENOMEM;
-	}
-
-	memcpy(buffer, fw->data, fw->size);
-	memset(buffer+fw->size, 0xff, buffer_size-fw->size);
-
-	for(pos = sizeof(struct ti_firmware_header); pos < buffer_size; pos++)
+	for (pos = sizeof(struct ti_firmware_header); pos < size; pos++)
 		cs = (__u8)(cs + buffer[pos]);
 
 	header = (struct ti_firmware_header *)buffer;
-	header->wLength = cpu_to_le16((__u16)(buffer_size - sizeof(struct ti_firmware_header)));
+	header->wLength = cpu_to_le16((__u16)(size
+					- sizeof(struct ti_firmware_header)));
 	header->bCheckSum = cs;
 
 	dbg("%s - downloading firmware", __func__);
-	for (pos = 0; pos < buffer_size; pos += done) {
-		len = min(buffer_size - pos, TI_DOWNLOAD_MAX_PACKET_SIZE);
-		status = usb_bulk_msg(dev, pipe, buffer+pos, len, &done, 1000);
+	for (pos = 0; pos < size; pos += done) {
+		len = min(size - pos, TI_DOWNLOAD_MAX_PACKET_SIZE);
+		status = usb_bulk_msg(dev, pipe, buffer + pos, len,
+								&done, 1000);
 		if (status)
 			break;
 	}
+	return status;
+}
 
-	kfree(buffer);
-	release_firmware(fw);
+static int ti_download_firmware(struct ti_device *tdev, int type)
+{
+	int status = -ENOMEM;
+	int buffer_size;
+	__u8 *buffer;
+	struct usb_device *dev = tdev->td_serial->dev;
+	unsigned int pipe = usb_sndbulkpipe(dev,
+		tdev->td_serial->port[0]->bulk_out_endpointAddress);
+	const struct firmware *fw_p;
+	char buf[32];
+	sprintf(buf, "ti_usb-%d.bin", type);
 
+	if (request_firmware(&fw_p, buf, &dev->dev)) {
+		dev_err(&dev->dev, "%s - firmware not found\n", __func__);
+		return -ENOENT;
+	}
+	if (fw_p->size > TI_FIRMWARE_BUF_SIZE) {
+		dev_err(&dev->dev, "%s - firmware too large\n", __func__);
+		return -ENOENT;
+	}
+
+	buffer_size = TI_FIRMWARE_BUF_SIZE + sizeof(struct ti_firmware_header);
+	buffer = kmalloc(buffer_size, GFP_KERNEL);
+	if (buffer) {
+		memcpy(buffer, fw_p->data, fw_p->size);
+		memset(buffer + fw_p->size, 0xff, buffer_size - fw_p->size);
+		ti_do_download(dev, pipe, buffer, fw_p->size);
+		kfree(buffer);
+	}
+	release_firmware(fw_p);
 	if (status) {
-		dev_err(&dev->dev, "%s - error downloading firmware, %d\n", __func__, status);
+		dev_err(&dev->dev, "%s - error downloading firmware, %d\n",
+							__func__, status);
 		return status;
 	}
 
@@ -1787,7 +1822,7 @@
 
 static int ti_buf_data_avail(struct circ_buf *cb)
 {
-	return CIRC_CNT(cb->head,cb->tail,TI_WRITE_BUF_SIZE);
+	return CIRC_CNT(cb->head, cb->tail, TI_WRITE_BUF_SIZE);
 }
 
 
@@ -1800,7 +1835,7 @@
 
 static int ti_buf_space_avail(struct circ_buf *cb)
 {
-	return CIRC_SPACE(cb->head,cb->tail,TI_WRITE_BUF_SIZE);
+	return CIRC_SPACE(cb->head, cb->tail, TI_WRITE_BUF_SIZE);
 }
 
 
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 0cb0d77..8c2d531 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -12,7 +12,8 @@
  * This driver was originally based on the ACM driver by Armin Fuerst (which was
  * based on a driver by Brad Keryan)
  *
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
  *
  */
 
@@ -28,7 +29,7 @@
 #include <linux/spinlock.h>
 #include <linux/mutex.h>
 #include <linux/list.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 #include "pl2303.h"
@@ -59,7 +60,8 @@
 */
 
 static int debug;
-static struct usb_serial *serial_table[SERIAL_TTY_MINORS];	/* initially all NULL */
+/* initially all NULL */
+static struct usb_serial *serial_table[SERIAL_TTY_MINORS];
 static DEFINE_MUTEX(table_lock);
 static LIST_HEAD(usb_serial_driver_list);
 
@@ -76,7 +78,8 @@
 	return serial;
 }
 
-static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_ports, unsigned int *minor)
+static struct usb_serial *get_free_serial(struct usb_serial *serial,
+					int num_ports, unsigned int *minor)
 {
 	unsigned int i, j;
 	int good_spot;
@@ -122,9 +125,8 @@
 	if (serial == NULL)
 		return;
 
-	for (i = 0; i < serial->num_ports; ++i) {
+	for (i = 0; i < serial->num_ports; ++i)
 		serial_table[serial->minor + i] = NULL;
-	}
 }
 
 static void destroy_serial(struct kref *kref)
@@ -143,7 +145,7 @@
 	return_serial(serial);
 
 	for (i = 0; i < serial->num_ports; ++i)
-		serial->port[i]->open_count = 0;
+		serial->port[i]->port.count = 0;
 
 	/* the ports are cleaned up and released in port_release() */
 	for (i = 0; i < serial->num_ports; ++i)
@@ -156,7 +158,8 @@
 	 * not get cleaned up in port_release() as it was never registered with
 	 * the driver core */
 	if (serial->num_ports < serial->num_port_pointers) {
-		for (i = serial->num_ports; i < serial->num_port_pointers; ++i) {
+		for (i = serial->num_ports;
+					i < serial->num_port_pointers; ++i) {
 			port = serial->port[i];
 			if (!port)
 				continue;
@@ -167,7 +170,7 @@
 	usb_put_dev(serial->dev);
 
 	/* free up any memory that we allocated */
-	kfree (serial);
+	kfree(serial);
 }
 
 void usb_serial_put(struct usb_serial *serial)
@@ -180,13 +183,13 @@
 /*****************************************************************************
  * Driver tty interface functions
  *****************************************************************************/
-static int serial_open (struct tty_struct *tty, struct file * filp)
+static int serial_open (struct tty_struct *tty, struct file *filp)
 {
 	struct usb_serial *serial;
 	struct usb_serial_port *port;
 	unsigned int portNumber;
 	int retval;
-	
+
 	dbg("%s", __func__);
 
 	/* get the serial object associated with this tty pointer */
@@ -207,15 +210,15 @@
 		retval = -ERESTARTSYS;
 		goto bailout_kref_put;
 	}
-	 
-	++port->open_count;
+
+	++port->port.count;
 
 	/* set up our port structure making the tty driver
 	 * remember our port object, and us it */
 	tty->driver_data = port;
-	port->tty = tty;
+	port->port.tty = tty;
 
-	if (port->open_count == 1) {
+	if (port->port.count == 1) {
 
 		/* lock this module before we call it
 		 * this may fail, which means we must bail out,
@@ -228,9 +231,9 @@
 		retval = usb_autopm_get_interface(serial->interface);
 		if (retval)
 			goto bailout_module_put;
-		/* only call the device specific open if this 
+		/* only call the device specific open if this
 		 * is the first time the port is opened */
-		retval = serial->type->open(port, filp);
+		retval = serial->type->open(tty, port, filp);
 		if (retval)
 			goto bailout_interface_put;
 	}
@@ -243,16 +246,16 @@
 bailout_module_put:
 	module_put(serial->type->driver.owner);
 bailout_mutex_unlock:
-	port->open_count = 0;
+	port->port.count = 0;
 	tty->driver_data = NULL;
-	port->tty = NULL;
+	port->port.tty = NULL;
 	mutex_unlock(&port->mutex);
 bailout_kref_put:
 	usb_serial_put(serial);
 	return retval;
 }
 
-static void serial_close(struct tty_struct *tty, struct file * filp)
+static void serial_close(struct tty_struct *tty, struct file *filp)
 {
 	struct usb_serial_port *port = tty->driver_data;
 
@@ -263,27 +266,30 @@
 
 	mutex_lock(&port->mutex);
 
-	if (port->open_count == 0) {
+	if (port->port.count == 0) {
 		mutex_unlock(&port->mutex);
 		return;
 	}
 
-	--port->open_count;
-	if (port->open_count == 0)
-		/* only call the device specific close if this 
+	--port->port.count;
+	if (port->port.count == 0)
+		/* only call the device specific close if this
 		 * port is being closed by the last owner */
-		port->serial->type->close(port, filp);
+		port->serial->type->close(tty, port, filp);
 
-	if (port->open_count == (port->console? 1 : 0)) {
-		if (port->tty) {
-			if (port->tty->driver_data)
-				port->tty->driver_data = NULL;
-			port->tty = NULL;
+	if (port->port.count == (port->console? 1 : 0)) {
+		if (port->port.tty) {
+			if (port->port.tty->driver_data)
+				port->port.tty->driver_data = NULL;
+			port->port.tty = NULL;
 		}
 	}
 
-	if (port->open_count == 0) {
-		usb_autopm_put_interface(port->serial->interface);
+	if (port->port.count == 0) {
+		mutex_lock(&port->serial->disc_mutex);
+		if (!port->serial->disconnected)
+			usb_autopm_put_interface(port->serial->interface);
+		mutex_unlock(&port->serial->disc_mutex);
 		module_put(port->serial->type->driver.owner);
 	}
 
@@ -291,7 +297,8 @@
 	usb_serial_put(port->serial);
 }
 
-static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count)
+static int serial_write(struct tty_struct *tty, const unsigned char *buf,
+								int count)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	int retval = -ENODEV;
@@ -301,107 +308,112 @@
 
 	dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
 
-	/* open_count is managed under the mutex lock for the tty so cannot
-           drop to zero until after the last close completes */
-	WARN_ON(!port->open_count);
+	/* count is managed under the mutex lock for the tty so cannot
+	   drop to zero until after the last close completes */
+	WARN_ON(!port->port.count);
 
 	/* pass on to the driver specific version of this function */
-	retval = port->serial->type->write(port, buf, count);
+	retval = port->serial->type->write(tty, port, buf, count);
 
 exit:
 	return retval;
 }
 
-static int serial_write_room (struct tty_struct *tty) 
+static int serial_write_room(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	dbg("%s - port %d", __func__, port->number);
-	WARN_ON(!port->open_count);
+	WARN_ON(!port->port.count);
 	/* pass on to the driver specific version of this function */
-	return port->serial->type->write_room(port);
+	return port->serial->type->write_room(tty);
 }
 
-static int serial_chars_in_buffer (struct tty_struct *tty) 
+static int serial_chars_in_buffer(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	dbg("%s = port %d", __func__, port->number);
 
-	WARN_ON(!port->open_count);
+	WARN_ON(!port->port.count);
 	/* pass on to the driver specific version of this function */
-	return port->serial->type->chars_in_buffer(port);
+	return port->serial->type->chars_in_buffer(tty);
 }
 
-static void serial_throttle (struct tty_struct * tty)
+static void serial_throttle(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	dbg("%s - port %d", __func__, port->number);
 
-	WARN_ON(!port->open_count);
+	WARN_ON(!port->port.count);
 	/* pass on to the driver specific version of this function */
 	if (port->serial->type->throttle)
-		port->serial->type->throttle(port);
+		port->serial->type->throttle(tty);
 }
 
-static void serial_unthrottle (struct tty_struct * tty)
+static void serial_unthrottle(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	dbg("%s - port %d", __func__, port->number);
 
-	WARN_ON(!port->open_count);
+	WARN_ON(!port->port.count);
 	/* pass on to the driver specific version of this function */
 	if (port->serial->type->unthrottle)
-		port->serial->type->unthrottle(port);
+		port->serial->type->unthrottle(tty);
 }
 
-static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
+static int serial_ioctl(struct tty_struct *tty, struct file *file,
+					unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	int retval = -ENODEV;
 
 	dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
 
-	WARN_ON(!port->open_count);
+	WARN_ON(!port->port.count);
 
-	/* pass on to the driver specific version of this function if it is available */
+	/* pass on to the driver specific version of this function
+	   if it is available */
 	if (port->serial->type->ioctl) {
 		lock_kernel();
-		retval = port->serial->type->ioctl(port, file, cmd, arg);
+		retval = port->serial->type->ioctl(tty, file, cmd, arg);
 		unlock_kernel();
-	}
-	else
+	} else
 		retval = -ENOIOCTLCMD;
 	return retval;
 }
 
-static void serial_set_termios (struct tty_struct *tty, struct ktermios * old)
+static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	dbg("%s - port %d", __func__, port->number);
 
-	WARN_ON(!port->open_count);
-	/* pass on to the driver specific version of this function if it is available */
+	WARN_ON(!port->port.count);
+	/* pass on to the driver specific version of this function
+	   if it is available */
 	if (port->serial->type->set_termios)
-		port->serial->type->set_termios(port, old);
+		port->serial->type->set_termios(tty, port, old);
 	else
 		tty_termios_copy_hw(tty->termios, old);
 }
 
-static void serial_break (struct tty_struct *tty, int break_state)
+static int serial_break(struct tty_struct *tty, int break_state)
 {
 	struct usb_serial_port *port = tty->driver_data;
 
 	dbg("%s - port %d", __func__, port->number);
 
-	WARN_ON(!port->open_count);
-	/* pass on to the driver specific version of this function if it is available */
+	WARN_ON(!port->port.count);
+	/* pass on to the driver specific version of this function
+	   if it is available */
 	if (port->serial->type->break_ctl) {
 		lock_kernel();
-		port->serial->type->break_ctl(port, break_state);
+		port->serial->type->break_ctl(tty, break_state);
 		unlock_kernel();
 	}
+	return 0;
 }
 
-static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
+static int serial_read_proc(char *page, char **start, off_t off, int count,
+							int *eof, void *data)
 {
 	struct usb_serial *serial;
 	int length = 0;
@@ -410,26 +422,29 @@
 	char tmp[40];
 
 	dbg("%s", __func__);
-	length += sprintf (page, "usbserinfo:1.0 driver:2.0\n");
+	length += sprintf(page, "usbserinfo:1.0 driver:2.0\n");
 	for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) {
 		serial = usb_serial_get_by_index(i);
 		if (serial == NULL)
 			continue;
 
-		length += sprintf (page+length, "%d:", i);
+		length += sprintf(page+length, "%d:", i);
 		if (serial->type->driver.owner)
-			length += sprintf (page+length, " module:%s", module_name(serial->type->driver.owner));
-		length += sprintf (page+length, " name:\"%s\"", serial->type->description);
-		length += sprintf (page+length, " vendor:%04x product:%04x", 
-				   le16_to_cpu(serial->dev->descriptor.idVendor), 
-				   le16_to_cpu(serial->dev->descriptor.idProduct));
-		length += sprintf (page+length, " num_ports:%d", serial->num_ports);
-		length += sprintf (page+length, " port:%d", i - serial->minor + 1);
-
+			length += sprintf(page+length, " module:%s",
+				module_name(serial->type->driver.owner));
+		length += sprintf(page+length, " name:\"%s\"",
+				serial->type->description);
+		length += sprintf(page+length, " vendor:%04x product:%04x",
+			le16_to_cpu(serial->dev->descriptor.idVendor),
+			le16_to_cpu(serial->dev->descriptor.idProduct));
+		length += sprintf(page+length, " num_ports:%d",
+							serial->num_ports);
+		length += sprintf(page+length, " port:%d",
+							i - serial->minor + 1);
 		usb_make_path(serial->dev, tmp, sizeof(tmp));
-		length += sprintf (page+length, " path:%s", tmp);
-			
-		length += sprintf (page+length, "\n");
+		length += sprintf(page+length, " path:%s", tmp);
+
+		length += sprintf(page+length, "\n");
 		if ((length + begin) > (off + count)) {
 			usb_serial_put(serial);
 			goto done;
@@ -445,31 +460,31 @@
 	if (off >= (length + begin))
 		return 0;
 	*start = page + (off-begin);
-	return ((count < begin+length-off) ? count : begin+length-off);
+	return (count < begin+length-off) ? count : begin+length-off;
 }
 
-static int serial_tiocmget (struct tty_struct *tty, struct file *file)
+static int serial_tiocmget(struct tty_struct *tty, struct file *file)
 {
 	struct usb_serial_port *port = tty->driver_data;
 
 	dbg("%s - port %d", __func__, port->number);
 
-	WARN_ON(!port->open_count);
+	WARN_ON(!port->port.count);
 	if (port->serial->type->tiocmget)
-		return port->serial->type->tiocmget(port, file);
+		return port->serial->type->tiocmget(tty, file);
 	return -EINVAL;
 }
 
-static int serial_tiocmset (struct tty_struct *tty, struct file *file,
+static int serial_tiocmset(struct tty_struct *tty, struct file *file,
 			    unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
 
 	dbg("%s - port %d", __func__, port->number);
 
-	WARN_ON(!port->open_count);
+	WARN_ON(!port->port.count);
 	if (port->serial->type->tiocmset)
-		return port->serial->type->tiocmset(port, file, set, clear);
+		return port->serial->type->tiocmset(tty, file, set, clear);
 	return -EINVAL;
 }
 
@@ -482,6 +497,7 @@
 {
 	schedule_work(&port->work);
 }
+EXPORT_SYMBOL_GPL(usb_serial_port_softint);
 
 static void usb_serial_port_work(struct work_struct *work)
 {
@@ -490,11 +506,11 @@
 	struct tty_struct *tty;
 
 	dbg("%s - port %d", __func__, port->number);
-	
+
 	if (!port)
 		return;
 
-	tty = port->tty;
+	tty = port->port.tty;
 	if (!tty)
 		return;
 
@@ -505,7 +521,7 @@
 {
 	struct usb_serial_port *port = to_usb_serial_port(dev);
 
-	dbg ("%s - %s", __func__, dev->bus_id);
+	dbg ("%s - %s", __func__, dev_name(dev));
 	port_free(port);
 }
 
@@ -543,9 +559,9 @@
 	kfree(port);
 }
 
-static struct usb_serial * create_serial (struct usb_device *dev, 
-					  struct usb_interface *interface,
-					  struct usb_serial_driver *driver)
+static struct usb_serial *create_serial(struct usb_device *dev,
+					struct usb_interface *interface,
+					struct usb_serial_driver *driver)
 {
 	struct usb_serial *serial;
 
@@ -564,7 +580,7 @@
 }
 
 static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
-						    struct usb_serial_driver *drv)
+					    struct usb_serial_driver *drv)
 {
 	struct usb_dynid *dynid;
 
@@ -596,7 +612,8 @@
 	return id;
 }
 
-static struct usb_serial_driver *search_serial_device(struct usb_interface *iface)
+static struct usb_serial_driver *search_serial_device(
+					struct usb_interface *iface)
 {
 	const struct usb_device_id *id;
 	struct usb_serial_driver *drv;
@@ -614,7 +631,7 @@
 int usb_serial_probe(struct usb_interface *interface,
 			       const struct usb_device_id *id)
 {
-	struct usb_device *dev = interface_to_usbdev (interface);
+	struct usb_device *dev = interface_to_usbdev(interface);
 	struct usb_serial *serial = NULL;
 	struct usb_serial_port *port;
 	struct usb_host_interface *iface_desc;
@@ -625,7 +642,7 @@
 	struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
 	struct usb_serial_driver *type = NULL;
 	int retval;
-	int minor;
+	unsigned int minor;
 	int buffer_size;
 	int i;
 	int num_interrupt_in = 0;
@@ -643,7 +660,7 @@
 		return -ENODEV;
 	}
 
-	serial = create_serial (dev, interface, type);
+	serial = create_serial(dev, interface, type);
 	if (!serial) {
 		unlock_kernel();
 		dev_err(&interface->dev, "%s - out of memory\n", __func__);
@@ -656,8 +673,9 @@
 
 		if (!try_module_get(type->driver.owner)) {
 			unlock_kernel();
-			dev_err(&interface->dev, "module get failed, exiting\n");
-			kfree (serial);
+			dev_err(&interface->dev,
+				"module get failed, exiting\n");
+			kfree(serial);
 			return -EIO;
 		}
 
@@ -667,8 +685,8 @@
 
 		if (retval) {
 			unlock_kernel();
-			dbg ("sub driver rejected device");
-			kfree (serial);
+			dbg("sub driver rejected device");
+			kfree(serial);
 			return retval;
 		}
 	}
@@ -709,7 +727,7 @@
 	}
 
 #if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
-	/* BEGIN HORRIBLE HACK FOR PL2303 */ 
+	/* BEGIN HORRIBLE HACK FOR PL2303 */
 	/* this is needed due to the looney way its endpoints are set up */
 	if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
 	     (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
@@ -738,7 +756,7 @@
 		if (num_bulk_in == 0 || num_bulk_out == 0) {
 			unlock_kernel();
 			dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
-			kfree (serial);
+			kfree(serial);
 			return -ENODEV;
 		}
 	}
@@ -750,8 +768,9 @@
 		num_ports = num_bulk_out;
 		if (num_ports == 0) {
 			unlock_kernel();
-			dev_err(&interface->dev, "Generic device with no bulk out, not allowed.\n");
-			kfree (serial);
+			dev_err(&interface->dev,
+			    "Generic device with no bulk out, not allowed.\n");
+			kfree(serial);
 			return -EIO;
 		}
 	}
@@ -761,11 +780,12 @@
 		if (type->calc_num_ports) {
 			if (!try_module_get(type->driver.owner)) {
 				unlock_kernel();
-				dev_err(&interface->dev, "module get failed, exiting\n");
-				kfree (serial);
+				dev_err(&interface->dev,
+					"module get failed, exiting\n");
+				kfree(serial);
 				return -EIO;
 			}
-			num_ports = type->calc_num_ports (serial);
+			num_ports = type->calc_num_ports(serial);
 			module_put(type->driver.owner);
 		}
 		if (!num_ports)
@@ -783,7 +803,8 @@
 			type->description);
 
 	/* create our ports, we need as many as the max endpoints */
-	/* we don't use num_ports here cauz some devices have more endpoint pairs than ports */
+	/* we don't use num_ports here because some devices have more
+	   endpoint pairs than ports */
 	max_endpoints = max(num_bulk_in, num_bulk_out);
 	max_endpoints = max(max_endpoints, num_interrupt_in);
 	max_endpoints = max(max_endpoints, num_interrupt_out);
@@ -791,7 +812,8 @@
 	serial->num_port_pointers = max_endpoints;
 	unlock_kernel();
 
-	dbg("%s - setting up %d port structures for this device", __func__, max_endpoints);
+	dbg("%s - setting up %d port structures for this device",
+						__func__, max_endpoints);
 	for (i = 0; i < max_endpoints; ++i) {
 		port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
 		if (!port)
@@ -807,7 +829,7 @@
 	for (i = 0; i < num_bulk_in; ++i) {
 		endpoint = bulk_in_endpoint[i];
 		port = serial->port[i];
-		port->read_urb = usb_alloc_urb (0, GFP_KERNEL);
+		port->read_urb = usb_alloc_urb(0, GFP_KERNEL);
 		if (!port->read_urb) {
 			dev_err(&interface->dev, "No free urbs available\n");
 			goto probe_error;
@@ -815,17 +837,17 @@
 		buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
 		port->bulk_in_size = buffer_size;
 		port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
-		port->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
+		port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
 		if (!port->bulk_in_buffer) {
-			dev_err(&interface->dev, "Couldn't allocate bulk_in_buffer\n");
+			dev_err(&interface->dev,
+					"Couldn't allocate bulk_in_buffer\n");
 			goto probe_error;
 		}
-		usb_fill_bulk_urb (port->read_urb, dev,
-				   usb_rcvbulkpipe (dev,
-					   	    endpoint->bEndpointAddress),
-				   port->bulk_in_buffer, buffer_size,
-				   serial->type->read_bulk_callback,
-				   port);
+		usb_fill_bulk_urb(port->read_urb, dev,
+				usb_rcvbulkpipe(dev,
+						endpoint->bEndpointAddress),
+				port->bulk_in_buffer, buffer_size,
+				serial->type->read_bulk_callback, port);
 	}
 
 	for (i = 0; i < num_bulk_out; ++i) {
@@ -839,17 +861,17 @@
 		buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
 		port->bulk_out_size = buffer_size;
 		port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
-		port->bulk_out_buffer = kmalloc (buffer_size, GFP_KERNEL);
+		port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
 		if (!port->bulk_out_buffer) {
-			dev_err(&interface->dev, "Couldn't allocate bulk_out_buffer\n");
+			dev_err(&interface->dev,
+					"Couldn't allocate bulk_out_buffer\n");
 			goto probe_error;
 		}
-		usb_fill_bulk_urb (port->write_urb, dev,
-				   usb_sndbulkpipe (dev,
-						    endpoint->bEndpointAddress),
-				   port->bulk_out_buffer, buffer_size, 
-				   serial->type->write_bulk_callback,
-				   port);
+		usb_fill_bulk_urb(port->write_urb, dev,
+				usb_sndbulkpipe(dev,
+					endpoint->bEndpointAddress),
+				port->bulk_out_buffer, buffer_size,
+				serial->type->write_bulk_callback, port);
 	}
 
 	if (serial->type->read_int_callback) {
@@ -858,73 +880,82 @@
 			port = serial->port[i];
 			port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
 			if (!port->interrupt_in_urb) {
-				dev_err(&interface->dev, "No free urbs available\n");
+				dev_err(&interface->dev,
+						"No free urbs available\n");
 				goto probe_error;
 			}
 			buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
-			port->interrupt_in_endpointAddress = endpoint->bEndpointAddress;
-			port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
+			port->interrupt_in_endpointAddress =
+						endpoint->bEndpointAddress;
+			port->interrupt_in_buffer = kmalloc(buffer_size,
+								GFP_KERNEL);
 			if (!port->interrupt_in_buffer) {
-				dev_err(&interface->dev, "Couldn't allocate interrupt_in_buffer\n");
+				dev_err(&interface->dev,
+				    "Couldn't allocate interrupt_in_buffer\n");
 				goto probe_error;
 			}
-			usb_fill_int_urb (port->interrupt_in_urb, dev, 
-					  usb_rcvintpipe (dev,
-							  endpoint->bEndpointAddress),
-					  port->interrupt_in_buffer, buffer_size, 
-					  serial->type->read_int_callback, port, 
-					  endpoint->bInterval);
+			usb_fill_int_urb(port->interrupt_in_urb, dev,
+				usb_rcvintpipe(dev,
+						endpoint->bEndpointAddress),
+				port->interrupt_in_buffer, buffer_size,
+				serial->type->read_int_callback, port,
+				endpoint->bInterval);
 		}
 	} else if (num_interrupt_in) {
 		dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
 	}
-	
+
 	if (serial->type->write_int_callback) {
 		for (i = 0; i < num_interrupt_out; ++i) {
 			endpoint = interrupt_out_endpoint[i];
 			port = serial->port[i];
 			port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
 			if (!port->interrupt_out_urb) {
-				dev_err(&interface->dev, "No free urbs available\n");
+				dev_err(&interface->dev,
+						"No free urbs available\n");
 				goto probe_error;
 			}
 			buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
 			port->interrupt_out_size = buffer_size;
-			port->interrupt_out_endpointAddress = endpoint->bEndpointAddress;
-			port->interrupt_out_buffer = kmalloc (buffer_size, GFP_KERNEL);
+			port->interrupt_out_endpointAddress =
+						endpoint->bEndpointAddress;
+			port->interrupt_out_buffer = kmalloc(buffer_size,
+								GFP_KERNEL);
 			if (!port->interrupt_out_buffer) {
-				dev_err(&interface->dev, "Couldn't allocate interrupt_out_buffer\n");
+				dev_err(&interface->dev,
+				  "Couldn't allocate interrupt_out_buffer\n");
 				goto probe_error;
 			}
-			usb_fill_int_urb (port->interrupt_out_urb, dev,
-					  usb_sndintpipe (dev,
-							  endpoint->bEndpointAddress),
-					  port->interrupt_out_buffer, buffer_size,
-					  serial->type->write_int_callback, port,
-					  endpoint->bInterval);
+			usb_fill_int_urb(port->interrupt_out_urb, dev,
+				usb_sndintpipe(dev,
+						  endpoint->bEndpointAddress),
+				port->interrupt_out_buffer, buffer_size,
+				serial->type->write_int_callback, port,
+				endpoint->bInterval);
 		}
 	} else if (num_interrupt_out) {
 		dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined");
 	}
-	
+
 	/* if this device type has an attach function, call it */
 	if (type->attach) {
 		if (!try_module_get(type->driver.owner)) {
-			dev_err(&interface->dev, "module get failed, exiting\n");
+			dev_err(&interface->dev,
+					"module get failed, exiting\n");
 			goto probe_error;
 		}
-		retval = type->attach (serial);
+		retval = type->attach(serial);
 		module_put(type->driver.owner);
 		if (retval < 0)
 			goto probe_error;
 		if (retval > 0) {
-			/* quietly accept this device, but don't bind to a serial port
-			 * as it's about to disappear */
+			/* quietly accept this device, but don't bind to a
+			   serial port as it's about to disappear */
 			goto exit;
 		}
 	}
 
-	if (get_free_serial (serial, num_ports, &minor) == NULL) {
+	if (get_free_serial(serial, num_ports, &minor) == NULL) {
 		dev_err(&interface->dev, "No more free serial devices\n");
 		goto probe_error;
 	}
@@ -938,19 +969,19 @@
 		port->dev.bus = &usb_serial_bus_type;
 		port->dev.release = &port_release;
 
-		snprintf (&port->dev.bus_id[0], sizeof(port->dev.bus_id), "ttyUSB%d", port->number);
-		dbg ("%s - registering %s", __func__, port->dev.bus_id);
+		dev_set_name(&port->dev, "ttyUSB%d", port->number);
+		dbg ("%s - registering %s", __func__, dev_name(&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);
+	usb_serial_console_init(debug, minor);
 
 exit:
 	/* success */
-	usb_set_intfdata (interface, serial);
+	usb_set_intfdata(interface, serial);
 	return 0;
 
 probe_error:
@@ -986,29 +1017,30 @@
 	/* free up any memory that we allocated */
 	for (i = 0; i < serial->num_port_pointers; ++i)
 		kfree(serial->port[i]);
-	kfree (serial);
+	kfree(serial);
 	return -EIO;
 }
+EXPORT_SYMBOL_GPL(usb_serial_probe);
 
 void usb_serial_disconnect(struct usb_interface *interface)
 {
 	int i;
-	struct usb_serial *serial = usb_get_intfdata (interface);
+	struct usb_serial *serial = usb_get_intfdata(interface);
 	struct device *dev = &interface->dev;
 	struct usb_serial_port *port;
 
 	usb_serial_console_disconnect(serial);
-	dbg ("%s", __func__);
+	dbg("%s", __func__);
 
 	mutex_lock(&serial->disc_mutex);
-	usb_set_intfdata (interface, NULL);
+	usb_set_intfdata(interface, NULL);
 	/* must set a flag, to signal subdrivers */
 	serial->disconnected = 1;
 	for (i = 0; i < serial->num_ports; ++i) {
 		port = serial->port[i];
 		if (port) {
-			if (port->tty)
-				tty_hangup(port->tty);
+			if (port->port.tty)
+				tty_hangup(port->port.tty);
 			kill_traffic(port);
 		}
 	}
@@ -1018,6 +1050,7 @@
 	usb_serial_put(serial);
 	dev_info(dev, "device disconnected\n");
 }
+EXPORT_SYMBOL_GPL(usb_serial_disconnect);
 
 int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
 {
@@ -1076,9 +1109,8 @@
 		return -ENOMEM;
 
 	/* Initialize our global data */
-	for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
+	for (i = 0; i < SERIAL_TTY_MINORS; ++i)
 		serial_table[i] = NULL;
-	}
 
 	result = bus_register(&usb_serial_bus_type);
 	if (result) {
@@ -1093,9 +1125,11 @@
 	usb_serial_tty_driver->minor_start = 0;
 	usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
 	usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
-	usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+	usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW |
+						TTY_DRIVER_DYNAMIC_DEV;
 	usb_serial_tty_driver->init_termios = tty_std_termios;
-	usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
+							| HUPCL | CLOCAL;
 	usb_serial_tty_driver->init_termios.c_ispeed = 9600;
 	usb_serial_tty_driver->init_termios.c_ospeed = 9600;
 	tty_set_operations(usb_serial_tty_driver, &serial_ops);
@@ -1133,7 +1167,7 @@
 	bus_unregister(&usb_serial_bus_type);
 
 exit_bus:
-	err ("%s - returning with error %d", __func__, result);
+	err("%s - returning with error %d", __func__, result);
 	put_tty_driver(usb_serial_tty_driver);
 	return result;
 }
@@ -1160,7 +1194,7 @@
 		if (!type->function) {					\
 			type->function = usb_serial_generic_##function;	\
 			dbg("Had to override the " #function		\
-				 " usb serial operation with the generic one.");\
+				" usb serial operation with the generic one.");\
 			}						\
 	} while (0)
 
@@ -1177,8 +1211,9 @@
 	set_to_generic_if_null(device, resume);
 }
 
-int usb_serial_register(struct usb_serial_driver *driver) /* must be called with BKL held */
+int usb_serial_register(struct usb_serial_driver *driver)
 {
+	/* must be called with BKL held */
 	int retval;
 
 	fixup_generic(driver);
@@ -1191,37 +1226,30 @@
 
 	retval = usb_serial_bus_register(driver);
 	if (retval) {
-		err("problem %d when registering driver %s", retval, driver->description);
+		err("problem %d when registering driver %s",
+						retval, driver->description);
 		list_del(&driver->driver_list);
-	}
-	else
-		info("USB Serial support registered for %s", driver->description);
+	} else
+		info("USB Serial support registered for %s",
+						driver->description);
 
 	return retval;
 }
+EXPORT_SYMBOL_GPL(usb_serial_register);
 
 
-void usb_serial_deregister(struct usb_serial_driver *device) /* must be called with BKL held */
+void usb_serial_deregister(struct usb_serial_driver *device)
 {
+	/* must be called with BKL held */
 	info("USB Serial deregistering driver %s", device->description);
 	list_del(&device->driver_list);
 	usb_serial_bus_deregister(device);
 }
-
-
-
-/* If the usb-serial core is built into the core, the usb-serial drivers
-   need these symbols to load properly as modules. */
-EXPORT_SYMBOL_GPL(usb_serial_register);
 EXPORT_SYMBOL_GPL(usb_serial_deregister);
-EXPORT_SYMBOL_GPL(usb_serial_probe);
-EXPORT_SYMBOL_GPL(usb_serial_disconnect);
-EXPORT_SYMBOL_GPL(usb_serial_port_softint);
-
 
 /* Module information */
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c
index f9fc926..fc5d995 100644
--- a/drivers/usb/serial/usb_debug.c
+++ b/drivers/usb/serial/usb_debug.c
@@ -15,6 +15,8 @@
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
+#define USB_DEBUG_MAX_PACKET_SIZE	8
+
 static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(0x0525, 0x127a) },
 	{ },
@@ -29,6 +31,13 @@
 	.no_dynamic_id = 	1,
 };
 
+int usb_debug_open(struct tty_struct *tty, struct usb_serial_port *port,
+							struct file *filp)
+{
+	port->bulk_out_size = USB_DEBUG_MAX_PACKET_SIZE;
+	return usb_serial_generic_open(tty, port, filp);
+}
+
 static struct usb_serial_driver debug_device = {
 	.driver = {
 		.owner =	THIS_MODULE,
@@ -36,6 +45,7 @@
 	},
 	.id_table =		id_table,
 	.num_ports =		1,
+	.open =			usb_debug_open,
 };
 
 static int __init debug_init(void)
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 5fc2012..cf8924f 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -9,7 +9,8 @@
  *	modify it under the terms of the GNU General Public License version
  *	2 as published by the Free Software Foundation.
  *
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
  *
  */
 
@@ -23,7 +24,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 #include "visor.h"
@@ -35,25 +36,29 @@
 #define DRIVER_DESC "USB HandSpring Visor / Palm OS driver"
 
 /* function prototypes for a handspring visor */
-static int  visor_open		(struct usb_serial_port *port, struct file *filp);
-static void visor_close		(struct usb_serial_port *port, struct file *filp);
-static int  visor_write		(struct usb_serial_port *port, const unsigned char *buf, int count);
-static int  visor_write_room		(struct usb_serial_port *port);
-static int  visor_chars_in_buffer	(struct usb_serial_port *port);
-static void visor_throttle	(struct usb_serial_port *port);
-static void visor_unthrottle	(struct usb_serial_port *port);
-static int  visor_probe		(struct usb_serial *serial, const struct usb_device_id *id);
+static int  visor_open(struct tty_struct *tty, struct usb_serial_port *port,
+					struct file *filp);
+static void visor_close(struct tty_struct *tty, struct usb_serial_port *port,
+					struct file *filp);
+static int  visor_write(struct tty_struct *tty, struct usb_serial_port *port,
+					const unsigned char *buf, int count);
+static int  visor_write_room(struct tty_struct *tty);
+static void visor_throttle(struct tty_struct *tty);
+static void visor_unthrottle(struct tty_struct *tty);
+static int  visor_probe(struct usb_serial *serial,
+					const struct usb_device_id *id);
 static int  visor_calc_num_ports(struct usb_serial *serial);
-static void visor_shutdown	(struct usb_serial *serial);
-static int  visor_ioctl		(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void visor_write_bulk_callback	(struct urb *urb);
-static void visor_read_bulk_callback	(struct urb *urb);
-static void visor_read_int_callback	(struct urb *urb);
-static int  clie_3_5_startup	(struct usb_serial *serial);
-static int  treo_attach		(struct usb_serial *serial);
-static int clie_5_attach (struct usb_serial *serial);
-static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_id *id);
-static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_id *id);
+static void visor_shutdown(struct usb_serial *serial);
+static void visor_write_bulk_callback(struct urb *urb);
+static void visor_read_bulk_callback(struct urb *urb);
+static void visor_read_int_callback(struct urb *urb);
+static int  clie_3_5_startup(struct usb_serial *serial);
+static int  treo_attach(struct usb_serial *serial);
+static int clie_5_attach(struct usb_serial *serial);
+static int palm_os_3_probe(struct usb_serial *serial,
+					const struct usb_device_id *id);
+static int palm_os_4_probe(struct usb_serial *serial,
+					const struct usb_device_id *id);
 
 /* Parameters that may be passed into the module. */
 static int debug;
@@ -105,13 +110,13 @@
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
 	{ USB_DEVICE(ACER_VENDOR_ID, ACER_S10_ID),
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
-	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID), 
+	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID),
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
-	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID), 
+	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID),
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
 	{ USB_DEVICE(TAPWAVE_VENDOR_ID, TAPWAVE_ZODIAC_ID),
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
-	{ USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID), 
+	{ USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID),
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
 	{ USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID),
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
@@ -170,7 +175,7 @@
 	{ }					/* Terminating entry */
 };
 
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
 
 static struct usb_driver visor_driver = {
 	.name =		"visor",
@@ -180,7 +185,8 @@
 	.no_dynamic_id = 	1,
 };
 
-/* All of the device info needed for the Handspring Visor, and Palm 4.0 devices */
+/* All of the device info needed for the Handspring Visor,
+   and Palm 4.0 devices */
 static struct usb_serial_driver handspring_device = {
 	.driver = {
 		.owner =	THIS_MODULE,
@@ -198,10 +204,8 @@
 	.probe =		visor_probe,
 	.calc_num_ports =	visor_calc_num_ports,
 	.shutdown =		visor_shutdown,
-	.ioctl =		visor_ioctl,
 	.write =		visor_write,
 	.write_room =		visor_write_room,
-	.chars_in_buffer =	visor_chars_in_buffer,
 	.write_bulk_callback =	visor_write_bulk_callback,
 	.read_bulk_callback =	visor_read_bulk_callback,
 	.read_int_callback =	visor_read_int_callback,
@@ -225,10 +229,8 @@
 	.probe =		visor_probe,
 	.calc_num_ports =	visor_calc_num_ports,
 	.shutdown =		visor_shutdown,
-	.ioctl =		visor_ioctl,
 	.write =		visor_write,
 	.write_room =		visor_write_room,
-	.chars_in_buffer =	visor_chars_in_buffer,
 	.write_bulk_callback =	visor_write_bulk_callback,
 	.read_bulk_callback =	visor_read_bulk_callback,
 	.read_int_callback =	visor_read_int_callback,
@@ -249,10 +251,8 @@
 	.throttle =		visor_throttle,
 	.unthrottle =		visor_unthrottle,
 	.attach =		clie_3_5_startup,
-	.ioctl =		visor_ioctl,
 	.write =		visor_write,
 	.write_room =		visor_write_room,
-	.chars_in_buffer =	visor_chars_in_buffer,
 	.write_bulk_callback =	visor_write_bulk_callback,
 	.read_bulk_callback =	visor_read_bulk_callback,
 };
@@ -274,7 +274,8 @@
 /******************************************************************************
  * Handspring Visor specific driver functions
  ******************************************************************************/
-static int visor_open (struct usb_serial_port *port, struct file *filp)
+static int visor_open(struct tty_struct *tty, struct usb_serial_port *port,
+							struct file *filp)
 {
 	struct usb_serial *serial = port->serial;
 	struct visor_private *priv = usb_get_serial_port_data(port);
@@ -300,42 +301,45 @@
 	 * 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;
+	if (tty)
+		tty->low_latency = 1;
 
 	/* Start reading from the device */
-	usb_fill_bulk_urb (port->read_urb, serial->dev,
-			   usb_rcvbulkpipe (serial->dev, 
+	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,
 			   visor_read_bulk_callback, port);
 	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 	if (result) {
-		dev_err(&port->dev, "%s - failed submitting read urb, error %d\n",
-			__func__, result);
+		dev_err(&port->dev,
+			"%s - failed submitting read urb, error %d\n",
+							__func__, result);
 		goto exit;
 	}
-	
+
 	if (port->interrupt_in_urb) {
 		dbg("%s - adding interrupt input for treo", __func__);
 		result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
 		if (result)
-			dev_err(&port->dev, "%s - failed submitting interrupt urb, error %d\n",
-				__func__, result);
+			dev_err(&port->dev,
+			    "%s - failed submitting interrupt urb, error %d\n",
+							__func__, result);
 	}
-exit:	
+exit:
 	return result;
 }
 
 
-static void visor_close (struct usb_serial_port *port, struct file * filp)
+static void visor_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct visor_private *priv = usb_get_serial_port_data(port);
 	unsigned char *transfer_buffer;
 
 	dbg("%s - port %d", __func__, port->number);
-			 
+
 	/* shutdown our urbs */
 	usb_kill_urb(port->read_urb);
 	usb_kill_urb(port->interrupt_in_urb);
@@ -343,14 +347,14 @@
 	mutex_lock(&port->serial->disc_mutex);
 	if (!port->serial->disconnected) {
 		/* Try to send shutdown message, unless the device is gone */
-		transfer_buffer =  kmalloc (0x12, GFP_KERNEL);
+		transfer_buffer =  kmalloc(0x12, GFP_KERNEL);
 		if (transfer_buffer) {
-			usb_control_msg (port->serial->dev,
+			usb_control_msg(port->serial->dev,
 					 usb_rcvctrlpipe(port->serial->dev, 0),
 					 VISOR_CLOSE_NOTIFICATION, 0xc2,
 					 0x0000, 0x0000,
 					 transfer_buffer, 0x12, 300);
-			kfree (transfer_buffer);
+			kfree(transfer_buffer);
 		}
 	}
 	mutex_unlock(&port->serial->disc_mutex);
@@ -361,7 +365,8 @@
 }
 
 
-static int visor_write (struct usb_serial_port *port, const unsigned char *buf, int count)
+static int visor_write(struct tty_struct *tty, struct usb_serial_port *port,
+					const unsigned char *buf, int count)
 {
 	struct visor_private *priv = usb_get_serial_port_data(port);
 	struct usb_serial *serial = port->serial;
@@ -381,7 +386,7 @@
 	priv->outstanding_urbs++;
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	buffer = kmalloc (count, GFP_ATOMIC);
+	buffer = kmalloc(count, GFP_ATOMIC);
 	if (!buffer) {
 		dev_err(&port->dev, "out of memory\n");
 		count = -ENOMEM;
@@ -395,21 +400,22 @@
 		goto error_no_urb;
 	}
 
-	memcpy (buffer, buf, count);
+	memcpy(buffer, buf, count);
 
 	usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
 
-	usb_fill_bulk_urb (urb, serial->dev,
-			   usb_sndbulkpipe (serial->dev,
+	usb_fill_bulk_urb(urb, serial->dev,
+			   usb_sndbulkpipe(serial->dev,
 					    port->bulk_out_endpointAddress),
-			   buffer, count, 
+			   buffer, count,
 			   visor_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",
-			__func__, status);
+		dev_err(&port->dev,
+		   "%s - usb_submit_urb(write bulk) failed with status = %d\n",
+							__func__, status);
 		count = status;
 		goto error;
 	} else {
@@ -435,8 +441,9 @@
 }
 
 
-static int visor_write_room (struct usb_serial_port *port)
+static int visor_write_room(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct visor_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 
@@ -460,23 +467,7 @@
 }
 
 
-static int visor_chars_in_buffer (struct usb_serial_port *port)
-{
-	dbg("%s - port %d", __func__, port->number);
-
-	/* 
-	 * We can't really account for how much data we
-	 * have sent out, but hasn't made it through to the
-	 * device, so just tell the tty layer that everything
-	 * is flushed.
-	 *
-	 * FIXME: Should walk outstanding_urbs
-	 */
-	return 0;
-}
-
-
-static void visor_write_bulk_callback (struct urb *urb)
+static void visor_write_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 	struct visor_private *priv = usb_get_serial_port_data(port);
@@ -484,7 +475,7 @@
 	unsigned long flags;
 
 	/* free up the transfer buffer, as usb_free_urb() does not do this */
-	kfree (urb->transfer_buffer);
+	kfree(urb->transfer_buffer);
 
 	dbg("%s - port %d", __func__, port->number);
 
@@ -500,7 +491,7 @@
 }
 
 
-static void visor_read_bulk_callback (struct urb *urb)
+static void visor_read_bulk_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 	struct visor_private *priv = usb_get_serial_port_data(port);
@@ -518,11 +509,13 @@
 		return;
 	}
 
-	usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+	usb_serial_debug_data(debug, &port->dev, __func__,
+						urb->actual_length, data);
 
-	tty = port->tty;
+	tty = port->port.tty;
 	if (tty && urb->actual_length) {
-		available_room = tty_buffer_request_room(tty, urb->actual_length);
+		available_room = tty_buffer_request_room(tty,
+							urb->actual_length);
 		if (available_room) {
 			tty_insert_flip_string(tty, data, available_room);
 			tty_flip_buffer_push(tty);
@@ -536,22 +529,23 @@
 
 	/* Continue trying to always read if we should */
 	if (!priv->throttled) {
-		usb_fill_bulk_urb (port->read_urb, port->serial->dev,
+		usb_fill_bulk_urb(port->read_urb, port->serial->dev,
 				   usb_rcvbulkpipe(port->serial->dev,
-						   port->bulk_in_endpointAddress),
+					   port->bulk_in_endpointAddress),
 				   port->read_urb->transfer_buffer,
 				   port->read_urb->transfer_buffer_length,
 				   visor_read_bulk_callback, port);
 		result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 		if (result)
-			dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result);
-	} else {
+			dev_err(&port->dev,
+			    "%s - failed resubmitting read urb, error %d\n",
+							__func__, result);
+	} else
 		priv->actually_throttled = 1;
-	}
 	spin_unlock(&priv->lock);
 }
 
-static void visor_read_int_callback (struct urb *urb)
+static void visor_read_int_callback(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
 	int status = urb->status;
@@ -585,14 +579,16 @@
 			      urb->actual_length, urb->transfer_buffer);
 
 exit:
-	result = usb_submit_urb (urb, GFP_ATOMIC);
+	result = usb_submit_urb(urb, GFP_ATOMIC);
 	if (result)
-		dev_err(&urb->dev->dev, "%s - Error %d submitting interrupt urb\n",
-			__func__, result);
+		dev_err(&urb->dev->dev,
+				"%s - Error %d submitting interrupt urb\n",
+							__func__, result);
 }
 
-static void visor_throttle (struct usb_serial_port *port)
+static void visor_throttle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct visor_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 
@@ -603,8 +599,9 @@
 }
 
 
-static void visor_unthrottle (struct usb_serial_port *port)
+static void visor_unthrottle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct visor_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
 	int result;
@@ -618,10 +615,13 @@
 	port->read_urb->dev = port->serial->dev;
 	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
 	if (result)
-		dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result);
+		dev_err(&port->dev,
+			"%s - failed submitting read urb, error %d\n",
+							__func__, result);
 }
 
-static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_id *id)
+static int palm_os_3_probe(struct usb_serial *serial,
+						const struct usb_device_id *id)
 {
 	struct device *dev = &serial->dev->dev;
 	struct visor_connection_info *connection_info;
@@ -633,7 +633,7 @@
 
 	dbg("%s", __func__);
 
-	transfer_buffer = kmalloc (sizeof (*connection_info), GFP_KERNEL);
+	transfer_buffer = kmalloc(sizeof(*connection_info), GFP_KERNEL);
 	if (!transfer_buffer) {
 		dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __func__,
 			sizeof(*connection_info));
@@ -641,7 +641,7 @@
 	}
 
 	/* send a get connection info request */
-	retval = usb_control_msg (serial->dev,
+	retval = usb_control_msg(serial->dev,
 				  usb_rcvctrlpipe(serial->dev, 0),
 				  VISOR_GET_CONNECTION_INFORMATION,
 				  0xc2, 0x0000, 0x0000, transfer_buffer,
@@ -653,29 +653,31 @@
 	}
 
 	if (retval == sizeof(*connection_info)) {
-	        connection_info = (struct visor_connection_info *)transfer_buffer;
+			connection_info = (struct visor_connection_info *)
+							transfer_buffer;
 
 		num_ports = le16_to_cpu(connection_info->num_ports);
 		for (i = 0; i < num_ports; ++i) {
-			switch (connection_info->connections[i].port_function_id) {
-				case VISOR_FUNCTION_GENERIC:
-					string = "Generic";
-					break;
-				case VISOR_FUNCTION_DEBUGGER:
-					string = "Debugger";
-					break;
-				case VISOR_FUNCTION_HOTSYNC:
-					string = "HotSync";
-					break;
-				case VISOR_FUNCTION_CONSOLE:
-					string = "Console";
-					break;
-				case VISOR_FUNCTION_REMOTE_FILE_SYS:
-					string = "Remote File System";
-					break;
-				default:
-					string = "unknown";
-					break;
+			switch (
+			   connection_info->connections[i].port_function_id) {
+			case VISOR_FUNCTION_GENERIC:
+				string = "Generic";
+				break;
+			case VISOR_FUNCTION_DEBUGGER:
+				string = "Debugger";
+				break;
+			case VISOR_FUNCTION_HOTSYNC:
+				string = "HotSync";
+				break;
+			case VISOR_FUNCTION_CONSOLE:
+				string = "Console";
+				break;
+			case VISOR_FUNCTION_REMOTE_FILE_SYS:
+				string = "Remote File System";
+				break;
+			default:
+				string = "unknown";
+				break;
 			}
 			dev_info(dev, "%s: port %d, is for %s use\n",
 				serial->type->description,
@@ -686,11 +688,11 @@
 	* Handle devices that report invalid stuff here.
 	*/
 	if (num_ports == 0 || num_ports > 2) {
-		dev_warn (dev, "%s: No valid connect info available\n",
+		dev_warn(dev, "%s: No valid connect info available\n",
 			serial->type->description);
 		num_ports = 2;
 	}
-  
+
 	dev_info(dev, "%s: Number of ports: %d\n", serial->type->description,
 		num_ports);
 
@@ -700,8 +702,9 @@
 	 */
 	usb_set_serial_data(serial, (void *)(long)num_ports);
 
-	/* ask for the number of bytes available, but ignore the response as it is broken */
-	retval = usb_control_msg (serial->dev,
+	/* ask for the number of bytes available, but ignore the
+	   response as it is broken */
+	retval = usb_control_msg(serial->dev,
 				  usb_rcvctrlpipe(serial->dev, 0),
 				  VISOR_REQUEST_BYTES_AVAILABLE,
 				  0xc2, 0x0000, 0x0005, transfer_buffer,
@@ -712,12 +715,13 @@
 	retval = 0;
 
 exit:
-	kfree (transfer_buffer);
+	kfree(transfer_buffer);
 
 	return retval;
 }
 
-static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_id *id)
+static int palm_os_4_probe(struct usb_serial *serial,
+						const struct usb_device_id *id)
 {
 	struct device *dev = &serial->dev->dev;
 	struct palm_ext_connection_info *connection_info;
@@ -726,18 +730,18 @@
 
 	dbg("%s", __func__);
 
-	transfer_buffer =  kmalloc (sizeof (*connection_info), GFP_KERNEL);
+	transfer_buffer =  kmalloc(sizeof(*connection_info), GFP_KERNEL);
 	if (!transfer_buffer) {
 		dev_err(dev, "%s - kmalloc(%Zd) failed.\n", __func__,
 			sizeof(*connection_info));
 		return -ENOMEM;
 	}
 
-	retval = usb_control_msg (serial->dev,
-				  usb_rcvctrlpipe(serial->dev, 0), 
+	retval = usb_control_msg(serial->dev,
+				  usb_rcvctrlpipe(serial->dev, 0),
 				  PALM_GET_EXT_CONNECTION_INFORMATION,
 				  0xc2, 0x0000, 0x0000, transfer_buffer,
-				  sizeof (*connection_info), 300);
+				  sizeof(*connection_info), 300);
 	if (retval < 0)
 		dev_err(dev, "%s - error %d getting connection info\n",
 			__func__, retval);
@@ -745,15 +749,17 @@
 		usb_serial_debug_data(debug, &serial->dev->dev, __func__,
 				      retval, transfer_buffer);
 
-	kfree (transfer_buffer);
+	kfree(transfer_buffer);
 	return 0;
 }
 
 
-static int visor_probe (struct usb_serial *serial, const struct usb_device_id *id)
+static int visor_probe(struct usb_serial *serial,
+					const struct usb_device_id *id)
 {
 	int retval = 0;
-	int (*startup) (struct usb_serial *serial, const struct usb_device_id *id);
+	int (*startup)(struct usb_serial *serial,
+					const struct usb_device_id *id);
 
 	dbg("%s", __func__);
 
@@ -771,7 +777,7 @@
 	return retval;
 }
 
-static int visor_calc_num_ports (struct usb_serial *serial)
+static int visor_calc_num_ports(struct usb_serial *serial)
 {
 	int num_ports = (int)(long)(usb_get_serial_data(serial));
 
@@ -788,7 +794,7 @@
 	int i;
 
 	for (i = 0; i < serial->num_ports; ++i) {
-		priv = kzalloc (sizeof(*priv), GFP_KERNEL);
+		priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 		if (!priv) {
 			while (i-- != 0) {
 				priv = usb_get_serial_port_data(ports[i]);
@@ -803,7 +809,7 @@
 	return 0;
 }
 
-static int clie_3_5_startup (struct usb_serial *serial)
+static int clie_3_5_startup(struct usb_serial *serial)
 {
 	struct device *dev = &serial->dev->dev;
 	int result;
@@ -816,62 +822,72 @@
 	 */
 
 	/* get the config number */
-	result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
 				  USB_REQ_GET_CONFIGURATION, USB_DIR_IN,
 				  0, 0, &data, 1, 3000);
 	if (result < 0) {
-		dev_err(dev, "%s: get config number failed: %d\n", __func__, result);
+		dev_err(dev, "%s: get config number failed: %d\n",
+							__func__, result);
 		return result;
 	}
 	if (result != 1) {
-		dev_err(dev, "%s: get config number bad return length: %d\n", __func__, result);
+		dev_err(dev, "%s: get config number bad return length: %d\n",
+							__func__, result);
 		return -EIO;
 	}
 
 	/* get the interface number */
-	result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0),
-				  USB_REQ_GET_INTERFACE, 
+	result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+				  USB_REQ_GET_INTERFACE,
 				  USB_DIR_IN | USB_RECIP_INTERFACE,
 				  0, 0, &data, 1, 3000);
 	if (result < 0) {
-		dev_err(dev, "%s: get interface number failed: %d\n", __func__, result);
+		dev_err(dev, "%s: get interface number failed: %d\n",
+							__func__, result);
 		return result;
 	}
 	if (result != 1) {
-		dev_err(dev, "%s: get interface number bad return length: %d\n", __func__, result);
+		dev_err(dev,
+			"%s: get interface number bad return length: %d\n",
+							__func__, result);
 		return -EIO;
 	}
 
 	return generic_startup(serial);
 }
- 
-static int treo_attach (struct usb_serial *serial)
+
+static int treo_attach(struct usb_serial *serial)
 {
 	struct usb_serial_port *swap_port;
 
 	/* Only do this endpoint hack for the Handspring devices with
 	 * interrupt in endpoints, which for now are the Treo devices. */
-	if (!((le16_to_cpu(serial->dev->descriptor.idVendor) == HANDSPRING_VENDOR_ID) ||
-	      (le16_to_cpu(serial->dev->descriptor.idVendor) == KYOCERA_VENDOR_ID)) ||
-	    (serial->num_interrupt_in == 0))
+	if (!((le16_to_cpu(serial->dev->descriptor.idVendor)
+						== HANDSPRING_VENDOR_ID) ||
+		(le16_to_cpu(serial->dev->descriptor.idVendor)
+						== KYOCERA_VENDOR_ID)) ||
+		(serial->num_interrupt_in == 0))
 		goto generic_startup;
 
 	dbg("%s", __func__);
 
 	/*
-	* It appears that Treos and Kyoceras want to use the 
-	* 1st bulk in endpoint to communicate with the 2nd bulk out endpoint, 
-	* so let's swap the 1st and 2nd bulk in and interrupt endpoints.  
-	* Note that swapping the bulk out endpoints would break lots of 
+	* It appears that Treos and Kyoceras want to use the
+	* 1st bulk in endpoint to communicate with the 2nd bulk out endpoint,
+	* so let's swap the 1st and 2nd bulk in and interrupt endpoints.
+	* Note that swapping the bulk out endpoints would break lots of
 	* apps that want to communicate on the second port.
 	*/
 #define COPY_PORT(dest, src)						\
-	dest->read_urb = src->read_urb;					\
-	dest->bulk_in_endpointAddress = src->bulk_in_endpointAddress;	\
-	dest->bulk_in_buffer = src->bulk_in_buffer;			\
-	dest->interrupt_in_urb = src->interrupt_in_urb;			\
-	dest->interrupt_in_endpointAddress = src->interrupt_in_endpointAddress;	\
-	dest->interrupt_in_buffer = src->interrupt_in_buffer;
+	do { \
+		dest->read_urb = src->read_urb;				\
+		dest->bulk_in_endpointAddress = src->bulk_in_endpointAddress;\
+		dest->bulk_in_buffer = src->bulk_in_buffer;		\
+		dest->interrupt_in_urb = src->interrupt_in_urb;		\
+		dest->interrupt_in_endpointAddress = \
+					src->interrupt_in_endpointAddress;\
+		dest->interrupt_in_buffer = src->interrupt_in_buffer;	\
+	} while (0);
 
 	swap_port = kmalloc(sizeof(*swap_port), GFP_KERNEL);
 	if (!swap_port)
@@ -885,28 +901,30 @@
 	return generic_startup(serial);
 }
 
-static int clie_5_attach (struct usb_serial *serial)
+static int clie_5_attach(struct usb_serial *serial)
 {
 	dbg("%s", __func__);
 
-	/* TH55 registers 2 ports. 
-	   Communication in from the UX50/TH55 uses bulk_in_endpointAddress from port 0 
-	   Communication out to the UX50/TH55 uses bulk_out_endpointAddress from port 1 
-	   
+	/* TH55 registers 2 ports.
+	   Communication in from the UX50/TH55 uses bulk_in_endpointAddress
+	   from port 0. Communication out to the UX50/TH55 uses
+	   bulk_out_endpointAddress from port 1
+
 	   Lets do a quick and dirty mapping
 	 */
-	
+
 	/* some sanity check */
 	if (serial->num_ports < 2)
 		return -1;
-		
+
 	/* port 0 now uses the modified endpoint Address */
-	serial->port[0]->bulk_out_endpointAddress = serial->port[1]->bulk_out_endpointAddress;
+	serial->port[0]->bulk_out_endpointAddress =
+				serial->port[1]->bulk_out_endpointAddress;
 
 	return generic_startup(serial);
 }
 
-static void visor_shutdown (struct usb_serial *serial)
+static void visor_shutdown(struct usb_serial *serial)
 {
 	struct visor_private *priv;
 	int i;
@@ -922,37 +940,35 @@
 	}
 }
 
-static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
-{
-	dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
-
-	return -ENOIOCTLCMD;
-}
-
-static int __init visor_init (void)
+static int __init visor_init(void)
 {
 	int i, retval;
 	/* Only if parameters were passed to us */
-	if ((vendor>0) && (product>0)) {
-		struct usb_device_id usb_dev_temp[]=
-			{{USB_DEVICE(vendor, product),
-			.driver_info = (kernel_ulong_t)&palm_os_4_probe }};
+	if (vendor > 0 && product > 0) {
+		struct usb_device_id usb_dev_temp[] = {
+			{
+				USB_DEVICE(vendor, product),
+				.driver_info =
+					(kernel_ulong_t) &palm_os_4_probe
+			}
+		};
 
 		/* Find the last entry in id_table */
-		for (i=0; ; i++) {
-			if (id_table[i].idVendor==0) {
+		for (i = 0;; i++) {
+			if (id_table[i].idVendor == 0) {
 				id_table[i] = usb_dev_temp[0];
 				break;
 			}
 		}
 		/* Find the last entry in id_table_combined */
-		for (i=0; ; i++) {
-			if (id_table_combined[i].idVendor==0) {
+		for (i = 0;; i++) {
+			if (id_table_combined[i].idVendor == 0) {
 				id_table_combined[i] = usb_dev_temp[0];
 				break;
 			}
 		}
-		info("Untested USB device specified at time of module insertion");
+		info(
+		  "Untested USB device specified at time of module insertion");
 		info("Warning: This is not guaranteed to work");
 		info("Using a newer kernel is preferred to this method");
 		info("Adding Palm OS protocol 4.x support for unknown device: 0x%x/0x%x",
@@ -968,7 +984,7 @@
 	if (retval)
 		goto failed_clie_5_register;
 	retval = usb_register(&visor_driver);
-	if (retval) 
+	if (retval)
 		goto failed_usb_register;
 	info(DRIVER_DESC);
 
@@ -986,18 +1002,18 @@
 
 static void __exit visor_exit (void)
 {
-	usb_deregister (&visor_driver);
-	usb_serial_deregister (&handspring_device);
-	usb_serial_deregister (&clie_3_5_device);
-	usb_serial_deregister (&clie_5_device);
+	usb_deregister(&visor_driver);
+	usb_serial_deregister(&handspring_device);
+	usb_serial_deregister(&clie_3_5_device);
+	usb_serial_deregister(&clie_5_device);
 }
 
 
 module_init(visor_init);
 module_exit(visor_exit);
 
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 665aa77..3a9d143 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -12,29 +12,31 @@
  *	the Free Software Foundation; either version 2 of the License, or
  *	(at your option) any later version.
  *
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
  *
  * (10/09/2002) Stuart MacDonald (stuartm@connecttech.com)
  *	Upgrade to full working driver
  *
  * (05/30/2001) gkh
- *	switched from using spinlock to a semaphore, which fixes lots of problems.
+ *	switched from using spinlock to a semaphore, which fixes lots of
+ *	problems.
  *
  * (04/08/2001) gb
  *	Identify version on module load.
- * 
+ *
  * 2001_Mar_19 gkh
- *	Fixed MOD_INC and MOD_DEC logic, the ability to open a port more 
+ *	Fixed MOD_INC and MOD_DEC logic, the ability to open a port more
  *	than once, and the got the proper usb_device_id table entries so
  *	the driver works again.
  *
  * (11/01/2000) Adam J. Richter
  *	usb_device_id table support
- * 
+ *
  * (10/05/2000) gkh
  *	Fixed bug with urb->dev not being set properly, now that the usb
  *	core needs it.
- * 
+ *
  * (10/03/2000) smd
  *	firmware is improved to guard against crap sent to device
  *	firmware now replies CMD_FAILURE on bad things
@@ -52,9 +54,9 @@
  *	Fixed bug with port->minor that was found by Al Borchers
  *
  * (07/04/2000) gkh
- *	Added support for port settings. Baud rate can now be changed. Line signals
- *	are not transferred to and from the tty layer yet, but things seem to be 
- *	working well now.
+ *	Added support for port settings. Baud rate can now be changed. Line
+ *	signals are not transferred to and from the tty layer yet, but things
+ *	seem to be working well now.
  *
  * (05/04/2000) gkh
  *	First cut at open and close commands. Data can flow through the ports at
@@ -62,7 +64,7 @@
  *
  * (03/26/2000) gkh
  *	Split driver up into device specific pieces.
- * 
+ *
  */
 
 #include <linux/kernel.h>
@@ -75,7 +77,7 @@
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/mutex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/termbits.h>
 #include <linux/usb.h>
 #include <linux/serial_reg.h>
@@ -125,7 +127,7 @@
 	{ }						/* Terminating entry */
 };
 
-MODULE_DEVICE_TABLE (usb, id_table_combined);
+MODULE_DEVICE_TABLE(usb, id_table_combined);
 
 static struct usb_driver whiteheat_driver = {
 	.name =		"whiteheat",
@@ -136,26 +138,34 @@
 };
 
 /* function prototypes for the Connect Tech WhiteHEAT prerenumeration device */
-static int  whiteheat_firmware_download	(struct usb_serial *serial, const struct usb_device_id *id);
-static int  whiteheat_firmware_attach	(struct usb_serial *serial);
+static int  whiteheat_firmware_download(struct usb_serial *serial,
+					const struct usb_device_id *id);
+static int  whiteheat_firmware_attach(struct usb_serial *serial);
 
 /* function prototypes for the Connect Tech WhiteHEAT serial converter */
-static int  whiteheat_attach		(struct usb_serial *serial);
-static void whiteheat_shutdown		(struct usb_serial *serial);
-static int  whiteheat_open		(struct usb_serial_port *port, struct file *filp);
-static void whiteheat_close		(struct usb_serial_port *port, struct file *filp);
-static int  whiteheat_write		(struct usb_serial_port *port, const unsigned char *buf, int count);
-static int  whiteheat_write_room	(struct usb_serial_port *port);
-static int  whiteheat_ioctl		(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void whiteheat_set_termios	(struct usb_serial_port *port, struct ktermios * old);
-static int  whiteheat_tiocmget		(struct usb_serial_port *port, struct file *file);
-static int  whiteheat_tiocmset		(struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
-static void whiteheat_break_ctl		(struct usb_serial_port *port, int break_state);
-static int  whiteheat_chars_in_buffer	(struct usb_serial_port *port);
-static void whiteheat_throttle		(struct usb_serial_port *port);
-static void whiteheat_unthrottle	(struct usb_serial_port *port);
-static void whiteheat_read_callback	(struct urb *urb);
-static void whiteheat_write_callback	(struct urb *urb);
+static int  whiteheat_attach(struct usb_serial *serial);
+static void whiteheat_shutdown(struct usb_serial *serial);
+static int  whiteheat_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
+static void whiteheat_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
+static int  whiteheat_write(struct tty_struct *tty,
+			struct usb_serial_port *port,
+			const unsigned char *buf, int count);
+static int  whiteheat_write_room(struct tty_struct *tty);
+static int  whiteheat_ioctl(struct tty_struct *tty, struct file *file,
+			unsigned int cmd, unsigned long arg);
+static void whiteheat_set_termios(struct tty_struct *tty,
+			struct usb_serial_port *port, struct ktermios *old);
+static int  whiteheat_tiocmget(struct tty_struct *tty, struct file *file);
+static int  whiteheat_tiocmset(struct tty_struct *tty, struct file *file,
+			unsigned int set, unsigned int clear);
+static void whiteheat_break_ctl(struct tty_struct *tty, int break_state);
+static int  whiteheat_chars_in_buffer(struct tty_struct *tty);
+static void whiteheat_throttle(struct tty_struct *tty);
+static void whiteheat_unthrottle(struct tty_struct *tty);
+static void whiteheat_read_callback(struct urb *urb);
+static void whiteheat_write_callback(struct urb *urb);
 
 static struct usb_serial_driver whiteheat_fake_device = {
 	.driver = {
@@ -202,7 +212,9 @@
 	struct mutex		mutex;
 	__u8			port_running;
 	__u8			command_finished;
-	wait_queue_head_t	wait_command;	/* for handling sleeping while waiting for a command to finish */
+	wait_queue_head_t	wait_command; /* for handling sleeping whilst
+						 waiting for a command to
+						 finish */
 	__u8			result_buffer[64];
 };
 
@@ -239,14 +251,16 @@
 static void command_port_read_callback(struct urb *urb);
 
 static int start_port_read(struct usb_serial_port *port);
-static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb, struct list_head *head);
+static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb,
+						struct list_head *head);
 static struct list_head *list_first(struct list_head *head);
 static void rx_data_softint(struct work_struct *work);
 
-static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize);
+static int firm_send_command(struct usb_serial_port *port, __u8 command,
+						__u8 *data, __u8 datasize);
 static int firm_open(struct usb_serial_port *port);
 static int firm_close(struct usb_serial_port *port);
-static int firm_setup_port(struct usb_serial_port *port);
+static int firm_setup_port(struct tty_struct *tty);
 static int firm_set_rts(struct usb_serial_port *port, __u8 onoff);
 static int firm_set_dtr(struct usb_serial_port *port, __u8 onoff);
 static int firm_set_break(struct usb_serial_port *port, __u8 onoff);
@@ -278,7 +292,8 @@
  - device renumerated itself and comes up as new device id with all
    firmware download completed.
 */
-static int whiteheat_firmware_download (struct usb_serial *serial, const struct usb_device_id *id)
+static int whiteheat_firmware_download(struct usb_serial *serial,
+					const struct usb_device_id *id)
 {
 	int response, ret = -ENOENT;
 	const struct firmware *loader_fw = NULL, *firmware_fw = NULL;
@@ -313,7 +328,7 @@
 		record = ihex_next_binrec(record);
 	}
 
-	response = ezusb_set_reset (serial, 0);
+	response = ezusb_set_reset(serial, 0);
 
 	record = (const struct ihex_binrec *)firmware_fw->data;
 	while (record && be32_to_cpu(record->addr) < 0x1b40)
@@ -330,8 +345,8 @@
 		}
 		++record;
 	}
-	
-	response = ezusb_set_reset (serial, 1);
+
+	response = ezusb_set_reset(serial, 1);
 
 	record = (const struct ihex_binrec *)firmware_fw->data;
 	while (record && be32_to_cpu(record->addr) < 0x1b40) {
@@ -355,7 +370,7 @@
 }
 
 
-static int whiteheat_firmware_attach (struct usb_serial *serial)
+static int whiteheat_firmware_attach(struct usb_serial *serial)
 {
 	/* We want this device to fail to have a driver assigned to it */
 	return 1;
@@ -365,7 +380,7 @@
 /*****************************************************************************
  * Connect Tech's White Heat serial driver functions
  *****************************************************************************/
-static int whiteheat_attach (struct usb_serial *serial)
+static int whiteheat_attach(struct usb_serial *serial)
 {
 	struct usb_serial_port *command_port;
 	struct whiteheat_command_private *command_info;
@@ -386,43 +401,52 @@
 
 	command_port = serial->port[COMMAND_PORT];
 
-	pipe = usb_sndbulkpipe (serial->dev, command_port->bulk_out_endpointAddress);
+	pipe = usb_sndbulkpipe(serial->dev,
+			command_port->bulk_out_endpointAddress);
 	command = kmalloc(2, GFP_KERNEL);
 	if (!command)
 		goto no_command_buffer;
 	command[0] = WHITEHEAT_GET_HW_INFO;
 	command[1] = 0;
-	
+
 	result = kmalloc(sizeof(*hw_info) + 1, GFP_KERNEL);
 	if (!result)
 		goto no_result_buffer;
 	/*
 	 * When the module is reloaded the firmware is still there and
 	 * the endpoints are still in the usb core unchanged. This is the
-         * unlinking bug in disguise. Same for the call below.
-         */
+	 * unlinking bug in disguise. Same for the call below.
+	 */
 	usb_clear_halt(serial->dev, pipe);
-	ret = usb_bulk_msg (serial->dev, pipe, command, 2, &alen, COMMAND_TIMEOUT_MS);
+	ret = usb_bulk_msg(serial->dev, pipe, command, 2,
+						&alen, COMMAND_TIMEOUT_MS);
 	if (ret) {
-		err("%s: Couldn't send command [%d]", serial->type->description, ret);
+		err("%s: Couldn't send command [%d]",
+				serial->type->description, ret);
 		goto no_firmware;
 	} else if (alen != 2) {
-		err("%s: Send command incomplete [%d]", serial->type->description, alen);
+		err("%s: Send command incomplete [%d]",
+				serial->type->description, alen);
 		goto no_firmware;
 	}
 
-	pipe = usb_rcvbulkpipe (serial->dev, command_port->bulk_in_endpointAddress);
+	pipe = usb_rcvbulkpipe(serial->dev,
+				command_port->bulk_in_endpointAddress);
 	/* See the comment on the usb_clear_halt() above */
 	usb_clear_halt(serial->dev, pipe);
-	ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(*hw_info) + 1, &alen, COMMAND_TIMEOUT_MS);
+	ret = usb_bulk_msg(serial->dev, pipe, result,
+			sizeof(*hw_info) + 1, &alen, COMMAND_TIMEOUT_MS);
 	if (ret) {
-		err("%s: Couldn't get results [%d]", serial->type->description, ret);
+		err("%s: Couldn't get results [%d]",
+				serial->type->description, ret);
 		goto no_firmware;
 	} else if (alen != sizeof(*hw_info) + 1) {
-		err("%s: Get results incomplete [%d]", serial->type->description, alen);
+		err("%s: Get results incomplete [%d]",
+				serial->type->description, alen);
 		goto no_firmware;
 	} else if (result[0] != command[0]) {
-		err("%s: Command failed [%d]", serial->type->description, result[0]);
+		err("%s: Command failed [%d]",
+				serial->type->description, result[0]);
 		goto no_firmware;
 	}
 
@@ -436,7 +460,8 @@
 
 		info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
 		if (info == NULL) {
-			err("%s: Out of memory for port structures\n", serial->type->description);
+			err("%s: Out of memory for port structures\n",
+					serial->type->description);
 			goto no_private;
 		}
 
@@ -506,9 +531,11 @@
 		usb_set_serial_port_data(port, info);
 	}
 
-	command_info = kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL);
+	command_info = kmalloc(sizeof(struct whiteheat_command_private),
+								GFP_KERNEL);
 	if (command_info == NULL) {
-		err("%s: Out of memory for port structures\n", serial->type->description);
+		err("%s: Out of memory for port structures\n",
+					serial->type->description);
 		goto no_command_private;
 	}
 
@@ -525,9 +552,12 @@
 
 no_firmware:
 	/* Firmware likely not running */
-	err("%s: Unable to retrieve firmware version, try replugging\n", serial->type->description);
-	err("%s: If the firmware is not running (status led not blinking)\n", serial->type->description);
-	err("%s: please contact support@connecttech.com\n", serial->type->description);
+	err("%s: Unable to retrieve firmware version, try replugging\n",
+					serial->type->description);
+	err("%s: If the firmware is not running (status led not blinking)\n",
+					serial->type->description);
+	err("%s: please contact support@connecttech.com\n",
+					serial->type->description);
 	kfree(result);
 	return -ENODEV;
 
@@ -570,7 +600,7 @@
 }
 
 
-static void whiteheat_shutdown (struct usb_serial *serial)
+static void whiteheat_shutdown(struct usb_serial *serial)
 {
 	struct usb_serial_port *command_port;
 	struct usb_serial_port *port;
@@ -585,7 +615,7 @@
 
 	/* free up our private data for our command port */
 	command_port = serial->port[COMMAND_PORT];
-	kfree (usb_get_serial_port_data(command_port));
+	kfree(usb_get_serial_port_data(command_port));
 
 	for (i = 0; i < serial->num_ports; i++) {
 		port = serial->port[i];
@@ -612,11 +642,10 @@
 	return;
 }
 
-
-static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
+static int whiteheat_open(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	int		retval = 0;
-	struct ktermios	old_term;
 
 	dbg("%s - port %d", __func__, port->number);
 
@@ -624,7 +653,8 @@
 	if (retval)
 		goto exit;
 
-	port->tty->low_latency = 1;
+	if (tty)
+		tty->low_latency = 1;
 
 	/* send an open port command */
 	retval = firm_open(port);
@@ -640,9 +670,8 @@
 		goto exit;
 	}
 
-	old_term.c_cflag = ~port->tty->termios->c_cflag;
-	old_term.c_iflag = ~port->tty->termios->c_iflag;
-	whiteheat_set_termios(port, &old_term);
+	if (tty)
+		firm_setup_port(tty);
 
 	/* Work around HCD bugs */
 	usb_clear_halt(port->serial->dev, port->read_urb->pipe);
@@ -651,7 +680,8 @@
 	/* Start reading from the device */
 	retval = start_port_read(port);
 	if (retval) {
-		err("%s - failed submitting read urb, error %d", __func__, retval);
+		err("%s - failed submitting read urb, error %d",
+				__func__, retval);
 		firm_close(port);
 		stop_command_port(port->serial);
 		goto exit;
@@ -663,7 +693,8 @@
 }
 
 
-static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
+static void whiteheat_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp)
 {
 	struct whiteheat_private *info = usb_get_serial_port_data(port);
 	struct whiteheat_urb_wrap *wrap;
@@ -681,7 +712,7 @@
 	}
 	mutex_unlock(&port->serial->disc_mutex);
 
-	port->tty->closing = 1;
+	tty->closing = 1;
 
 /*
  * Not currently in use; tty_wait_until_sent() calls
@@ -689,12 +720,12 @@
  * acquisition. This should be fixed at some point. Greg's been
  * notified.
 	if ((filp->f_flags & (O_NDELAY | O_NONBLOCK)) == 0) {
-		tty_wait_until_sent(port->tty, CLOSING_DELAY);
+		tty_wait_until_sent(tty, CLOSING_DELAY);
 	}
 */
 
-	tty_driver_flush_buffer(port->tty);
-	tty_ldisc_flush(port->tty);
+	tty_driver_flush_buffer(tty);
+	tty_ldisc_flush(tty);
 
 	firm_report_tx_done(port);
 
@@ -728,11 +759,12 @@
 
 	stop_command_port(port->serial);
 
-	port->tty->closing = 0;
+	tty->closing = 0;
 }
 
 
-static int whiteheat_write(struct usb_serial_port *port, const unsigned char *buf, int count)
+static int whiteheat_write(struct tty_struct *tty,
+	struct usb_serial_port *port, const unsigned char *buf, int count)
 {
 	struct usb_serial *serial = port->serial;
 	struct whiteheat_private *info = usb_get_serial_port_data(port);
@@ -763,16 +795,19 @@
 
 		wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
 		urb = wrap->urb;
-		bytes = (count > port->bulk_out_size) ? port->bulk_out_size : count;
-		memcpy (urb->transfer_buffer, buf + sent, bytes);
+		bytes = (count > port->bulk_out_size) ?
+					port->bulk_out_size : count;
+		memcpy(urb->transfer_buffer, buf + sent, bytes);
 
-		usb_serial_debug_data(debug, &port->dev, __func__, bytes, urb->transfer_buffer);
+		usb_serial_debug_data(debug, &port->dev,
+				__func__, bytes, urb->transfer_buffer);
 
 		urb->dev = serial->dev;
 		urb->transfer_buffer_length = bytes;
 		result = usb_submit_urb(urb, GFP_ATOMIC);
 		if (result) {
-			err("%s - failed submitting write urb, error %d", __func__, result);
+			err("%s - failed submitting write urb, error %d",
+							__func__, result);
 			sent = result;
 			spin_lock_irqsave(&info->lock, flags);
 			list_add(tmp, &info->tx_urbs_free);
@@ -790,16 +825,16 @@
 	return sent;
 }
 
-
-static int whiteheat_write_room(struct usb_serial_port *port)
+static int whiteheat_write_room(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct whiteheat_private *info = usb_get_serial_port_data(port);
 	struct list_head *tmp;
 	int room = 0;
 	unsigned long flags;
 
 	dbg("%s - port %d", __func__, port->number);
-	
+
 	spin_lock_irqsave(&info->lock, flags);
 	list_for_each(tmp, &info->tx_urbs_free)
 		room++;
@@ -810,9 +845,9 @@
 	return (room);
 }
 
-
-static int whiteheat_tiocmget (struct usb_serial_port *port, struct file *file)
+static int whiteheat_tiocmget(struct tty_struct *tty, struct file *file)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct whiteheat_private *info = usb_get_serial_port_data(port);
 	unsigned int modem_signals = 0;
 
@@ -827,10 +862,10 @@
 	return modem_signals;
 }
 
-
-static int whiteheat_tiocmset (struct usb_serial_port *port, struct file *file,
+static int whiteheat_tiocmset(struct tty_struct *tty, struct file *file,
 			       unsigned int set, unsigned int clear)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct whiteheat_private *info = usb_get_serial_port_data(port);
 
 	dbg("%s - port %d", __func__, port->number);
@@ -851,65 +886,55 @@
 }
 
 
-static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+static int whiteheat_ioctl(struct tty_struct *tty, struct file *file,
+					unsigned int cmd, unsigned long arg)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct serial_struct serstruct;
 	void __user *user_arg = (void __user *)arg;
 
 	dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
 
 	switch (cmd) {
-		case TIOCGSERIAL:
-			memset(&serstruct, 0, sizeof(serstruct));
-			serstruct.type = PORT_16654;
-			serstruct.line = port->serial->minor;
-			serstruct.port = port->number;
-			serstruct.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
-			serstruct.xmit_fifo_size = port->bulk_out_size;
-			serstruct.custom_divisor = 0;
-			serstruct.baud_base = 460800;
-			serstruct.close_delay = CLOSING_DELAY;
-			serstruct.closing_wait = CLOSING_DELAY;
+	case TIOCGSERIAL:
+		memset(&serstruct, 0, sizeof(serstruct));
+		serstruct.type = PORT_16654;
+		serstruct.line = port->serial->minor;
+		serstruct.port = port->number;
+		serstruct.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
+		serstruct.xmit_fifo_size = port->bulk_out_size;
+		serstruct.custom_divisor = 0;
+		serstruct.baud_base = 460800;
+		serstruct.close_delay = CLOSING_DELAY;
+		serstruct.closing_wait = CLOSING_DELAY;
 
-			if (copy_to_user(user_arg, &serstruct, sizeof(serstruct)))
-				return -EFAULT;
-
-			break;
-
-		case TIOCSSERIAL:
-			if (copy_from_user(&serstruct, user_arg, sizeof(serstruct)))
-				return -EFAULT;
-
-			/*
-			 * For now this is ignored. dip sets the ASYNC_[V]HI flags
-			 * but this isn't used by us at all. Maybe someone somewhere
-			 * will need the custom_divisor setting.
-			 */
-
-			break;
-
-		default:
-			break;
+		if (copy_to_user(user_arg, &serstruct, sizeof(serstruct)))
+			return -EFAULT;
+		break;
+	default:
+		break;
 	}
 
 	return -ENOIOCTLCMD;
 }
 
 
-static void whiteheat_set_termios(struct usb_serial_port *port, struct ktermios *old_termios)
+static void whiteheat_set_termios(struct tty_struct *tty,
+	struct usb_serial_port *port, struct ktermios *old_termios)
 {
-	dbg("%s -port %d", __func__, port->number);
-	firm_setup_port(port);
+	firm_setup_port(tty);
 }
 
-
-static void whiteheat_break_ctl(struct usb_serial_port *port, int break_state) {
+static void whiteheat_break_ctl(struct tty_struct *tty, int break_state)
+{
+	struct usb_serial_port *port = tty->driver_data;
 	firm_set_break(port, break_state);
 }
 
 
-static int whiteheat_chars_in_buffer(struct usb_serial_port *port)
+static int whiteheat_chars_in_buffer(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct whiteheat_private *info = usb_get_serial_port_data(port);
 	struct list_head *tmp;
 	struct whiteheat_urb_wrap *wrap;
@@ -925,13 +950,14 @@
 	}
 	spin_unlock_irqrestore(&info->lock, flags);
 
-	dbg ("%s - returns %d", __func__, chars);
+	dbg("%s - returns %d", __func__, chars);
 	return chars;
 }
 
 
-static void whiteheat_throttle (struct usb_serial_port *port)
+static void whiteheat_throttle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct whiteheat_private *info = usb_get_serial_port_data(port);
 	unsigned long flags;
 
@@ -945,8 +971,9 @@
 }
 
 
-static void whiteheat_unthrottle (struct usb_serial_port *port)
+static void whiteheat_unthrottle(struct tty_struct *tty)
 {
+	struct usb_serial_port *port = tty->driver_data;
 	struct whiteheat_private *info = usb_get_serial_port_data(port);
 	int actually_throttled;
 	unsigned long flags;
@@ -993,7 +1020,7 @@
 
 	command_info = usb_get_serial_port_data(command_port);
 	if (!command_info) {
-		dbg ("%s - command_info is NULL, exiting.", __func__);
+		dbg("%s - command_info is NULL, exiting.", __func__);
 		return;
 	}
 	if (status) {
@@ -1004,7 +1031,8 @@
 		return;
 	}
 
-	usb_serial_debug_data(debug, &command_port->dev, __func__, urb->actual_length, data);
+	usb_serial_debug_data(debug, &command_port->dev,
+				__func__, urb->actual_length, data);
 
 	if (data[0] == WHITEHEAT_CMD_COMPLETE) {
 		command_info->command_finished = WHITEHEAT_CMD_COMPLETE;
@@ -1013,21 +1041,23 @@
 		command_info->command_finished = WHITEHEAT_CMD_FAILURE;
 		wake_up(&command_info->wait_command);
 	} else if (data[0] == WHITEHEAT_EVENT) {
-		/* These are unsolicited reports from the firmware, hence no waiting command to wakeup */
+		/* These are unsolicited reports from the firmware, hence no
+		   waiting command to wakeup */
 		dbg("%s - event received", __func__);
 	} else if (data[0] == WHITEHEAT_GET_DTR_RTS) {
-		memcpy(command_info->result_buffer, &data[1], urb->actual_length - 1);
+		memcpy(command_info->result_buffer, &data[1],
+						urb->actual_length - 1);
 		command_info->command_finished = WHITEHEAT_CMD_COMPLETE;
 		wake_up(&command_info->wait_command);
-	} else {
+	} else
 		dbg("%s - bad reply from firmware", __func__);
-	}
-	
+
 	/* Continue trying to always read */
 	command_port->read_urb->dev = command_port->serial->dev;
 	result = usb_submit_urb(command_port->read_urb, GFP_ATOMIC);
 	if (result)
-		dbg("%s - failed resubmitting read urb, error %d", __func__, result);
+		dbg("%s - failed resubmitting read urb, error %d",
+			__func__, result);
 }
 
 
@@ -1060,7 +1090,8 @@
 		return;
 	}
 
-	usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
+	usb_serial_debug_data(debug, &port->dev,
+				__func__, urb->actual_length, data);
 
 	spin_lock(&info->lock);
 	list_add_tail(&wrap->list, &info->rx_urb_q);
@@ -1107,7 +1138,8 @@
 /*****************************************************************************
  * Connect Tech's White Heat firmware interface
  *****************************************************************************/
-static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize)
+static int firm_send_command(struct usb_serial_port *port, __u8 command,
+						__u8 *data, __u8 datasize)
 {
 	struct usb_serial_port *command_port;
 	struct whiteheat_command_private *command_info;
@@ -1122,13 +1154,13 @@
 	command_info = usb_get_serial_port_data(command_port);
 	mutex_lock(&command_info->mutex);
 	command_info->command_finished = false;
-	
+
 	transfer_buffer = (__u8 *)command_port->write_urb->transfer_buffer;
 	transfer_buffer[0] = command;
-	memcpy (&transfer_buffer[1], data, datasize);
+	memcpy(&transfer_buffer[1], data, datasize);
 	command_port->write_urb->transfer_buffer_length = datasize + 1;
 	command_port->write_urb->dev = port->serial->dev;
-	retval = usb_submit_urb (command_port->write_urb, GFP_NOIO);
+	retval = usb_submit_urb(command_port->write_urb, GFP_NOIO);
 	if (retval) {
 		dbg("%s - submit urb failed", __func__);
 		goto exit;
@@ -1155,51 +1187,57 @@
 	if (command_info->command_finished == WHITEHEAT_CMD_COMPLETE) {
 		dbg("%s - command completed.", __func__);
 		switch (command) {
-			case WHITEHEAT_GET_DTR_RTS:
-				info = usb_get_serial_port_data(port);
-				memcpy(&info->mcr, command_info->result_buffer, sizeof(struct whiteheat_dr_info));
+		case WHITEHEAT_GET_DTR_RTS:
+			info = usb_get_serial_port_data(port);
+			memcpy(&info->mcr, command_info->result_buffer,
+					sizeof(struct whiteheat_dr_info));
 				break;
 		}
 	}
-
 exit:
 	mutex_unlock(&command_info->mutex);
 	return retval;
 }
 
 
-static int firm_open(struct usb_serial_port *port) {
+static int firm_open(struct usb_serial_port *port)
+{
 	struct whiteheat_simple open_command;
 
 	open_command.port = port->number - port->serial->minor + 1;
-	return firm_send_command(port, WHITEHEAT_OPEN, (__u8 *)&open_command, sizeof(open_command));
+	return firm_send_command(port, WHITEHEAT_OPEN,
+		(__u8 *)&open_command, sizeof(open_command));
 }
 
 
-static int firm_close(struct usb_serial_port *port) {
+static int firm_close(struct usb_serial_port *port)
+{
 	struct whiteheat_simple close_command;
 
 	close_command.port = port->number - port->serial->minor + 1;
-	return firm_send_command(port, WHITEHEAT_CLOSE, (__u8 *)&close_command, sizeof(close_command));
+	return firm_send_command(port, WHITEHEAT_CLOSE,
+			(__u8 *)&close_command, sizeof(close_command));
 }
 
 
-static int firm_setup_port(struct usb_serial_port *port) {
+static int firm_setup_port(struct tty_struct *tty)
+{
+	struct usb_serial_port *port = tty->driver_data;
 	struct whiteheat_port_settings port_settings;
-	unsigned int cflag = port->tty->termios->c_cflag;
+	unsigned int cflag = tty->termios->c_cflag;
 
 	port_settings.port = port->number + 1;
 
 	/* get the byte size */
 	switch (cflag & CSIZE) {
-		case CS5:	port_settings.bits = 5;   break;
-		case CS6:	port_settings.bits = 6;   break;
-		case CS7:	port_settings.bits = 7;   break;
-		default:
-		case CS8:	port_settings.bits = 8;   break;
+	case CS5:	port_settings.bits = 5;   break;
+	case CS6:	port_settings.bits = 6;   break;
+	case CS7:	port_settings.bits = 7;   break;
+	default:
+	case CS8:	port_settings.bits = 8;   break;
 	}
 	dbg("%s - data bits = %d", __func__, port_settings.bits);
-	
+
 	/* determine the parity */
 	if (cflag & PARENB)
 		if (cflag & CMSPAR)
@@ -1225,7 +1263,8 @@
 
 	/* figure out the flow control settings */
 	if (cflag & CRTSCTS)
-		port_settings.hflow = (WHITEHEAT_HFLOW_CTS | WHITEHEAT_HFLOW_RTS);
+		port_settings.hflow = (WHITEHEAT_HFLOW_CTS |
+						WHITEHEAT_HFLOW_RTS);
 	else
 		port_settings.hflow = WHITEHEAT_HFLOW_NONE;
 	dbg("%s - hardware flow control = %s %s %s %s", __func__,
@@ -1233,81 +1272,95 @@
 	    (port_settings.hflow & WHITEHEAT_HFLOW_RTS) ? "RTS" : "",
 	    (port_settings.hflow & WHITEHEAT_HFLOW_DSR) ? "DSR" : "",
 	    (port_settings.hflow & WHITEHEAT_HFLOW_DTR) ? "DTR" : "");
-	
+
 	/* determine software flow control */
-	if (I_IXOFF(port->tty))
+	if (I_IXOFF(tty))
 		port_settings.sflow = WHITEHEAT_SFLOW_RXTX;
 	else
 		port_settings.sflow = WHITEHEAT_SFLOW_NONE;
 	dbg("%s - software flow control = %c", __func__, port_settings.sflow);
-	
-	port_settings.xon = START_CHAR(port->tty);
-	port_settings.xoff = STOP_CHAR(port->tty);
-	dbg("%s - XON = %2x, XOFF = %2x", __func__, port_settings.xon, port_settings.xoff);
+
+	port_settings.xon = START_CHAR(tty);
+	port_settings.xoff = STOP_CHAR(tty);
+	dbg("%s - XON = %2x, XOFF = %2x",
+			__func__, port_settings.xon, port_settings.xoff);
 
 	/* get the baud rate wanted */
-	port_settings.baud = tty_get_baud_rate(port->tty);
+	port_settings.baud = tty_get_baud_rate(tty);
 	dbg("%s - baud rate = %d", __func__, port_settings.baud);
 
 	/* fixme: should set validated settings */
-	tty_encode_baud_rate(port->tty, port_settings.baud, port_settings.baud);
+	tty_encode_baud_rate(tty, port_settings.baud, port_settings.baud);
 	/* handle any settings that aren't specified in the tty structure */
 	port_settings.lloop = 0;
-	
+
 	/* now send the message to the device */
-	return firm_send_command(port, WHITEHEAT_SETUP_PORT, (__u8 *)&port_settings, sizeof(port_settings));
+	return firm_send_command(port, WHITEHEAT_SETUP_PORT,
+			(__u8 *)&port_settings, sizeof(port_settings));
 }
 
 
-static int firm_set_rts(struct usb_serial_port *port, __u8 onoff) {
+static int firm_set_rts(struct usb_serial_port *port, __u8 onoff)
+{
 	struct whiteheat_set_rdb rts_command;
 
 	rts_command.port = port->number - port->serial->minor + 1;
 	rts_command.state = onoff;
-	return firm_send_command(port, WHITEHEAT_SET_RTS, (__u8 *)&rts_command, sizeof(rts_command));
+	return firm_send_command(port, WHITEHEAT_SET_RTS,
+			(__u8 *)&rts_command, sizeof(rts_command));
 }
 
 
-static int firm_set_dtr(struct usb_serial_port *port, __u8 onoff) {
+static int firm_set_dtr(struct usb_serial_port *port, __u8 onoff)
+{
 	struct whiteheat_set_rdb dtr_command;
 
 	dtr_command.port = port->number - port->serial->minor + 1;
 	dtr_command.state = onoff;
-	return firm_send_command(port, WHITEHEAT_SET_RTS, (__u8 *)&dtr_command, sizeof(dtr_command));
+	return firm_send_command(port, WHITEHEAT_SET_DTR,
+			(__u8 *)&dtr_command, sizeof(dtr_command));
 }
 
 
-static int firm_set_break(struct usb_serial_port *port, __u8 onoff) {
+static int firm_set_break(struct usb_serial_port *port, __u8 onoff)
+{
 	struct whiteheat_set_rdb break_command;
 
 	break_command.port = port->number - port->serial->minor + 1;
 	break_command.state = onoff;
-	return firm_send_command(port, WHITEHEAT_SET_RTS, (__u8 *)&break_command, sizeof(break_command));
+	return firm_send_command(port, WHITEHEAT_SET_BREAK,
+			(__u8 *)&break_command, sizeof(break_command));
 }
 
 
-static int firm_purge(struct usb_serial_port *port, __u8 rxtx) {
+static int firm_purge(struct usb_serial_port *port, __u8 rxtx)
+{
 	struct whiteheat_purge purge_command;
 
 	purge_command.port = port->number - port->serial->minor + 1;
 	purge_command.what = rxtx;
-	return firm_send_command(port, WHITEHEAT_PURGE, (__u8 *)&purge_command, sizeof(purge_command));
+	return firm_send_command(port, WHITEHEAT_PURGE,
+			(__u8 *)&purge_command, sizeof(purge_command));
 }
 
 
-static int firm_get_dtr_rts(struct usb_serial_port *port) {
+static int firm_get_dtr_rts(struct usb_serial_port *port)
+{
 	struct whiteheat_simple get_dr_command;
 
 	get_dr_command.port = port->number - port->serial->minor + 1;
-	return firm_send_command(port, WHITEHEAT_GET_DTR_RTS, (__u8 *)&get_dr_command, sizeof(get_dr_command));
+	return firm_send_command(port, WHITEHEAT_GET_DTR_RTS,
+			(__u8 *)&get_dr_command, sizeof(get_dr_command));
 }
 
 
-static int firm_report_tx_done(struct usb_serial_port *port) {
+static int firm_report_tx_done(struct usb_serial_port *port)
+{
 	struct whiteheat_simple close_command;
 
 	close_command.port = port->number - port->serial->minor + 1;
-	return firm_send_command(port, WHITEHEAT_REPORT_TX_DONE, (__u8 *)&close_command, sizeof(close_command));
+	return firm_send_command(port, WHITEHEAT_REPORT_TX_DONE,
+			(__u8 *)&close_command, sizeof(close_command));
 }
 
 
@@ -1319,7 +1372,7 @@
 	struct usb_serial_port *command_port;
 	struct whiteheat_command_private *command_info;
 	int retval = 0;
-	
+
 	command_port = serial->port[COMMAND_PORT];
 	command_info = usb_get_serial_port_data(command_port);
 	mutex_lock(&command_info->mutex);
@@ -1330,7 +1383,8 @@
 		command_port->read_urb->dev = serial->dev;
 		retval = usb_submit_urb(command_port->read_urb, GFP_KERNEL);
 		if (retval) {
-			err("%s - failed submitting read urb, error %d", __func__, retval);
+			err("%s - failed submitting read urb, error %d",
+							__func__, retval);
 			goto exit;
 		}
 	}
@@ -1400,7 +1454,8 @@
 }
 
 
-static struct whiteheat_urb_wrap *urb_to_wrap(struct urb* urb, struct list_head *head)
+static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb,
+						struct list_head *head)
 {
 	struct whiteheat_urb_wrap *wrap;
 	struct list_head *tmp;
@@ -1426,7 +1481,7 @@
 	struct whiteheat_private *info =
 		container_of(work, struct whiteheat_private, rx_work);
 	struct usb_serial_port *port = info->port;
-	struct tty_struct *tty = port->tty;
+	struct tty_struct *tty = port->port.tty;
 	struct whiteheat_urb_wrap *wrap;
 	struct urb *urb;
 	unsigned long flags;
@@ -1449,7 +1504,8 @@
 		urb = wrap->urb;
 
 		if (tty && urb->actual_length) {
-			int len = tty_buffer_request_room(tty, urb->actual_length);
+			int len = tty_buffer_request_room(tty,
+							urb->actual_length);
 			/* This stuff can go away now I suspect */
 			if (unlikely(len < urb->actual_length)) {
 				spin_lock_irqsave(&info->lock, flags);
@@ -1466,7 +1522,8 @@
 		urb->dev = port->serial->dev;
 		result = usb_submit_urb(urb, GFP_ATOMIC);
 		if (result) {
-			err("%s - failed resubmitting read urb, error %d", __func__, result);
+			err("%s - failed resubmitting read urb, error %d",
+				__func__, result);
 			spin_lock_irqsave(&info->lock, flags);
 			list_add(tmp, &info->rx_urbs_free);
 			continue;
@@ -1485,7 +1542,7 @@
 /*****************************************************************************
  * Connect Tech's White Heat module functions
  *****************************************************************************/
-static int __init whiteheat_init (void)
+static int __init whiteheat_init(void)
 {
 	int retval;
 	retval = usb_serial_register(&whiteheat_fake_device);
@@ -1508,19 +1565,19 @@
 }
 
 
-static void __exit whiteheat_exit (void)
+static void __exit whiteheat_exit(void)
 {
-	usb_deregister (&whiteheat_driver);
-	usb_serial_deregister (&whiteheat_fake_device);
-	usb_serial_deregister (&whiteheat_device);
+	usb_deregister(&whiteheat_driver);
+	usb_serial_deregister(&whiteheat_fake_device);
+	usb_serial_deregister(&whiteheat_device);
 }
 
 
 module_init(whiteheat_init);
 module_exit(whiteheat_exit);
 
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 MODULE_FIRMWARE("whiteheat.fw");
diff --git a/drivers/usb/serial/whiteheat.h b/drivers/usb/serial/whiteheat.h
index f160797..38065df 100644
--- a/drivers/usb/serial/whiteheat.h
+++ b/drivers/usb/serial/whiteheat.h
@@ -2,7 +2,7 @@
  * USB ConnectTech WhiteHEAT driver
  *
  *      Copyright (C) 2002
- *          Connect Tech Inc.	
+ *          Connect Tech Inc.
  *
  *      Copyright (C) 1999, 2000
  *          Greg Kroah-Hartman (greg@kroah.com)
@@ -12,7 +12,8 @@
  *      the Free Software Foundation; either version 2 of the License, or
  *      (at your option) any later version.
  *
- * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * See Documentation/usb/usb-serial.txt for more information on using this
+ * driver
  *
  */
 
@@ -30,13 +31,16 @@
 #define WHITEHEAT_DUMP			7	/* dump memory */
 #define WHITEHEAT_STATUS		8	/* get status */
 #define WHITEHEAT_PURGE			9	/* clear the UART fifos */
-#define WHITEHEAT_GET_DTR_RTS		10	/* get the state of DTR and RTS for a port */
-#define WHITEHEAT_GET_HW_INFO		11	/* get EEPROM info and hardware ID */
+#define WHITEHEAT_GET_DTR_RTS		10	/* get the state of DTR and RTS
+							for a port */
+#define WHITEHEAT_GET_HW_INFO		11	/* get EEPROM info and
+							hardware ID */
 #define WHITEHEAT_REPORT_TX_DONE	12	/* get the next TX done */
 #define WHITEHEAT_EVENT			13	/* unsolicited status events */
-#define WHITEHEAT_ECHO			14	/* send data to the indicated IN endpoint */
-#define WHITEHEAT_DO_TEST		15	/* perform the specified test */
-#define WHITEHEAT_CMD_COMPLETE		16	/* reply for certain commands */
+#define WHITEHEAT_ECHO			14	/* send data to the indicated
+						   IN endpoint */
+#define WHITEHEAT_DO_TEST		15	/* perform specified test */
+#define WHITEHEAT_CMD_COMPLETE		16	/* reply for some commands */
 #define WHITEHEAT_CMD_FAILURE		17	/* reply for failed commands */
 
 
@@ -67,20 +71,28 @@
 #define WHITEHEAT_PAR_MARK	'1'	/* mark (force 1) parity */
 
 #define WHITEHEAT_SFLOW_NONE	'n'	/* no software flow control */
-#define WHITEHEAT_SFLOW_RX	'r'	/* XOFF/ON is sent when RX fills/empties */
-#define WHITEHEAT_SFLOW_TX	't'	/* when received XOFF/ON will stop/start TX */
+#define WHITEHEAT_SFLOW_RX	'r'	/* XOFF/ON is sent when RX
+					   fills/empties */
+#define WHITEHEAT_SFLOW_TX	't'	/* when received XOFF/ON will
+					   stop/start TX */
 #define WHITEHEAT_SFLOW_RXTX	'b'	/* both SFLOW_RX and SFLOW_TX */
 
 #define WHITEHEAT_HFLOW_NONE		0x00	/* no hardware flow control */
-#define WHITEHEAT_HFLOW_RTS_TOGGLE	0x01	/* RTS is on during transmit, off otherwise */
-#define WHITEHEAT_HFLOW_DTR		0x02	/* DTR is off/on when RX fills/empties */
-#define WHITEHEAT_HFLOW_CTS		0x08	/* when received CTS off/on will stop/start TX */
-#define WHITEHEAT_HFLOW_DSR		0x10	/* when received DSR off/on will stop/start TX */
-#define WHITEHEAT_HFLOW_RTS		0x80	/* RTS is off/on when RX fills/empties */
+#define WHITEHEAT_HFLOW_RTS_TOGGLE	0x01	/* RTS is on during transmit,
+						   off otherwise */
+#define WHITEHEAT_HFLOW_DTR		0x02	/* DTR is off/on when RX
+						   fills/empties */
+#define WHITEHEAT_HFLOW_CTS		0x08	/* when received CTS off/on
+						   will stop/start TX */
+#define WHITEHEAT_HFLOW_DSR		0x10	/* when received DSR off/on
+						   will stop/start TX */
+#define WHITEHEAT_HFLOW_RTS		0x80	/* RTS is off/on when RX
+						   fills/empties */
 
 struct whiteheat_port_settings {
 	__u8	port;		/* port number (1 to N) */
-	__u32	baud;		/* any value 7 - 460800, firmware calculates best fit; arrives little endian */
+	__u32	baud;		/* any value 7 - 460800, firmware calculates
+				   best fit; arrives little endian */
 	__u8	bits;		/* 5, 6, 7, or 8 */
 	__u8	stop;		/* 1 or 2, default 1 (2 = 1.5 if bits = 5) */
 	__u8	parity;		/* see WHITEHEAT_PAR_* above */
@@ -167,12 +179,14 @@
  */
 #define WHITEHEAT_TEST_UART_RW		0x01  /* read/write uart registers */
 #define WHITEHEAT_TEST_UART_INTR	0x02  /* uart interrupt */
-#define WHITEHEAT_TEST_SETUP_CONT	0x03  /* setup for PORT_CONT/PORT_DISCONT */
+#define WHITEHEAT_TEST_SETUP_CONT	0x03  /* setup for
+						PORT_CONT/PORT_DISCONT */
 #define WHITEHEAT_TEST_PORT_CONT	0x04  /* port connect */
 #define WHITEHEAT_TEST_PORT_DISCONT	0x05  /* port disconnect */
 #define WHITEHEAT_TEST_UART_CLK_START	0x06  /* uart clock test start */
 #define WHITEHEAT_TEST_UART_CLK_STOP	0x07  /* uart clock test stop */
-#define WHITEHEAT_TEST_MODEM_FT		0x08  /* modem signals, requires a loopback cable/connector */
+#define WHITEHEAT_TEST_MODEM_FT		0x08  /* modem signals, requires a
+						loopback cable/connector */
 #define WHITEHEAT_TEST_ERASE_EEPROM	0x09  /* erase eeprom */
 #define WHITEHEAT_TEST_READ_EEPROM	0x0a  /* read eeprom */
 #define WHITEHEAT_TEST_PROGRAM_EEPROM	0x0b  /* program eeprom */
@@ -198,19 +212,27 @@
 #define WHITEHEAT_EVENT_CONNECT		0x08	/* connect field is valid */
 
 #define WHITEHEAT_FLOW_NONE		0x00	/* no flow control active */
-#define WHITEHEAT_FLOW_HARD_OUT		0x01	/* TX is stopped by CTS (waiting for CTS to go on) */
-#define WHITEHEAT_FLOW_HARD_IN		0x02	/* remote TX is stopped by RTS */
-#define WHITEHEAT_FLOW_SOFT_OUT		0x04	/* TX is stopped by XOFF received (waiting for XON) */
-#define WHITEHEAT_FLOW_SOFT_IN		0x08	/* remote TX is stopped by XOFF transmitted */
+#define WHITEHEAT_FLOW_HARD_OUT		0x01	/* TX is stopped by CTS
+						  (waiting for CTS to go on) */
+#define WHITEHEAT_FLOW_HARD_IN		0x02	/* remote TX is stopped
+						  by RTS */
+#define WHITEHEAT_FLOW_SOFT_OUT		0x04	/* TX is stopped by XOFF
+						  received (waiting for XON) */
+#define WHITEHEAT_FLOW_SOFT_IN		0x08	/* remote TX is stopped by XOFF
+						  transmitted */
 #define WHITEHEAT_FLOW_TX_DONE		0x80	/* TX has completed */
 
 struct whiteheat_status_info {
 	__u8	port;		/* port number (1 to N) */
-	__u8	event;		/* indicates what the current event is, see WHITEHEAT_EVENT_* above */
-	__u8	modem;		/* modem signal status (copy of uart's MSR register) */
+	__u8	event;		/* indicates what the current event is,
+					see WHITEHEAT_EVENT_* above */
+	__u8	modem;		/* modem signal status (copy of uart's
+					MSR register) */
 	__u8	error;		/* line status (copy of uart's LSR register) */
-	__u8	flow;		/* flow control state, see WHITEHEAT_FLOW_* above */
-	__u8	connect;	/* 0 means not connected, non-zero means connected */
+	__u8	flow;		/* flow control state, see WHITEHEAT_FLOW_*
+					above */
+	__u8	connect;	/* 0 means not connected, non-zero means
+					connected */
 };
 
 
@@ -256,7 +278,8 @@
 struct whiteheat_event_info {
 	__u8	port;		/* port number (1 to N) */
 	__u8	event;		/* see whiteheat_status_info.event */
-	__u8	info;		/* see whiteheat_status_info.modem, .error, .flow, .connect */
+	__u8	info;		/* see whiteheat_status_info.modem, .error,
+					.flow, .connect */
 };
 
 
@@ -269,7 +292,8 @@
 
 struct whiteheat_test_info {
 	__u8	port;		/* port number (1 to N) */
-	__u8	test;		/* indicates which test this is a response for, see WHITEHEAT_DO_TEST above */
+	__u8	test;		/* indicates which test this is a response for,
+				   see WHITEHEAT_DO_TEST above */
 	__u8	status;		/* see WHITEHEAT_TEST_* above */
 	__u8	results[32];	/* test-dependent results */
 };
diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c
index 579e9f5..17f1ae2 100644
--- a/drivers/usb/storage/datafab.c
+++ b/drivers/usb/storage/datafab.c
@@ -1,7 +1,5 @@
 /* Driver for Datafab USB Compact Flash reader
  *
- * $Id: datafab.c,v 1.7 2002/02/25 00:40:13 mdharm Exp $
- *
  * datafab driver v0.1:
  *
  * First release
diff --git a/drivers/usb/storage/debug.c b/drivers/usb/storage/debug.c
index 01e4306..a2b5526 100644
--- a/drivers/usb/storage/debug.c
+++ b/drivers/usb/storage/debug.c
@@ -1,8 +1,6 @@
 /* Driver for USB Mass Storage compliant devices
  * Debugging Functions Source Code File
  *
- * $Id: debug.c,v 1.9 2002/04/22 03:39:43 mdharm Exp $
- *
  * Current development and maintenance by:
  *   (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
  *
diff --git a/drivers/usb/storage/debug.h b/drivers/usb/storage/debug.h
index 77e244a..dbb985d 100644
--- a/drivers/usb/storage/debug.h
+++ b/drivers/usb/storage/debug.h
@@ -1,8 +1,6 @@
 /* Driver for USB Mass Storage compliant devices
  * Debugging Functions Header File
  *
- * $Id: debug.h,v 1.6 2001/01/12 23:51:04 mdharm Exp $
- *
  * Current development and maintenance by:
  *   (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
  *
diff --git a/drivers/usb/storage/dpcm.c b/drivers/usb/storage/dpcm.c
index 9a410b5..9399234 100644
--- a/drivers/usb/storage/dpcm.c
+++ b/drivers/usb/storage/dpcm.c
@@ -1,7 +1,5 @@
 /* Driver for Microtech DPCM-USB CompactFlash/SmartMedia reader
  *
- * $Id: dpcm.c,v 1.4 2001/06/11 02:54:25 mdharm Exp $
- *
  * DPCM driver v0.1:
  *
  * First release
diff --git a/drivers/usb/storage/dpcm.h b/drivers/usb/storage/dpcm.h
index 81b464c..e7b7b0f 100644
--- a/drivers/usb/storage/dpcm.h
+++ b/drivers/usb/storage/dpcm.h
@@ -1,7 +1,5 @@
 /* Driver for Microtech DPCM-USB CompactFlash/SmartMedia reader
  *
- * $Id: dpcm.h,v 1.2 2000/08/25 00:13:51 mdharm Exp $
- *
  * DPCM driver v0.1:
  *
  * First release
diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
index f5a4e8d..7a4d456 100644
--- a/drivers/usb/storage/freecom.c
+++ b/drivers/usb/storage/freecom.c
@@ -1,7 +1,5 @@
 /* Driver for Freecom USB/IDE adaptor
  *
- * $Id: freecom.c,v 1.22 2002/04/22 03:39:43 mdharm Exp $
- *
  * Freecom v0.1:
  *
  * First release
diff --git a/drivers/usb/storage/freecom.h b/drivers/usb/storage/freecom.h
index 1b012d6..20d0fe6 100644
--- a/drivers/usb/storage/freecom.h
+++ b/drivers/usb/storage/freecom.h
@@ -1,7 +1,5 @@
 /* Driver for Freecom USB/IDE adaptor
  *
- * $Id: freecom.h,v 1.4 2000/08/29 14:49:15 dlbrown Exp $
- *
  * Freecom v0.1:
  *
  * First release
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c
index 187dd1e..4995bb5 100644
--- a/drivers/usb/storage/initializers.c
+++ b/drivers/usb/storage/initializers.c
@@ -1,7 +1,5 @@
 /* Special Initializers for certain USB Mass Storage devices
  *
- * $Id: initializers.c,v 1.2 2000/09/06 22:35:57 mdharm Exp $
- *
  * Current development and maintenance by:
  *   (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
  *
diff --git a/drivers/usb/storage/initializers.h b/drivers/usb/storage/initializers.h
index ad3ffd4..529327f 100644
--- a/drivers/usb/storage/initializers.h
+++ b/drivers/usb/storage/initializers.h
@@ -1,7 +1,5 @@
 /* Header file for Special Initializers for certain USB Mass Storage devices
  *
- * $Id: initializers.h,v 1.1 2000/08/29 23:07:02 mdharm Exp $
- *
  * Current development and maintenance by:
  *   (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
  *
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index 3addcd8..383abf2 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -1,7 +1,5 @@
 /* Transport & Protocol Driver for In-System Design, Inc. ISD200 ASIC
  *
- * $Id: isd200.c,v 1.16 2002/04/22 03:39:43 mdharm Exp $
- *
  * Current development and maintenance:
  *   (C) 2001-2002 Björn Stenberg (bjorn@haxx.se)
  *
@@ -586,7 +584,7 @@
 	/* if the command gets aborted by the higher layers, we need to
 	 * short-circuit all other processing
 	 */
-	if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
+	if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
 		US_DEBUGP("-- command was aborted\n");
 		goto Handle_Abort;
 	}
@@ -633,7 +631,7 @@
 
 	if (need_auto_sense) {
 		result = isd200_read_regs(us);
-		if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
+		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
 			US_DEBUGP("-- auto-sense aborted\n");
 			goto Handle_Abort;
 		}
@@ -663,7 +661,7 @@
 	srb->result = DID_ABORT << 16;
 
 	/* permit the reset transfer to take place */
-	clear_bit(US_FLIDX_ABORTING, &us->flags);
+	clear_bit(US_FLIDX_ABORTING, &us->dflags);
 	/* Need reset here */
 }
 
diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c
index 61097cb..df67f13 100644
--- a/drivers/usb/storage/jumpshot.c
+++ b/drivers/usb/storage/jumpshot.c
@@ -1,7 +1,5 @@
 /* Driver for Lexar "Jumpshot" Compact Flash reader
  *
- * $Id: jumpshot.c,v 1.7 2002/02/25 00:40:13 mdharm Exp $
- *
  * jumpshot driver v0.1:
  *
  * First release
diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
index b9b8ede..3b3357e 100644
--- a/drivers/usb/storage/protocol.c
+++ b/drivers/usb/storage/protocol.c
@@ -1,7 +1,5 @@
 /* Driver for USB Mass Storage compliant devices
  *
- * $Id: protocol.c,v 1.14 2002/04/22 03:39:43 mdharm Exp $
- *
  * Current development and maintenance by:
  *   (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
  *
diff --git a/drivers/usb/storage/protocol.h b/drivers/usb/storage/protocol.h
index 8737a36..487056f 100644
--- a/drivers/usb/storage/protocol.h
+++ b/drivers/usb/storage/protocol.h
@@ -1,8 +1,6 @@
 /* Driver for USB Mass Storage compliant devices
  * Protocol Functions Header File
  *
- * $Id: protocol.h,v 1.4 2001/02/13 07:10:03 mdharm Exp $
- *
  * Current development and maintenance by:
  *   (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
  *
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 3fcde9f..09779f6 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -1,8 +1,6 @@
 /* Driver for USB Mass Storage compliant devices
  * SCSI layer glue code
  *
- * $Id: scsiglue.c,v 1.26 2002/04/22 03:39:43 mdharm Exp $
- *
  * Current development and maintenance by:
  *   (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
  *
@@ -73,7 +71,6 @@
 static int slave_alloc (struct scsi_device *sdev)
 {
 	struct us_data *us = host_to_us(sdev->host);
-	struct usb_host_endpoint *bulk_in_ep;
 
 	/*
 	 * Set the INQUIRY transfer length to 36.  We don't use any of
@@ -82,16 +79,22 @@
 	 */
 	sdev->inquiry_len = 36;
 
-	/* Scatter-gather buffers (all but the last) must have a length
-	 * divisible by the bulk maxpacket size.  Otherwise a data packet
-	 * would end up being short, causing a premature end to the data
-	 * transfer.  We'll use the maxpacket value of the bulk-IN pipe
-	 * to set the SCSI device queue's DMA alignment mask.
+	/* USB has unusual DMA-alignment requirements: Although the
+	 * starting address of each scatter-gather element doesn't matter,
+	 * the length of each element except the last must be divisible
+	 * by the Bulk maxpacket value.  There's currently no way to
+	 * express this by block-layer constraints, so we'll cop out
+	 * and simply require addresses to be aligned at 512-byte
+	 * boundaries.  This is okay since most block I/O involves
+	 * hardware sectors that are multiples of 512 bytes in length,
+	 * and since host controllers up through USB 2.0 have maxpacket
+	 * values no larger than 512.
+	 *
+	 * But it doesn't suffice for Wireless USB, where Bulk maxpacket
+	 * values can be as large as 2048.  To make that work properly
+	 * will require changes to the block layer.
 	 */
-	bulk_in_ep = us->pusb_dev->ep_in[usb_pipeendpoint(us->recv_bulk_pipe)];
-	blk_queue_update_dma_alignment(sdev->request_queue,
-			le16_to_cpu(bulk_in_ep->desc.wMaxPacketSize) - 1);
-			/* wMaxPacketSize must be a power of 2 */
+	blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
 
 	/*
 	 * The UFI spec treates the Peripheral Qualifier bits in an
@@ -116,10 +119,10 @@
 	 * while others have trouble with more than 64K. At this time we
 	 * are limiting both to 32K (64 sectores).
 	 */
-	if (us->flags & (US_FL_MAX_SECTORS_64 | US_FL_MAX_SECTORS_MIN)) {
+	if (us->fflags & (US_FL_MAX_SECTORS_64 | US_FL_MAX_SECTORS_MIN)) {
 		unsigned int max_sectors = 64;
 
-		if (us->flags & US_FL_MAX_SECTORS_MIN)
+		if (us->fflags & US_FL_MAX_SECTORS_MIN)
 			max_sectors = PAGE_CACHE_SIZE >> 9;
 		if (sdev->request_queue->max_sectors > max_sectors)
 			blk_queue_max_sectors(sdev->request_queue,
@@ -148,7 +151,7 @@
 		 * majority of devices work fine, but a few still can't
 		 * handle it.  The sd driver will simply assume those
 		 * devices are write-enabled. */
-		if (us->flags & US_FL_NO_WP_DETECT)
+		if (us->fflags & US_FL_NO_WP_DETECT)
 			sdev->skip_ms_page_3f = 1;
 
 		/* A number of devices have problems with MODE SENSE for
@@ -158,13 +161,13 @@
 		/* Some disks return the total number of blocks in response
 		 * to READ CAPACITY rather than the highest block number.
 		 * If this device makes that mistake, tell the sd driver. */
-		if (us->flags & US_FL_FIX_CAPACITY)
+		if (us->fflags & US_FL_FIX_CAPACITY)
 			sdev->fix_capacity = 1;
 
 		/* A few disks have two indistinguishable version, one of
 		 * which reports the correct capacity and the other does not.
 		 * The sd driver has to guess which is the case. */
-		if (us->flags & US_FL_CAPACITY_HEURISTICS)
+		if (us->fflags & US_FL_CAPACITY_HEURISTICS)
 			sdev->guess_capacity = 1;
 
 		/* Some devices report a SCSI revision level above 2 but are
@@ -213,7 +216,7 @@
 
 	/* Some devices choke when they receive a PREVENT-ALLOW MEDIUM
 	 * REMOVAL command, so suppress those commands. */
-	if (us->flags & US_FL_NOT_LOCKABLE)
+	if (us->fflags & US_FL_NOT_LOCKABLE)
 		sdev->lockable = 0;
 
 	/* this is to satisfy the compiler, tho I don't think the 
@@ -238,7 +241,7 @@
 	}
 
 	/* fail the command if we are disconnecting */
-	if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
+	if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
 		US_DEBUGP("Fail command during disconnect\n");
 		srb->result = DID_NO_CONNECT << 16;
 		done(srb);
@@ -248,7 +251,7 @@
 	/* enqueue the command and wake up the control thread */
 	srb->scsi_done = done;
 	us->srb = srb;
-	up(&(us->sema));
+	complete(&us->cmnd_ready);
 
 	return 0;
 }
@@ -280,9 +283,9 @@
 	 * with the reset).  Note that we must retain the host lock while
 	 * calling usb_stor_stop_transport(); otherwise it might interfere
 	 * with an auto-reset that begins as soon as we release the lock. */
-	set_bit(US_FLIDX_TIMED_OUT, &us->flags);
-	if (!test_bit(US_FLIDX_RESETTING, &us->flags)) {
-		set_bit(US_FLIDX_ABORTING, &us->flags);
+	set_bit(US_FLIDX_TIMED_OUT, &us->dflags);
+	if (!test_bit(US_FLIDX_RESETTING, &us->dflags)) {
+		set_bit(US_FLIDX_ABORTING, &us->dflags);
 		usb_stor_stop_transport(us);
 	}
 	scsi_unlock(us_to_host(us));
@@ -329,7 +332,7 @@
 	struct Scsi_Host *host = us_to_host(us);
 
 	scsi_report_device_reset(host, 0, 0);
-	if (us->flags & US_FL_SCM_MULT_TARG) {
+	if (us->fflags & US_FL_SCM_MULT_TARG) {
 		for (i = 1; i < host->max_id; ++i)
 			scsi_report_device_reset(host, 0, i);
 	}
@@ -400,7 +403,7 @@
 		pos += sprintf(pos, "       Quirks:");
 
 #define US_FLAG(name, value) \
-	if (us->flags & value) pos += sprintf(pos, " " #name);
+	if (us->fflags & value) pos += sprintf(pos, " " #name);
 US_DO_ALL_FLAGS
 #undef US_FLAG
 
diff --git a/drivers/usb/storage/scsiglue.h b/drivers/usb/storage/scsiglue.h
index 737e4fa..ffa1cca 100644
--- a/drivers/usb/storage/scsiglue.h
+++ b/drivers/usb/storage/scsiglue.h
@@ -1,8 +1,6 @@
 /* Driver for USB Mass Storage compliant devices
  * SCSI Connecting Glue Header File
  *
- * $Id: scsiglue.h,v 1.4 2000/08/25 00:13:51 mdharm Exp $
- *
  * Current development and maintenance by:
  *   (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
  *
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index 8972b17..c5a54b8 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -1,6 +1,5 @@
 /* Driver for SanDisk SDDR-09 SmartMedia reader
  *
- * $Id: sddr09.c,v 1.24 2002/04/22 03:39:43 mdharm Exp $
  *   (c) 2000, 2001 Robert Baruch (autophile@starband.net)
  *   (c) 2002 Andries Brouwer (aeb@cwi.nl)
  * Developed with the assistance of:
diff --git a/drivers/usb/storage/sddr09.h b/drivers/usb/storage/sddr09.h
index c03089a..e50033a 100644
--- a/drivers/usb/storage/sddr09.h
+++ b/drivers/usb/storage/sddr09.h
@@ -1,8 +1,6 @@
 /* Driver for SanDisk SDDR-09 SmartMedia reader
  * Header File
  *
- * $Id: sddr09.h,v 1.5 2000/08/25 00:13:51 mdharm Exp $
- *
  * Current development and maintenance by:
  *   (c) 2000 Robert Baruch (autophile@dol.net)
  *   (c) 2002 Andries Brouwer (aeb@cwi.nl)
diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
index 6d14327..0d8df75 100644
--- a/drivers/usb/storage/sddr55.c
+++ b/drivers/usb/storage/sddr55.c
@@ -1,7 +1,5 @@
 /* Driver for SanDisk SDDR-55 SmartMedia reader
  *
- * $Id:$
- *
  * SDDR55 driver v0.1:
  *
  * First release
diff --git a/drivers/usb/storage/sddr55.h b/drivers/usb/storage/sddr55.h
index d6bd32f..a815a04 100644
--- a/drivers/usb/storage/sddr55.h
+++ b/drivers/usb/storage/sddr55.h
@@ -1,8 +1,6 @@
 /* Driver for SanDisk SDDR-55 SmartMedia reader
  * Header File
  *
- * $Id:$
- *
  * Current development and maintenance by:
  *   (c) 2002 Simon Munton
  *
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
index 570c125..ae6d6481 100644
--- a/drivers/usb/storage/shuttle_usbat.c
+++ b/drivers/usb/storage/shuttle_usbat.c
@@ -1,7 +1,5 @@
 /* Driver for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable
  *
- * $Id: shuttle_usbat.c,v 1.17 2002/04/22 03:39:43 mdharm Exp $
- *
  * Current development and maintenance by:
  *   (c) 2000, 2001 Robert Baruch (autophile@starband.net)
  *   (c) 2004, 2005 Daniel Drake <dsd@gentoo.org>
diff --git a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h
index 3ddf143..d8bfc43 100644
--- a/drivers/usb/storage/shuttle_usbat.h
+++ b/drivers/usb/storage/shuttle_usbat.h
@@ -1,8 +1,6 @@
 /* Driver for SCM Microsystems USB-ATAPI cable
  * Header File
  *
- * $Id: shuttle_usbat.h,v 1.5 2000/09/17 14:44:52 groovyjava Exp $
- *
  * Current development and maintenance by:
  *   (c) 2000 Robert Baruch (autophile@dol.net)
  *   (c) 2004, 2005 Daniel Drake <dsd@gentoo.org>
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 6610d2dd..fcbbfdb 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -1,7 +1,5 @@
 /* Driver for USB Mass Storage compliant devices
  *
- * $Id: transport.c,v 1.47 2002/04/22 03:39:43 mdharm Exp $
- *
  * Current development and maintenance by:
  *   (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
  *
@@ -75,14 +73,14 @@
  * by a separate code path.)
  *
  * The abort function (usb_storage_command_abort() in scsiglue.c) first
- * sets the machine state and the ABORTING bit in us->flags to prevent
+ * sets the machine state and the ABORTING bit in us->dflags to prevent
  * new URBs from being submitted.  It then calls usb_stor_stop_transport()
- * below, which atomically tests-and-clears the URB_ACTIVE bit in us->flags
+ * below, which atomically tests-and-clears the URB_ACTIVE bit in us->dflags
  * to see if the current_urb needs to be stopped.  Likewise, the SG_ACTIVE
  * bit is tested to see if the current_sg scatter-gather request needs to be
  * stopped.  The timeout callback routine does much the same thing.
  *
- * When a disconnect occurs, the DISCONNECTING bit in us->flags is set to
+ * When a disconnect occurs, the DISCONNECTING bit in us->dflags is set to
  * prevent new URBs from being submitted, and usb_stor_stop_transport() is
  * called to stop any ongoing requests.
  *
@@ -127,8 +125,8 @@
 	long timeleft;
 	int status;
 
-	/* don't submit URBs during abort/disconnect processing */
-	if (us->flags & ABORTING_OR_DISCONNECTING)
+	/* don't submit URBs during abort processing */
+	if (test_bit(US_FLIDX_ABORTING, &us->dflags))
 		return -EIO;
 
 	/* set up data structures for the wakeup system */
@@ -159,13 +157,13 @@
 
 	/* since the URB has been submitted successfully, it's now okay
 	 * to cancel it */
-	set_bit(US_FLIDX_URB_ACTIVE, &us->flags);
+	set_bit(US_FLIDX_URB_ACTIVE, &us->dflags);
 
-	/* did an abort/disconnect occur during the submission? */
-	if (us->flags & ABORTING_OR_DISCONNECTING) {
+	/* did an abort occur during the submission? */
+	if (test_bit(US_FLIDX_ABORTING, &us->dflags)) {
 
 		/* cancel the URB, if it hasn't been cancelled already */
-		if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) {
+		if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) {
 			US_DEBUGP("-- cancelling URB\n");
 			usb_unlink_urb(us->current_urb);
 		}
@@ -175,7 +173,7 @@
 	timeleft = wait_for_completion_interruptible_timeout(
 			&urb_done, timeout ? : MAX_SCHEDULE_TIMEOUT);
  
-	clear_bit(US_FLIDX_URB_ACTIVE, &us->flags);
+	clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags);
 
 	if (timeleft <= 0) {
 		US_DEBUGP("%s -- cancelling URB\n",
@@ -419,8 +417,8 @@
 {
 	int result;
 
-	/* don't submit s-g requests during abort/disconnect processing */
-	if (us->flags & ABORTING_OR_DISCONNECTING)
+	/* don't submit s-g requests during abort processing */
+	if (test_bit(US_FLIDX_ABORTING, &us->dflags))
 		return USB_STOR_XFER_ERROR;
 
 	/* initialize the scatter-gather request block */
@@ -435,13 +433,13 @@
 
 	/* since the block has been initialized successfully, it's now
 	 * okay to cancel it */
-	set_bit(US_FLIDX_SG_ACTIVE, &us->flags);
+	set_bit(US_FLIDX_SG_ACTIVE, &us->dflags);
 
-	/* did an abort/disconnect occur during the submission? */
-	if (us->flags & ABORTING_OR_DISCONNECTING) {
+	/* did an abort occur during the submission? */
+	if (test_bit(US_FLIDX_ABORTING, &us->dflags)) {
 
 		/* cancel the request, if it hasn't been cancelled already */
-		if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->flags)) {
+		if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) {
 			US_DEBUGP("-- cancelling sg request\n");
 			usb_sg_cancel(&us->current_sg);
 		}
@@ -449,7 +447,7 @@
 
 	/* wait for the completion of the transfer */
 	usb_sg_wait(&us->current_sg);
-	clear_bit(US_FLIDX_SG_ACTIVE, &us->flags);
+	clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags);
 
 	result = us->current_sg.status;
 	if (act_len)
@@ -530,7 +528,7 @@
 	/* if the command gets aborted by the higher layers, we need to
 	 * short-circuit all other processing
 	 */
-	if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
+	if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
 		US_DEBUGP("-- command was aborted\n");
 		srb->result = DID_ABORT << 16;
 		goto Handle_Errors;
@@ -616,7 +614,7 @@
 		/* let's clean up right away */
 		scsi_eh_restore_cmnd(srb, &ses);
 
-		if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
+		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
 			US_DEBUGP("-- auto-sense aborted\n");
 			srb->result = DID_ABORT << 16;
 			goto Handle_Errors;
@@ -629,7 +627,7 @@
 			 * auto-sense is perfectly valid
 			 */
 			srb->result = DID_ERROR << 16;
-			if (!(us->flags & US_FL_SCM_MULT_TARG))
+			if (!(us->fflags & US_FL_SCM_MULT_TARG))
 				goto Handle_Errors;
 			return;
 		}
@@ -679,8 +677,8 @@
 	/* Set the RESETTING bit, and clear the ABORTING bit so that
 	 * the reset may proceed. */
 	scsi_lock(us_to_host(us));
-	set_bit(US_FLIDX_RESETTING, &us->flags);
-	clear_bit(US_FLIDX_ABORTING, &us->flags);
+	set_bit(US_FLIDX_RESETTING, &us->dflags);
+	clear_bit(US_FLIDX_ABORTING, &us->dflags);
 	scsi_unlock(us_to_host(us));
 
 	/* We must release the device lock because the pre_reset routine
@@ -695,7 +693,7 @@
 		scsi_unlock(us_to_host(us));
 		us->transport_reset(us);
 	}
-	clear_bit(US_FLIDX_RESETTING, &us->flags);
+	clear_bit(US_FLIDX_RESETTING, &us->dflags);
 }
 
 /* Stop the current URB transfer */
@@ -707,13 +705,13 @@
 	 * let's wake it up.  The test_and_clear_bit() call
 	 * guarantees that if a URB has just been submitted,
 	 * it won't be cancelled more than once. */
-	if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) {
+	if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) {
 		US_DEBUGP("-- cancelling URB\n");
 		usb_unlink_urb(us->current_urb);
 	}
 
 	/* If we are waiting for a scatter-gather operation, cancel it. */
-	if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->flags)) {
+	if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) {
 		US_DEBUGP("-- cancelling sg request\n");
 		usb_sg_cancel(&us->current_sg);
 	}
@@ -914,7 +912,7 @@
 	unsigned int cbwlen = US_BULK_CB_WRAP_LEN;
 
 	/* Take care of BULK32 devices; set extra byte to 0 */
-	if ( unlikely(us->flags & US_FL_BULK32)) {
+	if (unlikely(us->fflags & US_FL_BULK32)) {
 		cbwlen = 32;
 		us->iobuf[31] = 0;
 	}
@@ -925,7 +923,7 @@
 	bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ? 1 << 7 : 0;
 	bcb->Tag = ++us->tag;
 	bcb->Lun = srb->device->lun;
-	if (us->flags & US_FL_SCM_MULT_TARG)
+	if (us->fflags & US_FL_SCM_MULT_TARG)
 		bcb->Lun |= srb->device->id << 4;
 	bcb->Length = srb->cmd_len;
 
@@ -951,7 +949,7 @@
 	/* Some USB-IDE converter chips need a 100us delay between the
 	 * command phase and the data phase.  Some devices need a little
 	 * more than that, probably because of clock rate inaccuracies. */
-	if (unlikely(us->flags & US_FL_GO_SLOW))
+	if (unlikely(us->fflags & US_FL_GO_SLOW))
 		udelay(125);
 
 	if (transfer_length) {
@@ -1010,7 +1008,7 @@
 	US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
 			le32_to_cpu(bcs->Signature), bcs->Tag, 
 			residue, bcs->Status);
-	if (!(bcs->Tag == us->tag || (us->flags & US_FL_BULK_IGNORE_TAG)) ||
+	if (!(bcs->Tag == us->tag || (us->fflags & US_FL_BULK_IGNORE_TAG)) ||
 		bcs->Status > US_BULK_STAT_PHASE) {
 		US_DEBUGP("Bulk logical error\n");
 		return USB_STOR_TRANSPORT_ERROR;
@@ -1035,7 +1033,7 @@
 	/* try to compute the actual residue, based on how much data
 	 * was really transferred and what the device tells us */
 	if (residue) {
-		if (!(us->flags & US_FL_IGNORE_RESIDUE)) {
+		if (!(us->fflags & US_FL_IGNORE_RESIDUE)) {
 			residue = min(residue, transfer_length);
 			scsi_set_resid(srb, max(scsi_get_resid(srb),
 			                                       (int) residue));
@@ -1090,7 +1088,7 @@
 	int result;
 	int result2;
 
-	if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
+	if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
 		US_DEBUGP("No reset during disconnect\n");
 		return -EIO;
 	}
@@ -1103,12 +1101,12 @@
 		return result;
 	}
 
- 	/* Give the device some time to recover from the reset,
- 	 * but don't delay disconnect processing. */
- 	wait_event_interruptible_timeout(us->delay_wait,
- 			test_bit(US_FLIDX_DISCONNECTING, &us->flags),
- 			HZ*6);
-	if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
+	/* Give the device some time to recover from the reset,
+	 * but don't delay disconnect processing. */
+	wait_event_interruptible_timeout(us->delay_wait,
+			test_bit(US_FLIDX_DISCONNECTING, &us->dflags),
+			HZ*6);
+	if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
 		US_DEBUGP("Reset interrupted by disconnect\n");
 		return -EIO;
 	}
@@ -1170,13 +1168,12 @@
 		US_DEBUGP("unable to lock device for reset: %d\n", result);
 	else {
 		/* Were we disconnected while waiting for the lock? */
-		if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
+		if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
 			result = -EIO;
 			US_DEBUGP("No reset during disconnect\n");
 		} else {
-			result = usb_reset_composite_device(
-					us->pusb_dev, us->pusb_intf);
-			US_DEBUGP("usb_reset_composite_device returns %d\n",
+			result = usb_reset_device(us->pusb_dev);
+			US_DEBUGP("usb_reset_device returns %d\n",
 					result);
 		}
 		if (rc_lock)
diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
index ada7c2f..e70b881 100644
--- a/drivers/usb/storage/transport.h
+++ b/drivers/usb/storage/transport.h
@@ -1,8 +1,6 @@
 /* Driver for USB Mass Storage compliant devices
  * Transport Functions Header File
  *
- * $Id: transport.h,v 1.18 2002/04/21 02:57:59 mdharm Exp $
- *
  * Current development and maintenance by:
  *   (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
  *
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 39a7c11..7ae69f5 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1,8 +1,6 @@
 /* Driver for USB Mass Storage compliant devices
  * Unusual Devices File
  *
- * $Id: unusual_devs.h,v 1.32 2002/02/25 02:41:24 mdharm Exp $
- *
  * Current development and maintenance by:
  *   (c) 2000-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
  *
@@ -1234,6 +1232,17 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_NOT_LOCKABLE),
 
+/* Andrew Lunn <andrew@lunn.ch>
+ * PanDigital Digital Picture Frame. Does not like ALLOW_MEDIUM_REMOVAL
+ * on LUN 4.
+ * Note: Vend:Prod clash with "Ltd Maxell WS30 Slim Digital Camera"
+*/
+UNUSUAL_DEV(  0x0851, 0x1543, 0x0200, 0x0200,
+		"PanDigital",
+		"Photo Frame",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_NOT_LOCKABLE),
+
 /* Submitted by Jan De Luyck <lkml@kcore.org> */
 UNUSUAL_DEV(  0x08bd, 0x1100, 0x0000, 0x0000,
 		"CITIZEN",
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index e268aac..bfea851 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -1,7 +1,5 @@
 /* Driver for USB Mass Storage compliant devices
  *
- * $Id: usb.c,v 1.75 2002/04/22 03:39:43 mdharm Exp $
- *
  * Current development and maintenance by:
  *   (c) 1999-2003 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
  *
@@ -312,26 +310,27 @@
 
 	for(;;) {
 		US_DEBUGP("*** thread sleeping.\n");
-		if(down_interruptible(&us->sema))
+		if (wait_for_completion_interruptible(&us->cmnd_ready))
 			break;
-			
+
 		US_DEBUGP("*** thread awakened.\n");
 
 		/* lock the device pointers */
 		mutex_lock(&(us->dev_mutex));
 
-		/* if the device has disconnected, we are free to exit */
-		if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
-			US_DEBUGP("-- exiting\n");
-			mutex_unlock(&us->dev_mutex);
-			break;
-		}
-
 		/* lock access to the state */
 		scsi_lock(host);
 
+		/* When we are called with no command pending, we're done */
+		if (us->srb == NULL) {
+			scsi_unlock(host);
+			mutex_unlock(&us->dev_mutex);
+			US_DEBUGP("-- exiting\n");
+			break;
+		}
+
 		/* has the command timed out *already* ? */
-		if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
+		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
 			us->srb->result = DID_ABORT << 16;
 			goto SkipForAbort;
 		}
@@ -350,7 +349,7 @@
 		 * the maximum known LUN
 		 */
 		else if (us->srb->device->id && 
-				!(us->flags & US_FL_SCM_MULT_TARG)) {
+				!(us->fflags & US_FL_SCM_MULT_TARG)) {
 			US_DEBUGP("Bad target number (%d:%d)\n",
 				  us->srb->device->id, us->srb->device->lun);
 			us->srb->result = DID_BAD_TARGET << 16;
@@ -365,7 +364,7 @@
 		/* Handle those devices which need us to fake 
 		 * their inquiry data */
 		else if ((us->srb->cmnd[0] == INQUIRY) &&
-			    (us->flags & US_FL_FIX_INQUIRY)) {
+			    (us->fflags & US_FL_FIX_INQUIRY)) {
 			unsigned char data_ptr[36] = {
 			    0x00, 0x80, 0x02, 0x02,
 			    0x1F, 0x00, 0x00, 0x00};
@@ -384,12 +383,8 @@
 		/* lock access to the state */
 		scsi_lock(host);
 
-		/* did the command already complete because of a disconnect? */
-		if (!us->srb)
-			;		/* nothing to do */
-
 		/* indicate that the command is done */
-		else if (us->srb->result != DID_ABORT << 16) {
+		if (us->srb->result != DID_ABORT << 16) {
 			US_DEBUGP("scsi cmd done, result=0x%x\n", 
 				   us->srb->result);
 			us->srb->scsi_done(us->srb);
@@ -403,12 +398,12 @@
 		 * the TIMED_OUT flag, not srb->result == DID_ABORT, because
 		 * the timeout might have occurred after the command had
 		 * already completed with a different result code. */
-		if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {
+		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
 			complete(&(us->notify));
 
 			/* Allow USB transfers to resume */
-			clear_bit(US_FLIDX_ABORTING, &us->flags);
-			clear_bit(US_FLIDX_TIMED_OUT, &us->flags);
+			clear_bit(US_FLIDX_ABORTING, &us->dflags);
+			clear_bit(US_FLIDX_TIMED_OUT, &us->dflags);
 		}
 
 		/* finished working on this command */
@@ -500,9 +495,9 @@
 	us->protocol = (unusual_dev->useTransport == US_PR_DEVICE) ?
 			idesc->bInterfaceProtocol :
 			unusual_dev->useTransport;
-	us->flags = USB_US_ORIG_FLAGS(id->driver_info);
+	us->fflags = USB_US_ORIG_FLAGS(id->driver_info);
 
-	if (us->flags & US_FL_IGNORE_DEVICE) {
+	if (us->fflags & US_FL_IGNORE_DEVICE) {
 		printk(KERN_INFO USB_STORAGE "device ignored\n");
 		return -ENODEV;
 	}
@@ -512,7 +507,7 @@
 	 * disable it if we're in full-speed
 	 */
 	if (dev->speed != USB_SPEED_HIGH)
-		us->flags &= ~US_FL_GO_SLOW;
+		us->fflags &= ~US_FL_GO_SLOW;
 
 	/* Log a message if a non-generic unusual_dev entry contains an
 	 * unnecessary subclass or protocol override.  This may stimulate
@@ -533,7 +528,7 @@
 		if (unusual_dev->useTransport != US_PR_DEVICE &&
 			us->protocol == idesc->bInterfaceProtocol)
 			msg += 2;
-		if (msg >= 0 && !(us->flags & US_FL_NEED_OVERRIDE))
+		if (msg >= 0 && !(us->fflags & US_FL_NEED_OVERRIDE))
 			printk(KERN_NOTICE USB_STORAGE "This device "
 				"(%04x,%04x,%04x S %02x P %02x)"
 				" has %s in unusual_devs.h (kernel"
@@ -663,7 +658,7 @@
 	US_DEBUGP("Transport: %s\n", us->transport_name);
 
 	/* fix for single-lun devices */
-	if (us->flags & US_FL_SINGLE_LUN)
+	if (us->fflags & US_FL_SINGLE_LUN)
 		us->max_lun = 0;
 	return 0;
 }
@@ -820,12 +815,11 @@
 	US_DEBUGP("-- %s\n", __func__);
 
 	/* Tell the control thread to exit.  The SCSI host must
-	 * already have been removed so it won't try to queue
-	 * any more commands.
+	 * already have been removed and the DISCONNECTING flag set
+	 * so that we won't accept any more commands.
 	 */
 	US_DEBUGP("-- sending exit command to thread\n");
-	set_bit(US_FLIDX_DISCONNECTING, &us->flags);
-	up(&us->sema);
+	complete(&us->cmnd_ready);
 	if (us->ctl_thread)
 		kthread_stop(us->ctl_thread);
 
@@ -859,39 +853,36 @@
 	usb_set_intfdata(us->pusb_intf, NULL);
 }
 
-/* First stage of disconnect processing: stop all commands and remove
- * the host */
+/* First stage of disconnect processing: stop SCSI scanning,
+ * remove the host, and stop accepting new commands
+ */
 static void quiesce_and_remove_host(struct us_data *us)
 {
 	struct Scsi_Host *host = us_to_host(us);
 
-	/* Prevent new USB transfers, stop the current command, and
-	 * interrupt a SCSI-scan or device-reset delay */
-	scsi_lock(host);
-	set_bit(US_FLIDX_DISCONNECTING, &us->flags);
-	scsi_unlock(host);
-	usb_stor_stop_transport(us);
+	/* If the device is really gone, cut short reset delays */
+	if (us->pusb_dev->state == USB_STATE_NOTATTACHED)
+		set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
+
+	/* Prevent SCSI-scanning (if it hasn't started yet)
+	 * and wait for the SCSI-scanning thread to stop.
+	 */
+	set_bit(US_FLIDX_DONT_SCAN, &us->dflags);
 	wake_up(&us->delay_wait);
+	wait_for_completion(&us->scanning_done);
 
-	/* queuecommand won't accept any new commands and the control
-	 * thread won't execute a previously-queued command.  If there
-	 * is such a command pending, complete it with an error. */
-	mutex_lock(&us->dev_mutex);
-	if (us->srb) {
-		us->srb->result = DID_NO_CONNECT << 16;
-		scsi_lock(host);
-		us->srb->scsi_done(us->srb);
-		us->srb = NULL;
-		complete(&us->notify);		/* in case of an abort */
-		scsi_unlock(host);
-	}
-	mutex_unlock(&us->dev_mutex);
-
-	/* Now we own no commands so it's safe to remove the SCSI host */
+	/* Removing the host will perform an orderly shutdown: caches
+	 * synchronized, disks spun down, etc.
+	 */
 	scsi_remove_host(host);
 
-	/* Wait for the SCSI-scanning thread to stop */
-	wait_for_completion(&us->scanning_done);
+	/* Prevent any new commands from being accepted and cut short
+	 * reset delays.
+	 */
+	scsi_lock(host);
+	set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
+	scsi_unlock(host);
+	wake_up(&us->delay_wait);
 }
 
 /* Second stage of disconnect processing: deallocate all resources */
@@ -919,16 +910,16 @@
 		printk(KERN_DEBUG "usb-storage: waiting for device "
 				"to settle before scanning\n");
 		wait_event_freezable_timeout(us->delay_wait,
-				test_bit(US_FLIDX_DISCONNECTING, &us->flags),
+				test_bit(US_FLIDX_DONT_SCAN, &us->dflags),
 				delay_use * HZ);
 	}
 
 	/* If the device is still connected, perform the scanning */
-	if (!test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
+	if (!test_bit(US_FLIDX_DONT_SCAN, &us->dflags)) {
 
 		/* For bulk-only devices, determine the max LUN value */
 		if (us->protocol == US_PR_BULK &&
-				!(us->flags & US_FL_SINGLE_LUN)) {
+				!(us->fflags & US_FL_SINGLE_LUN)) {
 			mutex_lock(&us->dev_mutex);
 			us->max_lun = usb_stor_Bulk_max_lun(us);
 			mutex_unlock(&us->dev_mutex);
@@ -975,7 +966,7 @@
 	us = host_to_us(host);
 	memset(us, 0, sizeof(struct us_data));
 	mutex_init(&(us->dev_mutex));
-	init_MUTEX_LOCKED(&(us->sema));
+	init_completion(&us->cmnd_ready);
 	init_completion(&(us->notify));
 	init_waitqueue_head(&us->delay_wait);
 	init_completion(&us->scanning_done);
@@ -1023,6 +1014,7 @@
 	if (IS_ERR(th)) {
 		printk(KERN_WARNING USB_STORAGE 
 		       "Unable to start the device-scanning thread\n");
+		complete(&us->scanning_done);
 		quiesce_and_remove_host(us);
 		result = PTR_ERR(th);
 		goto BadDevice;
@@ -1065,6 +1057,7 @@
 	.pre_reset =	storage_pre_reset,
 	.post_reset =	storage_post_reset,
 	.id_table =	storage_usb_ids,
+	.soft_unbind =	1,
 };
 
 static int __init usb_stor_init(void)
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 8d87503..a4ad73b 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -1,8 +1,6 @@
 /* Driver for USB Mass Storage compliant devices
  * Main Header File
  *
- * $Id: usb.h,v 1.21 2002/04/21 02:57:59 mdharm Exp $
- *
  * Current development and maintenance by:
  *   (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
  *
@@ -67,16 +65,14 @@
 };
 
 
-/* Dynamic flag definitions: used in set_bit() etc. */
-#define US_FLIDX_URB_ACTIVE	18  /* 0x00040000  current_urb is in use  */
-#define US_FLIDX_SG_ACTIVE	19  /* 0x00080000  current_sg is in use   */
-#define US_FLIDX_ABORTING	20  /* 0x00100000  abort is in progress   */
-#define US_FLIDX_DISCONNECTING	21  /* 0x00200000  disconnect in progress */
-#define ABORTING_OR_DISCONNECTING	((1UL << US_FLIDX_ABORTING) | \
-					 (1UL << US_FLIDX_DISCONNECTING))
-#define US_FLIDX_RESETTING	22  /* 0x00400000  device reset in progress */
-#define US_FLIDX_TIMED_OUT	23  /* 0x00800000  SCSI midlayer timed out  */
-
+/* Dynamic bitflag definitions (us->dflags): used in set_bit() etc. */
+#define US_FLIDX_URB_ACTIVE	0	/* current_urb is in use    */
+#define US_FLIDX_SG_ACTIVE	1	/* current_sg is in use     */
+#define US_FLIDX_ABORTING	2	/* abort is in progress     */
+#define US_FLIDX_DISCONNECTING	3	/* disconnect in progress   */
+#define US_FLIDX_RESETTING	4	/* device reset in progress */
+#define US_FLIDX_TIMED_OUT	5	/* SCSI midlayer timed out  */
+#define US_FLIDX_DONT_SCAN	6	/* don't scan (disconnect)  */
 
 #define USB_STOR_STRING_LEN 32
 
@@ -109,7 +105,8 @@
 	struct usb_device	*pusb_dev;	 /* this usb_device */
 	struct usb_interface	*pusb_intf;	 /* this interface */
 	struct us_unusual_dev   *unusual_dev;	 /* device-filter entry     */
-	unsigned long		flags;		 /* from filter initially */
+	unsigned long		fflags;		 /* fixed flags from filter */
+	unsigned long		dflags;		 /* dynamic atomic bitflags */
 	unsigned int		send_bulk_pipe;	 /* cached pipe values */
 	unsigned int		recv_bulk_pipe;
 	unsigned int		send_ctrl_pipe;
@@ -147,7 +144,7 @@
 	struct task_struct	*ctl_thread;	 /* the control thread   */
 
 	/* mutual exclusion and synchronization structures */
-	struct semaphore	sema;		 /* to sleep thread on	    */
+	struct completion	cmnd_ready;	 /* to sleep thread on	    */
 	struct completion	notify;		 /* thread begin/end	    */
 	wait_queue_head_t	delay_wait;	 /* wait during scan, reset */
 	struct completion	scanning_done;	 /* wait for scan thread    */
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index 24ee96c..07b6add 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -1872,7 +1872,7 @@
 	struct fb_info *info = pci_get_drvdata(pdev);
 	struct aty128fb_par *par = info->par;
 	struct fb_var_screeninfo var;
-	char video_card[DEVICE_NAME_SIZE];
+	char video_card[50];
 	u8 chip_rev;
 	u32 dac;
 
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index c347e38..ccbfffd 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -289,7 +289,7 @@
 	struct radeon_regs 	state;
 	struct radeon_regs	init_state;
 
-	char			name[DEVICE_NAME_SIZE];
+	char			name[50];
 
 	unsigned long		mmio_base_phys;
 	unsigned long		fb_base_phys;
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 97aff8d..4be3b46 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -3586,7 +3586,8 @@
 
 	acquire_console_sem();
 	fb_register_client(&fbcon_event_notifier);
-	fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), "fbcon");
+	fbcon_device = device_create_drvdata(fb_class, NULL, MKDEV(0, 0),
+					     NULL, "fbcon");
 
 	if (IS_ERR(fbcon_device)) {
 		printk(KERN_WARNING "Unable to create device "
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 33ebdb1..1cd5071 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1439,8 +1439,9 @@
 			break;
 	fb_info->node = i;
 
-	fb_info->dev = device_create(fb_class, fb_info->device,
-				     MKDEV(FB_MAJOR, i), "fb%d", i);
+	fb_info->dev = device_create_drvdata(fb_class, fb_info->device,
+					     MKDEV(FB_MAJOR, i), NULL,
+					     "fb%d", i);
 	if (IS_ERR(fb_info->dev)) {
 		/* Not fatal */
 		printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index d7b3dcc..e1d9eeb 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -47,6 +47,7 @@
 	cmap_M3B,		/* ATI Rage Mobility M3 Head B */
 	cmap_radeon,		/* ATI Radeon */
 	cmap_gxt2000,		/* IBM GXT2000 */
+	cmap_avivo,		/* ATI R5xx */
 };
 
 struct offb_par {
@@ -58,26 +59,36 @@
 
 struct offb_par default_par;
 
-    /*
-     *  Interface used by the world
-     */
-
-static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			  u_int transp, struct fb_info *info);
-static int offb_blank(int blank, struct fb_info *info);
-
 #ifdef CONFIG_PPC32
 extern boot_infos_t *boot_infos;
 #endif
 
-static struct fb_ops offb_ops = {
-	.owner		= THIS_MODULE,
-	.fb_setcolreg	= offb_setcolreg,
-	.fb_blank	= offb_blank,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
-	.fb_imageblit	= cfb_imageblit,
-};
+/* Definitions used by the Avivo palette hack */
+#define AVIVO_DC_LUT_RW_SELECT                  0x6480
+#define AVIVO_DC_LUT_RW_MODE                    0x6484
+#define AVIVO_DC_LUT_RW_INDEX                   0x6488
+#define AVIVO_DC_LUT_SEQ_COLOR                  0x648c
+#define AVIVO_DC_LUT_PWL_DATA                   0x6490
+#define AVIVO_DC_LUT_30_COLOR                   0x6494
+#define AVIVO_DC_LUT_READ_PIPE_SELECT           0x6498
+#define AVIVO_DC_LUT_WRITE_EN_MASK              0x649c
+#define AVIVO_DC_LUT_AUTOFILL                   0x64a0
+
+#define AVIVO_DC_LUTA_CONTROL                   0x64c0
+#define AVIVO_DC_LUTA_BLACK_OFFSET_BLUE         0x64c4
+#define AVIVO_DC_LUTA_BLACK_OFFSET_GREEN        0x64c8
+#define AVIVO_DC_LUTA_BLACK_OFFSET_RED          0x64cc
+#define AVIVO_DC_LUTA_WHITE_OFFSET_BLUE         0x64d0
+#define AVIVO_DC_LUTA_WHITE_OFFSET_GREEN        0x64d4
+#define AVIVO_DC_LUTA_WHITE_OFFSET_RED          0x64d8
+
+#define AVIVO_DC_LUTB_CONTROL                   0x6cc0
+#define AVIVO_DC_LUTB_BLACK_OFFSET_BLUE         0x6cc4
+#define AVIVO_DC_LUTB_BLACK_OFFSET_GREEN        0x6cc8
+#define AVIVO_DC_LUTB_BLACK_OFFSET_RED          0x6ccc
+#define AVIVO_DC_LUTB_WHITE_OFFSET_BLUE         0x6cd0
+#define AVIVO_DC_LUTB_WHITE_OFFSET_GREEN        0x6cd4
+#define AVIVO_DC_LUTB_WHITE_OFFSET_RED          0x6cd8
 
     /*
      *  Set a single color register. The values supplied are already
@@ -160,6 +171,17 @@
 		out_le32(((unsigned __iomem *) par->cmap_adr) + regno,
 			 (red << 16 | green << 8 | blue));
 		break;
+	case cmap_avivo:
+		/* Write to both LUTs for now */
+		writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+		writeb(regno, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
+		writel(((red) << 22) | ((green) << 12) | ((blue) << 2),
+		       par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
+		writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+		writeb(regno, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
+		writel(((red) << 22) | ((green) << 12) | ((blue) << 2),
+		       par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
+		break;
 	}
 
 	return 0;
@@ -216,12 +238,59 @@
 				out_le32(((unsigned __iomem *) par->cmap_adr) + i,
 					 0);
 				break;
+			case cmap_avivo:
+				writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+				writeb(i, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
+				writel(0, par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
+				writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+				writeb(i, par->cmap_adr + AVIVO_DC_LUT_RW_INDEX);
+				writel(0, par->cmap_adr + AVIVO_DC_LUT_30_COLOR);
+				break;
 			}
 	} else
 		fb_set_cmap(&info->cmap, info);
 	return 0;
 }
 
+static int offb_set_par(struct fb_info *info)
+{
+	struct offb_par *par = (struct offb_par *) info->par;
+
+	/* On avivo, initialize palette control */
+	if (par->cmap_type == cmap_avivo) {
+		writel(0, par->cmap_adr + AVIVO_DC_LUTA_CONTROL);
+		writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_BLUE);
+		writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_GREEN);
+		writel(0, par->cmap_adr + AVIVO_DC_LUTA_BLACK_OFFSET_RED);
+		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_BLUE);
+		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_GREEN);
+		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTA_WHITE_OFFSET_RED);
+		writel(0, par->cmap_adr + AVIVO_DC_LUTB_CONTROL);
+		writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_BLUE);
+		writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_GREEN);
+		writel(0, par->cmap_adr + AVIVO_DC_LUTB_BLACK_OFFSET_RED);
+		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_BLUE);
+		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_GREEN);
+		writel(0x0000ffff, par->cmap_adr + AVIVO_DC_LUTB_WHITE_OFFSET_RED);
+		writel(1, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+		writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_MODE);
+		writel(0x0000003f, par->cmap_adr + AVIVO_DC_LUT_WRITE_EN_MASK);
+		writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_SELECT);
+		writel(0, par->cmap_adr + AVIVO_DC_LUT_RW_MODE);
+		writel(0x0000003f, par->cmap_adr + AVIVO_DC_LUT_WRITE_EN_MASK);
+	}
+	return 0;
+}
+
+static struct fb_ops offb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_setcolreg	= offb_setcolreg,
+	.fb_set_par	= offb_set_par,
+	.fb_blank	= offb_blank,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
 
 static void __iomem *offb_map_reg(struct device_node *np, int index,
 				  unsigned long offset, unsigned long size)
@@ -245,6 +314,59 @@
 	return ioremap(taddr + offset, size);
 }
 
+static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp,
+				    const char *name, unsigned long address)
+{
+	struct offb_par *par = (struct offb_par *) info->par;
+
+	if (dp && !strncmp(name, "ATY,Rage128", 11)) {
+		par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
+		if (par->cmap_adr)
+			par->cmap_type = cmap_r128;
+	} else if (dp && (!strncmp(name, "ATY,RageM3pA", 12)
+			  || !strncmp(name, "ATY,RageM3p12A", 14))) {
+		par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
+		if (par->cmap_adr)
+			par->cmap_type = cmap_M3A;
+	} else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) {
+		par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
+		if (par->cmap_adr)
+			par->cmap_type = cmap_M3B;
+	} else if (dp && !strncmp(name, "ATY,Rage6", 9)) {
+		par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff);
+		if (par->cmap_adr)
+			par->cmap_type = cmap_radeon;
+	} else if (!strncmp(name, "ATY,", 4)) {
+		unsigned long base = address & 0xff000000UL;
+		par->cmap_adr =
+			ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
+		par->cmap_data = par->cmap_adr + 1;
+		par->cmap_type = cmap_m64;
+	} else if (dp && (of_device_is_compatible(dp, "pci1014,b7") ||
+			  of_device_is_compatible(dp, "pci1014,21c"))) {
+		par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000);
+		if (par->cmap_adr)
+			par->cmap_type = cmap_gxt2000;
+	} else if (dp && !strncmp(name, "vga,Display-", 12)) {
+		/* Look for AVIVO initialized by SLOF */
+		struct device_node *pciparent = of_get_parent(dp);
+		const u32 *vid, *did;
+		vid = of_get_property(pciparent, "vendor-id", NULL);
+		did = of_get_property(pciparent, "device-id", NULL);
+		/* This will match most R5xx */
+		if (vid && did && *vid == 0x1002 &&
+		    ((*did >= 0x7100 && *did < 0x7800) ||
+		     (*did >= 0x9400))) {
+			par->cmap_adr = offb_map_reg(pciparent, 2, 0, 0x10000);
+			if (par->cmap_adr)
+				par->cmap_type = cmap_avivo;
+		}
+		of_node_put(pciparent);
+	}
+	info->fix.visual = (par->cmap_type != cmap_unknown) ?
+		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR;
+}
+
 static void __init offb_init_fb(const char *name, const char *full_name,
 				int width, int height, int depth,
 				int pitch, unsigned long address,
@@ -283,6 +405,7 @@
 
 	fix = &info->fix;
 	var = &info->var;
+	info->par = par;
 
 	strcpy(fix->id, "OFfb ");
 	strncat(fix->id, name, sizeof(fix->id) - sizeof("OFfb "));
@@ -298,39 +421,9 @@
 	fix->type_aux = 0;
 
 	par->cmap_type = cmap_unknown;
-	if (depth == 8) {
-		if (dp && !strncmp(name, "ATY,Rage128", 11)) {
-			par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
-			if (par->cmap_adr)
-				par->cmap_type = cmap_r128;
-		} else if (dp && (!strncmp(name, "ATY,RageM3pA", 12)
-				  || !strncmp(name, "ATY,RageM3p12A", 14))) {
-			par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
-			if (par->cmap_adr)
-				par->cmap_type = cmap_M3A;
-		} else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) {
-			par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
-			if (par->cmap_adr)
-				par->cmap_type = cmap_M3B;
-		} else if (dp && !strncmp(name, "ATY,Rage6", 9)) {
-			par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff);
-			if (par->cmap_adr)
-				par->cmap_type = cmap_radeon;
-		} else if (!strncmp(name, "ATY,", 4)) {
-			unsigned long base = address & 0xff000000UL;
-			par->cmap_adr =
-			    ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
-			par->cmap_data = par->cmap_adr + 1;
-			par->cmap_type = cmap_m64;
-		} else if (dp && (of_device_is_compatible(dp, "pci1014,b7") ||
-				  of_device_is_compatible(dp, "pci1014,21c"))) {
-			par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000);
-			if (par->cmap_adr)
-				par->cmap_type = cmap_gxt2000;
-		}
-		fix->visual = (par->cmap_type != cmap_unknown) ?
-			FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR;
-	} else
+	if (depth == 8)
+		offb_init_palette_hacks(info, dp, name, address);
+	else
 		fix->visual = FB_VISUAL_TRUECOLOR;
 
 	var->xoffset = var->yoffset = 0;
@@ -395,7 +488,6 @@
 
 	info->fbops = &offb_ops;
 	info->screen_base = ioremap(address, fix->smem_len);
-	info->par = par;
 	info->pseudo_palette = (void *) (info + 1);
 	info->flags = FBINFO_DEFAULT | foreign_endian;
 
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index dc3af1c..4b5d8077 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -1297,6 +1297,7 @@
 
 static struct ps3_system_bus_driver ps3fb_driver = {
 	.match_id	= PS3_MATCH_ID_GRAPHICS,
+	.match_sub_id	= PS3_MATCH_SUB_ID_FB,
 	.core.name	= DEVICE_NAME,
 	.core.owner	= THIS_MODULE,
 	.probe		= ps3fb_probe,
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index d074626..bb25143 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -227,6 +227,22 @@
 	case 4:  ret = LCCR3_4BPP; break;
 	case 8:  ret = LCCR3_8BPP; break;
 	case 16: ret = LCCR3_16BPP; break;
+	case 24:
+		switch (var->red.length + var->green.length +
+				var->blue.length + var->transp.length) {
+		case 18: ret = LCCR3_18BPP_P | LCCR3_PDFOR_3; break;
+		case 19: ret = LCCR3_19BPP_P; break;
+		}
+		break;
+	case 32:
+		switch (var->red.length + var->green.length +
+				var->blue.length + var->transp.length) {
+		case 18: ret = LCCR3_18BPP | LCCR3_PDFOR_3; break;
+		case 19: ret = LCCR3_19BPP; break;
+		case 24: ret = LCCR3_24BPP | LCCR3_PDFOR_3; break;
+		case 25: ret = LCCR3_25BPP; break;
+		}
+		break;
 	}
 	return ret;
 }
@@ -345,6 +361,41 @@
 		var->green.offset = 5;  var->green.length = 6;
 		var->blue.offset  = 0;  var->blue.length  = 5;
 		var->transp.offset = var->transp.length = 0;
+	} else if (var->bits_per_pixel > 16) {
+		struct pxafb_mode_info *mode;
+
+		mode = pxafb_getmode(inf, var);
+		if (!mode)
+			return -EINVAL;
+
+		switch (mode->depth) {
+		case 18: /* RGB666 */
+			var->transp.offset = var->transp.length     = 0;
+			var->red.offset	   = 12; var->red.length    = 6;
+			var->green.offset  = 6;  var->green.length  = 6;
+			var->blue.offset   = 0;  var->blue.length   = 6;
+			break;
+		case 19: /* RGBT666 */
+			var->transp.offset = 18; var->transp.length = 1;
+			var->red.offset	   = 12; var->red.length    = 6;
+			var->green.offset  = 6;  var->green.length  = 6;
+			var->blue.offset   = 0;  var->blue.length   = 6;
+			break;
+		case 24: /* RGB888 */
+			var->transp.offset = var->transp.length     = 0;
+			var->red.offset	   = 16; var->red.length    = 8;
+			var->green.offset  = 8;  var->green.length  = 8;
+			var->blue.offset   = 0;  var->blue.length   = 8;
+			break;
+		case 25: /* RGBT888 */
+			var->transp.offset = 24; var->transp.length = 1;
+			var->red.offset	   = 16; var->red.length    = 8;
+			var->green.offset  = 8;  var->green.length  = 8;
+			var->blue.offset   = 0;  var->blue.length   = 8;
+			break;
+		default:
+			return -EINVAL;
+		}
 	} else {
 		var->red.offset = var->green.offset = 0;
 		var->blue.offset = var->transp.offset = 0;
@@ -376,7 +427,7 @@
 	struct pxafb_info *fbi = (struct pxafb_info *)info;
 	struct fb_var_screeninfo *var = &info->var;
 
-	if (var->bits_per_pixel == 16)
+	if (var->bits_per_pixel >= 16)
 		fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
 	else if (!fbi->cmap_static)
 		fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
@@ -391,7 +442,7 @@
 
 	fbi->fb.fix.line_length = var->xres_virtual *
 				  var->bits_per_pixel / 8;
-	if (var->bits_per_pixel == 16)
+	if (var->bits_per_pixel >= 16)
 		fbi->palette_size = 0;
 	else
 		fbi->palette_size = var->bits_per_pixel == 1 ?
@@ -404,7 +455,7 @@
 	 */
 	pxafb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR);
 
-	if (fbi->fb.var.bits_per_pixel == 16)
+	if (fbi->fb.var.bits_per_pixel >= 16)
 		fb_dealloc_cmap(&fbi->fb.cmap);
 	else
 		fb_alloc_cmap(&fbi->fb.cmap, 1<<fbi->fb.var.bits_per_pixel, 0);
@@ -831,6 +882,8 @@
 		case 4:
 		case 8:
 		case 16:
+		case 24:
+		case 32:
 			break;
 		default:
 			printk(KERN_ERR "%s: invalid bit depth %d\n",
@@ -968,6 +1021,11 @@
 
 	for (gpio = 58; ldd_bits; gpio++, ldd_bits--)
 		pxa_gpio_mode(gpio | GPIO_ALT_FN_2_OUT);
+	/* 18 bit interface */
+	if (fbi->fb.var.bits_per_pixel > 16) {
+		pxa_gpio_mode(86 | GPIO_ALT_FN_2_OUT);
+		pxa_gpio_mode(87 | GPIO_ALT_FN_2_OUT);
+	}
 	pxa_gpio_mode(GPIO74_LCD_FCLK_MD);
 	pxa_gpio_mode(GPIO75_LCD_LCLK_MD);
 	pxa_gpio_mode(GPIO76_LCD_PCLK_MD);
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index 591bc29..d4427cb 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -610,6 +610,7 @@
 }
 
 static ssize_t store_target_kb(struct sys_device *dev,
+			       struct sysdev_attribute *attr,
 			       const char *buf,
 			       size_t count)
 {
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 332dd637..0e0c285 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -734,6 +734,33 @@
 	}
 }
 
+/* Clear an irq's pending state, in preparation for polling on it */
+void xen_clear_irq_pending(int irq)
+{
+	int evtchn = evtchn_from_irq(irq);
+
+	if (VALID_EVTCHN(evtchn))
+		clear_evtchn(evtchn);
+}
+
+/* Poll waiting for an irq to become pending.  In the usual case, the
+   irq will be disabled so it won't deliver an interrupt. */
+void xen_poll_irq(int irq)
+{
+	evtchn_port_t evtchn = evtchn_from_irq(irq);
+
+	if (VALID_EVTCHN(evtchn)) {
+		struct sched_poll poll;
+
+		poll.nr_ports = 1;
+		poll.timeout = 0;
+		poll.ports = &evtchn;
+
+		if (HYPERVISOR_sched_op(SCHEDOP_poll, &poll) != 0)
+			BUG();
+	}
+}
+
 void xen_irq_resume(void)
 {
 	unsigned int cpu, irq, evtchn;
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
index 5b546e3..a5bc91a 100644
--- a/drivers/xen/manage.c
+++ b/drivers/xen/manage.c
@@ -63,11 +63,12 @@
 	gnttab_resume();
 	xen_mm_unpin_all();
 
-	device_power_up();
+	device_power_up(PMSG_RESUME);
 
 	if (!*cancelled) {
 		xen_irq_resume();
 		xen_console_resume();
+		xen_timer_resume();
 	}
 
 	return 0;
@@ -107,12 +108,13 @@
 		goto out;
 	}
 
-	if (!cancelled)
+	if (!cancelled) {
+		xen_arch_resume();
 		xenbus_resume();
-	else
+	} else
 		xenbus_suspend_cancel();
 
-	device_resume();
+	device_resume(PMSG_RESUME);
 
 	/* Make sure timer events get retriggered on all CPUs */
 	clock_was_set();
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index d48ff5f3..639d2d8 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -204,6 +204,7 @@
 	NEW_AUX_ENT(AT_GID, tsk->gid);
 	NEW_AUX_ENT(AT_EGID, tsk->egid);
  	NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm));
+	NEW_AUX_ENT(AT_EXECFN, bprm->exec);
 	if (k_platform) {
 		NEW_AUX_ENT(AT_PLATFORM,
 			    (elf_addr_t)(unsigned long)u_platform);
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index e3eb355..40c36f7 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -362,8 +362,9 @@
 		goto out_chrdev;
 	}		
 	for (i = 0; i < MAX_CODADEVS; i++)
-		device_create(coda_psdev_class, NULL,
-			      MKDEV(CODA_PSDEV_MAJOR,i), "cfs%d", i);
+		device_create_drvdata(coda_psdev_class, NULL,
+				      MKDEV(CODA_PSDEV_MAJOR, i),
+				      NULL, "cfs%d", i);
 	coda_sysctl_init();
 	goto out;
 
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index e9602d8..08e28c9 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -309,32 +309,10 @@
 }
 EXPORT_SYMBOL_GPL(debugfs_create_symlink);
 
-/**
- * debugfs_remove - removes a file or directory from the debugfs filesystem
- * @dentry: a pointer to a the dentry of the file or directory to be
- *          removed.
- *
- * This function removes a file or directory in debugfs that was previously
- * created with a call to another debugfs function (like
- * debugfs_create_file() or variants thereof.)
- *
- * This function is required to be called in order for the file to be
- * removed, no automatic cleanup of files will happen when a module is
- * removed, you are responsible here.
- */
-void debugfs_remove(struct dentry *dentry)
+static void __debugfs_remove(struct dentry *dentry, struct dentry *parent)
 {
-	struct dentry *parent;
 	int ret = 0;
-	
-	if (!dentry)
-		return;
 
-	parent = dentry->d_parent;
-	if (!parent || !parent->d_inode)
-		return;
-
-	mutex_lock(&parent->d_inode->i_mutex);
 	if (debugfs_positive(dentry)) {
 		if (dentry->d_inode) {
 			dget(dentry);
@@ -354,12 +332,112 @@
 			dput(dentry);
 		}
 	}
+}
+
+/**
+ * debugfs_remove - removes a file or directory from the debugfs filesystem
+ * @dentry: a pointer to a the dentry of the file or directory to be
+ *          removed.
+ *
+ * This function removes a file or directory in debugfs that was previously
+ * created with a call to another debugfs function (like
+ * debugfs_create_file() or variants thereof.)
+ *
+ * This function is required to be called in order for the file to be
+ * removed, no automatic cleanup of files will happen when a module is
+ * removed, you are responsible here.
+ */
+void debugfs_remove(struct dentry *dentry)
+{
+	struct dentry *parent;
+	
+	if (!dentry)
+		return;
+
+	parent = dentry->d_parent;
+	if (!parent || !parent->d_inode)
+		return;
+
+	mutex_lock(&parent->d_inode->i_mutex);
+	__debugfs_remove(dentry, parent);
 	mutex_unlock(&parent->d_inode->i_mutex);
 	simple_release_fs(&debugfs_mount, &debugfs_mount_count);
 }
 EXPORT_SYMBOL_GPL(debugfs_remove);
 
 /**
+ * debugfs_remove_recursive - recursively removes a directory
+ * @dentry: a pointer to a the dentry of the directory to be removed.
+ *
+ * This function recursively removes a directory tree in debugfs that
+ * was previously created with a call to another debugfs function
+ * (like debugfs_create_file() or variants thereof.)
+ *
+ * This function is required to be called in order for the file to be
+ * removed, no automatic cleanup of files will happen when a module is
+ * removed, you are responsible here.
+ */
+void debugfs_remove_recursive(struct dentry *dentry)
+{
+	struct dentry *child;
+	struct dentry *parent;
+
+	if (!dentry)
+		return;
+
+	parent = dentry->d_parent;
+	if (!parent || !parent->d_inode)
+		return;
+
+	parent = dentry;
+	mutex_lock(&parent->d_inode->i_mutex);
+
+	while (1) {
+		/*
+		 * When all dentries under "parent" has been removed,
+		 * walk up the tree until we reach our starting point.
+		 */
+		if (list_empty(&parent->d_subdirs)) {
+			mutex_unlock(&parent->d_inode->i_mutex);
+			if (parent == dentry)
+				break;
+			parent = parent->d_parent;
+			mutex_lock(&parent->d_inode->i_mutex);
+		}
+		child = list_entry(parent->d_subdirs.next, struct dentry,
+				d_u.d_child);
+
+		/*
+		 * If "child" isn't empty, walk down the tree and
+		 * remove all its descendants first.
+		 */
+		if (!list_empty(&child->d_subdirs)) {
+			mutex_unlock(&parent->d_inode->i_mutex);
+			parent = child;
+			mutex_lock(&parent->d_inode->i_mutex);
+			continue;
+		}
+		__debugfs_remove(child, parent);
+		if (parent->d_subdirs.next == &child->d_u.d_child) {
+			/*
+			 * Avoid infinite loop if we fail to remove
+			 * one dentry.
+			 */
+			mutex_unlock(&parent->d_inode->i_mutex);
+			break;
+		}
+		simple_release_fs(&debugfs_mount, &debugfs_mount_count);
+	}
+
+	parent = dentry->d_parent;
+	mutex_lock(&parent->d_inode->i_mutex);
+	__debugfs_remove(dentry, parent);
+	mutex_unlock(&parent->d_inode->i_mutex);
+	simple_release_fs(&debugfs_mount, &debugfs_mount_count);
+}
+EXPORT_SYMBOL_GPL(debugfs_remove_recursive);
+
+/**
  * debugfs_rename - rename a file/directory in the debugfs filesystem
  * @old_dir: a pointer to the parent dentry for the renamed object. This
  *          should be a directory dentry.
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 6149e4b..efef715 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -401,7 +401,7 @@
 	disk->dev.parent = disk->driverfs_dev;
 	disk->dev.devt = MKDEV(disk->major, disk->first_minor);
 
-	strlcpy(disk->dev.bus_id, disk->disk_name, KOBJ_NAME_LEN);
+	strlcpy(disk->dev.bus_id, disk->disk_name, BUS_ID_SIZE);
 	/* ewww... some of these buggers have / in the name... */
 	s = strchr(disk->dev.bus_id, '/');
 	if (s)
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
index b224a28..7bc296f 100644
--- a/fs/proc/proc_net.c
+++ b/fs/proc/proc_net.c
@@ -27,6 +27,11 @@
 #include "internal.h"
 
 
+static struct net *get_proc_net(const struct inode *inode)
+{
+	return maybe_get_net(PDE_NET(PDE(inode)));
+}
+
 int seq_open_net(struct inode *ino, struct file *f,
 		 const struct seq_operations *ops, int size)
 {
@@ -185,12 +190,6 @@
 }
 EXPORT_SYMBOL_GPL(proc_net_remove);
 
-struct net *get_proc_net(const struct inode *inode)
-{
-	return maybe_get_net(PDE_NET(PDE(inode)));
-}
-EXPORT_SYMBOL_GPL(get_proc_net);
-
 static __net_init int proc_net_ns_init(struct net *net)
 {
 	struct proc_dir_entry *netd, *net_statd;
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 164bd9f..7546a91 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -636,7 +636,7 @@
 	struct pagemapread pm;
 	int pagecount;
 	int ret = -ESRCH;
-	struct mm_walk pagemap_walk;
+	struct mm_walk pagemap_walk = {};
 	unsigned long src;
 	unsigned long svpfn;
 	unsigned long start_vaddr;
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 8c0e4b9..c1a7efb 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -398,6 +398,43 @@
 }
 
 /**
+ *	__sysfs_add_one - add sysfs_dirent to parent without warning
+ *	@acxt: addrm context to use
+ *	@sd: sysfs_dirent to be added
+ *
+ *	Get @acxt->parent_sd and set sd->s_parent to it and increment
+ *	nlink of parent inode if @sd is a directory and link into the
+ *	children list of the parent.
+ *
+ *	This function should be called between calls to
+ *	sysfs_addrm_start() and sysfs_addrm_finish() and should be
+ *	passed the same @acxt as passed to sysfs_addrm_start().
+ *
+ *	LOCKING:
+ *	Determined by sysfs_addrm_start().
+ *
+ *	RETURNS:
+ *	0 on success, -EEXIST if entry with the given name already
+ *	exists.
+ */
+int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
+{
+	if (sysfs_find_dirent(acxt->parent_sd, sd->s_name))
+		return -EEXIST;
+
+	sd->s_parent = sysfs_get(acxt->parent_sd);
+
+	if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode)
+		inc_nlink(acxt->parent_inode);
+
+	acxt->cnt++;
+
+	sysfs_link_sibling(sd);
+
+	return 0;
+}
+
+/**
  *	sysfs_add_one - add sysfs_dirent to parent
  *	@acxt: addrm context to use
  *	@sd: sysfs_dirent to be added
@@ -419,19 +456,15 @@
  */
 int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
 {
-	if (sysfs_find_dirent(acxt->parent_sd, sd->s_name))
-		return -EEXIST;
+	int ret;
 
-	sd->s_parent = sysfs_get(acxt->parent_sd);
-
-	if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode)
-		inc_nlink(acxt->parent_inode);
-
-	acxt->cnt++;
-
-	sysfs_link_sibling(sd);
-
-	return 0;
+	ret = __sysfs_add_one(acxt, sd);
+	if (ret == -EEXIST) {
+		printk(KERN_WARNING "sysfs: duplicate filename '%s' "
+		       "can not be created\n", sd->s_name);
+		WARN_ON(1);
+	}
+	return ret;
 }
 
 /**
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index e7735f6..3f07893 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -14,6 +14,7 @@
 #include <linux/kobject.h>
 #include <linux/kallsyms.h>
 #include <linux/slab.h>
+#include <linux/fsnotify.h>
 #include <linux/namei.h>
 #include <linux/poll.h>
 #include <linux/list.h>
@@ -585,9 +586,11 @@
 
 	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
 	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
-	rc = notify_change(victim, &newattrs);
+	newattrs.ia_ctime = current_fs_time(inode->i_sb);
+	rc = sysfs_setattr(victim, &newattrs);
 
 	if (rc == 0) {
+		fsnotify_change(victim, newattrs.ia_valid);
 		mutex_lock(&sysfs_mutex);
 		victim_sd->s_mode = newattrs.ia_mode;
 		mutex_unlock(&sysfs_mutex);
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index 817f596..a3ba217 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -19,13 +19,8 @@
 
 #include "sysfs.h"
 
-/**
- *	sysfs_create_link - create symlink between two objects.
- *	@kobj:	object whose directory we're creating the link in.
- *	@target:	object we're pointing to.
- *	@name:		name of the symlink.
- */
-int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name)
+static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target,
+				const char *name, int warn)
 {
 	struct sysfs_dirent *parent_sd = NULL;
 	struct sysfs_dirent *target_sd = NULL;
@@ -65,7 +60,10 @@
 	target_sd = NULL;	/* reference is now owned by the symlink */
 
 	sysfs_addrm_start(&acxt, parent_sd);
-	error = sysfs_add_one(&acxt, sd);
+	if (warn)
+		error = sysfs_add_one(&acxt, sd);
+	else
+		error = __sysfs_add_one(&acxt, sd);
 	sysfs_addrm_finish(&acxt);
 
 	if (error)
@@ -80,6 +78,33 @@
 }
 
 /**
+ *	sysfs_create_link - create symlink between two objects.
+ *	@kobj:	object whose directory we're creating the link in.
+ *	@target:	object we're pointing to.
+ *	@name:		name of the symlink.
+ */
+int sysfs_create_link(struct kobject *kobj, struct kobject *target,
+		      const char *name)
+{
+	return sysfs_do_create_link(kobj, target, name, 1);
+}
+
+/**
+ *	sysfs_create_link_nowarn - create symlink between two objects.
+ *	@kobj:	object whose directory we're creating the link in.
+ *	@target:	object we're pointing to.
+ *	@name:		name of the symlink.
+ *
+ *	This function does the same as sysf_create_link(), but it
+ *	doesn't warn if the link already exists.
+ */
+int sysfs_create_link_nowarn(struct kobject *kobj, struct kobject *target,
+			     const char *name)
+{
+	return sysfs_do_create_link(kobj, target, name, 0);
+}
+
+/**
  *	sysfs_remove_link - remove symlink in object's directory.
  *	@kobj:	object we're acting for.
  *	@name:	name of the symlink to remove.
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index ce4e15f8..a5db496 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -107,6 +107,7 @@
 void sysfs_put_active_two(struct sysfs_dirent *sd);
 void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
 		       struct sysfs_dirent *parent_sd);
+int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd);
 int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd);
 void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd);
 void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt);
diff --git a/include/asm-arm/arch-iop13xx/adma.h b/include/asm-arm/arch-iop13xx/adma.h
index 90d14ee..ef4f5da 100644
--- a/include/asm-arm/arch-iop13xx/adma.h
+++ b/include/asm-arm/arch-iop13xx/adma.h
@@ -198,17 +198,13 @@
 static inline int
 iop_chan_xor_slot_count(size_t len, int src_cnt, int *slots_per_op)
 {
-	int num_slots;
-	/* slots_to_find = 1 for basic descriptor + 1 per 4 sources above 1
-	 * (1 source => 8 bytes) (1 slot => 32 bytes)
-	 */
-	num_slots = 1 + (((src_cnt - 1) << 3) >> 5);
-	if (((src_cnt - 1) << 3) & 0x1f)
-		num_slots++;
-
-	*slots_per_op = num_slots;
-
-	return num_slots;
+	static const char slot_count_table[] = { 1, 2, 2, 2,
+						 2, 3, 3, 3,
+						 3, 4, 4, 4,
+						 4, 5, 5, 5,
+						};
+	*slots_per_op = slot_count_table[src_cnt - 1];
+	return *slots_per_op;
 }
 
 #define ADMA_MAX_BYTE_COUNT	(16 * 1024 * 1024)
diff --git a/include/asm-arm/arch-pxa/cm-x270.h b/include/asm-arm/arch-pxa/cm-x270.h
deleted file mode 100644
index f8fac9e..0000000
--- a/include/asm-arm/arch-pxa/cm-x270.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * linux/include/asm/arch-pxa/cm-x270.h
- *
- * Copyright Compulab Ltd., 2003, 2007
- * Mike Rapoport <mike@compulab.co.il>
- *
- * 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.
- */
-
-
-/* CM-x270 device physical addresses */
-#define CMX270_CS1_PHYS		(PXA_CS1_PHYS)
-#define MARATHON_PHYS		(PXA_CS2_PHYS)
-#define CMX270_IDE104_PHYS	(PXA_CS3_PHYS)
-#define CMX270_IT8152_PHYS	(PXA_CS4_PHYS)
-
-/* Statically mapped regions */
-#define CMX270_VIRT_BASE		(0xe8000000)
-#define CMX270_IT8152_VIRT		(CMX270_VIRT_BASE)
-#define CMX270_IDE104_VIRT		(CMX270_IT8152_VIRT + SZ_64M)
-
-/* GPIO related definitions */
-#define GPIO_IT8152_IRQ			(22)
-
-#define IRQ_GPIO_IT8152_IRQ	IRQ_GPIO(GPIO_IT8152_IRQ)
-#define PME_IRQ			IRQ_GPIO(0)
-#define CMX270_IDE_IRQ		IRQ_GPIO(100)
-#define CMX270_GPIRQ1		IRQ_GPIO(101)
-#define CMX270_TOUCHIRQ		IRQ_GPIO(96)
-#define CMX270_ETHIRQ		IRQ_GPIO(10)
-#define CMX270_GFXIRQ		IRQ_GPIO(95)
-#define CMX270_NANDIRQ		IRQ_GPIO(89)
-#define CMX270_MMC_IRQ		IRQ_GPIO(83)
-
-/* PCMCIA related definitions */
-#define PCC_DETECT(x)	(GPLR(84 - (x)) & GPIO_bit(84 - (x)))
-#define PCC_READY(x)	(GPLR(82 - (x)) & GPIO_bit(82 - (x)))
-
-#define PCMCIA_S0_CD_VALID		IRQ_GPIO(84)
-#define PCMCIA_S0_CD_VALID_EDGE		GPIO_BOTH_EDGES
-
-#define PCMCIA_S1_CD_VALID		IRQ_GPIO(83)
-#define PCMCIA_S1_CD_VALID_EDGE		GPIO_BOTH_EDGES
-
-#define PCMCIA_S0_RDYINT		IRQ_GPIO(82)
-#define PCMCIA_S1_RDYINT		IRQ_GPIO(81)
-
-#define PCMCIA_RESET_GPIO		53
diff --git a/include/asm-arm/arch-pxa/eseries-gpio.h b/include/asm-arm/arch-pxa/eseries-gpio.h
new file mode 100644
index 0000000..4c90b13
--- /dev/null
+++ b/include/asm-arm/arch-pxa/eseries-gpio.h
@@ -0,0 +1,50 @@
+/*
+ *  eseries-gpio.h
+ *
+ *  Copyright (C) Ian Molton <spyro@f2s.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.
+ *
+ */
+
+/* e-series power button */
+#define GPIO_ESERIES_POWERBTN     0
+
+/* UDC GPIO definitions */
+#define GPIO_E7XX_USB_DISC       13
+#define GPIO_E7XX_USB_PULLUP      3
+
+#define GPIO_E800_USB_DISC        4
+#define GPIO_E800_USB_PULLUP     84
+
+/* e740 PCMCIA GPIO definitions */
+/* Note: PWR1 seems to be inverted */
+#define GPIO_E740_PCMCIA_CD0      8
+#define GPIO_E740_PCMCIA_CD1     44
+#define GPIO_E740_PCMCIA_RDY0    11
+#define GPIO_E740_PCMCIA_RDY1     6
+#define GPIO_E740_PCMCIA_RST0    27
+#define GPIO_E740_PCMCIA_RST1    24
+#define GPIO_E740_PCMCIA_PWR0    20
+#define GPIO_E740_PCMCIA_PWR1    23
+
+/* e750 PCMCIA GPIO definitions */
+#define GPIO_E750_PCMCIA_CD0      8
+#define GPIO_E750_PCMCIA_RDY0    12
+#define GPIO_E750_PCMCIA_RST0    27
+#define GPIO_E750_PCMCIA_PWR0    20
+
+/* e800 PCMCIA GPIO definitions */
+#define GPIO_E800_PCMCIA_RST0    69
+#define GPIO_E800_PCMCIA_RST1    72
+#define GPIO_E800_PCMCIA_PWR0    20
+#define GPIO_E800_PCMCIA_PWR1    73
+
+/* e7xx IrDA power control */
+#define GPIO_E7XX_IR_ON          38
+
+/* ASIC related GPIOs */
+#define GPIO_ESERIES_TMIO_IRQ        5
+#define GPIO_E800_ANGELX_IRQ      8
diff --git a/include/asm-arm/arch-pxa/eseries-irq.h b/include/asm-arm/arch-pxa/eseries-irq.h
new file mode 100644
index 0000000..f2a93d5
--- /dev/null
+++ b/include/asm-arm/arch-pxa/eseries-irq.h
@@ -0,0 +1,27 @@
+/*
+ *  eseries-irq.h
+ *
+ *  Copyright (C) Ian Molton <spyro@f2s.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.
+ *
+ */
+
+#define ANGELX_IRQ_BASE (IRQ_BOARD_START+8)
+#define IRQ_ANGELX(n) (ANGELX_IRQ_BASE + (n))
+
+#define ANGELX_RDY0_IRQ IRQ_ANGELX(0)
+#define ANGELX_ST0_IRQ  IRQ_ANGELX(1)
+#define ANGELX_CD0_IRQ  IRQ_ANGELX(2)
+#define ANGELX_RDY1_IRQ IRQ_ANGELX(3)
+#define ANGELX_ST1_IRQ  IRQ_ANGELX(4)
+#define ANGELX_CD1_IRQ  IRQ_ANGELX(5)
+
+#define TMIO_IRQ_BASE (IRQ_BOARD_START+0)
+#define IRQ_TMIO(n) (TMIO_IRQ_BASE + (n))
+
+#define TMIO_SD_IRQ     IRQ_TMIO(1)
+#define TMIO_USB_IRQ    IRQ_TMIO(2)
+
diff --git a/include/asm-arm/arch-pxa/hardware.h b/include/asm-arm/arch-pxa/hardware.h
index d9af6da..979a456 100644
--- a/include/asm-arm/arch-pxa/hardware.h
+++ b/include/asm-arm/arch-pxa/hardware.h
@@ -69,6 +69,12 @@
 		_id == 0x212;				\
 	})
 
+#define __cpu_is_pxa255(id)                             \
+	({                                              \
+		unsigned int _id = (id) >> 4 & 0xfff;   \
+		_id == 0x2d0;                           \
+	 })
+
 #define __cpu_is_pxa25x(id)				\
 	({						\
 		unsigned int _id = (id) >> 4 & 0xfff;	\
@@ -76,6 +82,7 @@
 	})
 #else
 #define __cpu_is_pxa21x(id)	(0)
+#define __cpu_is_pxa255(id)	(0)
 #define __cpu_is_pxa25x(id)	(0)
 #endif
 
@@ -119,11 +126,26 @@
 #define __cpu_is_pxa320(id)	(0)
 #endif
 
+#ifdef CONFIG_CPU_PXA930
+#define __cpu_is_pxa930(id)				\
+	({						\
+		unsigned int _id = (id) >> 4 & 0xfff;	\
+		_id == 0x683;		\
+	 })
+#else
+#define __cpu_is_pxa930(id)	(0)
+#endif
+
 #define cpu_is_pxa21x()					\
 	({						\
 		__cpu_is_pxa21x(read_cpuid_id());	\
 	})
 
+#define cpu_is_pxa255()                                 \
+	({                                              \
+		__cpu_is_pxa255(read_cpuid_id());       \
+	})
+
 #define cpu_is_pxa25x()					\
 	({						\
 		__cpu_is_pxa25x(read_cpuid_id());	\
@@ -149,6 +171,12 @@
 		__cpu_is_pxa320(read_cpuid_id());	\
 	 })
 
+#define cpu_is_pxa930()					\
+	({						\
+		unsigned int id = read_cpuid(CPUID_ID);	\
+		__cpu_is_pxa930(id);			\
+	 })
+
 /*
  * CPUID Core Generation Bit
  * <= 0x2 for pxa21x/pxa25x/pxa26x/pxa27x
@@ -196,6 +224,11 @@
  */
 extern unsigned int get_memclk_frequency_10khz(void);
 
+/*
+ * register GPIO as reset generator
+ */
+extern int init_gpio_reset(int gpio);
+
 #endif
 
 #if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)
diff --git a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h
index b6c8fe3..9413121 100644
--- a/include/asm-arm/arch-pxa/irqs.h
+++ b/include/asm-arm/arch-pxa/irqs.h
@@ -180,10 +180,13 @@
 #define NR_IRQS			(IRQ_LOCOMO_SPI_TEND + 1)
 #elif defined(CONFIG_ARCH_LUBBOCK) || \
       defined(CONFIG_MACH_LOGICPD_PXA270) || \
+      defined(CONFIG_MACH_TOSA) || \
       defined(CONFIG_MACH_MAINSTONE) || \
       defined(CONFIG_MACH_PCM027) || \
       defined(CONFIG_MACH_MAGICIAN)
 #define NR_IRQS			(IRQ_BOARD_END)
+#elif defined(CONFIG_MACH_ZYLONITE)
+#define NR_IRQS			(IRQ_BOARD_START + 32)
 #else
 #define NR_IRQS			(IRQ_BOARD_START)
 #endif
diff --git a/include/asm-arm/arch-pxa/mfp-pxa2xx.h b/include/asm-arm/arch-pxa/mfp-pxa2xx.h
index db8d890..8de1c0d 100644
--- a/include/asm-arm/arch-pxa/mfp-pxa2xx.h
+++ b/include/asm-arm/arch-pxa/mfp-pxa2xx.h
@@ -128,5 +128,6 @@
 #define GPIO84_GPIO	MFP_CFG_IN(GPIO84, AF0)
 
 extern void pxa2xx_mfp_config(unsigned long *mfp_cfgs, int num);
+extern void pxa2xx_mfp_set_lpm(int mfp, unsigned long lpm);
 extern int gpio_set_wake(unsigned int gpio, unsigned int on);
 #endif /* __ASM_ARCH_MFP_PXA2XX_H */
diff --git a/include/asm-arm/arch-pxa/mfp-pxa930.h b/include/asm-arm/arch-pxa/mfp-pxa930.h
new file mode 100644
index 0000000..c4e945a
--- /dev/null
+++ b/include/asm-arm/arch-pxa/mfp-pxa930.h
@@ -0,0 +1,491 @@
+/*
+ * linux/include/asm-arm/arch-pxa/mfp-pxa930.h
+ *
+ * PXA930 specific MFP configuration definitions
+ *
+ * Copyright (C) 2007-2008 Marvell International Ltd.
+ *
+ *  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_ARCH_MFP_PXA9xx_H
+#define __ASM_ARCH_MFP_PXA9xx_H
+
+#include <asm/arch/mfp.h>
+#include <asm/arch/mfp-pxa3xx.h>
+
+/* GPIO */
+#define GPIO46_GPIO		MFP_CFG(GPIO46, AF0)
+#define GPIO49_GPIO		MFP_CFG(GPIO49, AF0)
+#define GPIO50_GPIO		MFP_CFG(GPIO50, AF0)
+#define GPIO51_GPIO		MFP_CFG(GPIO51, AF0)
+#define GPIO52_GPIO		MFP_CFG(GPIO52, AF0)
+#define GPIO56_GPIO		MFP_CFG(GPIO56, AF0)
+#define GPIO58_GPIO		MFP_CFG(GPIO58, AF0)
+#define GPIO59_GPIO		MFP_CFG(GPIO59, AF0)
+#define GPIO60_GPIO		MFP_CFG(GPIO60, AF0)
+#define GPIO61_GPIO		MFP_CFG(GPIO61, AF0)
+#define GPIO62_GPIO		MFP_CFG(GPIO62, AF0)
+
+#define GSIM_UCLK_GPIO_79	MFP_CFG(GSIM_UCLK, AF0)
+#define GSIM_UIO_GPIO_80	MFP_CFG(GSIM_UIO, AF0)
+#define GSIM_nURST_GPIO_81	MFP_CFG(GSIM_nURST, AF0)
+#define GSIM_UDET_GPIO_82	MFP_CFG(GSIM_UDET, AF0)
+
+#define DF_IO15_GPIO_28		MFP_CFG(DF_IO15, AF0)
+#define DF_IO14_GPIO_29		MFP_CFG(DF_IO14, AF0)
+#define DF_IO13_GPIO_30		MFP_CFG(DF_IO13, AF0)
+#define DF_IO12_GPIO_31		MFP_CFG(DF_IO12, AF0)
+#define DF_IO11_GPIO_32		MFP_CFG(DF_IO11, AF0)
+#define DF_IO10_GPIO_33		MFP_CFG(DF_IO10, AF0)
+#define DF_IO9_GPIO_34		MFP_CFG(DF_IO9, AF0)
+#define DF_IO8_GPIO_35		MFP_CFG(DF_IO8, AF0)
+#define DF_IO7_GPIO_36		MFP_CFG(DF_IO7, AF0)
+#define DF_IO6_GPIO_37		MFP_CFG(DF_IO6, AF0)
+#define DF_IO5_GPIO_38		MFP_CFG(DF_IO5, AF0)
+#define DF_IO4_GPIO_39		MFP_CFG(DF_IO4, AF0)
+#define DF_IO3_GPIO_40		MFP_CFG(DF_IO3, AF0)
+#define DF_IO2_GPIO_41		MFP_CFG(DF_IO2, AF0)
+#define DF_IO1_GPIO_42		MFP_CFG(DF_IO1, AF0)
+#define DF_IO0_GPIO_43		MFP_CFG(DF_IO0, AF0)
+#define DF_nCS0_GPIO_44		MFP_CFG(DF_nCS0, AF0)
+#define DF_nCS1_GPIO_45		MFP_CFG(DF_nCS1, AF0)
+#define DF_nWE_GPIO_46		MFP_CFG(DF_nWE, AF0)
+#define DF_nRE_nOE_GPIO_47	MFP_CFG(DF_nRE_nOE, AF0)
+#define DF_CLE_nOE_GPIO_48	MFP_CFG(DF_CLE_nOE, AF0)
+#define DF_nADV1_ALE_GPIO_49	MFP_CFG(DF_nADV1_ALE, AF0)
+#define DF_nADV2_ALE_GPIO_50	MFP_CFG(DF_nADV2_ALE, AF0)
+#define DF_INT_RnB_GPIO_51	MFP_CFG(DF_INT_RnB, AF0)
+#define DF_SCLK_E_GPIO_52	MFP_CFG(DF_SCLK_E, AF0)
+
+#define DF_ADDR0_GPIO_53	MFP_CFG(DF_ADDR0, AF0)
+#define DF_ADDR1_GPIO_54	MFP_CFG(DF_ADDR1, AF0)
+#define DF_ADDR2_GPIO_55	MFP_CFG(DF_ADDR2, AF0)
+#define DF_ADDR3_GPIO_56	MFP_CFG(DF_ADDR3, AF0)
+#define nXCVREN_GPIO_57		MFP_CFG(nXCVREN, AF0)
+#define nLUA_GPIO_58		MFP_CFG(nLUA, AF0)
+#define nLLA_GPIO_59		MFP_CFG(nLLA, AF0)
+#define nBE0_GPIO_60		MFP_CFG(nBE0, AF0)
+#define nBE1_GPIO_61		MFP_CFG(nBE1, AF0)
+#define RDY_GPIO_62		MFP_CFG(RDY, AF0)
+
+/* Chip Select */
+#define DF_nCS0_nCS2		MFP_CFG_LPM(DF_nCS0, AF3, PULL_HIGH)
+#define DF_nCS1_nCS3		MFP_CFG_LPM(DF_nCS1, AF3, PULL_HIGH)
+
+/* AC97 */
+#define GPIO83_BAC97_SYSCLK	MFP_CFG(GPIO83, AF3)
+#define GPIO84_BAC97_SDATA_IN0	MFP_CFG(GPIO84, AF3)
+#define GPIO85_BAC97_BITCLK	MFP_CFG(GPIO85, AF3)
+#define GPIO86_BAC97_nRESET	MFP_CFG(GPIO86, AF3)
+#define GPIO87_BAC97_SYNC	MFP_CFG(GPIO87, AF3)
+#define GPIO88_BAC97_SDATA_OUT	MFP_CFG(GPIO88, AF3)
+
+/* I2C */
+#define GPIO39_CI2C_SCL		MFP_CFG_LPM(GPIO39, AF3, PULL_HIGH)
+#define GPIO40_CI2C_SDA		MFP_CFG_LPM(GPIO40, AF3, PULL_HIGH)
+
+#define GPIO51_CI2C_SCL		MFP_CFG_LPM(GPIO51, AF3, PULL_HIGH)
+#define GPIO52_CI2C_SDA		MFP_CFG_LPM(GPIO52, AF3, PULL_HIGH)
+
+#define GPIO63_CI2C_SCL		MFP_CFG_LPM(GPIO63, AF4, PULL_HIGH)
+#define GPIO64_CI2C_SDA		MFP_CFG_LPM(GPIO64, AF4, PULL_HIGH)
+
+#define GPIO77_CI2C_SCL		MFP_CFG_LPM(GPIO77, AF2, PULL_HIGH)
+#define GPIO78_CI2C_SDA		MFP_CFG_LPM(GPIO78, AF2, PULL_HIGH)
+
+#define GPIO89_CI2C_SCL		MFP_CFG_LPM(GPIO89, AF1, PULL_HIGH)
+#define GPIO90_CI2C_SDA		MFP_CFG_LPM(GPIO90, AF1, PULL_HIGH)
+
+#define GPIO95_CI2C_SCL		MFP_CFG_LPM(GPIO95, AF1, PULL_HIGH)
+#define GPIO96_CI2C_SDA		MFP_CFG_LPM(GPIO96, AF1, PULL_HIGH)
+
+#define GPIO97_CI2C_SCL		MFP_CFG_LPM(GPIO97, AF3, PULL_HIGH)
+#define GPIO98_CI2C_SDA		MFP_CFG_LPM(GPIO98, AF3, PULL_HIGH)
+
+/* QCI */
+#define GPIO63_CI_DD_9		MFP_CFG_LPM(GPIO63, AF1, PULL_LOW)
+#define GPIO64_CI_DD_8		MFP_CFG_LPM(GPIO64, AF1, PULL_LOW)
+#define GPIO65_CI_DD_7		MFP_CFG_LPM(GPIO65, AF1, PULL_LOW)
+#define GPIO66_CI_DD_6		MFP_CFG_LPM(GPIO66, AF1, PULL_LOW)
+#define GPIO67_CI_DD_5		MFP_CFG_LPM(GPIO67, AF1, PULL_LOW)
+#define GPIO68_CI_DD_4		MFP_CFG_LPM(GPIO68, AF1, PULL_LOW)
+#define GPIO69_CI_DD_3		MFP_CFG_LPM(GPIO69, AF1, PULL_LOW)
+#define GPIO70_CI_DD_2		MFP_CFG_LPM(GPIO70, AF1, PULL_LOW)
+#define GPIO71_CI_DD_1		MFP_CFG_LPM(GPIO71, AF1, PULL_LOW)
+#define GPIO72_CI_DD_0		MFP_CFG_LPM(GPIO72, AF1, PULL_LOW)
+#define GPIO73_CI_HSYNC		MFP_CFG_LPM(GPIO73, AF1, PULL_LOW)
+#define GPIO74_CI_VSYNC		MFP_CFG_LPM(GPIO74, AF1, PULL_LOW)
+#define GPIO75_CI_MCLK		MFP_CFG_LPM(GPIO75, AF1, PULL_LOW)
+#define GPIO76_CI_PCLK		MFP_CFG_LPM(GPIO76, AF1, PULL_LOW)
+
+/* KEYPAD */
+#define GPIO4_KP_DKIN_4		MFP_CFG_LPM(GPIO4, AF3, FLOAT)
+#define GPIO5_KP_DKIN_5		MFP_CFG_LPM(GPIO5, AF3, FLOAT)
+#define GPIO6_KP_DKIN_6		MFP_CFG_LPM(GPIO6, AF3, FLOAT)
+#define GPIO7_KP_DKIN_7		MFP_CFG_LPM(GPIO7, AF3, FLOAT)
+#define GPIO8_KP_DKIN_4		MFP_CFG_LPM(GPIO8, AF3, FLOAT)
+#define GPIO9_KP_DKIN_5		MFP_CFG_LPM(GPIO9, AF3, FLOAT)
+#define GPIO10_KP_DKIN_6	MFP_CFG_LPM(GPIO10, AF3, FLOAT)
+#define GPIO11_KP_DKIN_7	MFP_CFG_LPM(GPIO11, AF3, FLOAT)
+
+#define GPIO12_KP_DKIN_0	MFP_CFG_LPM(GPIO12, AF2, FLOAT)
+#define GPIO13_KP_DKIN_1	MFP_CFG_LPM(GPIO13, AF2, FLOAT)
+#define GPIO14_KP_DKIN_2	MFP_CFG_LPM(GPIO14, AF2, FLOAT)
+#define GPIO15_KP_DKIN_3	MFP_CFG_LPM(GPIO15, AF2, FLOAT)
+
+#define GPIO41_KP_DKIN_0	MFP_CFG_LPM(GPIO41, AF2, FLOAT)
+#define GPIO42_KP_DKIN_1	MFP_CFG_LPM(GPIO42, AF2, FLOAT)
+#define GPIO43_KP_DKIN_2	MFP_CFG_LPM(GPIO43, AF2, FLOAT)
+#define GPIO44_KP_DKIN_3	MFP_CFG_LPM(GPIO44, AF2, FLOAT)
+#define GPIO41_KP_DKIN_4	MFP_CFG_LPM(GPIO41, AF4, FLOAT)
+#define GPIO42_KP_DKIN_5	MFP_CFG_LPM(GPIO42, AF4, FLOAT)
+
+#define GPIO0_KP_MKIN_0		MFP_CFG_LPM(GPIO0, AF1, FLOAT)
+#define GPIO2_KP_MKIN_1		MFP_CFG_LPM(GPIO2, AF1, FLOAT)
+#define GPIO4_KP_MKIN_2		MFP_CFG_LPM(GPIO4, AF1, FLOAT)
+#define GPIO6_KP_MKIN_3		MFP_CFG_LPM(GPIO6, AF1, FLOAT)
+#define GPIO8_KP_MKIN_4		MFP_CFG_LPM(GPIO8, AF1, FLOAT)
+#define GPIO10_KP_MKIN_5	MFP_CFG_LPM(GPIO10, AF1, FLOAT)
+#define GPIO12_KP_MKIN_6	MFP_CFG_LPM(GPIO12, AF1, FLOAT)
+#define GPIO14_KP_MKIN_7	MFP_CFG(GPIO14, AF1)
+#define GPIO35_KP_MKIN_5	MFP_CFG(GPIO35, AF4)
+
+#define GPIO1_KP_MKOUT_0	MFP_CFG_LPM(GPIO1, AF1, DRIVE_HIGH)
+#define GPIO3_KP_MKOUT_1	MFP_CFG_LPM(GPIO3, AF1, DRIVE_HIGH)
+#define GPIO5_KP_MKOUT_2	MFP_CFG_LPM(GPIO5, AF1, DRIVE_HIGH)
+#define GPIO7_KP_MKOUT_3	MFP_CFG_LPM(GPIO7, AF1, DRIVE_HIGH)
+#define GPIO9_KP_MKOUT_4	MFP_CFG_LPM(GPIO9, AF1, DRIVE_HIGH)
+#define GPIO11_KP_MKOUT_5	MFP_CFG_LPM(GPIO11, AF1, DRIVE_HIGH)
+#define GPIO13_KP_MKOUT_6	MFP_CFG_LPM(GPIO13, AF1, DRIVE_HIGH)
+#define GPIO15_KP_MKOUT_7	MFP_CFG_LPM(GPIO15, AF1, DRIVE_HIGH)
+#define GPIO36_KP_MKOUT_5	MFP_CFG_LPM(GPIO36, AF4, DRIVE_HIGH)
+
+/* LCD */
+#define GPIO17_LCD_FCLK_RD	MFP_CFG(GPIO17, AF1)
+#define GPIO18_LCD_LCLK_A0	MFP_CFG(GPIO18, AF1)
+#define GPIO19_LCD_PCLK_WR	MFP_CFG(GPIO19, AF1)
+#define GPIO20_LCD_BIAS		MFP_CFG(GPIO20, AF1)
+#define GPIO21_LCD_CS		MFP_CFG(GPIO21, AF1)
+#define GPIO22_LCD_CS2		MFP_CFG(GPIO22, AF2)
+#define GPIO22_LCD_VSYNC	MFP_CFG(GPIO22, AF1)
+#define GPIO23_LCD_DD0		MFP_CFG(GPIO23, AF1)
+#define GPIO24_LCD_DD1		MFP_CFG(GPIO24, AF1)
+#define GPIO25_LCD_DD2		MFP_CFG(GPIO25, AF1)
+#define GPIO26_LCD_DD3		MFP_CFG(GPIO26, AF1)
+#define GPIO27_LCD_DD4		MFP_CFG(GPIO27, AF1)
+#define GPIO28_LCD_DD5		MFP_CFG(GPIO28, AF1)
+#define GPIO29_LCD_DD6		MFP_CFG(GPIO29, AF1)
+#define GPIO30_LCD_DD7		MFP_CFG(GPIO30, AF1)
+#define GPIO31_LCD_DD8		MFP_CFG(GPIO31, AF1)
+#define GPIO32_LCD_DD9		MFP_CFG(GPIO32, AF1)
+#define GPIO33_LCD_DD10		MFP_CFG(GPIO33, AF1)
+#define GPIO34_LCD_DD11		MFP_CFG(GPIO34, AF1)
+#define GPIO35_LCD_DD12		MFP_CFG(GPIO35, AF1)
+#define GPIO36_LCD_DD13		MFP_CFG(GPIO36, AF1)
+#define GPIO37_LCD_DD14		MFP_CFG(GPIO37, AF1)
+#define GPIO38_LCD_DD15		MFP_CFG(GPIO38, AF1)
+#define GPIO39_LCD_DD16		MFP_CFG(GPIO39, AF1)
+#define GPIO40_LCD_DD17		MFP_CFG(GPIO40, AF1)
+#define GPIO41_LCD_CS2		MFP_CFG(GPIO41, AF3)
+#define GPIO42_LCD_VSYNC2	MFP_CFG(GPIO42, AF3)
+#define GPIO44_LCD_DD7		MFP_CFG(GPIO44, AF1)
+
+/* Mini-LCD */
+#define GPIO17_MLCD_FCLK	MFP_CFG(GPIO17, AF3)
+#define GPIO18_MLCD_LCLK	MFP_CFG(GPIO18, AF3)
+#define GPIO19_MLCD_PCLK	MFP_CFG(GPIO19, AF3)
+#define GPIO20_MLCD_BIAS	MFP_CFG(GPIO20, AF3)
+#define GPIO23_MLCD_DD0		MFP_CFG(GPIO23, AF3)
+#define GPIO24_MLCD_DD1		MFP_CFG(GPIO24, AF3)
+#define GPIO25_MLCD_DD2		MFP_CFG(GPIO25, AF3)
+#define GPIO26_MLCD_DD3		MFP_CFG(GPIO26, AF3)
+#define GPIO27_MLCD_DD4		MFP_CFG(GPIO27, AF3)
+#define GPIO28_MLCD_DD5		MFP_CFG(GPIO28, AF3)
+#define GPIO29_MLCD_DD6		MFP_CFG(GPIO29, AF3)
+#define GPIO30_MLCD_DD7		MFP_CFG(GPIO30, AF3)
+#define GPIO31_MLCD_DD8		MFP_CFG(GPIO31, AF3)
+#define GPIO32_MLCD_DD9		MFP_CFG(GPIO32, AF3)
+#define GPIO33_MLCD_DD10	MFP_CFG(GPIO33, AF3)
+#define GPIO34_MLCD_DD11	MFP_CFG(GPIO34, AF3)
+#define GPIO35_MLCD_DD12	MFP_CFG(GPIO35, AF3)
+#define GPIO36_MLCD_DD13	MFP_CFG(GPIO36, AF3)
+#define GPIO37_MLCD_DD14	MFP_CFG(GPIO37, AF3)
+#define GPIO38_MLCD_DD15	MFP_CFG(GPIO38, AF3)
+#define GPIO44_MLCD_DD7		MFP_CFG(GPIO44, AF5)
+
+/* MMC1 */
+#define GPIO10_MMC1_DAT3	MFP_CFG(GPIO10, AF4)
+#define GPIO11_MMC1_DAT2	MFP_CFG(GPIO11, AF4)
+#define GPIO12_MMC1_DAT1	MFP_CFG(GPIO12, AF4)
+#define GPIO13_MMC1_DAT0	MFP_CFG(GPIO13, AF4)
+#define GPIO14_MMC1_CMD		MFP_CFG(GPIO14, AF4)
+#define GPIO15_MMC1_CLK		MFP_CFG(GPIO15, AF4)
+#define GPIO55_MMC1_CMD		MFP_CFG(GPIO55, AF3)
+#define GPIO56_MMC1_CLK		MFP_CFG(GPIO56, AF3)
+#define GPIO57_MMC1_DAT0	MFP_CFG(GPIO57, AF3)
+#define GPIO58_MMC1_DAT1	MFP_CFG(GPIO58, AF3)
+#define GPIO59_MMC1_DAT2	MFP_CFG(GPIO59, AF3)
+#define GPIO60_MMC1_DAT3	MFP_CFG(GPIO60, AF3)
+
+#define DF_ADDR0_MMC1_CLK	MFP_CFG(DF_ADDR0, AF2)
+#define DF_ADDR1_MMC1_CMD	MFP_CFG(DF_ADDR1, AF2)
+#define DF_ADDR2_MMC1_DAT0	MFP_CFG(DF_ADDR2, AF2)
+#define DF_ADDR3_MMC1_DAT1	MFP_CFG(DF_ADDR3, AF3)
+#define nXCVREN_MMC1_DAT2	MFP_CFG(nXCVREN, AF2)
+
+/* MMC2 */
+#define GPIO31_MMC2_CMD		MFP_CFG(GPIO31, AF7)
+#define GPIO32_MMC2_CLK		MFP_CFG(GPIO32, AF7)
+#define GPIO33_MMC2_DAT0	MFP_CFG(GPIO33, AF7)
+#define GPIO34_MMC2_DAT1	MFP_CFG(GPIO34, AF7)
+#define GPIO35_MMC2_DAT2	MFP_CFG(GPIO35, AF7)
+#define GPIO36_MMC2_DAT3	MFP_CFG(GPIO36, AF7)
+
+#define GPIO101_MMC2_DAT3	MFP_CFG(GPIO101, AF1)
+#define GPIO102_MMC2_DAT2	MFP_CFG(GPIO102, AF1)
+#define GPIO103_MMC2_DAT1	MFP_CFG(GPIO103, AF1)
+#define GPIO104_MMC2_DAT0	MFP_CFG(GPIO104, AF1)
+#define GPIO105_MMC2_CMD	MFP_CFG(GPIO105, AF1)
+#define GPIO106_MMC2_CLK	MFP_CFG(GPIO106, AF1)
+
+#define DF_IO10_MMC2_DAT3	MFP_CFG(DF_IO10, AF3)
+#define DF_IO11_MMC2_DAT2	MFP_CFG(DF_IO11, AF3)
+#define DF_IO12_MMC2_DAT1	MFP_CFG(DF_IO12, AF3)
+#define DF_IO13_MMC2_DAT0	MFP_CFG(DF_IO13, AF3)
+#define DF_IO14_MMC2_CLK	MFP_CFG(DF_IO14, AF3)
+#define DF_IO15_MMC2_CMD	MFP_CFG(DF_IO15, AF3)
+
+/* BSSP1 */
+#define GPIO12_BSSP1_CLK	MFP_CFG(GPIO12, AF3)
+#define GPIO13_BSSP1_FRM	MFP_CFG(GPIO13, AF3)
+#define GPIO14_BSSP1_RXD	MFP_CFG(GPIO14, AF3)
+#define GPIO15_BSSP1_TXD	MFP_CFG(GPIO15, AF3)
+#define GPIO97_BSSP1_CLK	MFP_CFG(GPIO97, AF5)
+#define GPIO98_BSSP1_FRM	MFP_CFG(GPIO98, AF5)
+
+/* BSSP2 */
+#define GPIO84_BSSP2_SDATA_IN	MFP_CFG(GPIO84, AF1)
+#define GPIO85_BSSP2_BITCLK	MFP_CFG(GPIO85, AF1)
+#define GPIO86_BSSP2_SYSCLK	MFP_CFG(GPIO86, AF1)
+#define GPIO87_BSSP2_SYNC	MFP_CFG(GPIO87, AF1)
+#define GPIO88_BSSP2_DATA_OUT	MFP_CFG(GPIO88, AF1)
+#define GPIO86_BSSP2_SDATA_IN	MFP_CFG(GPIO86, AF4)
+
+/* BSSP3 */
+#define GPIO79_BSSP3_CLK	MFP_CFG(GPIO79, AF1)
+#define GPIO80_BSSP3_FRM	MFP_CFG(GPIO80, AF1)
+#define GPIO81_BSSP3_TXD	MFP_CFG(GPIO81, AF1)
+#define GPIO82_BSSP3_RXD	MFP_CFG(GPIO82, AF1)
+#define GPIO83_BSSP3_SYSCLK	MFP_CFG(GPIO83, AF1)
+
+/* BSSP4 */
+#define GPIO43_BSSP4_CLK	MFP_CFG(GPIO43, AF4)
+#define GPIO44_BSSP4_FRM	MFP_CFG(GPIO44, AF4)
+#define GPIO45_BSSP4_TXD	MFP_CFG(GPIO45, AF4)
+#define GPIO46_BSSP4_RXD	MFP_CFG(GPIO46, AF4)
+
+#define GPIO51_BSSP4_CLK	MFP_CFG(GPIO51, AF4)
+#define GPIO52_BSSP4_FRM	MFP_CFG(GPIO52, AF4)
+#define GPIO53_BSSP4_TXD	MFP_CFG(GPIO53, AF4)
+#define GPIO54_BSSP4_RXD	MFP_CFG(GPIO54, AF4)
+
+/* GSSP1 */
+#define GPIO79_GSSP1_CLK	MFP_CFG(GPIO79, AF2)
+#define GPIO80_GSSP1_FRM	MFP_CFG(GPIO80, AF2)
+#define GPIO81_GSSP1_TXD	MFP_CFG(GPIO81, AF2)
+#define GPIO82_GSSP1_RXD	MFP_CFG(GPIO82, AF2)
+#define GPIO83_GSSP1_SYSCLK	MFP_CFG(GPIO83, AF2)
+
+#define GPIO93_GSSP1_CLK	MFP_CFG(GPIO93, AF4)
+#define GPIO94_GSSP1_FRM	MFP_CFG(GPIO94, AF4)
+#define GPIO95_GSSP1_TXD	MFP_CFG(GPIO95, AF4)
+#define GPIO96_GSSP1_RXD	MFP_CFG(GPIO96, AF4)
+
+/* GSSP2 */
+#define GPIO47_GSSP2_CLK	MFP_CFG(GPIO47, AF4)
+#define GPIO48_GSSP2_FRM	MFP_CFG(GPIO48, AF4)
+#define GPIO49_GSSP2_RXD	MFP_CFG(GPIO49, AF4)
+#define GPIO50_GSSP2_TXD	MFP_CFG(GPIO50, AF4)
+
+#define GPIO69_GSSP2_CLK	MFP_CFG(GPIO69, AF4)
+#define GPIO70_GSSP2_FRM	MFP_CFG(GPIO70, AF4)
+#define GPIO71_GSSP2_RXD	MFP_CFG(GPIO71, AF4)
+#define GPIO72_GSSP2_TXD	MFP_CFG(GPIO72, AF4)
+
+#define GPIO84_GSSP2_RXD	MFP_CFG(GPIO84, AF2)
+#define GPIO85_GSSP2_CLK	MFP_CFG(GPIO85, AF2)
+#define GPIO86_GSSP2_SYSCLK	MFP_CFG(GPIO86, AF2)
+#define GPIO87_GSSP2_FRM	MFP_CFG(GPIO87, AF2)
+#define GPIO88_GSSP2_TXD	MFP_CFG(GPIO88, AF2)
+#define GPIO86_GSSP2_RXD	MFP_CFG(GPIO86, AF5)
+
+#define GPIO103_GSSP2_CLK	MFP_CFG(GPIO103, AF2)
+#define GPIO104_GSSP2_FRM	MFP_CFG(GPIO104, AF2)
+#define GPIO105_GSSP2_RXD	MFP_CFG(GPIO105, AF2)
+#define GPIO106_GSSP2_TXD	MFP_CFG(GPIO106, AF2)
+
+/* UART1 - FFUART */
+#define GPIO47_UART1_DSR_N	MFP_CFG(GPIO47, AF1)
+#define GPIO48_UART1_DTR_N	MFP_CFG(GPIO48, AF1)
+#define GPIO49_UART1_RI		MFP_CFG(GPIO49, AF1)
+#define GPIO50_UART1_DCD	MFP_CFG(GPIO50, AF1)
+#define GPIO51_UART1_CTS	MFP_CFG(GPIO51, AF1)
+#define GPIO52_UART1_RTS	MFP_CFG(GPIO52, AF1)
+#define GPIO53_UART1_RXD	MFP_CFG(GPIO53, AF1)
+#define GPIO54_UART1_TXD	MFP_CFG(GPIO54, AF1)
+
+#define GPIO63_UART1_TXD	MFP_CFG(GPIO63, AF2)
+#define GPIO64_UART1_RXD	MFP_CFG(GPIO64, AF2)
+#define GPIO65_UART1_DSR	MFP_CFG(GPIO65, AF2)
+#define GPIO66_UART1_DTR	MFP_CFG(GPIO66, AF2)
+#define GPIO67_UART1_RI		MFP_CFG(GPIO67, AF2)
+#define GPIO68_UART1_DCD	MFP_CFG(GPIO68, AF2)
+#define GPIO69_UART1_CTS	MFP_CFG(GPIO69, AF2)
+#define GPIO70_UART1_RTS	MFP_CFG(GPIO70, AF2)
+
+/* UART2 - BTUART */
+#define GPIO91_UART2_RXD	MFP_CFG(GPIO91, AF1)
+#define GPIO92_UART2_TXD	MFP_CFG(GPIO92, AF1)
+#define GPIO93_UART2_CTS	MFP_CFG(GPIO93, AF1)
+#define GPIO94_UART2_RTS	MFP_CFG(GPIO94, AF1)
+
+/* UART3 - STUART */
+#define GPIO43_UART3_RTS	MFP_CFG(GPIO43, AF3)
+#define GPIO44_UART3_CTS	MFP_CFG(GPIO44, AF3)
+#define GPIO45_UART3_RXD	MFP_CFG(GPIO45, AF3)
+#define GPIO46_UART3_TXD	MFP_CFG(GPIO46, AF3)
+
+#define GPIO75_UART3_RTS	MFP_CFG(GPIO75, AF5)
+#define GPIO76_UART3_CTS	MFP_CFG(GPIO76, AF5)
+#define GPIO77_UART3_TXD	MFP_CFG(GPIO77, AF5)
+#define GPIO78_UART3_RXD	MFP_CFG(GPIO78, AF5)
+
+/* DFI */
+#define DF_IO0_DF_IO0		MFP_CFG(DF_IO0, AF2)
+#define DF_IO1_DF_IO1		MFP_CFG(DF_IO1, AF2)
+#define DF_IO2_DF_IO2		MFP_CFG(DF_IO2, AF2)
+#define DF_IO3_DF_IO3		MFP_CFG(DF_IO3, AF2)
+#define DF_IO4_DF_IO4		MFP_CFG(DF_IO4, AF2)
+#define DF_IO5_DF_IO5		MFP_CFG(DF_IO5, AF2)
+#define DF_IO6_DF_IO6		MFP_CFG(DF_IO6, AF2)
+#define DF_IO7_DF_IO7		MFP_CFG(DF_IO7, AF2)
+#define DF_IO8_DF_IO8		MFP_CFG(DF_IO8, AF2)
+#define DF_IO9_DF_IO9		MFP_CFG(DF_IO9, AF2)
+#define DF_IO10_DF_IO10		MFP_CFG(DF_IO10, AF2)
+#define DF_IO11_DF_IO11		MFP_CFG(DF_IO11, AF2)
+#define DF_IO12_DF_IO12		MFP_CFG(DF_IO12, AF2)
+#define DF_IO13_DF_IO13		MFP_CFG(DF_IO13, AF2)
+#define DF_IO14_DF_IO14		MFP_CFG(DF_IO14, AF2)
+#define DF_IO15_DF_IO15		MFP_CFG(DF_IO15, AF2)
+#define DF_nADV1_ALE_DF_nADV1	MFP_CFG(DF_nADV1_ALE, AF2)
+#define DF_nADV2_ALE_DF_nADV2	MFP_CFG(DF_nADV2_ALE, AF2)
+#define DF_nCS0_DF_nCS0		MFP_CFG(DF_nCS0, AF2)
+#define DF_nCS1_DF_nCS1		MFP_CFG(DF_nCS1, AF2)
+#define DF_nRE_nOE_DF_nOE	MFP_CFG(DF_nRE_nOE, AF2)
+#define DF_nWE_DF_nWE		MFP_CFG(DF_nWE, AF2)
+
+/* DFI - NAND */
+#define DF_CLE_nOE_ND_CLE	MFP_CFG_LPM(DF_CLE_nOE, AF1, PULL_HIGH)
+#define DF_INT_RnB_ND_INT_RnB	MFP_CFG_LPM(DF_INT_RnB, AF1, PULL_LOW)
+#define DF_IO0_ND_IO0		MFP_CFG_LPM(DF_IO0, AF1, PULL_LOW)
+#define DF_IO1_ND_IO1		MFP_CFG_LPM(DF_IO1, AF1, PULL_LOW)
+#define DF_IO2_ND_IO2		MFP_CFG_LPM(DF_IO2, AF1, PULL_LOW)
+#define DF_IO3_ND_IO3		MFP_CFG_LPM(DF_IO3, AF1, PULL_LOW)
+#define DF_IO4_ND_IO4		MFP_CFG_LPM(DF_IO4, AF1, PULL_LOW)
+#define DF_IO5_ND_IO5		MFP_CFG_LPM(DF_IO5, AF1, PULL_LOW)
+#define DF_IO6_ND_IO6		MFP_CFG_LPM(DF_IO6, AF1, PULL_LOW)
+#define DF_IO7_ND_IO7		MFP_CFG_LPM(DF_IO7, AF1, PULL_LOW)
+#define DF_IO8_ND_IO8		MFP_CFG_LPM(DF_IO8, AF1, PULL_LOW)
+#define DF_IO9_ND_IO9		MFP_CFG_LPM(DF_IO9, AF1, PULL_LOW)
+#define DF_IO10_ND_IO10		MFP_CFG_LPM(DF_IO10, AF1, PULL_LOW)
+#define DF_IO11_ND_IO11		MFP_CFG_LPM(DF_IO11, AF1, PULL_LOW)
+#define DF_IO12_ND_IO12		MFP_CFG_LPM(DF_IO12, AF1, PULL_LOW)
+#define DF_IO13_ND_IO13		MFP_CFG_LPM(DF_IO13, AF1, PULL_LOW)
+#define DF_IO14_ND_IO14		MFP_CFG_LPM(DF_IO14, AF1, PULL_LOW)
+#define DF_IO15_ND_IO15		MFP_CFG_LPM(DF_IO15, AF1, PULL_LOW)
+#define DF_nADV1_ALE_ND_ALE	MFP_CFG_LPM(DF_nADV1_ALE, AF1, PULL_HIGH)
+#define DF_nADV2_ALE_ND_ALE	MFP_CFG_LPM(DF_nADV2_ALE, AF1, PULL_HIGH)
+#define	DF_nADV2_ALE_nCS3	MFP_CFG_LPM(DF_nADV2_ALE, AF3, PULL_HIGH)
+#define DF_nCS0_ND_nCS0		MFP_CFG_LPM(DF_nCS0, AF1, PULL_HIGH)
+#define DF_nCS1_ND_nCS1		MFP_CFG_LPM(DF_nCS1, AF1, PULL_HIGH)
+#define DF_nRE_nOE_ND_nRE	MFP_CFG_LPM(DF_nRE_nOE, AF1, PULL_HIGH)
+#define DF_nWE_ND_nWE		MFP_CFG_LPM(DF_nWE, AF1, PULL_HIGH)
+
+/* PWM */
+#define GPIO41_PWM0		MFP_CFG_LPM(GPIO41, AF1, PULL_LOW)
+#define GPIO42_PWM1		MFP_CFG_LPM(GPIO42, AF1, PULL_LOW)
+#define GPIO43_PWM3		MFP_CFG_LPM(GPIO43, AF1, PULL_LOW)
+#define GPIO20_PWM0		MFP_CFG_LPM(GPIO20, AF2, PULL_LOW)
+#define GPIO21_PWM2		MFP_CFG_LPM(GPIO21, AF3, PULL_LOW)
+#define GPIO22_PWM3		MFP_CFG_LPM(GPIO22, AF3, PULL_LOW)
+
+/* CIR */
+#define GPIO46_CIR_OUT		MFP_CFG(GPIO46, AF1)
+#define GPIO77_CIR_OUT		MFP_CFG(GPIO77, AF3)
+
+/* USB P2 */
+#define GPIO0_USB_P2_7		MFP_CFG(GPIO0, AF3)
+#define GPIO15_USB_P2_7		MFP_CFG(GPIO15, AF5)
+#define GPIO16_USB_P2_7		MFP_CFG(GPIO16, AF2)
+#define GPIO48_USB_P2_7		MFP_CFG(GPIO48, AF7)
+#define GPIO49_USB_P2_7		MFP_CFG(GPIO49, AF6)
+#define DF_IO9_USB_P2_7		MFP_CFG(DF_IO9, AF3)
+
+#define GPIO48_USB_P2_8		MFP_CFG(GPIO48, AF2)
+#define GPIO50_USB_P2_7		MFP_CFG_X(GPIO50, AF2, DS02X, FLOAT)
+#define GPIO51_USB_P2_5		MFP_CFG(GPIO51, AF2)
+#define GPIO47_USB_P2_4		MFP_CFG(GPIO47, AF2)
+#define GPIO53_USB_P2_3		MFP_CFG(GPIO53, AF2)
+#define GPIO54_USB_P2_6		MFP_CFG(GPIO54, AF2)
+#define GPIO49_USB_P2_2		MFP_CFG(GPIO49, AF2)
+#define GPIO52_USB_P2_1		MFP_CFG(GPIO52, AF2)
+
+#define GPIO63_USB_P2_8		MFP_CFG(GPIO63, AF3)
+#define GPIO64_USB_P2_7		MFP_CFG(GPIO64, AF3)
+#define GPIO65_USB_P2_6		MFP_CFG(GPIO65, AF3)
+#define GPIO66_USG_P2_5		MFP_CFG(GPIO66, AF3)
+#define GPIO67_USB_P2_4		MFP_CFG(GPIO67, AF3)
+#define GPIO68_USB_P2_3		MFP_CFG(GPIO68, AF3)
+#define GPIO69_USB_P2_2		MFP_CFG(GPIO69, AF3)
+#define GPIO70_USB_P2_1		MFP_CFG(GPIO70, AF3)
+
+/* ULPI */
+#define GPIO31_USB_ULPI_D0	MFP_CFG(GPIO31, AF4)
+#define GPIO30_USB_ULPI_D1	MFP_CFG(GPIO30, AF7)
+#define GPIO33_USB_ULPI_D2	MFP_CFG(GPIO33, AF5)
+#define GPIO34_USB_ULPI_D3	MFP_CFG(GPIO34, AF5)
+#define GPIO35_USB_ULPI_D4	MFP_CFG(GPIO35, AF5)
+#define GPIO36_USB_ULPI_D5	MFP_CFG(GPIO36, AF5)
+#define GPIO41_USB_ULPI_D6	MFP_CFG(GPIO41, AF5)
+#define GPIO42_USB_ULPI_D7	MFP_CFG(GPIO42, AF5)
+#define GPIO37_USB_ULPI_DIR	MFP_CFG(GPIO37, AF4)
+#define GPIO38_USB_ULPI_CLK	MFP_CFG(GPIO38, AF4)
+#define GPIO39_USB_ULPI_STP	MFP_CFG(GPIO39, AF4)
+#define GPIO40_USB_ULPI_NXT	MFP_CFG(GPIO40, AF4)
+
+#define GPIO3_CLK26MOUTDMD	MFP_CFG(GPIO3, AF3)
+#define GPIO40_CLK26MOUTDMD	MFP_CFG(GPIO40, AF7)
+#define GPIO94_CLK26MOUTDMD	MFP_CFG(GPIO94, AF5)
+#define GPIO104_CLK26MOUTDMD	MFP_CFG(GPIO104, AF4)
+#define DF_ADDR1_CLK26MOUTDMD	MFP_CFG(DF_ADDR2, AF3)
+#define DF_ADDR3_CLK26MOUTDMD	MFP_CFG(DF_ADDR3, AF3)
+
+#define GPIO14_CLK26MOUT	MFP_CFG(GPIO14, AF5)
+#define GPIO38_CLK26MOUT	MFP_CFG(GPIO38, AF7)
+#define GPIO92_CLK26MOUT	MFP_CFG(GPIO92, AF5)
+#define GPIO105_CLK26MOUT	MFP_CFG(GPIO105, AF4)
+
+#define GPIO2_CLK13MOUTDMD	MFP_CFG(GPIO2, AF3)
+#define GPIO39_CLK13MOUTDMD	MFP_CFG(GPIO39, AF7)
+#define GPIO50_CLK13MOUTDMD	MFP_CFG(GPIO50, AF3)
+#define GPIO93_CLK13MOUTDMD	MFP_CFG(GPIO93, AF5)
+#define GPIO103_CLK13MOUTDMD	MFP_CFG(GPIO103, AF4)
+#define DF_ADDR2_CLK13MOUTDMD	MFP_CFG(DF_ADDR2, AF3)
+
+/* 1 wire */
+#define GPIO95_OW_DQ_IN		MFP_CFG(GPIO95, AF5)
+
+#endif /* __ASM_ARCH_MFP_PXA9xx_H */
diff --git a/include/asm-arm/arch-pxa/mfp.h b/include/asm-arm/arch-pxa/mfp.h
index 02f6157..e7d5879 100644
--- a/include/asm-arm/arch-pxa/mfp.h
+++ b/include/asm-arm/arch-pxa/mfp.h
@@ -210,6 +210,14 @@
 	MFP_PIN_DF_IO14,
 	MFP_PIN_DF_IO15,
 
+	/* additional pins on PXA930 */
+	MFP_PIN_GSIM_UIO,
+	MFP_PIN_GSIM_UCLK,
+	MFP_PIN_GSIM_UDET,
+	MFP_PIN_GSIM_nURST,
+	MFP_PIN_PMIC_INT,
+	MFP_PIN_RDY,
+
 	MFP_PIN_MAX,
 };
 
diff --git a/include/asm-arm/arch-pxa/palmtx.h b/include/asm-arm/arch-pxa/palmtx.h
new file mode 100644
index 0000000..1e8bccb
--- /dev/null
+++ b/include/asm-arm/arch-pxa/palmtx.h
@@ -0,0 +1,106 @@
+/*
+ * GPIOs and interrupts for Palm T|X Handheld Computer
+ *
+ * Based on palmld-gpio.h by Alex Osborne
+ *
+ * Authors:	Marek Vasut <marek.vasut@gmail.com>
+ *		Cristiano P. <cristianop@users.sourceforge.net>
+ *		Jan Herman <2hp@seznam.cz>
+ *
+ * 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 _INCLUDE_PALMTX_H_
+#define _INCLUDE_PALMTX_H_
+
+/** HERE ARE GPIOs **/
+
+/* GPIOs */
+#define GPIO_NR_PALMTX_GPIO_RESET		1
+
+#define GPIO_NR_PALMTX_POWER_DETECT		12 /* 90 */
+#define GPIO_NR_PALMTX_HOTSYNC_BUTTON_N		10
+#define GPIO_NR_PALMTX_EARPHONE_DETECT		107
+
+/* SD/MMC */
+#define GPIO_NR_PALMTX_SD_DETECT_N		14
+#define GPIO_NR_PALMTX_SD_POWER			114 /* probably */
+#define GPIO_NR_PALMTX_SD_READONLY		115 /* probably */
+
+/* TOUCHSCREEN */
+#define GPIO_NR_PALMTX_WM9712_IRQ		27
+
+/* IRDA -  disable GPIO connected to SD pin of tranceiver (TFBS4710?) ? */
+#define GPIO_NR_PALMTX_IR_DISABLE		40
+
+/* USB */
+#define GPIO_NR_PALMTX_USB_DETECT_N		13
+#define GPIO_NR_PALMTX_USB_POWER		95
+#define GPIO_NR_PALMTX_USB_PULLUP		93
+
+/* LCD/BACKLIGHT */
+#define GPIO_NR_PALMTX_BL_POWER			84
+#define GPIO_NR_PALMTX_LCD_POWER		96
+
+/* LCD BORDER */
+#define GPIO_NR_PALMTX_BORDER_SWITCH		98
+#define GPIO_NR_PALMTX_BORDER_SELECT		22
+
+/* BLUETOOTH */
+#define GPIO_NR_PALMTX_BT_POWER			17
+#define GPIO_NR_PALMTX_BT_RESET			83
+
+/* PCMCIA (WiFi) */
+#define GPIO_NR_PALMTX_PCMCIA_POWER1		94
+#define GPIO_NR_PALMTX_PCMCIA_POWER2		108
+#define GPIO_NR_PALMTX_PCMCIA_RESET		79
+#define GPIO_NR_PALMTX_PCMCIA_READY		116
+
+/* NAND Flash ... this GPIO may be incorrect! */
+#define GPIO_NR_PALMTX_NAND_BUFFER_DIR		79
+
+/* INTERRUPTS */
+#define IRQ_GPIO_PALMTX_SD_DETECT_N	IRQ_GPIO(GPIO_NR_PALMTX_SD_DETECT_N)
+#define IRQ_GPIO_PALMTX_WM9712_IRQ	IRQ_GPIO(GPIO_NR_PALMTX_WM9712_IRQ)
+#define IRQ_GPIO_PALMTX_USB_DETECT	IRQ_GPIO(GPIO_NR_PALMTX_USB_DETECT)
+#define IRQ_GPIO_PALMTX_GPIO_RESET	IRQ_GPIO(GPIO_NR_PALMTX_GPIO_RESET)
+
+/** HERE ARE INIT VALUES **/
+
+/* Various addresses  */
+#define PALMTX_PCMCIA_PHYS	0x28000000
+#define PALMTX_PCMCIA_VIRT	0xf0000000
+#define PALMTX_PCMCIA_SIZE	0x100000
+
+#define PALMTX_PHYS_RAM_START	0xa0000000
+#define PALMTX_PHYS_IO_START	0x40000000
+
+#define PALMTX_PHYS_FLASH_START	PXA_CS0_PHYS	/* ChipSelect 0 */
+#define PALMTX_PHYS_NAND_START	PXA_CS1_PHYS	/* ChipSelect 1 */
+
+/* TOUCHSCREEN */
+#define AC97_LINK_FRAME			21
+
+
+/* BATTERY */
+#define PALMTX_BAT_MAX_VOLTAGE		4000	/* 4.00v current voltage */
+#define PALMTX_BAT_MIN_VOLTAGE		3550	/* 3.55v critical voltage */
+#define PALMTX_BAT_MAX_CURRENT		0	/* unknokn */
+#define PALMTX_BAT_MIN_CURRENT		0	/* unknown */
+#define PALMTX_BAT_MAX_CHARGE		1	/* unknown */
+#define PALMTX_BAT_MIN_CHARGE		1	/* unknown */
+#define PALMTX_MAX_LIFE_MINS		360	/* on-life in minutes */
+
+#define PALMTX_BAT_MEASURE_DELAY	(HZ * 1)
+
+/* BACKLIGHT */
+#define PALMTX_MAX_INTENSITY		0xFE
+#define PALMTX_DEFAULT_INTENSITY	0x7E
+#define PALMTX_LIMIT_MASK		0x7F
+#define PALMTX_PRESCALER		0x3F
+#define PALMTX_PERIOD_NS		3500
+
+#endif
diff --git a/include/asm-arm/arch-pxa/pxa27x-udc.h b/include/asm-arm/arch-pxa/pxa27x-udc.h
index bc1cf7d0..ab1443f 100644
--- a/include/asm-arm/arch-pxa/pxa27x-udc.h
+++ b/include/asm-arm/arch-pxa/pxa27x-udc.h
@@ -97,7 +97,7 @@
 #define UP2OCR_IDON		(1 << 10)	/* OTG ID Read Enable */
 #define UP2OCR_HXS		(1 << 16)	/* Host Port 2 Transceiver Output Select */
 #define UP2OCR_HXOE		(1 << 17)	/* Host Port 2 Transceiver Output Enable */
-#define UP2OCR_SEOS		(1 << 24)	/* Single-Ended Output Select */
+#define UP2OCR_SEOS(x)		((x & 7) << 24)	/* Single-Ended Output Select */
 
 #define UDCCSN(x)	__REG2(0x40600100, (x) << 2)
 #define UDCCSR0         __REG(0x40600100) /* UDC Control/Status register - Endpoint 0 */
diff --git a/include/asm-arm/arch-pxa/pxa2xx_spi.h b/include/asm-arm/arch-pxa/pxa2xx_spi.h
index 3459fb2..2206cb6 100644
--- a/include/asm-arm/arch-pxa/pxa2xx_spi.h
+++ b/include/asm-arm/arch-pxa/pxa2xx_spi.h
@@ -41,4 +41,6 @@
 	void (*cs_control)(u32 command);
 };
 
+extern void pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_master *info);
+
 #endif /*PXA2XX_SPI_H_*/
diff --git a/include/asm-arm/arch-pxa/pxa3xx_nand.h b/include/asm-arm/arch-pxa/pxa3xx_nand.h
index 81a8937..eb4b190 100644
--- a/include/asm-arm/arch-pxa/pxa3xx_nand.h
+++ b/include/asm-arm/arch-pxa/pxa3xx_nand.h
@@ -15,4 +15,6 @@
 	struct mtd_partition *parts;
 	unsigned int	nr_parts;
 };
+
+extern void pxa3xx_set_nand_info(struct pxa3xx_nand_platform_data *info);
 #endif /* __ASM_ARCH_PXA3XX_NAND_H */
diff --git a/include/asm-arm/arch-pxa/pxafb.h b/include/asm-arm/arch-pxa/pxafb.h
index bbd2239..daf018d 100644
--- a/include/asm-arm/arch-pxa/pxafb.h
+++ b/include/asm-arm/arch-pxa/pxafb.h
@@ -71,7 +71,8 @@
 
 	u_char		bpp;
 	u_int		cmap_greyscale:1,
-			unused:31;
+			depth:8,
+			unused:23;
 
 	/* Parallel Mode Timing */
 	u_char		hsync_len;
diff --git a/include/asm-arm/arch-pxa/regs-lcd.h b/include/asm-arm/arch-pxa/regs-lcd.h
index 3ba464c9..820a189 100644
--- a/include/asm-arm/arch-pxa/regs-lcd.h
+++ b/include/asm-arm/arch-pxa/regs-lcd.h
@@ -27,6 +27,12 @@
 #define LCCR3_4BPP	(2 << 24)
 #define LCCR3_8BPP	(3 << 24)
 #define LCCR3_16BPP	(4 << 24)
+#define LCCR3_18BPP	(5 << 24)
+#define LCCR3_18BPP_P	(6 << 24)
+#define LCCR3_19BPP	(7 << 24)
+#define LCCR3_19BPP_P	(1 << 29)
+#define LCCR3_24BPP	((1 << 29) | (1 << 24))
+#define LCCR3_25BPP	((1 << 29) | (2 << 24))
 
 #define LCCR3_PDFOR_0	(0 << 30)
 #define LCCR3_PDFOR_1	(1 << 30)
diff --git a/include/asm-arm/arch-pxa/regs-ssp.h b/include/asm-arm/arch-pxa/regs-ssp.h
index 0255328..3c04cde 100644
--- a/include/asm-arm/arch-pxa/regs-ssp.h
+++ b/include/asm-arm/arch-pxa/regs-ssp.h
@@ -20,6 +20,10 @@
 #define SSTSS		(0x38)  /* SSP Timeslot Status */
 #define SSACD		(0x3C)  /* SSP Audio Clock Divider */
 
+#if defined(CONFIG_PXA3xx)
+#define SSACDD		(0x40)	/* SSP Audio Clock Dither Divider */
+#endif
+
 /* Common PXA2xx bits first */
 #define SSCR0_DSS	(0x0000000f)	/* Data Size Select (mask) */
 #define SSCR0_DataSize(x)  ((x) - 1)	/* Data Size Select [4..16] */
@@ -29,10 +33,12 @@
 #define SSCR0_National	(0x2 << 4)	/* National Microwire */
 #define SSCR0_ECS	(1 << 6)	/* External clock select */
 #define SSCR0_SSE	(1 << 7)	/* Synchronous Serial Port Enable */
+
 #if defined(CONFIG_PXA25x)
 #define SSCR0_SCR	(0x0000ff00)	/* Serial Clock Rate (mask) */
 #define SSCR0_SerClkDiv(x) ((((x) - 2)/2) << 8) /* Divisor [2..512] */
-#elif defined(CONFIG_PXA27x)
+
+#elif defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
 #define SSCR0_SCR	(0x000fff00)	/* Serial Clock Rate (mask) */
 #define SSCR0_SerClkDiv(x) (((x) - 1) << 8) /* Divisor [1..4096] */
 #define SSCR0_EDSS	(1 << 20)	/* Extended data size select */
@@ -45,6 +51,10 @@
 #define SSCR0_MOD	(1 << 31)	/* Mode (normal or network) */
 #endif
 
+#if defined(CONFIG_PXA3xx)
+#define SSCR0_FPCKE	(1 << 29)	/* FIFO packing enable */
+#endif
+
 #define SSCR1_RIE	(1 << 0)	/* Receive FIFO Interrupt Enable */
 #define SSCR1_TIE	(1 << 1)	/* Transmit FIFO Interrupt Enable */
 #define SSCR1_LBM	(1 << 2)	/* Loop-Back Mode */
@@ -109,5 +119,9 @@
 #define SSACD_SCDB		(1 << 3)	/* SSPSYSCLK Divider Bypass */
 #define SSACD_ACPS(x)		((x) << 4)	/* Audio clock PLL select */
 #define SSACD_ACDS(x)		((x) << 0)	/* Audio clock divider select */
+#if defined(CONFIG_PXA3xx)
+#define SSACD_SCDX8		(1 << 7)	/* SYSCLK division ratio select */
+#endif
+
 
 #endif /* __ASM_ARCH_REGS_SSP_H */
diff --git a/include/asm-arm/arch-pxa/system.h b/include/asm-arm/arch-pxa/system.h
index ba7e132..6956fc5 100644
--- a/include/asm-arm/arch-pxa/system.h
+++ b/include/asm-arm/arch-pxa/system.h
@@ -21,19 +21,4 @@
 }
 
 
-static inline void arch_reset(char mode)
-{
-	if (cpu_is_pxa2xx())
-		RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
-
-	if (mode == 's') {
-		/* Jump into ROM at address 0 */
-		cpu_reset(0);
-	} else {
-		/* Initialize the watchdog and let it fire */
-		OWER = OWER_WME;
-		OSSR = OSSR_M3;
-		OSMR3 = OSCR + 368640;	/* ... in 100 ms */
-	}
-}
-
+void arch_reset(char mode);
diff --git a/include/asm-arm/arch-pxa/tosa.h b/include/asm-arm/arch-pxa/tosa.h
index c5b6fde..a72803f 100644
--- a/include/asm-arm/arch-pxa/tosa.h
+++ b/include/asm-arm/arch-pxa/tosa.h
@@ -25,21 +25,18 @@
  */
 #define TOSA_SCOOP_GPIO_BASE		NR_BUILTIN_GPIO
 #define TOSA_SCOOP_PXA_VCORE1		SCOOP_GPCR_PA11
-#define TOSA_SCOOP_TC6393_REST_IN	SCOOP_GPCR_PA12
+#define TOSA_GPIO_TC6393XB_REST_IN	(TOSA_SCOOP_GPIO_BASE + 1)
 #define TOSA_GPIO_IR_POWERDWN		(TOSA_SCOOP_GPIO_BASE + 2)
 #define TOSA_GPIO_SD_WP			(TOSA_SCOOP_GPIO_BASE + 3)
 #define TOSA_GPIO_PWR_ON		(TOSA_SCOOP_GPIO_BASE + 4)
 #define TOSA_SCOOP_AUD_PWR_ON		SCOOP_GPCR_PA16
-#define TOSA_SCOOP_BT_RESET		SCOOP_GPCR_PA17
-#define TOSA_SCOOP_BT_PWR_EN		SCOOP_GPCR_PA18
+#define TOSA_GPIO_BT_RESET		(TOSA_SCOOP_GPIO_BASE + 6)
+#define TOSA_GPIO_BT_PWR_EN		(TOSA_SCOOP_GPIO_BASE + 7)
 #define TOSA_SCOOP_AC_IN_OL		SCOOP_GPCR_PA19
 
 /* GPIO Direction   1 : output mode / 0:input mode */
-#define TOSA_SCOOP_IO_DIR     ( TOSA_SCOOP_PXA_VCORE1 | TOSA_SCOOP_TC6393_REST_IN | \
-		TOSA_SCOOP_AUD_PWR_ON |\
-		TOSA_SCOOP_BT_RESET | TOSA_SCOOP_BT_PWR_EN )
-/* GPIO out put level when init   1: Hi */
-#define TOSA_SCOOP_IO_OUT     ( TOSA_SCOOP_TC6393_REST_IN )
+#define TOSA_SCOOP_IO_DIR     (TOSA_SCOOP_PXA_VCORE1 | \
+		TOSA_SCOOP_AUD_PWR_ON)
 
 /*
  * SCOOP2 jacket GPIOs
@@ -49,16 +46,34 @@
 #define TOSA_GPIO_NOTE_LED		(TOSA_SCOOP_JC_GPIO_BASE + 1)
 #define TOSA_GPIO_CHRG_ERR_LED		(TOSA_SCOOP_JC_GPIO_BASE + 2)
 #define TOSA_GPIO_USB_PULLUP		(TOSA_SCOOP_JC_GPIO_BASE + 3)
-#define TOSA_SCOOP_JC_TC6393_SUSPEND	SCOOP_GPCR_PA15
-#define TOSA_SCOOP_JC_TC3693_L3V_ON	SCOOP_GPCR_PA16
+#define TOSA_GPIO_TC6393XB_SUSPEND	(TOSA_SCOOP_JC_GPIO_BASE + 4)
+#define TOSA_GPIO_TC6393XB_L3V_ON	(TOSA_SCOOP_JC_GPIO_BASE + 5)
 #define TOSA_SCOOP_JC_WLAN_DETECT	SCOOP_GPCR_PA17
 #define TOSA_GPIO_WLAN_LED		(TOSA_SCOOP_JC_GPIO_BASE + 7)
 #define TOSA_SCOOP_JC_CARD_LIMIT_SEL	SCOOP_GPCR_PA19
 
 /* GPIO Direction   1 : output mode / 0:input mode */
-#define TOSA_SCOOP_JC_IO_DIR ( \
-		TOSA_SCOOP_JC_TC6393_SUSPEND | TOSA_SCOOP_JC_TC3693_L3V_ON | \
-		TOSA_SCOOP_JC_CARD_LIMIT_SEL )
+#define TOSA_SCOOP_JC_IO_DIR (TOSA_SCOOP_JC_CARD_LIMIT_SEL)
+
+/*
+ * TC6393XB GPIOs
+ */
+#define TOSA_TC6393XB_GPIO_BASE		(NR_BUILTIN_GPIO + 2 * 12)
+#define TOSA_TC6393XB_GPIO(i)		(TOSA_TC6393XB_GPIO_BASE + (i))
+#define TOSA_TC6393XB_GPIO_BIT(gpio)	(1 << (gpio - TOSA_TC6393XB_GPIO_BASE))
+
+#define TOSA_GPIO_TG_ON			(TOSA_TC6393XB_GPIO_BASE + 0)
+#define TOSA_GPIO_L_MUTE		(TOSA_TC6393XB_GPIO_BASE + 1)
+#define TOSA_GPIO_BL_C20MA		(TOSA_TC6393XB_GPIO_BASE + 3)
+#define TOSA_GPIO_CARD_VCC_ON		(TOSA_TC6393XB_GPIO_BASE + 4)
+#define TOSA_GPIO_CHARGE_OFF		(TOSA_TC6393XB_GPIO_BASE + 6)
+#define TOSA_GPIO_CHARGE_OFF_JC		(TOSA_TC6393XB_GPIO_BASE + 7)
+#define TOSA_GPIO_BAT0_V_ON		(TOSA_TC6393XB_GPIO_BASE + 9)
+#define TOSA_GPIO_BAT1_V_ON		(TOSA_TC6393XB_GPIO_BASE + 10)
+#define TOSA_GPIO_BU_CHRG_ON		(TOSA_TC6393XB_GPIO_BASE + 11)
+#define TOSA_GPIO_BAT_SW_ON		(TOSA_TC6393XB_GPIO_BASE + 12)
+#define TOSA_GPIO_BAT0_TH_ON		(TOSA_TC6393XB_GPIO_BASE + 14)
+#define TOSA_GPIO_BAT1_TH_ON		(TOSA_TC6393XB_GPIO_BASE + 15)
 
 /*
  * Timing Generator
@@ -84,13 +99,13 @@
 #define TOSA_GPIO_JACKET_DETECT		(7)
 #define TOSA_GPIO_nSD_DETECT		(9)
 #define TOSA_GPIO_nSD_INT		(10)
-#define TOSA_GPIO_TC6393_CLK		(11)
+#define TOSA_GPIO_TC6393XB_CLK		(11)
 #define TOSA_GPIO_BAT1_CRG		(12)
 #define TOSA_GPIO_CF_CD			(13)
 #define TOSA_GPIO_BAT0_CRG		(14)
-#define TOSA_GPIO_TC6393_INT		(15)
+#define TOSA_GPIO_TC6393XB_INT		(15)
 #define TOSA_GPIO_BAT0_LOW		(17)
-#define TOSA_GPIO_TC6393_RDY		(18)
+#define TOSA_GPIO_TC6393XB_RDY		(18)
 #define TOSA_GPIO_ON_RESET		(19)
 #define TOSA_GPIO_EAR_IN		(20)
 #define TOSA_GPIO_CF_IRQ		(21)	/* CF slot0 Ready */
@@ -99,6 +114,7 @@
 #define TOSA_GPIO_TP_INT		(32)	/* Touch Panel pen down interrupt */
 #define TOSA_GPIO_JC_CF_IRQ		(36)	/* CF slot1 Ready */
 #define TOSA_GPIO_BAT_LOCKED		(38)	/* Battery locked */
+#define TOSA_GPIO_IRDA_TX		(47)
 #define TOSA_GPIO_TG_SPI_SCLK		(81)
 #define TOSA_GPIO_TG_SPI_CS		(82)
 #define TOSA_GPIO_TG_SPI_MOSI		(83)
@@ -137,7 +153,7 @@
 #define TOSA_IRQ_GPIO_BAT1_CRG      	IRQ_GPIO(TOSA_GPIO_BAT1_CRG)
 #define TOSA_IRQ_GPIO_CF_CD         	IRQ_GPIO(TOSA_GPIO_CF_CD)
 #define TOSA_IRQ_GPIO_BAT0_CRG      	IRQ_GPIO(TOSA_GPIO_BAT0_CRG)
-#define TOSA_IRQ_GPIO_TC6393_INT    	IRQ_GPIO(TOSA_GPIO_TC6393_INT)
+#define TOSA_IRQ_GPIO_TC6393XB_INT    	IRQ_GPIO(TOSA_GPIO_TC6393XB_INT)
 #define TOSA_IRQ_GPIO_BAT0_LOW      	IRQ_GPIO(TOSA_GPIO_BAT0_LOW)
 #define TOSA_IRQ_GPIO_EAR_IN        	IRQ_GPIO(TOSA_GPIO_EAR_IN)
 #define TOSA_IRQ_GPIO_CF_IRQ        	IRQ_GPIO(TOSA_GPIO_CF_IRQ)
diff --git a/include/asm-arm/arch-pxa/tosa_bt.h b/include/asm-arm/arch-pxa/tosa_bt.h
new file mode 100644
index 0000000..efc3c3d
--- /dev/null
+++ b/include/asm-arm/arch-pxa/tosa_bt.h
@@ -0,0 +1,22 @@
+/*
+ * Tosa bluetooth built-in chip control.
+ *
+ * Later it may be shared with some other platforms.
+ *
+ * Copyright (c) 2008 Dmitry Baryshkov
+ *
+ * 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 TOSA_BT_H
+#define TOSA_BT_H
+
+struct tosa_bt_data {
+	int gpio_pwr;
+	int gpio_reset;
+};
+
+#endif
+
diff --git a/include/asm-arm/arch-pxa/uncompress.h b/include/asm-arm/arch-pxa/uncompress.h
index dadf4c2..f455126 100644
--- a/include/asm-arm/arch-pxa/uncompress.h
+++ b/include/asm-arm/arch-pxa/uncompress.h
@@ -11,11 +11,11 @@
 
 #include <linux/serial_reg.h>
 #include <asm/arch/pxa-regs.h>
+#include <asm/mach-types.h>
 
-#define __REG(x)	((volatile unsigned long *)x)
+#define __REG(x)       ((volatile unsigned long *)x)
 
-#define UART		FFUART
-
+static volatile unsigned long *UART = FFUART;
 
 static inline void putc(char c)
 {
@@ -33,8 +33,13 @@
 {
 }
 
+static inline void arch_decomp_setup(void)
+{
+	if (machine_is_littleton())
+		UART = STUART;
+}
+
 /*
  * nothing to do
  */
-#define arch_decomp_setup()
 #define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-pxa/zylonite.h b/include/asm-arm/arch-pxa/zylonite.h
index de577de..0d35ca0 100644
--- a/include/asm-arm/arch-pxa/zylonite.h
+++ b/include/asm-arm/arch-pxa/zylonite.h
@@ -16,6 +16,8 @@
 extern struct platform_mmc_slot zylonite_mmc_slot[];
 
 extern int gpio_eth_irq;
+extern int gpio_debug_led1;
+extern int gpio_debug_led2;
 
 extern int wm9713_irq;
 
diff --git a/include/asm-arm/hardware/iop3xx-adma.h b/include/asm-arm/hardware/iop3xx-adma.h
index a32b86a..af64676 100644
--- a/include/asm-arm/hardware/iop3xx-adma.h
+++ b/include/asm-arm/hardware/iop3xx-adma.h
@@ -260,7 +260,7 @@
 static inline int iop3xx_aau_xor_slot_count(size_t len, int src_cnt,
 					int *slots_per_op)
 {
-	static const int slot_count_table[] = { 0,
+	static const char slot_count_table[] = {
 						1, 1, 1, 1, /* 01 - 04 */
 						2, 2, 2, 2, /* 05 - 08 */
 						4, 4, 4, 4, /* 09 - 12 */
@@ -270,7 +270,7 @@
 						8, 8, 8, 8, /* 25 - 28 */
 						8, 8, 8, 8, /* 29 - 32 */
 					      };
-	*slots_per_op = slot_count_table[src_cnt];
+	*slots_per_op = slot_count_table[src_cnt - 1];
 	return *slots_per_op;
 }
 
diff --git a/include/asm-arm/kgdb.h b/include/asm-arm/kgdb.h
new file mode 100644
index 0000000..67af4b8
--- /dev/null
+++ b/include/asm-arm/kgdb.h
@@ -0,0 +1,104 @@
+/*
+ * ARM KGDB support
+ *
+ * Author: Deepak Saxena <dsaxena@mvista.com>
+ *
+ * Copyright (C) 2002 MontaVista Software Inc.
+ *
+ */
+
+#ifndef __ARM_KGDB_H__
+#define __ARM_KGDB_H__
+
+#include <linux/ptrace.h>
+
+/*
+ * GDB assumes that we're a user process being debugged, so
+ * it will send us an SWI command to write into memory as the
+ * debug trap. When an SWI occurs, the next instruction addr is
+ * placed into R14_svc before jumping to the vector trap.
+ * This doesn't work for kernel debugging as we are already in SVC
+ * we would loose the kernel's LR, which is a bad thing. This
+ * is  bad thing.
+ *
+ * By doing this as an undefined instruction trap, we force a mode
+ * switch from SVC to UND mode, allowing us to save full kernel state.
+ *
+ * We also define a KGDB_COMPILED_BREAK which can be used to compile
+ * in breakpoints. This is important for things like sysrq-G and for
+ * the initial breakpoint from trap_init().
+ *
+ * Note to ARM HW designers: Add real trap support like SH && PPC to
+ * make our lives much much simpler. :)
+ */
+#define BREAK_INSTR_SIZE	4
+#define GDB_BREAKINST		0xef9f0001
+#define KGDB_BREAKINST		0xe7ffdefe
+#define KGDB_COMPILED_BREAK	0xe7ffdeff
+#define CACHE_FLUSH_IS_SAFE	1
+
+#ifndef	__ASSEMBLY__
+
+static inline void arch_kgdb_breakpoint(void)
+{
+	asm(".word 0xe7ffdeff");
+}
+
+extern void kgdb_handle_bus_error(void);
+extern int kgdb_fault_expected;
+
+#endif /* !__ASSEMBLY__ */
+
+/*
+ * From Kevin Hilman:
+ *
+ * gdb is expecting the following registers layout.
+ *
+ * r0-r15: 1 long word each
+ * f0-f7:  unused, 3 long words each !!
+ * fps:    unused, 1 long word
+ * cpsr:   1 long word
+ *
+ * Even though f0-f7 and fps are not used, they need to be
+ * present in the registers sent for correct processing in
+ * the host-side gdb.
+ *
+ * In particular, it is crucial that CPSR is in the right place,
+ * otherwise gdb will not be able to correctly interpret stepping over
+ * conditional branches.
+ */
+#define _GP_REGS		16
+#define _FP_REGS		8
+#define _EXTRA_REGS		2
+#define GDB_MAX_REGS		(_GP_REGS + (_FP_REGS * 3) + _EXTRA_REGS)
+
+#define KGDB_MAX_NO_CPUS	1
+#define BUFMAX			400
+#define NUMREGBYTES		(GDB_MAX_REGS << 2)
+#define NUMCRITREGBYTES		(32 << 2)
+
+#define _R0			0
+#define _R1			1
+#define _R2			2
+#define _R3			3
+#define _R4			4
+#define _R5			5
+#define _R6			6
+#define _R7			7
+#define _R8			8
+#define _R9			9
+#define _R10			10
+#define _FP			11
+#define _IP			12
+#define _SPT			13
+#define _LR			14
+#define _PC			15
+#define _CPSR			(GDB_MAX_REGS - 1)
+
+/*
+ * So that we can denote the end of a frame for tracing,
+ * in the simple case:
+ */
+#define CFI_END_FRAME(func)	__CFI_END_FRAME(_PC, _SPT, func)
+
+#endif /* __ASM_KGDB_H__ */
diff --git a/include/asm-arm/mach/udc_pxa2xx.h b/include/asm-arm/mach/udc_pxa2xx.h
index f9f3606..9e5ed7c 100644
--- a/include/asm-arm/mach/udc_pxa2xx.h
+++ b/include/asm-arm/mach/udc_pxa2xx.h
@@ -23,6 +23,7 @@
 	 */
 	bool	gpio_vbus_inverted;
 	u16	gpio_vbus;			/* high == vbus present */
+	bool	gpio_pullup_inverted;
 	u16	gpio_pullup;			/* high == pullup activated */
 };
 
diff --git a/include/asm-arm/plat-orion/mv_xor.h b/include/asm-arm/plat-orion/mv_xor.h
new file mode 100644
index 0000000..c349e8ff
--- /dev/null
+++ b/include/asm-arm/plat-orion/mv_xor.h
@@ -0,0 +1,28 @@
+/*
+ * Marvell XOR platform device data definition file.
+ */
+
+#ifndef __ASM_PLAT_ORION_MV_XOR_H
+#define __ASM_PLAT_ORION_MV_XOR_H
+
+#include <linux/dmaengine.h>
+#include <linux/mbus.h>
+
+#define MV_XOR_SHARED_NAME	"mv_xor_shared"
+#define MV_XOR_NAME		"mv_xor"
+
+struct mbus_dram_target_info;
+
+struct mv_xor_platform_shared_data {
+	struct mbus_dram_target_info	*dram;
+};
+
+struct mv_xor_platform_data {
+	struct platform_device		*shared;
+	int				hw_id;
+	dma_cap_mask_t			cap_mask;
+	size_t				pool_size;
+};
+
+
+#endif
diff --git a/include/asm-arm/traps.h b/include/asm-arm/traps.h
index f1541af..aa399ae 100644
--- a/include/asm-arm/traps.h
+++ b/include/asm-arm/traps.h
@@ -24,4 +24,6 @@
 	       ptr < (unsigned long)&__exception_text_end;
 }
 
+extern void __init early_trap_init(void);
+
 #endif
diff --git a/include/asm-avr32/arch-at32ap/at32ap700x.h b/include/asm-avr32/arch-at32ap/at32ap700x.h
index 31e48b0..d18a305 100644
--- a/include/asm-avr32/arch-at32ap/at32ap700x.h
+++ b/include/asm-avr32/arch-at32ap/at32ap700x.h
@@ -30,4 +30,20 @@
 #define GPIO_PIN_PD(N)	(GPIO_PIOD_BASE + (N))
 #define GPIO_PIN_PE(N)	(GPIO_PIOE_BASE + (N))
 
+
+/*
+ * DMAC peripheral hardware handshaking interfaces, used with dw_dmac
+ */
+#define DMAC_MCI_RX		0
+#define DMAC_MCI_TX		1
+#define DMAC_DAC_TX		2
+#define DMAC_AC97_A_RX		3
+#define DMAC_AC97_A_TX		4
+#define DMAC_AC97_B_RX		5
+#define DMAC_AC97_B_TX		6
+#define DMAC_DMAREQ_0		7
+#define DMAC_DMAREQ_1		8
+#define DMAC_DMAREQ_2		9
+#define DMAC_DMAREQ_3		10
+
 #endif /* __ASM_ARCH_AT32AP700X_H__ */
diff --git a/include/asm-ia64/Kbuild b/include/asm-ia64/Kbuild
index eb24a3f..ccbe8ae 100644
--- a/include/asm-ia64/Kbuild
+++ b/include/asm-ia64/Kbuild
@@ -5,12 +5,12 @@
 header-y += fpswa.h
 header-y += ia64regs.h
 header-y += intel_intrin.h
-header-y += intrinsics.h
 header-y += perfmon_default_smpl.h
 header-y += ptrace_offsets.h
 header-y += rse.h
 header-y += ucontext.h
 
 unifdef-y += gcc_intrin.h
+unifdef-y += intrinsics.h
 unifdef-y += perfmon.h
 unifdef-y += ustack.h
diff --git a/include/asm-ia64/gcc_intrin.h b/include/asm-ia64/gcc_intrin.h
index 2fe292c..0f5b559 100644
--- a/include/asm-ia64/gcc_intrin.h
+++ b/include/asm-ia64/gcc_intrin.h
@@ -32,7 +32,7 @@
 register unsigned long ia64_r13 asm ("r13") __used;
 #endif
 
-#define ia64_setreg(regnum, val)						\
+#define ia64_native_setreg(regnum, val)						\
 ({										\
 	switch (regnum) {							\
 	    case _IA64_REG_PSR_L:						\
@@ -61,7 +61,7 @@
 	}									\
 })
 
-#define ia64_getreg(regnum)							\
+#define ia64_native_getreg(regnum)						\
 ({										\
 	__u64 ia64_intri_res;							\
 										\
@@ -385,7 +385,7 @@
 
 #define ia64_invala() asm volatile ("invala" ::: "memory")
 
-#define ia64_thash(addr)							\
+#define ia64_native_thash(addr)							\
 ({										\
 	__u64 ia64_intri_res;							\
 	asm volatile ("thash %0=%1" : "=r"(ia64_intri_res) : "r" (addr));	\
@@ -438,10 +438,10 @@
 #define ia64_set_pmd(index, val)						\
 	asm volatile ("mov pmd[%0]=%1" :: "r"(index), "r"(val) : "memory")
 
-#define ia64_set_rr(index, val)							\
+#define ia64_native_set_rr(index, val)							\
 	asm volatile ("mov rr[%0]=%1" :: "r"(index), "r"(val) : "memory");
 
-#define ia64_get_cpuid(index)								\
+#define ia64_native_get_cpuid(index)							\
 ({											\
 	__u64 ia64_intri_res;								\
 	asm volatile ("mov %0=cpuid[%r1]" : "=r"(ia64_intri_res) : "rO"(index));	\
@@ -477,33 +477,33 @@
 })
 
 
-#define ia64_get_pmd(index)							\
+#define ia64_native_get_pmd(index)						\
 ({										\
 	__u64 ia64_intri_res;							\
 	asm volatile ("mov %0=pmd[%1]" : "=r"(ia64_intri_res) : "r"(index));	\
 	ia64_intri_res;								\
 })
 
-#define ia64_get_rr(index)							\
+#define ia64_native_get_rr(index)						\
 ({										\
 	__u64 ia64_intri_res;							\
 	asm volatile ("mov %0=rr[%1]" : "=r"(ia64_intri_res) : "r" (index));	\
 	ia64_intri_res;								\
 })
 
-#define ia64_fc(addr)	asm volatile ("fc %0" :: "r"(addr) : "memory")
+#define ia64_native_fc(addr)	asm volatile ("fc %0" :: "r"(addr) : "memory")
 
 
 #define ia64_sync_i()	asm volatile (";; sync.i" ::: "memory")
 
-#define ia64_ssm(mask)	asm volatile ("ssm %0":: "i"((mask)) : "memory")
-#define ia64_rsm(mask)	asm volatile ("rsm %0":: "i"((mask)) : "memory")
+#define ia64_native_ssm(mask)	asm volatile ("ssm %0":: "i"((mask)) : "memory")
+#define ia64_native_rsm(mask)	asm volatile ("rsm %0":: "i"((mask)) : "memory")
 #define ia64_sum(mask)	asm volatile ("sum %0":: "i"((mask)) : "memory")
 #define ia64_rum(mask)	asm volatile ("rum %0":: "i"((mask)) : "memory")
 
 #define ia64_ptce(addr)	asm volatile ("ptc.e %0" :: "r"(addr))
 
-#define ia64_ptcga(addr, size)							\
+#define ia64_native_ptcga(addr, size)						\
 do {										\
 	asm volatile ("ptc.ga %0,%1" :: "r"(addr), "r"(size) : "memory");	\
 	ia64_dv_serialize_data();						\
@@ -608,7 +608,7 @@
         }								\
 })
 
-#define ia64_intrin_local_irq_restore(x)			\
+#define ia64_native_intrin_local_irq_restore(x)			\
 do {								\
 	asm volatile (";;   cmp.ne p6,p7=%0,r0;;"		\
 		      "(p6) ssm psr.i;"				\
diff --git a/include/asm-ia64/hw_irq.h b/include/asm-ia64/hw_irq.h
index 76366dc..5c99cbc 100644
--- a/include/asm-ia64/hw_irq.h
+++ b/include/asm-ia64/hw_irq.h
@@ -15,7 +15,11 @@
 #include <asm/ptrace.h>
 #include <asm/smp.h>
 
+#ifndef CONFIG_PARAVIRT
 typedef u8 ia64_vector;
+#else
+typedef u16 ia64_vector;
+#endif
 
 /*
  * 0 special
@@ -104,13 +108,24 @@
 
 extern struct hw_interrupt_type irq_type_ia64_lsapic;	/* CPU-internal interrupt controller */
 
+#ifdef CONFIG_PARAVIRT_GUEST
+#include <asm/paravirt.h>
+#else
+#define ia64_register_ipi	ia64_native_register_ipi
+#define assign_irq_vector	ia64_native_assign_irq_vector
+#define free_irq_vector		ia64_native_free_irq_vector
+#define register_percpu_irq	ia64_native_register_percpu_irq
+#define ia64_resend_irq		ia64_native_resend_irq
+#endif
+
+extern void ia64_native_register_ipi(void);
 extern int bind_irq_vector(int irq, int vector, cpumask_t domain);
-extern int assign_irq_vector (int irq);	/* allocate a free vector */
-extern void free_irq_vector (int vector);
+extern int ia64_native_assign_irq_vector (int irq);	/* allocate a free vector */
+extern void ia64_native_free_irq_vector (int vector);
 extern int reserve_irq_vector (int vector);
 extern void __setup_vector_irq(int cpu);
 extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect);
-extern void register_percpu_irq (ia64_vector vec, struct irqaction *action);
+extern void ia64_native_register_percpu_irq (ia64_vector vec, struct irqaction *action);
 extern int check_irq_used (int irq);
 extern void destroy_and_reserve_irq (unsigned int irq);
 
@@ -122,7 +137,7 @@
 static inline void irq_complete_move(unsigned int irq) {}
 #endif
 
-static inline void ia64_resend_irq(unsigned int vector)
+static inline void ia64_native_resend_irq(unsigned int vector)
 {
 	platform_send_ipi(smp_processor_id(), vector, IA64_IPI_DM_INT, 0);
 }
diff --git a/include/asm-ia64/intel_intrin.h b/include/asm-ia64/intel_intrin.h
index a520d10..53cec57 100644
--- a/include/asm-ia64/intel_intrin.h
+++ b/include/asm-ia64/intel_intrin.h
@@ -16,8 +16,8 @@
 		 	 * intrinsic
 		 	 */
 
-#define ia64_getreg		__getReg
-#define ia64_setreg		__setReg
+#define ia64_native_getreg	__getReg
+#define ia64_native_setreg	__setReg
 
 #define ia64_hint		__hint
 #define ia64_hint_pause		__hint_pause
@@ -39,10 +39,10 @@
 #define ia64_invala_fr		__invala_fr
 #define ia64_nop		__nop
 #define ia64_sum		__sum
-#define ia64_ssm		__ssm
+#define ia64_native_ssm		__ssm
 #define ia64_rum		__rum
-#define ia64_rsm		__rsm
-#define ia64_fc 		__fc
+#define ia64_native_rsm		__rsm
+#define ia64_native_fc 		__fc
 
 #define ia64_ldfs		__ldfs
 #define ia64_ldfd		__ldfd
@@ -88,16 +88,17 @@
 		__setIndReg(_IA64_REG_INDR_PMC, index, val)
 #define ia64_set_pmd(index, val)	\
 		__setIndReg(_IA64_REG_INDR_PMD, index, val)
-#define ia64_set_rr(index, val)	\
+#define ia64_native_set_rr(index, val)	\
 		__setIndReg(_IA64_REG_INDR_RR, index, val)
 
-#define ia64_get_cpuid(index) 	__getIndReg(_IA64_REG_INDR_CPUID, index)
-#define __ia64_get_dbr(index) 	__getIndReg(_IA64_REG_INDR_DBR, index)
-#define ia64_get_ibr(index) 	__getIndReg(_IA64_REG_INDR_IBR, index)
-#define ia64_get_pkr(index) 	__getIndReg(_IA64_REG_INDR_PKR, index)
-#define ia64_get_pmc(index) 	__getIndReg(_IA64_REG_INDR_PMC, index)
-#define ia64_get_pmd(index)  	__getIndReg(_IA64_REG_INDR_PMD, index)
-#define ia64_get_rr(index) 	__getIndReg(_IA64_REG_INDR_RR, index)
+#define ia64_native_get_cpuid(index)	\
+		__getIndReg(_IA64_REG_INDR_CPUID, index)
+#define __ia64_get_dbr(index)		__getIndReg(_IA64_REG_INDR_DBR, index)
+#define ia64_get_ibr(index)		__getIndReg(_IA64_REG_INDR_IBR, index)
+#define ia64_get_pkr(index)		__getIndReg(_IA64_REG_INDR_PKR, index)
+#define ia64_get_pmc(index)		__getIndReg(_IA64_REG_INDR_PMC, index)
+#define ia64_native_get_pmd(index)	__getIndReg(_IA64_REG_INDR_PMD, index)
+#define ia64_native_get_rr(index)	__getIndReg(_IA64_REG_INDR_RR, index)
 
 #define ia64_srlz_d		__dsrlz
 #define ia64_srlz_i		__isrlz
@@ -119,16 +120,16 @@
 #define ia64_ld8_acq		__ld8_acq
 
 #define ia64_sync_i		__synci
-#define ia64_thash		__thash
-#define ia64_ttag		__ttag
+#define ia64_native_thash	__thash
+#define ia64_native_ttag	__ttag
 #define ia64_itcd		__itcd
 #define ia64_itci		__itci
 #define ia64_itrd		__itrd
 #define ia64_itri		__itri
 #define ia64_ptce		__ptce
 #define ia64_ptcl		__ptcl
-#define ia64_ptcg		__ptcg
-#define ia64_ptcga		__ptcga
+#define ia64_native_ptcg	__ptcg
+#define ia64_native_ptcga	__ptcga
 #define ia64_ptri		__ptri
 #define ia64_ptrd		__ptrd
 #define ia64_dep_mi		_m64_dep_mi
@@ -145,13 +146,13 @@
 #define ia64_lfetch_fault	__lfetch_fault
 #define ia64_lfetch_fault_excl	__lfetch_fault_excl
 
-#define ia64_intrin_local_irq_restore(x)		\
+#define ia64_native_intrin_local_irq_restore(x)		\
 do {							\
 	if ((x) != 0) {					\
-		ia64_ssm(IA64_PSR_I);			\
+		ia64_native_ssm(IA64_PSR_I);		\
 		ia64_srlz_d();				\
 	} else {					\
-		ia64_rsm(IA64_PSR_I);			\
+		ia64_native_rsm(IA64_PSR_I);		\
 	}						\
 } while (0)
 
diff --git a/include/asm-ia64/intrinsics.h b/include/asm-ia64/intrinsics.h
index f1135b5..47d686d 100644
--- a/include/asm-ia64/intrinsics.h
+++ b/include/asm-ia64/intrinsics.h
@@ -18,6 +18,17 @@
 # include <asm/gcc_intrin.h>
 #endif
 
+#define ia64_native_get_psr_i()	(ia64_native_getreg(_IA64_REG_PSR) & IA64_PSR_I)
+
+#define ia64_native_set_rr0_to_rr4(val0, val1, val2, val3, val4)	\
+do {									\
+	ia64_native_set_rr(0x0000000000000000UL, (val0));		\
+	ia64_native_set_rr(0x2000000000000000UL, (val1));		\
+	ia64_native_set_rr(0x4000000000000000UL, (val2));		\
+	ia64_native_set_rr(0x6000000000000000UL, (val3));		\
+	ia64_native_set_rr(0x8000000000000000UL, (val4));		\
+} while (0)
+
 /*
  * Force an unresolved reference if someone tries to use
  * ia64_fetch_and_add() with a bad value.
@@ -183,4 +194,48 @@
 #endif /* !CONFIG_IA64_DEBUG_CMPXCHG */
 
 #endif
+
+#ifdef __KERNEL__
+#include <asm/paravirt_privop.h>
+#endif
+
+#ifndef __ASSEMBLY__
+#if defined(CONFIG_PARAVIRT) && defined(__KERNEL__)
+#define IA64_INTRINSIC_API(name)	pv_cpu_ops.name
+#define IA64_INTRINSIC_MACRO(name)	paravirt_ ## name
+#else
+#define IA64_INTRINSIC_API(name)	ia64_native_ ## name
+#define IA64_INTRINSIC_MACRO(name)	ia64_native_ ## name
+#endif
+
+/************************************************/
+/* Instructions paravirtualized for correctness */
+/************************************************/
+/* fc, thash, get_cpuid, get_pmd, get_eflags, set_eflags */
+/* Note that "ttag" and "cover" are also privilege-sensitive; "ttag"
+ * is not currently used (though it may be in a long-format VHPT system!)
+ */
+#define ia64_fc				IA64_INTRINSIC_API(fc)
+#define ia64_thash			IA64_INTRINSIC_API(thash)
+#define ia64_get_cpuid			IA64_INTRINSIC_API(get_cpuid)
+#define ia64_get_pmd			IA64_INTRINSIC_API(get_pmd)
+
+
+/************************************************/
+/* Instructions paravirtualized for performance */
+/************************************************/
+#define ia64_ssm			IA64_INTRINSIC_MACRO(ssm)
+#define ia64_rsm			IA64_INTRINSIC_MACRO(rsm)
+#define ia64_getreg			IA64_INTRINSIC_API(getreg)
+#define ia64_setreg			IA64_INTRINSIC_API(setreg)
+#define ia64_set_rr			IA64_INTRINSIC_API(set_rr)
+#define ia64_get_rr			IA64_INTRINSIC_API(get_rr)
+#define ia64_ptcga			IA64_INTRINSIC_API(ptcga)
+#define ia64_get_psr_i			IA64_INTRINSIC_API(get_psr_i)
+#define ia64_intrin_local_irq_restore	\
+	IA64_INTRINSIC_API(intrin_local_irq_restore)
+#define ia64_set_rr0_to_rr4		IA64_INTRINSIC_API(set_rr0_to_rr4)
+
+#endif /* !__ASSEMBLY__ */
+
 #endif /* _ASM_IA64_INTRINSICS_H */
diff --git a/include/asm-ia64/iosapic.h b/include/asm-ia64/iosapic.h
index a3a4288..b9c102e 100644
--- a/include/asm-ia64/iosapic.h
+++ b/include/asm-ia64/iosapic.h
@@ -55,13 +55,27 @@
 
 #define NR_IOSAPICS			256
 
-static inline unsigned int __iosapic_read(char __iomem *iosapic, unsigned int reg)
+#ifdef CONFIG_PARAVIRT_GUEST
+#include <asm/paravirt.h>
+#else
+#define iosapic_pcat_compat_init	ia64_native_iosapic_pcat_compat_init
+#define __iosapic_read			__ia64_native_iosapic_read
+#define __iosapic_write			__ia64_native_iosapic_write
+#define iosapic_get_irq_chip		ia64_native_iosapic_get_irq_chip
+#endif
+
+extern void __init ia64_native_iosapic_pcat_compat_init(void);
+extern struct irq_chip *ia64_native_iosapic_get_irq_chip(unsigned long trigger);
+
+static inline unsigned int
+__ia64_native_iosapic_read(char __iomem *iosapic, unsigned int reg)
 {
 	writel(reg, iosapic + IOSAPIC_REG_SELECT);
 	return readl(iosapic + IOSAPIC_WINDOW);
 }
 
-static inline void __iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val)
+static inline void
+__ia64_native_iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val)
 {
 	writel(reg, iosapic + IOSAPIC_REG_SELECT);
 	writel(val, iosapic + IOSAPIC_WINDOW);
diff --git a/include/asm-ia64/irq.h b/include/asm-ia64/irq.h
index a66d268..3627116 100644
--- a/include/asm-ia64/irq.h
+++ b/include/asm-ia64/irq.h
@@ -13,14 +13,7 @@
 
 #include <linux/types.h>
 #include <linux/cpumask.h>
-
-#define NR_VECTORS	256
-
-#if (NR_VECTORS + 32 * NR_CPUS) < 1024
-#define NR_IRQS (NR_VECTORS + 32 * NR_CPUS)
-#else
-#define NR_IRQS 1024
-#endif
+#include <asm-ia64/nr-irqs.h>
 
 static __inline__ int
 irq_canonicalize (int irq)
diff --git a/include/asm-ia64/mmu_context.h b/include/asm-ia64/mmu_context.h
index cef2400..040bc87 100644
--- a/include/asm-ia64/mmu_context.h
+++ b/include/asm-ia64/mmu_context.h
@@ -152,11 +152,7 @@
 #  endif
 #endif
 
-	ia64_set_rr(0x0000000000000000UL, rr0);
-	ia64_set_rr(0x2000000000000000UL, rr1);
-	ia64_set_rr(0x4000000000000000UL, rr2);
-	ia64_set_rr(0x6000000000000000UL, rr3);
-	ia64_set_rr(0x8000000000000000UL, rr4);
+	ia64_set_rr0_to_rr4(rr0, rr1, rr2, rr3, rr4);
 	ia64_srlz_i();			/* srlz.i implies srlz.d */
 }
 
diff --git a/include/asm-ia64/native/inst.h b/include/asm-ia64/native/inst.h
new file mode 100644
index 0000000..c953a2c
--- /dev/null
+++ b/include/asm-ia64/native/inst.h
@@ -0,0 +1,175 @@
+/******************************************************************************
+ * include/asm-ia64/native/inst.h
+ *
+ * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#define DO_SAVE_MIN		IA64_NATIVE_DO_SAVE_MIN
+
+#define __paravirt_switch_to			ia64_native_switch_to
+#define __paravirt_leave_syscall		ia64_native_leave_syscall
+#define __paravirt_work_processed_syscall	ia64_native_work_processed_syscall
+#define __paravirt_leave_kernel			ia64_native_leave_kernel
+#define __paravirt_pending_syscall_end		ia64_work_pending_syscall_end
+#define __paravirt_work_processed_syscall_target \
+						ia64_work_processed_syscall
+
+#ifdef CONFIG_PARAVIRT_GUEST_ASM_CLOBBER_CHECK
+# define PARAVIRT_POISON	0xdeadbeefbaadf00d
+# define CLOBBER(clob)				\
+	;;					\
+	movl clob = PARAVIRT_POISON;		\
+	;;
+#else
+# define CLOBBER(clob)		/* nothing */
+#endif
+
+#define MOV_FROM_IFA(reg)	\
+	mov reg = cr.ifa
+
+#define MOV_FROM_ITIR(reg)	\
+	mov reg = cr.itir
+
+#define MOV_FROM_ISR(reg)	\
+	mov reg = cr.isr
+
+#define MOV_FROM_IHA(reg)	\
+	mov reg = cr.iha
+
+#define MOV_FROM_IPSR(pred, reg)	\
+(pred)	mov reg = cr.ipsr
+
+#define MOV_FROM_IIM(reg)	\
+	mov reg = cr.iim
+
+#define MOV_FROM_IIP(reg)	\
+	mov reg = cr.iip
+
+#define MOV_FROM_IVR(reg, clob)	\
+	mov reg = cr.ivr	\
+	CLOBBER(clob)
+
+#define MOV_FROM_PSR(pred, reg, clob)	\
+(pred)	mov reg = psr			\
+	CLOBBER(clob)
+
+#define MOV_TO_IFA(reg, clob)	\
+	mov cr.ifa = reg	\
+	CLOBBER(clob)
+
+#define MOV_TO_ITIR(pred, reg, clob)	\
+(pred)	mov cr.itir = reg		\
+	CLOBBER(clob)
+
+#define MOV_TO_IHA(pred, reg, clob)	\
+(pred)	mov cr.iha = reg		\
+	CLOBBER(clob)
+
+#define MOV_TO_IPSR(pred, reg, clob)		\
+(pred)	mov cr.ipsr = reg			\
+	CLOBBER(clob)
+
+#define MOV_TO_IFS(pred, reg, clob)	\
+(pred)	mov cr.ifs = reg		\
+	CLOBBER(clob)
+
+#define MOV_TO_IIP(reg, clob)	\
+	mov cr.iip = reg	\
+	CLOBBER(clob)
+
+#define MOV_TO_KR(kr, reg, clob0, clob1)	\
+	mov IA64_KR(kr) = reg			\
+	CLOBBER(clob0)				\
+	CLOBBER(clob1)
+
+#define ITC_I(pred, reg, clob)	\
+(pred)	itc.i reg		\
+	CLOBBER(clob)
+
+#define ITC_D(pred, reg, clob)	\
+(pred)	itc.d reg		\
+	CLOBBER(clob)
+
+#define ITC_I_AND_D(pred_i, pred_d, reg, clob)	\
+(pred_i) itc.i reg;				\
+(pred_d) itc.d reg				\
+	CLOBBER(clob)
+
+#define THASH(pred, reg0, reg1, clob)		\
+(pred)	thash reg0 = reg1			\
+	CLOBBER(clob)
+
+#define SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(clob0, clob1)		\
+	ssm psr.ic | PSR_DEFAULT_BITS					\
+	CLOBBER(clob0)							\
+	CLOBBER(clob1)							\
+	;;								\
+	srlz.i /* guarantee that interruption collectin is on */	\
+	;;
+
+#define SSM_PSR_IC_AND_SRLZ_D(clob0, clob1)	\
+	ssm psr.ic				\
+	CLOBBER(clob0)				\
+	CLOBBER(clob1)				\
+	;;					\
+	srlz.d
+
+#define RSM_PSR_IC(clob)	\
+	rsm psr.ic		\
+	CLOBBER(clob)
+
+#define SSM_PSR_I(pred, pred_clob, clob)	\
+(pred)	ssm psr.i				\
+	CLOBBER(clob)
+
+#define RSM_PSR_I(pred, clob0, clob1)	\
+(pred)	rsm psr.i			\
+	CLOBBER(clob0)			\
+	CLOBBER(clob1)
+
+#define RSM_PSR_I_IC(clob0, clob1, clob2)	\
+	rsm psr.i | psr.ic			\
+	CLOBBER(clob0)				\
+	CLOBBER(clob1)				\
+	CLOBBER(clob2)
+
+#define RSM_PSR_DT		\
+	rsm psr.dt
+
+#define SSM_PSR_DT_AND_SRLZ_I	\
+	ssm psr.dt		\
+	;;			\
+	srlz.i
+
+#define BSW_0(clob0, clob1, clob2)	\
+	bsw.0				\
+	CLOBBER(clob0)			\
+	CLOBBER(clob1)			\
+	CLOBBER(clob2)
+
+#define BSW_1(clob0, clob1)	\
+	bsw.1			\
+	CLOBBER(clob0)		\
+	CLOBBER(clob1)
+
+#define COVER	\
+	cover
+
+#define RFI	\
+	rfi
diff --git a/include/asm-ia64/native/irq.h b/include/asm-ia64/native/irq.h
new file mode 100644
index 0000000..efe9ff7
--- /dev/null
+++ b/include/asm-ia64/native/irq.h
@@ -0,0 +1,35 @@
+/******************************************************************************
+ * include/asm-ia64/native/irq.h
+ *
+ * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * 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
+ *
+ * moved from linux/include/asm-ia64/irq.h.
+ */
+
+#ifndef _ASM_IA64_NATIVE_IRQ_H
+#define _ASM_IA64_NATIVE_IRQ_H
+
+#define NR_VECTORS	256
+
+#if (NR_VECTORS + 32 * NR_CPUS) < 1024
+#define IA64_NATIVE_NR_IRQS (NR_VECTORS + 32 * NR_CPUS)
+#else
+#define IA64_NATIVE_NR_IRQS 1024
+#endif
+
+#endif /* _ASM_IA64_NATIVE_IRQ_H */
diff --git a/include/asm-ia64/paravirt.h b/include/asm-ia64/paravirt.h
new file mode 100644
index 0000000..1b4df12
--- /dev/null
+++ b/include/asm-ia64/paravirt.h
@@ -0,0 +1,255 @@
+/******************************************************************************
+ * include/asm-ia64/paravirt.h
+ *
+ * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+#ifndef __ASM_PARAVIRT_H
+#define __ASM_PARAVIRT_H
+
+#ifdef CONFIG_PARAVIRT_GUEST
+
+#define PARAVIRT_HYPERVISOR_TYPE_DEFAULT	0
+#define PARAVIRT_HYPERVISOR_TYPE_XEN		1
+
+#ifndef __ASSEMBLY__
+
+#include <asm/hw_irq.h>
+#include <asm/meminit.h>
+
+/******************************************************************************
+ * general info
+ */
+struct pv_info {
+	unsigned int kernel_rpl;
+	int paravirt_enabled;
+	const char *name;
+};
+
+extern struct pv_info pv_info;
+
+static inline int paravirt_enabled(void)
+{
+	return pv_info.paravirt_enabled;
+}
+
+static inline unsigned int get_kernel_rpl(void)
+{
+	return pv_info.kernel_rpl;
+}
+
+/******************************************************************************
+ * initialization hooks.
+ */
+struct rsvd_region;
+
+struct pv_init_ops {
+	void (*banner)(void);
+
+	int (*reserve_memory)(struct rsvd_region *region);
+
+	void (*arch_setup_early)(void);
+	void (*arch_setup_console)(char **cmdline_p);
+	int (*arch_setup_nomca)(void);
+
+	void (*post_smp_prepare_boot_cpu)(void);
+};
+
+extern struct pv_init_ops pv_init_ops;
+
+static inline void paravirt_banner(void)
+{
+	if (pv_init_ops.banner)
+		pv_init_ops.banner();
+}
+
+static inline int paravirt_reserve_memory(struct rsvd_region *region)
+{
+	if (pv_init_ops.reserve_memory)
+		return pv_init_ops.reserve_memory(region);
+	return 0;
+}
+
+static inline void paravirt_arch_setup_early(void)
+{
+	if (pv_init_ops.arch_setup_early)
+		pv_init_ops.arch_setup_early();
+}
+
+static inline void paravirt_arch_setup_console(char **cmdline_p)
+{
+	if (pv_init_ops.arch_setup_console)
+		pv_init_ops.arch_setup_console(cmdline_p);
+}
+
+static inline int paravirt_arch_setup_nomca(void)
+{
+	if (pv_init_ops.arch_setup_nomca)
+		return pv_init_ops.arch_setup_nomca();
+	return 0;
+}
+
+static inline void paravirt_post_smp_prepare_boot_cpu(void)
+{
+	if (pv_init_ops.post_smp_prepare_boot_cpu)
+		pv_init_ops.post_smp_prepare_boot_cpu();
+}
+
+/******************************************************************************
+ * replacement of iosapic operations.
+ */
+
+struct pv_iosapic_ops {
+	void (*pcat_compat_init)(void);
+
+	struct irq_chip *(*get_irq_chip)(unsigned long trigger);
+
+	unsigned int (*__read)(char __iomem *iosapic, unsigned int reg);
+	void (*__write)(char __iomem *iosapic, unsigned int reg, u32 val);
+};
+
+extern struct pv_iosapic_ops pv_iosapic_ops;
+
+static inline void
+iosapic_pcat_compat_init(void)
+{
+	if (pv_iosapic_ops.pcat_compat_init)
+		pv_iosapic_ops.pcat_compat_init();
+}
+
+static inline struct irq_chip*
+iosapic_get_irq_chip(unsigned long trigger)
+{
+	return pv_iosapic_ops.get_irq_chip(trigger);
+}
+
+static inline unsigned int
+__iosapic_read(char __iomem *iosapic, unsigned int reg)
+{
+	return pv_iosapic_ops.__read(iosapic, reg);
+}
+
+static inline void
+__iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val)
+{
+	return pv_iosapic_ops.__write(iosapic, reg, val);
+}
+
+/******************************************************************************
+ * replacement of irq operations.
+ */
+
+struct pv_irq_ops {
+	void (*register_ipi)(void);
+
+	int (*assign_irq_vector)(int irq);
+	void (*free_irq_vector)(int vector);
+
+	void (*register_percpu_irq)(ia64_vector vec,
+				    struct irqaction *action);
+
+	void (*resend_irq)(unsigned int vector);
+};
+
+extern struct pv_irq_ops pv_irq_ops;
+
+static inline void
+ia64_register_ipi(void)
+{
+	pv_irq_ops.register_ipi();
+}
+
+static inline int
+assign_irq_vector(int irq)
+{
+	return pv_irq_ops.assign_irq_vector(irq);
+}
+
+static inline void
+free_irq_vector(int vector)
+{
+	return pv_irq_ops.free_irq_vector(vector);
+}
+
+static inline void
+register_percpu_irq(ia64_vector vec, struct irqaction *action)
+{
+	pv_irq_ops.register_percpu_irq(vec, action);
+}
+
+static inline void
+ia64_resend_irq(unsigned int vector)
+{
+	pv_irq_ops.resend_irq(vector);
+}
+
+/******************************************************************************
+ * replacement of time operations.
+ */
+
+extern struct itc_jitter_data_t itc_jitter_data;
+extern volatile int time_keeper_id;
+
+struct pv_time_ops {
+	void (*init_missing_ticks_accounting)(int cpu);
+	int (*do_steal_accounting)(unsigned long *new_itm);
+
+	void (*clocksource_resume)(void);
+};
+
+extern struct pv_time_ops pv_time_ops;
+
+static inline void
+paravirt_init_missing_ticks_accounting(int cpu)
+{
+	if (pv_time_ops.init_missing_ticks_accounting)
+		pv_time_ops.init_missing_ticks_accounting(cpu);
+}
+
+static inline int
+paravirt_do_steal_accounting(unsigned long *new_itm)
+{
+	return pv_time_ops.do_steal_accounting(new_itm);
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#else
+/* fallback for native case */
+
+#ifndef __ASSEMBLY__
+
+#define paravirt_banner()				do { } while (0)
+#define paravirt_reserve_memory(region)			0
+
+#define paravirt_arch_setup_early()			do { } while (0)
+#define paravirt_arch_setup_console(cmdline_p)		do { } while (0)
+#define paravirt_arch_setup_nomca()			0
+#define paravirt_post_smp_prepare_boot_cpu()		do { } while (0)
+
+#define paravirt_init_missing_ticks_accounting(cpu)	do { } while (0)
+#define paravirt_do_steal_accounting(new_itm)		0
+
+#endif /* __ASSEMBLY__ */
+
+
+#endif /* CONFIG_PARAVIRT_GUEST */
+
+#endif /* __ASM_PARAVIRT_H */
diff --git a/include/asm-ia64/paravirt_privop.h b/include/asm-ia64/paravirt_privop.h
new file mode 100644
index 0000000..52482e6
--- /dev/null
+++ b/include/asm-ia64/paravirt_privop.h
@@ -0,0 +1,114 @@
+/******************************************************************************
+ * include/asm-ia64/paravirt_privops.h
+ *
+ * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _ASM_IA64_PARAVIRT_PRIVOP_H
+#define _ASM_IA64_PARAVIRT_PRIVOP_H
+
+#ifdef CONFIG_PARAVIRT
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+#include <asm/kregs.h> /* for IA64_PSR_I */
+
+/******************************************************************************
+ * replacement of intrinsics operations.
+ */
+
+struct pv_cpu_ops {
+	void (*fc)(unsigned long addr);
+	unsigned long (*thash)(unsigned long addr);
+	unsigned long (*get_cpuid)(int index);
+	unsigned long (*get_pmd)(int index);
+	unsigned long (*getreg)(int reg);
+	void (*setreg)(int reg, unsigned long val);
+	void (*ptcga)(unsigned long addr, unsigned long size);
+	unsigned long (*get_rr)(unsigned long index);
+	void (*set_rr)(unsigned long index, unsigned long val);
+	void (*set_rr0_to_rr4)(unsigned long val0, unsigned long val1,
+			       unsigned long val2, unsigned long val3,
+			       unsigned long val4);
+	void (*ssm_i)(void);
+	void (*rsm_i)(void);
+	unsigned long (*get_psr_i)(void);
+	void (*intrin_local_irq_restore)(unsigned long flags);
+};
+
+extern struct pv_cpu_ops pv_cpu_ops;
+
+extern void ia64_native_setreg_func(int regnum, unsigned long val);
+extern unsigned long ia64_native_getreg_func(int regnum);
+
+/************************************************/
+/* Instructions paravirtualized for performance */
+/************************************************/
+
+/* mask for ia64_native_ssm/rsm() must be constant.("i" constraing).
+ * static inline function doesn't satisfy it. */
+#define paravirt_ssm(mask)			\
+	do {					\
+		if ((mask) == IA64_PSR_I)	\
+			pv_cpu_ops.ssm_i();	\
+		else				\
+			ia64_native_ssm(mask);	\
+	} while (0)
+
+#define paravirt_rsm(mask)			\
+	do {					\
+		if ((mask) == IA64_PSR_I)	\
+			pv_cpu_ops.rsm_i();	\
+		else				\
+			ia64_native_rsm(mask);	\
+	} while (0)
+
+/******************************************************************************
+ * replacement of hand written assembly codes.
+ */
+struct pv_cpu_asm_switch {
+	unsigned long switch_to;
+	unsigned long leave_syscall;
+	unsigned long work_processed_syscall;
+	unsigned long leave_kernel;
+};
+void paravirt_cpu_asm_init(const struct pv_cpu_asm_switch *cpu_asm_switch);
+
+#endif /* __ASSEMBLY__ */
+
+#define IA64_PARAVIRT_ASM_FUNC(name)	paravirt_ ## name
+
+#else
+
+/* fallback for native case */
+#define IA64_PARAVIRT_ASM_FUNC(name)	ia64_native_ ## name
+
+#endif /* CONFIG_PARAVIRT */
+
+/* these routines utilize privilege-sensitive or performance-sensitive
+ * privileged instructions so the code must be replaced with
+ * paravirtualized versions */
+#define ia64_switch_to			IA64_PARAVIRT_ASM_FUNC(switch_to)
+#define ia64_leave_syscall		IA64_PARAVIRT_ASM_FUNC(leave_syscall)
+#define ia64_work_processed_syscall	\
+	IA64_PARAVIRT_ASM_FUNC(work_processed_syscall)
+#define ia64_leave_kernel		IA64_PARAVIRT_ASM_FUNC(leave_kernel)
+
+#endif /* _ASM_IA64_PARAVIRT_PRIVOP_H */
diff --git a/include/asm-ia64/smp.h b/include/asm-ia64/smp.h
index 27731e0..12d96e0 100644
--- a/include/asm-ia64/smp.h
+++ b/include/asm-ia64/smp.h
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/cpumask.h>
 #include <linux/bitops.h>
+#include <linux/irqreturn.h>
 
 #include <asm/io.h>
 #include <asm/param.h>
@@ -120,6 +121,7 @@
 extern void __init init_smp_config (void);
 extern void smp_do_timer (struct pt_regs *regs);
 
+extern irqreturn_t handle_IPI(int irq, void *dev_id);
 extern void smp_send_reschedule (int cpu);
 extern void identify_siblings (struct cpuinfo_ia64 *);
 extern int is_multithreading_enabled(void);
diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h
index 26e250b..927a381 100644
--- a/include/asm-ia64/system.h
+++ b/include/asm-ia64/system.h
@@ -26,6 +26,7 @@
  */
 #define KERNEL_START		 (GATE_ADDR+__IA64_UL_CONST(0x100000000))
 #define PERCPU_ADDR		(-PERCPU_PAGE_SIZE)
+#define LOAD_OFFSET		(KERNEL_START - KERNEL_TR_PAGE_SIZE)
 
 #ifndef __ASSEMBLY__
 
@@ -122,10 +123,16 @@
  *   write a floating-point register right before reading the PSR
  *   and that writes to PSR.mfl
  */
+#ifdef CONFIG_PARAVIRT
+#define __local_save_flags()	ia64_get_psr_i()
+#else
+#define __local_save_flags()	ia64_getreg(_IA64_REG_PSR)
+#endif
+
 #define __local_irq_save(x)			\
 do {						\
 	ia64_stop();				\
-	(x) = ia64_getreg(_IA64_REG_PSR);	\
+	(x) = __local_save_flags();		\
 	ia64_stop();				\
 	ia64_rsm(IA64_PSR_I);			\
 } while (0)
@@ -173,7 +180,7 @@
 #endif /* !CONFIG_IA64_DEBUG_IRQ */
 
 #define local_irq_enable()	({ ia64_stop(); ia64_ssm(IA64_PSR_I); ia64_srlz_d(); })
-#define local_save_flags(flags)	({ ia64_stop(); (flags) = ia64_getreg(_IA64_REG_PSR); })
+#define local_save_flags(flags)	({ ia64_stop(); (flags) = __local_save_flags(); })
 
 #define irqs_disabled()				\
 ({						\
diff --git a/include/asm-ia64/uv/uv_mmrs.h b/include/asm-ia64/uv/uv_mmrs.h
index 1cc1dbb..c149ef0 100644
--- a/include/asm-ia64/uv/uv_mmrs.h
+++ b/include/asm-ia64/uv/uv_mmrs.h
@@ -11,11 +11,284 @@
 #ifndef __ASM_IA64_UV_MMRS__
 #define __ASM_IA64_UV_MMRS__
 
-/*
- *       AUTO GENERATED - Do not edit
- */
+#define UV_MMR_ENABLE		(1UL << 63)
 
- #define UV_MMR_ENABLE		(1UL << 63)
+/* ========================================================================= */
+/*                           UVH_BAU_DATA_CONFIG                             */
+/* ========================================================================= */
+#define UVH_BAU_DATA_CONFIG 0x61680UL
+#define UVH_BAU_DATA_CONFIG_32 0x0438
+
+#define UVH_BAU_DATA_CONFIG_VECTOR_SHFT 0
+#define UVH_BAU_DATA_CONFIG_VECTOR_MASK 0x00000000000000ffUL
+#define UVH_BAU_DATA_CONFIG_DM_SHFT 8
+#define UVH_BAU_DATA_CONFIG_DM_MASK 0x0000000000000700UL
+#define UVH_BAU_DATA_CONFIG_DESTMODE_SHFT 11
+#define UVH_BAU_DATA_CONFIG_DESTMODE_MASK 0x0000000000000800UL
+#define UVH_BAU_DATA_CONFIG_STATUS_SHFT 12
+#define UVH_BAU_DATA_CONFIG_STATUS_MASK 0x0000000000001000UL
+#define UVH_BAU_DATA_CONFIG_P_SHFT 13
+#define UVH_BAU_DATA_CONFIG_P_MASK 0x0000000000002000UL
+#define UVH_BAU_DATA_CONFIG_T_SHFT 15
+#define UVH_BAU_DATA_CONFIG_T_MASK 0x0000000000008000UL
+#define UVH_BAU_DATA_CONFIG_M_SHFT 16
+#define UVH_BAU_DATA_CONFIG_M_MASK 0x0000000000010000UL
+#define UVH_BAU_DATA_CONFIG_APIC_ID_SHFT 32
+#define UVH_BAU_DATA_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
+
+union uvh_bau_data_config_u {
+    unsigned long	v;
+    struct uvh_bau_data_config_s {
+	unsigned long	vector_  :  8;  /* RW */
+	unsigned long	dm       :  3;  /* RW */
+	unsigned long	destmode :  1;  /* RW */
+	unsigned long	status   :  1;  /* RO */
+	unsigned long	p        :  1;  /* RO */
+	unsigned long	rsvd_14  :  1;  /*    */
+	unsigned long	t        :  1;  /* RO */
+	unsigned long	m        :  1;  /* RW */
+	unsigned long	rsvd_17_31: 15;  /*    */
+	unsigned long	apic_id  : 32;  /* RW */
+    } s;
+};
+
+/* ========================================================================= */
+/*                           UVH_EVENT_OCCURRED0                             */
+/* ========================================================================= */
+#define UVH_EVENT_OCCURRED0 0x70000UL
+#define UVH_EVENT_OCCURRED0_32 0x005e8
+
+#define UVH_EVENT_OCCURRED0_LB_HCERR_SHFT 0
+#define UVH_EVENT_OCCURRED0_LB_HCERR_MASK 0x0000000000000001UL
+#define UVH_EVENT_OCCURRED0_GR0_HCERR_SHFT 1
+#define UVH_EVENT_OCCURRED0_GR0_HCERR_MASK 0x0000000000000002UL
+#define UVH_EVENT_OCCURRED0_GR1_HCERR_SHFT 2
+#define UVH_EVENT_OCCURRED0_GR1_HCERR_MASK 0x0000000000000004UL
+#define UVH_EVENT_OCCURRED0_LH_HCERR_SHFT 3
+#define UVH_EVENT_OCCURRED0_LH_HCERR_MASK 0x0000000000000008UL
+#define UVH_EVENT_OCCURRED0_RH_HCERR_SHFT 4
+#define UVH_EVENT_OCCURRED0_RH_HCERR_MASK 0x0000000000000010UL
+#define UVH_EVENT_OCCURRED0_XN_HCERR_SHFT 5
+#define UVH_EVENT_OCCURRED0_XN_HCERR_MASK 0x0000000000000020UL
+#define UVH_EVENT_OCCURRED0_SI_HCERR_SHFT 6
+#define UVH_EVENT_OCCURRED0_SI_HCERR_MASK 0x0000000000000040UL
+#define UVH_EVENT_OCCURRED0_LB_AOERR0_SHFT 7
+#define UVH_EVENT_OCCURRED0_LB_AOERR0_MASK 0x0000000000000080UL
+#define UVH_EVENT_OCCURRED0_GR0_AOERR0_SHFT 8
+#define UVH_EVENT_OCCURRED0_GR0_AOERR0_MASK 0x0000000000000100UL
+#define UVH_EVENT_OCCURRED0_GR1_AOERR0_SHFT 9
+#define UVH_EVENT_OCCURRED0_GR1_AOERR0_MASK 0x0000000000000200UL
+#define UVH_EVENT_OCCURRED0_LH_AOERR0_SHFT 10
+#define UVH_EVENT_OCCURRED0_LH_AOERR0_MASK 0x0000000000000400UL
+#define UVH_EVENT_OCCURRED0_RH_AOERR0_SHFT 11
+#define UVH_EVENT_OCCURRED0_RH_AOERR0_MASK 0x0000000000000800UL
+#define UVH_EVENT_OCCURRED0_XN_AOERR0_SHFT 12
+#define UVH_EVENT_OCCURRED0_XN_AOERR0_MASK 0x0000000000001000UL
+#define UVH_EVENT_OCCURRED0_SI_AOERR0_SHFT 13
+#define UVH_EVENT_OCCURRED0_SI_AOERR0_MASK 0x0000000000002000UL
+#define UVH_EVENT_OCCURRED0_LB_AOERR1_SHFT 14
+#define UVH_EVENT_OCCURRED0_LB_AOERR1_MASK 0x0000000000004000UL
+#define UVH_EVENT_OCCURRED0_GR0_AOERR1_SHFT 15
+#define UVH_EVENT_OCCURRED0_GR0_AOERR1_MASK 0x0000000000008000UL
+#define UVH_EVENT_OCCURRED0_GR1_AOERR1_SHFT 16
+#define UVH_EVENT_OCCURRED0_GR1_AOERR1_MASK 0x0000000000010000UL
+#define UVH_EVENT_OCCURRED0_LH_AOERR1_SHFT 17
+#define UVH_EVENT_OCCURRED0_LH_AOERR1_MASK 0x0000000000020000UL
+#define UVH_EVENT_OCCURRED0_RH_AOERR1_SHFT 18
+#define UVH_EVENT_OCCURRED0_RH_AOERR1_MASK 0x0000000000040000UL
+#define UVH_EVENT_OCCURRED0_XN_AOERR1_SHFT 19
+#define UVH_EVENT_OCCURRED0_XN_AOERR1_MASK 0x0000000000080000UL
+#define UVH_EVENT_OCCURRED0_SI_AOERR1_SHFT 20
+#define UVH_EVENT_OCCURRED0_SI_AOERR1_MASK 0x0000000000100000UL
+#define UVH_EVENT_OCCURRED0_RH_VPI_INT_SHFT 21
+#define UVH_EVENT_OCCURRED0_RH_VPI_INT_MASK 0x0000000000200000UL
+#define UVH_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_SHFT 22
+#define UVH_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_MASK 0x0000000000400000UL
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_0_SHFT 23
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_0_MASK 0x0000000000800000UL
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_1_SHFT 24
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_1_MASK 0x0000000001000000UL
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_2_SHFT 25
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_2_MASK 0x0000000002000000UL
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_3_SHFT 26
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_3_MASK 0x0000000004000000UL
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_4_SHFT 27
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_4_MASK 0x0000000008000000UL
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_5_SHFT 28
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_5_MASK 0x0000000010000000UL
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_6_SHFT 29
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_6_MASK 0x0000000020000000UL
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_7_SHFT 30
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_7_MASK 0x0000000040000000UL
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_8_SHFT 31
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_8_MASK 0x0000000080000000UL
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_9_SHFT 32
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_9_MASK 0x0000000100000000UL
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_10_SHFT 33
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_10_MASK 0x0000000200000000UL
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_11_SHFT 34
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_11_MASK 0x0000000400000000UL
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_12_SHFT 35
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_12_MASK 0x0000000800000000UL
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_13_SHFT 36
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_13_MASK 0x0000001000000000UL
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_14_SHFT 37
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_14_MASK 0x0000002000000000UL
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_15_SHFT 38
+#define UVH_EVENT_OCCURRED0_LB_IRQ_INT_15_MASK 0x0000004000000000UL
+#define UVH_EVENT_OCCURRED0_L1_NMI_INT_SHFT 39
+#define UVH_EVENT_OCCURRED0_L1_NMI_INT_MASK 0x0000008000000000UL
+#define UVH_EVENT_OCCURRED0_STOP_CLOCK_SHFT 40
+#define UVH_EVENT_OCCURRED0_STOP_CLOCK_MASK 0x0000010000000000UL
+#define UVH_EVENT_OCCURRED0_ASIC_TO_L1_SHFT 41
+#define UVH_EVENT_OCCURRED0_ASIC_TO_L1_MASK 0x0000020000000000UL
+#define UVH_EVENT_OCCURRED0_L1_TO_ASIC_SHFT 42
+#define UVH_EVENT_OCCURRED0_L1_TO_ASIC_MASK 0x0000040000000000UL
+#define UVH_EVENT_OCCURRED0_LTC_INT_SHFT 43
+#define UVH_EVENT_OCCURRED0_LTC_INT_MASK 0x0000080000000000UL
+#define UVH_EVENT_OCCURRED0_LA_SEQ_TRIGGER_SHFT 44
+#define UVH_EVENT_OCCURRED0_LA_SEQ_TRIGGER_MASK 0x0000100000000000UL
+#define UVH_EVENT_OCCURRED0_IPI_INT_SHFT 45
+#define UVH_EVENT_OCCURRED0_IPI_INT_MASK 0x0000200000000000UL
+#define UVH_EVENT_OCCURRED0_EXTIO_INT0_SHFT 46
+#define UVH_EVENT_OCCURRED0_EXTIO_INT0_MASK 0x0000400000000000UL
+#define UVH_EVENT_OCCURRED0_EXTIO_INT1_SHFT 47
+#define UVH_EVENT_OCCURRED0_EXTIO_INT1_MASK 0x0000800000000000UL
+#define UVH_EVENT_OCCURRED0_EXTIO_INT2_SHFT 48
+#define UVH_EVENT_OCCURRED0_EXTIO_INT2_MASK 0x0001000000000000UL
+#define UVH_EVENT_OCCURRED0_EXTIO_INT3_SHFT 49
+#define UVH_EVENT_OCCURRED0_EXTIO_INT3_MASK 0x0002000000000000UL
+#define UVH_EVENT_OCCURRED0_PROFILE_INT_SHFT 50
+#define UVH_EVENT_OCCURRED0_PROFILE_INT_MASK 0x0004000000000000UL
+#define UVH_EVENT_OCCURRED0_RTC0_SHFT 51
+#define UVH_EVENT_OCCURRED0_RTC0_MASK 0x0008000000000000UL
+#define UVH_EVENT_OCCURRED0_RTC1_SHFT 52
+#define UVH_EVENT_OCCURRED0_RTC1_MASK 0x0010000000000000UL
+#define UVH_EVENT_OCCURRED0_RTC2_SHFT 53
+#define UVH_EVENT_OCCURRED0_RTC2_MASK 0x0020000000000000UL
+#define UVH_EVENT_OCCURRED0_RTC3_SHFT 54
+#define UVH_EVENT_OCCURRED0_RTC3_MASK 0x0040000000000000UL
+#define UVH_EVENT_OCCURRED0_BAU_DATA_SHFT 55
+#define UVH_EVENT_OCCURRED0_BAU_DATA_MASK 0x0080000000000000UL
+#define UVH_EVENT_OCCURRED0_POWER_MANAGEMENT_REQ_SHFT 56
+#define UVH_EVENT_OCCURRED0_POWER_MANAGEMENT_REQ_MASK 0x0100000000000000UL
+union uvh_event_occurred0_u {
+    unsigned long	v;
+    struct uvh_event_occurred0_s {
+	unsigned long	lb_hcerr             :  1;  /* RW, W1C */
+	unsigned long	gr0_hcerr            :  1;  /* RW, W1C */
+	unsigned long	gr1_hcerr            :  1;  /* RW, W1C */
+	unsigned long	lh_hcerr             :  1;  /* RW, W1C */
+	unsigned long	rh_hcerr             :  1;  /* RW, W1C */
+	unsigned long	xn_hcerr             :  1;  /* RW, W1C */
+	unsigned long	si_hcerr             :  1;  /* RW, W1C */
+	unsigned long	lb_aoerr0            :  1;  /* RW, W1C */
+	unsigned long	gr0_aoerr0           :  1;  /* RW, W1C */
+	unsigned long	gr1_aoerr0           :  1;  /* RW, W1C */
+	unsigned long	lh_aoerr0            :  1;  /* RW, W1C */
+	unsigned long	rh_aoerr0            :  1;  /* RW, W1C */
+	unsigned long	xn_aoerr0            :  1;  /* RW, W1C */
+	unsigned long	si_aoerr0            :  1;  /* RW, W1C */
+	unsigned long	lb_aoerr1            :  1;  /* RW, W1C */
+	unsigned long	gr0_aoerr1           :  1;  /* RW, W1C */
+	unsigned long	gr1_aoerr1           :  1;  /* RW, W1C */
+	unsigned long	lh_aoerr1            :  1;  /* RW, W1C */
+	unsigned long	rh_aoerr1            :  1;  /* RW, W1C */
+	unsigned long	xn_aoerr1            :  1;  /* RW, W1C */
+	unsigned long	si_aoerr1            :  1;  /* RW, W1C */
+	unsigned long	rh_vpi_int           :  1;  /* RW, W1C */
+	unsigned long	system_shutdown_int  :  1;  /* RW, W1C */
+	unsigned long	lb_irq_int_0         :  1;  /* RW, W1C */
+	unsigned long	lb_irq_int_1         :  1;  /* RW, W1C */
+	unsigned long	lb_irq_int_2         :  1;  /* RW, W1C */
+	unsigned long	lb_irq_int_3         :  1;  /* RW, W1C */
+	unsigned long	lb_irq_int_4         :  1;  /* RW, W1C */
+	unsigned long	lb_irq_int_5         :  1;  /* RW, W1C */
+	unsigned long	lb_irq_int_6         :  1;  /* RW, W1C */
+	unsigned long	lb_irq_int_7         :  1;  /* RW, W1C */
+	unsigned long	lb_irq_int_8         :  1;  /* RW, W1C */
+	unsigned long	lb_irq_int_9         :  1;  /* RW, W1C */
+	unsigned long	lb_irq_int_10        :  1;  /* RW, W1C */
+	unsigned long	lb_irq_int_11        :  1;  /* RW, W1C */
+	unsigned long	lb_irq_int_12        :  1;  /* RW, W1C */
+	unsigned long	lb_irq_int_13        :  1;  /* RW, W1C */
+	unsigned long	lb_irq_int_14        :  1;  /* RW, W1C */
+	unsigned long	lb_irq_int_15        :  1;  /* RW, W1C */
+	unsigned long	l1_nmi_int           :  1;  /* RW, W1C */
+	unsigned long	stop_clock           :  1;  /* RW, W1C */
+	unsigned long	asic_to_l1           :  1;  /* RW, W1C */
+	unsigned long	l1_to_asic           :  1;  /* RW, W1C */
+	unsigned long	ltc_int              :  1;  /* RW, W1C */
+	unsigned long	la_seq_trigger       :  1;  /* RW, W1C */
+	unsigned long	ipi_int              :  1;  /* RW, W1C */
+	unsigned long	extio_int0           :  1;  /* RW, W1C */
+	unsigned long	extio_int1           :  1;  /* RW, W1C */
+	unsigned long	extio_int2           :  1;  /* RW, W1C */
+	unsigned long	extio_int3           :  1;  /* RW, W1C */
+	unsigned long	profile_int          :  1;  /* RW, W1C */
+	unsigned long	rtc0                 :  1;  /* RW, W1C */
+	unsigned long	rtc1                 :  1;  /* RW, W1C */
+	unsigned long	rtc2                 :  1;  /* RW, W1C */
+	unsigned long	rtc3                 :  1;  /* RW, W1C */
+	unsigned long	bau_data             :  1;  /* RW, W1C */
+	unsigned long	power_management_req :  1;  /* RW, W1C */
+	unsigned long	rsvd_57_63           :  7;  /*    */
+    } s;
+};
+
+/* ========================================================================= */
+/*                        UVH_EVENT_OCCURRED0_ALIAS                          */
+/* ========================================================================= */
+#define UVH_EVENT_OCCURRED0_ALIAS 0x0000000000070008UL
+#define UVH_EVENT_OCCURRED0_ALIAS_32 0x005f0
+
+/* ========================================================================= */
+/*                               UVH_INT_CMPB                                */
+/* ========================================================================= */
+#define UVH_INT_CMPB 0x22080UL
+
+#define UVH_INT_CMPB_REAL_TIME_CMPB_SHFT 0
+#define UVH_INT_CMPB_REAL_TIME_CMPB_MASK 0x00ffffffffffffffUL
+
+union uvh_int_cmpb_u {
+    unsigned long	v;
+    struct uvh_int_cmpb_s {
+	unsigned long	real_time_cmpb : 56;  /* RW */
+	unsigned long	rsvd_56_63     :  8;  /*    */
+    } s;
+};
+
+/* ========================================================================= */
+/*                               UVH_INT_CMPC                                */
+/* ========================================================================= */
+#define UVH_INT_CMPC 0x22100UL
+
+#define UVH_INT_CMPC_REAL_TIME_CMPC_SHFT 0
+#define UVH_INT_CMPC_REAL_TIME_CMPC_MASK 0x00ffffffffffffffUL
+
+union uvh_int_cmpc_u {
+    unsigned long	v;
+    struct uvh_int_cmpc_s {
+	unsigned long	real_time_cmpc : 56;  /* RW */
+	unsigned long	rsvd_56_63     :  8;  /*    */
+    } s;
+};
+
+/* ========================================================================= */
+/*                               UVH_INT_CMPD                                */
+/* ========================================================================= */
+#define UVH_INT_CMPD 0x22180UL
+
+#define UVH_INT_CMPD_REAL_TIME_CMPD_SHFT 0
+#define UVH_INT_CMPD_REAL_TIME_CMPD_MASK 0x00ffffffffffffffUL
+
+union uvh_int_cmpd_u {
+    unsigned long	v;
+    struct uvh_int_cmpd_s {
+	unsigned long	real_time_cmpd : 56;  /* RW */
+	unsigned long	rsvd_56_63     :  8;  /*    */
+    } s;
+};
 
 /* ========================================================================= */
 /*                               UVH_NODE_ID                                 */
@@ -111,8 +384,8 @@
 
 #define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT 28
 #define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffff0000000UL
-#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_GR4_SHFT 46
-#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_GR4_MASK 0x0000400000000000UL
+#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_GR4_SHFT 48
+#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_GR4_MASK 0x0001000000000000UL
 #define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_SHFT 52
 #define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_MASK 0x00f0000000000000UL
 #define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63
@@ -123,8 +396,9 @@
     struct uvh_rh_gam_gru_overlay_config_mmr_s {
 	unsigned long	rsvd_0_27: 28;  /*    */
 	unsigned long	base   : 18;  /* RW */
+	unsigned long	rsvd_46_47:  2;  /*    */
 	unsigned long	gr4    :  1;  /* RW */
-	unsigned long	rsvd_47_51:  5;  /*    */
+	unsigned long	rsvd_49_51:  3;  /*    */
 	unsigned long	n_gru  :  4;  /* RW */
 	unsigned long	rsvd_56_62:  7;  /*    */
 	unsigned long	enable :  1;  /* RW */
@@ -157,7 +431,7 @@
 /* ========================================================================= */
 /*                                 UVH_RTC                                   */
 /* ========================================================================= */
-#define UVH_RTC 0x28000UL
+#define UVH_RTC 0x340000UL
 
 #define UVH_RTC_REAL_TIME_CLOCK_SHFT 0
 #define UVH_RTC_REAL_TIME_CLOCK_MASK 0x00ffffffffffffffUL
@@ -171,6 +445,139 @@
 };
 
 /* ========================================================================= */
+/*                           UVH_RTC1_INT_CONFIG                             */
+/* ========================================================================= */
+#define UVH_RTC1_INT_CONFIG 0x615c0UL
+
+#define UVH_RTC1_INT_CONFIG_VECTOR_SHFT 0
+#define UVH_RTC1_INT_CONFIG_VECTOR_MASK 0x00000000000000ffUL
+#define UVH_RTC1_INT_CONFIG_DM_SHFT 8
+#define UVH_RTC1_INT_CONFIG_DM_MASK 0x0000000000000700UL
+#define UVH_RTC1_INT_CONFIG_DESTMODE_SHFT 11
+#define UVH_RTC1_INT_CONFIG_DESTMODE_MASK 0x0000000000000800UL
+#define UVH_RTC1_INT_CONFIG_STATUS_SHFT 12
+#define UVH_RTC1_INT_CONFIG_STATUS_MASK 0x0000000000001000UL
+#define UVH_RTC1_INT_CONFIG_P_SHFT 13
+#define UVH_RTC1_INT_CONFIG_P_MASK 0x0000000000002000UL
+#define UVH_RTC1_INT_CONFIG_T_SHFT 15
+#define UVH_RTC1_INT_CONFIG_T_MASK 0x0000000000008000UL
+#define UVH_RTC1_INT_CONFIG_M_SHFT 16
+#define UVH_RTC1_INT_CONFIG_M_MASK 0x0000000000010000UL
+#define UVH_RTC1_INT_CONFIG_APIC_ID_SHFT 32
+#define UVH_RTC1_INT_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
+
+union uvh_rtc1_int_config_u {
+    unsigned long	v;
+    struct uvh_rtc1_int_config_s {
+	unsigned long	vector_  :  8;  /* RW */
+	unsigned long	dm       :  3;  /* RW */
+	unsigned long	destmode :  1;  /* RW */
+	unsigned long	status   :  1;  /* RO */
+	unsigned long	p        :  1;  /* RO */
+	unsigned long	rsvd_14  :  1;  /*    */
+	unsigned long	t        :  1;  /* RO */
+	unsigned long	m        :  1;  /* RW */
+	unsigned long	rsvd_17_31: 15;  /*    */
+	unsigned long	apic_id  : 32;  /* RW */
+    } s;
+};
+
+/* ========================================================================= */
+/*                           UVH_RTC2_INT_CONFIG                             */
+/* ========================================================================= */
+#define UVH_RTC2_INT_CONFIG 0x61600UL
+
+#define UVH_RTC2_INT_CONFIG_VECTOR_SHFT 0
+#define UVH_RTC2_INT_CONFIG_VECTOR_MASK 0x00000000000000ffUL
+#define UVH_RTC2_INT_CONFIG_DM_SHFT 8
+#define UVH_RTC2_INT_CONFIG_DM_MASK 0x0000000000000700UL
+#define UVH_RTC2_INT_CONFIG_DESTMODE_SHFT 11
+#define UVH_RTC2_INT_CONFIG_DESTMODE_MASK 0x0000000000000800UL
+#define UVH_RTC2_INT_CONFIG_STATUS_SHFT 12
+#define UVH_RTC2_INT_CONFIG_STATUS_MASK 0x0000000000001000UL
+#define UVH_RTC2_INT_CONFIG_P_SHFT 13
+#define UVH_RTC2_INT_CONFIG_P_MASK 0x0000000000002000UL
+#define UVH_RTC2_INT_CONFIG_T_SHFT 15
+#define UVH_RTC2_INT_CONFIG_T_MASK 0x0000000000008000UL
+#define UVH_RTC2_INT_CONFIG_M_SHFT 16
+#define UVH_RTC2_INT_CONFIG_M_MASK 0x0000000000010000UL
+#define UVH_RTC2_INT_CONFIG_APIC_ID_SHFT 32
+#define UVH_RTC2_INT_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
+
+union uvh_rtc2_int_config_u {
+    unsigned long	v;
+    struct uvh_rtc2_int_config_s {
+	unsigned long	vector_  :  8;  /* RW */
+	unsigned long	dm       :  3;  /* RW */
+	unsigned long	destmode :  1;  /* RW */
+	unsigned long	status   :  1;  /* RO */
+	unsigned long	p        :  1;  /* RO */
+	unsigned long	rsvd_14  :  1;  /*    */
+	unsigned long	t        :  1;  /* RO */
+	unsigned long	m        :  1;  /* RW */
+	unsigned long	rsvd_17_31: 15;  /*    */
+	unsigned long	apic_id  : 32;  /* RW */
+    } s;
+};
+
+/* ========================================================================= */
+/*                           UVH_RTC3_INT_CONFIG                             */
+/* ========================================================================= */
+#define UVH_RTC3_INT_CONFIG 0x61640UL
+
+#define UVH_RTC3_INT_CONFIG_VECTOR_SHFT 0
+#define UVH_RTC3_INT_CONFIG_VECTOR_MASK 0x00000000000000ffUL
+#define UVH_RTC3_INT_CONFIG_DM_SHFT 8
+#define UVH_RTC3_INT_CONFIG_DM_MASK 0x0000000000000700UL
+#define UVH_RTC3_INT_CONFIG_DESTMODE_SHFT 11
+#define UVH_RTC3_INT_CONFIG_DESTMODE_MASK 0x0000000000000800UL
+#define UVH_RTC3_INT_CONFIG_STATUS_SHFT 12
+#define UVH_RTC3_INT_CONFIG_STATUS_MASK 0x0000000000001000UL
+#define UVH_RTC3_INT_CONFIG_P_SHFT 13
+#define UVH_RTC3_INT_CONFIG_P_MASK 0x0000000000002000UL
+#define UVH_RTC3_INT_CONFIG_T_SHFT 15
+#define UVH_RTC3_INT_CONFIG_T_MASK 0x0000000000008000UL
+#define UVH_RTC3_INT_CONFIG_M_SHFT 16
+#define UVH_RTC3_INT_CONFIG_M_MASK 0x0000000000010000UL
+#define UVH_RTC3_INT_CONFIG_APIC_ID_SHFT 32
+#define UVH_RTC3_INT_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
+
+union uvh_rtc3_int_config_u {
+    unsigned long	v;
+    struct uvh_rtc3_int_config_s {
+	unsigned long	vector_  :  8;  /* RW */
+	unsigned long	dm       :  3;  /* RW */
+	unsigned long	destmode :  1;  /* RW */
+	unsigned long	status   :  1;  /* RO */
+	unsigned long	p        :  1;  /* RO */
+	unsigned long	rsvd_14  :  1;  /*    */
+	unsigned long	t        :  1;  /* RO */
+	unsigned long	m        :  1;  /* RW */
+	unsigned long	rsvd_17_31: 15;  /*    */
+	unsigned long	apic_id  : 32;  /* RW */
+    } s;
+};
+
+/* ========================================================================= */
+/*                            UVH_RTC_INC_RATIO                              */
+/* ========================================================================= */
+#define UVH_RTC_INC_RATIO 0x350000UL
+
+#define UVH_RTC_INC_RATIO_FRACTION_SHFT 0
+#define UVH_RTC_INC_RATIO_FRACTION_MASK 0x00000000000fffffUL
+#define UVH_RTC_INC_RATIO_RATIO_SHFT 20
+#define UVH_RTC_INC_RATIO_RATIO_MASK 0x0000000000700000UL
+
+union uvh_rtc_inc_ratio_u {
+    unsigned long	v;
+    struct uvh_rtc_inc_ratio_s {
+	unsigned long	fraction : 20;  /* RW */
+	unsigned long	ratio    :  3;  /* RW */
+	unsigned long	rsvd_23_63: 41;  /*    */
+    } s;
+};
+
+/* ========================================================================= */
 /*                          UVH_SI_ADDR_MAP_CONFIG                           */
 /* ========================================================================= */
 #define UVH_SI_ADDR_MAP_CONFIG 0xc80000UL
diff --git a/include/asm-powerpc/asm-compat.h b/include/asm-powerpc/asm-compat.h
index 8ec2e1d..8f0fe79 100644
--- a/include/asm-powerpc/asm-compat.h
+++ b/include/asm-powerpc/asm-compat.h
@@ -22,6 +22,7 @@
 #define PPC_STL		stringify_in_c(std)
 #define PPC_LCMPI	stringify_in_c(cmpdi)
 #define PPC_LONG	stringify_in_c(.llong)
+#define PPC_LONG_ALIGN	stringify_in_c(.balign 8)
 #define PPC_TLNEI	stringify_in_c(tdnei)
 #define PPC_LLARX	stringify_in_c(ldarx)
 #define PPC_STLCX	stringify_in_c(stdcx.)
@@ -43,6 +44,7 @@
 #define PPC_STL		stringify_in_c(stw)
 #define PPC_LCMPI	stringify_in_c(cmpwi)
 #define PPC_LONG	stringify_in_c(.long)
+#define PPC_LONG_ALIGN	stringify_in_c(.balign 4)
 #define PPC_TLNEI	stringify_in_c(twnei)
 #define PPC_LLARX	stringify_in_c(lwarx)
 #define PPC_STLCX	stringify_in_c(stwcx.)
diff --git a/include/asm-powerpc/kgdb.h b/include/asm-powerpc/kgdb.h
index b617dac..1399caf 100644
--- a/include/asm-powerpc/kgdb.h
+++ b/include/asm-powerpc/kgdb.h
@@ -1,57 +1,65 @@
 /*
- * kgdb.h: Defines and declarations for serial line source level
- *         remote debugging of the Linux kernel using gdb.
+ * include/asm-powerpc/kgdb.h
  *
+ * The PowerPC (32/64) specific defines / externs for KGDB.  Based on
+ * the previous 32bit and 64bit specific files, which had the following
+ * copyrights:
+ *
+ * PPC64 Mods (C) 2005 Frank Rowand (frowand@mvista.com)
+ * PPC Mods (C) 2004 Tom Rini (trini@mvista.com)
+ * PPC Mods (C) 2003 John Whitney (john.whitney@timesys.com)
  * PPC Mods (C) 1998 Michael Tesch (tesch@cs.wisc.edu)
  *
+ *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Author: Tom Rini <trini@kernel.crashing.org>
+ *
+ * 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.
  */
 #ifdef __KERNEL__
-#ifndef _PPC_KGDB_H
-#define _PPC_KGDB_H
+#ifndef __POWERPC_KGDB_H__
+#define __POWERPC_KGDB_H__
 
 #ifndef __ASSEMBLY__
 
-/* Things specific to the gen550 backend. */
-struct uart_port;
+#define BREAK_INSTR_SIZE	4
+#define BUFMAX			((NUMREGBYTES * 2) + 512)
+#define OUTBUFMAX		((NUMREGBYTES * 2) + 512)
+static inline void arch_kgdb_breakpoint(void)
+{
+	asm(".long 0x7d821008"); /* twge r2, r2 */
+}
+#define CACHE_FLUSH_IS_SAFE	1
 
-extern void gen550_progress(char *, unsigned short);
-extern void gen550_kgdb_map_scc(void);
-extern void gen550_init(int, struct uart_port *);
-
-/* Things specific to the pmac backend. */
-extern void zs_kgdb_hook(int tty_num);
-
-/* To init the kgdb engine. (called by serial hook)*/
-extern void set_debug_traps(void);
-
-/* To enter the debugger explicitly. */
-extern void breakpoint(void);
-
-/* For taking exceptions
- * these are defined in traps.c
- */
-extern int (*debugger)(struct pt_regs *regs);
-extern int (*debugger_bpt)(struct pt_regs *regs);
-extern int (*debugger_sstep)(struct pt_regs *regs);
-extern int (*debugger_iabr_match)(struct pt_regs *regs);
-extern int (*debugger_dabr_match)(struct pt_regs *regs);
-extern void (*debugger_fault_handler)(struct pt_regs *regs);
-
-/* What we bring to the party */
-int kgdb_bpt(struct pt_regs *regs);
-int kgdb_sstep(struct pt_regs *regs);
-void kgdb(struct pt_regs *regs);
-int kgdb_iabr_match(struct pt_regs *regs);
-int kgdb_dabr_match(struct pt_regs *regs);
-
+/* The number bytes of registers we have to save depends on a few
+ * things.  For 64bit we default to not including vector registers and
+ * vector state registers. */
+#ifdef CONFIG_PPC64
 /*
- * external low-level support routines (ie macserial.c)
+ * 64 bit (8 byte) registers:
+ *   32 gpr, 32 fpr, nip, msr, link, ctr
+ * 32 bit (4 byte) registers:
+ *   ccr, xer, fpscr
  */
-extern void kgdb_interruptible(int); /* control interrupts from serial */
-extern void putDebugChar(char);   /* write a single character      */
-extern char getDebugChar(void);   /* read and return a single char */
-
+#define NUMREGBYTES		((68 * 8) + (3 * 4))
+#define NUMCRITREGBYTES		184
+#else /* CONFIG_PPC32 */
+/* On non-E500 family PPC32 we determine the size by picking the last
+ * register we need, but on E500 we skip sections so we list what we
+ * need to store, and add it up. */
+#ifndef CONFIG_E500
+#define MAXREG			(PT_FPSCR+1)
+#else
+/* 32 GPRs (8 bytes), nip, msr, ccr, link, ctr, xer, acc (8 bytes), spefscr*/
+#define MAXREG                 ((32*2)+6+2+1)
+#endif
+#define NUMREGBYTES		(MAXREG * sizeof(int))
+/* CR/LR, R1, R2, R13-R31 inclusive. */
+#define NUMCRITREGBYTES		(23 * sizeof(int))
+#endif /* 32/64 */
 #endif /* !(__ASSEMBLY__) */
-#endif /* !(_PPC_KGDB_H) */
+#endif /* !__POWERPC_KGDB_H__ */
 #endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
index 9899226..1233d73 100644
--- a/include/asm-powerpc/machdep.h
+++ b/include/asm-powerpc/machdep.h
@@ -80,7 +80,8 @@
 				     long index,
 				     long npages,
 				     unsigned long uaddr,
-				     enum dma_data_direction direction);
+				     enum dma_data_direction direction,
+				     struct dma_attrs *attrs);
 	void		(*tce_free)(struct iommu_table *tbl,
 				    long index,
 				    long npages);
diff --git a/include/asm-powerpc/pgtable-ppc32.h b/include/asm-powerpc/pgtable-ppc32.h
index 73015f0..3a96d00 100644
--- a/include/asm-powerpc/pgtable-ppc32.h
+++ b/include/asm-powerpc/pgtable-ppc32.h
@@ -295,10 +295,10 @@
 #define _PAGE_PRESENT	0x00001	/* S: PTE contains a translation */
 #define _PAGE_USER	0x00002	/* S: User page (maps to UR) */
 #define _PAGE_FILE	0x00002	/* S: when !present: nonlinear file mapping */
-#define _PAGE_ACCESSED	0x00004	/* S: Page referenced */
-#define _PAGE_HWWRITE	0x00008	/* H: Dirty & RW, set in exception */
-#define _PAGE_RW	0x00010	/* S: Write permission */
-#define _PAGE_HWEXEC	0x00020	/* H: UX permission */
+#define _PAGE_RW	0x00004	/* S: Write permission (SW) */
+#define _PAGE_DIRTY	0x00008	/* S: Page dirty */
+#define _PAGE_HWEXEC	0x00010	/* H: SX permission */
+#define _PAGE_ACCESSED	0x00020	/* S: Page referenced */
 
 #define _PAGE_ENDIAN	0x00040	/* H: E bit */
 #define _PAGE_GUARDED	0x00080	/* H: G bit */
@@ -307,21 +307,14 @@
 #define _PAGE_WRITETHRU	0x00400	/* H: W bit */
 
 #ifdef CONFIG_PTE_64BIT
-#define _PAGE_DIRTY	0x08000	/* S: Page dirty */
-
 /* ERPN in a PTE never gets cleared, ignore it */
 #define _PTE_NONE_MASK	0xffffffffffff0000ULL
-#else
-#define _PAGE_DIRTY	0x00800	/* S: Page dirty */
 #endif
 
 #define _PMD_PRESENT	0
 #define _PMD_PRESENT_MASK (PAGE_MASK)
 #define _PMD_BAD	(~PAGE_MASK)
 
-/* Until my rework is finished, FSL BookE still needs atomic PTE updates */
-#define PTE_ATOMIC_UPDATES	1
-
 #elif defined(CONFIG_8xx)
 /* Definitions for 8xx embedded chips. */
 #define _PAGE_PRESENT	0x0001	/* Page is valid */
diff --git a/include/asm-powerpc/pmi.h b/include/asm-powerpc/pmi.h
index e1dc090..b4e91fb 100644
--- a/include/asm-powerpc/pmi.h
+++ b/include/asm-powerpc/pmi.h
@@ -30,6 +30,7 @@
 #ifdef __KERNEL__
 
 #define PMI_TYPE_FREQ_CHANGE	0x01
+#define PMI_TYPE_POWER_BUTTON	0x02
 #define PMI_READ_TYPE		0
 #define PMI_READ_DATA0		1
 #define PMI_READ_DATA1		2
diff --git a/include/asm-powerpc/ps3.h b/include/asm-powerpc/ps3.h
index 81ffe3b..f9e34c4 100644
--- a/include/asm-powerpc/ps3.h
+++ b/include/asm-powerpc/ps3.h
@@ -337,12 +337,18 @@
 	PS3_DEVICE_TYPE_LPM,
 };
 
+enum ps3_match_sub_id {
+	/* for PS3_MATCH_ID_GRAPHICS */
+	PS3_MATCH_SUB_ID_FB		= 1,
+};
+
 /**
  * struct ps3_system_bus_device - a device on the system bus
  */
 
 struct ps3_system_bus_device {
 	enum ps3_match_id match_id;
+	enum ps3_match_sub_id match_sub_id;
 	enum ps3_system_bus_device_type dev_type;
 
 	u64 bus_id;                       /* SB */
@@ -371,6 +377,7 @@
 
 struct ps3_system_bus_driver {
 	enum ps3_match_id match_id;
+	enum ps3_match_sub_id match_sub_id;
 	struct device_driver core;
 	int (*probe)(struct ps3_system_bus_device *);
 	int (*remove)(struct ps3_system_bus_device *);
diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h
index bbccadf..c6d1ab6 100644
--- a/include/asm-powerpc/reg.h
+++ b/include/asm-powerpc/reg.h
@@ -155,10 +155,12 @@
 #define   CTRL_RUNLATCH	0x1
 #define SPRN_DABR	0x3F5	/* Data Address Breakpoint Register */
 #define   DABR_TRANSLATION	(1UL << 2)
+#define SPRN_DABR2	0x13D	/* e300 */
 #define SPRN_DABRX	0x3F7	/* Data Address Breakpoint Register Extension */
 #define   DABRX_USER	(1UL << 0)
 #define   DABRX_KERNEL	(1UL << 1)
 #define SPRN_DAR	0x013	/* Data Address Register */
+#define SPRN_DBCR	0x136	/* e300 Data Breakpoint Control Reg */
 #define SPRN_DSISR	0x012	/* Data Storage Interrupt Status Register */
 #define   DSISR_NOHPTE		0x40000000	/* no translation found */
 #define   DSISR_PROTFAULT	0x08000000	/* protection fault */
@@ -264,6 +266,8 @@
 #define HID1_PS		(1<<16)		/* 750FX PLL selection */
 #define SPRN_HID2	0x3F8		/* Hardware Implementation Register 2 */
 #define SPRN_IABR	0x3F2	/* Instruction Address Breakpoint Register */
+#define SPRN_IABR2	0x3FA		/* 83xx */
+#define SPRN_IBCR	0x135		/* 83xx Insn Breakpoint Control Reg */
 #define SPRN_HID4	0x3F4		/* 970 HID4 */
 #define SPRN_HID5	0x3F6		/* 970 HID5 */
 #define SPRN_HID6	0x3F9	/* BE HID 6 */
diff --git a/include/asm-powerpc/uaccess.h b/include/asm-powerpc/uaccess.h
index 1a0736f..bd0fb84 100644
--- a/include/asm-powerpc/uaccess.h
+++ b/include/asm-powerpc/uaccess.h
@@ -6,6 +6,7 @@
 
 #include <linux/sched.h>
 #include <linux/errno.h>
+#include <asm/asm-compat.h>
 #include <asm/processor.h>
 #include <asm/page.h>
 
@@ -141,12 +142,11 @@
 		"	b 2b\n"					\
 		".previous\n"					\
 		".section __ex_table,\"a\"\n"			\
-		"	.balign %5\n"				\
+			PPC_LONG_ALIGN "\n"			\
 			PPC_LONG "1b,3b\n"			\
 		".previous"					\
 		: "=r" (err)					\
-		: "r" (x), "b" (addr), "i" (-EFAULT), "0" (err),\
-		  "i"(sizeof(unsigned long)))
+		: "r" (x), "b" (addr), "i" (-EFAULT), "0" (err))
 
 #ifdef __powerpc64__
 #define __put_user_asm2(x, ptr, retval)				\
@@ -162,13 +162,12 @@
 		"	b 3b\n"					\
 		".previous\n"					\
 		".section __ex_table,\"a\"\n"			\
-		"	.balign %5\n"				\
+			PPC_LONG_ALIGN "\n"			\
 			PPC_LONG "1b,4b\n"			\
 			PPC_LONG "2b,4b\n"			\
 		".previous"					\
 		: "=r" (err)					\
-		: "r" (x), "b" (addr), "i" (-EFAULT), "0" (err),\
-		  "i"(sizeof(unsigned long)))
+		: "r" (x), "b" (addr), "i" (-EFAULT), "0" (err))
 #endif /* __powerpc64__ */
 
 #define __put_user_size(x, ptr, size, retval)			\
@@ -226,12 +225,11 @@
 		"	b 2b\n"				\
 		".previous\n"				\
 		".section __ex_table,\"a\"\n"		\
-		"	.balign %5\n"			\
+			PPC_LONG_ALIGN "\n"		\
 			PPC_LONG "1b,3b\n"		\
 		".previous"				\
 		: "=r" (err), "=r" (x)			\
-		: "b" (addr), "i" (-EFAULT), "0" (err),	\
-		  "i"(sizeof(unsigned long)))
+		: "b" (addr), "i" (-EFAULT), "0" (err))
 
 #ifdef __powerpc64__
 #define __get_user_asm2(x, addr, err)			\
@@ -249,13 +247,12 @@
 		"	b 3b\n"				\
 		".previous\n"				\
 		".section __ex_table,\"a\"\n"		\
-		"	.balign %5\n"			\
+			PPC_LONG_ALIGN "\n"		\
 			PPC_LONG "1b,4b\n"		\
 			PPC_LONG "2b,4b\n"		\
 		".previous"				\
 		: "=r" (err), "=&r" (x)			\
-		: "b" (addr), "i" (-EFAULT), "0" (err),	\
-		  "i"(sizeof(unsigned long)))
+		: "b" (addr), "i" (-EFAULT), "0" (err))
 #endif /* __powerpc64__ */
 
 #define __get_user_size(x, ptr, size, retval)			\
diff --git a/include/asm-powerpc/ucc_fast.h b/include/asm-powerpc/ucc_fast.h
index f529f70..fce16ab 100644
--- a/include/asm-powerpc/ucc_fast.h
+++ b/include/asm-powerpc/ucc_fast.h
@@ -156,11 +156,11 @@
 
 struct ucc_fast_private {
 	struct ucc_fast_info *uf_info;
-	struct ucc_fast *uf_regs;	/* a pointer to memory map of UCC regs. */
-	u32 *p_ucce;		/* a pointer to the event register in memory. */
-	u32 *p_uccm;		/* a pointer to the mask register in memory. */
+	struct ucc_fast __iomem *uf_regs; /* a pointer to the UCC regs. */
+	u32 __iomem *p_ucce;	/* a pointer to the event register in memory. */
+	u32 __iomem *p_uccm;	/* a pointer to the mask register in memory. */
 #ifdef CONFIG_UGETH_TX_ON_DEMAND
-	u16 *p_utodr;		/* pointer to the transmit on demand register */
+	u16 __iomem *p_utodr;	/* pointer to the transmit on demand register */
 #endif
 	int enabled_tx;		/* Whether channel is enabled for Tx (ENT) */
 	int enabled_rx;		/* Whether channel is enabled for Rx (ENR) */
diff --git a/include/asm-sparc/Kbuild b/include/asm-sparc/Kbuild
index 6712237..6cdaf9d 100644
--- a/include/asm-sparc/Kbuild
+++ b/include/asm-sparc/Kbuild
@@ -1,14 +1 @@
-include include/asm-generic/Kbuild.asm
-
-header-y += apc.h
-header-y += asi.h
-header-y += bpp.h
-header-y += jsflash.h
-header-y += openpromio.h
-header-y += reg.h
-header-y += traps.h
-header-y += vfc_ioctls.h
-
-unifdef-y += fbio.h
-unifdef-y += perfctr.h
-unifdef-y += psr.h
+# dummy file to avoid breaking make headers_install
diff --git a/include/asm-sparc/agp.h b/include/asm-sparc/agp.h
new file mode 100644
index 0000000..c245687
--- /dev/null
+++ b/include/asm-sparc/agp.h
@@ -0,0 +1,20 @@
+#ifndef AGP_H
+#define AGP_H 1
+
+/* dummy for now */
+
+#define map_page_into_agp(page)
+#define unmap_page_from_agp(page)
+#define flush_agp_cache() mb()
+
+/* Convert a physical address to an address suitable for the GART. */
+#define phys_to_gart(x) (x)
+#define gart_to_phys(x) (x)
+
+/* GATT allocation. Returns/accepts GATT kernel virtual address. */
+#define alloc_gatt_pages(order)		\
+	((char *)__get_free_pages(GFP_KERNEL, (order)))
+#define free_gatt_pages(table, order)	\
+	free_pages((unsigned long)(table), (order))
+
+#endif
diff --git a/include/asm-sparc/apb.h b/include/asm-sparc/apb.h
new file mode 100644
index 0000000..8f3b57d
--- /dev/null
+++ b/include/asm-sparc/apb.h
@@ -0,0 +1,36 @@
+/*
+ * apb.h: Advanced PCI Bridge Configuration Registers and Bits
+ *
+ * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
+ */
+
+#ifndef _SPARC64_APB_H
+#define _SPARC64_APB_H
+
+#define APB_TICK_REGISTER			0xb0
+#define APB_INT_ACK				0xb8
+#define APB_PRIMARY_MASTER_RETRY_LIMIT		0xc0
+#define APB_DMA_ASFR				0xc8
+#define APB_DMA_AFAR				0xd0
+#define APB_PIO_TARGET_RETRY_LIMIT		0xd8
+#define APB_PIO_TARGET_LATENCY_TIMER		0xd9
+#define APB_DMA_TARGET_RETRY_LIMIT		0xda
+#define APB_DMA_TARGET_LATENCY_TIMER		0xdb
+#define APB_SECONDARY_MASTER_RETRY_LIMIT	0xdc
+#define APB_SECONDARY_CONTROL			0xdd
+#define APB_IO_ADDRESS_MAP			0xde
+#define APB_MEM_ADDRESS_MAP			0xdf
+
+#define APB_PCI_CONTROL_LOW			0xe0
+#  define APB_PCI_CTL_LOW_ARB_PARK			(1 << 21)
+#  define APB_PCI_CTL_LOW_ERRINT_EN			(1 << 8)
+
+#define APB_PCI_CONTROL_HIGH			0xe4
+#  define APB_PCI_CTL_HIGH_SERR				(1 << 2)
+#  define APB_PCI_CTL_HIGH_ARBITER_EN			(1 << 0)
+
+#define APB_PIO_ASFR				0xe8
+#define APB_PIO_AFAR				0xf0
+#define APB_DIAG_REGISTER			0xf8
+
+#endif /* !(_SPARC64_APB_H) */
diff --git a/include/asm-sparc/asi.h b/include/asm-sparc/asi.h
index 158f9b0..74703c5 100644
--- a/include/asm-sparc/asi.h
+++ b/include/asm-sparc/asi.h
@@ -3,7 +3,7 @@
 
 /* asi.h:  Address Space Identifier values for the sparc.
  *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
  *
  * Pioneer work for sun4m: Paul Hatchman (paul@sfe.com.au)
  * Joint edition for sun4c+sun4m: Pete A. Zaitcev <zaitcev@ipmce.su>
@@ -108,4 +108,155 @@
 
 #define ASI_M_ACTION       0x4c   /* Breakpoint Action Register (GNU/Viking) */
 
+/* V9 Architecture mandary ASIs. */
+#define ASI_N			0x04 /* Nucleus				*/
+#define ASI_NL			0x0c /* Nucleus, little endian		*/
+#define ASI_AIUP		0x10 /* Primary, user			*/
+#define ASI_AIUS		0x11 /* Secondary, user			*/
+#define ASI_AIUPL		0x18 /* Primary, user, little endian	*/
+#define ASI_AIUSL		0x19 /* Secondary, user, little endian	*/
+#define ASI_P			0x80 /* Primary, implicit		*/
+#define ASI_S			0x81 /* Secondary, implicit		*/
+#define ASI_PNF			0x82 /* Primary, no fault		*/
+#define ASI_SNF			0x83 /* Secondary, no fault		*/
+#define ASI_PL			0x88 /* Primary, implicit, l-endian	*/
+#define ASI_SL			0x89 /* Secondary, implicit, l-endian	*/
+#define ASI_PNFL		0x8a /* Primary, no fault, l-endian	*/
+#define ASI_SNFL		0x8b /* Secondary, no fault, l-endian	*/
+
+/* SpitFire and later extended ASIs.  The "(III)" marker designates
+ * UltraSparc-III and later specific ASIs.  The "(CMT)" marker designates
+ * Chip Multi Threading specific ASIs.  "(NG)" designates Niagara specific
+ * ASIs, "(4V)" designates SUN4V specific ASIs.
+ */
+#define ASI_PHYS_USE_EC		0x14 /* PADDR, E-cachable		*/
+#define ASI_PHYS_BYPASS_EC_E	0x15 /* PADDR, E-bit			*/
+#define ASI_BLK_AIUP_4V		0x16 /* (4V) Prim, user, block ld/st	*/
+#define ASI_BLK_AIUS_4V		0x17 /* (4V) Sec, user, block ld/st	*/
+#define ASI_PHYS_USE_EC_L	0x1c /* PADDR, E-cachable, little endian*/
+#define ASI_PHYS_BYPASS_EC_E_L	0x1d /* PADDR, E-bit, little endian	*/
+#define ASI_BLK_AIUP_L_4V	0x1e /* (4V) Prim, user, block, l-endian*/
+#define ASI_BLK_AIUS_L_4V	0x1f /* (4V) Sec, user, block, l-endian	*/
+#define ASI_SCRATCHPAD		0x20 /* (4V) Scratch Pad Registers	*/
+#define ASI_MMU			0x21 /* (4V) MMU Context Registers	*/
+#define ASI_BLK_INIT_QUAD_LDD_AIUS 0x23 /* (NG) init-store, twin load,
+					 * secondary, user
+					 */
+#define ASI_NUCLEUS_QUAD_LDD	0x24 /* Cachable, qword load		*/
+#define ASI_QUEUE		0x25 /* (4V) Interrupt Queue Registers	*/
+#define ASI_QUAD_LDD_PHYS_4V	0x26 /* (4V) Physical, qword load	*/
+#define ASI_NUCLEUS_QUAD_LDD_L	0x2c /* Cachable, qword load, l-endian 	*/
+#define ASI_QUAD_LDD_PHYS_L_4V	0x2e /* (4V) Phys, qword load, l-endian	*/
+#define ASI_PCACHE_DATA_STATUS	0x30 /* (III) PCache data stat RAM diag	*/
+#define ASI_PCACHE_DATA		0x31 /* (III) PCache data RAM diag	*/
+#define ASI_PCACHE_TAG		0x32 /* (III) PCache tag RAM diag	*/
+#define ASI_PCACHE_SNOOP_TAG	0x33 /* (III) PCache snoop tag RAM diag	*/
+#define ASI_QUAD_LDD_PHYS	0x34 /* (III+) PADDR, qword load	*/
+#define ASI_WCACHE_VALID_BITS	0x38 /* (III) WCache Valid Bits diag	*/
+#define ASI_WCACHE_DATA		0x39 /* (III) WCache data RAM diag	*/
+#define ASI_WCACHE_TAG		0x3a /* (III) WCache tag RAM diag	*/
+#define ASI_WCACHE_SNOOP_TAG	0x3b /* (III) WCache snoop tag RAM diag	*/
+#define ASI_QUAD_LDD_PHYS_L	0x3c /* (III+) PADDR, qw-load, l-endian	*/
+#define ASI_SRAM_FAST_INIT	0x40 /* (III+) Fast SRAM init		*/
+#define ASI_CORE_AVAILABLE	0x41 /* (CMT) LP Available		*/
+#define ASI_CORE_ENABLE_STAT	0x41 /* (CMT) LP Enable Status		*/
+#define ASI_CORE_ENABLE		0x41 /* (CMT) LP Enable RW		*/
+#define ASI_XIR_STEERING	0x41 /* (CMT) XIR Steering RW		*/
+#define ASI_CORE_RUNNING_RW	0x41 /* (CMT) LP Running RW		*/
+#define ASI_CORE_RUNNING_W1S	0x41 /* (CMT) LP Running Write-One Set	*/
+#define ASI_CORE_RUNNING_W1C	0x41 /* (CMT) LP Running Write-One Clr	*/
+#define ASI_CORE_RUNNING_STAT	0x41 /* (CMT) LP Running Status		*/
+#define ASI_CMT_ERROR_STEERING	0x41 /* (CMT) Error Steering RW		*/
+#define ASI_DCACHE_INVALIDATE	0x42 /* (III) DCache Invalidate diag	*/
+#define ASI_DCACHE_UTAG		0x43 /* (III) DCache uTag diag		*/
+#define ASI_DCACHE_SNOOP_TAG	0x44 /* (III) DCache snoop tag RAM diag	*/
+#define ASI_LSU_CONTROL		0x45 /* Load-store control unit		*/
+#define ASI_DCU_CONTROL_REG	0x45 /* (III) DCache Unit Control reg	*/
+#define ASI_DCACHE_DATA		0x46 /* DCache data-ram diag access	*/
+#define ASI_DCACHE_TAG		0x47 /* Dcache tag/valid ram diag access*/
+#define ASI_INTR_DISPATCH_STAT	0x48 /* IRQ vector dispatch status	*/
+#define ASI_INTR_RECEIVE	0x49 /* IRQ vector receive status	*/
+#define ASI_UPA_CONFIG		0x4a /* UPA config space		*/
+#define ASI_JBUS_CONFIG		0x4a /* (IIIi) JBUS Config Register	*/
+#define ASI_SAFARI_CONFIG	0x4a /* (III) Safari Config Register	*/
+#define ASI_SAFARI_ADDRESS	0x4a /* (III) Safari Address Register	*/
+#define ASI_ESTATE_ERROR_EN	0x4b /* E-cache error enable space	*/
+#define ASI_AFSR		0x4c /* Async fault status register	*/
+#define ASI_AFAR		0x4d /* Async fault address register	*/
+#define ASI_EC_TAG_DATA		0x4e /* E-cache tag/valid ram diag acc	*/
+#define ASI_IMMU		0x50 /* Insn-MMU main register space	*/
+#define ASI_IMMU_TSB_8KB_PTR	0x51 /* Insn-MMU 8KB TSB pointer reg	*/
+#define ASI_IMMU_TSB_64KB_PTR	0x52 /* Insn-MMU 64KB TSB pointer reg	*/
+#define ASI_ITLB_DATA_IN	0x54 /* Insn-MMU TLB data in reg	*/
+#define ASI_ITLB_DATA_ACCESS	0x55 /* Insn-MMU TLB data access reg	*/
+#define ASI_ITLB_TAG_READ	0x56 /* Insn-MMU TLB tag read reg	*/
+#define ASI_IMMU_DEMAP		0x57 /* Insn-MMU TLB demap		*/
+#define ASI_DMMU		0x58 /* Data-MMU main register space	*/
+#define ASI_DMMU_TSB_8KB_PTR	0x59 /* Data-MMU 8KB TSB pointer reg	*/
+#define ASI_DMMU_TSB_64KB_PTR	0x5a /* Data-MMU 16KB TSB pointer reg	*/
+#define ASI_DMMU_TSB_DIRECT_PTR	0x5b /* Data-MMU TSB direct pointer reg	*/
+#define ASI_DTLB_DATA_IN	0x5c /* Data-MMU TLB data in reg	*/
+#define ASI_DTLB_DATA_ACCESS	0x5d /* Data-MMU TLB data access reg	*/
+#define ASI_DTLB_TAG_READ	0x5e /* Data-MMU TLB tag read reg	*/
+#define ASI_DMMU_DEMAP		0x5f /* Data-MMU TLB demap		*/
+#define ASI_IIU_INST_TRAP	0x60 /* (III) Instruction Breakpoint	*/
+#define ASI_INTR_ID		0x63 /* (CMT) Interrupt ID register	*/
+#define ASI_CORE_ID		0x63 /* (CMT) LP ID register		*/
+#define ASI_CESR_ID		0x63 /* (CMT) CESR ID register		*/
+#define ASI_IC_INSTR		0x66 /* Insn cache instrucion ram diag	*/
+#define ASI_IC_TAG		0x67 /* Insn cache tag/valid ram diag 	*/
+#define ASI_IC_STAG		0x68 /* (III) Insn cache snoop tag ram	*/
+#define ASI_IC_PRE_DECODE	0x6e /* Insn cache pre-decode ram diag	*/
+#define ASI_IC_NEXT_FIELD	0x6f /* Insn cache next-field ram diag	*/
+#define ASI_BRPRED_ARRAY	0x6f /* (III) Branch Prediction RAM diag*/
+#define ASI_BLK_AIUP		0x70 /* Primary, user, block load/store	*/
+#define ASI_BLK_AIUS		0x71 /* Secondary, user, block ld/st	*/
+#define ASI_MCU_CTRL_REG	0x72 /* (III) Memory controller regs	*/
+#define ASI_EC_DATA		0x74 /* (III) E-cache data staging reg	*/
+#define ASI_EC_CTRL		0x75 /* (III) E-cache control reg	*/
+#define ASI_EC_W		0x76 /* E-cache diag write access	*/
+#define ASI_UDB_ERROR_W		0x77 /* External UDB error regs W	*/
+#define ASI_UDB_CONTROL_W	0x77 /* External UDB control regs W	*/
+#define ASI_INTR_W		0x77 /* IRQ vector dispatch write	*/
+#define ASI_INTR_DATAN_W	0x77 /* (III) Out irq vector data reg N	*/
+#define ASI_INTR_DISPATCH_W	0x77 /* (III) Interrupt vector dispatch	*/
+#define ASI_BLK_AIUPL		0x78 /* Primary, user, little, blk ld/st*/
+#define ASI_BLK_AIUSL		0x79 /* Secondary, user, little, blk ld/st*/
+#define ASI_EC_R		0x7e /* E-cache diag read access	*/
+#define ASI_UDBH_ERROR_R	0x7f /* External UDB error regs rd hi	*/
+#define ASI_UDBL_ERROR_R	0x7f /* External UDB error regs rd low	*/
+#define ASI_UDBH_CONTROL_R	0x7f /* External UDB control regs rd hi	*/
+#define ASI_UDBL_CONTROL_R	0x7f /* External UDB control regs rd low*/
+#define ASI_INTR_R		0x7f /* IRQ vector dispatch read	*/
+#define ASI_INTR_DATAN_R	0x7f /* (III) In irq vector data reg N	*/
+#define ASI_PST8_P		0xc0 /* Primary, 8 8-bit, partial	*/
+#define ASI_PST8_S		0xc1 /* Secondary, 8 8-bit, partial	*/
+#define ASI_PST16_P		0xc2 /* Primary, 4 16-bit, partial	*/
+#define ASI_PST16_S		0xc3 /* Secondary, 4 16-bit, partial	*/
+#define ASI_PST32_P		0xc4 /* Primary, 2 32-bit, partial	*/
+#define ASI_PST32_S		0xc5 /* Secondary, 2 32-bit, partial	*/
+#define ASI_PST8_PL		0xc8 /* Primary, 8 8-bit, partial, L	*/
+#define ASI_PST8_SL		0xc9 /* Secondary, 8 8-bit, partial, L	*/
+#define ASI_PST16_PL		0xca /* Primary, 4 16-bit, partial, L	*/
+#define ASI_PST16_SL		0xcb /* Secondary, 4 16-bit, partial, L	*/
+#define ASI_PST32_PL		0xcc /* Primary, 2 32-bit, partial, L	*/
+#define ASI_PST32_SL		0xcd /* Secondary, 2 32-bit, partial, L	*/
+#define ASI_FL8_P		0xd0 /* Primary, 1 8-bit, fpu ld/st	*/
+#define ASI_FL8_S		0xd1 /* Secondary, 1 8-bit, fpu ld/st	*/
+#define ASI_FL16_P		0xd2 /* Primary, 1 16-bit, fpu ld/st	*/
+#define ASI_FL16_S		0xd3 /* Secondary, 1 16-bit, fpu ld/st	*/
+#define ASI_FL8_PL		0xd8 /* Primary, 1 8-bit, fpu ld/st, L	*/
+#define ASI_FL8_SL		0xd9 /* Secondary, 1 8-bit, fpu ld/st, L*/
+#define ASI_FL16_PL		0xda /* Primary, 1 16-bit, fpu ld/st, L	*/
+#define ASI_FL16_SL		0xdb /* Secondary, 1 16-bit, fpu ld/st,L*/
+#define ASI_BLK_COMMIT_P	0xe0 /* Primary, blk store commit	*/
+#define ASI_BLK_COMMIT_S	0xe1 /* Secondary, blk store commit	*/
+#define ASI_BLK_INIT_QUAD_LDD_P	0xe2 /* (NG) init-store, twin load,
+				      * primary, implicit
+				      */
+#define ASI_BLK_P		0xf0 /* Primary, blk ld/st		*/
+#define ASI_BLK_S		0xf1 /* Secondary, blk ld/st		*/
+#define ASI_BLK_PL		0xf8 /* Primary, blk ld/st, little	*/
+#define ASI_BLK_SL		0xf9 /* Secondary, blk ld/st, little	*/
+
 #endif /* _SPARC_ASI_H */
diff --git a/include/asm-sparc/atomic.h b/include/asm-sparc/atomic.h
index 5c944b5..66d8166 100644
--- a/include/asm-sparc/atomic.h
+++ b/include/asm-sparc/atomic.h
@@ -1,165 +1,8 @@
-/* atomic.h: These still suck, but the I-cache hit rate is higher.
- *
- * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
- * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com.au)
- * Copyright (C) 2007 Kyle McMartin (kyle@parisc-linux.org)
- *
- * Additions by Keith M Wesolowski (wesolows@foobazco.org) based
- * on asm-parisc/atomic.h Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>.
- */
-
-#ifndef __ARCH_SPARC_ATOMIC__
-#define __ARCH_SPARC_ATOMIC__
-
-#include <linux/types.h>
-
-typedef struct { volatile int counter; } atomic_t;
-
-#ifdef __KERNEL__
-
-#define ATOMIC_INIT(i)  { (i) }
-
-extern int __atomic_add_return(int, atomic_t *);
-extern int atomic_cmpxchg(atomic_t *, int, int);
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-extern int atomic_add_unless(atomic_t *, int, int);
-extern void atomic_set(atomic_t *, int);
-
-#define atomic_read(v)          ((v)->counter)
-
-#define atomic_add(i, v)	((void)__atomic_add_return( (int)(i), (v)))
-#define atomic_sub(i, v)	((void)__atomic_add_return(-(int)(i), (v)))
-#define atomic_inc(v)		((void)__atomic_add_return(        1, (v)))
-#define atomic_dec(v)		((void)__atomic_add_return(       -1, (v)))
-
-#define atomic_add_return(i, v)	(__atomic_add_return( (int)(i), (v)))
-#define atomic_sub_return(i, v)	(__atomic_add_return(-(int)(i), (v)))
-#define atomic_inc_return(v)	(__atomic_add_return(        1, (v)))
-#define atomic_dec_return(v)	(__atomic_add_return(       -1, (v)))
-
-#define atomic_add_negative(a, v)	(atomic_add_return((a), (v)) < 0)
-
-/*
- * atomic_inc_and_test - increment and test
- * @v: pointer of type atomic_t
- *
- * Atomically increments @v by 1
- * and returns true if the result is zero, or false for all
- * other cases.
- */
-#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
-
-#define atomic_dec_and_test(v) (atomic_dec_return(v) == 0)
-#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0)
-
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
-
-/* This is the old 24-bit implementation.  It's still used internally
- * by some sparc-specific code, notably the semaphore implementation.
- */
-typedef struct { volatile int counter; } atomic24_t;
-
-#ifndef CONFIG_SMP
-
-#define ATOMIC24_INIT(i)  { (i) }
-#define atomic24_read(v)          ((v)->counter)
-#define atomic24_set(v, i)        (((v)->counter) = i)
-
+#ifndef ___ASM_SPARC_ATOMIC_H
+#define ___ASM_SPARC_ATOMIC_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/atomic_64.h>
 #else
-/* We do the bulk of the actual work out of line in two common
- * routines in assembler, see arch/sparc/lib/atomic.S for the
- * "fun" details.
- *
- * For SMP the trick is you embed the spin lock byte within
- * the word, use the low byte so signedness is easily retained
- * via a quick arithmetic shift.  It looks like this:
- *
- *	----------------------------------------
- *	| signed 24-bit counter value |  lock  |  atomic_t
- *	----------------------------------------
- *	 31                          8 7      0
- */
-
-#define ATOMIC24_INIT(i)	{ ((i) << 8) }
-
-static inline int atomic24_read(const atomic24_t *v)
-{
-	int ret = v->counter;
-
-	while(ret & 0xff)
-		ret = v->counter;
-
-	return ret >> 8;
-}
-
-#define atomic24_set(v, i)	(((v)->counter) = ((i) << 8))
+#include <asm-sparc/atomic_32.h>
 #endif
-
-static inline int __atomic24_add(int i, atomic24_t *v)
-{
-	register volatile int *ptr asm("g1");
-	register int increment asm("g2");
-	register int tmp1 asm("g3");
-	register int tmp2 asm("g4");
-	register int tmp3 asm("g7");
-
-	ptr = &v->counter;
-	increment = i;
-
-	__asm__ __volatile__(
-	"mov	%%o7, %%g4\n\t"
-	"call	___atomic24_add\n\t"
-	" add	%%o7, 8, %%o7\n"
-	: "=&r" (increment), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3)
-	: "0" (increment), "r" (ptr)
-	: "memory", "cc");
-
-	return increment;
-}
-
-static inline int __atomic24_sub(int i, atomic24_t *v)
-{
-	register volatile int *ptr asm("g1");
-	register int increment asm("g2");
-	register int tmp1 asm("g3");
-	register int tmp2 asm("g4");
-	register int tmp3 asm("g7");
-
-	ptr = &v->counter;
-	increment = i;
-
-	__asm__ __volatile__(
-	"mov	%%o7, %%g4\n\t"
-	"call	___atomic24_sub\n\t"
-	" add	%%o7, 8, %%o7\n"
-	: "=&r" (increment), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3)
-	: "0" (increment), "r" (ptr)
-	: "memory", "cc");
-
-	return increment;
-}
-
-#define atomic24_add(i, v) ((void)__atomic24_add((i), (v)))
-#define atomic24_sub(i, v) ((void)__atomic24_sub((i), (v)))
-
-#define atomic24_dec_return(v) __atomic24_sub(1, (v))
-#define atomic24_inc_return(v) __atomic24_add(1, (v))
-
-#define atomic24_sub_and_test(i, v) (__atomic24_sub((i), (v)) == 0)
-#define atomic24_dec_and_test(v) (__atomic24_sub(1, (v)) == 0)
-
-#define atomic24_inc(v) ((void)__atomic24_add(1, (v)))
-#define atomic24_dec(v) ((void)__atomic24_sub(1, (v)))
-
-#define atomic24_add_negative(i, v) (__atomic24_add((i), (v)) < 0)
-
-/* Atomic operations are already serializing */
-#define smp_mb__before_atomic_dec()	barrier()
-#define smp_mb__after_atomic_dec()	barrier()
-#define smp_mb__before_atomic_inc()	barrier()
-#define smp_mb__after_atomic_inc()	barrier()
-
-#endif /* !(__KERNEL__) */
-
-#include <asm-generic/atomic.h>
-#endif /* !(__ARCH_SPARC_ATOMIC__) */
+#endif
diff --git a/include/asm-sparc/atomic_32.h b/include/asm-sparc/atomic_32.h
new file mode 100644
index 0000000..5c944b5
--- /dev/null
+++ b/include/asm-sparc/atomic_32.h
@@ -0,0 +1,165 @@
+/* atomic.h: These still suck, but the I-cache hit rate is higher.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com.au)
+ * Copyright (C) 2007 Kyle McMartin (kyle@parisc-linux.org)
+ *
+ * Additions by Keith M Wesolowski (wesolows@foobazco.org) based
+ * on asm-parisc/atomic.h Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>.
+ */
+
+#ifndef __ARCH_SPARC_ATOMIC__
+#define __ARCH_SPARC_ATOMIC__
+
+#include <linux/types.h>
+
+typedef struct { volatile int counter; } atomic_t;
+
+#ifdef __KERNEL__
+
+#define ATOMIC_INIT(i)  { (i) }
+
+extern int __atomic_add_return(int, atomic_t *);
+extern int atomic_cmpxchg(atomic_t *, int, int);
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+extern int atomic_add_unless(atomic_t *, int, int);
+extern void atomic_set(atomic_t *, int);
+
+#define atomic_read(v)          ((v)->counter)
+
+#define atomic_add(i, v)	((void)__atomic_add_return( (int)(i), (v)))
+#define atomic_sub(i, v)	((void)__atomic_add_return(-(int)(i), (v)))
+#define atomic_inc(v)		((void)__atomic_add_return(        1, (v)))
+#define atomic_dec(v)		((void)__atomic_add_return(       -1, (v)))
+
+#define atomic_add_return(i, v)	(__atomic_add_return( (int)(i), (v)))
+#define atomic_sub_return(i, v)	(__atomic_add_return(-(int)(i), (v)))
+#define atomic_inc_return(v)	(__atomic_add_return(        1, (v)))
+#define atomic_dec_return(v)	(__atomic_add_return(       -1, (v)))
+
+#define atomic_add_negative(a, v)	(atomic_add_return((a), (v)) < 0)
+
+/*
+ * atomic_inc_and_test - increment and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
+
+#define atomic_dec_and_test(v) (atomic_dec_return(v) == 0)
+#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0)
+
+#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+
+/* This is the old 24-bit implementation.  It's still used internally
+ * by some sparc-specific code, notably the semaphore implementation.
+ */
+typedef struct { volatile int counter; } atomic24_t;
+
+#ifndef CONFIG_SMP
+
+#define ATOMIC24_INIT(i)  { (i) }
+#define atomic24_read(v)          ((v)->counter)
+#define atomic24_set(v, i)        (((v)->counter) = i)
+
+#else
+/* We do the bulk of the actual work out of line in two common
+ * routines in assembler, see arch/sparc/lib/atomic.S for the
+ * "fun" details.
+ *
+ * For SMP the trick is you embed the spin lock byte within
+ * the word, use the low byte so signedness is easily retained
+ * via a quick arithmetic shift.  It looks like this:
+ *
+ *	----------------------------------------
+ *	| signed 24-bit counter value |  lock  |  atomic_t
+ *	----------------------------------------
+ *	 31                          8 7      0
+ */
+
+#define ATOMIC24_INIT(i)	{ ((i) << 8) }
+
+static inline int atomic24_read(const atomic24_t *v)
+{
+	int ret = v->counter;
+
+	while(ret & 0xff)
+		ret = v->counter;
+
+	return ret >> 8;
+}
+
+#define atomic24_set(v, i)	(((v)->counter) = ((i) << 8))
+#endif
+
+static inline int __atomic24_add(int i, atomic24_t *v)
+{
+	register volatile int *ptr asm("g1");
+	register int increment asm("g2");
+	register int tmp1 asm("g3");
+	register int tmp2 asm("g4");
+	register int tmp3 asm("g7");
+
+	ptr = &v->counter;
+	increment = i;
+
+	__asm__ __volatile__(
+	"mov	%%o7, %%g4\n\t"
+	"call	___atomic24_add\n\t"
+	" add	%%o7, 8, %%o7\n"
+	: "=&r" (increment), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3)
+	: "0" (increment), "r" (ptr)
+	: "memory", "cc");
+
+	return increment;
+}
+
+static inline int __atomic24_sub(int i, atomic24_t *v)
+{
+	register volatile int *ptr asm("g1");
+	register int increment asm("g2");
+	register int tmp1 asm("g3");
+	register int tmp2 asm("g4");
+	register int tmp3 asm("g7");
+
+	ptr = &v->counter;
+	increment = i;
+
+	__asm__ __volatile__(
+	"mov	%%o7, %%g4\n\t"
+	"call	___atomic24_sub\n\t"
+	" add	%%o7, 8, %%o7\n"
+	: "=&r" (increment), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3)
+	: "0" (increment), "r" (ptr)
+	: "memory", "cc");
+
+	return increment;
+}
+
+#define atomic24_add(i, v) ((void)__atomic24_add((i), (v)))
+#define atomic24_sub(i, v) ((void)__atomic24_sub((i), (v)))
+
+#define atomic24_dec_return(v) __atomic24_sub(1, (v))
+#define atomic24_inc_return(v) __atomic24_add(1, (v))
+
+#define atomic24_sub_and_test(i, v) (__atomic24_sub((i), (v)) == 0)
+#define atomic24_dec_and_test(v) (__atomic24_sub(1, (v)) == 0)
+
+#define atomic24_inc(v) ((void)__atomic24_add(1, (v)))
+#define atomic24_dec(v) ((void)__atomic24_sub(1, (v)))
+
+#define atomic24_add_negative(i, v) (__atomic24_add((i), (v)) < 0)
+
+/* Atomic operations are already serializing */
+#define smp_mb__before_atomic_dec()	barrier()
+#define smp_mb__after_atomic_dec()	barrier()
+#define smp_mb__before_atomic_inc()	barrier()
+#define smp_mb__after_atomic_inc()	barrier()
+
+#endif /* !(__KERNEL__) */
+
+#include <asm-generic/atomic.h>
+#endif /* !(__ARCH_SPARC_ATOMIC__) */
diff --git a/include/asm-sparc/atomic_64.h b/include/asm-sparc/atomic_64.h
new file mode 100644
index 0000000..2c71ec4a
--- /dev/null
+++ b/include/asm-sparc/atomic_64.h
@@ -0,0 +1,128 @@
+/* atomic.h: Thankfully the V9 is at least reasonable for this
+ *           stuff.
+ *
+ * Copyright (C) 1996, 1997, 2000 David S. Miller (davem@redhat.com)
+ */
+
+#ifndef __ARCH_SPARC64_ATOMIC__
+#define __ARCH_SPARC64_ATOMIC__
+
+#include <linux/types.h>
+#include <asm/system.h>
+
+typedef struct { volatile int counter; } atomic_t;
+typedef struct { volatile __s64 counter; } atomic64_t;
+
+#define ATOMIC_INIT(i)		{ (i) }
+#define ATOMIC64_INIT(i)	{ (i) }
+
+#define atomic_read(v)		((v)->counter)
+#define atomic64_read(v)	((v)->counter)
+
+#define atomic_set(v, i)	(((v)->counter) = i)
+#define atomic64_set(v, i)	(((v)->counter) = i)
+
+extern void atomic_add(int, atomic_t *);
+extern void atomic64_add(int, atomic64_t *);
+extern void atomic_sub(int, atomic_t *);
+extern void atomic64_sub(int, atomic64_t *);
+
+extern int atomic_add_ret(int, atomic_t *);
+extern int atomic64_add_ret(int, atomic64_t *);
+extern int atomic_sub_ret(int, atomic_t *);
+extern int atomic64_sub_ret(int, atomic64_t *);
+
+#define atomic_dec_return(v) atomic_sub_ret(1, v)
+#define atomic64_dec_return(v) atomic64_sub_ret(1, v)
+
+#define atomic_inc_return(v) atomic_add_ret(1, v)
+#define atomic64_inc_return(v) atomic64_add_ret(1, v)
+
+#define atomic_sub_return(i, v) atomic_sub_ret(i, v)
+#define atomic64_sub_return(i, v) atomic64_sub_ret(i, v)
+
+#define atomic_add_return(i, v) atomic_add_ret(i, v)
+#define atomic64_add_return(i, v) atomic64_add_ret(i, v)
+
+/*
+ * atomic_inc_and_test - increment and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
+#define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0)
+
+#define atomic_sub_and_test(i, v) (atomic_sub_ret(i, v) == 0)
+#define atomic64_sub_and_test(i, v) (atomic64_sub_ret(i, v) == 0)
+
+#define atomic_dec_and_test(v) (atomic_sub_ret(1, v) == 0)
+#define atomic64_dec_and_test(v) (atomic64_sub_ret(1, v) == 0)
+
+#define atomic_inc(v) atomic_add(1, v)
+#define atomic64_inc(v) atomic64_add(1, v)
+
+#define atomic_dec(v) atomic_sub(1, v)
+#define atomic64_dec(v) atomic64_sub(1, v)
+
+#define atomic_add_negative(i, v) (atomic_add_ret(i, v) < 0)
+#define atomic64_add_negative(i, v) (atomic64_add_ret(i, v) < 0)
+
+#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+
+static inline int atomic_add_unless(atomic_t *v, int a, int u)
+{
+	int c, old;
+	c = atomic_read(v);
+	for (;;) {
+		if (unlikely(c == (u)))
+			break;
+		old = atomic_cmpxchg((v), c, c + (a));
+		if (likely(old == c))
+			break;
+		c = old;
+	}
+	return c != (u);
+}
+
+#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+
+#define atomic64_cmpxchg(v, o, n) \
+	((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
+#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
+
+static inline int atomic64_add_unless(atomic64_t *v, long a, long u)
+{
+	long c, old;
+	c = atomic64_read(v);
+	for (;;) {
+		if (unlikely(c == (u)))
+			break;
+		old = atomic64_cmpxchg((v), c, c + (a));
+		if (likely(old == c))
+			break;
+		c = old;
+	}
+	return c != (u);
+}
+
+#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+
+/* Atomic operations are already serializing */
+#ifdef CONFIG_SMP
+#define smp_mb__before_atomic_dec()	membar_storeload_loadload();
+#define smp_mb__after_atomic_dec()	membar_storeload_storestore();
+#define smp_mb__before_atomic_inc()	membar_storeload_loadload();
+#define smp_mb__after_atomic_inc()	membar_storeload_storestore();
+#else
+#define smp_mb__before_atomic_dec()	barrier()
+#define smp_mb__after_atomic_dec()	barrier()
+#define smp_mb__before_atomic_inc()	barrier()
+#define smp_mb__after_atomic_inc()	barrier()
+#endif
+
+#include <asm-generic/atomic.h>
+#endif /* !(__ARCH_SPARC64_ATOMIC__) */
diff --git a/include/asm-sparc/auxio.h b/include/asm-sparc/auxio.h
index e552b8d..24c6f3c 100644
--- a/include/asm-sparc/auxio.h
+++ b/include/asm-sparc/auxio.h
@@ -1,89 +1,8 @@
-/*
- * auxio.h:  Definitions and code for the Auxiliary I/O register.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-#ifndef _SPARC_AUXIO_H
-#define _SPARC_AUXIO_H
-
-#include <asm/system.h>
-#include <asm/vaddrs.h>
-
-/* This register is an unsigned char in IO space.  It does two things.
- * First, it is used to control the front panel LED light on machines
- * that have it (good for testing entry points to trap handlers and irq's)
- * Secondly, it controls various floppy drive parameters.
- */
-#define AUXIO_ORMEIN      0xf0    /* All writes must set these bits. */
-#define AUXIO_ORMEIN4M    0xc0    /* sun4m - All writes must set these bits. */
-#define AUXIO_FLPY_DENS   0x20    /* Floppy density, high if set. Read only. */
-#define AUXIO_FLPY_DCHG   0x10    /* A disk change occurred.  Read only. */
-#define AUXIO_EDGE_ON     0x10    /* sun4m - On means Jumper block is in. */
-#define AUXIO_FLPY_DSEL   0x08    /* Drive select/start-motor. Write only. */
-#define AUXIO_LINK_TEST   0x08    /* sun4m - On means TPE Carrier detect. */
-
-/* Set the following to one, then zero, after doing a pseudo DMA transfer. */
-#define AUXIO_FLPY_TCNT   0x04    /* Floppy terminal count. Write only. */
-
-/* Set the following to zero to eject the floppy. */
-#define AUXIO_FLPY_EJCT   0x02    /* Eject floppy disk.  Write only. */
-#define AUXIO_LED         0x01    /* On if set, off if unset. Read/Write */
-
-#ifndef __ASSEMBLY__
-
-/* 
- * NOTE: these routines are implementation dependent-- 
- * understand the hardware you are querying! 
- */
-extern void set_auxio(unsigned char bits_on, unsigned char bits_off);
-extern unsigned char get_auxio(void); /* .../asm-sparc/floppy.h */
-
-/*
- * The following routines are provided for driver-compatibility
- * with sparc64 (primarily sunlance.c)
- */
-
-#define AUXIO_LTE_ON    1
-#define AUXIO_LTE_OFF   0
-
-/* auxio_set_lte - Set Link Test Enable (TPE Link Detect)
- *
- * on - AUXIO_LTE_ON or AUXIO_LTE_OFF
- */
-#define auxio_set_lte(on) \
-do { \
-	if(on) { \
-		set_auxio(AUXIO_LINK_TEST, 0); \
-	} else { \
-		set_auxio(0, AUXIO_LINK_TEST); \
-	} \
-} while (0)
-
-#define AUXIO_LED_ON    1
-#define AUXIO_LED_OFF   0
-
-/* auxio_set_led - Set system front panel LED
- *
- * on - AUXIO_LED_ON or AUXIO_LED_OFF
- */
-#define auxio_set_led(on) \
-do { \
-	if(on) { \
-		set_auxio(AUXIO_LED, 0); \
-	} else { \
-		set_auxio(0, AUXIO_LED); \
-	} \
-} while (0)
-
-#endif /* !(__ASSEMBLY__) */
-
-
-/* AUXIO2 (Power Off Control) */
-extern __volatile__ unsigned char * auxio_power_register;
-
-#define	AUXIO_POWER_DETECT_FAILURE	32
-#define	AUXIO_POWER_CLEAR_FAILURE	2
-#define	AUXIO_POWER_OFF			1
-
-
-#endif /* !(_SPARC_AUXIO_H) */
+#ifndef ___ASM_SPARC_AUXIO_H
+#define ___ASM_SPARC_AUXIO_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/auxio_64.h>
+#else
+#include <asm-sparc/auxio_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/auxio_32.h b/include/asm-sparc/auxio_32.h
new file mode 100644
index 0000000..4db8f23
--- /dev/null
+++ b/include/asm-sparc/auxio_32.h
@@ -0,0 +1,89 @@
+/*
+ * auxio.h:  Definitions and code for the Auxiliary I/O register.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+#ifndef _SPARC_AUXIO_H
+#define _SPARC_AUXIO_H
+
+#include <asm/system.h>
+#include <asm/vaddrs.h>
+
+/* This register is an unsigned char in IO space.  It does two things.
+ * First, it is used to control the front panel LED light on machines
+ * that have it (good for testing entry points to trap handlers and irq's)
+ * Secondly, it controls various floppy drive parameters.
+ */
+#define AUXIO_ORMEIN      0xf0    /* All writes must set these bits. */
+#define AUXIO_ORMEIN4M    0xc0    /* sun4m - All writes must set these bits. */
+#define AUXIO_FLPY_DENS   0x20    /* Floppy density, high if set. Read only. */
+#define AUXIO_FLPY_DCHG   0x10    /* A disk change occurred.  Read only. */
+#define AUXIO_EDGE_ON     0x10    /* sun4m - On means Jumper block is in. */
+#define AUXIO_FLPY_DSEL   0x08    /* Drive select/start-motor. Write only. */
+#define AUXIO_LINK_TEST   0x08    /* sun4m - On means TPE Carrier detect. */
+
+/* Set the following to one, then zero, after doing a pseudo DMA transfer. */
+#define AUXIO_FLPY_TCNT   0x04    /* Floppy terminal count. Write only. */
+
+/* Set the following to zero to eject the floppy. */
+#define AUXIO_FLPY_EJCT   0x02    /* Eject floppy disk.  Write only. */
+#define AUXIO_LED         0x01    /* On if set, off if unset. Read/Write */
+
+#ifndef __ASSEMBLY__
+
+/*
+ * NOTE: these routines are implementation dependent--
+ * understand the hardware you are querying!
+ */
+extern void set_auxio(unsigned char bits_on, unsigned char bits_off);
+extern unsigned char get_auxio(void); /* .../asm-sparc/floppy.h */
+
+/*
+ * The following routines are provided for driver-compatibility
+ * with sparc64 (primarily sunlance.c)
+ */
+
+#define AUXIO_LTE_ON    1
+#define AUXIO_LTE_OFF   0
+
+/* auxio_set_lte - Set Link Test Enable (TPE Link Detect)
+ *
+ * on - AUXIO_LTE_ON or AUXIO_LTE_OFF
+ */
+#define auxio_set_lte(on) \
+do { \
+	if(on) { \
+		set_auxio(AUXIO_LINK_TEST, 0); \
+	} else { \
+		set_auxio(0, AUXIO_LINK_TEST); \
+	} \
+} while (0)
+
+#define AUXIO_LED_ON    1
+#define AUXIO_LED_OFF   0
+
+/* auxio_set_led - Set system front panel LED
+ *
+ * on - AUXIO_LED_ON or AUXIO_LED_OFF
+ */
+#define auxio_set_led(on) \
+do { \
+	if(on) { \
+		set_auxio(AUXIO_LED, 0); \
+	} else { \
+		set_auxio(0, AUXIO_LED); \
+	} \
+} while (0)
+
+#endif /* !(__ASSEMBLY__) */
+
+
+/* AUXIO2 (Power Off Control) */
+extern __volatile__ unsigned char * auxio_power_register;
+
+#define	AUXIO_POWER_DETECT_FAILURE	32
+#define	AUXIO_POWER_CLEAR_FAILURE	2
+#define	AUXIO_POWER_OFF			1
+
+
+#endif /* !(_SPARC_AUXIO_H) */
diff --git a/include/asm-sparc/auxio_64.h b/include/asm-sparc/auxio_64.h
new file mode 100644
index 0000000..f61cd1e
--- /dev/null
+++ b/include/asm-sparc/auxio_64.h
@@ -0,0 +1,100 @@
+/*
+ * auxio.h:  Definitions and code for the Auxiliary I/O registers.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * Refactoring for unified NCR/PCIO support 2002 Eric Brower (ebrower@usa.net)
+ */
+#ifndef _SPARC64_AUXIO_H
+#define _SPARC64_AUXIO_H
+
+/* AUXIO implementations:
+ * sbus-based NCR89C105 "Slavio"
+ *	LED/Floppy (AUX1) register
+ *	Power (AUX2) register
+ *
+ * ebus-based auxio on PCIO
+ *	LED Auxio Register
+ *	Power Auxio Register
+ *
+ * Register definitions from NCR _NCR89C105 Chip Specification_
+ *
+ * SLAVIO AUX1 @ 0x1900000
+ * -------------------------------------------------
+ * | (R) | (R) |  D  | (R) |  E  |  M  |  T  |  L  |
+ * -------------------------------------------------
+ * (R) - bit 7:6,4 are reserved and should be masked in s/w
+ *  D  - Floppy Density Sense (1=high density) R/O
+ *  E  - Link Test Enable, directly reflected on AT&T 7213 LTE pin
+ *  M  - Monitor/Mouse Mux, directly reflected on MON_MSE_MUX pin
+ *  T  - Terminal Count: sends TC pulse to 82077 floppy controller
+ *  L  - System LED on front panel (0=off, 1=on)
+ */
+#define AUXIO_AUX1_MASK		0xc0 /* Mask bits 		*/
+#define AUXIO_AUX1_FDENS	0x20 /* Floppy Density Sense	*/
+#define AUXIO_AUX1_LTE 		0x08 /* Link Test Enable 	*/
+#define AUXIO_AUX1_MMUX		0x04 /* Monitor/Mouse Mux	*/
+#define AUXIO_AUX1_FTCNT	0x02 /* Terminal Count, 	*/
+#define AUXIO_AUX1_LED		0x01 /* System LED		*/
+
+/* SLAVIO AUX2 @ 0x1910000
+ * -------------------------------------------------
+ * | (R) | (R) |  D  | (R) | (R) | (R) |  C  |  F  |
+ * -------------------------------------------------
+ * (R) - bits 7:6,4:2 are reserved and should be masked in s/w
+ *  D  - Power Failure Detect (1=power fail)
+ *  C  - Clear Power Failure Detect Int (1=clear)
+ *  F  - Power Off (1=power off)
+ */
+#define AUXIO_AUX2_MASK		0xdc /* Mask Bits		*/
+#define AUXIO_AUX2_PFAILDET	0x20 /* Power Fail Detect	*/
+#define AUXIO_AUX2_PFAILCLR 	0x02 /* Clear Pwr Fail Det Intr	*/
+#define AUXIO_AUX2_PWR_OFF	0x01 /* Power Off		*/
+
+/* Register definitions from Sun Microsystems _PCIO_ p/n 802-7837
+ *
+ * PCIO LED Auxio @ 0x726000
+ * -------------------------------------------------
+ * |             31:1 Unused                 | LED |
+ * -------------------------------------------------
+ * Bits 31:1 unused
+ * LED - System LED on front panel (0=off, 1=on)
+ */
+#define AUXIO_PCIO_LED		0x01 /* System LED 		*/
+
+/* PCIO Power Auxio @ 0x724000
+ * -------------------------------------------------
+ * |             31:2 Unused           | CPO | SPO |
+ * -------------------------------------------------
+ * Bits 31:2 unused
+ * CPO - Courtesy Power Off (1=off)
+ * SPO - System Power Off   (1=off)
+ */
+#define AUXIO_PCIO_CPWR_OFF	0x02 /* Courtesy Power Off	*/
+#define AUXIO_PCIO_SPWR_OFF	0x01 /* System Power Off	*/
+
+#ifndef __ASSEMBLY__
+
+extern void __iomem *auxio_register;
+
+#define AUXIO_LTE_ON	1
+#define AUXIO_LTE_OFF	0
+
+/* auxio_set_lte - Set Link Test Enable (TPE Link Detect)
+ *
+ * on - AUXIO_LTE_ON or AUXIO_LTE_OFF
+ */
+extern void auxio_set_lte(int on);
+
+#define AUXIO_LED_ON	1
+#define AUXIO_LED_OFF	0
+
+/* auxio_set_led - Set system front panel LED
+ *
+ * on - AUXIO_LED_ON or AUXIO_LED_OFF
+ */
+extern void auxio_set_led(int on);
+
+#endif /* ifndef __ASSEMBLY__ */
+
+#endif /* !(_SPARC64_AUXIO_H) */
diff --git a/include/asm-sparc/backoff.h b/include/asm-sparc/backoff.h
new file mode 100644
index 0000000..fa1fdf6
--- /dev/null
+++ b/include/asm-sparc/backoff.h
@@ -0,0 +1,31 @@
+#ifndef _SPARC64_BACKOFF_H
+#define _SPARC64_BACKOFF_H
+
+#define BACKOFF_LIMIT	(4 * 1024)
+
+#ifdef CONFIG_SMP
+
+#define BACKOFF_SETUP(reg)	\
+	mov	1, reg
+
+#define BACKOFF_SPIN(reg, tmp, label)	\
+	mov	reg, tmp; \
+88:	brnz,pt	tmp, 88b; \
+	 sub	tmp, 1, tmp; \
+	set	BACKOFF_LIMIT, tmp; \
+	cmp	reg, tmp; \
+	bg,pn	%xcc, label; \
+	 nop; \
+	ba,pt	%xcc, label; \
+	 sllx	reg, 1, reg;
+
+#else
+
+#define BACKOFF_SETUP(reg)
+#define BACKOFF_SPIN(reg, tmp, label) \
+	ba,pt	%xcc, label; \
+	 nop;
+
+#endif
+
+#endif /* _SPARC64_BACKOFF_H */
diff --git a/include/asm-sparc/bbc.h b/include/asm-sparc/bbc.h
new file mode 100644
index 0000000..423a858
--- /dev/null
+++ b/include/asm-sparc/bbc.h
@@ -0,0 +1,225 @@
+/*
+ * bbc.h: Defines for BootBus Controller found on UltraSPARC-III
+ *        systems.
+ *
+ * Copyright (C) 2000 David S. Miller (davem@redhat.com)
+ */
+
+#ifndef _SPARC64_BBC_H
+#define _SPARC64_BBC_H
+
+/* Register sizes are indicated by "B" (Byte, 1-byte),
+ * "H" (Half-word, 2 bytes), "W" (Word, 4 bytes) or
+ * "Q" (Quad, 8 bytes) inside brackets.
+ */
+
+#define BBC_AID		0x00	/* [B] Agent ID			*/
+#define BBC_DEVP	0x01	/* [B] Device Present		*/
+#define BBC_ARB		0x02	/* [B] Arbitration		*/
+#define BBC_QUIESCE	0x03	/* [B] Quiesce			*/
+#define BBC_WDACTION	0x04	/* [B] Watchdog Action		*/
+#define BBC_SPG		0x06	/* [B] Soft POR Gen		*/
+#define BBC_SXG		0x07	/* [B] Soft XIR Gen		*/
+#define BBC_PSRC	0x08	/* [W] POR Source		*/
+#define BBC_XSRC	0x0c	/* [B] XIR Source		*/
+#define BBC_CSC		0x0d	/* [B] Clock Synthesizers Control*/
+#define BBC_ES_CTRL	0x0e	/* [H] Energy Star Control	*/
+#define BBC_ES_ACT	0x10	/* [W] E* Assert Change Time	*/
+#define BBC_ES_DACT	0x14	/* [B] E* De-Assert Change Time	*/
+#define BBC_ES_DABT	0x15	/* [B] E* De-Assert Bypass Time	*/
+#define BBC_ES_ABT	0x16	/* [H] E* Assert Bypass Time	*/
+#define BBC_ES_PST	0x18	/* [W] E* PLL Settle Time	*/
+#define BBC_ES_FSL	0x1c	/* [W] E* Frequency Switch Latency*/
+#define BBC_EBUST	0x20	/* [Q] EBUS Timing		*/
+#define BBC_JTAG_CMD	0x28	/* [W] JTAG+ Command		*/
+#define BBC_JTAG_CTRL	0x2c	/* [B] JTAG+ Control		*/
+#define BBC_I2C_SEL	0x2d	/* [B] I2C Selection		*/
+#define BBC_I2C_0_S1	0x2e	/* [B] I2C ctrlr-0 reg S1	*/
+#define BBC_I2C_0_S0	0x2f	/* [B] I2C ctrlr-0 regs S0,S0',S2,S3*/
+#define BBC_I2C_1_S1	0x30	/* [B] I2C ctrlr-1 reg S1	*/
+#define BBC_I2C_1_S0	0x31	/* [B] I2C ctrlr-1 regs S0,S0',S2,S3*/
+#define BBC_KBD_BEEP	0x32	/* [B] Keyboard Beep		*/
+#define BBC_KBD_BCNT	0x34	/* [W] Keyboard Beep Counter	*/
+
+#define BBC_REGS_SIZE	0x40
+
+/* There is a 2K scratch ram area at offset 0x80000 but I doubt
+ * we will use it for anything.
+ */
+
+/* Agent ID register.  This register shows the Safari Agent ID
+ * for the processors.  The value returned depends upon which
+ * cpu is reading the register.
+ */
+#define BBC_AID_ID	0x07	/* Safari ID		*/
+#define BBC_AID_RESV	0xf8	/* Reserved		*/
+
+/* Device Present register.  One can determine which cpus are actually
+ * present in the machine by interrogating this register.
+ */
+#define BBC_DEVP_CPU0	0x01	/* Processor 0 present	*/
+#define BBC_DEVP_CPU1	0x02	/* Processor 1 present	*/
+#define BBC_DEVP_CPU2	0x04	/* Processor 2 present	*/
+#define BBC_DEVP_CPU3	0x08	/* Processor 3 present	*/
+#define BBC_DEVP_RESV	0xf0	/* Reserved		*/
+
+/* Arbitration register.  This register is used to block access to
+ * the BBC from a particular cpu.
+ */
+#define BBC_ARB_CPU0	0x01	/* Enable cpu 0 BBC arbitratrion */
+#define BBC_ARB_CPU1	0x02	/* Enable cpu 1 BBC arbitratrion */
+#define BBC_ARB_CPU2	0x04	/* Enable cpu 2 BBC arbitratrion */
+#define BBC_ARB_CPU3	0x08	/* Enable cpu 3 BBC arbitratrion */
+#define BBC_ARB_RESV	0xf0	/* Reserved			 */
+
+/* Quiesce register.  Bus and BBC segments for cpus can be disabled
+ * with this register, ie. for hot plugging.
+ */
+#define BBC_QUIESCE_S02	0x01	/* Quiesce Safari segment for cpu 0 and 2 */
+#define BBC_QUIESCE_S13	0x02	/* Quiesce Safari segment for cpu 1 and 3 */
+#define BBC_QUIESCE_B02	0x04	/* Quiesce BBC segment for cpu 0 and 2    */
+#define BBC_QUIESCE_B13	0x08	/* Quiesce BBC segment for cpu 1 and 3    */
+#define BBC_QUIESCE_FD0 0x10	/* Disable Fatal_Error[0] reporting	  */
+#define BBC_QUIESCE_FD1 0x20	/* Disable Fatal_Error[1] reporting	  */
+#define BBC_QUIESCE_FD2 0x40	/* Disable Fatal_Error[2] reporting	  */
+#define BBC_QUIESCE_FD3 0x80	/* Disable Fatal_Error[3] reporting	  */
+
+/* Watchdog Action register.  When the watchdog device timer expires
+ * a line is enabled to the BBC.  The action BBC takes when this line
+ * is asserted can be controlled by this regiser.
+ */
+#define BBC_WDACTION_RST  0x01	/* When set, watchdog causes system reset.
+				 * When clear, BBC ignores watchdog signal.
+				 */
+#define BBC_WDACTION_RESV 0xfe	/* Reserved */
+
+/* Soft_POR_GEN register.  The POR (Power On Reset) signal may be asserted
+ * for specific processors or all processors via this register.
+ */
+#define BBC_SPG_CPU0	0x01 /* Assert POR for processor 0	*/
+#define BBC_SPG_CPU1	0x02 /* Assert POR for processor 1	*/
+#define BBC_SPG_CPU2	0x04 /* Assert POR for processor 2	*/
+#define BBC_SPG_CPU3	0x08 /* Assert POR for processor 3	*/
+#define BBC_SPG_CPUALL	0x10 /* Reset all processors and reset
+			      * the entire system.
+			      */
+#define BBC_SPG_RESV	0xe0 /* Reserved			*/
+
+/* Soft_XIR_GEN register.  The XIR (eXternally Initiated Reset) signal
+ * may be asserted to specific processors via this register.
+ */
+#define BBC_SXG_CPU0	0x01 /* Assert XIR for processor 0	*/
+#define BBC_SXG_CPU1	0x02 /* Assert XIR for processor 1	*/
+#define BBC_SXG_CPU2	0x04 /* Assert XIR for processor 2	*/
+#define BBC_SXG_CPU3	0x08 /* Assert XIR for processor 3	*/
+#define BBC_SXG_RESV	0xf0 /* Reserved			*/
+
+/* POR Source register.  One may identify the cause of the most recent
+ * reset by reading this register.
+ */
+#define BBC_PSRC_SPG0	0x0001 /* CPU 0 reset via BBC_SPG register	*/
+#define BBC_PSRC_SPG1	0x0002 /* CPU 1 reset via BBC_SPG register	*/
+#define BBC_PSRC_SPG2	0x0004 /* CPU 2 reset via BBC_SPG register	*/
+#define BBC_PSRC_SPG3	0x0008 /* CPU 3 reset via BBC_SPG register	*/
+#define BBC_PSRC_SPGSYS	0x0010 /* System reset via BBC_SPG register	*/
+#define BBC_PSRC_JTAG	0x0020 /* System reset via JTAG+		*/
+#define BBC_PSRC_BUTTON	0x0040 /* System reset via push-button dongle	*/
+#define BBC_PSRC_PWRUP	0x0080 /* System reset via power-up		*/
+#define BBC_PSRC_FE0	0x0100 /* CPU 0 reported Fatal_Error		*/
+#define BBC_PSRC_FE1	0x0200 /* CPU 1 reported Fatal_Error		*/
+#define BBC_PSRC_FE2	0x0400 /* CPU 2 reported Fatal_Error		*/
+#define BBC_PSRC_FE3	0x0800 /* CPU 3 reported Fatal_Error		*/
+#define BBC_PSRC_FE4	0x1000 /* Schizo reported Fatal_Error		*/
+#define BBC_PSRC_FE5	0x2000 /* Safari device 5 reported Fatal_Error	*/
+#define BBC_PSRC_FE6	0x4000 /* CPMS reported Fatal_Error		*/
+#define BBC_PSRC_SYNTH	0x8000 /* System reset when on-board clock synthesizers
+				* were updated.
+				*/
+#define BBC_PSRC_WDT   0x10000 /* System reset via Super I/O watchdog	*/
+#define BBC_PSRC_RSC   0x20000 /* System reset via RSC remote monitoring
+				* device
+				*/
+
+/* XIR Source register.  The source of an XIR event sent to a processor may
+ * be determined via this register.
+ */
+#define BBC_XSRC_SXG0	0x01	/* CPU 0 received XIR via Soft_XIR_GEN reg */
+#define BBC_XSRC_SXG1	0x02	/* CPU 1 received XIR via Soft_XIR_GEN reg */
+#define BBC_XSRC_SXG2	0x04	/* CPU 2 received XIR via Soft_XIR_GEN reg */
+#define BBC_XSRC_SXG3	0x08	/* CPU 3 received XIR via Soft_XIR_GEN reg */
+#define BBC_XSRC_JTAG	0x10	/* All CPUs received XIR via JTAG+         */
+#define BBC_XSRC_W_OR_B	0x20	/* All CPUs received XIR either because:
+				 * a) Super I/O watchdog fired, or
+				 * b) XIR push button was activated
+				 */
+#define BBC_XSRC_RESV	0xc0	/* Reserved				   */
+
+/* Clock Synthesizers Control register.  This register provides the big-bang
+ * programming interface to the two clock synthesizers of the machine.
+ */
+#define BBC_CSC_SLOAD	0x01	/* Directly connected to S_LOAD pins	*/
+#define BBC_CSC_SDATA	0x02	/* Directly connected to S_DATA pins	*/
+#define BBC_CSC_SCLOCK	0x04	/* Directly connected to S_CLOCK pins	*/
+#define BBC_CSC_RESV	0x78	/* Reserved				*/
+#define BBC_CSC_RST	0x80	/* Generate system reset when S_LOAD==1	*/
+
+/* Energy Star Control register.  This register is used to generate the
+ * clock frequency change trigger to the main system devices (Schizo and
+ * the processors).  The transition occurs when bits in this register
+ * go from 0 to 1, only one bit must be set at once else no action
+ * occurs.  Basically the sequence of events is:
+ * a) Choose new frequency: full, 1/2 or 1/32
+ * b) Program this desired frequency into the cpus and Schizo.
+ * c) Set the same value in this register.
+ * d) 16 system clocks later, clear this register.
+ */
+#define BBC_ES_CTRL_1_1		0x01	/* Full frequency	*/
+#define BBC_ES_CTRL_1_2		0x02	/* 1/2 frequency	*/
+#define BBC_ES_CTRL_1_32	0x20	/* 1/32 frequency	*/
+#define BBC_ES_RESV		0xdc	/* Reserved		*/
+
+/* Energy Star Assert Change Time register.  This determines the number
+ * of BBC clock cycles (which is half the system frequency) between
+ * the detection of FREEZE_ACK being asserted and the assertion of
+ * the CLK_CHANGE_L[2:0] signals.
+ */
+#define BBC_ES_ACT_VAL	0xff
+
+/* Energy Star Assert Bypass Time register.  This determines the number
+ * of BBC clock cycles (which is half the system frequency) between
+ * the assertion of the CLK_CHANGE_L[2:0] signals and the assertion of
+ * the ESTAR_PLL_BYPASS signal.
+ */
+#define BBC_ES_ABT_VAL	0xffff
+
+/* Energy Star PLL Settle Time register.  This determines the number of
+ * BBC clock cycles (which is half the system frequency) between the
+ * de-assertion of CLK_CHANGE_L[2:0] and the de-assertion of the FREEZE_L
+ * signal.
+ */
+#define BBC_ES_PST_VAL	0xffffffff
+
+/* Energy Star Frequency Switch Latency register.  This is the number of
+ * BBC clocks between the de-assertion of CLK_CHANGE_L[2:0] and the first
+ * edge of the Safari clock at the new frequency.
+ */
+#define BBC_ES_FSL_VAL	0xffffffff
+
+/* Keyboard Beep control register.  This is a simple enabler for the audio
+ * beep sound.
+ */
+#define BBC_KBD_BEEP_ENABLE	0x01 /* Enable beep	*/
+#define BBC_KBD_BEEP_RESV	0xfe /* Reserved	*/
+
+/* Keyboard Beep Counter register.  There is a free-running counter inside
+ * the BBC which runs at half the system clock.  The bit set in this register
+ * determines when the audio sound is generated.  So for example if bit
+ * 10 is set, the audio beep will oscillate at 1/(2**12).  The keyboard beep
+ * generator automatically selects a different bit to use if the system clock
+ * is changed via Energy Star.
+ */
+#define BBC_KBD_BCNT_BITS	0x0007fc00
+#define BBC_KBC_BCNT_RESV	0xfff803ff
+
+#endif /* _SPARC64_BBC_H */
+
diff --git a/include/asm-sparc/bitops.h b/include/asm-sparc/bitops.h
index 68b98a7e..1a2949d 100644
--- a/include/asm-sparc/bitops.h
+++ b/include/asm-sparc/bitops.h
@@ -1,111 +1,8 @@
-/*
- * bitops.h: Bit string operations on the Sparc.
- *
- * Copyright 1995 David S. Miller (davem@caip.rutgers.edu)
- * Copyright 1996 Eddie C. Dost   (ecd@skynet.be)
- * Copyright 2001 Anton Blanchard (anton@samba.org)
- */
-
-#ifndef _SPARC_BITOPS_H
-#define _SPARC_BITOPS_H
-
-#include <linux/compiler.h>
-#include <asm/byteorder.h>
-
-#ifdef __KERNEL__
-
-#ifndef _LINUX_BITOPS_H
-#error only <linux/bitops.h> can be included directly
+#ifndef ___ASM_SPARC_BITOPS_H
+#define ___ASM_SPARC_BITOPS_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/bitops_64.h>
+#else
+#include <asm-sparc/bitops_32.h>
 #endif
-
-extern unsigned long ___set_bit(unsigned long *addr, unsigned long mask);
-extern unsigned long ___clear_bit(unsigned long *addr, unsigned long mask);
-extern unsigned long ___change_bit(unsigned long *addr, unsigned long mask);
-
-/*
- * Set bit 'nr' in 32-bit quantity at address 'addr' where bit '0'
- * is in the highest of the four bytes and bit '31' is the high bit
- * within the first byte. Sparc is BIG-Endian. Unless noted otherwise
- * all bit-ops return 0 if bit was previously clear and != 0 otherwise.
- */
-static inline int test_and_set_bit(unsigned long nr, volatile unsigned long *addr)
-{
-	unsigned long *ADDR, mask;
-
-	ADDR = ((unsigned long *) addr) + (nr >> 5);
-	mask = 1 << (nr & 31);
-
-	return ___set_bit(ADDR, mask) != 0;
-}
-
-static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
-{
-	unsigned long *ADDR, mask;
-
-	ADDR = ((unsigned long *) addr) + (nr >> 5);
-	mask = 1 << (nr & 31);
-
-	(void) ___set_bit(ADDR, mask);
-}
-
-static inline int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr)
-{
-	unsigned long *ADDR, mask;
-
-	ADDR = ((unsigned long *) addr) + (nr >> 5);
-	mask = 1 << (nr & 31);
-
-	return ___clear_bit(ADDR, mask) != 0;
-}
-
-static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
-{
-	unsigned long *ADDR, mask;
-
-	ADDR = ((unsigned long *) addr) + (nr >> 5);
-	mask = 1 << (nr & 31);
-
-	(void) ___clear_bit(ADDR, mask);
-}
-
-static inline int test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
-{
-	unsigned long *ADDR, mask;
-
-	ADDR = ((unsigned long *) addr) + (nr >> 5);
-	mask = 1 << (nr & 31);
-
-	return ___change_bit(ADDR, mask) != 0;
-}
-
-static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
-{
-	unsigned long *ADDR, mask;
-
-	ADDR = ((unsigned long *) addr) + (nr >> 5);
-	mask = 1 << (nr & 31);
-
-	(void) ___change_bit(ADDR, mask);
-}
-
-#include <asm-generic/bitops/non-atomic.h>
-
-#define smp_mb__before_clear_bit()	do { } while(0)
-#define smp_mb__after_clear_bit()	do { } while(0)
-
-#include <asm-generic/bitops/ffz.h>
-#include <asm-generic/bitops/__ffs.h>
-#include <asm-generic/bitops/sched.h>
-#include <asm-generic/bitops/ffs.h>
-#include <asm-generic/bitops/fls.h>
-#include <asm-generic/bitops/fls64.h>
-#include <asm-generic/bitops/hweight.h>
-#include <asm-generic/bitops/lock.h>
-#include <asm-generic/bitops/find.h>
-#include <asm-generic/bitops/ext2-non-atomic.h>
-#include <asm-generic/bitops/ext2-atomic.h>
-#include <asm-generic/bitops/minix.h>
-
-#endif /* __KERNEL__ */
-
-#endif /* defined(_SPARC_BITOPS_H) */
+#endif
diff --git a/include/asm-sparc/bitops_32.h b/include/asm-sparc/bitops_32.h
new file mode 100644
index 0000000..68b98a7e
--- /dev/null
+++ b/include/asm-sparc/bitops_32.h
@@ -0,0 +1,111 @@
+/*
+ * bitops.h: Bit string operations on the Sparc.
+ *
+ * Copyright 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright 1996 Eddie C. Dost   (ecd@skynet.be)
+ * Copyright 2001 Anton Blanchard (anton@samba.org)
+ */
+
+#ifndef _SPARC_BITOPS_H
+#define _SPARC_BITOPS_H
+
+#include <linux/compiler.h>
+#include <asm/byteorder.h>
+
+#ifdef __KERNEL__
+
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
+extern unsigned long ___set_bit(unsigned long *addr, unsigned long mask);
+extern unsigned long ___clear_bit(unsigned long *addr, unsigned long mask);
+extern unsigned long ___change_bit(unsigned long *addr, unsigned long mask);
+
+/*
+ * Set bit 'nr' in 32-bit quantity at address 'addr' where bit '0'
+ * is in the highest of the four bytes and bit '31' is the high bit
+ * within the first byte. Sparc is BIG-Endian. Unless noted otherwise
+ * all bit-ops return 0 if bit was previously clear and != 0 otherwise.
+ */
+static inline int test_and_set_bit(unsigned long nr, volatile unsigned long *addr)
+{
+	unsigned long *ADDR, mask;
+
+	ADDR = ((unsigned long *) addr) + (nr >> 5);
+	mask = 1 << (nr & 31);
+
+	return ___set_bit(ADDR, mask) != 0;
+}
+
+static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
+{
+	unsigned long *ADDR, mask;
+
+	ADDR = ((unsigned long *) addr) + (nr >> 5);
+	mask = 1 << (nr & 31);
+
+	(void) ___set_bit(ADDR, mask);
+}
+
+static inline int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr)
+{
+	unsigned long *ADDR, mask;
+
+	ADDR = ((unsigned long *) addr) + (nr >> 5);
+	mask = 1 << (nr & 31);
+
+	return ___clear_bit(ADDR, mask) != 0;
+}
+
+static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
+{
+	unsigned long *ADDR, mask;
+
+	ADDR = ((unsigned long *) addr) + (nr >> 5);
+	mask = 1 << (nr & 31);
+
+	(void) ___clear_bit(ADDR, mask);
+}
+
+static inline int test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
+{
+	unsigned long *ADDR, mask;
+
+	ADDR = ((unsigned long *) addr) + (nr >> 5);
+	mask = 1 << (nr & 31);
+
+	return ___change_bit(ADDR, mask) != 0;
+}
+
+static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
+{
+	unsigned long *ADDR, mask;
+
+	ADDR = ((unsigned long *) addr) + (nr >> 5);
+	mask = 1 << (nr & 31);
+
+	(void) ___change_bit(ADDR, mask);
+}
+
+#include <asm-generic/bitops/non-atomic.h>
+
+#define smp_mb__before_clear_bit()	do { } while(0)
+#define smp_mb__after_clear_bit()	do { } while(0)
+
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
+#include <asm-generic/bitops/find.h>
+#include <asm-generic/bitops/ext2-non-atomic.h>
+#include <asm-generic/bitops/ext2-atomic.h>
+#include <asm-generic/bitops/minix.h>
+
+#endif /* __KERNEL__ */
+
+#endif /* defined(_SPARC_BITOPS_H) */
diff --git a/include/asm-sparc/bitops_64.h b/include/asm-sparc/bitops_64.h
new file mode 100644
index 0000000..bb87b80
--- /dev/null
+++ b/include/asm-sparc/bitops_64.h
@@ -0,0 +1,107 @@
+/*
+ * bitops.h: Bit string operations on the V9.
+ *
+ * Copyright 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC64_BITOPS_H
+#define _SPARC64_BITOPS_H
+
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
+#include <linux/compiler.h>
+#include <asm/byteorder.h>
+
+extern int test_and_set_bit(unsigned long nr, volatile unsigned long *addr);
+extern int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr);
+extern int test_and_change_bit(unsigned long nr, volatile unsigned long *addr);
+extern void set_bit(unsigned long nr, volatile unsigned long *addr);
+extern void clear_bit(unsigned long nr, volatile unsigned long *addr);
+extern void change_bit(unsigned long nr, volatile unsigned long *addr);
+
+#include <asm-generic/bitops/non-atomic.h>
+
+#ifdef CONFIG_SMP
+#define smp_mb__before_clear_bit()	membar_storeload_loadload()
+#define smp_mb__after_clear_bit()	membar_storeload_storestore()
+#else
+#define smp_mb__before_clear_bit()	barrier()
+#define smp_mb__after_clear_bit()	barrier()
+#endif
+
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/__fls.h>
+#include <asm-generic/bitops/fls64.h>
+
+#ifdef __KERNEL__
+
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/ffs.h>
+
+/*
+ * hweightN: returns the hamming weight (i.e. the number
+ * of bits set) of a N-bit word
+ */
+
+#ifdef ULTRA_HAS_POPULATION_COUNT
+
+static inline unsigned int hweight64(unsigned long w)
+{
+	unsigned int res;
+
+	__asm__ ("popc %1,%0" : "=r" (res) : "r" (w));
+	return res;
+}
+
+static inline unsigned int hweight32(unsigned int w)
+{
+	unsigned int res;
+
+	__asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffffffff));
+	return res;
+}
+
+static inline unsigned int hweight16(unsigned int w)
+{
+	unsigned int res;
+
+	__asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffff));
+	return res;
+}
+
+static inline unsigned int hweight8(unsigned int w)
+{
+	unsigned int res;
+
+	__asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xff));
+	return res;
+}
+
+#else
+
+#include <asm-generic/bitops/hweight.h>
+
+#endif
+#include <asm-generic/bitops/lock.h>
+#endif /* __KERNEL__ */
+
+#include <asm-generic/bitops/find.h>
+
+#ifdef __KERNEL__
+
+#include <asm-generic/bitops/ext2-non-atomic.h>
+
+#define ext2_set_bit_atomic(lock,nr,addr) \
+	test_and_set_bit((nr) ^ 0x38,(unsigned long *)(addr))
+#define ext2_clear_bit_atomic(lock,nr,addr) \
+	test_and_clear_bit((nr) ^ 0x38,(unsigned long *)(addr))
+
+#include <asm-generic/bitops/minix.h>
+
+#endif /* __KERNEL__ */
+
+#endif /* defined(_SPARC64_BITOPS_H) */
diff --git a/include/asm-sparc/cacheflush.h b/include/asm-sparc/cacheflush.h
index 68ac109..2b6a379 100644
--- a/include/asm-sparc/cacheflush.h
+++ b/include/asm-sparc/cacheflush.h
@@ -1,85 +1,8 @@
-#ifndef _SPARC_CACHEFLUSH_H
-#define _SPARC_CACHEFLUSH_H
-
-#include <linux/mm.h>		/* Common for other includes */
-// #include <linux/kernel.h> from pgalloc.h
-// #include <linux/sched.h>  from pgalloc.h
-
-// #include <asm/page.h>
-#include <asm/btfixup.h>
-
-/*
- * Fine grained cache flushing.
- */
-#ifdef CONFIG_SMP
-
-BTFIXUPDEF_CALL(void, local_flush_cache_all, void)
-BTFIXUPDEF_CALL(void, local_flush_cache_mm, struct mm_struct *)
-BTFIXUPDEF_CALL(void, local_flush_cache_range, struct vm_area_struct *, unsigned long, unsigned long)
-BTFIXUPDEF_CALL(void, local_flush_cache_page, struct vm_area_struct *, unsigned long)
-
-#define local_flush_cache_all() BTFIXUP_CALL(local_flush_cache_all)()
-#define local_flush_cache_mm(mm) BTFIXUP_CALL(local_flush_cache_mm)(mm)
-#define local_flush_cache_range(vma,start,end) BTFIXUP_CALL(local_flush_cache_range)(vma,start,end)
-#define local_flush_cache_page(vma,addr) BTFIXUP_CALL(local_flush_cache_page)(vma,addr)
-
-BTFIXUPDEF_CALL(void, local_flush_page_to_ram, unsigned long)
-BTFIXUPDEF_CALL(void, local_flush_sig_insns, struct mm_struct *, unsigned long)
-
-#define local_flush_page_to_ram(addr) BTFIXUP_CALL(local_flush_page_to_ram)(addr)
-#define local_flush_sig_insns(mm,insn_addr) BTFIXUP_CALL(local_flush_sig_insns)(mm,insn_addr)
-
-extern void smp_flush_cache_all(void);
-extern void smp_flush_cache_mm(struct mm_struct *mm);
-extern void smp_flush_cache_range(struct vm_area_struct *vma,
-				  unsigned long start,
-				  unsigned long end);
-extern void smp_flush_cache_page(struct vm_area_struct *vma, unsigned long page);
-
-extern void smp_flush_page_to_ram(unsigned long page);
-extern void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr);
-
-#endif /* CONFIG_SMP */
-
-BTFIXUPDEF_CALL(void, flush_cache_all, void)
-BTFIXUPDEF_CALL(void, flush_cache_mm, struct mm_struct *)
-BTFIXUPDEF_CALL(void, flush_cache_range, struct vm_area_struct *, unsigned long, unsigned long)
-BTFIXUPDEF_CALL(void, flush_cache_page, struct vm_area_struct *, unsigned long)
-
-#define flush_cache_all() BTFIXUP_CALL(flush_cache_all)()
-#define flush_cache_mm(mm) BTFIXUP_CALL(flush_cache_mm)(mm)
-#define flush_cache_dup_mm(mm) BTFIXUP_CALL(flush_cache_mm)(mm)
-#define flush_cache_range(vma,start,end) BTFIXUP_CALL(flush_cache_range)(vma,start,end)
-#define flush_cache_page(vma,addr,pfn) BTFIXUP_CALL(flush_cache_page)(vma,addr)
-#define flush_icache_range(start, end)		do { } while (0)
-#define flush_icache_page(vma, pg)		do { } while (0)
-
-#define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
-
-#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-	do {							\
-		flush_cache_page(vma, vaddr, page_to_pfn(page));\
-		memcpy(dst, src, len);				\
-	} while (0)
-#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-	do {							\
-		flush_cache_page(vma, vaddr, page_to_pfn(page));\
-		memcpy(dst, src, len);				\
-	} while (0)
-
-BTFIXUPDEF_CALL(void, __flush_page_to_ram, unsigned long)
-BTFIXUPDEF_CALL(void, flush_sig_insns, struct mm_struct *, unsigned long)
-
-#define __flush_page_to_ram(addr) BTFIXUP_CALL(__flush_page_to_ram)(addr)
-#define flush_sig_insns(mm,insn_addr) BTFIXUP_CALL(flush_sig_insns)(mm,insn_addr)
-
-extern void sparc_flush_page_to_ram(struct page *page);
-
-#define flush_dcache_page(page)			sparc_flush_page_to_ram(page)
-#define flush_dcache_mmap_lock(mapping)		do { } while (0)
-#define flush_dcache_mmap_unlock(mapping)	do { } while (0)
-
-#define flush_cache_vmap(start, end)		flush_cache_all()
-#define flush_cache_vunmap(start, end)		flush_cache_all()
-
-#endif /* _SPARC_CACHEFLUSH_H */
+#ifndef ___ASM_SPARC_CACHEFLUSH_H
+#define ___ASM_SPARC_CACHEFLUSH_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/cacheflush_64.h>
+#else
+#include <asm-sparc/cacheflush_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/cacheflush_32.h b/include/asm-sparc/cacheflush_32.h
new file mode 100644
index 0000000..68ac109
--- /dev/null
+++ b/include/asm-sparc/cacheflush_32.h
@@ -0,0 +1,85 @@
+#ifndef _SPARC_CACHEFLUSH_H
+#define _SPARC_CACHEFLUSH_H
+
+#include <linux/mm.h>		/* Common for other includes */
+// #include <linux/kernel.h> from pgalloc.h
+// #include <linux/sched.h>  from pgalloc.h
+
+// #include <asm/page.h>
+#include <asm/btfixup.h>
+
+/*
+ * Fine grained cache flushing.
+ */
+#ifdef CONFIG_SMP
+
+BTFIXUPDEF_CALL(void, local_flush_cache_all, void)
+BTFIXUPDEF_CALL(void, local_flush_cache_mm, struct mm_struct *)
+BTFIXUPDEF_CALL(void, local_flush_cache_range, struct vm_area_struct *, unsigned long, unsigned long)
+BTFIXUPDEF_CALL(void, local_flush_cache_page, struct vm_area_struct *, unsigned long)
+
+#define local_flush_cache_all() BTFIXUP_CALL(local_flush_cache_all)()
+#define local_flush_cache_mm(mm) BTFIXUP_CALL(local_flush_cache_mm)(mm)
+#define local_flush_cache_range(vma,start,end) BTFIXUP_CALL(local_flush_cache_range)(vma,start,end)
+#define local_flush_cache_page(vma,addr) BTFIXUP_CALL(local_flush_cache_page)(vma,addr)
+
+BTFIXUPDEF_CALL(void, local_flush_page_to_ram, unsigned long)
+BTFIXUPDEF_CALL(void, local_flush_sig_insns, struct mm_struct *, unsigned long)
+
+#define local_flush_page_to_ram(addr) BTFIXUP_CALL(local_flush_page_to_ram)(addr)
+#define local_flush_sig_insns(mm,insn_addr) BTFIXUP_CALL(local_flush_sig_insns)(mm,insn_addr)
+
+extern void smp_flush_cache_all(void);
+extern void smp_flush_cache_mm(struct mm_struct *mm);
+extern void smp_flush_cache_range(struct vm_area_struct *vma,
+				  unsigned long start,
+				  unsigned long end);
+extern void smp_flush_cache_page(struct vm_area_struct *vma, unsigned long page);
+
+extern void smp_flush_page_to_ram(unsigned long page);
+extern void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr);
+
+#endif /* CONFIG_SMP */
+
+BTFIXUPDEF_CALL(void, flush_cache_all, void)
+BTFIXUPDEF_CALL(void, flush_cache_mm, struct mm_struct *)
+BTFIXUPDEF_CALL(void, flush_cache_range, struct vm_area_struct *, unsigned long, unsigned long)
+BTFIXUPDEF_CALL(void, flush_cache_page, struct vm_area_struct *, unsigned long)
+
+#define flush_cache_all() BTFIXUP_CALL(flush_cache_all)()
+#define flush_cache_mm(mm) BTFIXUP_CALL(flush_cache_mm)(mm)
+#define flush_cache_dup_mm(mm) BTFIXUP_CALL(flush_cache_mm)(mm)
+#define flush_cache_range(vma,start,end) BTFIXUP_CALL(flush_cache_range)(vma,start,end)
+#define flush_cache_page(vma,addr,pfn) BTFIXUP_CALL(flush_cache_page)(vma,addr)
+#define flush_icache_range(start, end)		do { } while (0)
+#define flush_icache_page(vma, pg)		do { } while (0)
+
+#define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
+
+#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
+	do {							\
+		flush_cache_page(vma, vaddr, page_to_pfn(page));\
+		memcpy(dst, src, len);				\
+	} while (0)
+#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
+	do {							\
+		flush_cache_page(vma, vaddr, page_to_pfn(page));\
+		memcpy(dst, src, len);				\
+	} while (0)
+
+BTFIXUPDEF_CALL(void, __flush_page_to_ram, unsigned long)
+BTFIXUPDEF_CALL(void, flush_sig_insns, struct mm_struct *, unsigned long)
+
+#define __flush_page_to_ram(addr) BTFIXUP_CALL(__flush_page_to_ram)(addr)
+#define flush_sig_insns(mm,insn_addr) BTFIXUP_CALL(flush_sig_insns)(mm,insn_addr)
+
+extern void sparc_flush_page_to_ram(struct page *page);
+
+#define flush_dcache_page(page)			sparc_flush_page_to_ram(page)
+#define flush_dcache_mmap_lock(mapping)		do { } while (0)
+#define flush_dcache_mmap_unlock(mapping)	do { } while (0)
+
+#define flush_cache_vmap(start, end)		flush_cache_all()
+#define flush_cache_vunmap(start, end)		flush_cache_all()
+
+#endif /* _SPARC_CACHEFLUSH_H */
diff --git a/include/asm-sparc/cacheflush_64.h b/include/asm-sparc/cacheflush_64.h
new file mode 100644
index 0000000..c433217
--- /dev/null
+++ b/include/asm-sparc/cacheflush_64.h
@@ -0,0 +1,76 @@
+#ifndef _SPARC64_CACHEFLUSH_H
+#define _SPARC64_CACHEFLUSH_H
+
+#include <asm/page.h>
+
+#ifndef __ASSEMBLY__
+
+#include <linux/mm.h>
+
+/* Cache flush operations. */
+
+/* These are the same regardless of whether this is an SMP kernel or not. */
+#define flush_cache_mm(__mm) \
+	do { if ((__mm) == current->mm) flushw_user(); } while(0)
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
+#define flush_cache_range(vma, start, end) \
+	flush_cache_mm((vma)->vm_mm)
+#define flush_cache_page(vma, page, pfn) \
+	flush_cache_mm((vma)->vm_mm)
+
+/*
+ * On spitfire, the icache doesn't snoop local stores and we don't
+ * use block commit stores (which invalidate icache lines) during
+ * module load, so we need this.
+ */
+extern void flush_icache_range(unsigned long start, unsigned long end);
+extern void __flush_icache_page(unsigned long);
+
+extern void __flush_dcache_page(void *addr, int flush_icache);
+extern void flush_dcache_page_impl(struct page *page);
+#ifdef CONFIG_SMP
+extern void smp_flush_dcache_page_impl(struct page *page, int cpu);
+extern void flush_dcache_page_all(struct mm_struct *mm, struct page *page);
+#else
+#define smp_flush_dcache_page_impl(page,cpu) flush_dcache_page_impl(page)
+#define flush_dcache_page_all(mm,page) flush_dcache_page_impl(page)
+#endif
+
+extern void __flush_dcache_range(unsigned long start, unsigned long end);
+extern void flush_dcache_page(struct page *page);
+
+#define flush_icache_page(vma, pg)	do { } while(0)
+#define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
+
+extern void flush_ptrace_access(struct vm_area_struct *, struct page *,
+				unsigned long uaddr, void *kaddr,
+				unsigned long len, int write);
+
+#define copy_to_user_page(vma, page, vaddr, dst, src, len)		\
+	do {								\
+		flush_cache_page(vma, vaddr, page_to_pfn(page));	\
+		memcpy(dst, src, len);					\
+		flush_ptrace_access(vma, page, vaddr, src, len, 0);	\
+	} while (0)
+
+#define copy_from_user_page(vma, page, vaddr, dst, src, len) 		\
+	do {								\
+		flush_cache_page(vma, vaddr, page_to_pfn(page));	\
+		memcpy(dst, src, len);					\
+		flush_ptrace_access(vma, page, vaddr, dst, len, 1);	\
+	} while (0)
+
+#define flush_dcache_mmap_lock(mapping)		do { } while (0)
+#define flush_dcache_mmap_unlock(mapping)	do { } while (0)
+
+#define flush_cache_vmap(start, end)		do { } while (0)
+#define flush_cache_vunmap(start, end)		do { } while (0)
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
+/* internal debugging function */
+void kernel_map_pages(struct page *page, int numpages, int enable);
+#endif
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _SPARC64_CACHEFLUSH_H */
diff --git a/include/asm-sparc/chafsr.h b/include/asm-sparc/chafsr.h
new file mode 100644
index 0000000..85c69b3
--- /dev/null
+++ b/include/asm-sparc/chafsr.h
@@ -0,0 +1,241 @@
+#ifndef _SPARC64_CHAFSR_H
+#define _SPARC64_CHAFSR_H
+
+/* Cheetah Asynchronous Fault Status register, ASI=0x4C VA<63:0>=0x0 */
+
+/* Comments indicate which processor variants on which the bit definition
+ * is valid.  Codes are:
+ * ch	-->	cheetah
+ * ch+	-->	cheetah plus
+ * jp	-->	jalapeno
+ */
+
+/* All bits of this register except M_SYNDROME and E_SYNDROME are
+ * read, write 1 to clear.  M_SYNDROME and E_SYNDROME are read-only.
+ */
+
+/* Software bit set by linux trap handlers to indicate that the trap was
+ * signalled at %tl >= 1.
+ */
+#define CHAFSR_TL1		(1UL << 63UL) /* n/a */
+
+/* Unmapped error from system bus for prefetch queue or
+ * store queue read operation
+ */
+#define CHPAFSR_DTO		(1UL << 59UL) /* ch+ */
+
+/* Bus error from system bus for prefetch queue or store queue
+ * read operation
+ */
+#define CHPAFSR_DBERR		(1UL << 58UL) /* ch+ */
+
+/* Hardware corrected E-cache Tag ECC error */
+#define CHPAFSR_THCE		(1UL << 57UL) /* ch+ */
+/* System interface protocol error, hw timeout caused */
+#define JPAFSR_JETO		(1UL << 57UL) /* jp */
+
+/* SW handled correctable E-cache Tag ECC error */
+#define CHPAFSR_TSCE		(1UL << 56UL) /* ch+ */
+/* Parity error on system snoop results */
+#define JPAFSR_SCE		(1UL << 56UL) /* jp */
+
+/* Uncorrectable E-cache Tag ECC error */
+#define CHPAFSR_TUE		(1UL << 55UL) /* ch+ */
+/* System interface protocol error, illegal command detected */
+#define JPAFSR_JEIC		(1UL << 55UL) /* jp */
+
+/* Uncorrectable system bus data ECC error due to prefetch
+ * or store fill request
+ */
+#define CHPAFSR_DUE		(1UL << 54UL) /* ch+ */
+/* System interface protocol error, illegal ADTYPE detected */
+#define JPAFSR_JEIT		(1UL << 54UL) /* jp */
+
+/* Multiple errors of the same type have occurred.  This bit is set when
+ * an uncorrectable error or a SW correctable error occurs and the status
+ * bit to report that error is already set.  When multiple errors of
+ * different types are indicated by setting multiple status bits.
+ *
+ * This bit is not set if multiple HW corrected errors with the same
+ * status bit occur, only uncorrectable and SW correctable ones have
+ * this behavior.
+ *
+ * This bit is not set when multiple ECC errors happen within a single
+ * 64-byte system bus transaction.  Only the first ECC error in a 16-byte
+ * subunit will be logged.  All errors in subsequent 16-byte subunits
+ * from the same 64-byte transaction are ignored.
+ */
+#define CHAFSR_ME		(1UL << 53UL) /* ch,ch+,jp */
+
+/* Privileged state error has occurred.  This is a capture of PSTATE.PRIV
+ * at the time the error is detected.
+ */
+#define CHAFSR_PRIV		(1UL << 52UL) /* ch,ch+,jp */
+
+/* The following bits 51 (CHAFSR_PERR) to 33 (CHAFSR_CE) are sticky error
+ * bits and record the most recently detected errors.  Bits accumulate
+ * errors that have been detected since the last write to clear the bit.
+ */
+
+/* System interface protocol error.  The processor asserts its' ERROR
+ * pin when this event occurs and it also logs a specific cause code
+ * into a JTAG scannable flop.
+ */
+#define CHAFSR_PERR		(1UL << 51UL) /* ch,ch+,jp */
+
+/* Internal processor error.  The processor asserts its' ERROR
+ * pin when this event occurs and it also logs a specific cause code
+ * into a JTAG scannable flop.
+ */
+#define CHAFSR_IERR		(1UL << 50UL) /* ch,ch+,jp */
+
+/* System request parity error on incoming address */
+#define CHAFSR_ISAP		(1UL << 49UL) /* ch,ch+,jp */
+
+/* HW Corrected system bus MTAG ECC error */
+#define CHAFSR_EMC		(1UL << 48UL) /* ch,ch+ */
+/* Parity error on L2 cache tag SRAM */
+#define JPAFSR_ETP		(1UL << 48UL) /* jp */
+
+/* Uncorrectable system bus MTAG ECC error */
+#define CHAFSR_EMU		(1UL << 47UL) /* ch,ch+ */
+/* Out of range memory error has occurred */
+#define JPAFSR_OM		(1UL << 47UL) /* jp */
+
+/* HW Corrected system bus data ECC error for read of interrupt vector */
+#define CHAFSR_IVC		(1UL << 46UL) /* ch,ch+ */
+/* Error due to unsupported store */
+#define JPAFSR_UMS		(1UL << 46UL) /* jp */
+
+/* Uncorrectable system bus data ECC error for read of interrupt vector */
+#define CHAFSR_IVU		(1UL << 45UL) /* ch,ch+,jp */
+
+/* Unmapped error from system bus */
+#define CHAFSR_TO		(1UL << 44UL) /* ch,ch+,jp */
+
+/* Bus error response from system bus */
+#define CHAFSR_BERR		(1UL << 43UL) /* ch,ch+,jp */
+
+/* SW Correctable E-cache ECC error for instruction fetch or data access
+ * other than block load.
+ */
+#define CHAFSR_UCC		(1UL << 42UL) /* ch,ch+,jp */
+
+/* Uncorrectable E-cache ECC error for instruction fetch or data access
+ * other than block load.
+ */
+#define CHAFSR_UCU		(1UL << 41UL) /* ch,ch+,jp */
+
+/* Copyout HW Corrected ECC error */
+#define CHAFSR_CPC		(1UL << 40UL) /* ch,ch+,jp */
+
+/* Copyout Uncorrectable ECC error */
+#define CHAFSR_CPU		(1UL << 39UL) /* ch,ch+,jp */
+
+/* HW Corrected ECC error from E-cache for writeback */
+#define CHAFSR_WDC		(1UL << 38UL) /* ch,ch+,jp */
+
+/* Uncorrectable ECC error from E-cache for writeback */
+#define CHAFSR_WDU		(1UL << 37UL) /* ch,ch+,jp */
+
+/* HW Corrected ECC error from E-cache for store merge or block load */
+#define CHAFSR_EDC		(1UL << 36UL) /* ch,ch+,jp */
+
+/* Uncorrectable ECC error from E-cache for store merge or block load */
+#define CHAFSR_EDU		(1UL << 35UL) /* ch,ch+,jp */
+
+/* Uncorrectable system bus data ECC error for read of memory or I/O */
+#define CHAFSR_UE		(1UL << 34UL) /* ch,ch+,jp */
+
+/* HW Corrected system bus data ECC error for read of memory or I/O */
+#define CHAFSR_CE		(1UL << 33UL) /* ch,ch+,jp */
+
+/* Uncorrectable ECC error from remote cache/memory */
+#define JPAFSR_RUE		(1UL << 32UL) /* jp */
+
+/* Correctable ECC error from remote cache/memory */
+#define JPAFSR_RCE		(1UL << 31UL) /* jp */
+
+/* JBUS parity error on returned read data */
+#define JPAFSR_BP		(1UL << 30UL) /* jp */
+
+/* JBUS parity error on data for writeback or block store */
+#define JPAFSR_WBP		(1UL << 29UL) /* jp */
+
+/* Foreign read to DRAM incurring correctable ECC error */
+#define JPAFSR_FRC		(1UL << 28UL) /* jp */
+
+/* Foreign read to DRAM incurring uncorrectable ECC error */
+#define JPAFSR_FRU		(1UL << 27UL) /* jp */
+
+#define CHAFSR_ERRORS		(CHAFSR_PERR | CHAFSR_IERR | CHAFSR_ISAP | CHAFSR_EMC | \
+				 CHAFSR_EMU | CHAFSR_IVC | CHAFSR_IVU | CHAFSR_TO | \
+				 CHAFSR_BERR | CHAFSR_UCC | CHAFSR_UCU | CHAFSR_CPC | \
+				 CHAFSR_CPU | CHAFSR_WDC | CHAFSR_WDU | CHAFSR_EDC | \
+				 CHAFSR_EDU | CHAFSR_UE | CHAFSR_CE)
+#define CHPAFSR_ERRORS		(CHPAFSR_DTO | CHPAFSR_DBERR | CHPAFSR_THCE | \
+				 CHPAFSR_TSCE | CHPAFSR_TUE | CHPAFSR_DUE | \
+				 CHAFSR_PERR | CHAFSR_IERR | CHAFSR_ISAP | CHAFSR_EMC | \
+				 CHAFSR_EMU | CHAFSR_IVC | CHAFSR_IVU | CHAFSR_TO | \
+				 CHAFSR_BERR | CHAFSR_UCC | CHAFSR_UCU | CHAFSR_CPC | \
+				 CHAFSR_CPU | CHAFSR_WDC | CHAFSR_WDU | CHAFSR_EDC | \
+				 CHAFSR_EDU | CHAFSR_UE | CHAFSR_CE)
+#define JPAFSR_ERRORS		(JPAFSR_JETO | JPAFSR_SCE | JPAFSR_JEIC | \
+				 JPAFSR_JEIT | CHAFSR_PERR | CHAFSR_IERR | \
+				 CHAFSR_ISAP | JPAFSR_ETP | JPAFSR_OM | \
+				 JPAFSR_UMS | CHAFSR_IVU | CHAFSR_TO | \
+				 CHAFSR_BERR | CHAFSR_UCC | CHAFSR_UCU | \
+				 CHAFSR_CPC | CHAFSR_CPU | CHAFSR_WDC | \
+				 CHAFSR_WDU | CHAFSR_EDC | CHAFSR_EDU | \
+				 CHAFSR_UE | CHAFSR_CE | JPAFSR_RUE | \
+				 JPAFSR_RCE | JPAFSR_BP | JPAFSR_WBP | \
+				 JPAFSR_FRC | JPAFSR_FRU)
+
+/* Active JBUS request signal when error occurred */
+#define JPAFSR_JBREQ		(0x7UL << 24UL) /* jp */
+#define JPAFSR_JBREQ_SHIFT	24UL
+
+/* L2 cache way information */
+#define JPAFSR_ETW		(0x3UL << 22UL) /* jp */
+#define JPAFSR_ETW_SHIFT	22UL
+
+/* System bus MTAG ECC syndrome.  This field captures the status of the
+ * first occurrence of the highest-priority error according to the M_SYND
+ * overwrite policy.  After the AFSR sticky bit, corresponding to the error
+ * for which the M_SYND is reported, is cleared, the contents of the M_SYND
+ * field will be unchanged by will be unfrozen for further error capture.
+ */
+#define CHAFSR_M_SYNDROME	(0xfUL << 16UL) /* ch,ch+,jp */
+#define CHAFSR_M_SYNDROME_SHIFT	16UL
+
+/* Agenid Id of the foreign device causing the UE/CE errors */
+#define JPAFSR_AID		(0x1fUL << 9UL) /* jp */
+#define JPAFSR_AID_SHIFT	9UL
+
+/* System bus or E-cache data ECC syndrome.  This field captures the status
+ * of the first occurrence of the highest-priority error according to the
+ * E_SYND overwrite policy.  After the AFSR sticky bit, corresponding to the
+ * error for which the E_SYND is reported, is cleare, the contents of the E_SYND
+ * field will be unchanged but will be unfrozen for further error capture.
+ */
+#define CHAFSR_E_SYNDROME	(0x1ffUL << 0UL) /* ch,ch+,jp */
+#define CHAFSR_E_SYNDROME_SHIFT	0UL
+
+/* The AFSR must be explicitly cleared by software, it is not cleared automatically
+ * by a read.  Writes to bits <51:33> with bits set will clear the corresponding
+ * bits in the AFSR.  Bits associated with disrupting traps must be cleared before
+ * interrupts are re-enabled to prevent multiple traps for the same error.  I.e.
+ * PSTATE.IE and AFSR bits control delivery of disrupting traps.
+ *
+ * Since there is only one AFAR, when multiple events have been logged by the
+ * bits in the AFSR, at most one of these events will have its status captured
+ * in the AFAR.  The highest priority of those event bits will get AFAR logging.
+ * The AFAR will be unlocked and available to capture the address of another event
+ * as soon as the one bit in AFSR that corresponds to the event logged in AFAR is
+ * cleared.  For example, if AFSR.CE is detected, then AFSR.UE (which overwrites
+ * the AFAR), and AFSR.UE is cleared by not AFSR.CE, then the AFAR will be unlocked
+ * and ready for another event, even though AFSR.CE is still set.  The same rules
+ * also apply to the M_SYNDROME and E_SYNDROME fields of the AFSR.
+ */
+
+#endif /* _SPARC64_CHAFSR_H */
diff --git a/include/asm-sparc/checksum.h b/include/asm-sparc/checksum.h
index d044ddb..4e3553d 100644
--- a/include/asm-sparc/checksum.h
+++ b/include/asm-sparc/checksum.h
@@ -1,241 +1,8 @@
-#ifndef __SPARC_CHECKSUM_H
-#define __SPARC_CHECKSUM_H
-
-/*  checksum.h:  IP/UDP/TCP checksum routines on the Sparc.
- *
- *  Copyright(C) 1995 Linus Torvalds
- *  Copyright(C) 1995 Miguel de Icaza
- *  Copyright(C) 1996 David S. Miller
- *  Copyright(C) 1996 Eddie C. Dost
- *  Copyright(C) 1997 Jakub Jelinek
- *
- * derived from:
- *	Alpha checksum c-code
- *      ix86 inline assembly
- *      RFC1071 Computing the Internet Checksum
- */
- 
-#include <linux/in6.h>
-#include <asm/uaccess.h>
-
-/* computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-extern __wsum csum_partial(const void *buff, int len, __wsum sum);
-
-/* the same as csum_partial, but copies from fs:src while it
- * checksums
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-
-extern unsigned int __csum_partial_copy_sparc_generic (const unsigned char *, unsigned char *);
-
-static inline __wsum
-csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
-{
-	register unsigned int ret asm("o0") = (unsigned int)src;
-	register char *d asm("o1") = dst;
-	register int l asm("g1") = len;
-
-	__asm__ __volatile__ (
-		"call __csum_partial_copy_sparc_generic\n\t"
-		" mov %6, %%g7\n"
-	: "=&r" (ret), "=&r" (d), "=&r" (l)
-	: "0" (ret), "1" (d), "2" (l), "r" (sum)
-	: "o2", "o3", "o4", "o5", "o7",
-	  "g2", "g3", "g4", "g5", "g7",
-	  "memory", "cc");
-	return (__force __wsum)ret;
-}
-
-static inline __wsum
-csum_partial_copy_from_user(const void __user *src, void *dst, int len,
-			    __wsum sum, int *err)
-  {
-	register unsigned long ret asm("o0") = (unsigned long)src;
-	register char *d asm("o1") = dst;
-	register int l asm("g1") = len;
-	register __wsum s asm("g7") = sum;
-
-	__asm__ __volatile__ (
-	".section __ex_table,#alloc\n\t"
-	".align 4\n\t"
-	".word 1f,2\n\t"
-	".previous\n"
-	"1:\n\t"
-	"call __csum_partial_copy_sparc_generic\n\t"
-	" st %8, [%%sp + 64]\n"
-	: "=&r" (ret), "=&r" (d), "=&r" (l), "=&r" (s)
-	: "0" (ret), "1" (d), "2" (l), "3" (s), "r" (err)
-	: "o2", "o3", "o4", "o5", "o7", "g2", "g3", "g4", "g5",
-	  "cc", "memory");
-	return (__force __wsum)ret;
-}
-  
-static inline __wsum
-csum_partial_copy_to_user(const void *src, void __user *dst, int len,
-			  __wsum sum, int *err)
-{
-	if (!access_ok (VERIFY_WRITE, dst, len)) {
-		*err = -EFAULT;
-		return sum;
-	} else {
-		register unsigned long ret asm("o0") = (unsigned long)src;
-		register char __user *d asm("o1") = dst;
-		register int l asm("g1") = len;
-		register __wsum s asm("g7") = sum;
-
-		__asm__ __volatile__ (
-		".section __ex_table,#alloc\n\t"
-		".align 4\n\t"
-		".word 1f,1\n\t"
-		".previous\n"
-		"1:\n\t"
-		"call __csum_partial_copy_sparc_generic\n\t"
-		" st %8, [%%sp + 64]\n"
-		: "=&r" (ret), "=&r" (d), "=&r" (l), "=&r" (s)
-		: "0" (ret), "1" (d), "2" (l), "3" (s), "r" (err)
-		: "o2", "o3", "o4", "o5", "o7",
-		  "g2", "g3", "g4", "g5",
-		  "cc", "memory");
-		return (__force __wsum)ret;
-	}
-}
-
-#define HAVE_CSUM_COPY_USER
-#define csum_and_copy_to_user csum_partial_copy_to_user
-
-/* ihl is always 5 or greater, almost always is 5, and iph is word aligned
- * the majority of the time.
- */
-static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
-{
-	__sum16 sum;
-
-	/* Note: We must read %2 before we touch %0 for the first time,
-	 *       because GCC can legitimately use the same register for
-	 *       both operands.
-	 */
-	__asm__ __volatile__("sub\t%2, 4, %%g4\n\t"
-			     "ld\t[%1 + 0x00], %0\n\t"
-			     "ld\t[%1 + 0x04], %%g2\n\t"
-			     "ld\t[%1 + 0x08], %%g3\n\t"
-			     "addcc\t%%g2, %0, %0\n\t"
-			     "addxcc\t%%g3, %0, %0\n\t"
-			     "ld\t[%1 + 0x0c], %%g2\n\t"
-			     "ld\t[%1 + 0x10], %%g3\n\t"
-			     "addxcc\t%%g2, %0, %0\n\t"
-			     "addx\t%0, %%g0, %0\n"
-			     "1:\taddcc\t%%g3, %0, %0\n\t"
-			     "add\t%1, 4, %1\n\t"
-			     "addxcc\t%0, %%g0, %0\n\t"
-			     "subcc\t%%g4, 1, %%g4\n\t"
-			     "be,a\t2f\n\t"
-			     "sll\t%0, 16, %%g2\n\t"
-			     "b\t1b\n\t"
-			     "ld\t[%1 + 0x10], %%g3\n"
-			     "2:\taddcc\t%0, %%g2, %%g2\n\t"
-			     "srl\t%%g2, 16, %0\n\t"
-			     "addx\t%0, %%g0, %0\n\t"
-			     "xnor\t%%g0, %0, %0"
-			     : "=r" (sum), "=&r" (iph)
-			     : "r" (ihl), "1" (iph)
-			     : "g2", "g3", "g4", "cc", "memory");
-	return sum;
-}
-
-/* Fold a partial checksum without adding pseudo headers. */
-static inline __sum16 csum_fold(__wsum sum)
-{
-	unsigned int tmp;
-
-	__asm__ __volatile__("addcc\t%0, %1, %1\n\t"
-			     "srl\t%1, 16, %1\n\t"
-			     "addx\t%1, %%g0, %1\n\t"
-			     "xnor\t%%g0, %1, %0"
-			     : "=&r" (sum), "=r" (tmp)
-			     : "0" (sum), "1" ((__force u32)sum<<16)
-			     : "cc");
-	return (__force __sum16)sum;
-}
-
-static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
-					       unsigned short len,
-					       unsigned short proto,
-					       __wsum sum)
-{
-	__asm__ __volatile__("addcc\t%1, %0, %0\n\t"
-			     "addxcc\t%2, %0, %0\n\t"
-			     "addxcc\t%3, %0, %0\n\t"
-			     "addx\t%0, %%g0, %0\n\t"
-			     : "=r" (sum), "=r" (saddr)
-			     : "r" (daddr), "r" (proto + len), "0" (sum),
-			       "1" (saddr)
-			     : "cc");
-	return sum;
-}
-
-/*
- * computes the checksum of the TCP/UDP pseudo-header
- * returns a 16-bit checksum, already complemented
- */
-static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
-						   unsigned short len,
-						   unsigned short proto,
-						   __wsum sum)
-{
-	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
-}
-
-#define _HAVE_ARCH_IPV6_CSUM
-
-static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
-				      const struct in6_addr *daddr,
-				      __u32 len, unsigned short proto,
-				      __wsum sum)
-{
-	__asm__ __volatile__ (
-		"addcc	%3, %4, %%g4\n\t"
-		"addxcc	%5, %%g4, %%g4\n\t"
-		"ld	[%2 + 0x0c], %%g2\n\t"
-		"ld	[%2 + 0x08], %%g3\n\t"
-		"addxcc	%%g2, %%g4, %%g4\n\t"
-		"ld	[%2 + 0x04], %%g2\n\t"
-		"addxcc	%%g3, %%g4, %%g4\n\t"
-		"ld	[%2 + 0x00], %%g3\n\t"
-		"addxcc	%%g2, %%g4, %%g4\n\t"
-		"ld	[%1 + 0x0c], %%g2\n\t"
-		"addxcc	%%g3, %%g4, %%g4\n\t"
-		"ld	[%1 + 0x08], %%g3\n\t"
-		"addxcc	%%g2, %%g4, %%g4\n\t"
-		"ld	[%1 + 0x04], %%g2\n\t"
-		"addxcc	%%g3, %%g4, %%g4\n\t"
-		"ld	[%1 + 0x00], %%g3\n\t"
-		"addxcc	%%g2, %%g4, %%g4\n\t"
-		"addxcc	%%g3, %%g4, %0\n\t"
-		"addx	0, %0, %0\n"
-		: "=&r" (sum)
-		: "r" (saddr), "r" (daddr), 
-		  "r"(htonl(len)), "r"(htonl(proto)), "r"(sum)
-		: "g2", "g3", "g4", "cc");
-
-	return csum_fold(sum);
-}
-
-/* this routine is used for miscellaneous IP-like checksums, mainly in icmp.c */
-static inline __sum16 ip_compute_csum(const void *buff, int len)
-{
-	return csum_fold(csum_partial(buff, len, 0));
-}
-
-#endif /* !(__SPARC_CHECKSUM_H) */
+#ifndef ___ASM_SPARC_CHECKSUM_H
+#define ___ASM_SPARC_CHECKSUM_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/checksum_64.h>
+#else
+#include <asm-sparc/checksum_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/checksum_32.h b/include/asm-sparc/checksum_32.h
new file mode 100644
index 0000000..bdbda14
--- /dev/null
+++ b/include/asm-sparc/checksum_32.h
@@ -0,0 +1,241 @@
+#ifndef __SPARC_CHECKSUM_H
+#define __SPARC_CHECKSUM_H
+
+/*  checksum.h:  IP/UDP/TCP checksum routines on the Sparc.
+ *
+ *  Copyright(C) 1995 Linus Torvalds
+ *  Copyright(C) 1995 Miguel de Icaza
+ *  Copyright(C) 1996 David S. Miller
+ *  Copyright(C) 1996 Eddie C. Dost
+ *  Copyright(C) 1997 Jakub Jelinek
+ *
+ * derived from:
+ *	Alpha checksum c-code
+ *      ix86 inline assembly
+ *      RFC1071 Computing the Internet Checksum
+ */
+
+#include <linux/in6.h>
+#include <asm/uaccess.h>
+
+/* computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+extern __wsum csum_partial(const void *buff, int len, __wsum sum);
+
+/* the same as csum_partial, but copies from fs:src while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+
+extern unsigned int __csum_partial_copy_sparc_generic (const unsigned char *, unsigned char *);
+
+static inline __wsum
+csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
+{
+	register unsigned int ret asm("o0") = (unsigned int)src;
+	register char *d asm("o1") = dst;
+	register int l asm("g1") = len;
+
+	__asm__ __volatile__ (
+		"call __csum_partial_copy_sparc_generic\n\t"
+		" mov %6, %%g7\n"
+	: "=&r" (ret), "=&r" (d), "=&r" (l)
+	: "0" (ret), "1" (d), "2" (l), "r" (sum)
+	: "o2", "o3", "o4", "o5", "o7",
+	  "g2", "g3", "g4", "g5", "g7",
+	  "memory", "cc");
+	return (__force __wsum)ret;
+}
+
+static inline __wsum
+csum_partial_copy_from_user(const void __user *src, void *dst, int len,
+			    __wsum sum, int *err)
+  {
+	register unsigned long ret asm("o0") = (unsigned long)src;
+	register char *d asm("o1") = dst;
+	register int l asm("g1") = len;
+	register __wsum s asm("g7") = sum;
+
+	__asm__ __volatile__ (
+	".section __ex_table,#alloc\n\t"
+	".align 4\n\t"
+	".word 1f,2\n\t"
+	".previous\n"
+	"1:\n\t"
+	"call __csum_partial_copy_sparc_generic\n\t"
+	" st %8, [%%sp + 64]\n"
+	: "=&r" (ret), "=&r" (d), "=&r" (l), "=&r" (s)
+	: "0" (ret), "1" (d), "2" (l), "3" (s), "r" (err)
+	: "o2", "o3", "o4", "o5", "o7", "g2", "g3", "g4", "g5",
+	  "cc", "memory");
+	return (__force __wsum)ret;
+}
+
+static inline __wsum
+csum_partial_copy_to_user(const void *src, void __user *dst, int len,
+			  __wsum sum, int *err)
+{
+	if (!access_ok (VERIFY_WRITE, dst, len)) {
+		*err = -EFAULT;
+		return sum;
+	} else {
+		register unsigned long ret asm("o0") = (unsigned long)src;
+		register char __user *d asm("o1") = dst;
+		register int l asm("g1") = len;
+		register __wsum s asm("g7") = sum;
+
+		__asm__ __volatile__ (
+		".section __ex_table,#alloc\n\t"
+		".align 4\n\t"
+		".word 1f,1\n\t"
+		".previous\n"
+		"1:\n\t"
+		"call __csum_partial_copy_sparc_generic\n\t"
+		" st %8, [%%sp + 64]\n"
+		: "=&r" (ret), "=&r" (d), "=&r" (l), "=&r" (s)
+		: "0" (ret), "1" (d), "2" (l), "3" (s), "r" (err)
+		: "o2", "o3", "o4", "o5", "o7",
+		  "g2", "g3", "g4", "g5",
+		  "cc", "memory");
+		return (__force __wsum)ret;
+	}
+}
+
+#define HAVE_CSUM_COPY_USER
+#define csum_and_copy_to_user csum_partial_copy_to_user
+
+/* ihl is always 5 or greater, almost always is 5, and iph is word aligned
+ * the majority of the time.
+ */
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+{
+	__sum16 sum;
+
+	/* Note: We must read %2 before we touch %0 for the first time,
+	 *       because GCC can legitimately use the same register for
+	 *       both operands.
+	 */
+	__asm__ __volatile__("sub\t%2, 4, %%g4\n\t"
+			     "ld\t[%1 + 0x00], %0\n\t"
+			     "ld\t[%1 + 0x04], %%g2\n\t"
+			     "ld\t[%1 + 0x08], %%g3\n\t"
+			     "addcc\t%%g2, %0, %0\n\t"
+			     "addxcc\t%%g3, %0, %0\n\t"
+			     "ld\t[%1 + 0x0c], %%g2\n\t"
+			     "ld\t[%1 + 0x10], %%g3\n\t"
+			     "addxcc\t%%g2, %0, %0\n\t"
+			     "addx\t%0, %%g0, %0\n"
+			     "1:\taddcc\t%%g3, %0, %0\n\t"
+			     "add\t%1, 4, %1\n\t"
+			     "addxcc\t%0, %%g0, %0\n\t"
+			     "subcc\t%%g4, 1, %%g4\n\t"
+			     "be,a\t2f\n\t"
+			     "sll\t%0, 16, %%g2\n\t"
+			     "b\t1b\n\t"
+			     "ld\t[%1 + 0x10], %%g3\n"
+			     "2:\taddcc\t%0, %%g2, %%g2\n\t"
+			     "srl\t%%g2, 16, %0\n\t"
+			     "addx\t%0, %%g0, %0\n\t"
+			     "xnor\t%%g0, %0, %0"
+			     : "=r" (sum), "=&r" (iph)
+			     : "r" (ihl), "1" (iph)
+			     : "g2", "g3", "g4", "cc", "memory");
+	return sum;
+}
+
+/* Fold a partial checksum without adding pseudo headers. */
+static inline __sum16 csum_fold(__wsum sum)
+{
+	unsigned int tmp;
+
+	__asm__ __volatile__("addcc\t%0, %1, %1\n\t"
+			     "srl\t%1, 16, %1\n\t"
+			     "addx\t%1, %%g0, %1\n\t"
+			     "xnor\t%%g0, %1, %0"
+			     : "=&r" (sum), "=r" (tmp)
+			     : "0" (sum), "1" ((__force u32)sum<<16)
+			     : "cc");
+	return (__force __sum16)sum;
+}
+
+static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
+					       unsigned short len,
+					       unsigned short proto,
+					       __wsum sum)
+{
+	__asm__ __volatile__("addcc\t%1, %0, %0\n\t"
+			     "addxcc\t%2, %0, %0\n\t"
+			     "addxcc\t%3, %0, %0\n\t"
+			     "addx\t%0, %%g0, %0\n\t"
+			     : "=r" (sum), "=r" (saddr)
+			     : "r" (daddr), "r" (proto + len), "0" (sum),
+			       "1" (saddr)
+			     : "cc");
+	return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+						   unsigned short len,
+						   unsigned short proto,
+						   __wsum sum)
+{
+	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+
+static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+				      const struct in6_addr *daddr,
+				      __u32 len, unsigned short proto,
+				      __wsum sum)
+{
+	__asm__ __volatile__ (
+		"addcc	%3, %4, %%g4\n\t"
+		"addxcc	%5, %%g4, %%g4\n\t"
+		"ld	[%2 + 0x0c], %%g2\n\t"
+		"ld	[%2 + 0x08], %%g3\n\t"
+		"addxcc	%%g2, %%g4, %%g4\n\t"
+		"ld	[%2 + 0x04], %%g2\n\t"
+		"addxcc	%%g3, %%g4, %%g4\n\t"
+		"ld	[%2 + 0x00], %%g3\n\t"
+		"addxcc	%%g2, %%g4, %%g4\n\t"
+		"ld	[%1 + 0x0c], %%g2\n\t"
+		"addxcc	%%g3, %%g4, %%g4\n\t"
+		"ld	[%1 + 0x08], %%g3\n\t"
+		"addxcc	%%g2, %%g4, %%g4\n\t"
+		"ld	[%1 + 0x04], %%g2\n\t"
+		"addxcc	%%g3, %%g4, %%g4\n\t"
+		"ld	[%1 + 0x00], %%g3\n\t"
+		"addxcc	%%g2, %%g4, %%g4\n\t"
+		"addxcc	%%g3, %%g4, %0\n\t"
+		"addx	0, %0, %0\n"
+		: "=&r" (sum)
+		: "r" (saddr), "r" (daddr),
+		  "r"(htonl(len)), "r"(htonl(proto)), "r"(sum)
+		: "g2", "g3", "g4", "cc");
+
+	return csum_fold(sum);
+}
+
+/* this routine is used for miscellaneous IP-like checksums, mainly in icmp.c */
+static inline __sum16 ip_compute_csum(const void *buff, int len)
+{
+	return csum_fold(csum_partial(buff, len, 0));
+}
+
+#endif /* !(__SPARC_CHECKSUM_H) */
diff --git a/include/asm-sparc/checksum_64.h b/include/asm-sparc/checksum_64.h
new file mode 100644
index 0000000..019b961
--- /dev/null
+++ b/include/asm-sparc/checksum_64.h
@@ -0,0 +1,167 @@
+#ifndef __SPARC64_CHECKSUM_H
+#define __SPARC64_CHECKSUM_H
+
+/*  checksum.h:  IP/UDP/TCP checksum routines on the V9.
+ *
+ *  Copyright(C) 1995 Linus Torvalds
+ *  Copyright(C) 1995 Miguel de Icaza
+ *  Copyright(C) 1996 David S. Miller
+ *  Copyright(C) 1996 Eddie C. Dost
+ *  Copyright(C) 1997 Jakub Jelinek
+ *
+ * derived from:
+ *	Alpha checksum c-code
+ *      ix86 inline assembly
+ *      RFC1071 Computing the Internet Checksum
+ */
+
+#include <linux/in6.h>
+#include <asm/uaccess.h>
+
+/* computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+extern __wsum csum_partial(const void * buff, int len, __wsum sum);
+
+/* the same as csum_partial, but copies from user space while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+extern __wsum csum_partial_copy_nocheck(const void *src, void *dst,
+					      int len, __wsum sum);
+
+extern long __csum_partial_copy_from_user(const void __user *src,
+					  void *dst, int len,
+					  __wsum sum);
+
+static inline __wsum
+csum_partial_copy_from_user(const void __user *src,
+			    void *dst, int len,
+			    __wsum sum, int *err)
+{
+	long ret = __csum_partial_copy_from_user(src, dst, len, sum);
+	if (ret < 0)
+		*err = -EFAULT;
+	return (__force __wsum) ret;
+}
+
+/*
+ *	Copy and checksum to user
+ */
+#define HAVE_CSUM_COPY_USER
+extern long __csum_partial_copy_to_user(const void *src,
+					void __user *dst, int len,
+					  __wsum sum);
+
+static inline __wsum
+csum_and_copy_to_user(const void *src,
+		      void __user *dst, int len,
+		      __wsum sum, int *err)
+{
+	long ret = __csum_partial_copy_to_user(src, dst, len, sum);
+	if (ret < 0)
+		*err = -EFAULT;
+	return (__force __wsum) ret;
+}
+
+/* ihl is always 5 or greater, almost always is 5, and iph is word aligned
+ * the majority of the time.
+ */
+extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl);
+
+/* Fold a partial checksum without adding pseudo headers. */
+static inline __sum16 csum_fold(__wsum sum)
+{
+	unsigned int tmp;
+
+	__asm__ __volatile__(
+"	addcc		%0, %1, %1\n"
+"	srl		%1, 16, %1\n"
+"	addc		%1, %%g0, %1\n"
+"	xnor		%%g0, %1, %0\n"
+	: "=&r" (sum), "=r" (tmp)
+	: "0" (sum), "1" ((__force u32)sum<<16)
+	: "cc");
+	return (__force __sum16)sum;
+}
+
+static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
+					       unsigned int len,
+					       unsigned short proto,
+					       __wsum sum)
+{
+	__asm__ __volatile__(
+"	addcc		%1, %0, %0\n"
+"	addccc		%2, %0, %0\n"
+"	addccc		%3, %0, %0\n"
+"	addc		%0, %%g0, %0\n"
+	: "=r" (sum), "=r" (saddr)
+	: "r" (daddr), "r" (proto + len), "0" (sum), "1" (saddr)
+	: "cc");
+	return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+						   unsigned short len,
+						   unsigned short proto,
+						   __wsum sum)
+{
+	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+
+static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+				      const struct in6_addr *daddr,
+				      __u32 len, unsigned short proto,
+				      __wsum sum)
+{
+	__asm__ __volatile__ (
+"	addcc		%3, %4, %%g7\n"
+"	addccc		%5, %%g7, %%g7\n"
+"	lduw		[%2 + 0x0c], %%g2\n"
+"	lduw		[%2 + 0x08], %%g3\n"
+"	addccc		%%g2, %%g7, %%g7\n"
+"	lduw		[%2 + 0x04], %%g2\n"
+"	addccc		%%g3, %%g7, %%g7\n"
+"	lduw		[%2 + 0x00], %%g3\n"
+"	addccc		%%g2, %%g7, %%g7\n"
+"	lduw		[%1 + 0x0c], %%g2\n"
+"	addccc		%%g3, %%g7, %%g7\n"
+"	lduw		[%1 + 0x08], %%g3\n"
+"	addccc		%%g2, %%g7, %%g7\n"
+"	lduw		[%1 + 0x04], %%g2\n"
+"	addccc		%%g3, %%g7, %%g7\n"
+"	lduw		[%1 + 0x00], %%g3\n"
+"	addccc		%%g2, %%g7, %%g7\n"
+"	addccc		%%g3, %%g7, %0\n"
+"	addc		0, %0, %0\n"
+	: "=&r" (sum)
+	: "r" (saddr), "r" (daddr), "r"(htonl(len)),
+	  "r"(htonl(proto)), "r"(sum)
+	: "g2", "g3", "g7", "cc");
+
+	return csum_fold(sum);
+}
+
+/* this routine is used for miscellaneous IP-like checksums, mainly in icmp.c */
+static inline __sum16 ip_compute_csum(const void *buff, int len)
+{
+	return csum_fold(csum_partial(buff, len, 0));
+}
+
+#endif /* !(__SPARC64_CHECKSUM_H) */
diff --git a/include/asm-sparc/chmctrl.h b/include/asm-sparc/chmctrl.h
new file mode 100644
index 0000000..859b4a4
--- /dev/null
+++ b/include/asm-sparc/chmctrl.h
@@ -0,0 +1,183 @@
+#ifndef _SPARC64_CHMCTRL_H
+#define _SPARC64_CHMCTRL_H
+
+/* Cheetah memory controller programmable registers. */
+#define CHMCTRL_TCTRL1		0x00 /* Memory Timing Control I		*/
+#define CHMCTRL_TCTRL2		0x08 /* Memory Timing Control II	*/
+#define CHMCTRL_TCTRL3		0x38 /* Memory Timing Control III	*/
+#define CHMCTRL_TCTRL4		0x40 /* Memory Timing Control IV	*/
+#define CHMCTRL_DECODE1		0x10 /* Memory Address Decode I		*/
+#define CHMCTRL_DECODE2		0x18 /* Memory Address Decode II	*/
+#define CHMCTRL_DECODE3		0x20 /* Memory Address Decode III	*/
+#define CHMCTRL_DECODE4		0x28 /* Memory Address Decode IV	*/
+#define CHMCTRL_MACTRL		0x30 /* Memory Address Control		*/
+
+/* Memory Timing Control I */
+#define TCTRL1_SDRAMCTL_DLY	0xf000000000000000UL
+#define TCTRL1_SDRAMCTL_DLY_SHIFT     60
+#define TCTRL1_SDRAMCLK_DLY	0x0e00000000000000UL
+#define TCTRL1_SDRAMCLK_DLY_SHIFT     57
+#define TCTRL1_R		0x0100000000000000UL
+#define TCTRL1_R_SHIFT 		      56
+#define TCTRL1_AUTORFR_CYCLE	0x00fe000000000000UL
+#define TCTRL1_AUTORFR_CYCLE_SHIFT    49
+#define TCTRL1_RD_WAIT		0x0001f00000000000UL
+#define TCTRL1_RD_WAIT_SHIFT	      44
+#define TCTRL1_PC_CYCLE		0x00000fc000000000UL
+#define TCTRL1_PC_CYCLE_SHIFT	      38
+#define TCTRL1_WR_MORE_RAS_PW	0x0000003f00000000UL
+#define TCTRL1_WR_MORE_RAS_PW_SHIFT   32
+#define TCTRL1_RD_MORE_RAW_PW	0x00000000fc000000UL
+#define TCTRL1_RD_MORE_RAS_PW_SHIFT   26
+#define TCTRL1_ACT_WR_DLY	0x0000000003f00000UL
+#define TCTRL1_ACT_WR_DLY_SHIFT	      20
+#define TCTRL1_ACT_RD_DLY	0x00000000000fc000UL
+#define TCTRL1_ACT_RD_DLY_SHIFT	      14
+#define TCTRL1_BANK_PRESENT	0x0000000000003000UL
+#define TCTRL1_BANK_PRESENT_SHIFT     12
+#define TCTRL1_RFR_INT		0x0000000000000ff8UL
+#define TCTRL1_RFR_INT_SHIFT	      3
+#define TCTRL1_SET_MODE_REG	0x0000000000000004UL
+#define TCTRL1_SET_MODE_REG_SHIFT     2
+#define TCTRL1_RFR_ENABLE	0x0000000000000002UL
+#define TCTRL1_RFR_ENABLE_SHIFT	      1
+#define TCTRL1_PRECHG_ALL	0x0000000000000001UL
+#define TCTRL1_PRECHG_ALL_SHIFT	      0
+
+/* Memory Timing Control II */
+#define TCTRL2_WR_MSEL_DLY	0xfc00000000000000UL
+#define TCTRL2_WR_MSEL_DLY_SHIFT      58
+#define TCTRL2_RD_MSEL_DLY	0x03f0000000000000UL
+#define TCTRL2_RD_MSEL_DLY_SHIFT      52
+#define TCTRL2_WRDATA_THLD	0x000c000000000000UL
+#define TCTRL2_WRDATA_THLD_SHIFT      50
+#define TCTRL2_RDWR_RD_TI_DLY	0x0003f00000000000UL
+#define TCTRL2_RDWR_RD_TI_DLY_SHIFT   44
+#define TCTRL2_AUTOPRECHG_ENBL	0x0000080000000000UL
+#define TCTRL2_AUTOPRECHG_ENBL_SHIFT  43
+#define TCTRL2_RDWR_PI_MORE_DLY	0x000007c000000000UL
+#define TCTRL2_RDWR_PI_MORE_DLY_SHIFT 38
+#define TCTRL2_RDWR_1_DLY	0x0000003f00000000UL
+#define TCTRL2_RDWR_1_DLY_SHIFT       32
+#define TCTRL2_WRWR_PI_MORE_DLY	0x00000000f8000000UL
+#define TCTRL2_WRWR_PI_MORE_DLY_SHIFT 27
+#define TCTRL2_WRWR_1_DLY	0x0000000007e00000UL
+#define TCTRL2_WRWR_1_DLY_SHIFT       21
+#define TCTRL2_RDWR_RD_PI_MORE_DLY 0x00000000001f0000UL
+#define TCTRL2_RDWR_RD_PI_MORE_DLY_SHIFT 16
+#define TCTRL2_R		0x0000000000008000UL
+#define TCTRL2_R_SHIFT		      15
+#define TCTRL2_SDRAM_MODE_REG_DATA 0x0000000000007fffUL
+#define TCTRL2_SDRAM_MODE_REG_DATA_SHIFT 0
+
+/* Memory Timing Control III */
+#define TCTRL3_SDRAM_CTL_DLY	0xf000000000000000UL
+#define TCTRL3_SDRAM_CTL_DLY_SHIFT    60
+#define TCTRL3_SDRAM_CLK_DLY	0x0e00000000000000UL
+#define TCTRL3_SDRAM_CLK_DLY_SHIFT    57
+#define TCTRL3_R		0x0100000000000000UL
+#define TCTRL3_R_SHIFT		      56
+#define TCTRL3_AUTO_RFR_CYCLE	0x00fe000000000000UL
+#define TCTRL3_AUTO_RFR_CYCLE_SHIFT   49
+#define TCTRL3_RD_WAIT		0x0001f00000000000UL
+#define TCTRL3_RD_WAIT_SHIFT	      44
+#define TCTRL3_PC_CYCLE		0x00000fc000000000UL
+#define TCTRL3_PC_CYCLE_SHIFT	      38
+#define TCTRL3_WR_MORE_RAW_PW	0x0000003f00000000UL
+#define TCTRL3_WR_MORE_RAW_PW_SHIFT   32
+#define TCTRL3_RD_MORE_RAW_PW	0x00000000fc000000UL
+#define TCTRL3_RD_MORE_RAW_PW_SHIFT   26
+#define TCTRL3_ACT_WR_DLY	0x0000000003f00000UL
+#define TCTRL3_ACT_WR_DLY_SHIFT       20
+#define TCTRL3_ACT_RD_DLY	0x00000000000fc000UL
+#define TCTRL3_ACT_RD_DLY_SHIFT       14
+#define TCTRL3_BANK_PRESENT	0x0000000000003000UL
+#define TCTRL3_BANK_PRESENT_SHIFT     12
+#define TCTRL3_RFR_INT		0x0000000000000ff8UL
+#define TCTRL3_RFR_INT_SHIFT	      3
+#define TCTRL3_SET_MODE_REG	0x0000000000000004UL
+#define TCTRL3_SET_MODE_REG_SHIFT     2
+#define TCTRL3_RFR_ENABLE	0x0000000000000002UL
+#define TCTRL3_RFR_ENABLE_SHIFT       1
+#define TCTRL3_PRECHG_ALL	0x0000000000000001UL
+#define TCTRL3_PRECHG_ALL_SHIFT	      0
+
+/* Memory Timing Control IV */
+#define TCTRL4_WR_MSEL_DLY	0xfc00000000000000UL
+#define TCTRL4_WR_MSEL_DLY_SHIFT      58
+#define TCTRL4_RD_MSEL_DLY	0x03f0000000000000UL
+#define TCTRL4_RD_MSEL_DLY_SHIFT      52
+#define TCTRL4_WRDATA_THLD	0x000c000000000000UL
+#define TCTRL4_WRDATA_THLD_SHIFT      50
+#define TCTRL4_RDWR_RD_RI_DLY	0x0003f00000000000UL
+#define TCTRL4_RDWR_RD_RI_DLY_SHIFT   44
+#define TCTRL4_AUTO_PRECHG_ENBL	0x0000080000000000UL
+#define TCTRL4_AUTO_PRECHG_ENBL_SHIFT 43
+#define TCTRL4_RD_WR_PI_MORE_DLY 0x000007c000000000UL
+#define TCTRL4_RD_WR_PI_MORE_DLY_SHIFT 38
+#define TCTRL4_RD_WR_TI_DLY	0x0000003f00000000UL
+#define TCTRL4_RD_WR_TI_DLY_SHIFT     32
+#define TCTRL4_WR_WR_PI_MORE_DLY 0x00000000f8000000UL
+#define TCTRL4_WR_WR_PI_MORE_DLY_SHIFT 27
+#define TCTRL4_WR_WR_TI_DLY	0x0000000007e00000UL
+#define TCTRL4_WR_WR_TI_DLY_SHIFT     21
+#define TCTRL4_RDWR_RD_PI_MORE_DLY 0x00000000001f000UL0
+#define TCTRL4_RDWR_RD_PI_MORE_DLY_SHIFT 16
+#define TCTRL4_R		0x0000000000008000UL
+#define TCTRL4_R_SHIFT		      15
+#define TCTRL4_SDRAM_MODE_REG_DATA 0x0000000000007fffUL
+#define TCTRL4_SDRAM_MODE_REG_DATA_SHIFT 0
+
+/* All 4 memory address decoding registers have the
+ * same layout.
+ */
+#define MEM_DECODE_VALID	0x8000000000000000UL /* Valid */
+#define MEM_DECODE_VALID_SHIFT	      63
+#define MEM_DECODE_UK		0x001ffe0000000000UL /* Upper mask */
+#define MEM_DECODE_UK_SHIFT	      41
+#define MEM_DECODE_UM		0x0000001ffff00000UL /* Upper match */
+#define MEM_DECODE_UM_SHIFT	      20
+#define MEM_DECODE_LK		0x000000000003c000UL /* Lower mask */
+#define MEM_DECODE_LK_SHIFT	      14
+#define MEM_DECODE_LM		0x0000000000000f00UL /* Lower match */
+#define MEM_DECODE_LM_SHIFT           8
+
+#define PA_UPPER_BITS		0x000007fffc000000UL
+#define PA_UPPER_BITS_SHIFT	26
+#define PA_LOWER_BITS		0x00000000000003c0UL
+#define PA_LOWER_BITS_SHIFT	6
+
+#define MACTRL_R0		         0x8000000000000000UL
+#define MACTRL_R0_SHIFT		         63
+#define MACTRL_ADDR_LE_PW                0x7000000000000000UL
+#define MACTRL_ADDR_LE_PW_SHIFT		 60
+#define MACTRL_CMD_PW                    0x0f00000000000000UL
+#define MACTRL_CMD_PW_SHIFT		 56
+#define MACTRL_HALF_MODE_WR_MSEL_DLY     0x00fc000000000000UL
+#define MACTRL_HALF_MODE_WR_MSEL_DLY_SHIFT 50
+#define MACTRL_HALF_MODE_RD_MSEL_DLY     0x0003f00000000000UL
+#define MACTRL_HALF_MODE_RD_MSEL_DLY_SHIFT 44
+#define MACTRL_HALF_MODE_SDRAM_CTL_DLY   0x00000f0000000000UL
+#define MACTRL_HALF_MODE_SDRAM_CTL_DLY_SHIFT 40
+#define MACTRL_HALF_MODE_SDRAM_CLK_DLY   0x000000e000000000UL
+#define MACTRL_HALF_MODE_SDRAM_CLK_DLY_SHIFT 37
+#define MACTRL_R1                        0x0000001000000000UL
+#define MACTRL_R1_SHIFT                      36
+#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B3 0x0000000f00000000UL
+#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B3_SHIFT 32
+#define MACTRL_ENC_INTLV_B3              0x00000000f8000000UL
+#define MACTRL_ENC_INTLV_B3_SHIFT              27
+#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B2 0x0000000007800000UL
+#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B2_SHIFT 23
+#define MACTRL_ENC_INTLV_B2              0x00000000007c0000UL
+#define MACTRL_ENC_INTLV_B2_SHIFT              18
+#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B1 0x000000000003c000UL
+#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B1_SHIFT 14
+#define MACTRL_ENC_INTLV_B1              0x0000000000003e00UL
+#define MACTRL_ENC_INTLV_B1_SHIFT               9
+#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B0 0x00000000000001e0UL
+#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B0_SHIFT  5
+#define MACTRL_ENC_INTLV_B0              0x000000000000001fUL
+#define MACTRL_ENC_INTLV_B0_SHIFT               0
+
+#endif /* _SPARC64_CHMCTRL_H */
diff --git a/include/asm-sparc/cmt.h b/include/asm-sparc/cmt.h
new file mode 100644
index 0000000..870db59
--- /dev/null
+++ b/include/asm-sparc/cmt.h
@@ -0,0 +1,59 @@
+#ifndef _SPARC64_CMT_H
+#define _SPARC64_CMT_H
+
+/* cmt.h: Chip Multi-Threading register definitions
+ *
+ * Copyright (C) 2004 David S. Miller (davem@redhat.com)
+ */
+
+/* ASI_CORE_ID - private */
+#define LP_ID		0x0000000000000010UL
+#define  LP_ID_MAX	0x00000000003f0000UL
+#define  LP_ID_ID	0x000000000000003fUL
+
+/* ASI_INTR_ID - private */
+#define LP_INTR_ID	0x0000000000000000UL
+#define  LP_INTR_ID_ID	0x00000000000003ffUL
+
+/* ASI_CESR_ID - private */
+#define CESR_ID		0x0000000000000040UL
+#define  CESR_ID_ID	0x00000000000000ffUL
+
+/* ASI_CORE_AVAILABLE - shared */
+#define LP_AVAIL	0x0000000000000000UL
+#define  LP_AVAIL_1	0x0000000000000002UL
+#define  LP_AVAIL_0	0x0000000000000001UL
+
+/* ASI_CORE_ENABLE_STATUS - shared */
+#define LP_ENAB_STAT	0x0000000000000010UL
+#define  LP_ENAB_STAT_1	0x0000000000000002UL
+#define  LP_ENAB_STAT_0	0x0000000000000001UL
+
+/* ASI_CORE_ENABLE - shared */
+#define LP_ENAB		0x0000000000000020UL
+#define  LP_ENAB_1	0x0000000000000002UL
+#define  LP_ENAB_0	0x0000000000000001UL
+
+/* ASI_CORE_RUNNING - shared */
+#define LP_RUNNING_RW	0x0000000000000050UL
+#define LP_RUNNING_W1S	0x0000000000000060UL
+#define LP_RUNNING_W1C	0x0000000000000068UL
+#define  LP_RUNNING_1	0x0000000000000002UL
+#define  LP_RUNNING_0	0x0000000000000001UL
+
+/* ASI_CORE_RUNNING_STAT - shared */
+#define LP_RUN_STAT	0x0000000000000058UL
+#define  LP_RUN_STAT_1	0x0000000000000002UL
+#define  LP_RUN_STAT_0	0x0000000000000001UL
+
+/* ASI_XIR_STEERING - shared */
+#define LP_XIR_STEER	0x0000000000000030UL
+#define  LP_XIR_STEER_1	0x0000000000000002UL
+#define  LP_XIR_STEER_0	0x0000000000000001UL
+
+/* ASI_CMT_ERROR_STEERING - shared */
+#define CMT_ER_STEER	0x0000000000000040UL
+#define  CMT_ER_STEER_1	0x0000000000000002UL
+#define  CMT_ER_STEER_0	0x0000000000000001UL
+
+#endif /* _SPARC64_CMT_H */
diff --git a/include/asm-sparc/compat.h b/include/asm-sparc/compat.h
new file mode 100644
index 0000000..f260b58
--- /dev/null
+++ b/include/asm-sparc/compat.h
@@ -0,0 +1,243 @@
+#ifndef _ASM_SPARC64_COMPAT_H
+#define _ASM_SPARC64_COMPAT_H
+/*
+ * Architecture specific compatibility types
+ */
+#include <linux/types.h>
+
+#define COMPAT_USER_HZ	100
+
+typedef u32		compat_size_t;
+typedef s32		compat_ssize_t;
+typedef s32		compat_time_t;
+typedef s32		compat_clock_t;
+typedef s32		compat_pid_t;
+typedef u16		__compat_uid_t;
+typedef u16		__compat_gid_t;
+typedef u32		__compat_uid32_t;
+typedef u32		__compat_gid32_t;
+typedef u16		compat_mode_t;
+typedef u32		compat_ino_t;
+typedef u16		compat_dev_t;
+typedef s32		compat_off_t;
+typedef s64		compat_loff_t;
+typedef s16		compat_nlink_t;
+typedef u16		compat_ipc_pid_t;
+typedef s32		compat_daddr_t;
+typedef u32		compat_caddr_t;
+typedef __kernel_fsid_t	compat_fsid_t;
+typedef s32		compat_key_t;
+typedef s32		compat_timer_t;
+
+typedef s32		compat_int_t;
+typedef s32		compat_long_t;
+typedef s64		compat_s64;
+typedef u32		compat_uint_t;
+typedef u32		compat_ulong_t;
+typedef u64		compat_u64;
+
+struct compat_timespec {
+	compat_time_t	tv_sec;
+	s32		tv_nsec;
+};
+
+struct compat_timeval {
+	compat_time_t	tv_sec;
+	s32		tv_usec;
+};
+
+struct compat_stat {
+	compat_dev_t	st_dev;
+	compat_ino_t	st_ino;
+	compat_mode_t	st_mode;
+	compat_nlink_t	st_nlink;
+	__compat_uid_t	st_uid;
+	__compat_gid_t	st_gid;
+	compat_dev_t	st_rdev;
+	compat_off_t	st_size;
+	compat_time_t	st_atime;
+	compat_ulong_t	st_atime_nsec;
+	compat_time_t	st_mtime;
+	compat_ulong_t	st_mtime_nsec;
+	compat_time_t	st_ctime;
+	compat_ulong_t	st_ctime_nsec;
+	compat_off_t	st_blksize;
+	compat_off_t	st_blocks;
+	u32		__unused4[2];
+};
+
+struct compat_stat64 {
+	unsigned long long	st_dev;
+
+	unsigned long long	st_ino;
+
+	unsigned int	st_mode;
+	unsigned int	st_nlink;
+
+	unsigned int	st_uid;
+	unsigned int	st_gid;
+
+	unsigned long long	st_rdev;
+
+	unsigned char	__pad3[8];
+
+	long long	st_size;
+	unsigned int	st_blksize;
+
+	unsigned char	__pad4[8];
+	unsigned int	st_blocks;
+
+	unsigned int	st_atime;
+	unsigned int	st_atime_nsec;
+
+	unsigned int	st_mtime;
+	unsigned int	st_mtime_nsec;
+
+	unsigned int	st_ctime;
+	unsigned int	st_ctime_nsec;
+
+	unsigned int	__unused4;
+	unsigned int	__unused5;
+};
+
+struct compat_flock {
+	short		l_type;
+	short		l_whence;
+	compat_off_t	l_start;
+	compat_off_t	l_len;
+	compat_pid_t	l_pid;
+	short		__unused;
+};
+
+#define F_GETLK64	12
+#define F_SETLK64	13
+#define F_SETLKW64	14
+
+struct compat_flock64 {
+	short		l_type;
+	short		l_whence;
+	compat_loff_t	l_start;
+	compat_loff_t	l_len;
+	compat_pid_t	l_pid;
+	short		__unused;
+};
+
+struct compat_statfs {
+	int		f_type;
+	int		f_bsize;
+	int		f_blocks;
+	int		f_bfree;
+	int		f_bavail;
+	int		f_files;
+	int		f_ffree;
+	compat_fsid_t	f_fsid;
+	int		f_namelen;	/* SunOS ignores this field. */
+	int		f_frsize;
+	int		f_spare[5];
+};
+
+#define COMPAT_RLIM_INFINITY 0x7fffffff
+
+typedef u32		compat_old_sigset_t;
+
+#define _COMPAT_NSIG		64
+#define _COMPAT_NSIG_BPW	32
+
+typedef u32		compat_sigset_word;
+
+#define COMPAT_OFF_T_MAX	0x7fffffff
+#define COMPAT_LOFF_T_MAX	0x7fffffffffffffffL
+
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately converted them already.
+ */
+typedef	u32		compat_uptr_t;
+
+static inline void __user *compat_ptr(compat_uptr_t uptr)
+{
+	return (void __user *)(unsigned long)uptr;
+}
+
+static inline compat_uptr_t ptr_to_compat(void __user *uptr)
+{
+	return (u32)(unsigned long)uptr;
+}
+
+static inline void __user *compat_alloc_user_space(long len)
+{
+	struct pt_regs *regs = current_thread_info()->kregs;
+	unsigned long usp = regs->u_regs[UREG_I6];
+
+	if (!(test_thread_flag(TIF_32BIT)))
+		usp += STACK_BIAS;
+	else
+		usp &= 0xffffffffUL;
+
+	usp -= len;
+	usp &= ~0x7UL;
+
+	return (void __user *) usp;
+}
+
+struct compat_ipc64_perm {
+	compat_key_t key;
+	__compat_uid32_t uid;
+	__compat_gid32_t gid;
+	__compat_uid32_t cuid;
+	__compat_gid32_t cgid;
+	unsigned short __pad1;
+	compat_mode_t mode;
+	unsigned short __pad2;
+	unsigned short seq;
+	unsigned long __unused1;	/* yes they really are 64bit pads */
+	unsigned long __unused2;
+};
+
+struct compat_semid64_ds {
+	struct compat_ipc64_perm sem_perm;
+	unsigned int	__pad1;
+	compat_time_t	sem_otime;
+	unsigned int	__pad2;
+	compat_time_t	sem_ctime;
+	u32		sem_nsems;
+	u32		__unused1;
+	u32		__unused2;
+};
+
+struct compat_msqid64_ds {
+	struct compat_ipc64_perm msg_perm;
+	unsigned int	__pad1;
+	compat_time_t	msg_stime;
+	unsigned int	__pad2;
+	compat_time_t	msg_rtime;
+	unsigned int	__pad3;
+	compat_time_t	msg_ctime;
+	unsigned int	msg_cbytes;
+	unsigned int	msg_qnum;
+	unsigned int	msg_qbytes;
+	compat_pid_t	msg_lspid;
+	compat_pid_t	msg_lrpid;
+	unsigned int	__unused1;
+	unsigned int	__unused2;
+};
+
+struct compat_shmid64_ds {
+	struct compat_ipc64_perm shm_perm;
+	unsigned int	__pad1;
+	compat_time_t	shm_atime;
+	unsigned int	__pad2;
+	compat_time_t	shm_dtime;
+	unsigned int	__pad3;
+	compat_time_t	shm_ctime;
+	compat_size_t	shm_segsz;
+	compat_pid_t	shm_cpid;
+	compat_pid_t	shm_lpid;
+	unsigned int	shm_nattch;
+	unsigned int	__unused1;
+	unsigned int	__unused2;
+};
+
+#endif /* _ASM_SPARC64_COMPAT_H */
diff --git a/include/asm-sparc/compat_signal.h b/include/asm-sparc/compat_signal.h
new file mode 100644
index 0000000..b759eab
--- /dev/null
+++ b/include/asm-sparc/compat_signal.h
@@ -0,0 +1,29 @@
+#ifndef _COMPAT_SIGNAL_H
+#define _COMPAT_SIGNAL_H
+
+#include <linux/compat.h>
+#include <asm/signal.h>
+
+#ifdef CONFIG_COMPAT
+struct __new_sigaction32 {
+	unsigned		sa_handler;
+	unsigned int    	sa_flags;
+	unsigned		sa_restorer;     /* not used by Linux/SPARC yet */
+	compat_sigset_t 	sa_mask;
+};
+
+struct __old_sigaction32 {
+	unsigned		sa_handler;
+	compat_old_sigset_t  	sa_mask;
+	unsigned int    	sa_flags;
+	unsigned		sa_restorer;     /* not used by Linux/SPARC yet */
+};
+
+typedef struct sigaltstack32 {
+	u32			ss_sp;
+	int			ss_flags;
+	compat_size_t		ss_size;
+} stack_t32;
+#endif
+
+#endif /* !(_COMPAT_SIGNAL_H) */
diff --git a/include/asm-sparc/cpudata.h b/include/asm-sparc/cpudata.h
index a2c4d51..b76fac0 100644
--- a/include/asm-sparc/cpudata.h
+++ b/include/asm-sparc/cpudata.h
@@ -1,27 +1,8 @@
-/* cpudata.h: Per-cpu parameters.
- *
- * Copyright (C) 2004 Keith M Wesolowski (wesolows@foobazco.org)
- *
- * Based on include/asm-sparc64/cpudata.h and Linux 2.4 smp.h
- * both (C) David S. Miller.
- */
-
-#ifndef _SPARC_CPUDATA_H
-#define _SPARC_CPUDATA_H
-
-#include <linux/percpu.h>
-
-typedef struct {
-	unsigned long udelay_val;
-	unsigned long clock_tick;
-	unsigned int multiplier;
-	unsigned int counter;
-	int prom_node;
-	int mid;
-	int next;
-} cpuinfo_sparc;
-
-DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data);
-#define cpu_data(__cpu) per_cpu(__cpu_data, (__cpu))
-
-#endif /* _SPARC_CPUDATA_H */
+#ifndef ___ASM_SPARC_CPUDATA_H
+#define ___ASM_SPARC_CPUDATA_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/cpudata_64.h>
+#else
+#include <asm-sparc/cpudata_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/cpudata_32.h b/include/asm-sparc/cpudata_32.h
new file mode 100644
index 0000000..a2c4d51
--- /dev/null
+++ b/include/asm-sparc/cpudata_32.h
@@ -0,0 +1,27 @@
+/* cpudata.h: Per-cpu parameters.
+ *
+ * Copyright (C) 2004 Keith M Wesolowski (wesolows@foobazco.org)
+ *
+ * Based on include/asm-sparc64/cpudata.h and Linux 2.4 smp.h
+ * both (C) David S. Miller.
+ */
+
+#ifndef _SPARC_CPUDATA_H
+#define _SPARC_CPUDATA_H
+
+#include <linux/percpu.h>
+
+typedef struct {
+	unsigned long udelay_val;
+	unsigned long clock_tick;
+	unsigned int multiplier;
+	unsigned int counter;
+	int prom_node;
+	int mid;
+	int next;
+} cpuinfo_sparc;
+
+DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data);
+#define cpu_data(__cpu) per_cpu(__cpu_data, (__cpu))
+
+#endif /* _SPARC_CPUDATA_H */
diff --git a/include/asm-sparc/cpudata_64.h b/include/asm-sparc/cpudata_64.h
new file mode 100644
index 0000000..532975e
--- /dev/null
+++ b/include/asm-sparc/cpudata_64.h
@@ -0,0 +1,240 @@
+/* cpudata.h: Per-cpu parameters.
+ *
+ * Copyright (C) 2003, 2005, 2006 David S. Miller (davem@davemloft.net)
+ */
+
+#ifndef _SPARC64_CPUDATA_H
+#define _SPARC64_CPUDATA_H
+
+#include <asm/hypervisor.h>
+#include <asm/asi.h>
+
+#ifndef __ASSEMBLY__
+
+#include <linux/percpu.h>
+#include <linux/threads.h>
+
+typedef struct {
+	/* Dcache line 1 */
+	unsigned int	__softirq_pending; /* must be 1st, see rtrap.S */
+	unsigned int	__pad0;
+	unsigned long	clock_tick;	/* %tick's per second */
+	unsigned long	__pad;
+	unsigned int	__pad1;
+	unsigned int	__pad2;
+
+	/* Dcache line 2, rarely used */
+	unsigned int	dcache_size;
+	unsigned int	dcache_line_size;
+	unsigned int	icache_size;
+	unsigned int	icache_line_size;
+	unsigned int	ecache_size;
+	unsigned int	ecache_line_size;
+	int		core_id;
+	int		proc_id;
+} cpuinfo_sparc;
+
+DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data);
+#define cpu_data(__cpu)		per_cpu(__cpu_data, (__cpu))
+#define local_cpu_data()	__get_cpu_var(__cpu_data)
+
+/* Trap handling code needs to get at a few critical values upon
+ * trap entry and to process TSB misses.  These cannot be in the
+ * per_cpu() area as we really need to lock them into the TLB and
+ * thus make them part of the main kernel image.  As a result we
+ * try to make this as small as possible.
+ *
+ * This is padded out and aligned to 64-bytes to avoid false sharing
+ * on SMP.
+ */
+
+/* If you modify the size of this structure, please update
+ * TRAP_BLOCK_SZ_SHIFT below.
+ */
+struct thread_info;
+struct trap_per_cpu {
+/* D-cache line 1: Basic thread information, cpu and device mondo queues */
+	struct thread_info	*thread;
+	unsigned long		pgd_paddr;
+	unsigned long		cpu_mondo_pa;
+	unsigned long		dev_mondo_pa;
+
+/* D-cache line 2: Error Mondo Queue and kernel buffer pointers */
+	unsigned long		resum_mondo_pa;
+	unsigned long		resum_kernel_buf_pa;
+	unsigned long		nonresum_mondo_pa;
+	unsigned long		nonresum_kernel_buf_pa;
+
+/* Dcache lines 3, 4, 5, and 6: Hypervisor Fault Status */
+	struct hv_fault_status	fault_info;
+
+/* Dcache line 7: Physical addresses of CPU send mondo block and CPU list.  */
+	unsigned long		cpu_mondo_block_pa;
+	unsigned long		cpu_list_pa;
+	unsigned long		tsb_huge;
+	unsigned long		tsb_huge_temp;
+
+/* Dcache line 8: IRQ work list, and keep trap_block a power-of-2 in size.  */
+	unsigned long		irq_worklist_pa;
+	unsigned int		cpu_mondo_qmask;
+	unsigned int		dev_mondo_qmask;
+	unsigned int		resum_qmask;
+	unsigned int		nonresum_qmask;
+	void			*hdesc;
+} __attribute__((aligned(64)));
+extern struct trap_per_cpu trap_block[NR_CPUS];
+extern void init_cur_cpu_trap(struct thread_info *);
+extern void setup_tba(void);
+extern int ncpus_probed;
+extern void __init cpu_probe(void);
+extern const struct seq_operations cpuinfo_op;
+
+extern unsigned long real_hard_smp_processor_id(void);
+
+struct cpuid_patch_entry {
+	unsigned int	addr;
+	unsigned int	cheetah_safari[4];
+	unsigned int	cheetah_jbus[4];
+	unsigned int	starfire[4];
+	unsigned int	sun4v[4];
+};
+extern struct cpuid_patch_entry __cpuid_patch, __cpuid_patch_end;
+
+struct sun4v_1insn_patch_entry {
+	unsigned int	addr;
+	unsigned int	insn;
+};
+extern struct sun4v_1insn_patch_entry __sun4v_1insn_patch,
+	__sun4v_1insn_patch_end;
+
+struct sun4v_2insn_patch_entry {
+	unsigned int	addr;
+	unsigned int	insns[2];
+};
+extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch,
+	__sun4v_2insn_patch_end;
+
+#endif /* !(__ASSEMBLY__) */
+
+#define TRAP_PER_CPU_THREAD		0x00
+#define TRAP_PER_CPU_PGD_PADDR		0x08
+#define TRAP_PER_CPU_CPU_MONDO_PA	0x10
+#define TRAP_PER_CPU_DEV_MONDO_PA	0x18
+#define TRAP_PER_CPU_RESUM_MONDO_PA	0x20
+#define TRAP_PER_CPU_RESUM_KBUF_PA	0x28
+#define TRAP_PER_CPU_NONRESUM_MONDO_PA	0x30
+#define TRAP_PER_CPU_NONRESUM_KBUF_PA	0x38
+#define TRAP_PER_CPU_FAULT_INFO		0x40
+#define TRAP_PER_CPU_CPU_MONDO_BLOCK_PA	0xc0
+#define TRAP_PER_CPU_CPU_LIST_PA	0xc8
+#define TRAP_PER_CPU_TSB_HUGE		0xd0
+#define TRAP_PER_CPU_TSB_HUGE_TEMP	0xd8
+#define TRAP_PER_CPU_IRQ_WORKLIST_PA	0xe0
+#define TRAP_PER_CPU_CPU_MONDO_QMASK	0xe8
+#define TRAP_PER_CPU_DEV_MONDO_QMASK	0xec
+#define TRAP_PER_CPU_RESUM_QMASK	0xf0
+#define TRAP_PER_CPU_NONRESUM_QMASK	0xf4
+
+#define TRAP_BLOCK_SZ_SHIFT		8
+
+#include <asm/scratchpad.h>
+
+#define __GET_CPUID(REG)				\
+	/* Spitfire implementation (default). */	\
+661:	ldxa		[%g0] ASI_UPA_CONFIG, REG;	\
+	srlx		REG, 17, REG;			\
+	 and		REG, 0x1f, REG;			\
+	nop;						\
+	.section	.cpuid_patch, "ax";		\
+	/* Instruction location. */			\
+	.word		661b;				\
+	/* Cheetah Safari implementation. */		\
+	ldxa		[%g0] ASI_SAFARI_CONFIG, REG;	\
+	srlx		REG, 17, REG;			\
+	and		REG, 0x3ff, REG;		\
+	nop;						\
+	/* Cheetah JBUS implementation. */		\
+	ldxa		[%g0] ASI_JBUS_CONFIG, REG;	\
+	srlx		REG, 17, REG;			\
+	and		REG, 0x1f, REG;			\
+	nop;						\
+	/* Starfire implementation. */			\
+	sethi		%hi(0x1fff40000d0 >> 9), REG;	\
+	sllx		REG, 9, REG;			\
+	or		REG, 0xd0, REG;			\
+	lduwa		[REG] ASI_PHYS_BYPASS_EC_E, REG;\
+	/* sun4v implementation. */			\
+	mov		SCRATCHPAD_CPUID, REG;		\
+	ldxa		[REG] ASI_SCRATCHPAD, REG;	\
+	nop;						\
+	nop;						\
+	.previous;
+
+#ifdef CONFIG_SMP
+
+#define TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
+	__GET_CPUID(TMP)			\
+	sethi	%hi(trap_block), DEST;		\
+	sllx	TMP, TRAP_BLOCK_SZ_SHIFT, TMP;	\
+	or	DEST, %lo(trap_block), DEST;	\
+	add	DEST, TMP, DEST;		\
+
+/* Clobbers TMP, current address space PGD phys address into DEST.  */
+#define TRAP_LOAD_PGD_PHYS(DEST, TMP)		\
+	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
+	ldx	[DEST + TRAP_PER_CPU_PGD_PADDR], DEST;
+
+/* Clobbers TMP, loads local processor's IRQ work area into DEST.  */
+#define TRAP_LOAD_IRQ_WORK_PA(DEST, TMP)	\
+	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
+	add	DEST, TRAP_PER_CPU_IRQ_WORKLIST_PA, DEST;
+
+/* Clobbers TMP, loads DEST with current thread info pointer.  */
+#define TRAP_LOAD_THREAD_REG(DEST, TMP)		\
+	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
+	ldx	[DEST + TRAP_PER_CPU_THREAD], DEST;
+
+/* Given the current thread info pointer in THR, load the per-cpu
+ * area base of the current processor into DEST.  REG1, REG2, and REG3 are
+ * clobbered.
+ *
+ * You absolutely cannot use DEST as a temporary in this code.  The
+ * reason is that traps can happen during execution, and return from
+ * trap will load the fully resolved DEST per-cpu base.  This can corrupt
+ * the calculations done by the macro mid-stream.
+ */
+#define LOAD_PER_CPU_BASE(DEST, THR, REG1, REG2, REG3)	\
+	lduh	[THR + TI_CPU], REG1;			\
+	sethi	%hi(__per_cpu_shift), REG3;		\
+	sethi	%hi(__per_cpu_base), REG2;		\
+	ldx	[REG3 + %lo(__per_cpu_shift)], REG3;	\
+	ldx	[REG2 + %lo(__per_cpu_base)], REG2;	\
+	sllx	REG1, REG3, REG3;			\
+	add	REG3, REG2, DEST;
+
+#else
+
+#define TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
+	sethi	%hi(trap_block), DEST;		\
+	or	DEST, %lo(trap_block), DEST;	\
+
+/* Uniprocessor versions, we know the cpuid is zero.  */
+#define TRAP_LOAD_PGD_PHYS(DEST, TMP)		\
+	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
+	ldx	[DEST + TRAP_PER_CPU_PGD_PADDR], DEST;
+
+/* Clobbers TMP, loads local processor's IRQ work area into DEST.  */
+#define TRAP_LOAD_IRQ_WORK_PA(DEST, TMP)	\
+	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
+	add	DEST, TRAP_PER_CPU_IRQ_WORKLIST_PA, DEST;
+
+#define TRAP_LOAD_THREAD_REG(DEST, TMP)		\
+	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
+	ldx	[DEST + TRAP_PER_CPU_THREAD], DEST;
+
+/* No per-cpu areas on uniprocessor, so no need to load DEST.  */
+#define LOAD_PER_CPU_BASE(DEST, THR, REG1, REG2, REG3)
+
+#endif /* !(CONFIG_SMP) */
+
+#endif /* _SPARC64_CPUDATA_H */
diff --git a/include/asm-sparc/dcr.h b/include/asm-sparc/dcr.h
new file mode 100644
index 0000000..620c9ba6
--- /dev/null
+++ b/include/asm-sparc/dcr.h
@@ -0,0 +1,14 @@
+#ifndef _SPARC64_DCR_H
+#define _SPARC64_DCR_H
+
+/* UltraSparc-III/III+ Dispatch Control Register, ASR 0x12 */
+#define DCR_DPE		0x0000000000001000 /* III+: D$ Parity Error Enable	*/
+#define DCR_OBS		0x0000000000000fc0 /* Observability Bus Controls	*/
+#define DCR_BPE		0x0000000000000020 /* Branch Predict Enable		*/
+#define DCR_RPE		0x0000000000000010 /* Return Address Prediction Enable	*/
+#define DCR_SI		0x0000000000000008 /* Single Instruction Disable	*/
+#define DCR_IPE		0x0000000000000004 /* III+: I$ Parity Error Enable	*/
+#define DCR_IFPOE	0x0000000000000002 /* IRQ FP Operation Enable		*/
+#define DCR_MS		0x0000000000000001 /* Multi-Scalar dispatch		*/
+
+#endif /* _SPARC64_DCR_H */
diff --git a/include/asm-sparc/dcu.h b/include/asm-sparc/dcu.h
new file mode 100644
index 0000000..0f704e10
--- /dev/null
+++ b/include/asm-sparc/dcu.h
@@ -0,0 +1,27 @@
+#ifndef _SPARC64_DCU_H
+#define _SPARC64_DCU_H
+
+#include <linux/const.h>
+
+/* UltraSparc-III Data Cache Unit Control Register */
+#define DCU_CP	_AC(0x0002000000000000,UL) /* Phys Cache Enable w/o mmu	*/
+#define DCU_CV	_AC(0x0001000000000000,UL) /* Virt Cache Enable w/o mmu	*/
+#define DCU_ME	_AC(0x0000800000000000,UL) /* NC-store Merging Enable	*/
+#define DCU_RE	_AC(0x0000400000000000,UL) /* RAW bypass Enable		*/
+#define DCU_PE	_AC(0x0000200000000000,UL) /* PCache Enable		*/
+#define DCU_HPE	_AC(0x0000100000000000,UL) /* HW prefetch Enable	*/
+#define DCU_SPE	_AC(0x0000080000000000,UL) /* SW prefetch Enable	*/
+#define DCU_SL	_AC(0x0000040000000000,UL) /* Secondary ld-steering Enab*/
+#define DCU_WE	_AC(0x0000020000000000,UL) /* WCache enable		*/
+#define DCU_PM	_AC(0x000001fe00000000,UL) /* PA Watchpoint Byte Mask	*/
+#define DCU_VM	_AC(0x00000001fe000000,UL) /* VA Watchpoint Byte Mask	*/
+#define DCU_PR	_AC(0x0000000001000000,UL) /* PA Watchpoint Read Enable	*/
+#define DCU_PW	_AC(0x0000000000800000,UL) /* PA Watchpoint Write Enable*/
+#define DCU_VR	_AC(0x0000000000400000,UL) /* VA Watchpoint Read Enable	*/
+#define DCU_VW	_AC(0x0000000000200000,UL) /* VA Watchpoint Write Enable*/
+#define DCU_DM	_AC(0x0000000000000008,UL) /* DMMU Enable		*/
+#define DCU_IM	_AC(0x0000000000000004,UL) /* IMMU Enable		*/
+#define DCU_DC	_AC(0x0000000000000002,UL) /* Data Cache Enable		*/
+#define DCU_IC	_AC(0x0000000000000001,UL) /* Instruction Cache Enable	*/
+
+#endif /* _SPARC64_DCU_H */
diff --git a/include/asm-sparc/delay.h b/include/asm-sparc/delay.h
index bc9aba2..6210a3c 100644
--- a/include/asm-sparc/delay.h
+++ b/include/asm-sparc/delay.h
@@ -1,34 +1,8 @@
-/*
- * delay.h: Linux delay routines on the Sparc.
- *
- * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu).
- */
-
-#ifndef __SPARC_DELAY_H
-#define __SPARC_DELAY_H
-
-#include <asm/cpudata.h>
-
-static inline void __delay(unsigned long loops)
-{
-	__asm__ __volatile__("cmp %0, 0\n\t"
-			     "1: bne 1b\n\t"
-			     "subcc %0, 1, %0\n" :
-			     "=&r" (loops) :
-			     "0" (loops) :
-			     "cc");
-}
-
-/* This is too messy with inline asm on the Sparc. */
-extern void __udelay(unsigned long usecs, unsigned long lpj);
-extern void __ndelay(unsigned long nsecs, unsigned long lpj);
-
-#ifdef CONFIG_SMP
-#define __udelay_val	cpu_data(smp_processor_id()).udelay_val
-#else /* SMP */
-#define __udelay_val	loops_per_jiffy
-#endif /* SMP */
-#define udelay(__usecs)	__udelay(__usecs, __udelay_val)
-#define ndelay(__nsecs)	__ndelay(__nsecs, __udelay_val)
-
-#endif /* defined(__SPARC_DELAY_H) */
+#ifndef ___ASM_SPARC_DELAY_H
+#define ___ASM_SPARC_DELAY_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/delay_64.h>
+#else
+#include <asm-sparc/delay_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/delay_32.h b/include/asm-sparc/delay_32.h
new file mode 100644
index 0000000..bc9aba2
--- /dev/null
+++ b/include/asm-sparc/delay_32.h
@@ -0,0 +1,34 @@
+/*
+ * delay.h: Linux delay routines on the Sparc.
+ *
+ * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu).
+ */
+
+#ifndef __SPARC_DELAY_H
+#define __SPARC_DELAY_H
+
+#include <asm/cpudata.h>
+
+static inline void __delay(unsigned long loops)
+{
+	__asm__ __volatile__("cmp %0, 0\n\t"
+			     "1: bne 1b\n\t"
+			     "subcc %0, 1, %0\n" :
+			     "=&r" (loops) :
+			     "0" (loops) :
+			     "cc");
+}
+
+/* This is too messy with inline asm on the Sparc. */
+extern void __udelay(unsigned long usecs, unsigned long lpj);
+extern void __ndelay(unsigned long nsecs, unsigned long lpj);
+
+#ifdef CONFIG_SMP
+#define __udelay_val	cpu_data(smp_processor_id()).udelay_val
+#else /* SMP */
+#define __udelay_val	loops_per_jiffy
+#endif /* SMP */
+#define udelay(__usecs)	__udelay(__usecs, __udelay_val)
+#define ndelay(__nsecs)	__ndelay(__nsecs, __udelay_val)
+
+#endif /* defined(__SPARC_DELAY_H) */
diff --git a/include/asm-sparc/delay_64.h b/include/asm-sparc/delay_64.h
new file mode 100644
index 0000000..a77aa62
--- /dev/null
+++ b/include/asm-sparc/delay_64.h
@@ -0,0 +1,17 @@
+/* delay.h: Linux delay routines on sparc64.
+ *
+ * Copyright (C) 1996, 2004, 2007 David S. Miller (davem@davemloft.net).
+ */
+
+#ifndef _SPARC64_DELAY_H
+#define _SPARC64_DELAY_H
+
+#ifndef __ASSEMBLY__
+
+extern void __delay(unsigned long loops);
+extern void udelay(unsigned long usecs);
+#define mdelay(n)	udelay((n) * 1000)
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _SPARC64_DELAY_H */
diff --git a/include/asm-sparc/display7seg.h b/include/asm-sparc/display7seg.h
new file mode 100644
index 0000000..86d4a90
--- /dev/null
+++ b/include/asm-sparc/display7seg.h
@@ -0,0 +1,79 @@
+/*
+ *
+ * display7seg - Driver interface for the 7-segment display
+ * present on Sun Microsystems CP1400 and CP1500
+ *
+ * Copyright (c) 2000 Eric Brower <ebrower@usa.net>
+ *
+ */
+
+#ifndef __display7seg_h__
+#define __display7seg_h__
+
+#define D7S_IOC	'p'
+
+#define D7SIOCRD _IOR(D7S_IOC, 0x45, int)	/* Read device state	*/
+#define D7SIOCWR _IOW(D7S_IOC, 0x46, int)	/* Write device state	*/
+#define D7SIOCTM _IO (D7S_IOC, 0x47)		/* Translate mode (FLIP)*/
+
+/*
+ * ioctl flag definitions
+ *
+ * POINT	- Toggle decimal point	(0=absent 1=present)
+ * ALARM	- Toggle alarm LED 		(0=green  1=red)
+ * FLIP		- Toggle inverted mode 	(0=normal 1=flipped)
+ * bits 0-4	- Character displayed	(see definitions below)
+ *
+ * Display segments are defined as follows,
+ * subject to D7S_FLIP register state:
+ *
+ *    a
+ *   ---
+ * f|   |b
+ *   -g-
+ * e|   |c
+ *   ---
+ *    d
+ */
+
+#define D7S_POINT	(1 << 7)	/* Decimal point*/
+#define D7S_ALARM	(1 << 6)	/* Alarm LED 	*/
+#define D7S_FLIP	(1 << 5)	/* Flip display */
+
+#define D7S_0		0x00		/* Numerals 0-9 */
+#define D7S_1		0x01
+#define D7S_2		0x02
+#define D7S_3		0x03
+#define D7S_4		0x04
+#define D7S_5		0x05
+#define D7S_6		0x06
+#define D7S_7		0x07
+#define D7S_8		0x08
+#define D7S_9		0x09
+#define D7S_A		0x0A		/* Letters A-F, H, L, P */
+#define D7S_B		0x0B
+#define D7S_C		0x0C
+#define D7S_D		0x0D
+#define D7S_E		0x0E
+#define D7S_F		0x0F
+#define D7S_H		0x10
+#define D7S_E2		0x11
+#define D7S_L		0x12
+#define D7S_P		0x13
+#define D7S_SEGA	0x14		/* Individual segments */
+#define D7S_SEGB	0x15
+#define D7S_SEGC	0x16
+#define D7S_SEGD	0x17
+#define D7S_SEGE	0x18
+#define D7S_SEGF	0x19
+#define D7S_SEGG	0x1A
+#define D7S_SEGABFG 0x1B		/* Segment groupings */
+#define D7S_SEGCDEG	0x1C
+#define D7S_SEGBCEF 0x1D
+#define D7S_SEGADG	0x1E
+#define D7S_BLANK	0x1F		/* Clear all segments */
+
+#define D7S_MIN_VAL	0x0
+#define D7S_MAX_VAL	0x1F
+
+#endif /* ifndef __display7seg_h__ */
diff --git a/include/asm-sparc/dma-mapping.h b/include/asm-sparc/dma-mapping.h
index f3a641e..7483504 100644
--- a/include/asm-sparc/dma-mapping.h
+++ b/include/asm-sparc/dma-mapping.h
@@ -1,11 +1,8 @@
-#ifndef _ASM_SPARC_DMA_MAPPING_H
-#define _ASM_SPARC_DMA_MAPPING_H
-
-
-#ifdef CONFIG_PCI
-#include <asm-generic/dma-mapping.h>
+#ifndef ___ASM_SPARC_DMA_MAPPING_H
+#define ___ASM_SPARC_DMA_MAPPING_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/dma-mapping_64.h>
 #else
-#include <asm-generic/dma-mapping-broken.h>
-#endif /* PCI */
-
-#endif /* _ASM_SPARC_DMA_MAPPING_H */
+#include <asm-sparc/dma-mapping_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/dma-mapping_32.h b/include/asm-sparc/dma-mapping_32.h
new file mode 100644
index 0000000..f3a641e
--- /dev/null
+++ b/include/asm-sparc/dma-mapping_32.h
@@ -0,0 +1,11 @@
+#ifndef _ASM_SPARC_DMA_MAPPING_H
+#define _ASM_SPARC_DMA_MAPPING_H
+
+
+#ifdef CONFIG_PCI
+#include <asm-generic/dma-mapping.h>
+#else
+#include <asm-generic/dma-mapping-broken.h>
+#endif /* PCI */
+
+#endif /* _ASM_SPARC_DMA_MAPPING_H */
diff --git a/include/asm-sparc/dma-mapping_64.h b/include/asm-sparc/dma-mapping_64.h
new file mode 100644
index 0000000..38cbec7
--- /dev/null
+++ b/include/asm-sparc/dma-mapping_64.h
@@ -0,0 +1,154 @@
+#ifndef _ASM_SPARC64_DMA_MAPPING_H
+#define _ASM_SPARC64_DMA_MAPPING_H
+
+#include <linux/scatterlist.h>
+#include <linux/mm.h>
+
+#define DMA_ERROR_CODE	(~(dma_addr_t)0x0)
+
+struct dma_ops {
+	void *(*alloc_coherent)(struct device *dev, size_t size,
+				dma_addr_t *dma_handle, gfp_t flag);
+	void (*free_coherent)(struct device *dev, size_t size,
+			      void *cpu_addr, dma_addr_t dma_handle);
+	dma_addr_t (*map_single)(struct device *dev, void *cpu_addr,
+				 size_t size,
+				 enum dma_data_direction direction);
+	void (*unmap_single)(struct device *dev, dma_addr_t dma_addr,
+			     size_t size,
+			     enum dma_data_direction direction);
+	int (*map_sg)(struct device *dev, struct scatterlist *sg, int nents,
+		      enum dma_data_direction direction);
+	void (*unmap_sg)(struct device *dev, struct scatterlist *sg,
+			 int nhwentries,
+			 enum dma_data_direction direction);
+	void (*sync_single_for_cpu)(struct device *dev,
+				    dma_addr_t dma_handle, size_t size,
+				    enum dma_data_direction direction);
+	void (*sync_sg_for_cpu)(struct device *dev, struct scatterlist *sg,
+				int nelems,
+				enum dma_data_direction direction);
+};
+extern const struct dma_ops *dma_ops;
+
+extern int dma_supported(struct device *dev, u64 mask);
+extern int dma_set_mask(struct device *dev, u64 dma_mask);
+
+static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+				       dma_addr_t *dma_handle, gfp_t flag)
+{
+	return dma_ops->alloc_coherent(dev, size, dma_handle, flag);
+}
+
+static inline void dma_free_coherent(struct device *dev, size_t size,
+				     void *cpu_addr, dma_addr_t dma_handle)
+{
+	dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
+}
+
+static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
+					size_t size,
+					enum dma_data_direction direction)
+{
+	return dma_ops->map_single(dev, cpu_addr, size, direction);
+}
+
+static inline void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
+				    size_t size,
+				    enum dma_data_direction direction)
+{
+	dma_ops->unmap_single(dev, dma_addr, size, direction);
+}
+
+static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
+				      unsigned long offset, size_t size,
+				      enum dma_data_direction direction)
+{
+	return dma_ops->map_single(dev, page_address(page) + offset,
+				   size, direction);
+}
+
+static inline void dma_unmap_page(struct device *dev, dma_addr_t dma_address,
+				  size_t size,
+				  enum dma_data_direction direction)
+{
+	dma_ops->unmap_single(dev, dma_address, size, direction);
+}
+
+static inline int dma_map_sg(struct device *dev, struct scatterlist *sg,
+			     int nents, enum dma_data_direction direction)
+{
+	return dma_ops->map_sg(dev, sg, nents, direction);
+}
+
+static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+				int nents, enum dma_data_direction direction)
+{
+	dma_ops->unmap_sg(dev, sg, nents, direction);
+}
+
+static inline void dma_sync_single_for_cpu(struct device *dev,
+					   dma_addr_t dma_handle, size_t size,
+					   enum dma_data_direction direction)
+{
+	dma_ops->sync_single_for_cpu(dev, dma_handle, size, direction);
+}
+
+static inline void dma_sync_single_for_device(struct device *dev,
+					      dma_addr_t dma_handle,
+					      size_t size,
+					      enum dma_data_direction direction)
+{
+	/* No flushing needed to sync cpu writes to the device.  */
+}
+
+static inline void dma_sync_single_range_for_cpu(struct device *dev,
+						 dma_addr_t dma_handle,
+						 unsigned long offset,
+						 size_t size,
+						 enum dma_data_direction direction)
+{
+	dma_sync_single_for_cpu(dev, dma_handle+offset, size, direction);
+}
+
+static inline void dma_sync_single_range_for_device(struct device *dev,
+						    dma_addr_t dma_handle,
+						    unsigned long offset,
+						    size_t size,
+						    enum dma_data_direction direction)
+{
+	/* No flushing needed to sync cpu writes to the device.  */
+}
+
+
+static inline void dma_sync_sg_for_cpu(struct device *dev,
+				       struct scatterlist *sg, int nelems,
+				       enum dma_data_direction direction)
+{
+	dma_ops->sync_sg_for_cpu(dev, sg, nelems, direction);
+}
+
+static inline void dma_sync_sg_for_device(struct device *dev,
+					  struct scatterlist *sg, int nelems,
+					  enum dma_data_direction direction)
+{
+	/* No flushing needed to sync cpu writes to the device.  */
+}
+
+static inline int dma_mapping_error(dma_addr_t dma_addr)
+{
+	return (dma_addr == DMA_ERROR_CODE);
+}
+
+static inline int dma_get_cache_alignment(void)
+{
+	/* no easy way to get cache size on all processors, so return
+	 * the maximum possible, to be safe */
+	return (1 << INTERNODE_CACHE_SHIFT);
+}
+
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+#define dma_is_consistent(d, h)	(1)
+
+#endif /* _ASM_SPARC64_DMA_MAPPING_H */
diff --git a/include/asm-sparc/dma.h b/include/asm-sparc/dma.h
index 959d6c8..8cc69bf 100644
--- a/include/asm-sparc/dma.h
+++ b/include/asm-sparc/dma.h
@@ -1,288 +1,8 @@
-/* include/asm-sparc/dma.h
- *
- * Copyright 1995 (C) David S. Miller (davem@davemloft.net)
- */
-
-#ifndef _ASM_SPARC_DMA_H
-#define _ASM_SPARC_DMA_H
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-
-#include <asm/vac-ops.h>  /* for invalidate's, etc. */
-#include <asm/sbus.h>
-#include <asm/delay.h>
-#include <asm/oplib.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <linux/spinlock.h>
-
-struct page;
-extern spinlock_t  dma_spin_lock;
-
-static inline unsigned long claim_dma_lock(void)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&dma_spin_lock, flags);
-	return flags;
-}
-
-static inline void release_dma_lock(unsigned long flags)
-{
-	spin_unlock_irqrestore(&dma_spin_lock, flags);
-}
-
-/* These are irrelevant for Sparc DMA, but we leave it in so that
- * things can compile.
- */
-#define MAX_DMA_CHANNELS 8
-#define MAX_DMA_ADDRESS  (~0UL)
-#define DMA_MODE_READ    1
-#define DMA_MODE_WRITE   2
-
-/* Useful constants */
-#define SIZE_16MB      (16*1024*1024)
-#define SIZE_64K       (64*1024)
-
-/* SBUS DMA controller reg offsets */
-#define DMA_CSR		0x00UL		/* rw  DMA control/status register    0x00   */
-#define DMA_ADDR	0x04UL		/* rw  DMA transfer address register  0x04   */
-#define DMA_COUNT	0x08UL		/* rw  DMA transfer count register    0x08   */
-#define DMA_TEST	0x0cUL		/* rw  DMA test/debug register        0x0c   */
-
-/* DVMA chip revisions */
-enum dvma_rev {
-	dvmarev0,
-	dvmaesc1,
-	dvmarev1,
-	dvmarev2,
-	dvmarev3,
-	dvmarevplus,
-	dvmahme
-};
-
-#define DMA_HASCOUNT(rev)  ((rev)==dvmaesc1)
-
-/* Linux DMA information structure, filled during probe. */
-struct sbus_dma {
-	struct sbus_dma *next;
-	struct sbus_dev *sdev;
-	void __iomem *regs;
-
-	/* Status, misc info */
-	int node;                /* Prom node for this DMA device */
-	int running;             /* Are we doing DMA now? */
-	int allocated;           /* Are we "owned" by anyone yet? */
-
-	/* Transfer information. */
-	unsigned long addr;      /* Start address of current transfer */
-	int nbytes;              /* Size of current transfer */
-	int realbytes;           /* For splitting up large transfers, etc. */
-
-	/* DMA revision */
-	enum dvma_rev revision;
-};
-
-extern struct sbus_dma *dma_chain;
-
-/* Broken hardware... */
-#ifdef CONFIG_SUN4
-/* Have to sort this out. Does rev0 work fine on sun4[cmd] without isbroken?
- * Or is rev0 present only on sun4 boxes? -jj */
-#define DMA_ISBROKEN(dma)    ((dma)->revision == dvmarev0 || (dma)->revision == dvmarev1)
+#ifndef ___ASM_SPARC_DMA_H
+#define ___ASM_SPARC_DMA_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/dma_64.h>
 #else
-#define DMA_ISBROKEN(dma)    ((dma)->revision == dvmarev1)
+#include <asm-sparc/dma_32.h>
 #endif
-#define DMA_ISESC1(dma)      ((dma)->revision == dvmaesc1)
-
-/* Main routines in dma.c */
-extern void dvma_init(struct sbus_bus *);
-
-/* Fields in the cond_reg register */
-/* First, the version identification bits */
-#define DMA_DEVICE_ID    0xf0000000        /* Device identification bits */
-#define DMA_VERS0        0x00000000        /* Sunray DMA version */
-#define DMA_ESCV1        0x40000000        /* DMA ESC Version 1 */
-#define DMA_VERS1        0x80000000        /* DMA rev 1 */
-#define DMA_VERS2        0xa0000000        /* DMA rev 2 */
-#define DMA_VERHME       0xb0000000        /* DMA hme gate array */
-#define DMA_VERSPLUS     0x90000000        /* DMA rev 1 PLUS */
-
-#define DMA_HNDL_INTR    0x00000001        /* An IRQ needs to be handled */
-#define DMA_HNDL_ERROR   0x00000002        /* We need to take an error */
-#define DMA_FIFO_ISDRAIN 0x0000000c        /* The DMA FIFO is draining */
-#define DMA_INT_ENAB     0x00000010        /* Turn on interrupts */
-#define DMA_FIFO_INV     0x00000020        /* Invalidate the FIFO */
-#define DMA_ACC_SZ_ERR   0x00000040        /* The access size was bad */
-#define DMA_FIFO_STDRAIN 0x00000040        /* DMA_VERS1 Drain the FIFO */
-#define DMA_RST_SCSI     0x00000080        /* Reset the SCSI controller */
-#define DMA_RST_ENET     DMA_RST_SCSI      /* Reset the ENET controller */
-#define DMA_RST_BPP      DMA_RST_SCSI      /* Reset the BPP controller */
-#define DMA_ST_WRITE     0x00000100        /* write from device to memory */
-#define DMA_ENABLE       0x00000200        /* Fire up DMA, handle requests */
-#define DMA_PEND_READ    0x00000400        /* DMA_VERS1/0/PLUS Pending Read */
-#define DMA_ESC_BURST    0x00000800        /* 1=16byte 0=32byte */
-#define DMA_READ_AHEAD   0x00001800        /* DMA read ahead partial longword */
-#define DMA_DSBL_RD_DRN  0x00001000        /* No EC drain on slave reads */
-#define DMA_BCNT_ENAB    0x00002000        /* If on, use the byte counter */
-#define DMA_TERM_CNTR    0x00004000        /* Terminal counter */
-#define DMA_SCSI_SBUS64  0x00008000        /* HME: Enable 64-bit SBUS mode. */
-#define DMA_CSR_DISAB    0x00010000        /* No FIFO drains during csr */
-#define DMA_SCSI_DISAB   0x00020000        /* No FIFO drains during reg */
-#define DMA_DSBL_WR_INV  0x00020000        /* No EC inval. on slave writes */
-#define DMA_ADD_ENABLE   0x00040000        /* Special ESC DVMA optimization */
-#define DMA_E_BURSTS	 0x000c0000	   /* ENET: SBUS r/w burst mask */
-#define DMA_E_BURST32	 0x00040000	   /* ENET: SBUS 32 byte r/w burst */
-#define DMA_E_BURST16	 0x00000000	   /* ENET: SBUS 16 byte r/w burst */
-#define DMA_BRST_SZ      0x000c0000        /* SCSI: SBUS r/w burst size */
-#define DMA_BRST64       0x00080000        /* SCSI: 64byte bursts (HME on UltraSparc only) */
-#define DMA_BRST32       0x00040000        /* SCSI/BPP: 32byte bursts */
-#define DMA_BRST16       0x00000000        /* SCSI/BPP: 16byte bursts */
-#define DMA_BRST0        0x00080000        /* SCSI: no bursts (non-HME gate arrays) */
-#define DMA_ADDR_DISAB   0x00100000        /* No FIFO drains during addr */
-#define DMA_2CLKS        0x00200000        /* Each transfer = 2 clock ticks */
-#define DMA_3CLKS        0x00400000        /* Each transfer = 3 clock ticks */
-#define DMA_EN_ENETAUI   DMA_3CLKS         /* Put lance into AUI-cable mode */
-#define DMA_CNTR_DISAB   0x00800000        /* No IRQ when DMA_TERM_CNTR set */
-#define DMA_AUTO_NADDR   0x01000000        /* Use "auto nxt addr" feature */
-#define DMA_SCSI_ON      0x02000000        /* Enable SCSI dma */
-#define DMA_BPP_ON       DMA_SCSI_ON       /* Enable BPP dma */
-#define DMA_PARITY_OFF   0x02000000        /* HME: disable parity checking */
-#define DMA_LOADED_ADDR  0x04000000        /* Address has been loaded */
-#define DMA_LOADED_NADDR 0x08000000        /* Next address has been loaded */
-#define DMA_RESET_FAS366 0x08000000        /* HME: Assert RESET to FAS366 */
-
-/* Values describing the burst-size property from the PROM */
-#define DMA_BURST1       0x01
-#define DMA_BURST2       0x02
-#define DMA_BURST4       0x04
-#define DMA_BURST8       0x08
-#define DMA_BURST16      0x10
-#define DMA_BURST32      0x20
-#define DMA_BURST64      0x40
-#define DMA_BURSTBITS    0x7f
-
-/* Determine highest possible final transfer address given a base */
-#define DMA_MAXEND(addr) (0x01000000UL-(((unsigned long)(addr))&0x00ffffffUL))
-
-/* Yes, I hack a lot of elisp in my spare time... */
-#define DMA_ERROR_P(regs)  ((((regs)->cond_reg) & DMA_HNDL_ERROR))
-#define DMA_IRQ_P(regs)    ((((regs)->cond_reg) & (DMA_HNDL_INTR | DMA_HNDL_ERROR)))
-#define DMA_WRITE_P(regs)  ((((regs)->cond_reg) & DMA_ST_WRITE))
-#define DMA_OFF(regs)      ((((regs)->cond_reg) &= (~DMA_ENABLE)))
-#define DMA_INTSOFF(regs)  ((((regs)->cond_reg) &= (~DMA_INT_ENAB)))
-#define DMA_INTSON(regs)   ((((regs)->cond_reg) |= (DMA_INT_ENAB)))
-#define DMA_PUNTFIFO(regs) ((((regs)->cond_reg) |= DMA_FIFO_INV))
-#define DMA_SETSTART(regs, addr)  ((((regs)->st_addr) = (char *) addr))
-#define DMA_BEGINDMA_W(regs) \
-        ((((regs)->cond_reg |= (DMA_ST_WRITE|DMA_ENABLE|DMA_INT_ENAB))))
-#define DMA_BEGINDMA_R(regs) \
-        ((((regs)->cond_reg |= ((DMA_ENABLE|DMA_INT_ENAB)&(~DMA_ST_WRITE)))))
-
-/* For certain DMA chips, we need to disable ints upon irq entry
- * and turn them back on when we are done.  So in any ESP interrupt
- * handler you *must* call DMA_IRQ_ENTRY upon entry and DMA_IRQ_EXIT
- * when leaving the handler.  You have been warned...
- */
-#define DMA_IRQ_ENTRY(dma, dregs) do { \
-        if(DMA_ISBROKEN(dma)) DMA_INTSOFF(dregs); \
-   } while (0)
-
-#define DMA_IRQ_EXIT(dma, dregs) do { \
-	if(DMA_ISBROKEN(dma)) DMA_INTSON(dregs); \
-   } while(0)
-
-#if 0	/* P3 this stuff is inline in ledma.c:init_restart_ledma() */
-/* Pause until counter runs out or BIT isn't set in the DMA condition
- * register.
- */
-static inline void sparc_dma_pause(struct sparc_dma_registers *regs,
-				       unsigned long bit)
-{
-	int ctr = 50000;   /* Let's find some bugs ;) */
-
-	/* Busy wait until the bit is not set any more */
-	while((regs->cond_reg&bit) && (ctr>0)) {
-		ctr--;
-		__delay(5);
-	}
-
-	/* Check for bogus outcome. */
-	if(!ctr)
-		panic("DMA timeout");
-}
-
-/* Reset the friggin' thing... */
-#define DMA_RESET(dma) do { \
-	struct sparc_dma_registers *regs = dma->regs;                      \
-	/* Let the current FIFO drain itself */                            \
-	sparc_dma_pause(regs, (DMA_FIFO_ISDRAIN));                         \
-	/* Reset the logic */                                              \
-	regs->cond_reg |= (DMA_RST_SCSI);     /* assert */                 \
-	__delay(400);                         /* let the bits set ;) */    \
-	regs->cond_reg &= ~(DMA_RST_SCSI);    /* de-assert */              \
-	sparc_dma_enable_interrupts(regs);    /* Re-enable interrupts */   \
-	/* Enable FAST transfers if available */                           \
-	if(dma->revision>dvmarev1) regs->cond_reg |= DMA_3CLKS;            \
-	dma->running = 0;                                                  \
-} while(0)
 #endif
-
-#define for_each_dvma(dma) \
-        for((dma) = dma_chain; (dma); (dma) = (dma)->next)
-
-extern int get_dma_list(char *);
-extern int request_dma(unsigned int, __const__ char *);
-extern void free_dma(unsigned int);
-
-/* From PCI */
-
-#ifdef CONFIG_PCI
-extern int isa_dma_bridge_buggy;
-#else
-#define isa_dma_bridge_buggy	(0)
-#endif
-
-/* Routines for data transfer buffers. */
-BTFIXUPDEF_CALL(char *, mmu_lockarea, char *, unsigned long)
-BTFIXUPDEF_CALL(void,   mmu_unlockarea, char *, unsigned long)
-
-#define mmu_lockarea(vaddr,len) BTFIXUP_CALL(mmu_lockarea)(vaddr,len)
-#define mmu_unlockarea(vaddr,len) BTFIXUP_CALL(mmu_unlockarea)(vaddr,len)
-
-/* These are implementations for sbus_map_sg/sbus_unmap_sg... collapse later */
-BTFIXUPDEF_CALL(__u32, mmu_get_scsi_one, char *, unsigned long, struct sbus_bus *sbus)
-BTFIXUPDEF_CALL(void,  mmu_get_scsi_sgl, struct scatterlist *, int, struct sbus_bus *sbus)
-BTFIXUPDEF_CALL(void,  mmu_release_scsi_one, __u32, unsigned long, struct sbus_bus *sbus)
-BTFIXUPDEF_CALL(void,  mmu_release_scsi_sgl, struct scatterlist *, int, struct sbus_bus *sbus)
-
-#define mmu_get_scsi_one(vaddr,len,sbus) BTFIXUP_CALL(mmu_get_scsi_one)(vaddr,len,sbus)
-#define mmu_get_scsi_sgl(sg,sz,sbus) BTFIXUP_CALL(mmu_get_scsi_sgl)(sg,sz,sbus)
-#define mmu_release_scsi_one(vaddr,len,sbus) BTFIXUP_CALL(mmu_release_scsi_one)(vaddr,len,sbus)
-#define mmu_release_scsi_sgl(sg,sz,sbus) BTFIXUP_CALL(mmu_release_scsi_sgl)(sg,sz,sbus)
-
-/*
- * mmu_map/unmap are provided by iommu/iounit; Invalid to call on IIep.
- *
- * The mmu_map_dma_area establishes two mappings in one go.
- * These mappings point to pages normally mapped at 'va' (linear address).
- * First mapping is for CPU visible address at 'a', uncached.
- * This is an alias, but it works because it is an uncached mapping.
- * Second mapping is for device visible address, or "bus" address.
- * The bus address is returned at '*pba'.
- *
- * These functions seem distinct, but are hard to split. On sun4c,
- * at least for now, 'a' is equal to bus address, and retured in *pba.
- * On sun4m, page attributes depend on the CPU type, so we have to
- * know if we are mapping RAM or I/O, so it has to be an additional argument
- * to a separate mapping function for CPU visible mappings.
- */
-BTFIXUPDEF_CALL(int,  mmu_map_dma_area, dma_addr_t *, unsigned long, unsigned long, int len)
-BTFIXUPDEF_CALL(struct page *, mmu_translate_dvma, unsigned long busa)
-BTFIXUPDEF_CALL(void,  mmu_unmap_dma_area, unsigned long busa, int len)
-
-#define mmu_map_dma_area(pba,va,a,len) BTFIXUP_CALL(mmu_map_dma_area)(pba,va,a,len)
-#define mmu_unmap_dma_area(ba,len) BTFIXUP_CALL(mmu_unmap_dma_area)(ba,len)
-#define mmu_translate_dvma(ba)     BTFIXUP_CALL(mmu_translate_dvma)(ba)
-
-#endif /* !(_ASM_SPARC_DMA_H) */
diff --git a/include/asm-sparc/dma_32.h b/include/asm-sparc/dma_32.h
new file mode 100644
index 0000000..959d6c8
--- /dev/null
+++ b/include/asm-sparc/dma_32.h
@@ -0,0 +1,288 @@
+/* include/asm-sparc/dma.h
+ *
+ * Copyright 1995 (C) David S. Miller (davem@davemloft.net)
+ */
+
+#ifndef _ASM_SPARC_DMA_H
+#define _ASM_SPARC_DMA_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <asm/vac-ops.h>  /* for invalidate's, etc. */
+#include <asm/sbus.h>
+#include <asm/delay.h>
+#include <asm/oplib.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <linux/spinlock.h>
+
+struct page;
+extern spinlock_t  dma_spin_lock;
+
+static inline unsigned long claim_dma_lock(void)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&dma_spin_lock, flags);
+	return flags;
+}
+
+static inline void release_dma_lock(unsigned long flags)
+{
+	spin_unlock_irqrestore(&dma_spin_lock, flags);
+}
+
+/* These are irrelevant for Sparc DMA, but we leave it in so that
+ * things can compile.
+ */
+#define MAX_DMA_CHANNELS 8
+#define MAX_DMA_ADDRESS  (~0UL)
+#define DMA_MODE_READ    1
+#define DMA_MODE_WRITE   2
+
+/* Useful constants */
+#define SIZE_16MB      (16*1024*1024)
+#define SIZE_64K       (64*1024)
+
+/* SBUS DMA controller reg offsets */
+#define DMA_CSR		0x00UL		/* rw  DMA control/status register    0x00   */
+#define DMA_ADDR	0x04UL		/* rw  DMA transfer address register  0x04   */
+#define DMA_COUNT	0x08UL		/* rw  DMA transfer count register    0x08   */
+#define DMA_TEST	0x0cUL		/* rw  DMA test/debug register        0x0c   */
+
+/* DVMA chip revisions */
+enum dvma_rev {
+	dvmarev0,
+	dvmaesc1,
+	dvmarev1,
+	dvmarev2,
+	dvmarev3,
+	dvmarevplus,
+	dvmahme
+};
+
+#define DMA_HASCOUNT(rev)  ((rev)==dvmaesc1)
+
+/* Linux DMA information structure, filled during probe. */
+struct sbus_dma {
+	struct sbus_dma *next;
+	struct sbus_dev *sdev;
+	void __iomem *regs;
+
+	/* Status, misc info */
+	int node;                /* Prom node for this DMA device */
+	int running;             /* Are we doing DMA now? */
+	int allocated;           /* Are we "owned" by anyone yet? */
+
+	/* Transfer information. */
+	unsigned long addr;      /* Start address of current transfer */
+	int nbytes;              /* Size of current transfer */
+	int realbytes;           /* For splitting up large transfers, etc. */
+
+	/* DMA revision */
+	enum dvma_rev revision;
+};
+
+extern struct sbus_dma *dma_chain;
+
+/* Broken hardware... */
+#ifdef CONFIG_SUN4
+/* Have to sort this out. Does rev0 work fine on sun4[cmd] without isbroken?
+ * Or is rev0 present only on sun4 boxes? -jj */
+#define DMA_ISBROKEN(dma)    ((dma)->revision == dvmarev0 || (dma)->revision == dvmarev1)
+#else
+#define DMA_ISBROKEN(dma)    ((dma)->revision == dvmarev1)
+#endif
+#define DMA_ISESC1(dma)      ((dma)->revision == dvmaesc1)
+
+/* Main routines in dma.c */
+extern void dvma_init(struct sbus_bus *);
+
+/* Fields in the cond_reg register */
+/* First, the version identification bits */
+#define DMA_DEVICE_ID    0xf0000000        /* Device identification bits */
+#define DMA_VERS0        0x00000000        /* Sunray DMA version */
+#define DMA_ESCV1        0x40000000        /* DMA ESC Version 1 */
+#define DMA_VERS1        0x80000000        /* DMA rev 1 */
+#define DMA_VERS2        0xa0000000        /* DMA rev 2 */
+#define DMA_VERHME       0xb0000000        /* DMA hme gate array */
+#define DMA_VERSPLUS     0x90000000        /* DMA rev 1 PLUS */
+
+#define DMA_HNDL_INTR    0x00000001        /* An IRQ needs to be handled */
+#define DMA_HNDL_ERROR   0x00000002        /* We need to take an error */
+#define DMA_FIFO_ISDRAIN 0x0000000c        /* The DMA FIFO is draining */
+#define DMA_INT_ENAB     0x00000010        /* Turn on interrupts */
+#define DMA_FIFO_INV     0x00000020        /* Invalidate the FIFO */
+#define DMA_ACC_SZ_ERR   0x00000040        /* The access size was bad */
+#define DMA_FIFO_STDRAIN 0x00000040        /* DMA_VERS1 Drain the FIFO */
+#define DMA_RST_SCSI     0x00000080        /* Reset the SCSI controller */
+#define DMA_RST_ENET     DMA_RST_SCSI      /* Reset the ENET controller */
+#define DMA_RST_BPP      DMA_RST_SCSI      /* Reset the BPP controller */
+#define DMA_ST_WRITE     0x00000100        /* write from device to memory */
+#define DMA_ENABLE       0x00000200        /* Fire up DMA, handle requests */
+#define DMA_PEND_READ    0x00000400        /* DMA_VERS1/0/PLUS Pending Read */
+#define DMA_ESC_BURST    0x00000800        /* 1=16byte 0=32byte */
+#define DMA_READ_AHEAD   0x00001800        /* DMA read ahead partial longword */
+#define DMA_DSBL_RD_DRN  0x00001000        /* No EC drain on slave reads */
+#define DMA_BCNT_ENAB    0x00002000        /* If on, use the byte counter */
+#define DMA_TERM_CNTR    0x00004000        /* Terminal counter */
+#define DMA_SCSI_SBUS64  0x00008000        /* HME: Enable 64-bit SBUS mode. */
+#define DMA_CSR_DISAB    0x00010000        /* No FIFO drains during csr */
+#define DMA_SCSI_DISAB   0x00020000        /* No FIFO drains during reg */
+#define DMA_DSBL_WR_INV  0x00020000        /* No EC inval. on slave writes */
+#define DMA_ADD_ENABLE   0x00040000        /* Special ESC DVMA optimization */
+#define DMA_E_BURSTS	 0x000c0000	   /* ENET: SBUS r/w burst mask */
+#define DMA_E_BURST32	 0x00040000	   /* ENET: SBUS 32 byte r/w burst */
+#define DMA_E_BURST16	 0x00000000	   /* ENET: SBUS 16 byte r/w burst */
+#define DMA_BRST_SZ      0x000c0000        /* SCSI: SBUS r/w burst size */
+#define DMA_BRST64       0x00080000        /* SCSI: 64byte bursts (HME on UltraSparc only) */
+#define DMA_BRST32       0x00040000        /* SCSI/BPP: 32byte bursts */
+#define DMA_BRST16       0x00000000        /* SCSI/BPP: 16byte bursts */
+#define DMA_BRST0        0x00080000        /* SCSI: no bursts (non-HME gate arrays) */
+#define DMA_ADDR_DISAB   0x00100000        /* No FIFO drains during addr */
+#define DMA_2CLKS        0x00200000        /* Each transfer = 2 clock ticks */
+#define DMA_3CLKS        0x00400000        /* Each transfer = 3 clock ticks */
+#define DMA_EN_ENETAUI   DMA_3CLKS         /* Put lance into AUI-cable mode */
+#define DMA_CNTR_DISAB   0x00800000        /* No IRQ when DMA_TERM_CNTR set */
+#define DMA_AUTO_NADDR   0x01000000        /* Use "auto nxt addr" feature */
+#define DMA_SCSI_ON      0x02000000        /* Enable SCSI dma */
+#define DMA_BPP_ON       DMA_SCSI_ON       /* Enable BPP dma */
+#define DMA_PARITY_OFF   0x02000000        /* HME: disable parity checking */
+#define DMA_LOADED_ADDR  0x04000000        /* Address has been loaded */
+#define DMA_LOADED_NADDR 0x08000000        /* Next address has been loaded */
+#define DMA_RESET_FAS366 0x08000000        /* HME: Assert RESET to FAS366 */
+
+/* Values describing the burst-size property from the PROM */
+#define DMA_BURST1       0x01
+#define DMA_BURST2       0x02
+#define DMA_BURST4       0x04
+#define DMA_BURST8       0x08
+#define DMA_BURST16      0x10
+#define DMA_BURST32      0x20
+#define DMA_BURST64      0x40
+#define DMA_BURSTBITS    0x7f
+
+/* Determine highest possible final transfer address given a base */
+#define DMA_MAXEND(addr) (0x01000000UL-(((unsigned long)(addr))&0x00ffffffUL))
+
+/* Yes, I hack a lot of elisp in my spare time... */
+#define DMA_ERROR_P(regs)  ((((regs)->cond_reg) & DMA_HNDL_ERROR))
+#define DMA_IRQ_P(regs)    ((((regs)->cond_reg) & (DMA_HNDL_INTR | DMA_HNDL_ERROR)))
+#define DMA_WRITE_P(regs)  ((((regs)->cond_reg) & DMA_ST_WRITE))
+#define DMA_OFF(regs)      ((((regs)->cond_reg) &= (~DMA_ENABLE)))
+#define DMA_INTSOFF(regs)  ((((regs)->cond_reg) &= (~DMA_INT_ENAB)))
+#define DMA_INTSON(regs)   ((((regs)->cond_reg) |= (DMA_INT_ENAB)))
+#define DMA_PUNTFIFO(regs) ((((regs)->cond_reg) |= DMA_FIFO_INV))
+#define DMA_SETSTART(regs, addr)  ((((regs)->st_addr) = (char *) addr))
+#define DMA_BEGINDMA_W(regs) \
+        ((((regs)->cond_reg |= (DMA_ST_WRITE|DMA_ENABLE|DMA_INT_ENAB))))
+#define DMA_BEGINDMA_R(regs) \
+        ((((regs)->cond_reg |= ((DMA_ENABLE|DMA_INT_ENAB)&(~DMA_ST_WRITE)))))
+
+/* For certain DMA chips, we need to disable ints upon irq entry
+ * and turn them back on when we are done.  So in any ESP interrupt
+ * handler you *must* call DMA_IRQ_ENTRY upon entry and DMA_IRQ_EXIT
+ * when leaving the handler.  You have been warned...
+ */
+#define DMA_IRQ_ENTRY(dma, dregs) do { \
+        if(DMA_ISBROKEN(dma)) DMA_INTSOFF(dregs); \
+   } while (0)
+
+#define DMA_IRQ_EXIT(dma, dregs) do { \
+	if(DMA_ISBROKEN(dma)) DMA_INTSON(dregs); \
+   } while(0)
+
+#if 0	/* P3 this stuff is inline in ledma.c:init_restart_ledma() */
+/* Pause until counter runs out or BIT isn't set in the DMA condition
+ * register.
+ */
+static inline void sparc_dma_pause(struct sparc_dma_registers *regs,
+				       unsigned long bit)
+{
+	int ctr = 50000;   /* Let's find some bugs ;) */
+
+	/* Busy wait until the bit is not set any more */
+	while((regs->cond_reg&bit) && (ctr>0)) {
+		ctr--;
+		__delay(5);
+	}
+
+	/* Check for bogus outcome. */
+	if(!ctr)
+		panic("DMA timeout");
+}
+
+/* Reset the friggin' thing... */
+#define DMA_RESET(dma) do { \
+	struct sparc_dma_registers *regs = dma->regs;                      \
+	/* Let the current FIFO drain itself */                            \
+	sparc_dma_pause(regs, (DMA_FIFO_ISDRAIN));                         \
+	/* Reset the logic */                                              \
+	regs->cond_reg |= (DMA_RST_SCSI);     /* assert */                 \
+	__delay(400);                         /* let the bits set ;) */    \
+	regs->cond_reg &= ~(DMA_RST_SCSI);    /* de-assert */              \
+	sparc_dma_enable_interrupts(regs);    /* Re-enable interrupts */   \
+	/* Enable FAST transfers if available */                           \
+	if(dma->revision>dvmarev1) regs->cond_reg |= DMA_3CLKS;            \
+	dma->running = 0;                                                  \
+} while(0)
+#endif
+
+#define for_each_dvma(dma) \
+        for((dma) = dma_chain; (dma); (dma) = (dma)->next)
+
+extern int get_dma_list(char *);
+extern int request_dma(unsigned int, __const__ char *);
+extern void free_dma(unsigned int);
+
+/* From PCI */
+
+#ifdef CONFIG_PCI
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy	(0)
+#endif
+
+/* Routines for data transfer buffers. */
+BTFIXUPDEF_CALL(char *, mmu_lockarea, char *, unsigned long)
+BTFIXUPDEF_CALL(void,   mmu_unlockarea, char *, unsigned long)
+
+#define mmu_lockarea(vaddr,len) BTFIXUP_CALL(mmu_lockarea)(vaddr,len)
+#define mmu_unlockarea(vaddr,len) BTFIXUP_CALL(mmu_unlockarea)(vaddr,len)
+
+/* These are implementations for sbus_map_sg/sbus_unmap_sg... collapse later */
+BTFIXUPDEF_CALL(__u32, mmu_get_scsi_one, char *, unsigned long, struct sbus_bus *sbus)
+BTFIXUPDEF_CALL(void,  mmu_get_scsi_sgl, struct scatterlist *, int, struct sbus_bus *sbus)
+BTFIXUPDEF_CALL(void,  mmu_release_scsi_one, __u32, unsigned long, struct sbus_bus *sbus)
+BTFIXUPDEF_CALL(void,  mmu_release_scsi_sgl, struct scatterlist *, int, struct sbus_bus *sbus)
+
+#define mmu_get_scsi_one(vaddr,len,sbus) BTFIXUP_CALL(mmu_get_scsi_one)(vaddr,len,sbus)
+#define mmu_get_scsi_sgl(sg,sz,sbus) BTFIXUP_CALL(mmu_get_scsi_sgl)(sg,sz,sbus)
+#define mmu_release_scsi_one(vaddr,len,sbus) BTFIXUP_CALL(mmu_release_scsi_one)(vaddr,len,sbus)
+#define mmu_release_scsi_sgl(sg,sz,sbus) BTFIXUP_CALL(mmu_release_scsi_sgl)(sg,sz,sbus)
+
+/*
+ * mmu_map/unmap are provided by iommu/iounit; Invalid to call on IIep.
+ *
+ * The mmu_map_dma_area establishes two mappings in one go.
+ * These mappings point to pages normally mapped at 'va' (linear address).
+ * First mapping is for CPU visible address at 'a', uncached.
+ * This is an alias, but it works because it is an uncached mapping.
+ * Second mapping is for device visible address, or "bus" address.
+ * The bus address is returned at '*pba'.
+ *
+ * These functions seem distinct, but are hard to split. On sun4c,
+ * at least for now, 'a' is equal to bus address, and retured in *pba.
+ * On sun4m, page attributes depend on the CPU type, so we have to
+ * know if we are mapping RAM or I/O, so it has to be an additional argument
+ * to a separate mapping function for CPU visible mappings.
+ */
+BTFIXUPDEF_CALL(int,  mmu_map_dma_area, dma_addr_t *, unsigned long, unsigned long, int len)
+BTFIXUPDEF_CALL(struct page *, mmu_translate_dvma, unsigned long busa)
+BTFIXUPDEF_CALL(void,  mmu_unmap_dma_area, unsigned long busa, int len)
+
+#define mmu_map_dma_area(pba,va,a,len) BTFIXUP_CALL(mmu_map_dma_area)(pba,va,a,len)
+#define mmu_unmap_dma_area(ba,len) BTFIXUP_CALL(mmu_unmap_dma_area)(ba,len)
+#define mmu_translate_dvma(ba)     BTFIXUP_CALL(mmu_translate_dvma)(ba)
+
+#endif /* !(_ASM_SPARC_DMA_H) */
diff --git a/include/asm-sparc/dma_64.h b/include/asm-sparc/dma_64.h
new file mode 100644
index 0000000..9d4c024
--- /dev/null
+++ b/include/asm-sparc/dma_64.h
@@ -0,0 +1,205 @@
+/*
+ * include/asm-sparc64/dma.h
+ *
+ * Copyright 1996 (C) David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _ASM_SPARC64_DMA_H
+#define _ASM_SPARC64_DMA_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/spinlock.h>
+
+#include <asm/sbus.h>
+#include <asm/delay.h>
+#include <asm/oplib.h>
+
+/* These are irrelevant for Sparc DMA, but we leave it in so that
+ * things can compile.
+ */
+#define MAX_DMA_CHANNELS 8
+#define DMA_MODE_READ    1
+#define DMA_MODE_WRITE   2
+#define MAX_DMA_ADDRESS  (~0UL)
+
+/* Useful constants */
+#define SIZE_16MB      (16*1024*1024)
+#define SIZE_64K       (64*1024)
+
+/* SBUS DMA controller reg offsets */
+#define DMA_CSR		0x00UL		/* rw  DMA control/status register    0x00   */
+#define DMA_ADDR	0x04UL		/* rw  DMA transfer address register  0x04   */
+#define DMA_COUNT	0x08UL		/* rw  DMA transfer count register    0x08   */
+#define DMA_TEST	0x0cUL		/* rw  DMA test/debug register        0x0c   */
+
+/* DVMA chip revisions */
+enum dvma_rev {
+	dvmarev0,
+	dvmaesc1,
+	dvmarev1,
+	dvmarev2,
+	dvmarev3,
+	dvmarevplus,
+	dvmahme
+};
+
+#define DMA_HASCOUNT(rev)  ((rev)==dvmaesc1)
+
+/* Linux DMA information structure, filled during probe. */
+struct sbus_dma {
+	struct sbus_dma *next;
+	struct sbus_dev *sdev;
+	void __iomem *regs;
+
+	/* Status, misc info */
+	int node;                /* Prom node for this DMA device */
+	int running;             /* Are we doing DMA now? */
+	int allocated;           /* Are we "owned" by anyone yet? */
+
+	/* Transfer information. */
+	u32 addr;                /* Start address of current transfer */
+	int nbytes;              /* Size of current transfer */
+	int realbytes;           /* For splitting up large transfers, etc. */
+
+	/* DMA revision */
+	enum dvma_rev revision;
+};
+
+extern struct sbus_dma *dma_chain;
+
+/* Broken hardware... */
+#define DMA_ISBROKEN(dma)    ((dma)->revision == dvmarev1)
+#define DMA_ISESC1(dma)      ((dma)->revision == dvmaesc1)
+
+/* Main routines in dma.c */
+extern void dvma_init(struct sbus_bus *);
+
+/* Fields in the cond_reg register */
+/* First, the version identification bits */
+#define DMA_DEVICE_ID    0xf0000000        /* Device identification bits */
+#define DMA_VERS0        0x00000000        /* Sunray DMA version */
+#define DMA_ESCV1        0x40000000        /* DMA ESC Version 1 */
+#define DMA_VERS1        0x80000000        /* DMA rev 1 */
+#define DMA_VERS2        0xa0000000        /* DMA rev 2 */
+#define DMA_VERHME       0xb0000000        /* DMA hme gate array */
+#define DMA_VERSPLUS     0x90000000        /* DMA rev 1 PLUS */
+
+#define DMA_HNDL_INTR    0x00000001        /* An IRQ needs to be handled */
+#define DMA_HNDL_ERROR   0x00000002        /* We need to take an error */
+#define DMA_FIFO_ISDRAIN 0x0000000c        /* The DMA FIFO is draining */
+#define DMA_INT_ENAB     0x00000010        /* Turn on interrupts */
+#define DMA_FIFO_INV     0x00000020        /* Invalidate the FIFO */
+#define DMA_ACC_SZ_ERR   0x00000040        /* The access size was bad */
+#define DMA_FIFO_STDRAIN 0x00000040        /* DMA_VERS1 Drain the FIFO */
+#define DMA_RST_SCSI     0x00000080        /* Reset the SCSI controller */
+#define DMA_RST_ENET     DMA_RST_SCSI      /* Reset the ENET controller */
+#define DMA_ST_WRITE     0x00000100        /* write from device to memory */
+#define DMA_ENABLE       0x00000200        /* Fire up DMA, handle requests */
+#define DMA_PEND_READ    0x00000400        /* DMA_VERS1/0/PLUS Pending Read */
+#define DMA_ESC_BURST    0x00000800        /* 1=16byte 0=32byte */
+#define DMA_READ_AHEAD   0x00001800        /* DMA read ahead partial longword */
+#define DMA_DSBL_RD_DRN  0x00001000        /* No EC drain on slave reads */
+#define DMA_BCNT_ENAB    0x00002000        /* If on, use the byte counter */
+#define DMA_TERM_CNTR    0x00004000        /* Terminal counter */
+#define DMA_SCSI_SBUS64  0x00008000        /* HME: Enable 64-bit SBUS mode. */
+#define DMA_CSR_DISAB    0x00010000        /* No FIFO drains during csr */
+#define DMA_SCSI_DISAB   0x00020000        /* No FIFO drains during reg */
+#define DMA_DSBL_WR_INV  0x00020000        /* No EC inval. on slave writes */
+#define DMA_ADD_ENABLE   0x00040000        /* Special ESC DVMA optimization */
+#define DMA_E_BURSTS	 0x000c0000	   /* ENET: SBUS r/w burst mask */
+#define DMA_E_BURST32	 0x00040000	   /* ENET: SBUS 32 byte r/w burst */
+#define DMA_E_BURST16	 0x00000000	   /* ENET: SBUS 16 byte r/w burst */
+#define DMA_BRST_SZ      0x000c0000        /* SCSI: SBUS r/w burst size */
+#define DMA_BRST64       0x000c0000        /* SCSI: 64byte bursts (HME on UltraSparc only) */
+#define DMA_BRST32       0x00040000        /* SCSI: 32byte bursts */
+#define DMA_BRST16       0x00000000        /* SCSI: 16byte bursts */
+#define DMA_BRST0        0x00080000        /* SCSI: no bursts (non-HME gate arrays) */
+#define DMA_ADDR_DISAB   0x00100000        /* No FIFO drains during addr */
+#define DMA_2CLKS        0x00200000        /* Each transfer = 2 clock ticks */
+#define DMA_3CLKS        0x00400000        /* Each transfer = 3 clock ticks */
+#define DMA_EN_ENETAUI   DMA_3CLKS         /* Put lance into AUI-cable mode */
+#define DMA_CNTR_DISAB   0x00800000        /* No IRQ when DMA_TERM_CNTR set */
+#define DMA_AUTO_NADDR   0x01000000        /* Use "auto nxt addr" feature */
+#define DMA_SCSI_ON      0x02000000        /* Enable SCSI dma */
+#define DMA_PARITY_OFF   0x02000000        /* HME: disable parity checking */
+#define DMA_LOADED_ADDR  0x04000000        /* Address has been loaded */
+#define DMA_LOADED_NADDR 0x08000000        /* Next address has been loaded */
+#define DMA_RESET_FAS366 0x08000000        /* HME: Assert RESET to FAS366 */
+
+/* Values describing the burst-size property from the PROM */
+#define DMA_BURST1       0x01
+#define DMA_BURST2       0x02
+#define DMA_BURST4       0x04
+#define DMA_BURST8       0x08
+#define DMA_BURST16      0x10
+#define DMA_BURST32      0x20
+#define DMA_BURST64      0x40
+#define DMA_BURSTBITS    0x7f
+
+/* Determine highest possible final transfer address given a base */
+#define DMA_MAXEND(addr) (0x01000000UL-(((unsigned long)(addr))&0x00ffffffUL))
+
+/* Yes, I hack a lot of elisp in my spare time... */
+#define DMA_ERROR_P(regs)  ((sbus_readl((regs) + DMA_CSR) & DMA_HNDL_ERROR))
+#define DMA_IRQ_P(regs)    ((sbus_readl((regs) + DMA_CSR)) & (DMA_HNDL_INTR | DMA_HNDL_ERROR))
+#define DMA_WRITE_P(regs)  ((sbus_readl((regs) + DMA_CSR) & DMA_ST_WRITE))
+#define DMA_OFF(__regs)		\
+do {	u32 tmp = sbus_readl((__regs) + DMA_CSR); \
+	tmp &= ~DMA_ENABLE; \
+	sbus_writel(tmp, (__regs) + DMA_CSR); \
+} while(0)
+#define DMA_INTSOFF(__regs)	\
+do {	u32 tmp = sbus_readl((__regs) + DMA_CSR); \
+	tmp &= ~DMA_INT_ENAB; \
+	sbus_writel(tmp, (__regs) + DMA_CSR); \
+} while(0)
+#define DMA_INTSON(__regs)	\
+do {	u32 tmp = sbus_readl((__regs) + DMA_CSR); \
+	tmp |= DMA_INT_ENAB; \
+	sbus_writel(tmp, (__regs) + DMA_CSR); \
+} while(0)
+#define DMA_PUNTFIFO(__regs)	\
+do {	u32 tmp = sbus_readl((__regs) + DMA_CSR); \
+	tmp |= DMA_FIFO_INV; \
+	sbus_writel(tmp, (__regs) + DMA_CSR); \
+} while(0)
+#define DMA_SETSTART(__regs, __addr)	\
+	sbus_writel((u32)(__addr), (__regs) + DMA_ADDR);
+#define DMA_BEGINDMA_W(__regs)	\
+do {	u32 tmp = sbus_readl((__regs) + DMA_CSR); \
+	tmp |= (DMA_ST_WRITE|DMA_ENABLE|DMA_INT_ENAB); \
+	sbus_writel(tmp, (__regs) + DMA_CSR); \
+} while(0)
+#define DMA_BEGINDMA_R(__regs)	\
+do {	u32 tmp = sbus_readl((__regs) + DMA_CSR); \
+	tmp |= (DMA_ENABLE|DMA_INT_ENAB); \
+	tmp &= ~DMA_ST_WRITE; \
+	sbus_writel(tmp, (__regs) + DMA_CSR); \
+} while(0)
+
+/* For certain DMA chips, we need to disable ints upon irq entry
+ * and turn them back on when we are done.  So in any ESP interrupt
+ * handler you *must* call DMA_IRQ_ENTRY upon entry and DMA_IRQ_EXIT
+ * when leaving the handler.  You have been warned...
+ */
+#define DMA_IRQ_ENTRY(dma, dregs) do { \
+        if(DMA_ISBROKEN(dma)) DMA_INTSOFF(dregs); \
+   } while (0)
+
+#define DMA_IRQ_EXIT(dma, dregs) do { \
+	if(DMA_ISBROKEN(dma)) DMA_INTSON(dregs); \
+   } while(0)
+
+#define for_each_dvma(dma) \
+        for((dma) = dma_chain; (dma); (dma) = (dma)->next)
+
+/* From PCI */
+
+#ifdef CONFIG_PCI
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy 	(0)
+#endif
+
+#endif /* !(_ASM_SPARC64_DMA_H) */
diff --git a/include/asm-sparc/ebus.h b/include/asm-sparc/ebus.h
index 491f85d..a5da2d0 100644
--- a/include/asm-sparc/ebus.h
+++ b/include/asm-sparc/ebus.h
@@ -1,99 +1,8 @@
-/*
- * ebus.h: PCI to Ebus pseudo driver software state.
- *
- * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) 
- *
- * Adopted for sparc by V. Roganov and G. Raiko.
- */
-
-#ifndef __SPARC_EBUS_H
-#define __SPARC_EBUS_H
-
-#ifndef _LINUX_IOPORT_H
-#include <linux/ioport.h>
+#ifndef ___ASM_SPARC_EBUS_H
+#define ___ASM_SPARC_EBUS_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/ebus_64.h>
+#else
+#include <asm-sparc/ebus_32.h>
 #endif
-#include <asm/oplib.h>
-#include <asm/prom.h>
-#include <asm/of_device.h>
-
-struct linux_ebus_child {
-	struct linux_ebus_child		*next;
-	struct linux_ebus_device	*parent;
-	struct linux_ebus		*bus;
-	struct device_node		*prom_node;
-	struct resource			 resource[PROMREG_MAX];
-	int				 num_addrs;
-	unsigned int			 irqs[PROMINTR_MAX];
-	int				 num_irqs;
-};
-
-struct linux_ebus_device {
-	struct of_device		ofdev;
-	struct linux_ebus_device	*next;
-	struct linux_ebus_child		*children;
-	struct linux_ebus		*bus;
-	struct device_node		*prom_node;
-	struct resource			 resource[PROMREG_MAX];
-	int				 num_addrs;
-	unsigned int			 irqs[PROMINTR_MAX];
-	int				 num_irqs;
-};
-#define to_ebus_device(d) container_of(d, struct linux_ebus_device, ofdev.dev)
-
-struct linux_ebus {
-	struct of_device		ofdev;
-	struct linux_ebus		*next;
-	struct linux_ebus_device	*devices;
-	struct linux_pbm_info		*parent;
-	struct pci_dev			*self;
-	struct device_node		*prom_node;
-};
-#define to_ebus(d) container_of(d, struct linux_ebus, ofdev.dev)
-
-struct linux_ebus_dma {
-	unsigned int dcsr;
-	unsigned int dacr;
-	unsigned int dbcr;
-};
-
-#define EBUS_DCSR_INT_PEND	0x00000001
-#define EBUS_DCSR_ERR_PEND	0x00000002
-#define EBUS_DCSR_DRAIN		0x00000004
-#define EBUS_DCSR_INT_EN	0x00000010
-#define EBUS_DCSR_RESET		0x00000080
-#define EBUS_DCSR_WRITE		0x00000100
-#define EBUS_DCSR_EN_DMA	0x00000200
-#define EBUS_DCSR_CYC_PEND	0x00000400
-#define EBUS_DCSR_DIAG_RD_DONE	0x00000800
-#define EBUS_DCSR_DIAG_WR_DONE	0x00001000
-#define EBUS_DCSR_EN_CNT	0x00002000
-#define EBUS_DCSR_TC		0x00004000
-#define EBUS_DCSR_DIS_CSR_DRN	0x00010000
-#define EBUS_DCSR_BURST_SZ_MASK	0x000c0000
-#define EBUS_DCSR_BURST_SZ_1	0x00080000
-#define EBUS_DCSR_BURST_SZ_4	0x00000000
-#define EBUS_DCSR_BURST_SZ_8	0x00040000
-#define EBUS_DCSR_BURST_SZ_16	0x000c0000
-#define EBUS_DCSR_DIAG_EN	0x00100000
-#define EBUS_DCSR_DIS_ERR_PEND	0x00400000
-#define EBUS_DCSR_TCI_DIS	0x00800000
-#define EBUS_DCSR_EN_NEXT	0x01000000
-#define EBUS_DCSR_DMA_ON	0x02000000
-#define EBUS_DCSR_A_LOADED	0x04000000
-#define EBUS_DCSR_NA_LOADED	0x08000000
-#define EBUS_DCSR_DEV_ID_MASK	0xf0000000
-
-extern struct linux_ebus		*ebus_chain;
-
-extern void ebus_init(void);
-
-#define for_each_ebus(bus)						\
-        for((bus) = ebus_chain; (bus); (bus) = (bus)->next)
-
-#define for_each_ebusdev(dev, bus)					\
-        for((dev) = (bus)->devices; (dev); (dev) = (dev)->next)
-
-#define for_each_edevchild(dev, child)					\
-        for((child) = (dev)->children; (child); (child) = (child)->next)
-
-#endif /* !(__SPARC_EBUS_H) */
+#endif
diff --git a/include/asm-sparc/ebus_32.h b/include/asm-sparc/ebus_32.h
new file mode 100644
index 0000000..29cb7df
--- /dev/null
+++ b/include/asm-sparc/ebus_32.h
@@ -0,0 +1,99 @@
+/*
+ * ebus.h: PCI to Ebus pseudo driver software state.
+ *
+ * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
+ *
+ * Adopted for sparc by V. Roganov and G. Raiko.
+ */
+
+#ifndef __SPARC_EBUS_H
+#define __SPARC_EBUS_H
+
+#ifndef _LINUX_IOPORT_H
+#include <linux/ioport.h>
+#endif
+#include <asm/oplib.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
+
+struct linux_ebus_child {
+	struct linux_ebus_child		*next;
+	struct linux_ebus_device	*parent;
+	struct linux_ebus		*bus;
+	struct device_node		*prom_node;
+	struct resource			 resource[PROMREG_MAX];
+	int				 num_addrs;
+	unsigned int			 irqs[PROMINTR_MAX];
+	int				 num_irqs;
+};
+
+struct linux_ebus_device {
+	struct of_device		ofdev;
+	struct linux_ebus_device	*next;
+	struct linux_ebus_child		*children;
+	struct linux_ebus		*bus;
+	struct device_node		*prom_node;
+	struct resource			 resource[PROMREG_MAX];
+	int				 num_addrs;
+	unsigned int			 irqs[PROMINTR_MAX];
+	int				 num_irqs;
+};
+#define to_ebus_device(d) container_of(d, struct linux_ebus_device, ofdev.dev)
+
+struct linux_ebus {
+	struct of_device		ofdev;
+	struct linux_ebus		*next;
+	struct linux_ebus_device	*devices;
+	struct linux_pbm_info		*parent;
+	struct pci_dev			*self;
+	struct device_node		*prom_node;
+};
+#define to_ebus(d) container_of(d, struct linux_ebus, ofdev.dev)
+
+struct linux_ebus_dma {
+	unsigned int dcsr;
+	unsigned int dacr;
+	unsigned int dbcr;
+};
+
+#define EBUS_DCSR_INT_PEND	0x00000001
+#define EBUS_DCSR_ERR_PEND	0x00000002
+#define EBUS_DCSR_DRAIN		0x00000004
+#define EBUS_DCSR_INT_EN	0x00000010
+#define EBUS_DCSR_RESET		0x00000080
+#define EBUS_DCSR_WRITE		0x00000100
+#define EBUS_DCSR_EN_DMA	0x00000200
+#define EBUS_DCSR_CYC_PEND	0x00000400
+#define EBUS_DCSR_DIAG_RD_DONE	0x00000800
+#define EBUS_DCSR_DIAG_WR_DONE	0x00001000
+#define EBUS_DCSR_EN_CNT	0x00002000
+#define EBUS_DCSR_TC		0x00004000
+#define EBUS_DCSR_DIS_CSR_DRN	0x00010000
+#define EBUS_DCSR_BURST_SZ_MASK	0x000c0000
+#define EBUS_DCSR_BURST_SZ_1	0x00080000
+#define EBUS_DCSR_BURST_SZ_4	0x00000000
+#define EBUS_DCSR_BURST_SZ_8	0x00040000
+#define EBUS_DCSR_BURST_SZ_16	0x000c0000
+#define EBUS_DCSR_DIAG_EN	0x00100000
+#define EBUS_DCSR_DIS_ERR_PEND	0x00400000
+#define EBUS_DCSR_TCI_DIS	0x00800000
+#define EBUS_DCSR_EN_NEXT	0x01000000
+#define EBUS_DCSR_DMA_ON	0x02000000
+#define EBUS_DCSR_A_LOADED	0x04000000
+#define EBUS_DCSR_NA_LOADED	0x08000000
+#define EBUS_DCSR_DEV_ID_MASK	0xf0000000
+
+extern struct linux_ebus		*ebus_chain;
+
+extern void ebus_init(void);
+
+#define for_each_ebus(bus)						\
+        for((bus) = ebus_chain; (bus); (bus) = (bus)->next)
+
+#define for_each_ebusdev(dev, bus)					\
+        for((dev) = (bus)->devices; (dev); (dev) = (dev)->next)
+
+#define for_each_edevchild(dev, child)					\
+        for((child) = (dev)->children; (child); (child) = (child)->next)
+
+#endif /* !(__SPARC_EBUS_H) */
diff --git a/include/asm-sparc/ebus_64.h b/include/asm-sparc/ebus_64.h
new file mode 100644
index 0000000..fcc62b9
--- /dev/null
+++ b/include/asm-sparc/ebus_64.h
@@ -0,0 +1,94 @@
+/*
+ * ebus.h: PCI to Ebus pseudo driver software state.
+ *
+ * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ */
+
+#ifndef __SPARC64_EBUS_H
+#define __SPARC64_EBUS_H
+
+#include <asm/oplib.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
+
+struct linux_ebus_child {
+	struct linux_ebus_child		*next;
+	struct linux_ebus_device	*parent;
+	struct linux_ebus		*bus;
+	struct device_node		*prom_node;
+	struct resource			 resource[PROMREG_MAX];
+	int				 num_addrs;
+	unsigned int			 irqs[PROMINTR_MAX];
+	int				 num_irqs;
+};
+
+struct linux_ebus_device {
+	struct of_device		ofdev;
+	struct linux_ebus_device	*next;
+	struct linux_ebus_child		*children;
+	struct linux_ebus		*bus;
+	struct device_node		*prom_node;
+	struct resource			 resource[PROMREG_MAX];
+	int				 num_addrs;
+	unsigned int			 irqs[PROMINTR_MAX];
+	int				 num_irqs;
+};
+#define to_ebus_device(d) container_of(d, struct linux_ebus_device, ofdev.dev)
+
+struct linux_ebus {
+	struct of_device		ofdev;
+	struct linux_ebus		*next;
+	struct linux_ebus_device	*devices;
+	struct pci_dev			*self;
+	int				 index;
+	int				 is_rio;
+	struct device_node		*prom_node;
+};
+#define to_ebus(d) container_of(d, struct linux_ebus, ofdev.dev)
+
+struct ebus_dma_info {
+	spinlock_t	lock;
+	void __iomem	*regs;
+
+	unsigned int	flags;
+#define EBUS_DMA_FLAG_USE_EBDMA_HANDLER		0x00000001
+#define EBUS_DMA_FLAG_TCI_DISABLE		0x00000002
+
+	/* These are only valid is EBUS_DMA_FLAG_USE_EBDMA_HANDLER is
+	 * set.
+	 */
+	void (*callback)(struct ebus_dma_info *p, int event, void *cookie);
+	void *client_cookie;
+	unsigned int	irq;
+#define EBUS_DMA_EVENT_ERROR	1
+#define EBUS_DMA_EVENT_DMA	2
+#define EBUS_DMA_EVENT_DEVICE	4
+
+	unsigned char	name[64];
+};
+
+extern int ebus_dma_register(struct ebus_dma_info *p);
+extern int ebus_dma_irq_enable(struct ebus_dma_info *p, int on);
+extern void ebus_dma_unregister(struct ebus_dma_info *p);
+extern int ebus_dma_request(struct ebus_dma_info *p, dma_addr_t bus_addr,
+			    size_t len);
+extern void ebus_dma_prepare(struct ebus_dma_info *p, int write);
+extern unsigned int ebus_dma_residue(struct ebus_dma_info *p);
+extern unsigned int ebus_dma_addr(struct ebus_dma_info *p);
+extern void ebus_dma_enable(struct ebus_dma_info *p, int on);
+
+extern struct linux_ebus		*ebus_chain;
+
+extern void ebus_init(void);
+
+#define for_each_ebus(bus)						\
+        for((bus) = ebus_chain; (bus); (bus) = (bus)->next)
+
+#define for_each_ebusdev(dev, bus)					\
+        for((dev) = (bus)->devices; (dev); (dev) = (dev)->next)
+
+#define for_each_edevchild(dev, child)					\
+        for((child) = (dev)->children; (child); (child) = (child)->next)
+
+#endif /* !(__SPARC64_EBUS_H) */
diff --git a/include/asm-sparc/elf.h b/include/asm-sparc/elf.h
index d043f80b..f035c45 100644
--- a/include/asm-sparc/elf.h
+++ b/include/asm-sparc/elf.h
@@ -1,145 +1,8 @@
-#ifndef __ASMSPARC_ELF_H
-#define __ASMSPARC_ELF_H
-
-/*
- * ELF register definitions..
- */
-
-#include <asm/ptrace.h>
-
-/*
- * Sparc section types
- */
-#define STT_REGISTER		13
-
-/*
- * Sparc ELF relocation types
- */
-#define	R_SPARC_NONE		0
-#define	R_SPARC_8		1
-#define	R_SPARC_16		2
-#define	R_SPARC_32		3
-#define	R_SPARC_DISP8		4
-#define	R_SPARC_DISP16		5
-#define	R_SPARC_DISP32		6
-#define	R_SPARC_WDISP30		7
-#define	R_SPARC_WDISP22		8
-#define	R_SPARC_HI22		9
-#define	R_SPARC_22		10
-#define	R_SPARC_13		11
-#define	R_SPARC_LO10		12
-#define	R_SPARC_GOT10		13
-#define	R_SPARC_GOT13		14
-#define	R_SPARC_GOT22		15
-#define	R_SPARC_PC10		16
-#define	R_SPARC_PC22		17
-#define	R_SPARC_WPLT30		18
-#define	R_SPARC_COPY		19
-#define	R_SPARC_GLOB_DAT	20
-#define	R_SPARC_JMP_SLOT	21
-#define	R_SPARC_RELATIVE	22
-#define	R_SPARC_UA32		23
-#define R_SPARC_PLT32		24
-#define R_SPARC_HIPLT22		25
-#define R_SPARC_LOPLT10		26
-#define R_SPARC_PCPLT32		27
-#define R_SPARC_PCPLT22		28
-#define R_SPARC_PCPLT10		29
-#define R_SPARC_10		30
-#define R_SPARC_11		31
-#define R_SPARC_64		32
-#define R_SPARC_OLO10		33
-#define R_SPARC_WDISP16		40
-#define R_SPARC_WDISP19		41
-#define R_SPARC_7		43
-#define R_SPARC_5		44
-#define R_SPARC_6		45
-
-/* Bits present in AT_HWCAP, primarily for Sparc32.  */
-
-#define HWCAP_SPARC_FLUSH       1    /* CPU supports flush instruction. */
-#define HWCAP_SPARC_STBAR       2
-#define HWCAP_SPARC_SWAP        4
-#define HWCAP_SPARC_MULDIV      8
-#define HWCAP_SPARC_V9		16
-#define HWCAP_SPARC_ULTRA3	32
-
-#define CORE_DUMP_USE_REGSET
-
-/* Format is:
- * 	G0 --> G7
- *	O0 --> O7
- *	L0 --> L7
- *	I0 --> I7
- *	PSR, PC, nPC, Y, WIM, TBR
- */
-typedef unsigned long elf_greg_t;
-#define ELF_NGREG 38
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-typedef struct {
-	union {
-		unsigned long	pr_regs[32];
-		double		pr_dregs[16];
-	} pr_fr;
-	unsigned long __unused;
-	unsigned long	pr_fsr;
-	unsigned char	pr_qcnt;
-	unsigned char	pr_q_entrysize;
-	unsigned char	pr_en;
-	unsigned int	pr_q[64];
-} elf_fpregset_t;
-
-#include <asm/mbus.h>
-
-/*
- * This is used to ensure we don't load something for the wrong architecture.
- */
-#define elf_check_arch(x) ((x)->e_machine == EM_SPARC)
-
-/*
- * These are used to set parameters in the core dumps.
- */
-#define ELF_ARCH	EM_SPARC
-#define ELF_CLASS	ELFCLASS32
-#define ELF_DATA	ELFDATA2MSB
-
-#define USE_ELF_CORE_DUMP
-#ifndef CONFIG_SUN4
-#define ELF_EXEC_PAGESIZE	4096
+#ifndef ___ASM_SPARC_ELF_H
+#define ___ASM_SPARC_ELF_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/elf_64.h>
 #else
-#define ELF_EXEC_PAGESIZE	8192
+#include <asm-sparc/elf_32.h>
 #endif
-
-
-/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
-   use of this is to invoke "./ld.so someprog" to test out a new version of
-   the loader.  We need to make sure that it is out of the way of the program
-   that it will "exec", and that there is sufficient room for the brk.  */
-
-#define ELF_ET_DYN_BASE         (TASK_UNMAPPED_BASE)
-
-/* This yields a mask that user programs can use to figure out what
-   instruction set this cpu supports.  This can NOT be done in userspace
-   on Sparc.  */
-
-/* Sun4c has none of the capabilities, most sun4m's have them all.
- * XXX This is gross, set some global variable at boot time. -DaveM
- */
-#define ELF_HWCAP	((ARCH_SUN4C_SUN4) ? 0 : \
-			 (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | \
-			  HWCAP_SPARC_SWAP | \
-			  ((srmmu_modtype != Cypress && \
-			    srmmu_modtype != Cypress_vE && \
-			    srmmu_modtype != Cypress_vD) ? \
-			   HWCAP_SPARC_MULDIV : 0)))
-
-/* This yields a string that ld.so will use to load implementation
-   specific libraries for optimization.  This is more specific in
-   intent than poking at uname or /proc/cpuinfo. */
-
-#define ELF_PLATFORM	(NULL)
-
-#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
-
-#endif /* !(__ASMSPARC_ELF_H) */
+#endif
diff --git a/include/asm-sparc/elf_32.h b/include/asm-sparc/elf_32.h
new file mode 100644
index 0000000..d043f80b
--- /dev/null
+++ b/include/asm-sparc/elf_32.h
@@ -0,0 +1,145 @@
+#ifndef __ASMSPARC_ELF_H
+#define __ASMSPARC_ELF_H
+
+/*
+ * ELF register definitions..
+ */
+
+#include <asm/ptrace.h>
+
+/*
+ * Sparc section types
+ */
+#define STT_REGISTER		13
+
+/*
+ * Sparc ELF relocation types
+ */
+#define	R_SPARC_NONE		0
+#define	R_SPARC_8		1
+#define	R_SPARC_16		2
+#define	R_SPARC_32		3
+#define	R_SPARC_DISP8		4
+#define	R_SPARC_DISP16		5
+#define	R_SPARC_DISP32		6
+#define	R_SPARC_WDISP30		7
+#define	R_SPARC_WDISP22		8
+#define	R_SPARC_HI22		9
+#define	R_SPARC_22		10
+#define	R_SPARC_13		11
+#define	R_SPARC_LO10		12
+#define	R_SPARC_GOT10		13
+#define	R_SPARC_GOT13		14
+#define	R_SPARC_GOT22		15
+#define	R_SPARC_PC10		16
+#define	R_SPARC_PC22		17
+#define	R_SPARC_WPLT30		18
+#define	R_SPARC_COPY		19
+#define	R_SPARC_GLOB_DAT	20
+#define	R_SPARC_JMP_SLOT	21
+#define	R_SPARC_RELATIVE	22
+#define	R_SPARC_UA32		23
+#define R_SPARC_PLT32		24
+#define R_SPARC_HIPLT22		25
+#define R_SPARC_LOPLT10		26
+#define R_SPARC_PCPLT32		27
+#define R_SPARC_PCPLT22		28
+#define R_SPARC_PCPLT10		29
+#define R_SPARC_10		30
+#define R_SPARC_11		31
+#define R_SPARC_64		32
+#define R_SPARC_OLO10		33
+#define R_SPARC_WDISP16		40
+#define R_SPARC_WDISP19		41
+#define R_SPARC_7		43
+#define R_SPARC_5		44
+#define R_SPARC_6		45
+
+/* Bits present in AT_HWCAP, primarily for Sparc32.  */
+
+#define HWCAP_SPARC_FLUSH       1    /* CPU supports flush instruction. */
+#define HWCAP_SPARC_STBAR       2
+#define HWCAP_SPARC_SWAP        4
+#define HWCAP_SPARC_MULDIV      8
+#define HWCAP_SPARC_V9		16
+#define HWCAP_SPARC_ULTRA3	32
+
+#define CORE_DUMP_USE_REGSET
+
+/* Format is:
+ * 	G0 --> G7
+ *	O0 --> O7
+ *	L0 --> L7
+ *	I0 --> I7
+ *	PSR, PC, nPC, Y, WIM, TBR
+ */
+typedef unsigned long elf_greg_t;
+#define ELF_NGREG 38
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct {
+	union {
+		unsigned long	pr_regs[32];
+		double		pr_dregs[16];
+	} pr_fr;
+	unsigned long __unused;
+	unsigned long	pr_fsr;
+	unsigned char	pr_qcnt;
+	unsigned char	pr_q_entrysize;
+	unsigned char	pr_en;
+	unsigned int	pr_q[64];
+} elf_fpregset_t;
+
+#include <asm/mbus.h>
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) ((x)->e_machine == EM_SPARC)
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_ARCH	EM_SPARC
+#define ELF_CLASS	ELFCLASS32
+#define ELF_DATA	ELFDATA2MSB
+
+#define USE_ELF_CORE_DUMP
+#ifndef CONFIG_SUN4
+#define ELF_EXEC_PAGESIZE	4096
+#else
+#define ELF_EXEC_PAGESIZE	8192
+#endif
+
+
+/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+   use of this is to invoke "./ld.so someprog" to test out a new version of
+   the loader.  We need to make sure that it is out of the way of the program
+   that it will "exec", and that there is sufficient room for the brk.  */
+
+#define ELF_ET_DYN_BASE         (TASK_UNMAPPED_BASE)
+
+/* This yields a mask that user programs can use to figure out what
+   instruction set this cpu supports.  This can NOT be done in userspace
+   on Sparc.  */
+
+/* Sun4c has none of the capabilities, most sun4m's have them all.
+ * XXX This is gross, set some global variable at boot time. -DaveM
+ */
+#define ELF_HWCAP	((ARCH_SUN4C_SUN4) ? 0 : \
+			 (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | \
+			  HWCAP_SPARC_SWAP | \
+			  ((srmmu_modtype != Cypress && \
+			    srmmu_modtype != Cypress_vE && \
+			    srmmu_modtype != Cypress_vD) ? \
+			   HWCAP_SPARC_MULDIV : 0)))
+
+/* This yields a string that ld.so will use to load implementation
+   specific libraries for optimization.  This is more specific in
+   intent than poking at uname or /proc/cpuinfo. */
+
+#define ELF_PLATFORM	(NULL)
+
+#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
+
+#endif /* !(__ASMSPARC_ELF_H) */
diff --git a/include/asm-sparc/elf_64.h b/include/asm-sparc/elf_64.h
new file mode 100644
index 0000000..0818a13
--- /dev/null
+++ b/include/asm-sparc/elf_64.h
@@ -0,0 +1,217 @@
+#ifndef __ASM_SPARC64_ELF_H
+#define __ASM_SPARC64_ELF_H
+
+/*
+ * ELF register definitions..
+ */
+
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/spitfire.h>
+
+/*
+ * Sparc section types
+ */
+#define STT_REGISTER		13
+
+/*
+ * Sparc ELF relocation types
+ */
+#define	R_SPARC_NONE		0
+#define	R_SPARC_8		1
+#define	R_SPARC_16		2
+#define	R_SPARC_32		3
+#define	R_SPARC_DISP8		4
+#define	R_SPARC_DISP16		5
+#define	R_SPARC_DISP32		6
+#define	R_SPARC_WDISP30		7
+#define	R_SPARC_WDISP22		8
+#define	R_SPARC_HI22		9
+#define	R_SPARC_22		10
+#define	R_SPARC_13		11
+#define	R_SPARC_LO10		12
+#define	R_SPARC_GOT10		13
+#define	R_SPARC_GOT13		14
+#define	R_SPARC_GOT22		15
+#define	R_SPARC_PC10		16
+#define	R_SPARC_PC22		17
+#define	R_SPARC_WPLT30		18
+#define	R_SPARC_COPY		19
+#define	R_SPARC_GLOB_DAT	20
+#define	R_SPARC_JMP_SLOT	21
+#define	R_SPARC_RELATIVE	22
+#define	R_SPARC_UA32		23
+#define R_SPARC_PLT32		24
+#define R_SPARC_HIPLT22		25
+#define R_SPARC_LOPLT10		26
+#define R_SPARC_PCPLT32		27
+#define R_SPARC_PCPLT22		28
+#define R_SPARC_PCPLT10		29
+#define R_SPARC_10		30
+#define R_SPARC_11		31
+#define R_SPARC_64		32
+#define R_SPARC_OLO10		33
+#define R_SPARC_WDISP16		40
+#define R_SPARC_WDISP19		41
+#define R_SPARC_7		43
+#define R_SPARC_5		44
+#define R_SPARC_6		45
+
+/* Bits present in AT_HWCAP, primarily for Sparc32.  */
+
+#define HWCAP_SPARC_FLUSH       1    /* CPU supports flush instruction. */
+#define HWCAP_SPARC_STBAR       2
+#define HWCAP_SPARC_SWAP        4
+#define HWCAP_SPARC_MULDIV      8
+#define HWCAP_SPARC_V9		16
+#define HWCAP_SPARC_ULTRA3	32
+#define HWCAP_SPARC_BLKINIT	64
+#define HWCAP_SPARC_N2		128
+
+#define CORE_DUMP_USE_REGSET
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_ARCH		EM_SPARCV9
+#define ELF_CLASS		ELFCLASS64
+#define ELF_DATA		ELFDATA2MSB
+
+/* Format of 64-bit elf_gregset_t is:
+ * 	G0 --> G7
+ * 	O0 --> O7
+ * 	L0 --> L7
+ * 	I0 --> I7
+ *	TSTATE
+ *	TPC
+ *	TNPC
+ *	Y
+ */
+typedef unsigned long elf_greg_t;
+#define ELF_NGREG 36
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct {
+	unsigned long	pr_regs[32];
+	unsigned long	pr_fsr;
+	unsigned long	pr_gsr;
+	unsigned long	pr_fprs;
+} elf_fpregset_t;
+
+/* Format of 32-bit elf_gregset_t is:
+ * 	G0 --> G7
+ *	O0 --> O7
+ *	L0 --> L7
+ *	I0 --> I7
+ *	PSR, PC, nPC, Y, WIM, TBR
+ */
+typedef unsigned int compat_elf_greg_t;
+#define COMPAT_ELF_NGREG 38
+typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG];
+
+typedef struct {
+	union {
+		unsigned int	pr_regs[32];
+		unsigned long	pr_dregs[16];
+	} pr_fr;
+	unsigned int __unused;
+	unsigned int	pr_fsr;
+	unsigned char	pr_qcnt;
+	unsigned char	pr_q_entrysize;
+	unsigned char	pr_en;
+	unsigned int	pr_q[64];
+} compat_elf_fpregset_t;
+
+/* UltraSparc extensions.  Still unused, but will be eventually.  */
+typedef struct {
+	unsigned int pr_type;
+	unsigned int pr_align;
+	union {
+		struct {
+			union {
+				unsigned int	pr_regs[32];
+				unsigned long	pr_dregs[16];
+				long double	pr_qregs[8];
+			} pr_xfr;
+		} pr_v8p;
+		unsigned int	pr_xfsr;
+		unsigned int	pr_fprs;
+		unsigned int	pr_xg[8];
+		unsigned int	pr_xo[8];
+		unsigned long	pr_tstate;
+		unsigned int	pr_filler[8];
+	} pr_un;
+} elf_xregset_t;
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x)		((x)->e_machine == ELF_ARCH)
+#define compat_elf_check_arch(x)	((x)->e_machine == EM_SPARC || \
+					 (x)->e_machine == EM_SPARC32PLUS)
+#define compat_start_thread		start_thread32
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE	PAGE_SIZE
+
+/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+   use of this is to invoke "./ld.so someprog" to test out a new version of
+   the loader.  We need to make sure that it is out of the way of the program
+   that it will "exec", and that there is sufficient room for the brk.  */
+
+#define ELF_ET_DYN_BASE		0x0000010000000000UL
+#define COMPAT_ELF_ET_DYN_BASE	0x0000000070000000UL
+
+
+/* This yields a mask that user programs can use to figure out what
+   instruction set this cpu supports.  */
+
+/* On Ultra, we support all of the v8 capabilities. */
+static inline unsigned int sparc64_elf_hwcap(void)
+{
+	unsigned int cap = (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR |
+			    HWCAP_SPARC_SWAP | HWCAP_SPARC_MULDIV |
+			    HWCAP_SPARC_V9);
+
+	if (tlb_type == cheetah || tlb_type == cheetah_plus)
+		cap |= HWCAP_SPARC_ULTRA3;
+	else if (tlb_type == hypervisor) {
+		if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 ||
+		    sun4v_chip_type == SUN4V_CHIP_NIAGARA2)
+			cap |= HWCAP_SPARC_BLKINIT;
+		if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2)
+			cap |= HWCAP_SPARC_N2;
+	}
+
+	return cap;
+}
+
+#define ELF_HWCAP	sparc64_elf_hwcap();
+
+/* This yields a string that ld.so will use to load implementation
+   specific libraries for optimization.  This is more specific in
+   intent than poking at uname or /proc/cpuinfo.  */
+
+#define ELF_PLATFORM	(NULL)
+
+#define SET_PERSONALITY(ex, ibcs2)			\
+do {	unsigned long new_flags = current_thread_info()->flags; \
+	new_flags &= _TIF_32BIT;			\
+	if ((ex).e_ident[EI_CLASS] == ELFCLASS32)	\
+		new_flags |= _TIF_32BIT;		\
+	else						\
+		new_flags &= ~_TIF_32BIT;		\
+	if ((current_thread_info()->flags & _TIF_32BIT) \
+	    != new_flags)				\
+		set_thread_flag(TIF_ABI_PENDING);	\
+	else						\
+		clear_thread_flag(TIF_ABI_PENDING);	\
+	/* flush_thread will update pgd cache */	\
+	if (ibcs2)					\
+		set_personality(PER_SVR4);		\
+	else if (current->personality != PER_LINUX32)	\
+		set_personality(PER_LINUX);		\
+} while (0)
+
+#endif /* !(__ASM_SPARC64_ELF_H) */
diff --git a/include/asm-sparc/envctrl.h b/include/asm-sparc/envctrl.h
new file mode 100644
index 0000000..624fa7e
--- /dev/null
+++ b/include/asm-sparc/envctrl.h
@@ -0,0 +1,103 @@
+/*
+ *
+ * envctrl.h: Definitions for access to the i2c environment
+ *            monitoring on Ultrasparc systems.
+ *
+ * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
+ * Copyright (C) 2000  Vinh Truong  (vinh.truong@eng.sun.com)
+ * VT - Add all ioctl commands and environment status definitions
+ * VT - Add application note
+ */
+#ifndef _SPARC64_ENVCTRL_H
+#define _SPARC64_ENVCTRL_H 1
+
+#include <linux/ioctl.h>
+
+/* Application note:
+ *
+ * The driver supports 4 operations: open(), close(), ioctl(), read()
+ * The device name is /dev/envctrl.
+ * Below is sample usage:
+ *
+ *	fd = open("/dev/envtrl", O_RDONLY);
+ *	if (ioctl(fd, ENVCTRL_READ_SHUTDOWN_TEMPERATURE, 0) < 0)
+ *		printf("error\n");
+ *	ret = read(fd, buf, 10);
+ *	close(fd);
+ *
+ * Notice in the case of cpu voltage and temperature, the default is
+ * cpu0.  If we need to know the info of cpu1, cpu2, cpu3, we need to
+ * pass in cpu number in ioctl() last parameter.  For example, to
+ * get the voltage of cpu2:
+ *
+ *	ioctlbuf[0] = 2;
+ *	if (ioctl(fd, ENVCTRL_READ_CPU_VOLTAGE, ioctlbuf) < 0)
+ *		printf("error\n");
+ *	ret = read(fd, buf, 10);
+ *
+ * All the return values are in ascii.  So check read return value
+ * and do appropriate conversions in your application.
+ */
+
+/* IOCTL commands */
+
+/* Note: these commands reflect possible monitor features.
+ * Some boards choose to support some of the features only.
+ */
+#define ENVCTRL_RD_CPU_TEMPERATURE	_IOR('p', 0x40, int)
+#define ENVCTRL_RD_CPU_VOLTAGE		_IOR('p', 0x41, int)
+#define ENVCTRL_RD_FAN_STATUS		_IOR('p', 0x42, int)
+#define ENVCTRL_RD_WARNING_TEMPERATURE	_IOR('p', 0x43, int)
+#define ENVCTRL_RD_SHUTDOWN_TEMPERATURE	_IOR('p', 0x44, int)
+#define ENVCTRL_RD_VOLTAGE_STATUS	_IOR('p', 0x45, int)
+#define ENVCTRL_RD_SCSI_TEMPERATURE	_IOR('p', 0x46, int)
+#define ENVCTRL_RD_ETHERNET_TEMPERATURE	_IOR('p', 0x47, int)
+#define ENVCTRL_RD_MTHRBD_TEMPERATURE	_IOR('p', 0x48, int)
+
+#define ENVCTRL_RD_GLOBALADDRESS	_IOR('p', 0x49, int)
+
+/* Read return values for a voltage status request. */
+#define ENVCTRL_VOLTAGE_POWERSUPPLY_GOOD	0x01
+#define ENVCTRL_VOLTAGE_BAD			0x02
+#define ENVCTRL_POWERSUPPLY_BAD			0x03
+#define ENVCTRL_VOLTAGE_POWERSUPPLY_BAD		0x04
+
+/* Read return values for a fan status request.
+ * A failure match means either the fan fails or
+ * the fan is not connected.  Some boards have optional
+ * connectors to connect extra fans.
+ *
+ * There are maximum 8 monitor fans.  Some are cpu fans
+ * some are system fans.  The mask below only indicates
+ * fan by order number.
+ * Below is a sample application:
+ *
+ *	if (ioctl(fd, ENVCTRL_READ_FAN_STATUS, 0) < 0) {
+ *		printf("ioctl fan failed\n");
+ *	}
+ *	if (read(fd, rslt, 1) <= 0) {
+ *		printf("error or fan not monitored\n");
+ *	} else {
+ *		if (rslt[0] == ENVCTRL_ALL_FANS_GOOD) {
+ *			printf("all fans good\n");
+ *	} else if (rslt[0] == ENVCTRL_ALL_FANS_BAD) {
+ *		printf("all fans bad\n");
+ *	} else {
+ *		if (rslt[0] & ENVCTRL_FAN0_FAILURE_MASK) {
+ *			printf("fan 0 failed or not connected\n");
+ *	}
+ *	......
+ */
+
+#define ENVCTRL_ALL_FANS_GOOD			0x00
+#define ENVCTRL_FAN0_FAILURE_MASK		0x01
+#define ENVCTRL_FAN1_FAILURE_MASK		0x02
+#define ENVCTRL_FAN2_FAILURE_MASK		0x04
+#define ENVCTRL_FAN3_FAILURE_MASK		0x08
+#define ENVCTRL_FAN4_FAILURE_MASK		0x10
+#define ENVCTRL_FAN5_FAILURE_MASK		0x20
+#define ENVCTRL_FAN6_FAILURE_MASK		0x40
+#define ENVCTRL_FAN7_FAILURE_MASK		0x80
+#define ENVCTRL_ALL_FANS_BAD 			0xFF
+
+#endif /* !(_SPARC64_ENVCTRL_H) */
diff --git a/include/asm-sparc/estate.h b/include/asm-sparc/estate.h
new file mode 100644
index 0000000..520c085
--- /dev/null
+++ b/include/asm-sparc/estate.h
@@ -0,0 +1,49 @@
+#ifndef _SPARC64_ESTATE_H
+#define _SPARC64_ESTATE_H
+
+/* UltraSPARC-III E-cache Error Enable */
+#define ESTATE_ERROR_FMT	0x0000000000040000 /* Force MTAG ECC		*/
+#define ESTATE_ERROR_FMESS	0x000000000003c000 /* Forced MTAG ECC val	*/
+#define ESTATE_ERROR_FMD	0x0000000000002000 /* Force DATA ECC		*/
+#define ESTATE_ERROR_FDECC	0x0000000000001ff0 /* Forced DATA ECC val	*/
+#define ESTATE_ERROR_UCEEN	0x0000000000000008 /* See below			*/
+#define ESTATE_ERROR_NCEEN	0x0000000000000002 /* See below			*/
+#define ESTATE_ERROR_CEEN	0x0000000000000001 /* See below			*/
+
+/* UCEEN enables the fast_ECC_error trap for: 1) software correctable E-cache
+ * errors 2) uncorrectable E-cache errors.  Such events only occur on reads
+ * of the E-cache by the local processor for: 1) data loads 2) instruction
+ * fetches 3) atomic operations.  Such events _cannot_ occur for: 1) merge
+ * 2) writeback 2) copyout.  The AFSR bits associated with these traps are
+ * UCC and UCU.
+ */
+
+/* NCEEN enables instruction_access_error, data_access_error, and ECC_error traps
+ * for uncorrectable ECC errors and system errors.
+ *
+ * Uncorrectable system bus data error or MTAG ECC error, system bus TimeOUT,
+ * or system bus BusERR:
+ * 1) As the result of an instruction fetch, will generate instruction_access_error
+ * 2) As the result of a load etc. will generate data_access_error.
+ * 3) As the result of store merge completion, writeback, or copyout will
+ *    generate a disrupting ECC_error trap.
+ * 4) As the result of such errors on instruction vector fetch can generate any
+ *    of the 3 trap types.
+ *
+ * The AFSR bits associated with these traps are EMU, EDU, WDU, CPU, IVU, UE,
+ * BERR, and TO.
+ */
+
+/* CEEN enables the ECC_error trap for hardware corrected ECC errors.  System bus
+ * reads resulting in a hardware corrected data or MTAG ECC error will generate an
+ * ECC_error disrupting trap with this bit enabled.
+ *
+ * This same trap will also be generated when a hardware corrected ECC error results
+ * during store merge, writeback, and copyout operations.
+ */
+
+/* In general, if the trap enable bits above are disabled the AFSR bits will still
+ * log the events even though the trap will not be generated by the processor.
+ */
+
+#endif /* _SPARC64_ESTATE_H */
diff --git a/include/asm-sparc/fbio.h b/include/asm-sparc/fbio.h
index c2b27e7..b9215a0 100644
--- a/include/asm-sparc/fbio.h
+++ b/include/asm-sparc/fbio.h
@@ -1,6 +1,9 @@
 #ifndef __LINUX_FBIO_H
 #define __LINUX_FBIO_H
 
+#include <linux/compiler.h>
+#include <linux/types.h>
+
 /* Constants used for fbio SunOS compatibility */
 /* (C) 1996 Miguel de Icaza */
 
@@ -38,6 +41,9 @@
 #define FBTYPE_PCI_IGA1682	23
 #define FBTYPE_P9100COLOR	24
 
+#define FBTYPE_PCI_GENERIC	1000
+#define FBTYPE_PCI_MACH64	1001
+
 /* fbio ioctls */
 /* Returned by FBIOGTYPE */
 struct  fbtype {
@@ -97,8 +103,8 @@
         struct fbcurpos hot;    /* cursor hot spot */
         struct fbcmap cmap;     /* color map info */
         struct fbcurpos size;   /* cursor bit map size */
-        char *image;            /* cursor image bits */
-        char *mask;             /* cursor mask bits */
+        char __user *image;     /* cursor image bits */
+        char __user *mask;      /* cursor mask bits */
 };
 
 /* set/get cursor attributes/shape */
@@ -294,4 +300,31 @@
 #define LEO_LD_GBL_MAP         0x01009000
 #define LEO_UNK2_MAP           0x0100a000
 
+#ifdef __KERNEL__
+struct  fbcmap32 {
+	int             index;          /* first element (0 origin) */
+	int             count;
+	u32		red;
+	u32		green;
+	u32		blue;
+};
+
+#define FBIOPUTCMAP32	_IOW('F', 3, struct fbcmap32)
+#define FBIOGETCMAP32	_IOW('F', 4, struct fbcmap32)
+
+struct fbcursor32 {
+	short set;		/* what to set, choose from the list above */
+	short enable;		/* cursor on/off */
+	struct fbcurpos pos;	/* cursor position */
+	struct fbcurpos hot;	/* cursor hot spot */
+	struct fbcmap32 cmap;	/* color map info */
+	struct fbcurpos size;	/* cursor bit map size */
+	u32	image;		/* cursor image bits */
+	u32	mask;		/* cursor mask bits */
+};
+
+#define FBIOSCURSOR32	_IOW('F', 24, struct fbcursor32)
+#define FBIOGCURSOR32	_IOW('F', 25, struct fbcursor32)
+#endif
+
 #endif /* __LINUX_FBIO_H */
diff --git a/include/asm-sparc/fcntl.h b/include/asm-sparc/fcntl.h
index 07bd2d8..d4d9c9d 100644
--- a/include/asm-sparc/fcntl.h
+++ b/include/asm-sparc/fcntl.h
@@ -10,7 +10,11 @@
 #define O_EXCL		0x0800	/* not fcntl */
 #define O_SYNC		0x2000
 #define O_NONBLOCK	0x4000
+#if defined(__sparc__) && defined(__arch64__)
+#define O_NDELAY	0x0004
+#else
 #define O_NDELAY	(0x0004 | O_NONBLOCK)
+#endif
 #define O_NOCTTY	0x8000	/* not fcntl */
 #define O_LARGEFILE	0x40000
 #define O_DIRECT        0x100000 /* direct disk access hint */
diff --git a/include/asm-sparc/fhc.h b/include/asm-sparc/fhc.h
new file mode 100644
index 0000000..788cbc4
--- /dev/null
+++ b/include/asm-sparc/fhc.h
@@ -0,0 +1,121 @@
+/*
+ * fhc.h: Structures for central/fhc pseudo driver on Sunfire/Starfire/Wildfire.
+ *
+ * Copyright (C) 1997, 1999 David S. Miller (davem@redhat.com)
+ */
+
+#ifndef _SPARC64_FHC_H
+#define _SPARC64_FHC_H
+
+#include <linux/timer.h>
+
+#include <asm/oplib.h>
+#include <asm/prom.h>
+#include <asm/upa.h>
+
+struct linux_fhc;
+
+/* Clock board register offsets. */
+#define CLOCK_CTRL	0x00UL	/* Main control */
+#define CLOCK_STAT1	0x10UL	/* Status one */
+#define CLOCK_STAT2	0x20UL	/* Status two */
+#define CLOCK_PWRSTAT	0x30UL	/* Power status */
+#define CLOCK_PWRPRES	0x40UL	/* Power presence */
+#define CLOCK_TEMP	0x50UL	/* Temperature */
+#define CLOCK_IRQDIAG	0x60UL	/* IRQ diagnostics */
+#define CLOCK_PWRSTAT2	0x70UL	/* Power status two */
+
+#define CLOCK_CTRL_LLED		0x04	/* Left LED, 0 == on */
+#define CLOCK_CTRL_MLED		0x02	/* Mid LED, 1 == on */
+#define CLOCK_CTRL_RLED		0x01	/* RIght LED, 1 == on */
+
+struct linux_central {
+	struct linux_fhc		*child;
+	unsigned long			cfreg;
+	unsigned long			clkregs;
+	unsigned long			clkver;
+	int				slots;
+	struct device_node		*prom_node;
+
+	struct linux_prom_ranges	central_ranges[PROMREG_MAX];
+	int				num_central_ranges;
+};
+
+/* Firehose controller register offsets */
+struct fhc_regs {
+	unsigned long			pregs;	/* FHC internal regs */
+#define FHC_PREGS_ID	0x00UL	/* FHC ID */
+#define  FHC_ID_VERS		0xf0000000 /* Version of this FHC		*/
+#define  FHC_ID_PARTID		0x0ffff000 /* Part ID code (0x0f9f == FHC)	*/
+#define  FHC_ID_MANUF		0x0000007e /* Manufacturer (0x3e == SUN's JEDEC)*/
+#define  FHC_ID_RESV		0x00000001 /* Read as one			*/
+#define FHC_PREGS_RCS	0x10UL	/* FHC Reset Control/Status Register */
+#define  FHC_RCS_POR		0x80000000 /* Last reset was a power cycle	*/
+#define  FHC_RCS_SPOR		0x40000000 /* Last reset was sw power on reset	*/
+#define  FHC_RCS_SXIR		0x20000000 /* Last reset was sw XIR reset	*/
+#define  FHC_RCS_BPOR		0x10000000 /* Last reset was due to POR button	*/
+#define  FHC_RCS_BXIR		0x08000000 /* Last reset was due to XIR button	*/
+#define  FHC_RCS_WEVENT		0x04000000 /* CPU reset was due to wakeup event	*/
+#define  FHC_RCS_CFATAL		0x02000000 /* Centerplane Fatal Error signalled	*/
+#define  FHC_RCS_FENAB		0x01000000 /* Fatal errors elicit system reset	*/
+#define FHC_PREGS_CTRL	0x20UL	/* FHC Control Register */
+#define  FHC_CONTROL_ICS	0x00100000 /* Ignore Centerplane Signals	*/
+#define  FHC_CONTROL_FRST	0x00080000 /* Fatal Error Reset Enable		*/
+#define  FHC_CONTROL_LFAT	0x00040000 /* AC/DC signalled a local error	*/
+#define  FHC_CONTROL_SLINE	0x00010000 /* Firmware Synchronization Line	*/
+#define  FHC_CONTROL_DCD	0x00008000 /* DC-->DC Converter Disable		*/
+#define  FHC_CONTROL_POFF	0x00004000 /* AC/DC Controller PLL Disable	*/
+#define  FHC_CONTROL_FOFF	0x00002000 /* FHC Controller PLL Disable	*/
+#define  FHC_CONTROL_AOFF	0x00001000 /* CPU A SRAM/SBD Low Power Mode	*/
+#define  FHC_CONTROL_BOFF	0x00000800 /* CPU B SRAM/SBD Low Power Mode	*/
+#define  FHC_CONTROL_PSOFF	0x00000400 /* Turns off this FHC's power supply	*/
+#define  FHC_CONTROL_IXIST	0x00000200 /* 0=FHC tells clock board it exists	*/
+#define  FHC_CONTROL_XMSTR	0x00000100 /* 1=Causes this FHC to be XIR master*/
+#define  FHC_CONTROL_LLED	0x00000040 /* 0=Left LED ON			*/
+#define  FHC_CONTROL_MLED	0x00000020 /* 1=Middle LED ON			*/
+#define  FHC_CONTROL_RLED	0x00000010 /* 1=Right LED			*/
+#define  FHC_CONTROL_BPINS	0x00000003 /* Spare Bidirectional Pins		*/
+#define FHC_PREGS_BSR	0x30UL	/* FHC Board Status Register */
+#define  FHC_BSR_DA64		0x00040000 /* Port A: 0=128bit 1=64bit data path */
+#define  FHC_BSR_DB64		0x00020000 /* Port B: 0=128bit 1=64bit data path */
+#define  FHC_BSR_BID		0x0001e000 /* Board ID                           */
+#define  FHC_BSR_SA		0x00001c00 /* Port A UPA Speed (from the pins)   */
+#define  FHC_BSR_SB		0x00000380 /* Port B UPA Speed (from the pins)   */
+#define  FHC_BSR_NDIAG		0x00000040 /* Not in Diag Mode                   */
+#define  FHC_BSR_NTBED		0x00000020 /* Not in TestBED Mode                */
+#define  FHC_BSR_NIA		0x0000001c /* Jumper, bit 18 in PROM space       */
+#define  FHC_BSR_SI		0x00000001 /* Spare input pin value              */
+#define FHC_PREGS_ECC	0x40UL	/* FHC ECC Control Register (16 bits) */
+#define FHC_PREGS_JCTRL	0xf0UL	/* FHC JTAG Control Register */
+#define  FHC_JTAG_CTRL_MENAB	0x80000000 /* Indicates this is JTAG Master	 */
+#define  FHC_JTAG_CTRL_MNONE	0x40000000 /* Indicates no JTAG Master present	 */
+#define FHC_PREGS_JCMD	0x100UL	/* FHC JTAG Command Register */
+	unsigned long			ireg;	/* FHC IGN reg */
+#define FHC_IREG_IGN	0x00UL	/* This FHC's IGN */
+	unsigned long			ffregs;	/* FHC fanfail regs */
+#define FHC_FFREGS_IMAP	0x00UL	/* FHC Fanfail IMAP */
+#define FHC_FFREGS_ICLR	0x10UL	/* FHC Fanfail ICLR */
+	unsigned long			sregs;	/* FHC system regs */
+#define FHC_SREGS_IMAP	0x00UL	/* FHC System IMAP */
+#define FHC_SREGS_ICLR	0x10UL	/* FHC System ICLR */
+	unsigned long			uregs;	/* FHC uart regs */
+#define FHC_UREGS_IMAP	0x00UL	/* FHC Uart IMAP */
+#define FHC_UREGS_ICLR	0x10UL	/* FHC Uart ICLR */
+	unsigned long			tregs;	/* FHC TOD regs */
+#define FHC_TREGS_IMAP	0x00UL	/* FHC TOD IMAP */
+#define FHC_TREGS_ICLR	0x10UL	/* FHC TOD ICLR */
+};
+
+struct linux_fhc {
+	struct linux_fhc		*next;
+	struct linux_central		*parent;	/* NULL if not central FHC */
+	struct fhc_regs			fhc_regs;
+	int				board;
+	int				jtag_master;
+	struct device_node		*prom_node;
+
+	struct linux_prom_ranges	fhc_ranges[PROMREG_MAX];
+	int				num_fhc_ranges;
+};
+
+#endif /* !(_SPARC64_FHC_H) */
diff --git a/include/asm-sparc/floppy.h b/include/asm-sparc/floppy.h
index d3978e0..6c628ba 100644
--- a/include/asm-sparc/floppy.h
+++ b/include/asm-sparc/floppy.h
@@ -1,388 +1,8 @@
-/* asm-sparc/floppy.h: Sparc specific parts of the Floppy driver.
- *
- * Copyright (C) 1995 David S. Miller (davem@davemloft.net)
- */
-
-#ifndef __ASM_SPARC_FLOPPY_H
-#define __ASM_SPARC_FLOPPY_H
-
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/idprom.h>
-#include <asm/machines.h>
-#include <asm/oplib.h>
-#include <asm/auxio.h>
-#include <asm/irq.h>
-
-/* We don't need no stinkin' I/O port allocation crap. */
-#undef release_region
-#undef request_region
-#define release_region(X, Y)	do { } while(0)
-#define request_region(X, Y, Z)	(1)
-
-/* References:
- * 1) Netbsd Sun floppy driver.
- * 2) NCR 82077 controller manual
- * 3) Intel 82077 controller manual
- */
-struct sun_flpy_controller {
-	volatile unsigned char status_82072;  /* Main Status reg. */
-#define dcr_82072              status_82072   /* Digital Control reg. */
-#define status1_82077          status_82072   /* Auxiliary Status reg. 1 */
-
-	volatile unsigned char data_82072;    /* Data fifo. */
-#define status2_82077          data_82072     /* Auxiliary Status reg. 2 */
-
-	volatile unsigned char dor_82077;     /* Digital Output reg. */
-	volatile unsigned char tapectl_82077; /* What the? Tape control reg? */
-
-	volatile unsigned char status_82077;  /* Main Status Register. */
-#define drs_82077              status_82077   /* Digital Rate Select reg. */
-
-	volatile unsigned char data_82077;    /* Data fifo. */
-	volatile unsigned char ___unused;
-	volatile unsigned char dir_82077;     /* Digital Input reg. */
-#define dcr_82077              dir_82077      /* Config Control reg. */
-};
-
-/* You'll only ever find one controller on a SparcStation anyways. */
-static struct sun_flpy_controller *sun_fdc = NULL;
-extern volatile unsigned char *fdc_status;
-
-struct sun_floppy_ops {
-	unsigned char (*fd_inb)(int port);
-	void (*fd_outb)(unsigned char value, int port);
-};
-
-static struct sun_floppy_ops sun_fdops;
-
-#define fd_inb(port)              sun_fdops.fd_inb(port)
-#define fd_outb(value,port)       sun_fdops.fd_outb(value,port)
-#define fd_enable_dma()           sun_fd_enable_dma()
-#define fd_disable_dma()          sun_fd_disable_dma()
-#define fd_request_dma()          (0) /* nothing... */
-#define fd_free_dma()             /* nothing... */
-#define fd_clear_dma_ff()         /* nothing... */
-#define fd_set_dma_mode(mode)     sun_fd_set_dma_mode(mode)
-#define fd_set_dma_addr(addr)     sun_fd_set_dma_addr(addr)
-#define fd_set_dma_count(count)   sun_fd_set_dma_count(count)
-#define fd_enable_irq()           /* nothing... */
-#define fd_disable_irq()          /* nothing... */
-#define fd_cacheflush(addr, size) /* nothing... */
-#define fd_request_irq()          sun_fd_request_irq()
-#define fd_free_irq()             /* nothing... */
-#if 0  /* P3: added by Alain, these cause a MMU corruption. 19960524 XXX */
-#define fd_dma_mem_alloc(size)    ((unsigned long) vmalloc(size))
-#define fd_dma_mem_free(addr,size) (vfree((void *)(addr)))
+#ifndef ___ASM_SPARC_FLOPPY_H
+#define ___ASM_SPARC_FLOPPY_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/floppy_64.h>
+#else
+#include <asm-sparc/floppy_32.h>
 #endif
-
-/* XXX This isn't really correct. XXX */
-#define get_dma_residue(x)        (0)
-
-#define FLOPPY0_TYPE  4
-#define FLOPPY1_TYPE  0
-
-/* Super paranoid... */
-#undef HAVE_DISABLE_HLT
-
-/* Here is where we catch the floppy driver trying to initialize,
- * therefore this is where we call the PROM device tree probing
- * routine etc. on the Sparc.
- */
-#define FDC1                      sun_floppy_init()
-
-#define N_FDC    1
-#define N_DRIVE  8
-
-/* No 64k boundary crossing problems on the Sparc. */
-#define CROSS_64KB(a,s) (0)
-
-/* Routines unique to each controller type on a Sun. */
-static void sun_set_dor(unsigned char value, int fdc_82077)
-{
-	if (sparc_cpu_model == sun4c) {
-		unsigned int bits = 0;
-		if (value & 0x10)
-			bits |= AUXIO_FLPY_DSEL;
-		if ((value & 0x80) == 0)
-			bits |= AUXIO_FLPY_EJCT;
-		set_auxio(bits, (~bits) & (AUXIO_FLPY_DSEL|AUXIO_FLPY_EJCT));
-	}
-	if (fdc_82077) {
-		sun_fdc->dor_82077 = value;
-	}
-}
-
-static unsigned char sun_read_dir(void)
-{
-	if (sparc_cpu_model == sun4c)
-		return (get_auxio() & AUXIO_FLPY_DCHG) ? 0x80 : 0;
-	else
-		return sun_fdc->dir_82077;
-}
-
-static unsigned char sun_82072_fd_inb(int port)
-{
-	udelay(5);
-	switch(port & 7) {
-	default:
-		printk("floppy: Asked to read unknown port %d\n", port);
-		panic("floppy: Port bolixed.");
-	case 4: /* FD_STATUS */
-		return sun_fdc->status_82072 & ~STATUS_DMA;
-	case 5: /* FD_DATA */
-		return sun_fdc->data_82072;
-	case 7: /* FD_DIR */
-		return sun_read_dir();
-	};
-	panic("sun_82072_fd_inb: How did I get here?");
-}
-
-static void sun_82072_fd_outb(unsigned char value, int port)
-{
-	udelay(5);
-	switch(port & 7) {
-	default:
-		printk("floppy: Asked to write to unknown port %d\n", port);
-		panic("floppy: Port bolixed.");
-	case 2: /* FD_DOR */
-		sun_set_dor(value, 0);
-		break;
-	case 5: /* FD_DATA */
-		sun_fdc->data_82072 = value;
-		break;
-	case 7: /* FD_DCR */
-		sun_fdc->dcr_82072 = value;
-		break;
-	case 4: /* FD_STATUS */
-		sun_fdc->status_82072 = value;
-		break;
-	};
-	return;
-}
-
-static unsigned char sun_82077_fd_inb(int port)
-{
-	udelay(5);
-	switch(port & 7) {
-	default:
-		printk("floppy: Asked to read unknown port %d\n", port);
-		panic("floppy: Port bolixed.");
-	case 0: /* FD_STATUS_0 */
-		return sun_fdc->status1_82077;
-	case 1: /* FD_STATUS_1 */
-		return sun_fdc->status2_82077;
-	case 2: /* FD_DOR */
-		return sun_fdc->dor_82077;
-	case 3: /* FD_TDR */
-		return sun_fdc->tapectl_82077;
-	case 4: /* FD_STATUS */
-		return sun_fdc->status_82077 & ~STATUS_DMA;
-	case 5: /* FD_DATA */
-		return sun_fdc->data_82077;
-	case 7: /* FD_DIR */
-		return sun_read_dir();
-	};
-	panic("sun_82077_fd_inb: How did I get here?");
-}
-
-static void sun_82077_fd_outb(unsigned char value, int port)
-{
-	udelay(5);
-	switch(port & 7) {
-	default:
-		printk("floppy: Asked to write to unknown port %d\n", port);
-		panic("floppy: Port bolixed.");
-	case 2: /* FD_DOR */
-		sun_set_dor(value, 1);
-		break;
-	case 5: /* FD_DATA */
-		sun_fdc->data_82077 = value;
-		break;
-	case 7: /* FD_DCR */
-		sun_fdc->dcr_82077 = value;
-		break;
-	case 4: /* FD_STATUS */
-		sun_fdc->status_82077 = value;
-		break;
-	case 3: /* FD_TDR */
-		sun_fdc->tapectl_82077 = value;
-		break;
-	};
-	return;
-}
-
-/* For pseudo-dma (Sun floppy drives have no real DMA available to
- * them so we must eat the data fifo bytes directly ourselves) we have
- * three state variables.  doing_pdma tells our inline low-level
- * assembly floppy interrupt entry point whether it should sit and eat
- * bytes from the fifo or just transfer control up to the higher level
- * floppy interrupt c-code.  I tried very hard but I could not get the
- * pseudo-dma to work in c-code without getting many overruns and
- * underruns.  If non-zero, doing_pdma encodes the direction of
- * the transfer for debugging.  1=read 2=write
- */
-extern char *pdma_vaddr;
-extern unsigned long pdma_size;
-extern volatile int doing_pdma;
-
-/* This is software state */
-extern char *pdma_base;
-extern unsigned long pdma_areasize;
-
-/* Common routines to all controller types on the Sparc. */
-static inline void virtual_dma_init(void)
-{
-	/* nothing... */
-}
-
-static inline void sun_fd_disable_dma(void)
-{
-	doing_pdma = 0;
-	if (pdma_base) {
-		mmu_unlockarea(pdma_base, pdma_areasize);
-		pdma_base = NULL;
-	}
-}
-
-static inline void sun_fd_set_dma_mode(int mode)
-{
-	switch(mode) {
-	case DMA_MODE_READ:
-		doing_pdma = 1;
-		break;
-	case DMA_MODE_WRITE:
-		doing_pdma = 2;
-		break;
-	default:
-		printk("Unknown dma mode %d\n", mode);
-		panic("floppy: Giving up...");
-	}
-}
-
-static inline void sun_fd_set_dma_addr(char *buffer)
-{
-	pdma_vaddr = buffer;
-}
-
-static inline void sun_fd_set_dma_count(int length)
-{
-	pdma_size = length;
-}
-
-static inline void sun_fd_enable_dma(void)
-{
-	pdma_vaddr = mmu_lockarea(pdma_vaddr, pdma_size);
-	pdma_base = pdma_vaddr;
-	pdma_areasize = pdma_size;
-}
-
-/* Our low-level entry point in arch/sparc/kernel/entry.S */
-extern int sparc_floppy_request_irq(int irq, unsigned long flags,
-				    irq_handler_t irq_handler);
-
-static int sun_fd_request_irq(void)
-{
-	static int once = 0;
-	int error;
-
-	if(!once) {
-		once = 1;
-		error = sparc_floppy_request_irq(FLOPPY_IRQ,
-						 IRQF_DISABLED,
-						 floppy_interrupt);
-		return ((error == 0) ? 0 : -1);
-	} else return 0;
-}
-
-static struct linux_prom_registers fd_regs[2];
-
-static int sun_floppy_init(void)
-{
-	char state[128];
-	int tnode, fd_node, num_regs;
-	struct resource r;
-
-	use_virtual_dma = 1;
-	
-	FLOPPY_IRQ = 11;
-	/* Forget it if we aren't on a machine that could possibly
-	 * ever have a floppy drive.
-	 */
-	if((sparc_cpu_model != sun4c && sparc_cpu_model != sun4m) ||
-	   ((idprom->id_machtype == (SM_SUN4C | SM_4C_SLC)) ||
-	    (idprom->id_machtype == (SM_SUN4C | SM_4C_ELC)))) {
-		/* We certainly don't have a floppy controller. */
-		goto no_sun_fdc;
-	}
-	/* Well, try to find one. */
-	tnode = prom_getchild(prom_root_node);
-	fd_node = prom_searchsiblings(tnode, "obio");
-	if(fd_node != 0) {
-		tnode = prom_getchild(fd_node);
-		fd_node = prom_searchsiblings(tnode, "SUNW,fdtwo");
-	} else {
-		fd_node = prom_searchsiblings(tnode, "fd");
-	}
-	if(fd_node == 0) {
-		goto no_sun_fdc;
-	}
-
-	/* The sun4m lets us know if the controller is actually usable. */
-	if(sparc_cpu_model == sun4m &&
-	   prom_getproperty(fd_node, "status", state, sizeof(state)) != -1) {
-		if(!strcmp(state, "disabled")) {
-			goto no_sun_fdc;
-		}
-	}
-	num_regs = prom_getproperty(fd_node, "reg", (char *) fd_regs, sizeof(fd_regs));
-	num_regs = (num_regs / sizeof(fd_regs[0]));
-	prom_apply_obio_ranges(fd_regs, num_regs);
-	memset(&r, 0, sizeof(r));
-	r.flags = fd_regs[0].which_io;
-	r.start = fd_regs[0].phys_addr;
-	sun_fdc = (struct sun_flpy_controller *)
-	    sbus_ioremap(&r, 0, fd_regs[0].reg_size, "floppy");
-
-	/* Last minute sanity check... */
-	if(sun_fdc->status_82072 == 0xff) {
-		sun_fdc = NULL;
-		goto no_sun_fdc;
-	}
-
-	sun_fdops.fd_inb = sun_82077_fd_inb;
-	sun_fdops.fd_outb = sun_82077_fd_outb;
-	fdc_status = &sun_fdc->status_82077;
-
-	if (sun_fdc->dor_82077 == 0x80) {
-		sun_fdc->dor_82077 = 0x02;
-		if (sun_fdc->dor_82077 == 0x80) {
-			sun_fdops.fd_inb = sun_82072_fd_inb;
-			sun_fdops.fd_outb = sun_82072_fd_outb;
-			fdc_status = &sun_fdc->status_82072;
-		}
-	}
-
-	/* Success... */
-	allowed_drive_mask = 0x01;
-	return (int) sun_fdc;
-
-no_sun_fdc:
-	return -1;
-}
-
-static int sparc_eject(void)
-{
-	set_dor(0x00, 0xff, 0x90);
-	udelay(500);
-	set_dor(0x00, 0x6f, 0x00);
-	udelay(500);
-	return 0;
-}
-
-#define fd_eject(drive) sparc_eject()
-
-#define EXTRA_FLOPPY_PARAMS
-
-#endif /* !(__ASM_SPARC_FLOPPY_H) */
+#endif
diff --git a/include/asm-sparc/floppy_32.h b/include/asm-sparc/floppy_32.h
new file mode 100644
index 0000000..acdd06e
--- /dev/null
+++ b/include/asm-sparc/floppy_32.h
@@ -0,0 +1,388 @@
+/* asm-sparc/floppy.h: Sparc specific parts of the Floppy driver.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@davemloft.net)
+ */
+
+#ifndef __ASM_SPARC_FLOPPY_H
+#define __ASM_SPARC_FLOPPY_H
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/idprom.h>
+#include <asm/machines.h>
+#include <asm/oplib.h>
+#include <asm/auxio.h>
+#include <asm/irq.h>
+
+/* We don't need no stinkin' I/O port allocation crap. */
+#undef release_region
+#undef request_region
+#define release_region(X, Y)	do { } while(0)
+#define request_region(X, Y, Z)	(1)
+
+/* References:
+ * 1) Netbsd Sun floppy driver.
+ * 2) NCR 82077 controller manual
+ * 3) Intel 82077 controller manual
+ */
+struct sun_flpy_controller {
+	volatile unsigned char status_82072;  /* Main Status reg. */
+#define dcr_82072              status_82072   /* Digital Control reg. */
+#define status1_82077          status_82072   /* Auxiliary Status reg. 1 */
+
+	volatile unsigned char data_82072;    /* Data fifo. */
+#define status2_82077          data_82072     /* Auxiliary Status reg. 2 */
+
+	volatile unsigned char dor_82077;     /* Digital Output reg. */
+	volatile unsigned char tapectl_82077; /* What the? Tape control reg? */
+
+	volatile unsigned char status_82077;  /* Main Status Register. */
+#define drs_82077              status_82077   /* Digital Rate Select reg. */
+
+	volatile unsigned char data_82077;    /* Data fifo. */
+	volatile unsigned char ___unused;
+	volatile unsigned char dir_82077;     /* Digital Input reg. */
+#define dcr_82077              dir_82077      /* Config Control reg. */
+};
+
+/* You'll only ever find one controller on a SparcStation anyways. */
+static struct sun_flpy_controller *sun_fdc = NULL;
+extern volatile unsigned char *fdc_status;
+
+struct sun_floppy_ops {
+	unsigned char (*fd_inb)(int port);
+	void (*fd_outb)(unsigned char value, int port);
+};
+
+static struct sun_floppy_ops sun_fdops;
+
+#define fd_inb(port)              sun_fdops.fd_inb(port)
+#define fd_outb(value,port)       sun_fdops.fd_outb(value,port)
+#define fd_enable_dma()           sun_fd_enable_dma()
+#define fd_disable_dma()          sun_fd_disable_dma()
+#define fd_request_dma()          (0) /* nothing... */
+#define fd_free_dma()             /* nothing... */
+#define fd_clear_dma_ff()         /* nothing... */
+#define fd_set_dma_mode(mode)     sun_fd_set_dma_mode(mode)
+#define fd_set_dma_addr(addr)     sun_fd_set_dma_addr(addr)
+#define fd_set_dma_count(count)   sun_fd_set_dma_count(count)
+#define fd_enable_irq()           /* nothing... */
+#define fd_disable_irq()          /* nothing... */
+#define fd_cacheflush(addr, size) /* nothing... */
+#define fd_request_irq()          sun_fd_request_irq()
+#define fd_free_irq()             /* nothing... */
+#if 0  /* P3: added by Alain, these cause a MMU corruption. 19960524 XXX */
+#define fd_dma_mem_alloc(size)    ((unsigned long) vmalloc(size))
+#define fd_dma_mem_free(addr,size) (vfree((void *)(addr)))
+#endif
+
+/* XXX This isn't really correct. XXX */
+#define get_dma_residue(x)        (0)
+
+#define FLOPPY0_TYPE  4
+#define FLOPPY1_TYPE  0
+
+/* Super paranoid... */
+#undef HAVE_DISABLE_HLT
+
+/* Here is where we catch the floppy driver trying to initialize,
+ * therefore this is where we call the PROM device tree probing
+ * routine etc. on the Sparc.
+ */
+#define FDC1                      sun_floppy_init()
+
+#define N_FDC    1
+#define N_DRIVE  8
+
+/* No 64k boundary crossing problems on the Sparc. */
+#define CROSS_64KB(a,s) (0)
+
+/* Routines unique to each controller type on a Sun. */
+static void sun_set_dor(unsigned char value, int fdc_82077)
+{
+	if (sparc_cpu_model == sun4c) {
+		unsigned int bits = 0;
+		if (value & 0x10)
+			bits |= AUXIO_FLPY_DSEL;
+		if ((value & 0x80) == 0)
+			bits |= AUXIO_FLPY_EJCT;
+		set_auxio(bits, (~bits) & (AUXIO_FLPY_DSEL|AUXIO_FLPY_EJCT));
+	}
+	if (fdc_82077) {
+		sun_fdc->dor_82077 = value;
+	}
+}
+
+static unsigned char sun_read_dir(void)
+{
+	if (sparc_cpu_model == sun4c)
+		return (get_auxio() & AUXIO_FLPY_DCHG) ? 0x80 : 0;
+	else
+		return sun_fdc->dir_82077;
+}
+
+static unsigned char sun_82072_fd_inb(int port)
+{
+	udelay(5);
+	switch(port & 7) {
+	default:
+		printk("floppy: Asked to read unknown port %d\n", port);
+		panic("floppy: Port bolixed.");
+	case 4: /* FD_STATUS */
+		return sun_fdc->status_82072 & ~STATUS_DMA;
+	case 5: /* FD_DATA */
+		return sun_fdc->data_82072;
+	case 7: /* FD_DIR */
+		return sun_read_dir();
+	};
+	panic("sun_82072_fd_inb: How did I get here?");
+}
+
+static void sun_82072_fd_outb(unsigned char value, int port)
+{
+	udelay(5);
+	switch(port & 7) {
+	default:
+		printk("floppy: Asked to write to unknown port %d\n", port);
+		panic("floppy: Port bolixed.");
+	case 2: /* FD_DOR */
+		sun_set_dor(value, 0);
+		break;
+	case 5: /* FD_DATA */
+		sun_fdc->data_82072 = value;
+		break;
+	case 7: /* FD_DCR */
+		sun_fdc->dcr_82072 = value;
+		break;
+	case 4: /* FD_STATUS */
+		sun_fdc->status_82072 = value;
+		break;
+	};
+	return;
+}
+
+static unsigned char sun_82077_fd_inb(int port)
+{
+	udelay(5);
+	switch(port & 7) {
+	default:
+		printk("floppy: Asked to read unknown port %d\n", port);
+		panic("floppy: Port bolixed.");
+	case 0: /* FD_STATUS_0 */
+		return sun_fdc->status1_82077;
+	case 1: /* FD_STATUS_1 */
+		return sun_fdc->status2_82077;
+	case 2: /* FD_DOR */
+		return sun_fdc->dor_82077;
+	case 3: /* FD_TDR */
+		return sun_fdc->tapectl_82077;
+	case 4: /* FD_STATUS */
+		return sun_fdc->status_82077 & ~STATUS_DMA;
+	case 5: /* FD_DATA */
+		return sun_fdc->data_82077;
+	case 7: /* FD_DIR */
+		return sun_read_dir();
+	};
+	panic("sun_82077_fd_inb: How did I get here?");
+}
+
+static void sun_82077_fd_outb(unsigned char value, int port)
+{
+	udelay(5);
+	switch(port & 7) {
+	default:
+		printk("floppy: Asked to write to unknown port %d\n", port);
+		panic("floppy: Port bolixed.");
+	case 2: /* FD_DOR */
+		sun_set_dor(value, 1);
+		break;
+	case 5: /* FD_DATA */
+		sun_fdc->data_82077 = value;
+		break;
+	case 7: /* FD_DCR */
+		sun_fdc->dcr_82077 = value;
+		break;
+	case 4: /* FD_STATUS */
+		sun_fdc->status_82077 = value;
+		break;
+	case 3: /* FD_TDR */
+		sun_fdc->tapectl_82077 = value;
+		break;
+	};
+	return;
+}
+
+/* For pseudo-dma (Sun floppy drives have no real DMA available to
+ * them so we must eat the data fifo bytes directly ourselves) we have
+ * three state variables.  doing_pdma tells our inline low-level
+ * assembly floppy interrupt entry point whether it should sit and eat
+ * bytes from the fifo or just transfer control up to the higher level
+ * floppy interrupt c-code.  I tried very hard but I could not get the
+ * pseudo-dma to work in c-code without getting many overruns and
+ * underruns.  If non-zero, doing_pdma encodes the direction of
+ * the transfer for debugging.  1=read 2=write
+ */
+extern char *pdma_vaddr;
+extern unsigned long pdma_size;
+extern volatile int doing_pdma;
+
+/* This is software state */
+extern char *pdma_base;
+extern unsigned long pdma_areasize;
+
+/* Common routines to all controller types on the Sparc. */
+static inline void virtual_dma_init(void)
+{
+	/* nothing... */
+}
+
+static inline void sun_fd_disable_dma(void)
+{
+	doing_pdma = 0;
+	if (pdma_base) {
+		mmu_unlockarea(pdma_base, pdma_areasize);
+		pdma_base = NULL;
+	}
+}
+
+static inline void sun_fd_set_dma_mode(int mode)
+{
+	switch(mode) {
+	case DMA_MODE_READ:
+		doing_pdma = 1;
+		break;
+	case DMA_MODE_WRITE:
+		doing_pdma = 2;
+		break;
+	default:
+		printk("Unknown dma mode %d\n", mode);
+		panic("floppy: Giving up...");
+	}
+}
+
+static inline void sun_fd_set_dma_addr(char *buffer)
+{
+	pdma_vaddr = buffer;
+}
+
+static inline void sun_fd_set_dma_count(int length)
+{
+	pdma_size = length;
+}
+
+static inline void sun_fd_enable_dma(void)
+{
+	pdma_vaddr = mmu_lockarea(pdma_vaddr, pdma_size);
+	pdma_base = pdma_vaddr;
+	pdma_areasize = pdma_size;
+}
+
+/* Our low-level entry point in arch/sparc/kernel/entry.S */
+extern int sparc_floppy_request_irq(int irq, unsigned long flags,
+				    irq_handler_t irq_handler);
+
+static int sun_fd_request_irq(void)
+{
+	static int once = 0;
+	int error;
+
+	if(!once) {
+		once = 1;
+		error = sparc_floppy_request_irq(FLOPPY_IRQ,
+						 IRQF_DISABLED,
+						 floppy_interrupt);
+		return ((error == 0) ? 0 : -1);
+	} else return 0;
+}
+
+static struct linux_prom_registers fd_regs[2];
+
+static int sun_floppy_init(void)
+{
+	char state[128];
+	int tnode, fd_node, num_regs;
+	struct resource r;
+
+	use_virtual_dma = 1;
+
+	FLOPPY_IRQ = 11;
+	/* Forget it if we aren't on a machine that could possibly
+	 * ever have a floppy drive.
+	 */
+	if((sparc_cpu_model != sun4c && sparc_cpu_model != sun4m) ||
+	   ((idprom->id_machtype == (SM_SUN4C | SM_4C_SLC)) ||
+	    (idprom->id_machtype == (SM_SUN4C | SM_4C_ELC)))) {
+		/* We certainly don't have a floppy controller. */
+		goto no_sun_fdc;
+	}
+	/* Well, try to find one. */
+	tnode = prom_getchild(prom_root_node);
+	fd_node = prom_searchsiblings(tnode, "obio");
+	if(fd_node != 0) {
+		tnode = prom_getchild(fd_node);
+		fd_node = prom_searchsiblings(tnode, "SUNW,fdtwo");
+	} else {
+		fd_node = prom_searchsiblings(tnode, "fd");
+	}
+	if(fd_node == 0) {
+		goto no_sun_fdc;
+	}
+
+	/* The sun4m lets us know if the controller is actually usable. */
+	if(sparc_cpu_model == sun4m &&
+	   prom_getproperty(fd_node, "status", state, sizeof(state)) != -1) {
+		if(!strcmp(state, "disabled")) {
+			goto no_sun_fdc;
+		}
+	}
+	num_regs = prom_getproperty(fd_node, "reg", (char *) fd_regs, sizeof(fd_regs));
+	num_regs = (num_regs / sizeof(fd_regs[0]));
+	prom_apply_obio_ranges(fd_regs, num_regs);
+	memset(&r, 0, sizeof(r));
+	r.flags = fd_regs[0].which_io;
+	r.start = fd_regs[0].phys_addr;
+	sun_fdc = (struct sun_flpy_controller *)
+	    sbus_ioremap(&r, 0, fd_regs[0].reg_size, "floppy");
+
+	/* Last minute sanity check... */
+	if(sun_fdc->status_82072 == 0xff) {
+		sun_fdc = NULL;
+		goto no_sun_fdc;
+	}
+
+	sun_fdops.fd_inb = sun_82077_fd_inb;
+	sun_fdops.fd_outb = sun_82077_fd_outb;
+	fdc_status = &sun_fdc->status_82077;
+
+	if (sun_fdc->dor_82077 == 0x80) {
+		sun_fdc->dor_82077 = 0x02;
+		if (sun_fdc->dor_82077 == 0x80) {
+			sun_fdops.fd_inb = sun_82072_fd_inb;
+			sun_fdops.fd_outb = sun_82072_fd_outb;
+			fdc_status = &sun_fdc->status_82072;
+		}
+	}
+
+	/* Success... */
+	allowed_drive_mask = 0x01;
+	return (int) sun_fdc;
+
+no_sun_fdc:
+	return -1;
+}
+
+static int sparc_eject(void)
+{
+	set_dor(0x00, 0xff, 0x90);
+	udelay(500);
+	set_dor(0x00, 0x6f, 0x00);
+	udelay(500);
+	return 0;
+}
+
+#define fd_eject(drive) sparc_eject()
+
+#define EXTRA_FLOPPY_PARAMS
+
+#endif /* !(__ASM_SPARC_FLOPPY_H) */
diff --git a/include/asm-sparc/floppy_64.h b/include/asm-sparc/floppy_64.h
new file mode 100644
index 0000000..c39db10
--- /dev/null
+++ b/include/asm-sparc/floppy_64.h
@@ -0,0 +1,782 @@
+/* floppy.h: Sparc specific parts of the Floppy driver.
+ *
+ * Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ *
+ * Ultra/PCI support added: Sep 1997  Eddie C. Dost  (ecd@skynet.be)
+ */
+
+#ifndef __ASM_SPARC64_FLOPPY_H
+#define __ASM_SPARC64_FLOPPY_H
+
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/idprom.h>
+#include <asm/oplib.h>
+#include <asm/auxio.h>
+#include <asm/sbus.h>
+#include <asm/irq.h>
+
+
+/*
+ * Define this to enable exchanging drive 0 and 1 if only drive 1 is
+ * probed on PCI machines.
+ */
+#undef PCI_FDC_SWAP_DRIVES
+
+
+/* References:
+ * 1) Netbsd Sun floppy driver.
+ * 2) NCR 82077 controller manual
+ * 3) Intel 82077 controller manual
+ */
+struct sun_flpy_controller {
+	volatile unsigned char status1_82077; /* Auxiliary Status reg. 1 */
+	volatile unsigned char status2_82077; /* Auxiliary Status reg. 2 */
+	volatile unsigned char dor_82077;     /* Digital Output reg. */
+	volatile unsigned char tapectl_82077; /* Tape Control reg */
+	volatile unsigned char status_82077;  /* Main Status Register. */
+#define drs_82077              status_82077   /* Digital Rate Select reg. */
+	volatile unsigned char data_82077;    /* Data fifo. */
+	volatile unsigned char ___unused;
+	volatile unsigned char dir_82077;     /* Digital Input reg. */
+#define dcr_82077              dir_82077      /* Config Control reg. */
+};
+
+/* You'll only ever find one controller on an Ultra anyways. */
+static struct sun_flpy_controller *sun_fdc = (struct sun_flpy_controller *)-1;
+unsigned long fdc_status;
+static struct sbus_dev *floppy_sdev = NULL;
+
+struct sun_floppy_ops {
+	unsigned char	(*fd_inb) (unsigned long port);
+	void		(*fd_outb) (unsigned char value, unsigned long port);
+	void		(*fd_enable_dma) (void);
+	void		(*fd_disable_dma) (void);
+	void		(*fd_set_dma_mode) (int);
+	void		(*fd_set_dma_addr) (char *);
+	void		(*fd_set_dma_count) (int);
+	unsigned int	(*get_dma_residue) (void);
+	int		(*fd_request_irq) (void);
+	void		(*fd_free_irq) (void);
+	int		(*fd_eject) (int);
+};
+
+static struct sun_floppy_ops sun_fdops;
+
+#define fd_inb(port)              sun_fdops.fd_inb(port)
+#define fd_outb(value,port)       sun_fdops.fd_outb(value,port)
+#define fd_enable_dma()           sun_fdops.fd_enable_dma()
+#define fd_disable_dma()          sun_fdops.fd_disable_dma()
+#define fd_request_dma()          (0) /* nothing... */
+#define fd_free_dma()             /* nothing... */
+#define fd_clear_dma_ff()         /* nothing... */
+#define fd_set_dma_mode(mode)     sun_fdops.fd_set_dma_mode(mode)
+#define fd_set_dma_addr(addr)     sun_fdops.fd_set_dma_addr(addr)
+#define fd_set_dma_count(count)   sun_fdops.fd_set_dma_count(count)
+#define get_dma_residue(x)        sun_fdops.get_dma_residue()
+#define fd_cacheflush(addr, size) /* nothing... */
+#define fd_request_irq()          sun_fdops.fd_request_irq()
+#define fd_free_irq()             sun_fdops.fd_free_irq()
+#define fd_eject(drive)           sun_fdops.fd_eject(drive)
+
+/* Super paranoid... */
+#undef HAVE_DISABLE_HLT
+
+static int sun_floppy_types[2] = { 0, 0 };
+
+/* Here is where we catch the floppy driver trying to initialize,
+ * therefore this is where we call the PROM device tree probing
+ * routine etc. on the Sparc.
+ */
+#define FLOPPY0_TYPE		sun_floppy_init()
+#define FLOPPY1_TYPE		sun_floppy_types[1]
+
+#define FDC1			((unsigned long)sun_fdc)
+
+#define N_FDC    1
+#define N_DRIVE  8
+
+/* No 64k boundary crossing problems on the Sparc. */
+#define CROSS_64KB(a,s) (0)
+
+static unsigned char sun_82077_fd_inb(unsigned long port)
+{
+	udelay(5);
+	switch(port & 7) {
+	default:
+		printk("floppy: Asked to read unknown port %lx\n", port);
+		panic("floppy: Port bolixed.");
+	case 4: /* FD_STATUS */
+		return sbus_readb(&sun_fdc->status_82077) & ~STATUS_DMA;
+	case 5: /* FD_DATA */
+		return sbus_readb(&sun_fdc->data_82077);
+	case 7: /* FD_DIR */
+		/* XXX: Is DCL on 0x80 in sun4m? */
+		return sbus_readb(&sun_fdc->dir_82077);
+	};
+	panic("sun_82072_fd_inb: How did I get here?");
+}
+
+static void sun_82077_fd_outb(unsigned char value, unsigned long port)
+{
+	udelay(5);
+	switch(port & 7) {
+	default:
+		printk("floppy: Asked to write to unknown port %lx\n", port);
+		panic("floppy: Port bolixed.");
+	case 2: /* FD_DOR */
+		/* Happily, the 82077 has a real DOR register. */
+		sbus_writeb(value, &sun_fdc->dor_82077);
+		break;
+	case 5: /* FD_DATA */
+		sbus_writeb(value, &sun_fdc->data_82077);
+		break;
+	case 7: /* FD_DCR */
+		sbus_writeb(value, &sun_fdc->dcr_82077);
+		break;
+	case 4: /* FD_STATUS */
+		sbus_writeb(value, &sun_fdc->status_82077);
+		break;
+	};
+	return;
+}
+
+/* For pseudo-dma (Sun floppy drives have no real DMA available to
+ * them so we must eat the data fifo bytes directly ourselves) we have
+ * three state variables.  doing_pdma tells our inline low-level
+ * assembly floppy interrupt entry point whether it should sit and eat
+ * bytes from the fifo or just transfer control up to the higher level
+ * floppy interrupt c-code.  I tried very hard but I could not get the
+ * pseudo-dma to work in c-code without getting many overruns and
+ * underruns.  If non-zero, doing_pdma encodes the direction of
+ * the transfer for debugging.  1=read 2=write
+ */
+unsigned char *pdma_vaddr;
+unsigned long pdma_size;
+volatile int doing_pdma = 0;
+
+/* This is software state */
+char *pdma_base = NULL;
+unsigned long pdma_areasize;
+
+/* Common routines to all controller types on the Sparc. */
+static void sun_fd_disable_dma(void)
+{
+	doing_pdma = 0;
+	if (pdma_base) {
+		mmu_unlockarea(pdma_base, pdma_areasize);
+		pdma_base = NULL;
+	}
+}
+
+static void sun_fd_set_dma_mode(int mode)
+{
+	switch(mode) {
+	case DMA_MODE_READ:
+		doing_pdma = 1;
+		break;
+	case DMA_MODE_WRITE:
+		doing_pdma = 2;
+		break;
+	default:
+		printk("Unknown dma mode %d\n", mode);
+		panic("floppy: Giving up...");
+	}
+}
+
+static void sun_fd_set_dma_addr(char *buffer)
+{
+	pdma_vaddr = buffer;
+}
+
+static void sun_fd_set_dma_count(int length)
+{
+	pdma_size = length;
+}
+
+static void sun_fd_enable_dma(void)
+{
+	pdma_vaddr = mmu_lockarea(pdma_vaddr, pdma_size);
+	pdma_base = pdma_vaddr;
+	pdma_areasize = pdma_size;
+}
+
+irqreturn_t sparc_floppy_irq(int irq, void *dev_cookie)
+{
+	if (likely(doing_pdma)) {
+		void __iomem *stat = (void __iomem *) fdc_status;
+		unsigned char *vaddr = pdma_vaddr;
+		unsigned long size = pdma_size;
+		u8 val;
+
+		while (size) {
+			val = readb(stat);
+			if (unlikely(!(val & 0x80))) {
+				pdma_vaddr = vaddr;
+				pdma_size = size;
+				return IRQ_HANDLED;
+			}
+			if (unlikely(!(val & 0x20))) {
+				pdma_vaddr = vaddr;
+				pdma_size = size;
+				doing_pdma = 0;
+				goto main_interrupt;
+			}
+			if (val & 0x40) {
+				/* read */
+				*vaddr++ = readb(stat + 1);
+			} else {
+				unsigned char data = *vaddr++;
+
+				/* write */
+				writeb(data, stat + 1);
+			}
+			size--;
+		}
+
+		pdma_vaddr = vaddr;
+		pdma_size = size;
+
+		/* Send Terminal Count pulse to floppy controller. */
+		val = readb(auxio_register);
+		val |= AUXIO_AUX1_FTCNT;
+		writeb(val, auxio_register);
+		val &= ~AUXIO_AUX1_FTCNT;
+		writeb(val, auxio_register);
+
+		doing_pdma = 0;
+	}
+
+main_interrupt:
+	return floppy_interrupt(irq, dev_cookie);
+}
+
+static int sun_fd_request_irq(void)
+{
+	static int once = 0;
+	int error;
+
+	if(!once) {
+		once = 1;
+
+		error = request_irq(FLOPPY_IRQ, sparc_floppy_irq,
+				    IRQF_DISABLED, "floppy", NULL);
+
+		return ((error == 0) ? 0 : -1);
+	}
+	return 0;
+}
+
+static void sun_fd_free_irq(void)
+{
+}
+
+static unsigned int sun_get_dma_residue(void)
+{
+	/* XXX This isn't really correct. XXX */
+	return 0;
+}
+
+static int sun_fd_eject(int drive)
+{
+	set_dor(0x00, 0xff, 0x90);
+	udelay(500);
+	set_dor(0x00, 0x6f, 0x00);
+	udelay(500);
+	return 0;
+}
+
+#ifdef CONFIG_PCI
+#include <asm/ebus.h>
+#include <asm/ns87303.h>
+
+static struct ebus_dma_info sun_pci_fd_ebus_dma;
+static struct pci_dev *sun_pci_ebus_dev;
+static int sun_pci_broken_drive = -1;
+
+struct sun_pci_dma_op {
+	unsigned int 	addr;
+	int		len;
+	int		direction;
+	char		*buf;
+};
+static struct sun_pci_dma_op sun_pci_dma_current = { -1U, 0, 0, NULL};
+static struct sun_pci_dma_op sun_pci_dma_pending = { -1U, 0, 0, NULL};
+
+extern irqreturn_t floppy_interrupt(int irq, void *dev_id);
+
+static unsigned char sun_pci_fd_inb(unsigned long port)
+{
+	udelay(5);
+	return inb(port);
+}
+
+static void sun_pci_fd_outb(unsigned char val, unsigned long port)
+{
+	udelay(5);
+	outb(val, port);
+}
+
+static void sun_pci_fd_broken_outb(unsigned char val, unsigned long port)
+{
+	udelay(5);
+	/*
+	 * XXX: Due to SUN's broken floppy connector on AX and AXi
+	 *      we need to turn on MOTOR_0 also, if the floppy is
+	 *      jumpered to DS1 (like most PC floppies are). I hope
+	 *      this does not hurt correct hardware like the AXmp.
+	 *      (Eddie, Sep 12 1998).
+	 */
+	if (port == ((unsigned long)sun_fdc) + 2) {
+		if (((val & 0x03) == sun_pci_broken_drive) && (val & 0x20)) {
+			val |= 0x10;
+		}
+	}
+	outb(val, port);
+}
+
+#ifdef PCI_FDC_SWAP_DRIVES
+static void sun_pci_fd_lde_broken_outb(unsigned char val, unsigned long port)
+{
+	udelay(5);
+	/*
+	 * XXX: Due to SUN's broken floppy connector on AX and AXi
+	 *      we need to turn on MOTOR_0 also, if the floppy is
+	 *      jumpered to DS1 (like most PC floppies are). I hope
+	 *      this does not hurt correct hardware like the AXmp.
+	 *      (Eddie, Sep 12 1998).
+	 */
+	if (port == ((unsigned long)sun_fdc) + 2) {
+		if (((val & 0x03) == sun_pci_broken_drive) && (val & 0x10)) {
+			val &= ~(0x03);
+			val |= 0x21;
+		}
+	}
+	outb(val, port);
+}
+#endif /* PCI_FDC_SWAP_DRIVES */
+
+static void sun_pci_fd_enable_dma(void)
+{
+	BUG_ON((NULL == sun_pci_dma_pending.buf) 	||
+	    (0	  == sun_pci_dma_pending.len) 	||
+	    (0	  == sun_pci_dma_pending.direction));
+
+	sun_pci_dma_current.buf = sun_pci_dma_pending.buf;
+	sun_pci_dma_current.len = sun_pci_dma_pending.len;
+	sun_pci_dma_current.direction = sun_pci_dma_pending.direction;
+
+	sun_pci_dma_pending.buf  = NULL;
+	sun_pci_dma_pending.len  = 0;
+	sun_pci_dma_pending.direction = 0;
+	sun_pci_dma_pending.addr = -1U;
+
+	sun_pci_dma_current.addr =
+		pci_map_single(sun_pci_ebus_dev,
+			       sun_pci_dma_current.buf,
+			       sun_pci_dma_current.len,
+			       sun_pci_dma_current.direction);
+
+	ebus_dma_enable(&sun_pci_fd_ebus_dma, 1);
+
+	if (ebus_dma_request(&sun_pci_fd_ebus_dma,
+			     sun_pci_dma_current.addr,
+			     sun_pci_dma_current.len))
+		BUG();
+}
+
+static void sun_pci_fd_disable_dma(void)
+{
+	ebus_dma_enable(&sun_pci_fd_ebus_dma, 0);
+	if (sun_pci_dma_current.addr != -1U)
+		pci_unmap_single(sun_pci_ebus_dev,
+				 sun_pci_dma_current.addr,
+				 sun_pci_dma_current.len,
+				 sun_pci_dma_current.direction);
+	sun_pci_dma_current.addr = -1U;
+}
+
+static void sun_pci_fd_set_dma_mode(int mode)
+{
+	if (mode == DMA_MODE_WRITE)
+		sun_pci_dma_pending.direction = PCI_DMA_TODEVICE;
+	else
+		sun_pci_dma_pending.direction = PCI_DMA_FROMDEVICE;
+
+	ebus_dma_prepare(&sun_pci_fd_ebus_dma, mode != DMA_MODE_WRITE);
+}
+
+static void sun_pci_fd_set_dma_count(int length)
+{
+	sun_pci_dma_pending.len = length;
+}
+
+static void sun_pci_fd_set_dma_addr(char *buffer)
+{
+	sun_pci_dma_pending.buf = buffer;
+}
+
+static unsigned int sun_pci_get_dma_residue(void)
+{
+	return ebus_dma_residue(&sun_pci_fd_ebus_dma);
+}
+
+static int sun_pci_fd_request_irq(void)
+{
+	return ebus_dma_irq_enable(&sun_pci_fd_ebus_dma, 1);
+}
+
+static void sun_pci_fd_free_irq(void)
+{
+	ebus_dma_irq_enable(&sun_pci_fd_ebus_dma, 0);
+}
+
+static int sun_pci_fd_eject(int drive)
+{
+	return -EINVAL;
+}
+
+void sun_pci_fd_dma_callback(struct ebus_dma_info *p, int event, void *cookie)
+{
+	floppy_interrupt(0, NULL);
+}
+
+/*
+ * Floppy probing, we'd like to use /dev/fd0 for a single Floppy on PCI,
+ * even if this is configured using DS1, thus looks like /dev/fd1 with
+ * the cabling used in Ultras.
+ */
+#define DOR	(port + 2)
+#define MSR	(port + 4)
+#define FIFO	(port + 5)
+
+static void sun_pci_fd_out_byte(unsigned long port, unsigned char val,
+			        unsigned long reg)
+{
+	unsigned char status;
+	int timeout = 1000;
+
+	while (!((status = inb(MSR)) & 0x80) && --timeout)
+		udelay(100);
+	outb(val, reg);
+}
+
+static unsigned char sun_pci_fd_sensei(unsigned long port)
+{
+	unsigned char result[2] = { 0x70, 0x00 };
+	unsigned char status;
+	int i = 0;
+
+	sun_pci_fd_out_byte(port, 0x08, FIFO);
+	do {
+		int timeout = 1000;
+
+		while (!((status = inb(MSR)) & 0x80) && --timeout)
+			udelay(100);
+
+		if (!timeout)
+			break;
+
+		if ((status & 0xf0) == 0xd0)
+			result[i++] = inb(FIFO);
+		else
+			break;
+	} while (i < 2);
+
+	return result[0];
+}
+
+static void sun_pci_fd_reset(unsigned long port)
+{
+	unsigned char mask = 0x00;
+	unsigned char status;
+	int timeout = 10000;
+
+	outb(0x80, MSR);
+	do {
+		status = sun_pci_fd_sensei(port);
+		if ((status & 0xc0) == 0xc0)
+			mask |= 1 << (status & 0x03);
+		else
+			udelay(100);
+	} while ((mask != 0x0f) && --timeout);
+}
+
+static int sun_pci_fd_test_drive(unsigned long port, int drive)
+{
+	unsigned char status, data;
+	int timeout = 1000;
+	int ready;
+
+	sun_pci_fd_reset(port);
+
+	data = (0x10 << drive) | 0x0c | drive;
+	sun_pci_fd_out_byte(port, data, DOR);
+
+	sun_pci_fd_out_byte(port, 0x07, FIFO);
+	sun_pci_fd_out_byte(port, drive & 0x03, FIFO);
+
+	do {
+		udelay(100);
+		status = sun_pci_fd_sensei(port);
+	} while (((status & 0xc0) == 0x80) && --timeout);
+
+	if (!timeout)
+		ready = 0;
+	else
+		ready = (status & 0x10) ? 0 : 1;
+
+	sun_pci_fd_reset(port);
+	return ready;
+}
+#undef FIFO
+#undef MSR
+#undef DOR
+
+#endif /* CONFIG_PCI */
+
+#ifdef CONFIG_PCI
+static int __init ebus_fdthree_p(struct linux_ebus_device *edev)
+{
+	if (!strcmp(edev->prom_node->name, "fdthree"))
+		return 1;
+	if (!strcmp(edev->prom_node->name, "floppy")) {
+		const char *compat;
+
+		compat = of_get_property(edev->prom_node,
+					 "compatible", NULL);
+		if (compat && !strcmp(compat, "fdthree"))
+			return 1;
+	}
+	return 0;
+}
+#endif
+
+static unsigned long __init sun_floppy_init(void)
+{
+	char state[128];
+	struct sbus_bus *bus;
+	struct sbus_dev *sdev = NULL;
+	static int initialized = 0;
+
+	if (initialized)
+		return sun_floppy_types[0];
+	initialized = 1;
+
+	for_all_sbusdev (sdev, bus) {
+		if (!strcmp(sdev->prom_name, "SUNW,fdtwo"))
+			break;
+	}
+	if(sdev) {
+		floppy_sdev = sdev;
+		FLOPPY_IRQ = sdev->irqs[0];
+	} else {
+#ifdef CONFIG_PCI
+		struct linux_ebus *ebus;
+		struct linux_ebus_device *edev = NULL;
+		unsigned long config = 0;
+		void __iomem *auxio_reg;
+		const char *state_prop;
+
+		for_each_ebus(ebus) {
+			for_each_ebusdev(edev, ebus) {
+				if (ebus_fdthree_p(edev))
+					goto ebus_done;
+			}
+		}
+	ebus_done:
+		if (!edev)
+			return 0;
+
+		state_prop = of_get_property(edev->prom_node, "status", NULL);
+		if (state_prop && !strncmp(state_prop, "disabled", 8))
+			return 0;
+
+		FLOPPY_IRQ = edev->irqs[0];
+
+		/* Make sure the high density bit is set, some systems
+		 * (most notably Ultra5/Ultra10) come up with it clear.
+		 */
+		auxio_reg = (void __iomem *) edev->resource[2].start;
+		writel(readl(auxio_reg)|0x2, auxio_reg);
+
+		sun_pci_ebus_dev = ebus->self;
+
+		spin_lock_init(&sun_pci_fd_ebus_dma.lock);
+
+		/* XXX ioremap */
+		sun_pci_fd_ebus_dma.regs = (void __iomem *)
+			edev->resource[1].start;
+		if (!sun_pci_fd_ebus_dma.regs)
+			return 0;
+
+		sun_pci_fd_ebus_dma.flags = (EBUS_DMA_FLAG_USE_EBDMA_HANDLER |
+					     EBUS_DMA_FLAG_TCI_DISABLE);
+		sun_pci_fd_ebus_dma.callback = sun_pci_fd_dma_callback;
+		sun_pci_fd_ebus_dma.client_cookie = NULL;
+		sun_pci_fd_ebus_dma.irq = FLOPPY_IRQ;
+		strcpy(sun_pci_fd_ebus_dma.name, "floppy");
+		if (ebus_dma_register(&sun_pci_fd_ebus_dma))
+			return 0;
+
+		/* XXX ioremap */
+		sun_fdc = (struct sun_flpy_controller *)edev->resource[0].start;
+
+		sun_fdops.fd_inb = sun_pci_fd_inb;
+		sun_fdops.fd_outb = sun_pci_fd_outb;
+
+		can_use_virtual_dma = use_virtual_dma = 0;
+		sun_fdops.fd_enable_dma = sun_pci_fd_enable_dma;
+		sun_fdops.fd_disable_dma = sun_pci_fd_disable_dma;
+		sun_fdops.fd_set_dma_mode = sun_pci_fd_set_dma_mode;
+		sun_fdops.fd_set_dma_addr = sun_pci_fd_set_dma_addr;
+		sun_fdops.fd_set_dma_count = sun_pci_fd_set_dma_count;
+		sun_fdops.get_dma_residue = sun_pci_get_dma_residue;
+
+		sun_fdops.fd_request_irq = sun_pci_fd_request_irq;
+		sun_fdops.fd_free_irq = sun_pci_fd_free_irq;
+
+		sun_fdops.fd_eject = sun_pci_fd_eject;
+
+		fdc_status = (unsigned long) &sun_fdc->status_82077;
+
+		/*
+		 * XXX: Find out on which machines this is really needed.
+		 */
+		if (1) {
+			sun_pci_broken_drive = 1;
+			sun_fdops.fd_outb = sun_pci_fd_broken_outb;
+		}
+
+		allowed_drive_mask = 0;
+		if (sun_pci_fd_test_drive((unsigned long)sun_fdc, 0))
+			sun_floppy_types[0] = 4;
+		if (sun_pci_fd_test_drive((unsigned long)sun_fdc, 1))
+			sun_floppy_types[1] = 4;
+
+		/*
+		 * Find NS87303 SuperIO config registers (through ecpp).
+		 */
+		for_each_ebus(ebus) {
+			for_each_ebusdev(edev, ebus) {
+				if (!strcmp(edev->prom_node->name, "ecpp")) {
+					config = edev->resource[1].start;
+					goto config_done;
+				}
+			}
+		}
+	config_done:
+
+		/*
+		 * Sanity check, is this really the NS87303?
+		 */
+		switch (config & 0x3ff) {
+		case 0x02e:
+		case 0x15c:
+		case 0x26e:
+		case 0x398:
+			break;
+		default:
+			config = 0;
+		}
+
+		if (!config)
+			return sun_floppy_types[0];
+
+		/* Enable PC-AT mode. */
+		ns87303_modify(config, ASC, 0, 0xc0);
+
+#ifdef PCI_FDC_SWAP_DRIVES
+		/*
+		 * If only Floppy 1 is present, swap drives.
+		 */
+		if (!sun_floppy_types[0] && sun_floppy_types[1]) {
+			/*
+			 * Set the drive exchange bit in FCR on NS87303,
+			 * make sure other bits are sane before doing so.
+			 */
+			ns87303_modify(config, FER, FER_EDM, 0);
+			ns87303_modify(config, ASC, ASC_DRV2_SEL, 0);
+			ns87303_modify(config, FCR, 0, FCR_LDE);
+
+			config = sun_floppy_types[0];
+			sun_floppy_types[0] = sun_floppy_types[1];
+			sun_floppy_types[1] = config;
+
+			if (sun_pci_broken_drive != -1) {
+				sun_pci_broken_drive = 1 - sun_pci_broken_drive;
+				sun_fdops.fd_outb = sun_pci_fd_lde_broken_outb;
+			}
+		}
+#endif /* PCI_FDC_SWAP_DRIVES */
+
+		return sun_floppy_types[0];
+#else
+		return 0;
+#endif
+	}
+	prom_getproperty(sdev->prom_node, "status", state, sizeof(state));
+	if(!strncmp(state, "disabled", 8))
+		return 0;
+
+	/*
+	 * We cannot do sbus_ioremap here: it does request_region,
+	 * which the generic floppy driver tries to do once again.
+	 * But we must use the sdev resource values as they have
+	 * had parent ranges applied.
+	 */
+	sun_fdc = (struct sun_flpy_controller *)
+		(sdev->resource[0].start +
+		 ((sdev->resource[0].flags & 0x1ffUL) << 32UL));
+
+	/* Last minute sanity check... */
+	if(sbus_readb(&sun_fdc->status1_82077) == 0xff) {
+		sun_fdc = (struct sun_flpy_controller *)-1;
+		return 0;
+	}
+
+        sun_fdops.fd_inb = sun_82077_fd_inb;
+        sun_fdops.fd_outb = sun_82077_fd_outb;
+
+	can_use_virtual_dma = use_virtual_dma = 1;
+	sun_fdops.fd_enable_dma = sun_fd_enable_dma;
+	sun_fdops.fd_disable_dma = sun_fd_disable_dma;
+	sun_fdops.fd_set_dma_mode = sun_fd_set_dma_mode;
+	sun_fdops.fd_set_dma_addr = sun_fd_set_dma_addr;
+	sun_fdops.fd_set_dma_count = sun_fd_set_dma_count;
+	sun_fdops.get_dma_residue = sun_get_dma_residue;
+
+	sun_fdops.fd_request_irq = sun_fd_request_irq;
+	sun_fdops.fd_free_irq = sun_fd_free_irq;
+
+	sun_fdops.fd_eject = sun_fd_eject;
+
+        fdc_status = (unsigned long) &sun_fdc->status_82077;
+
+	/* Success... */
+	allowed_drive_mask = 0x01;
+	sun_floppy_types[0] = 4;
+	sun_floppy_types[1] = 0;
+
+	return sun_floppy_types[0];
+}
+
+#define EXTRA_FLOPPY_PARAMS
+
+static DEFINE_SPINLOCK(dma_spin_lock);
+
+#define claim_dma_lock() \
+({	unsigned long flags; \
+	spin_lock_irqsave(&dma_spin_lock, flags); \
+	flags; \
+})
+
+#define release_dma_lock(__flags) \
+	spin_unlock_irqrestore(&dma_spin_lock, __flags);
+
+#endif /* !(__ASM_SPARC64_FLOPPY_H) */
diff --git a/include/asm-sparc/fpumacro.h b/include/asm-sparc/fpumacro.h
new file mode 100644
index 0000000..cc463fe
--- /dev/null
+++ b/include/asm-sparc/fpumacro.h
@@ -0,0 +1,33 @@
+/* fpumacro.h: FPU related macros.
+ *
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC64_FPUMACRO_H
+#define _SPARC64_FPUMACRO_H
+
+#include <asm/asi.h>
+#include <asm/visasm.h>
+
+struct fpustate {
+	u32	regs[64];
+};
+
+#define FPUSTATE (struct fpustate *)(current_thread_info()->fpregs)
+
+static inline unsigned long fprs_read(void)
+{
+	unsigned long retval;
+
+	__asm__ __volatile__("rd %%fprs, %0" : "=r" (retval));
+
+	return retval;
+}
+
+static inline void fprs_write(unsigned long val)
+{
+	__asm__ __volatile__("wr %0, 0x0, %%fprs" : : "r" (val));
+}
+
+#endif /* !(_SPARC64_FPUMACRO_H) */
diff --git a/include/asm-sparc/futex.h b/include/asm-sparc/futex.h
index 6a332a9..c6a9f03 100644
--- a/include/asm-sparc/futex.h
+++ b/include/asm-sparc/futex.h
@@ -1,6 +1,8 @@
-#ifndef _ASM_FUTEX_H
-#define _ASM_FUTEX_H
-
-#include <asm-generic/futex.h>
-
+#ifndef ___ASM_SPARC_FUTEX_H
+#define ___ASM_SPARC_FUTEX_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/futex_64.h>
+#else
+#include <asm-sparc/futex_32.h>
+#endif
 #endif
diff --git a/include/asm-sparc/futex_32.h b/include/asm-sparc/futex_32.h
new file mode 100644
index 0000000..6a332a9
--- /dev/null
+++ b/include/asm-sparc/futex_32.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#include <asm-generic/futex.h>
+
+#endif
diff --git a/include/asm-sparc/futex_64.h b/include/asm-sparc/futex_64.h
new file mode 100644
index 0000000..d837893
--- /dev/null
+++ b/include/asm-sparc/futex_64.h
@@ -0,0 +1,110 @@
+#ifndef _SPARC64_FUTEX_H
+#define _SPARC64_FUTEX_H
+
+#include <linux/futex.h>
+#include <linux/uaccess.h>
+#include <asm/errno.h>
+#include <asm/system.h>
+
+#define __futex_cas_op(insn, ret, oldval, uaddr, oparg)	\
+	__asm__ __volatile__(				\
+	"\n1:	lduwa	[%3] %%asi, %2\n"		\
+	"	" insn "\n"				\
+	"2:	casa	[%3] %%asi, %2, %1\n"		\
+	"	cmp	%2, %1\n"			\
+	"	bne,pn	%%icc, 1b\n"			\
+	"	 mov	0, %0\n"			\
+	"3:\n"						\
+	"	.section .fixup,#alloc,#execinstr\n"	\
+	"	.align	4\n"				\
+	"4:	sethi	%%hi(3b), %0\n"			\
+	"	jmpl	%0 + %%lo(3b), %%g0\n"		\
+	"	 mov	%5, %0\n"			\
+	"	.previous\n"				\
+	"	.section __ex_table,\"a\"\n"		\
+	"	.align	4\n"				\
+	"	.word	1b, 4b\n"			\
+	"	.word	2b, 4b\n"			\
+	"	.previous\n"				\
+	: "=&r" (ret), "=&r" (oldval), "=&r" (tem)	\
+	: "r" (uaddr), "r" (oparg), "i" (-EFAULT)	\
+	: "memory")
+
+static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+{
+	int op = (encoded_op >> 28) & 7;
+	int cmp = (encoded_op >> 24) & 15;
+	int oparg = (encoded_op << 8) >> 20;
+	int cmparg = (encoded_op << 20) >> 20;
+	int oldval = 0, ret, tem;
+
+	if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(int))))
+		return -EFAULT;
+	if (unlikely((((unsigned long) uaddr) & 0x3UL)))
+		return -EINVAL;
+
+	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+		oparg = 1 << oparg;
+
+	pagefault_disable();
+
+	switch (op) {
+	case FUTEX_OP_SET:
+		__futex_cas_op("mov\t%4, %1", ret, oldval, uaddr, oparg);
+		break;
+	case FUTEX_OP_ADD:
+		__futex_cas_op("add\t%2, %4, %1", ret, oldval, uaddr, oparg);
+		break;
+	case FUTEX_OP_OR:
+		__futex_cas_op("or\t%2, %4, %1", ret, oldval, uaddr, oparg);
+		break;
+	case FUTEX_OP_ANDN:
+		__futex_cas_op("and\t%2, %4, %1", ret, oldval, uaddr, oparg);
+		break;
+	case FUTEX_OP_XOR:
+		__futex_cas_op("xor\t%2, %4, %1", ret, oldval, uaddr, oparg);
+		break;
+	default:
+		ret = -ENOSYS;
+	}
+
+	pagefault_enable();
+
+	if (!ret) {
+		switch (cmp) {
+		case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+		case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+		case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+		case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+		case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+		case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+		default: ret = -ENOSYS;
+		}
+	}
+	return ret;
+}
+
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+	__asm__ __volatile__(
+	"\n1:	casa	[%3] %%asi, %2, %0\n"
+	"2:\n"
+	"	.section .fixup,#alloc,#execinstr\n"
+	"	.align	4\n"
+	"3:	sethi	%%hi(2b), %0\n"
+	"	jmpl	%0 + %%lo(2b), %%g0\n"
+	"	 mov	%4, %0\n"
+	"	.previous\n"
+	"	.section __ex_table,\"a\"\n"
+	"	.align	4\n"
+	"	.word	1b, 3b\n"
+	"	.previous\n"
+	: "=r" (newval)
+	: "0" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT)
+	: "memory");
+
+	return newval;
+}
+
+#endif /* !(_SPARC64_FUTEX_H) */
diff --git a/include/asm-sparc/hardirq.h b/include/asm-sparc/hardirq.h
index 4f63ed8..1564787 100644
--- a/include/asm-sparc/hardirq.h
+++ b/include/asm-sparc/hardirq.h
@@ -1,23 +1,8 @@
-/* hardirq.h: 32-bit Sparc hard IRQ support.
- *
- * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1998-2000 Anton Blanchard (anton@samba.org)
- */
-
-#ifndef __SPARC_HARDIRQ_H
-#define __SPARC_HARDIRQ_H
-
-#include <linux/threads.h>
-#include <linux/spinlock.h>
-#include <linux/cache.h>
-
-/* entry.S is sensitive to the offsets of these fields */ /* XXX P3 Is it? */
-typedef struct {
-	unsigned int __softirq_pending;
-} ____cacheline_aligned irq_cpustat_t;
-
-#include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
-
-#define HARDIRQ_BITS    8
-
-#endif /* __SPARC_HARDIRQ_H */
+#ifndef ___ASM_SPARC_HARDIRQ_H
+#define ___ASM_SPARC_HARDIRQ_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/hardirq_64.h>
+#else
+#include <asm-sparc/hardirq_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/hardirq_32.h b/include/asm-sparc/hardirq_32.h
new file mode 100644
index 0000000..4f63ed8
--- /dev/null
+++ b/include/asm-sparc/hardirq_32.h
@@ -0,0 +1,23 @@
+/* hardirq.h: 32-bit Sparc hard IRQ support.
+ *
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1998-2000 Anton Blanchard (anton@samba.org)
+ */
+
+#ifndef __SPARC_HARDIRQ_H
+#define __SPARC_HARDIRQ_H
+
+#include <linux/threads.h>
+#include <linux/spinlock.h>
+#include <linux/cache.h>
+
+/* entry.S is sensitive to the offsets of these fields */ /* XXX P3 Is it? */
+typedef struct {
+	unsigned int __softirq_pending;
+} ____cacheline_aligned irq_cpustat_t;
+
+#include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
+
+#define HARDIRQ_BITS    8
+
+#endif /* __SPARC_HARDIRQ_H */
diff --git a/include/asm-sparc/hardirq_64.h b/include/asm-sparc/hardirq_64.h
new file mode 100644
index 0000000..7c29fd1
--- /dev/null
+++ b/include/asm-sparc/hardirq_64.h
@@ -0,0 +1,19 @@
+/* hardirq.h: 64-bit Sparc hard IRQ support.
+ *
+ * Copyright (C) 1997, 1998, 2005 David S. Miller (davem@davemloft.net)
+ */
+
+#ifndef __SPARC64_HARDIRQ_H
+#define __SPARC64_HARDIRQ_H
+
+#include <asm/cpudata.h>
+
+#define __ARCH_IRQ_STAT
+#define local_softirq_pending() \
+	(local_cpu_data().__softirq_pending)
+
+void ack_bad_irq(unsigned int irq);
+
+#define HARDIRQ_BITS	8
+
+#endif /* !(__SPARC64_HARDIRQ_H) */
diff --git a/include/asm-sparc/head.h b/include/asm-sparc/head.h
index 7c35491..14652ab 100644
--- a/include/asm-sparc/head.h
+++ b/include/asm-sparc/head.h
@@ -1,102 +1,8 @@
-#ifndef __SPARC_HEAD_H
-#define __SPARC_HEAD_H
-
-#define KERNBASE        0xf0000000  /* First address the kernel will eventually be */
-#define LOAD_ADDR       0x4000      /* prom jumps to us here unless this is elf /boot */
-#define SUN4C_SEGSZ     (1 << 18)
-#define SRMMU_L1_KBASE_OFFSET ((KERNBASE>>24)<<2)  /* Used in boot remapping. */
-#define INTS_ENAB        0x01           /* entry.S uses this. */
-
-#define SUN4_PROM_VECTOR 0xFFE81000     /* SUN4 PROM needs to be hardwired */
-
-#define WRITE_PAUSE      nop; nop; nop; /* Have to do this after %wim/%psr chg */
-#define NOP_INSN         0x01000000     /* Used to patch sparc_save_state */
-
-/* Here are some trap goodies */
-
-/* Generic trap entry. */
-#define TRAP_ENTRY(type, label) \
-	rd %psr, %l0; b label; rd %wim, %l3; nop;
-
-/* Data/text faults. Defaults to sun4c version at boot time. */
-#define SPARC_TFAULT rd %psr, %l0; rd %wim, %l3; b sun4c_fault; mov 1, %l7;
-#define SPARC_DFAULT rd %psr, %l0; rd %wim, %l3; b sun4c_fault; mov 0, %l7;
-#define SRMMU_TFAULT rd %psr, %l0; rd %wim, %l3; b srmmu_fault; mov 1, %l7;
-#define SRMMU_DFAULT rd %psr, %l0; rd %wim, %l3; b srmmu_fault; mov 0, %l7;
-
-/* This is for traps we should NEVER get. */
-#define BAD_TRAP(num) \
-        rd %psr, %l0; mov num, %l7; b bad_trap_handler; rd %wim, %l3;
-
-/* This is for traps when we want just skip the instruction which caused it */
-#define SKIP_TRAP(type, name) \
-	jmpl %l2, %g0; rett %l2 + 4; nop; nop;
-
-/* Notice that for the system calls we pull a trick.  We load up a
- * different pointer to the system call vector table in %l7, but call
- * the same generic system call low-level entry point.  The trap table
- * entry sequences are also HyperSparc pipeline friendly ;-)
- */
-
-/* Software trap for Linux system calls. */
-#define LINUX_SYSCALL_TRAP \
-        sethi %hi(sys_call_table), %l7; \
-        or %l7, %lo(sys_call_table), %l7; \
-        b linux_sparc_syscall; \
-        rd %psr, %l0;
-
-#define BREAKPOINT_TRAP \
-	b breakpoint_trap; \
-	rd %psr,%l0; \
-	nop; \
-	nop;
-
-#ifdef CONFIG_KGDB
-#define KGDB_TRAP(num) \
-	b kgdb_trap_low; \
-	rd %psr,%l0; \
-	nop; \
-	nop;
+#ifndef ___ASM_SPARC_HEAD_H
+#define ___ASM_SPARC_HEAD_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/head_64.h>
 #else
-#define KGDB_TRAP(num) \
-	BAD_TRAP(num)
+#include <asm-sparc/head_32.h>
 #endif
-
-/* The Get Condition Codes software trap for userland. */
-#define GETCC_TRAP \
-        b getcc_trap_handler; mov %psr, %l0; nop; nop;
-
-/* The Set Condition Codes software trap for userland. */
-#define SETCC_TRAP \
-        b setcc_trap_handler; mov %psr, %l0; nop; nop;
-
-/* The Get PSR software trap for userland. */
-#define GETPSR_TRAP \
-	mov %psr, %i0; jmp %l2; rett %l2 + 4; nop;
-
-/* This is for hard interrupts from level 1-14, 15 is non-maskable (nmi) and
- * gets handled with another macro.
- */
-#define TRAP_ENTRY_INTERRUPT(int_level) \
-        mov int_level, %l7; rd %psr, %l0; b real_irq_entry; rd %wim, %l3;
-
-/* NMI's (Non Maskable Interrupts) are special, you can't keep them
- * from coming in, and basically if you get one, the shows over. ;(
- * On the sun4c they are usually asynchronous memory errors, on the
- * the sun4m they could be either due to mem errors or a software
- * initiated interrupt from the prom/kern on an SMP box saying "I
- * command you to do CPU tricks, read your mailbox for more info."
- */
-#define NMI_TRAP \
-        rd %wim, %l3; b linux_trap_nmi_sun4c; mov %psr, %l0; nop;
-
-/* Window overflows/underflows are special and we need to try to be as
- * efficient as possible here....
- */
-#define WINDOW_SPILL \
-        rd %psr, %l0; rd %wim, %l3; b spill_window_entry; andcc %l0, PSR_PS, %g0;
-
-#define WINDOW_FILL \
-        rd %psr, %l0; rd %wim, %l3; b fill_window_entry; andcc %l0, PSR_PS, %g0;
-
-#endif /* __SPARC_HEAD_H */
+#endif
diff --git a/include/asm-sparc/head_32.h b/include/asm-sparc/head_32.h
new file mode 100644
index 0000000..7c35491
--- /dev/null
+++ b/include/asm-sparc/head_32.h
@@ -0,0 +1,102 @@
+#ifndef __SPARC_HEAD_H
+#define __SPARC_HEAD_H
+
+#define KERNBASE        0xf0000000  /* First address the kernel will eventually be */
+#define LOAD_ADDR       0x4000      /* prom jumps to us here unless this is elf /boot */
+#define SUN4C_SEGSZ     (1 << 18)
+#define SRMMU_L1_KBASE_OFFSET ((KERNBASE>>24)<<2)  /* Used in boot remapping. */
+#define INTS_ENAB        0x01           /* entry.S uses this. */
+
+#define SUN4_PROM_VECTOR 0xFFE81000     /* SUN4 PROM needs to be hardwired */
+
+#define WRITE_PAUSE      nop; nop; nop; /* Have to do this after %wim/%psr chg */
+#define NOP_INSN         0x01000000     /* Used to patch sparc_save_state */
+
+/* Here are some trap goodies */
+
+/* Generic trap entry. */
+#define TRAP_ENTRY(type, label) \
+	rd %psr, %l0; b label; rd %wim, %l3; nop;
+
+/* Data/text faults. Defaults to sun4c version at boot time. */
+#define SPARC_TFAULT rd %psr, %l0; rd %wim, %l3; b sun4c_fault; mov 1, %l7;
+#define SPARC_DFAULT rd %psr, %l0; rd %wim, %l3; b sun4c_fault; mov 0, %l7;
+#define SRMMU_TFAULT rd %psr, %l0; rd %wim, %l3; b srmmu_fault; mov 1, %l7;
+#define SRMMU_DFAULT rd %psr, %l0; rd %wim, %l3; b srmmu_fault; mov 0, %l7;
+
+/* This is for traps we should NEVER get. */
+#define BAD_TRAP(num) \
+        rd %psr, %l0; mov num, %l7; b bad_trap_handler; rd %wim, %l3;
+
+/* This is for traps when we want just skip the instruction which caused it */
+#define SKIP_TRAP(type, name) \
+	jmpl %l2, %g0; rett %l2 + 4; nop; nop;
+
+/* Notice that for the system calls we pull a trick.  We load up a
+ * different pointer to the system call vector table in %l7, but call
+ * the same generic system call low-level entry point.  The trap table
+ * entry sequences are also HyperSparc pipeline friendly ;-)
+ */
+
+/* Software trap for Linux system calls. */
+#define LINUX_SYSCALL_TRAP \
+        sethi %hi(sys_call_table), %l7; \
+        or %l7, %lo(sys_call_table), %l7; \
+        b linux_sparc_syscall; \
+        rd %psr, %l0;
+
+#define BREAKPOINT_TRAP \
+	b breakpoint_trap; \
+	rd %psr,%l0; \
+	nop; \
+	nop;
+
+#ifdef CONFIG_KGDB
+#define KGDB_TRAP(num) \
+	b kgdb_trap_low; \
+	rd %psr,%l0; \
+	nop; \
+	nop;
+#else
+#define KGDB_TRAP(num) \
+	BAD_TRAP(num)
+#endif
+
+/* The Get Condition Codes software trap for userland. */
+#define GETCC_TRAP \
+        b getcc_trap_handler; mov %psr, %l0; nop; nop;
+
+/* The Set Condition Codes software trap for userland. */
+#define SETCC_TRAP \
+        b setcc_trap_handler; mov %psr, %l0; nop; nop;
+
+/* The Get PSR software trap for userland. */
+#define GETPSR_TRAP \
+	mov %psr, %i0; jmp %l2; rett %l2 + 4; nop;
+
+/* This is for hard interrupts from level 1-14, 15 is non-maskable (nmi) and
+ * gets handled with another macro.
+ */
+#define TRAP_ENTRY_INTERRUPT(int_level) \
+        mov int_level, %l7; rd %psr, %l0; b real_irq_entry; rd %wim, %l3;
+
+/* NMI's (Non Maskable Interrupts) are special, you can't keep them
+ * from coming in, and basically if you get one, the shows over. ;(
+ * On the sun4c they are usually asynchronous memory errors, on the
+ * the sun4m they could be either due to mem errors or a software
+ * initiated interrupt from the prom/kern on an SMP box saying "I
+ * command you to do CPU tricks, read your mailbox for more info."
+ */
+#define NMI_TRAP \
+        rd %wim, %l3; b linux_trap_nmi_sun4c; mov %psr, %l0; nop;
+
+/* Window overflows/underflows are special and we need to try to be as
+ * efficient as possible here....
+ */
+#define WINDOW_SPILL \
+        rd %psr, %l0; rd %wim, %l3; b spill_window_entry; andcc %l0, PSR_PS, %g0;
+
+#define WINDOW_FILL \
+        rd %psr, %l0; rd %wim, %l3; b fill_window_entry; andcc %l0, PSR_PS, %g0;
+
+#endif /* __SPARC_HEAD_H */
diff --git a/include/asm-sparc/head_64.h b/include/asm-sparc/head_64.h
new file mode 100644
index 0000000..10e9dab
--- /dev/null
+++ b/include/asm-sparc/head_64.h
@@ -0,0 +1,76 @@
+#ifndef _SPARC64_HEAD_H
+#define _SPARC64_HEAD_H
+
+#include <asm/pstate.h>
+
+	/* wrpr	%g0, val, %gl */
+#define SET_GL(val)	\
+	.word	0xa1902000 | val
+
+	/* rdpr %gl, %gN */
+#define GET_GL_GLOBAL(N)	\
+	.word	0x81540000 | (N << 25)
+
+#define KERNBASE	0x400000
+
+#define	PTREGS_OFF	(STACK_BIAS + STACKFRAME_SZ)
+
+#define __CHEETAH_ID	0x003e0014
+#define __JALAPENO_ID	0x003e0016
+#define __SERRANO_ID	0x003e0022
+
+#define CHEETAH_MANUF		0x003e
+#define CHEETAH_IMPL		0x0014 /* Ultra-III   */
+#define CHEETAH_PLUS_IMPL	0x0015 /* Ultra-III+  */
+#define JALAPENO_IMPL		0x0016 /* Ultra-IIIi  */
+#define JAGUAR_IMPL		0x0018 /* Ultra-IV    */
+#define PANTHER_IMPL		0x0019 /* Ultra-IV+   */
+#define SERRANO_IMPL		0x0022 /* Ultra-IIIi+ */
+
+#define BRANCH_IF_SUN4V(tmp1,label)		\
+	sethi	%hi(is_sun4v), %tmp1;		\
+	lduw	[%tmp1 + %lo(is_sun4v)], %tmp1; \
+	brnz,pn	%tmp1, label;			\
+	 nop
+
+#define BRANCH_IF_CHEETAH_BASE(tmp1,tmp2,label)	\
+	rdpr	%ver, %tmp1;			\
+	sethi	%hi(__CHEETAH_ID), %tmp2;	\
+	srlx	%tmp1, 32, %tmp1;		\
+	or	%tmp2, %lo(__CHEETAH_ID), %tmp2;\
+	cmp	%tmp1, %tmp2;			\
+	be,pn	%icc, label;			\
+	 nop;
+
+#define BRANCH_IF_JALAPENO(tmp1,tmp2,label)	\
+	rdpr	%ver, %tmp1;			\
+	sethi	%hi(__JALAPENO_ID), %tmp2;	\
+	srlx	%tmp1, 32, %tmp1;		\
+	or	%tmp2, %lo(__JALAPENO_ID), %tmp2;\
+	cmp	%tmp1, %tmp2;			\
+	be,pn	%icc, label;			\
+	 nop;
+
+#define BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(tmp1,tmp2,label)	\
+	rdpr	%ver, %tmp1;			\
+	srlx	%tmp1, (32 + 16), %tmp2;	\
+	cmp	%tmp2, CHEETAH_MANUF;		\
+	bne,pt	%xcc, 99f;			\
+	 sllx	%tmp1, 16, %tmp1;		\
+	srlx	%tmp1, (32 + 16), %tmp2;	\
+	cmp	%tmp2, CHEETAH_PLUS_IMPL;	\
+	bgeu,pt	%xcc, label;			\
+99:	 nop;
+
+#define BRANCH_IF_ANY_CHEETAH(tmp1,tmp2,label)	\
+	rdpr	%ver, %tmp1;			\
+	srlx	%tmp1, (32 + 16), %tmp2;	\
+	cmp	%tmp2, CHEETAH_MANUF;		\
+	bne,pt	%xcc, 99f;			\
+	 sllx	%tmp1, 16, %tmp1;		\
+	srlx	%tmp1, (32 + 16), %tmp2;	\
+	cmp	%tmp2, CHEETAH_IMPL;		\
+	bgeu,pt	%xcc, label;			\
+99:	 nop;
+
+#endif /* !(_SPARC64_HEAD_H) */
diff --git a/include/asm-sparc/hugetlb.h b/include/asm-sparc/hugetlb.h
new file mode 100644
index 0000000..412af58
--- /dev/null
+++ b/include/asm-sparc/hugetlb.h
@@ -0,0 +1,84 @@
+#ifndef _ASM_SPARC64_HUGETLB_H
+#define _ASM_SPARC64_HUGETLB_H
+
+#include <asm/page.h>
+
+
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+		     pte_t *ptep, pte_t pte);
+
+pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+			      pte_t *ptep);
+
+void hugetlb_prefault_arch_hook(struct mm_struct *mm);
+
+static inline int is_hugepage_only_range(struct mm_struct *mm,
+					 unsigned long addr,
+					 unsigned long len) {
+	return 0;
+}
+
+/*
+ * If the arch doesn't supply something else, assume that hugepage
+ * size aligned regions are ok without further preparation.
+ */
+static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
+{
+	if (len & ~HPAGE_MASK)
+		return -EINVAL;
+	if (addr & ~HPAGE_MASK)
+		return -EINVAL;
+	return 0;
+}
+
+static inline void hugetlb_free_pgd_range(struct mmu_gather **tlb,
+					  unsigned long addr, unsigned long end,
+					  unsigned long floor,
+					  unsigned long ceiling)
+{
+	free_pgd_range(tlb, addr, end, floor, ceiling);
+}
+
+static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
+					 unsigned long addr, pte_t *ptep)
+{
+}
+
+static inline int huge_pte_none(pte_t pte)
+{
+	return pte_none(pte);
+}
+
+static inline pte_t huge_pte_wrprotect(pte_t pte)
+{
+	return pte_wrprotect(pte);
+}
+
+static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
+					   unsigned long addr, pte_t *ptep)
+{
+	ptep_set_wrprotect(mm, addr, ptep);
+}
+
+static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
+					     unsigned long addr, pte_t *ptep,
+					     pte_t pte, int dirty)
+{
+	return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
+}
+
+static inline pte_t huge_ptep_get(pte_t *ptep)
+{
+	return *ptep;
+}
+
+static inline int arch_prepare_hugepage(struct page *page)
+{
+	return 0;
+}
+
+static inline void arch_release_hugepage(struct page *page)
+{
+}
+
+#endif /* _ASM_SPARC64_HUGETLB_H */
diff --git a/include/asm-sparc/hvtramp.h b/include/asm-sparc/hvtramp.h
new file mode 100644
index 0000000..b2b9b94
--- /dev/null
+++ b/include/asm-sparc/hvtramp.h
@@ -0,0 +1,37 @@
+#ifndef _SPARC64_HVTRAP_H
+#define _SPARC64_HVTRAP_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+struct hvtramp_mapping {
+	__u64		vaddr;
+	__u64		tte;
+};
+
+struct hvtramp_descr {
+	__u32			cpu;
+	__u32			num_mappings;
+	__u64			fault_info_va;
+	__u64			fault_info_pa;
+	__u64			thread_reg;
+	struct hvtramp_mapping	maps[1];
+};
+
+extern void hv_cpu_startup(unsigned long hvdescr_pa);
+
+#endif
+
+#define HVTRAMP_DESCR_CPU		0x00
+#define HVTRAMP_DESCR_NUM_MAPPINGS	0x04
+#define HVTRAMP_DESCR_FAULT_INFO_VA	0x08
+#define HVTRAMP_DESCR_FAULT_INFO_PA	0x10
+#define HVTRAMP_DESCR_THREAD_REG	0x18
+#define HVTRAMP_DESCR_MAPS		0x20
+
+#define HVTRAMP_MAPPING_VADDR		0x00
+#define HVTRAMP_MAPPING_TTE		0x08
+#define HVTRAMP_MAPPING_SIZE		0x10
+
+#endif /* _SPARC64_HVTRAP_H */
diff --git a/include/asm-sparc/hypervisor.h b/include/asm-sparc/hypervisor.h
new file mode 100644
index 0000000..109ae24
--- /dev/null
+++ b/include/asm-sparc/hypervisor.h
@@ -0,0 +1,2949 @@
+#ifndef _SPARC64_HYPERVISOR_H
+#define _SPARC64_HYPERVISOR_H
+
+/* Sun4v hypervisor interfaces and defines.
+ *
+ * Hypervisor calls are made via traps to software traps number 0x80
+ * and above.  Registers %o0 to %o5 serve as argument, status, and
+ * return value registers.
+ *
+ * There are two kinds of these traps.  First there are the normal
+ * "fast traps" which use software trap 0x80 and encode the function
+ * to invoke by number in register %o5.  Argument and return value
+ * handling is as follows:
+ *
+ * -----------------------------------------------
+ * |  %o5  | function number |     undefined     |
+ * |  %o0  |   argument 0    |   return status   |
+ * |  %o1  |   argument 1    |   return value 1  |
+ * |  %o2  |   argument 2    |   return value 2  |
+ * |  %o3  |   argument 3    |   return value 3  |
+ * |  %o4  |   argument 4    |   return value 4  |
+ * -----------------------------------------------
+ *
+ * The second type are "hyper-fast traps" which encode the function
+ * number in the software trap number itself.  So these use trap
+ * numbers > 0x80.  The register usage for hyper-fast traps is as
+ * follows:
+ *
+ * -----------------------------------------------
+ * |  %o0  |   argument 0    |   return status   |
+ * |  %o1  |   argument 1    |   return value 1  |
+ * |  %o2  |   argument 2    |   return value 2  |
+ * |  %o3  |   argument 3    |   return value 3  |
+ * |  %o4  |   argument 4    |   return value 4  |
+ * -----------------------------------------------
+ *
+ * Registers providing explicit arguments to the hypervisor calls
+ * are volatile across the call.  Upon return their values are
+ * undefined unless explicitly specified as containing a particular
+ * return value by the specific call.  The return status is always
+ * returned in register %o0, zero indicates a successful execution of
+ * the hypervisor call and other values indicate an error status as
+ * defined below.  So, for example, if a hyper-fast trap takes
+ * arguments 0, 1, and 2, then %o0, %o1, and %o2 are volatile across
+ * the call and %o3, %o4, and %o5 would be preserved.
+ *
+ * If the hypervisor trap is invalid, or the fast trap function number
+ * is invalid, HV_EBADTRAP will be returned in %o0.  Also, all 64-bits
+ * of the argument and return values are significant.
+ */
+
+/* Trap numbers.  */
+#define HV_FAST_TRAP		0x80
+#define HV_MMU_MAP_ADDR_TRAP	0x83
+#define HV_MMU_UNMAP_ADDR_TRAP	0x84
+#define HV_TTRACE_ADDENTRY_TRAP	0x85
+#define HV_CORE_TRAP		0xff
+
+/* Error codes.  */
+#define HV_EOK				0  /* Successful return            */
+#define HV_ENOCPU			1  /* Invalid CPU id               */
+#define HV_ENORADDR			2  /* Invalid real address         */
+#define HV_ENOINTR			3  /* Invalid interrupt id         */
+#define HV_EBADPGSZ			4  /* Invalid pagesize encoding    */
+#define HV_EBADTSB			5  /* Invalid TSB description      */
+#define HV_EINVAL			6  /* Invalid argument             */
+#define HV_EBADTRAP			7  /* Invalid function number      */
+#define HV_EBADALIGN			8  /* Invalid address alignment    */
+#define HV_EWOULDBLOCK			9  /* Cannot complete w/o blocking */
+#define HV_ENOACCESS			10 /* No access to resource        */
+#define HV_EIO				11 /* I/O error                    */
+#define HV_ECPUERROR			12 /* CPU in error state           */
+#define HV_ENOTSUPPORTED		13 /* Function not supported       */
+#define HV_ENOMAP			14 /* No mapping found             */
+#define HV_ETOOMANY			15 /* Too many items specified     */
+#define HV_ECHANNEL			16 /* Invalid LDC channel          */
+#define HV_EBUSY			17 /* Resource busy                */
+
+/* mach_exit()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_MACH_EXIT
+ * ARG0:	exit code
+ * ERRORS:	This service does not return.
+ *
+ * Stop all CPUs in the virtual domain and place them into the stopped
+ * state.  The 64-bit exit code may be passed to a service entity as
+ * the domain's exit status.  On systems without a service entity, the
+ * domain will undergo a reset, and the boot firmware will be
+ * reloaded.
+ *
+ * This function will never return to the guest that invokes it.
+ *
+ * Note: By convention an exit code of zero denotes a successful exit by
+ *       the guest code.  A non-zero exit code denotes a guest specific
+ *       error indication.
+ *
+ */
+#define HV_FAST_MACH_EXIT		0x00
+
+#ifndef __ASSEMBLY__
+extern void sun4v_mach_exit(unsigned long exit_code);
+#endif
+
+/* Domain services.  */
+
+/* mach_desc()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_MACH_DESC
+ * ARG0:	buffer
+ * ARG1:	length
+ * RET0:	status
+ * RET1:	length
+ * ERRORS:	HV_EBADALIGN	Buffer is badly aligned
+ *		HV_ENORADDR	Buffer is to an illegal real address.
+ *		HV_EINVAL	Buffer length is too small for complete
+ *				machine description.
+ *
+ * Copy the most current machine description into the buffer indicated
+ * by the real address in ARG0.  The buffer provided must be 16 byte
+ * aligned.  Upon success or HV_EINVAL, this service returns the
+ * actual size of the machine description in the RET1 return value.
+ *
+ * Note: A method of determining the appropriate buffer size for the
+ *       machine description is to first call this service with a buffer
+ *       length of 0 bytes.
+ */
+#define HV_FAST_MACH_DESC		0x01
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_mach_desc(unsigned long buffer_pa,
+				     unsigned long buf_len,
+				     unsigned long *real_buf_len);
+#endif
+
+/* mach_sir()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_MACH_SIR
+ * ERRORS:	This service does not return.
+ *
+ * Perform a software initiated reset of the virtual machine domain.
+ * All CPUs are captured as soon as possible, all hardware devices are
+ * returned to the entry default state, and the domain is restarted at
+ * the SIR (trap type 0x04) real trap table (RTBA) entry point on one
+ * of the CPUs.  The single CPU restarted is selected as determined by
+ * platform specific policy.  Memory is preserved across this
+ * operation.
+ */
+#define HV_FAST_MACH_SIR		0x02
+
+#ifndef __ASSEMBLY__
+extern void sun4v_mach_sir(void);
+#endif
+
+/* mach_set_watchdog()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_MACH_SET_WATCHDOG
+ * ARG0:	timeout in milliseconds
+ * RET0:	status
+ * RET1:	time remaining in milliseconds
+ *
+ * A guest uses this API to set a watchdog timer.  Once the gues has set
+ * the timer, it must call the timer service again either to disable or
+ * postpone the expiration.  If the timer expires before being reset or
+ * disabled, then the hypervisor take a platform specific action leading
+ * to guest termination within a bounded time period.  The platform action
+ * may include recovery actions such as reporting the expiration to a
+ * Service Processor, and/or automatically restarting the gues.
+ *
+ * The 'timeout' parameter is specified in milliseconds, however the
+ * implementated granularity is given by the 'watchdog-resolution'
+ * property in the 'platform' node of the guest's machine description.
+ * The largest allowed timeout value is specified by the
+ * 'watchdog-max-timeout' property of the 'platform' node.
+ *
+ * If the 'timeout' argument is not zero, the watchdog timer is set to
+ * expire after a minimum of 'timeout' milliseconds.
+ *
+ * If the 'timeout' argument is zero, the watchdog timer is disabled.
+ *
+ * If the 'timeout' value exceeds the value of the 'max-watchdog-timeout'
+ * property, the hypervisor leaves the watchdog timer state unchanged,
+ * and returns a status of EINVAL.
+ *
+ * The 'time remaining' return value is valid regardless of whether the
+ * return status is EOK or EINVAL.  A non-zero return value indicates the
+ * number of milliseconds that were remaining until the timer was to expire.
+ * If less than one millisecond remains, the return value is '1'.  If the
+ * watchdog timer was disabled at the time of the call, the return value is
+ * zero.
+ *
+ * If the hypervisor cannot support the exact timeout value requested, but
+ * can support a larger timeout value, the hypervisor may round the actual
+ * timeout to a value larger than the requested timeout, consequently the
+ * 'time remaining' return value may be larger than the previously requested
+ * timeout value.
+ *
+ * Any guest OS debugger should be aware that the watchdog service may be in
+ * use.  Consequently, it is recommended that the watchdog service is
+ * disabled upon debugger entry (e.g. reaching a breakpoint), and then
+ * re-enabled upon returning to normal execution.  The API has been designed
+ * with this in mind, and the 'time remaining' result of the disable call may
+ * be used directly as the timeout argument of the re-enable call.
+ */
+#define HV_FAST_MACH_SET_WATCHDOG	0x05
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_mach_set_watchdog(unsigned long timeout,
+					     unsigned long *orig_timeout);
+#endif
+
+/* CPU services.
+ *
+ * CPUs represent devices that can execute software threads.  A single
+ * chip that contains multiple cores or strands is represented as
+ * multiple CPUs with unique CPU identifiers.  CPUs are exported to
+ * OBP via the machine description (and to the OS via the OBP device
+ * tree).  CPUs are always in one of three states: stopped, running,
+ * or error.
+ *
+ * A CPU ID is a pre-assigned 16-bit value that uniquely identifies a
+ * CPU within a logical domain.  Operations that are to be performed
+ * on multiple CPUs specify them via a CPU list.  A CPU list is an
+ * array in real memory, of which each 16-bit word is a CPU ID.  CPU
+ * lists are passed through the API as two arguments.  The first is
+ * the number of entries (16-bit words) in the CPU list, and the
+ * second is the (real address) pointer to the CPU ID list.
+ */
+
+/* cpu_start()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_CPU_START
+ * ARG0:	CPU ID
+ * ARG1:	PC
+ * ARG2:	RTBA
+ * ARG3:	target ARG0
+ * RET0:	status
+ * ERRORS:	ENOCPU		Invalid CPU ID
+ *		EINVAL		Target CPU ID is not in the stopped state
+ *		ENORADDR	Invalid PC or RTBA real address
+ *		EBADALIGN	Unaligned PC or unaligned RTBA
+ *		EWOULDBLOCK	Starting resources are not available
+ *
+ * Start CPU with given CPU ID with PC in %pc and with a real trap
+ * base address value of RTBA.  The indicated CPU must be in the
+ * stopped state.  The supplied RTBA must be aligned on a 256 byte
+ * boundary.  On successful completion, the specified CPU will be in
+ * the running state and will be supplied with "target ARG0" in %o0
+ * and RTBA in %tba.
+ */
+#define HV_FAST_CPU_START		0x10
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_cpu_start(unsigned long cpuid,
+				     unsigned long pc,
+				     unsigned long rtba,
+				     unsigned long arg0);
+#endif
+
+/* cpu_stop()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_CPU_STOP
+ * ARG0:	CPU ID
+ * RET0:	status
+ * ERRORS:	ENOCPU		Invalid CPU ID
+ *		EINVAL		Target CPU ID is the current cpu
+ *		EINVAL		Target CPU ID is not in the running state
+ *		EWOULDBLOCK	Stopping resources are not available
+ *		ENOTSUPPORTED	Not supported on this platform
+ *
+ * The specified CPU is stopped.  The indicated CPU must be in the
+ * running state.  On completion, it will be in the stopped state.  It
+ * is not legal to stop the current CPU.
+ *
+ * Note: As this service cannot be used to stop the current cpu, this service
+ *       may not be used to stop the last running CPU in a domain.  To stop
+ *       and exit a running domain, a guest must use the mach_exit() service.
+ */
+#define HV_FAST_CPU_STOP		0x11
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_cpu_stop(unsigned long cpuid);
+#endif
+
+/* cpu_yield()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_CPU_YIELD
+ * RET0:	status
+ * ERRORS:	No possible error.
+ *
+ * Suspend execution on the current CPU.  Execution will resume when
+ * an interrupt (device, %stick_compare, or cross-call) is targeted to
+ * the CPU.  On some CPUs, this API may be used by the hypervisor to
+ * save power by disabling hardware strands.
+ */
+#define HV_FAST_CPU_YIELD		0x12
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_cpu_yield(void);
+#endif
+
+/* cpu_qconf()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_CPU_QCONF
+ * ARG0:	queue
+ * ARG1:	base real address
+ * ARG2:	number of entries
+ * RET0:	status
+ * ERRORS:	ENORADDR	Invalid base real address
+ *		EINVAL		Invalid queue or number of entries is less
+ *				than 2 or too large.
+ *		EBADALIGN	Base real address is not correctly aligned
+ *				for size.
+ *
+ * Configure the given queue to be placed at the given base real
+ * address, with the given number of entries.  The number of entries
+ * must be a power of 2.  The base real address must be aligned
+ * exactly to match the queue size.  Each queue entry is 64 bytes
+ * long, so for example a 32 entry queue must be aligned on a 2048
+ * byte real address boundary.
+ *
+ * The specified queue is unconfigured if the number of entries is given
+ * as zero.
+ *
+ * For the current version of this API service, the argument queue is defined
+ * as follows:
+ *
+ *	queue		description
+ *	-----		-------------------------
+ *	0x3c		cpu mondo queue
+ *	0x3d		device mondo queue
+ *	0x3e		resumable error queue
+ *	0x3f		non-resumable error queue
+ *
+ * Note: The maximum number of entries for each queue for a specific cpu may
+ *       be determined from the machine description.
+ */
+#define HV_FAST_CPU_QCONF		0x14
+#define  HV_CPU_QUEUE_CPU_MONDO		 0x3c
+#define  HV_CPU_QUEUE_DEVICE_MONDO	 0x3d
+#define  HV_CPU_QUEUE_RES_ERROR		 0x3e
+#define  HV_CPU_QUEUE_NONRES_ERROR	 0x3f
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_cpu_qconf(unsigned long type,
+				     unsigned long queue_paddr,
+				     unsigned long num_queue_entries);
+#endif
+
+/* cpu_qinfo()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_CPU_QINFO
+ * ARG0:	queue
+ * RET0:	status
+ * RET1:	base real address
+ * RET1:	number of entries
+ * ERRORS:	EINVAL		Invalid queue
+ *
+ * Return the configuration info for the given queue.  The base real
+ * address and number of entries of the defined queue are returned.
+ * The queue argument values are the same as for cpu_qconf() above.
+ *
+ * If the specified queue is a valid queue number, but no queue has
+ * been defined, the number of entries will be set to zero and the
+ * base real address returned is undefined.
+ */
+#define HV_FAST_CPU_QINFO		0x15
+
+/* cpu_mondo_send()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_CPU_MONDO_SEND
+ * ARG0-1:	CPU list
+ * ARG2:	data real address
+ * RET0:	status
+ * ERRORS:	EBADALIGN	Mondo data is not 64-byte aligned or CPU list
+ *				is not 2-byte aligned.
+ *		ENORADDR	Invalid data mondo address, or invalid cpu list
+ *				address.
+ *		ENOCPU		Invalid cpu in CPU list
+ *		EWOULDBLOCK	Some or all of the listed CPUs did not receive
+ *				the mondo
+ *		ECPUERROR	One or more of the listed CPUs are in error
+ *				state, use HV_FAST_CPU_STATE to see which ones
+ *		EINVAL		CPU list includes caller's CPU ID
+ *
+ * Send a mondo interrupt to the CPUs in the given CPU list with the
+ * 64-bytes at the given data real address.  The data must be 64-byte
+ * aligned.  The mondo data will be delivered to the cpu_mondo queues
+ * of the recipient CPUs.
+ *
+ * In all cases, error or not, the CPUs in the CPU list to which the
+ * mondo has been successfully delivered will be indicated by having
+ * their entry in CPU list updated with the value 0xffff.
+ */
+#define HV_FAST_CPU_MONDO_SEND		0x42
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_cpu_mondo_send(unsigned long cpu_count, unsigned long cpu_list_pa, unsigned long mondo_block_pa);
+#endif
+
+/* cpu_myid()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_CPU_MYID
+ * RET0:	status
+ * RET1:	CPU ID
+ * ERRORS:	No errors defined.
+ *
+ * Return the hypervisor ID handle for the current CPU.  Use by a
+ * virtual CPU to discover it's own identity.
+ */
+#define HV_FAST_CPU_MYID		0x16
+
+/* cpu_state()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_CPU_STATE
+ * ARG0:	CPU ID
+ * RET0:	status
+ * RET1:	state
+ * ERRORS:	ENOCPU		Invalid CPU ID
+ *
+ * Retrieve the current state of the CPU with the given CPU ID.
+ */
+#define HV_FAST_CPU_STATE		0x17
+#define  HV_CPU_STATE_STOPPED		 0x01
+#define  HV_CPU_STATE_RUNNING		 0x02
+#define  HV_CPU_STATE_ERROR		 0x03
+
+#ifndef __ASSEMBLY__
+extern long sun4v_cpu_state(unsigned long cpuid);
+#endif
+
+/* cpu_set_rtba()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_CPU_SET_RTBA
+ * ARG0:	RTBA
+ * RET0:	status
+ * RET1:	previous RTBA
+ * ERRORS:	ENORADDR	Invalid RTBA real address
+ *		EBADALIGN	RTBA is incorrectly aligned for a trap table
+ *
+ * Set the real trap base address of the local cpu to the given RTBA.
+ * The supplied RTBA must be aligned on a 256 byte boundary.  Upon
+ * success the previous value of the RTBA is returned in RET1.
+ *
+ * Note: This service does not affect %tba
+ */
+#define HV_FAST_CPU_SET_RTBA		0x18
+
+/* cpu_set_rtba()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_CPU_GET_RTBA
+ * RET0:	status
+ * RET1:	previous RTBA
+ * ERRORS:	No possible error.
+ *
+ * Returns the current value of RTBA in RET1.
+ */
+#define HV_FAST_CPU_GET_RTBA		0x19
+
+/* MMU services.
+ *
+ * Layout of a TSB description for mmu_tsb_ctx{,non}0() calls.
+ */
+#ifndef __ASSEMBLY__
+struct hv_tsb_descr {
+	unsigned short		pgsz_idx;
+	unsigned short		assoc;
+	unsigned int		num_ttes;	/* in TTEs */
+	unsigned int		ctx_idx;
+	unsigned int		pgsz_mask;
+	unsigned long		tsb_base;
+	unsigned long		resv;
+};
+#endif
+#define HV_TSB_DESCR_PGSZ_IDX_OFFSET	0x00
+#define HV_TSB_DESCR_ASSOC_OFFSET	0x02
+#define HV_TSB_DESCR_NUM_TTES_OFFSET	0x04
+#define HV_TSB_DESCR_CTX_IDX_OFFSET	0x08
+#define HV_TSB_DESCR_PGSZ_MASK_OFFSET	0x0c
+#define HV_TSB_DESCR_TSB_BASE_OFFSET	0x10
+#define HV_TSB_DESCR_RESV_OFFSET	0x18
+
+/* Page size bitmask.  */
+#define HV_PGSZ_MASK_8K			(1 << 0)
+#define HV_PGSZ_MASK_64K		(1 << 1)
+#define HV_PGSZ_MASK_512K		(1 << 2)
+#define HV_PGSZ_MASK_4MB		(1 << 3)
+#define HV_PGSZ_MASK_32MB		(1 << 4)
+#define HV_PGSZ_MASK_256MB		(1 << 5)
+#define HV_PGSZ_MASK_2GB		(1 << 6)
+#define HV_PGSZ_MASK_16GB		(1 << 7)
+
+/* Page size index.  The value given in the TSB descriptor must correspond
+ * to the smallest page size specified in the pgsz_mask page size bitmask.
+ */
+#define HV_PGSZ_IDX_8K			0
+#define HV_PGSZ_IDX_64K			1
+#define HV_PGSZ_IDX_512K		2
+#define HV_PGSZ_IDX_4MB			3
+#define HV_PGSZ_IDX_32MB		4
+#define HV_PGSZ_IDX_256MB		5
+#define HV_PGSZ_IDX_2GB			6
+#define HV_PGSZ_IDX_16GB		7
+
+/* MMU fault status area.
+ *
+ * MMU related faults have their status and fault address information
+ * placed into a memory region made available by privileged code.  Each
+ * virtual processor must make a mmu_fault_area_conf() call to tell the
+ * hypervisor where that processor's fault status should be stored.
+ *
+ * The fault status block is a multiple of 64-bytes and must be aligned
+ * on a 64-byte boundary.
+ */
+#ifndef __ASSEMBLY__
+struct hv_fault_status {
+	unsigned long		i_fault_type;
+	unsigned long		i_fault_addr;
+	unsigned long		i_fault_ctx;
+	unsigned long		i_reserved[5];
+	unsigned long		d_fault_type;
+	unsigned long		d_fault_addr;
+	unsigned long		d_fault_ctx;
+	unsigned long		d_reserved[5];
+};
+#endif
+#define HV_FAULT_I_TYPE_OFFSET	0x00
+#define HV_FAULT_I_ADDR_OFFSET	0x08
+#define HV_FAULT_I_CTX_OFFSET	0x10
+#define HV_FAULT_D_TYPE_OFFSET	0x40
+#define HV_FAULT_D_ADDR_OFFSET	0x48
+#define HV_FAULT_D_CTX_OFFSET	0x50
+
+#define HV_FAULT_TYPE_FAST_MISS	1
+#define HV_FAULT_TYPE_FAST_PROT	2
+#define HV_FAULT_TYPE_MMU_MISS	3
+#define HV_FAULT_TYPE_INV_RA	4
+#define HV_FAULT_TYPE_PRIV_VIOL	5
+#define HV_FAULT_TYPE_PROT_VIOL	6
+#define HV_FAULT_TYPE_NFO	7
+#define HV_FAULT_TYPE_NFO_SEFF	8
+#define HV_FAULT_TYPE_INV_VA	9
+#define HV_FAULT_TYPE_INV_ASI	10
+#define HV_FAULT_TYPE_NC_ATOMIC	11
+#define HV_FAULT_TYPE_PRIV_ACT	12
+#define HV_FAULT_TYPE_RESV1	13
+#define HV_FAULT_TYPE_UNALIGNED	14
+#define HV_FAULT_TYPE_INV_PGSZ	15
+/* Values 16 --> -2 are reserved.  */
+#define HV_FAULT_TYPE_MULTIPLE	-1
+
+/* Flags argument for mmu_{map,unmap}_addr(), mmu_demap_{page,context,all}(),
+ * and mmu_{map,unmap}_perm_addr().
+ */
+#define HV_MMU_DMMU			0x01
+#define HV_MMU_IMMU			0x02
+#define HV_MMU_ALL			(HV_MMU_DMMU | HV_MMU_IMMU)
+
+/* mmu_map_addr()
+ * TRAP:	HV_MMU_MAP_ADDR_TRAP
+ * ARG0:	virtual address
+ * ARG1:	mmu context
+ * ARG2:	TTE
+ * ARG3:	flags (HV_MMU_{IMMU,DMMU})
+ * ERRORS:	EINVAL		Invalid virtual address, mmu context, or flags
+ *		EBADPGSZ	Invalid page size value
+ *		ENORADDR	Invalid real address in TTE
+ *
+ * Create a non-permanent mapping using the given TTE, virtual
+ * address, and mmu context.  The flags argument determines which
+ * (data, or instruction, or both) TLB the mapping gets loaded into.
+ *
+ * The behavior is undefined if the valid bit is clear in the TTE.
+ *
+ * Note: This API call is for privileged code to specify temporary translation
+ *       mappings without the need to create and manage a TSB.
+ */
+
+/* mmu_unmap_addr()
+ * TRAP:	HV_MMU_UNMAP_ADDR_TRAP
+ * ARG0:	virtual address
+ * ARG1:	mmu context
+ * ARG2:	flags (HV_MMU_{IMMU,DMMU})
+ * ERRORS:	EINVAL		Invalid virtual address, mmu context, or flags
+ *
+ * Demaps the given virtual address in the given mmu context on this
+ * CPU.  This function is intended to be used to demap pages mapped
+ * with mmu_map_addr.  This service is equivalent to invoking
+ * mmu_demap_page() with only the current CPU in the CPU list. The
+ * flags argument determines which (data, or instruction, or both) TLB
+ * the mapping gets unmapped from.
+ *
+ * Attempting to perform an unmap operation for a previously defined
+ * permanent mapping will have undefined results.
+ */
+
+/* mmu_tsb_ctx0()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_MMU_TSB_CTX0
+ * ARG0:	number of TSB descriptions
+ * ARG1:	TSB descriptions pointer
+ * RET0:	status
+ * ERRORS:	ENORADDR		Invalid TSB descriptions pointer or
+ *					TSB base within a descriptor
+ *		EBADALIGN		TSB descriptions pointer is not aligned
+ *					to an 8-byte boundary, or TSB base
+ *					within a descriptor is not aligned for
+ *					the given TSB size
+ *		EBADPGSZ		Invalid page size in a TSB descriptor
+ *		EBADTSB			Invalid associativity or size in a TSB
+ *					descriptor
+ *		EINVAL			Invalid number of TSB descriptions, or
+ *					invalid context index in a TSB
+ *					descriptor, or index page size not
+ *					equal to smallest page size in page
+ *					size bitmask field.
+ *
+ * Configures the TSBs for the current CPU for virtual addresses with
+ * context zero.  The TSB descriptions pointer is a pointer to an
+ * array of the given number of TSB descriptions.
+ *
+ * Note: The maximum number of TSBs available to a virtual CPU is given by the
+ *       mmu-max-#tsbs property of the cpu's corresponding "cpu" node in the
+ *       machine description.
+ */
+#define HV_FAST_MMU_TSB_CTX0		0x20
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_mmu_tsb_ctx0(unsigned long num_descriptions,
+					unsigned long tsb_desc_ra);
+#endif
+
+/* mmu_tsb_ctxnon0()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_MMU_TSB_CTXNON0
+ * ARG0:	number of TSB descriptions
+ * ARG1:	TSB descriptions pointer
+ * RET0:	status
+ * ERRORS:	Same as for mmu_tsb_ctx0() above.
+ *
+ * Configures the TSBs for the current CPU for virtual addresses with
+ * non-zero contexts.  The TSB descriptions pointer is a pointer to an
+ * array of the given number of TSB descriptions.
+ *
+ * Note: A maximum of 16 TSBs may be specified in the TSB description list.
+ */
+#define HV_FAST_MMU_TSB_CTXNON0		0x21
+
+/* mmu_demap_page()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_MMU_DEMAP_PAGE
+ * ARG0:	reserved, must be zero
+ * ARG1:	reserved, must be zero
+ * ARG2:	virtual address
+ * ARG3:	mmu context
+ * ARG4:	flags (HV_MMU_{IMMU,DMMU})
+ * RET0:	status
+ * ERRORS:	EINVAL			Invalid virutal address, context, or
+ *					flags value
+ *		ENOTSUPPORTED		ARG0 or ARG1 is non-zero
+ *
+ * Demaps any page mapping of the given virtual address in the given
+ * mmu context for the current virtual CPU.  Any virtually tagged
+ * caches are guaranteed to be kept consistent.  The flags argument
+ * determines which TLB (instruction, or data, or both) participate in
+ * the operation.
+ *
+ * ARG0 and ARG1 are both reserved and must be set to zero.
+ */
+#define HV_FAST_MMU_DEMAP_PAGE		0x22
+
+/* mmu_demap_ctx()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_MMU_DEMAP_CTX
+ * ARG0:	reserved, must be zero
+ * ARG1:	reserved, must be zero
+ * ARG2:	mmu context
+ * ARG3:	flags (HV_MMU_{IMMU,DMMU})
+ * RET0:	status
+ * ERRORS:	EINVAL			Invalid context or flags value
+ *		ENOTSUPPORTED		ARG0 or ARG1 is non-zero
+ *
+ * Demaps all non-permanent virtual page mappings previously specified
+ * for the given context for the current virtual CPU.  Any virtual
+ * tagged caches are guaranteed to be kept consistent.  The flags
+ * argument determines which TLB (instruction, or data, or both)
+ * participate in the operation.
+ *
+ * ARG0 and ARG1 are both reserved and must be set to zero.
+ */
+#define HV_FAST_MMU_DEMAP_CTX		0x23
+
+/* mmu_demap_all()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_MMU_DEMAP_ALL
+ * ARG0:	reserved, must be zero
+ * ARG1:	reserved, must be zero
+ * ARG2:	flags (HV_MMU_{IMMU,DMMU})
+ * RET0:	status
+ * ERRORS:	EINVAL			Invalid flags value
+ *		ENOTSUPPORTED		ARG0 or ARG1 is non-zero
+ *
+ * Demaps all non-permanent virtual page mappings previously specified
+ * for the current virtual CPU.  Any virtual tagged caches are
+ * guaranteed to be kept consistent.  The flags argument determines
+ * which TLB (instruction, or data, or both) participate in the
+ * operation.
+ *
+ * ARG0 and ARG1 are both reserved and must be set to zero.
+ */
+#define HV_FAST_MMU_DEMAP_ALL		0x24
+
+#ifndef __ASSEMBLY__
+extern void sun4v_mmu_demap_all(void);
+#endif
+
+/* mmu_map_perm_addr()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_MMU_MAP_PERM_ADDR
+ * ARG0:	virtual address
+ * ARG1:	reserved, must be zero
+ * ARG2:	TTE
+ * ARG3:	flags (HV_MMU_{IMMU,DMMU})
+ * RET0:	status
+ * ERRORS:	EINVAL			Invalid virutal address or flags value
+ *		EBADPGSZ		Invalid page size value
+ *		ENORADDR		Invalid real address in TTE
+ *		ETOOMANY		Too many mappings (max of 8 reached)
+ *
+ * Create a permanent mapping using the given TTE and virtual address
+ * for context 0 on the calling virtual CPU.  A maximum of 8 such
+ * permanent mappings may be specified by privileged code.  Mappings
+ * may be removed with mmu_unmap_perm_addr().
+ *
+ * The behavior is undefined if a TTE with the valid bit clear is given.
+ *
+ * Note: This call is used to specify address space mappings for which
+ *       privileged code does not expect to receive misses.  For example,
+ *       this mechanism can be used to map kernel nucleus code and data.
+ */
+#define HV_FAST_MMU_MAP_PERM_ADDR	0x25
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_mmu_map_perm_addr(unsigned long vaddr,
+					     unsigned long set_to_zero,
+					     unsigned long tte,
+					     unsigned long flags);
+#endif
+
+/* mmu_fault_area_conf()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_MMU_FAULT_AREA_CONF
+ * ARG0:	real address
+ * RET0:	status
+ * RET1:	previous mmu fault area real address
+ * ERRORS:	ENORADDR		Invalid real address
+ *		EBADALIGN		Invalid alignment for fault area
+ *
+ * Configure the MMU fault status area for the calling CPU.  A 64-byte
+ * aligned real address specifies where MMU fault status information
+ * is placed.  The return value is the previously specified area, or 0
+ * for the first invocation.  Specifying a fault area at real address
+ * 0 is not allowed.
+ */
+#define HV_FAST_MMU_FAULT_AREA_CONF	0x26
+
+/* mmu_enable()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_MMU_ENABLE
+ * ARG0:	enable flag
+ * ARG1:	return target address
+ * RET0:	status
+ * ERRORS:	ENORADDR		Invalid real address when disabling
+ *					translation.
+ *		EBADALIGN		The return target address is not
+ *					aligned to an instruction.
+ *		EINVAL			The enable flag request the current
+ *					operating mode (e.g. disable if already
+ *					disabled)
+ *
+ * Enable or disable virtual address translation for the calling CPU
+ * within the virtual machine domain.  If the enable flag is zero,
+ * translation is disabled, any non-zero value will enable
+ * translation.
+ *
+ * When this function returns, the newly selected translation mode
+ * will be active.  If the mmu is being enabled, then the return
+ * target address is a virtual address else it is a real address.
+ *
+ * Upon successful completion, control will be returned to the given
+ * return target address (ie. the cpu will jump to that address).  On
+ * failure, the previous mmu mode remains and the trap simply returns
+ * as normal with the appropriate error code in RET0.
+ */
+#define HV_FAST_MMU_ENABLE		0x27
+
+/* mmu_unmap_perm_addr()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_MMU_UNMAP_PERM_ADDR
+ * ARG0:	virtual address
+ * ARG1:	reserved, must be zero
+ * ARG2:	flags (HV_MMU_{IMMU,DMMU})
+ * RET0:	status
+ * ERRORS:	EINVAL			Invalid virutal address or flags value
+ *		ENOMAP			Specified mapping was not found
+ *
+ * Demaps any permanent page mapping (established via
+ * mmu_map_perm_addr()) at the given virtual address for context 0 on
+ * the current virtual CPU.  Any virtual tagged caches are guaranteed
+ * to be kept consistent.
+ */
+#define HV_FAST_MMU_UNMAP_PERM_ADDR	0x28
+
+/* mmu_tsb_ctx0_info()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_MMU_TSB_CTX0_INFO
+ * ARG0:	max TSBs
+ * ARG1:	buffer pointer
+ * RET0:	status
+ * RET1:	number of TSBs
+ * ERRORS:	EINVAL			Supplied buffer is too small
+ *		EBADALIGN		The buffer pointer is badly aligned
+ *		ENORADDR		Invalid real address for buffer pointer
+ *
+ * Return the TSB configuration as previous defined by mmu_tsb_ctx0()
+ * into the provided buffer.  The size of the buffer is given in ARG1
+ * in terms of the number of TSB description entries.
+ *
+ * Upon return, RET1 always contains the number of TSB descriptions
+ * previously configured.  If zero TSBs were configured, EOK is
+ * returned with RET1 containing 0.
+ */
+#define HV_FAST_MMU_TSB_CTX0_INFO	0x29
+
+/* mmu_tsb_ctxnon0_info()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_MMU_TSB_CTXNON0_INFO
+ * ARG0:	max TSBs
+ * ARG1:	buffer pointer
+ * RET0:	status
+ * RET1:	number of TSBs
+ * ERRORS:	EINVAL			Supplied buffer is too small
+ *		EBADALIGN		The buffer pointer is badly aligned
+ *		ENORADDR		Invalid real address for buffer pointer
+ *
+ * Return the TSB configuration as previous defined by
+ * mmu_tsb_ctxnon0() into the provided buffer.  The size of the buffer
+ * is given in ARG1 in terms of the number of TSB description entries.
+ *
+ * Upon return, RET1 always contains the number of TSB descriptions
+ * previously configured.  If zero TSBs were configured, EOK is
+ * returned with RET1 containing 0.
+ */
+#define HV_FAST_MMU_TSB_CTXNON0_INFO	0x2a
+
+/* mmu_fault_area_info()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_MMU_FAULT_AREA_INFO
+ * RET0:	status
+ * RET1:	fault area real address
+ * ERRORS:	No errors defined.
+ *
+ * Return the currently defined MMU fault status area for the current
+ * CPU.  The real address of the fault status area is returned in
+ * RET1, or 0 is returned in RET1 if no fault status area is defined.
+ *
+ * Note: mmu_fault_area_conf() may be called with the return value (RET1)
+ *       from this service if there is a need to save and restore the fault
+ *	 area for a cpu.
+ */
+#define HV_FAST_MMU_FAULT_AREA_INFO	0x2b
+
+/* Cache and Memory services. */
+
+/* mem_scrub()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_MEM_SCRUB
+ * ARG0:	real address
+ * ARG1:	length
+ * RET0:	status
+ * RET1:	length scrubbed
+ * ERRORS:	ENORADDR	Invalid real address
+ *		EBADALIGN	Start address or length are not correctly
+ *				aligned
+ *		EINVAL		Length is zero
+ *
+ * Zero the memory contents in the range real address to real address
+ * plus length minus 1.  Also, valid ECC will be generated for that
+ * memory address range.  Scrubbing is started at the given real
+ * address, but may not scrub the entire given length.  The actual
+ * length scrubbed will be returned in RET1.
+ *
+ * The real address and length must be aligned on an 8K boundary, or
+ * contain the start address and length from a sun4v error report.
+ *
+ * Note: There are two uses for this function.  The first use is to block clear
+ *       and initialize memory and the second is to scrub an u ncorrectable
+ *       error reported via a resumable or non-resumable trap.  The second
+ *       use requires the arguments to be equal to the real address and length
+ *       provided in a sun4v memory error report.
+ */
+#define HV_FAST_MEM_SCRUB		0x31
+
+/* mem_sync()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_MEM_SYNC
+ * ARG0:	real address
+ * ARG1:	length
+ * RET0:	status
+ * RET1:	length synced
+ * ERRORS:	ENORADDR	Invalid real address
+ *		EBADALIGN	Start address or length are not correctly
+ *				aligned
+ *		EINVAL		Length is zero
+ *
+ * Force the next access within the real address to real address plus
+ * length minus 1 to be fetches from main system memory.  Less than
+ * the given length may be synced, the actual amount synced is
+ * returned in RET1.  The real address and length must be aligned on
+ * an 8K boundary.
+ */
+#define HV_FAST_MEM_SYNC		0x32
+
+/* Time of day services.
+ *
+ * The hypervisor maintains the time of day on a per-domain basis.
+ * Changing the time of day in one domain does not affect the time of
+ * day on any other domain.
+ *
+ * Time is described by a single unsigned 64-bit word which is the
+ * number of seconds since the UNIX Epoch (00:00:00 UTC, January 1,
+ * 1970).
+ */
+
+/* tod_get()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_TOD_GET
+ * RET0:	status
+ * RET1:	TOD
+ * ERRORS:	EWOULDBLOCK	TOD resource is temporarily unavailable
+ *		ENOTSUPPORTED	If TOD not supported on this platform
+ *
+ * Return the current time of day.  May block if TOD access is
+ * temporarily not possible.
+ */
+#define HV_FAST_TOD_GET			0x50
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_tod_get(unsigned long *time);
+#endif
+
+/* tod_set()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_TOD_SET
+ * ARG0:	TOD
+ * RET0:	status
+ * ERRORS:	EWOULDBLOCK	TOD resource is temporarily unavailable
+ *		ENOTSUPPORTED	If TOD not supported on this platform
+ *
+ * The current time of day is set to the value specified in ARG0.  May
+ * block if TOD access is temporarily not possible.
+ */
+#define HV_FAST_TOD_SET			0x51
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_tod_set(unsigned long time);
+#endif
+
+/* Console services */
+
+/* con_getchar()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_CONS_GETCHAR
+ * RET0:	status
+ * RET1:	character
+ * ERRORS:	EWOULDBLOCK	No character available.
+ *
+ * Returns a character from the console device.  If no character is
+ * available then an EWOULDBLOCK error is returned.  If a character is
+ * available, then the returned status is EOK and the character value
+ * is in RET1.
+ *
+ * A virtual BREAK is represented by the 64-bit value -1.
+ *
+ * A virtual HUP signal is represented by the 64-bit value -2.
+ */
+#define HV_FAST_CONS_GETCHAR		0x60
+
+/* con_putchar()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_CONS_PUTCHAR
+ * ARG0:	character
+ * RET0:	status
+ * ERRORS:	EINVAL		Illegal character
+ *		EWOULDBLOCK	Output buffer currently full, would block
+ *
+ * Send a character to the console device.  Only character values
+ * between 0 and 255 may be used.  Values outside this range are
+ * invalid except for the 64-bit value -1 which is used to send a
+ * virtual BREAK.
+ */
+#define HV_FAST_CONS_PUTCHAR		0x61
+
+/* con_read()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_CONS_READ
+ * ARG0:	buffer real address
+ * ARG1:	buffer size in bytes
+ * RET0:	status
+ * RET1:	bytes read or BREAK or HUP
+ * ERRORS:	EWOULDBLOCK	No character available.
+ *
+ * Reads characters into a buffer from the console device.  If no
+ * character is available then an EWOULDBLOCK error is returned.
+ * If a character is available, then the returned status is EOK
+ * and the number of bytes read into the given buffer is provided
+ * in RET1.
+ *
+ * A virtual BREAK is represented by the 64-bit RET1 value -1.
+ *
+ * A virtual HUP signal is represented by the 64-bit RET1 value -2.
+ *
+ * If BREAK or HUP are indicated, no bytes were read into buffer.
+ */
+#define HV_FAST_CONS_READ		0x62
+
+/* con_write()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_CONS_WRITE
+ * ARG0:	buffer real address
+ * ARG1:	buffer size in bytes
+ * RET0:	status
+ * RET1:	bytes written
+ * ERRORS:	EWOULDBLOCK	Output buffer currently full, would block
+ *
+ * Send a characters in buffer to the console device.  Breaks must be
+ * sent using con_putchar().
+ */
+#define HV_FAST_CONS_WRITE		0x63
+
+#ifndef __ASSEMBLY__
+extern long sun4v_con_getchar(long *status);
+extern long sun4v_con_putchar(long c);
+extern long sun4v_con_read(unsigned long buffer,
+			   unsigned long size,
+			   unsigned long *bytes_read);
+extern unsigned long sun4v_con_write(unsigned long buffer,
+				     unsigned long size,
+				     unsigned long *bytes_written);
+#endif
+
+/* mach_set_soft_state()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_MACH_SET_SOFT_STATE
+ * ARG0:	software state
+ * ARG1:	software state description pointer
+ * RET0:	status
+ * ERRORS:	EINVAL		software state not valid or software state
+ *				description is not NULL terminated
+ *		ENORADDR	software state description pointer is not a
+ *				valid real address
+ *		EBADALIGNED	software state description is not correctly
+ *				aligned
+ *
+ * This allows the guest to report it's soft state to the hypervisor.  There
+ * are two primary components to this state.  The first part states whether
+ * the guest software is running or not.  The second containts optional
+ * details specific to the software.
+ *
+ * The software state argument is defined below in HV_SOFT_STATE_*, and
+ * indicates whether the guest is operating normally or in a transitional
+ * state.
+ *
+ * The software state description argument is a real address of a data buffer
+ * of size 32-bytes aligned on a 32-byte boundary.  It is treated as a NULL
+ * terminated 7-bit ASCII string of up to 31 characters not including the
+ * NULL termination.
+ */
+#define HV_FAST_MACH_SET_SOFT_STATE	0x70
+#define  HV_SOFT_STATE_NORMAL		 0x01
+#define  HV_SOFT_STATE_TRANSITION	 0x02
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_mach_set_soft_state(unsigned long soft_state,
+					       unsigned long msg_string_ra);
+#endif
+
+/* mach_get_soft_state()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_MACH_GET_SOFT_STATE
+ * ARG0:	software state description pointer
+ * RET0:	status
+ * RET1:	software state
+ * ERRORS:	ENORADDR	software state description pointer is not a
+ *				valid real address
+ *		EBADALIGNED	software state description is not correctly
+ *				aligned
+ *
+ * Retrieve the current value of the guest's software state.  The rules
+ * for the software state pointer are the same as for mach_set_soft_state()
+ * above.
+ */
+#define HV_FAST_MACH_GET_SOFT_STATE	0x71
+
+/* svc_send()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_SVC_SEND
+ * ARG0:	service ID
+ * ARG1:	buffer real address
+ * ARG2:	buffer size
+ * RET0:	STATUS
+ * RET1:	sent_bytes
+ *
+ * Be careful, all output registers are clobbered by this operation,
+ * so for example it is not possible to save away a value in %o4
+ * across the trap.
+ */
+#define HV_FAST_SVC_SEND		0x80
+
+/* svc_recv()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_SVC_RECV
+ * ARG0:	service ID
+ * ARG1:	buffer real address
+ * ARG2:	buffer size
+ * RET0:	STATUS
+ * RET1:	recv_bytes
+ *
+ * Be careful, all output registers are clobbered by this operation,
+ * so for example it is not possible to save away a value in %o4
+ * across the trap.
+ */
+#define HV_FAST_SVC_RECV		0x81
+
+/* svc_getstatus()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_SVC_GETSTATUS
+ * ARG0:	service ID
+ * RET0:	STATUS
+ * RET1:	status bits
+ */
+#define HV_FAST_SVC_GETSTATUS		0x82
+
+/* svc_setstatus()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_SVC_SETSTATUS
+ * ARG0:	service ID
+ * ARG1:	bits to set
+ * RET0:	STATUS
+ */
+#define HV_FAST_SVC_SETSTATUS		0x83
+
+/* svc_clrstatus()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_SVC_CLRSTATUS
+ * ARG0:	service ID
+ * ARG1:	bits to clear
+ * RET0:	STATUS
+ */
+#define HV_FAST_SVC_CLRSTATUS		0x84
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_svc_send(unsigned long svc_id,
+				    unsigned long buffer,
+				    unsigned long buffer_size,
+				    unsigned long *sent_bytes);
+extern unsigned long sun4v_svc_recv(unsigned long svc_id,
+				    unsigned long buffer,
+				    unsigned long buffer_size,
+				    unsigned long *recv_bytes);
+extern unsigned long sun4v_svc_getstatus(unsigned long svc_id,
+					 unsigned long *status_bits);
+extern unsigned long sun4v_svc_setstatus(unsigned long svc_id,
+					 unsigned long status_bits);
+extern unsigned long sun4v_svc_clrstatus(unsigned long svc_id,
+					 unsigned long status_bits);
+#endif
+
+/* Trap trace services.
+ *
+ * The hypervisor provides a trap tracing capability for privileged
+ * code running on each virtual CPU.  Privileged code provides a
+ * round-robin trap trace queue within which the hypervisor writes
+ * 64-byte entries detailing hyperprivileged traps taken n behalf of
+ * privileged code.  This is provided as a debugging capability for
+ * privileged code.
+ *
+ * The trap trace control structure is 64-bytes long and placed at the
+ * start (offset 0) of the trap trace buffer, and is described as
+ * follows:
+ */
+#ifndef __ASSEMBLY__
+struct hv_trap_trace_control {
+	unsigned long		head_offset;
+	unsigned long		tail_offset;
+	unsigned long		__reserved[0x30 / sizeof(unsigned long)];
+};
+#endif
+#define HV_TRAP_TRACE_CTRL_HEAD_OFFSET	0x00
+#define HV_TRAP_TRACE_CTRL_TAIL_OFFSET	0x08
+
+/* The head offset is the offset of the most recently completed entry
+ * in the trap-trace buffer.  The tail offset is the offset of the
+ * next entry to be written.  The control structure is owned and
+ * modified by the hypervisor.  A guest may not modify the control
+ * structure contents.  Attempts to do so will result in undefined
+ * behavior for the guest.
+ *
+ * Each trap trace buffer entry is layed out as follows:
+ */
+#ifndef __ASSEMBLY__
+struct hv_trap_trace_entry {
+	unsigned char	type;		/* Hypervisor or guest entry?	*/
+	unsigned char	hpstate;	/* Hyper-privileged state	*/
+	unsigned char	tl;		/* Trap level			*/
+	unsigned char	gl;		/* Global register level	*/
+	unsigned short	tt;		/* Trap type			*/
+	unsigned short	tag;		/* Extended trap identifier	*/
+	unsigned long	tstate;		/* Trap state			*/
+	unsigned long	tick;		/* Tick				*/
+	unsigned long	tpc;		/* Trap PC			*/
+	unsigned long	f1;		/* Entry specific		*/
+	unsigned long	f2;		/* Entry specific		*/
+	unsigned long	f3;		/* Entry specific		*/
+	unsigned long	f4;		/* Entry specific		*/
+};
+#endif
+#define HV_TRAP_TRACE_ENTRY_TYPE	0x00
+#define HV_TRAP_TRACE_ENTRY_HPSTATE	0x01
+#define HV_TRAP_TRACE_ENTRY_TL		0x02
+#define HV_TRAP_TRACE_ENTRY_GL		0x03
+#define HV_TRAP_TRACE_ENTRY_TT		0x04
+#define HV_TRAP_TRACE_ENTRY_TAG		0x06
+#define HV_TRAP_TRACE_ENTRY_TSTATE	0x08
+#define HV_TRAP_TRACE_ENTRY_TICK	0x10
+#define HV_TRAP_TRACE_ENTRY_TPC		0x18
+#define HV_TRAP_TRACE_ENTRY_F1		0x20
+#define HV_TRAP_TRACE_ENTRY_F2		0x28
+#define HV_TRAP_TRACE_ENTRY_F3		0x30
+#define HV_TRAP_TRACE_ENTRY_F4		0x38
+
+/* The type field is encoded as follows.  */
+#define HV_TRAP_TYPE_UNDEF		0x00 /* Entry content undefined     */
+#define HV_TRAP_TYPE_HV			0x01 /* Hypervisor trap entry       */
+#define HV_TRAP_TYPE_GUEST		0xff /* Added via ttrace_addentry() */
+
+/* ttrace_buf_conf()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_TTRACE_BUF_CONF
+ * ARG0:	real address
+ * ARG1:	number of entries
+ * RET0:	status
+ * RET1:	number of entries
+ * ERRORS:	ENORADDR	Invalid real address
+ *		EINVAL		Size is too small
+ *		EBADALIGN	Real address not aligned on 64-byte boundary
+ *
+ * Requests hypervisor trap tracing and declares a virtual CPU's trap
+ * trace buffer to the hypervisor.  The real address supplies the real
+ * base address of the trap trace queue and must be 64-byte aligned.
+ * Specifying a value of 0 for the number of entries disables trap
+ * tracing for the calling virtual CPU.  The buffer allocated must be
+ * sized for a power of two number of 64-byte trap trace entries plus
+ * an initial 64-byte control structure.
+ *
+ * This may be invoked any number of times so that a virtual CPU may
+ * relocate a trap trace buffer or create "snapshots" of information.
+ *
+ * If the real address is illegal or badly aligned, then trap tracing
+ * is disabled and an error is returned.
+ *
+ * Upon failure with EINVAL, this service call returns in RET1 the
+ * minimum number of buffer entries required.  Upon other failures
+ * RET1 is undefined.
+ */
+#define HV_FAST_TTRACE_BUF_CONF		0x90
+
+/* ttrace_buf_info()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_TTRACE_BUF_INFO
+ * RET0:	status
+ * RET1:	real address
+ * RET2:	size
+ * ERRORS:	None defined.
+ *
+ * Returns the size and location of the previously declared trap-trace
+ * buffer.  In the event that no buffer was previously defined, or the
+ * buffer is disabled, this call will return a size of zero bytes.
+ */
+#define HV_FAST_TTRACE_BUF_INFO		0x91
+
+/* ttrace_enable()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_TTRACE_ENABLE
+ * ARG0:	enable
+ * RET0:	status
+ * RET1:	previous enable state
+ * ERRORS:	EINVAL		No trap trace buffer currently defined
+ *
+ * Enable or disable trap tracing, and return the previous enabled
+ * state in RET1.  Future systems may define various flags for the
+ * enable argument (ARG0), for the moment a guest should pass
+ * "(uint64_t) -1" to enable, and "(uint64_t) 0" to disable all
+ * tracing - which will ensure future compatability.
+ */
+#define HV_FAST_TTRACE_ENABLE		0x92
+
+/* ttrace_freeze()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_TTRACE_FREEZE
+ * ARG0:	freeze
+ * RET0:	status
+ * RET1:	previous freeze state
+ * ERRORS:	EINVAL		No trap trace buffer currently defined
+ *
+ * Freeze or unfreeze trap tracing, returning the previous freeze
+ * state in RET1.  A guest should pass a non-zero value to freeze and
+ * a zero value to unfreeze all tracing.  The returned previous state
+ * is 0 for not frozen and 1 for frozen.
+ */
+#define HV_FAST_TTRACE_FREEZE		0x93
+
+/* ttrace_addentry()
+ * TRAP:	HV_TTRACE_ADDENTRY_TRAP
+ * ARG0:	tag (16-bits)
+ * ARG1:	data word 0
+ * ARG2:	data word 1
+ * ARG3:	data word 2
+ * ARG4:	data word 3
+ * RET0:	status
+ * ERRORS:	EINVAL		No trap trace buffer currently defined
+ *
+ * Add an entry to the trap trace buffer.  Upon return only ARG0/RET0
+ * is modified - none of the other registers holding arguments are
+ * volatile across this hypervisor service.
+ */
+
+/* Core dump services.
+ *
+ * Since the hypervisor viraulizes and thus obscures a lot of the
+ * physical machine layout and state, traditional OS crash dumps can
+ * be difficult to diagnose especially when the problem is a
+ * configuration error of some sort.
+ *
+ * The dump services provide an opaque buffer into which the
+ * hypervisor can place it's internal state in order to assist in
+ * debugging such situations.  The contents are opaque and extremely
+ * platform and hypervisor implementation specific.  The guest, during
+ * a core dump, requests that the hypervisor update any information in
+ * the dump buffer in preparation to being dumped as part of the
+ * domain's memory image.
+ */
+
+/* dump_buf_update()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_DUMP_BUF_UPDATE
+ * ARG0:	real address
+ * ARG1:	size
+ * RET0:	status
+ * RET1:	required size of dump buffer
+ * ERRORS:	ENORADDR	Invalid real address
+ *		EBADALIGN	Real address is not aligned on a 64-byte
+ *				boundary
+ *		EINVAL		Size is non-zero but less than minimum size
+ *				required
+ *		ENOTSUPPORTED	Operation not supported on current logical
+ *				domain
+ *
+ * Declare a domain dump buffer to the hypervisor.  The real address
+ * provided for the domain dump buffer must be 64-byte aligned.  The
+ * size specifies the size of the dump buffer and may be larger than
+ * the minimum size specified in the machine description.  The
+ * hypervisor will fill the dump buffer with opaque data.
+ *
+ * Note: A guest may elect to include dump buffer contents as part of a crash
+ *       dump to assist with debugging.  This function may be called any number
+ *       of times so that a guest may relocate a dump buffer, or create
+ *       "snapshots" of any dump-buffer information.  Each call to
+ *       dump_buf_update() atomically declares the new dump buffer to the
+ *       hypervisor.
+ *
+ * A specified size of 0 unconfigures the dump buffer.  If the real
+ * address is illegal or badly aligned, then any currently active dump
+ * buffer is disabled and an error is returned.
+ *
+ * In the event that the call fails with EINVAL, RET1 contains the
+ * minimum size requires by the hypervisor for a valid dump buffer.
+ */
+#define HV_FAST_DUMP_BUF_UPDATE		0x94
+
+/* dump_buf_info()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_DUMP_BUF_INFO
+ * RET0:	status
+ * RET1:	real address of current dump buffer
+ * RET2:	size of current dump buffer
+ * ERRORS:	No errors defined.
+ *
+ * Return the currently configures dump buffer description.  A
+ * returned size of 0 bytes indicates an undefined dump buffer.  In
+ * this case the return address in RET1 is undefined.
+ */
+#define HV_FAST_DUMP_BUF_INFO		0x95
+
+/* Device interrupt services.
+ *
+ * Device interrupts are allocated to system bus bridges by the hypervisor,
+ * and described to OBP in the machine description.  OBP then describes
+ * these interrupts to the OS via properties in the device tree.
+ *
+ * Terminology:
+ *
+ *	cpuid		Unique opaque value which represents a target cpu.
+ *
+ *	devhandle	Device handle.  It uniquely identifies a device, and
+ *			consistes of the lower 28-bits of the hi-cell of the
+ *			first entry of the device's "reg" property in the
+ *			OBP device tree.
+ *
+ *	devino		Device interrupt number.  Specifies the relative
+ *			interrupt number within the device.  The unique
+ *			combination of devhandle and devino are used to
+ *			identify a specific device interrupt.
+ *
+ *			Note: The devino value is the same as the values in the
+ *			      "interrupts" property or "interrupt-map" property
+ *			      in the OBP device tree for that device.
+ *
+ *	sysino		System interrupt number.  A 64-bit unsigned interger
+ *			representing a unique interrupt within a virtual
+ *			machine.
+ *
+ *	intr_state	A flag representing the interrupt state for a given
+ *			sysino.  The state values are defined below.
+ *
+ *	intr_enabled	A flag representing the 'enabled' state for a given
+ *			sysino.  The enable values are defined below.
+ */
+
+#define HV_INTR_STATE_IDLE		0 /* Nothing pending */
+#define HV_INTR_STATE_RECEIVED		1 /* Interrupt received by hardware */
+#define HV_INTR_STATE_DELIVERED		2 /* Interrupt delivered to queue */
+
+#define HV_INTR_DISABLED		0 /* sysino not enabled */
+#define HV_INTR_ENABLED			1 /* sysino enabled */
+
+/* intr_devino_to_sysino()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_INTR_DEVINO2SYSINO
+ * ARG0:	devhandle
+ * ARG1:	devino
+ * RET0:	status
+ * RET1:	sysino
+ * ERRORS:	EINVAL		Invalid devhandle/devino
+ *
+ * Converts a device specific interrupt number of the given
+ * devhandle/devino into a system specific ino (sysino).
+ */
+#define HV_FAST_INTR_DEVINO2SYSINO	0xa0
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_devino_to_sysino(unsigned long devhandle,
+					    unsigned long devino);
+#endif
+
+/* intr_getenabled()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_INTR_GETENABLED
+ * ARG0:	sysino
+ * RET0:	status
+ * RET1:	intr_enabled (HV_INTR_{DISABLED,ENABLED})
+ * ERRORS:	EINVAL		Invalid sysino
+ *
+ * Returns interrupt enabled state in RET1 for the interrupt defined
+ * by the given sysino.
+ */
+#define HV_FAST_INTR_GETENABLED		0xa1
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_intr_getenabled(unsigned long sysino);
+#endif
+
+/* intr_setenabled()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_INTR_SETENABLED
+ * ARG0:	sysino
+ * ARG1:	intr_enabled (HV_INTR_{DISABLED,ENABLED})
+ * RET0:	status
+ * ERRORS:	EINVAL		Invalid sysino or intr_enabled value
+ *
+ * Set the 'enabled' state of the interrupt sysino.
+ */
+#define HV_FAST_INTR_SETENABLED		0xa2
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_intr_setenabled(unsigned long sysino, unsigned long intr_enabled);
+#endif
+
+/* intr_getstate()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_INTR_GETSTATE
+ * ARG0:	sysino
+ * RET0:	status
+ * RET1:	intr_state (HV_INTR_STATE_*)
+ * ERRORS:	EINVAL		Invalid sysino
+ *
+ * Returns current state of the interrupt defined by the given sysino.
+ */
+#define HV_FAST_INTR_GETSTATE		0xa3
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_intr_getstate(unsigned long sysino);
+#endif
+
+/* intr_setstate()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_INTR_SETSTATE
+ * ARG0:	sysino
+ * ARG1:	intr_state (HV_INTR_STATE_*)
+ * RET0:	status
+ * ERRORS:	EINVAL		Invalid sysino or intr_state value
+ *
+ * Sets the current state of the interrupt described by the given sysino
+ * value.
+ *
+ * Note: Setting the state to HV_INTR_STATE_IDLE clears any pending
+ *       interrupt for sysino.
+ */
+#define HV_FAST_INTR_SETSTATE		0xa4
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_intr_setstate(unsigned long sysino, unsigned long intr_state);
+#endif
+
+/* intr_gettarget()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_INTR_GETTARGET
+ * ARG0:	sysino
+ * RET0:	status
+ * RET1:	cpuid
+ * ERRORS:	EINVAL		Invalid sysino
+ *
+ * Returns CPU that is the current target of the interrupt defined by
+ * the given sysino.  The CPU value returned is undefined if the target
+ * has not been set via intr_settarget().
+ */
+#define HV_FAST_INTR_GETTARGET		0xa5
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_intr_gettarget(unsigned long sysino);
+#endif
+
+/* intr_settarget()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_INTR_SETTARGET
+ * ARG0:	sysino
+ * ARG1:	cpuid
+ * RET0:	status
+ * ERRORS:	EINVAL		Invalid sysino
+ *		ENOCPU		Invalid cpuid
+ *
+ * Set the target CPU for the interrupt defined by the given sysino.
+ */
+#define HV_FAST_INTR_SETTARGET		0xa6
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_intr_settarget(unsigned long sysino, unsigned long cpuid);
+#endif
+
+/* vintr_get_cookie()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_VINTR_GET_COOKIE
+ * ARG0:	device handle
+ * ARG1:	device ino
+ * RET0:	status
+ * RET1:	cookie
+ */
+#define HV_FAST_VINTR_GET_COOKIE	0xa7
+
+/* vintr_set_cookie()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_VINTR_SET_COOKIE
+ * ARG0:	device handle
+ * ARG1:	device ino
+ * ARG2:	cookie
+ * RET0:	status
+ */
+#define HV_FAST_VINTR_SET_COOKIE	0xa8
+
+/* vintr_get_valid()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_VINTR_GET_VALID
+ * ARG0:	device handle
+ * ARG1:	device ino
+ * RET0:	status
+ * RET1:	valid state
+ */
+#define HV_FAST_VINTR_GET_VALID		0xa9
+
+/* vintr_set_valid()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_VINTR_SET_VALID
+ * ARG0:	device handle
+ * ARG1:	device ino
+ * ARG2:	valid state
+ * RET0:	status
+ */
+#define HV_FAST_VINTR_SET_VALID		0xaa
+
+/* vintr_get_state()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_VINTR_GET_STATE
+ * ARG0:	device handle
+ * ARG1:	device ino
+ * RET0:	status
+ * RET1:	state
+ */
+#define HV_FAST_VINTR_GET_STATE		0xab
+
+/* vintr_set_state()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_VINTR_SET_STATE
+ * ARG0:	device handle
+ * ARG1:	device ino
+ * ARG2:	state
+ * RET0:	status
+ */
+#define HV_FAST_VINTR_SET_STATE		0xac
+
+/* vintr_get_target()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_VINTR_GET_TARGET
+ * ARG0:	device handle
+ * ARG1:	device ino
+ * RET0:	status
+ * RET1:	cpuid
+ */
+#define HV_FAST_VINTR_GET_TARGET	0xad
+
+/* vintr_set_target()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_VINTR_SET_TARGET
+ * ARG0:	device handle
+ * ARG1:	device ino
+ * ARG2:	cpuid
+ * RET0:	status
+ */
+#define HV_FAST_VINTR_SET_TARGET	0xae
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_vintr_get_cookie(unsigned long dev_handle,
+					    unsigned long dev_ino,
+					    unsigned long *cookie);
+extern unsigned long sun4v_vintr_set_cookie(unsigned long dev_handle,
+					    unsigned long dev_ino,
+					    unsigned long cookie);
+extern unsigned long sun4v_vintr_get_valid(unsigned long dev_handle,
+					   unsigned long dev_ino,
+					   unsigned long *valid);
+extern unsigned long sun4v_vintr_set_valid(unsigned long dev_handle,
+					   unsigned long dev_ino,
+					   unsigned long valid);
+extern unsigned long sun4v_vintr_get_state(unsigned long dev_handle,
+					   unsigned long dev_ino,
+					   unsigned long *state);
+extern unsigned long sun4v_vintr_set_state(unsigned long dev_handle,
+					   unsigned long dev_ino,
+					   unsigned long state);
+extern unsigned long sun4v_vintr_get_target(unsigned long dev_handle,
+					    unsigned long dev_ino,
+					    unsigned long *cpuid);
+extern unsigned long sun4v_vintr_set_target(unsigned long dev_handle,
+					    unsigned long dev_ino,
+					    unsigned long cpuid);
+#endif
+
+/* PCI IO services.
+ *
+ * See the terminology descriptions in the device interrupt services
+ * section above as those apply here too.  Here are terminology
+ * definitions specific to these PCI IO services:
+ *
+ *	tsbnum		TSB number.  Indentifies which io-tsb is used.
+ *			For this version of the specification, tsbnum
+ *			must be zero.
+ *
+ *	tsbindex	TSB index.  Identifies which entry in the TSB
+ *			is used.  The first entry is zero.
+ *
+ *	tsbid		A 64-bit aligned data structure which contains
+ *			a tsbnum and a tsbindex.  Bits 63:32 contain the
+ *			tsbnum and bits 31:00 contain the tsbindex.
+ *
+ *			Use the HV_PCI_TSBID() macro to construct such
+ * 			values.
+ *
+ *	io_attributes	IO attributes for IOMMU mappings.  One of more
+ *			of the attritbute bits are stores in a 64-bit
+ *			value.  The values are defined below.
+ *
+ *	r_addr		64-bit real address
+ *
+ *	pci_device	PCI device address.  A PCI device address identifies
+ *			a specific device on a specific PCI bus segment.
+ *			A PCI device address ia a 32-bit unsigned integer
+ *			with the following format:
+ *
+ *				00000000.bbbbbbbb.dddddfff.00000000
+ *
+ *			Use the HV_PCI_DEVICE_BUILD() macro to construct
+ *			such values.
+ *
+ *	pci_config_offset
+ *			PCI configureation space offset.  For conventional
+ *			PCI a value between 0 and 255.  For extended
+ *			configuration space, a value between 0 and 4095.
+ *
+ *			Note: For PCI configuration space accesses, the offset
+ *			      must be aligned to the access size.
+ *
+ *	error_flag	A return value which specifies if the action succeeded
+ *			or failed.  0 means no error, non-0 means some error
+ *			occurred while performing the service.
+ *
+ *	io_sync_direction
+ *			Direction definition for pci_dma_sync(), defined
+ *			below in HV_PCI_SYNC_*.
+ *
+ *	io_page_list	A list of io_page_addresses, an io_page_address is
+ *			a real address.
+ *
+ *	io_page_list_p	A pointer to an io_page_list.
+ *
+ *	"size based byte swap" - Some functions do size based byte swapping
+ *				 which allows sw to access pointers and
+ *				 counters in native form when the processor
+ *				 operates in a different endianness than the
+ *				 IO bus.  Size-based byte swapping converts a
+ *				 multi-byte field between big-endian and
+ *				 little-endian format.
+ */
+
+#define HV_PCI_MAP_ATTR_READ		0x01
+#define HV_PCI_MAP_ATTR_WRITE		0x02
+
+#define HV_PCI_DEVICE_BUILD(b,d,f)	\
+	((((b) & 0xff) << 16) | \
+	 (((d) & 0x1f) << 11) | \
+	 (((f) & 0x07) <<  8))
+
+#define HV_PCI_TSBID(__tsb_num, __tsb_index) \
+	((((u64)(__tsb_num)) << 32UL) | ((u64)(__tsb_index)))
+
+#define HV_PCI_SYNC_FOR_DEVICE		0x01
+#define HV_PCI_SYNC_FOR_CPU		0x02
+
+/* pci_iommu_map()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_IOMMU_MAP
+ * ARG0:	devhandle
+ * ARG1:	tsbid
+ * ARG2:	#ttes
+ * ARG3:	io_attributes
+ * ARG4:	io_page_list_p
+ * RET0:	status
+ * RET1:	#ttes mapped
+ * ERRORS:	EINVAL		Invalid devhandle/tsbnum/tsbindex/io_attributes
+ *		EBADALIGN	Improperly aligned real address
+ *		ENORADDR	Invalid real address
+ *
+ * Create IOMMU mappings in the sun4v device defined by the given
+ * devhandle.  The mappings are created in the TSB defined by the
+ * tsbnum component of the given tsbid.  The first mapping is created
+ * in the TSB i ndex defined by the tsbindex component of the given tsbid.
+ * The call creates up to #ttes mappings, the first one at tsbnum, tsbindex,
+ * the second at tsbnum, tsbindex + 1, etc.
+ *
+ * All mappings are created with the attributes defined by the io_attributes
+ * argument.  The page mapping addresses are described in the io_page_list
+ * defined by the given io_page_list_p, which is a pointer to the io_page_list.
+ * The first entry in the io_page_list is the address for the first iotte, the
+ * 2nd for the 2nd iotte, and so on.
+ *
+ * Each io_page_address in the io_page_list must be appropriately aligned.
+ * #ttes must be greater than zero.  For this version of the spec, the tsbnum
+ * component of the given tsbid must be zero.
+ *
+ * Returns the actual number of mappings creates, which may be less than
+ * or equal to the argument #ttes.  If the function returns a value which
+ * is less than the #ttes, the caller may continus to call the function with
+ * an updated tsbid, #ttes, io_page_list_p arguments until all pages are
+ * mapped.
+ *
+ * Note: This function does not imply an iotte cache flush.  The guest must
+ *       demap an entry before re-mapping it.
+ */
+#define HV_FAST_PCI_IOMMU_MAP		0xb0
+
+/* pci_iommu_demap()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_IOMMU_DEMAP
+ * ARG0:	devhandle
+ * ARG1:	tsbid
+ * ARG2:	#ttes
+ * RET0:	status
+ * RET1:	#ttes demapped
+ * ERRORS:	EINVAL		Invalid devhandle/tsbnum/tsbindex
+ *
+ * Demap and flush IOMMU mappings in the device defined by the given
+ * devhandle.  Demaps up to #ttes entries in the TSB defined by the tsbnum
+ * component of the given tsbid, starting at the TSB index defined by the
+ * tsbindex component of the given tsbid.
+ *
+ * For this version of the spec, the tsbnum of the given tsbid must be zero.
+ * #ttes must be greater than zero.
+ *
+ * Returns the actual number of ttes demapped, which may be less than or equal
+ * to the argument #ttes.  If #ttes demapped is less than #ttes, the caller
+ * may continue to call this function with updated tsbid and #ttes arguments
+ * until all pages are demapped.
+ *
+ * Note: Entries do not have to be mapped to be demapped.  A demap of an
+ *       unmapped page will flush the entry from the tte cache.
+ */
+#define HV_FAST_PCI_IOMMU_DEMAP		0xb1
+
+/* pci_iommu_getmap()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_IOMMU_GETMAP
+ * ARG0:	devhandle
+ * ARG1:	tsbid
+ * RET0:	status
+ * RET1:	io_attributes
+ * RET2:	real address
+ * ERRORS:	EINVAL		Invalid devhandle/tsbnum/tsbindex
+ *		ENOMAP		Mapping is not valid, no translation exists
+ *
+ * Read and return the mapping in the device described by the given devhandle
+ * and tsbid.  If successful, the io_attributes shall be returned in RET1
+ * and the page address of the mapping shall be returned in RET2.
+ *
+ * For this version of the spec, the tsbnum component of the given tsbid
+ * must be zero.
+ */
+#define HV_FAST_PCI_IOMMU_GETMAP	0xb2
+
+/* pci_iommu_getbypass()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_IOMMU_GETBYPASS
+ * ARG0:	devhandle
+ * ARG1:	real address
+ * ARG2:	io_attributes
+ * RET0:	status
+ * RET1:	io_addr
+ * ERRORS:	EINVAL		Invalid devhandle/io_attributes
+ *		ENORADDR	Invalid real address
+ *		ENOTSUPPORTED	Function not supported in this implementation.
+ *
+ * Create a "special" mapping in the device described by the given devhandle,
+ * for the given real address and attributes.  Return the IO address in RET1
+ * if successful.
+ */
+#define HV_FAST_PCI_IOMMU_GETBYPASS	0xb3
+
+/* pci_config_get()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_CONFIG_GET
+ * ARG0:	devhandle
+ * ARG1:	pci_device
+ * ARG2:	pci_config_offset
+ * ARG3:	size
+ * RET0:	status
+ * RET1:	error_flag
+ * RET2:	data
+ * ERRORS:	EINVAL		Invalid devhandle/pci_device/offset/size
+ *		EBADALIGN	pci_config_offset not size aligned
+ *		ENOACCESS	Access to this offset is not permitted
+ *
+ * Read PCI configuration space for the adapter described by the given
+ * devhandle.  Read size (1, 2, or 4) bytes of data from the given
+ * pci_device, at pci_config_offset from the beginning of the device's
+ * configuration space.  If there was no error, RET1 is set to zero and
+ * RET2 is set to the data read.  Insignificant bits in RET2 are not
+ * guarenteed to have any specific value and therefore must be ignored.
+ *
+ * The data returned in RET2 is size based byte swapped.
+ *
+ * If an error occurs during the read, set RET1 to a non-zero value.  The
+ * given pci_config_offset must be 'size' aligned.
+ */
+#define HV_FAST_PCI_CONFIG_GET		0xb4
+
+/* pci_config_put()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_CONFIG_PUT
+ * ARG0:	devhandle
+ * ARG1:	pci_device
+ * ARG2:	pci_config_offset
+ * ARG3:	size
+ * ARG4:	data
+ * RET0:	status
+ * RET1:	error_flag
+ * ERRORS:	EINVAL		Invalid devhandle/pci_device/offset/size
+ *		EBADALIGN	pci_config_offset not size aligned
+ *		ENOACCESS	Access to this offset is not permitted
+ *
+ * Write PCI configuration space for the adapter described by the given
+ * devhandle.  Write size (1, 2, or 4) bytes of data in a single operation,
+ * at pci_config_offset from the beginning of the device's configuration
+ * space.  The data argument contains the data to be written to configuration
+ * space.  Prior to writing, the data is size based byte swapped.
+ *
+ * If an error occurs during the write access, do not generate an error
+ * report, do set RET1 to a non-zero value.  Otherwise RET1 is zero.
+ * The given pci_config_offset must be 'size' aligned.
+ *
+ * This function is permitted to read from offset zero in the configuration
+ * space described by the given pci_device if necessary to ensure that the
+ * write access to config space completes.
+ */
+#define HV_FAST_PCI_CONFIG_PUT		0xb5
+
+/* pci_peek()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_PEEK
+ * ARG0:	devhandle
+ * ARG1:	real address
+ * ARG2:	size
+ * RET0:	status
+ * RET1:	error_flag
+ * RET2:	data
+ * ERRORS:	EINVAL		Invalid devhandle or size
+ *		EBADALIGN	Improperly aligned real address
+ *		ENORADDR	Bad real address
+ *		ENOACCESS	Guest access prohibited
+ *
+ * Attempt to read the IO address given by the given devhandle, real address,
+ * and size.  Size must be 1, 2, 4, or 8.  The read is performed as a single
+ * access operation using the given size.  If an error occurs when reading
+ * from the given location, do not generate an error report, but return a
+ * non-zero value in RET1.  If the read was successful, return zero in RET1
+ * and return the actual data read in RET2.  The data returned is size based
+ * byte swapped.
+ *
+ * Non-significant bits in RET2 are not guarenteed to have any specific value
+ * and therefore must be ignored.  If RET1 is returned as non-zero, the data
+ * value is not guarenteed to have any specific value and should be ignored.
+ *
+ * The caller must have permission to read from the given devhandle, real
+ * address, which must be an IO address.  The argument real address must be a
+ * size aligned address.
+ *
+ * The hypervisor implementation of this function must block access to any
+ * IO address that the guest does not have explicit permission to access.
+ */
+#define HV_FAST_PCI_PEEK		0xb6
+
+/* pci_poke()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_POKE
+ * ARG0:	devhandle
+ * ARG1:	real address
+ * ARG2:	size
+ * ARG3:	data
+ * ARG4:	pci_device
+ * RET0:	status
+ * RET1:	error_flag
+ * ERRORS:	EINVAL		Invalid devhandle, size, or pci_device
+ *		EBADALIGN	Improperly aligned real address
+ *		ENORADDR	Bad real address
+ *		ENOACCESS	Guest access prohibited
+ *		ENOTSUPPORTED	Function is not supported by implementation
+ *
+ * Attempt to write data to the IO address given by the given devhandle,
+ * real address, and size.  Size must be 1, 2, 4, or 8.  The write is
+ * performed as a single access operation using the given size. Prior to
+ * writing the data is size based swapped.
+ *
+ * If an error occurs when writing to the given location, do not generate an
+ * error report, but return a non-zero value in RET1.  If the write was
+ * successful, return zero in RET1.
+ *
+ * pci_device describes the configuration address of the device being
+ * written to.  The implementation may safely read from offset 0 with
+ * the configuration space of the device described by devhandle and
+ * pci_device in order to guarantee that the write portion of the operation
+ * completes
+ *
+ * Any error that occurs due to the read shall be reported using the normal
+ * error reporting mechanisms .. the read error is not suppressed.
+ *
+ * The caller must have permission to write to the given devhandle, real
+ * address, which must be an IO address.  The argument real address must be a
+ * size aligned address.  The caller must have permission to read from
+ * the given devhandle, pci_device cofiguration space offset 0.
+ *
+ * The hypervisor implementation of this function must block access to any
+ * IO address that the guest does not have explicit permission to access.
+ */
+#define HV_FAST_PCI_POKE		0xb7
+
+/* pci_dma_sync()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_DMA_SYNC
+ * ARG0:	devhandle
+ * ARG1:	real address
+ * ARG2:	size
+ * ARG3:	io_sync_direction
+ * RET0:	status
+ * RET1:	#synced
+ * ERRORS:	EINVAL		Invalid devhandle or io_sync_direction
+ *		ENORADDR	Bad real address
+ *
+ * Synchronize a memory region described by the given real address and size,
+ * for the device defined by the given devhandle using the direction(s)
+ * defined by the given io_sync_direction.  The argument size is the size of
+ * the memory region in bytes.
+ *
+ * Return the actual number of bytes synchronized in the return value #synced,
+ * which may be less than or equal to the argument size.  If the return
+ * value #synced is less than size, the caller must continue to call this
+ * function with updated real address and size arguments until the entire
+ * memory region is synchronized.
+ */
+#define HV_FAST_PCI_DMA_SYNC		0xb8
+
+/* PCI MSI services.  */
+
+#define HV_MSITYPE_MSI32		0x00
+#define HV_MSITYPE_MSI64		0x01
+
+#define HV_MSIQSTATE_IDLE		0x00
+#define HV_MSIQSTATE_ERROR		0x01
+
+#define HV_MSIQ_INVALID			0x00
+#define HV_MSIQ_VALID			0x01
+
+#define HV_MSISTATE_IDLE		0x00
+#define HV_MSISTATE_DELIVERED		0x01
+
+#define HV_MSIVALID_INVALID		0x00
+#define HV_MSIVALID_VALID		0x01
+
+#define HV_PCIE_MSGTYPE_PME_MSG		0x18
+#define HV_PCIE_MSGTYPE_PME_ACK_MSG	0x1b
+#define HV_PCIE_MSGTYPE_CORR_MSG	0x30
+#define HV_PCIE_MSGTYPE_NONFATAL_MSG	0x31
+#define HV_PCIE_MSGTYPE_FATAL_MSG	0x33
+
+#define HV_MSG_INVALID			0x00
+#define HV_MSG_VALID			0x01
+
+/* pci_msiq_conf()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_MSIQ_CONF
+ * ARG0:	devhandle
+ * ARG1:	msiqid
+ * ARG2:	real address
+ * ARG3:	number of entries
+ * RET0:	status
+ * ERRORS:	EINVAL		Invalid devhandle, msiqid or nentries
+ *		EBADALIGN	Improperly aligned real address
+ *		ENORADDR	Bad real address
+ *
+ * Configure the MSI queue given by the devhandle and msiqid arguments,
+ * and to be placed at the given real address and be of the given
+ * number of entries.  The real address must be aligned exactly to match
+ * the queue size.  Each queue entry is 64-bytes long, so f.e. a 32 entry
+ * queue must be aligned on a 2048 byte real address boundary.  The MSI-EQ
+ * Head and Tail are initialized so that the MSI-EQ is 'empty'.
+ *
+ * Implementation Note: Certain implementations have fixed sized queues.  In
+ *                      that case, number of entries must contain the correct
+ *                      value.
+ */
+#define HV_FAST_PCI_MSIQ_CONF		0xc0
+
+/* pci_msiq_info()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_MSIQ_INFO
+ * ARG0:	devhandle
+ * ARG1:	msiqid
+ * RET0:	status
+ * RET1:	real address
+ * RET2:	number of entries
+ * ERRORS:	EINVAL		Invalid devhandle or msiqid
+ *
+ * Return the configuration information for the MSI queue described
+ * by the given devhandle and msiqid.  The base address of the queue
+ * is returned in ARG1 and the number of entries is returned in ARG2.
+ * If the queue is unconfigured, the real address is undefined and the
+ * number of entries will be returned as zero.
+ */
+#define HV_FAST_PCI_MSIQ_INFO		0xc1
+
+/* pci_msiq_getvalid()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_MSIQ_GETVALID
+ * ARG0:	devhandle
+ * ARG1:	msiqid
+ * RET0:	status
+ * RET1:	msiqvalid	(HV_MSIQ_VALID or HV_MSIQ_INVALID)
+ * ERRORS:	EINVAL		Invalid devhandle or msiqid
+ *
+ * Get the valid state of the MSI-EQ described by the given devhandle and
+ * msiqid.
+ */
+#define HV_FAST_PCI_MSIQ_GETVALID	0xc2
+
+/* pci_msiq_setvalid()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_MSIQ_SETVALID
+ * ARG0:	devhandle
+ * ARG1:	msiqid
+ * ARG2:	msiqvalid	(HV_MSIQ_VALID or HV_MSIQ_INVALID)
+ * RET0:	status
+ * ERRORS:	EINVAL		Invalid devhandle or msiqid or msiqvalid
+ *				value or MSI EQ is uninitialized
+ *
+ * Set the valid state of the MSI-EQ described by the given devhandle and
+ * msiqid to the given msiqvalid.
+ */
+#define HV_FAST_PCI_MSIQ_SETVALID	0xc3
+
+/* pci_msiq_getstate()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_MSIQ_GETSTATE
+ * ARG0:	devhandle
+ * ARG1:	msiqid
+ * RET0:	status
+ * RET1:	msiqstate	(HV_MSIQSTATE_IDLE or HV_MSIQSTATE_ERROR)
+ * ERRORS:	EINVAL		Invalid devhandle or msiqid
+ *
+ * Get the state of the MSI-EQ described by the given devhandle and
+ * msiqid.
+ */
+#define HV_FAST_PCI_MSIQ_GETSTATE	0xc4
+
+/* pci_msiq_getvalid()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_MSIQ_GETVALID
+ * ARG0:	devhandle
+ * ARG1:	msiqid
+ * ARG2:	msiqstate	(HV_MSIQSTATE_IDLE or HV_MSIQSTATE_ERROR)
+ * RET0:	status
+ * ERRORS:	EINVAL		Invalid devhandle or msiqid or msiqstate
+ *				value or MSI EQ is uninitialized
+ *
+ * Set the state of the MSI-EQ described by the given devhandle and
+ * msiqid to the given msiqvalid.
+ */
+#define HV_FAST_PCI_MSIQ_SETSTATE	0xc5
+
+/* pci_msiq_gethead()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_MSIQ_GETHEAD
+ * ARG0:	devhandle
+ * ARG1:	msiqid
+ * RET0:	status
+ * RET1:	msiqhead
+ * ERRORS:	EINVAL		Invalid devhandle or msiqid
+ *
+ * Get the current MSI EQ queue head for the MSI-EQ described by the
+ * given devhandle and msiqid.
+ */
+#define HV_FAST_PCI_MSIQ_GETHEAD	0xc6
+
+/* pci_msiq_sethead()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_MSIQ_SETHEAD
+ * ARG0:	devhandle
+ * ARG1:	msiqid
+ * ARG2:	msiqhead
+ * RET0:	status
+ * ERRORS:	EINVAL		Invalid devhandle or msiqid or msiqhead,
+ *				or MSI EQ is uninitialized
+ *
+ * Set the current MSI EQ queue head for the MSI-EQ described by the
+ * given devhandle and msiqid.
+ */
+#define HV_FAST_PCI_MSIQ_SETHEAD	0xc7
+
+/* pci_msiq_gettail()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_MSIQ_GETTAIL
+ * ARG0:	devhandle
+ * ARG1:	msiqid
+ * RET0:	status
+ * RET1:	msiqtail
+ * ERRORS:	EINVAL		Invalid devhandle or msiqid
+ *
+ * Get the current MSI EQ queue tail for the MSI-EQ described by the
+ * given devhandle and msiqid.
+ */
+#define HV_FAST_PCI_MSIQ_GETTAIL	0xc8
+
+/* pci_msi_getvalid()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_MSI_GETVALID
+ * ARG0:	devhandle
+ * ARG1:	msinum
+ * RET0:	status
+ * RET1:	msivalidstate
+ * ERRORS:	EINVAL		Invalid devhandle or msinum
+ *
+ * Get the current valid/enabled state for the MSI defined by the
+ * given devhandle and msinum.
+ */
+#define HV_FAST_PCI_MSI_GETVALID	0xc9
+
+/* pci_msi_setvalid()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_MSI_SETVALID
+ * ARG0:	devhandle
+ * ARG1:	msinum
+ * ARG2:	msivalidstate
+ * RET0:	status
+ * ERRORS:	EINVAL		Invalid devhandle or msinum or msivalidstate
+ *
+ * Set the current valid/enabled state for the MSI defined by the
+ * given devhandle and msinum.
+ */
+#define HV_FAST_PCI_MSI_SETVALID	0xca
+
+/* pci_msi_getmsiq()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_MSI_GETMSIQ
+ * ARG0:	devhandle
+ * ARG1:	msinum
+ * RET0:	status
+ * RET1:	msiqid
+ * ERRORS:	EINVAL		Invalid devhandle or msinum or MSI is unbound
+ *
+ * Get the MSI EQ that the MSI defined by the given devhandle and
+ * msinum is bound to.
+ */
+#define HV_FAST_PCI_MSI_GETMSIQ		0xcb
+
+/* pci_msi_setmsiq()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_MSI_SETMSIQ
+ * ARG0:	devhandle
+ * ARG1:	msinum
+ * ARG2:	msitype
+ * ARG3:	msiqid
+ * RET0:	status
+ * ERRORS:	EINVAL		Invalid devhandle or msinum or msiqid
+ *
+ * Set the MSI EQ that the MSI defined by the given devhandle and
+ * msinum is bound to.
+ */
+#define HV_FAST_PCI_MSI_SETMSIQ		0xcc
+
+/* pci_msi_getstate()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_MSI_GETSTATE
+ * ARG0:	devhandle
+ * ARG1:	msinum
+ * RET0:	status
+ * RET1:	msistate
+ * ERRORS:	EINVAL		Invalid devhandle or msinum
+ *
+ * Get the state of the MSI defined by the given devhandle and msinum.
+ * If not initialized, return HV_MSISTATE_IDLE.
+ */
+#define HV_FAST_PCI_MSI_GETSTATE	0xcd
+
+/* pci_msi_setstate()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_MSI_SETSTATE
+ * ARG0:	devhandle
+ * ARG1:	msinum
+ * ARG2:	msistate
+ * RET0:	status
+ * ERRORS:	EINVAL		Invalid devhandle or msinum or msistate
+ *
+ * Set the state of the MSI defined by the given devhandle and msinum.
+ */
+#define HV_FAST_PCI_MSI_SETSTATE	0xce
+
+/* pci_msg_getmsiq()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_MSG_GETMSIQ
+ * ARG0:	devhandle
+ * ARG1:	msgtype
+ * RET0:	status
+ * RET1:	msiqid
+ * ERRORS:	EINVAL		Invalid devhandle or msgtype
+ *
+ * Get the MSI EQ of the MSG defined by the given devhandle and msgtype.
+ */
+#define HV_FAST_PCI_MSG_GETMSIQ		0xd0
+
+/* pci_msg_setmsiq()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_MSG_SETMSIQ
+ * ARG0:	devhandle
+ * ARG1:	msgtype
+ * ARG2:	msiqid
+ * RET0:	status
+ * ERRORS:	EINVAL		Invalid devhandle, msgtype, or msiqid
+ *
+ * Set the MSI EQ of the MSG defined by the given devhandle and msgtype.
+ */
+#define HV_FAST_PCI_MSG_SETMSIQ		0xd1
+
+/* pci_msg_getvalid()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_MSG_GETVALID
+ * ARG0:	devhandle
+ * ARG1:	msgtype
+ * RET0:	status
+ * RET1:	msgvalidstate
+ * ERRORS:	EINVAL		Invalid devhandle or msgtype
+ *
+ * Get the valid/enabled state of the MSG defined by the given
+ * devhandle and msgtype.
+ */
+#define HV_FAST_PCI_MSG_GETVALID	0xd2
+
+/* pci_msg_setvalid()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_PCI_MSG_SETVALID
+ * ARG0:	devhandle
+ * ARG1:	msgtype
+ * ARG2:	msgvalidstate
+ * RET0:	status
+ * ERRORS:	EINVAL		Invalid devhandle or msgtype or msgvalidstate
+ *
+ * Set the valid/enabled state of the MSG defined by the given
+ * devhandle and msgtype.
+ */
+#define HV_FAST_PCI_MSG_SETVALID	0xd3
+
+/* Logical Domain Channel services.  */
+
+#define LDC_CHANNEL_DOWN		0
+#define LDC_CHANNEL_UP			1
+#define LDC_CHANNEL_RESETTING		2
+
+/* ldc_tx_qconf()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_TX_QCONF
+ * ARG0:	channel ID
+ * ARG1:	real address base of queue
+ * ARG2:	num entries in queue
+ * RET0:	status
+ *
+ * Configure transmit queue for the LDC endpoint specified by the
+ * given channel ID, to be placed at the given real address, and
+ * be of the given num entries.  Num entries must be a power of two.
+ * The real address base of the queue must be aligned on the queue
+ * size.  Each queue entry is 64-bytes, so for example, a 32 entry
+ * queue must be aligned on a 2048 byte real address boundary.
+ *
+ * Upon configuration of a valid transmit queue the head and tail
+ * pointers are set to a hypervisor specific identical value indicating
+ * that the queue initially is empty.
+ *
+ * The endpoint's transmit queue is un-configured if num entries is zero.
+ *
+ * The maximum number of entries for each queue for a specific cpu may be
+ * determined from the machine description.  A transmit queue may be
+ * specified even in the event that the LDC is down (peer endpoint has no
+ * receive queue specified).  Transmission will begin as soon as the peer
+ * endpoint defines a receive queue.
+ *
+ * It is recommended that a guest wait for a transmit queue to empty prior
+ * to reconfiguring it, or un-configuring it.  Re or un-configuring of a
+ * non-empty transmit queue behaves exactly as defined above, however it
+ * is undefined as to how many of the pending entries in the original queue
+ * will be delivered prior to the re-configuration taking effect.
+ * Furthermore, as the queue configuration causes a reset of the head and
+ * tail pointers there is no way for a guest to determine how many entries
+ * have been sent after the configuration operation.
+ */
+#define HV_FAST_LDC_TX_QCONF		0xe0
+
+/* ldc_tx_qinfo()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_TX_QINFO
+ * ARG0:	channel ID
+ * RET0:	status
+ * RET1:	real address base of queue
+ * RET2:	num entries in queue
+ *
+ * Return the configuration info for the transmit queue of LDC endpoint
+ * defined by the given channel ID.  The real address is the currently
+ * defined real address base of the defined queue, and num entries is the
+ * size of the queue in terms of number of entries.
+ *
+ * If the specified channel ID is a valid endpoint number, but no transmit
+ * queue has been defined this service will return success, but with num
+ * entries set to zero and the real address will have an undefined value.
+ */
+#define HV_FAST_LDC_TX_QINFO		0xe1
+
+/* ldc_tx_get_state()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_TX_GET_STATE
+ * ARG0:	channel ID
+ * RET0:	status
+ * RET1:	head offset
+ * RET2:	tail offset
+ * RET3:	channel state
+ *
+ * Return the transmit state, and the head and tail queue pointers, for
+ * the transmit queue of the LDC endpoint defined by the given channel ID.
+ * The head and tail values are the byte offset of the head and tail
+ * positions of the transmit queue for the specified endpoint.
+ */
+#define HV_FAST_LDC_TX_GET_STATE	0xe2
+
+/* ldc_tx_set_qtail()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_TX_SET_QTAIL
+ * ARG0:	channel ID
+ * ARG1:	tail offset
+ * RET0:	status
+ *
+ * Update the tail pointer for the transmit queue associated with the LDC
+ * endpoint defined by the given channel ID.  The tail offset specified
+ * must be aligned on a 64 byte boundary, and calculated so as to increase
+ * the number of pending entries on the transmit queue.  Any attempt to
+ * decrease the number of pending transmit queue entires is considered
+ * an invalid tail offset and will result in an EINVAL error.
+ *
+ * Since the tail of the transmit queue may not be moved backwards, the
+ * transmit queue may be flushed by configuring a new transmit queue,
+ * whereupon the hypervisor will configure the initial transmit head and
+ * tail pointers to be equal.
+ */
+#define HV_FAST_LDC_TX_SET_QTAIL	0xe3
+
+/* ldc_rx_qconf()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_RX_QCONF
+ * ARG0:	channel ID
+ * ARG1:	real address base of queue
+ * ARG2:	num entries in queue
+ * RET0:	status
+ *
+ * Configure receive queue for the LDC endpoint specified by the
+ * given channel ID, to be placed at the given real address, and
+ * be of the given num entries.  Num entries must be a power of two.
+ * The real address base of the queue must be aligned on the queue
+ * size.  Each queue entry is 64-bytes, so for example, a 32 entry
+ * queue must be aligned on a 2048 byte real address boundary.
+ *
+ * The endpoint's transmit queue is un-configured if num entries is zero.
+ *
+ * If a valid receive queue is specified for a local endpoint the LDC is
+ * in the up state for the purpose of transmission to this endpoint.
+ *
+ * The maximum number of entries for each queue for a specific cpu may be
+ * determined from the machine description.
+ *
+ * As receive queue configuration causes a reset of the queue's head and
+ * tail pointers there is no way for a gues to determine how many entries
+ * have been received between a preceeding ldc_get_rx_state() API call
+ * and the completion of the configuration operation.  It should be noted
+ * that datagram delivery is not guarenteed via domain channels anyway,
+ * and therefore any higher protocol should be resilient to datagram
+ * loss if necessary.  However, to overcome this specific race potential
+ * it is recommended, for example, that a higher level protocol be employed
+ * to ensure either retransmission, or ensure that no datagrams are pending
+ * on the peer endpoint's transmit queue prior to the configuration process.
+ */
+#define HV_FAST_LDC_RX_QCONF		0xe4
+
+/* ldc_rx_qinfo()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_RX_QINFO
+ * ARG0:	channel ID
+ * RET0:	status
+ * RET1:	real address base of queue
+ * RET2:	num entries in queue
+ *
+ * Return the configuration info for the receive queue of LDC endpoint
+ * defined by the given channel ID.  The real address is the currently
+ * defined real address base of the defined queue, and num entries is the
+ * size of the queue in terms of number of entries.
+ *
+ * If the specified channel ID is a valid endpoint number, but no receive
+ * queue has been defined this service will return success, but with num
+ * entries set to zero and the real address will have an undefined value.
+ */
+#define HV_FAST_LDC_RX_QINFO		0xe5
+
+/* ldc_rx_get_state()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_RX_GET_STATE
+ * ARG0:	channel ID
+ * RET0:	status
+ * RET1:	head offset
+ * RET2:	tail offset
+ * RET3:	channel state
+ *
+ * Return the receive state, and the head and tail queue pointers, for
+ * the receive queue of the LDC endpoint defined by the given channel ID.
+ * The head and tail values are the byte offset of the head and tail
+ * positions of the receive queue for the specified endpoint.
+ */
+#define HV_FAST_LDC_RX_GET_STATE	0xe6
+
+/* ldc_rx_set_qhead()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_RX_SET_QHEAD
+ * ARG0:	channel ID
+ * ARG1:	head offset
+ * RET0:	status
+ *
+ * Update the head pointer for the receive queue associated with the LDC
+ * endpoint defined by the given channel ID.  The head offset specified
+ * must be aligned on a 64 byte boundary, and calculated so as to decrease
+ * the number of pending entries on the receive queue.  Any attempt to
+ * increase the number of pending receive queue entires is considered
+ * an invalid head offset and will result in an EINVAL error.
+ *
+ * The receive queue may be flushed by setting the head offset equal
+ * to the current tail offset.
+ */
+#define HV_FAST_LDC_RX_SET_QHEAD	0xe7
+
+/* LDC Map Table Entry.  Each slot is defined by a translation table
+ * entry, as specified by the LDC_MTE_* bits below, and a 64-bit
+ * hypervisor invalidation cookie.
+ */
+#define LDC_MTE_PADDR	0x0fffffffffffe000 /* pa[55:13]          */
+#define LDC_MTE_COPY_W	0x0000000000000400 /* copy write access  */
+#define LDC_MTE_COPY_R	0x0000000000000200 /* copy read access   */
+#define LDC_MTE_IOMMU_W	0x0000000000000100 /* IOMMU write access */
+#define LDC_MTE_IOMMU_R	0x0000000000000080 /* IOMMU read access  */
+#define LDC_MTE_EXEC	0x0000000000000040 /* execute            */
+#define LDC_MTE_WRITE	0x0000000000000020 /* read               */
+#define LDC_MTE_READ	0x0000000000000010 /* write              */
+#define LDC_MTE_SZALL	0x000000000000000f /* page size bits     */
+#define LDC_MTE_SZ16GB	0x0000000000000007 /* 16GB page          */
+#define LDC_MTE_SZ2GB	0x0000000000000006 /* 2GB page           */
+#define LDC_MTE_SZ256MB	0x0000000000000005 /* 256MB page         */
+#define LDC_MTE_SZ32MB	0x0000000000000004 /* 32MB page          */
+#define LDC_MTE_SZ4MB	0x0000000000000003 /* 4MB page           */
+#define LDC_MTE_SZ512K	0x0000000000000002 /* 512K page          */
+#define LDC_MTE_SZ64K	0x0000000000000001 /* 64K page           */
+#define LDC_MTE_SZ8K	0x0000000000000000 /* 8K page            */
+
+#ifndef __ASSEMBLY__
+struct ldc_mtable_entry {
+	unsigned long	mte;
+	unsigned long	cookie;
+};
+#endif
+
+/* ldc_set_map_table()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_SET_MAP_TABLE
+ * ARG0:	channel ID
+ * ARG1:	table real address
+ * ARG2:	num entries
+ * RET0:	status
+ *
+ * Register the MTE table at the given table real address, with the
+ * specified num entries, for the LDC indicated by the given channel
+ * ID.
+ */
+#define HV_FAST_LDC_SET_MAP_TABLE	0xea
+
+/* ldc_get_map_table()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_GET_MAP_TABLE
+ * ARG0:	channel ID
+ * RET0:	status
+ * RET1:	table real address
+ * RET2:	num entries
+ *
+ * Return the configuration of the current mapping table registered
+ * for the given channel ID.
+ */
+#define HV_FAST_LDC_GET_MAP_TABLE	0xeb
+
+#define LDC_COPY_IN	0
+#define LDC_COPY_OUT	1
+
+/* ldc_copy()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_COPY
+ * ARG0:	channel ID
+ * ARG1:	LDC_COPY_* direction code
+ * ARG2:	target real address
+ * ARG3:	local real address
+ * ARG4:	length in bytes
+ * RET0:	status
+ * RET1:	actual length in bytes
+ */
+#define HV_FAST_LDC_COPY		0xec
+
+#define LDC_MEM_READ	1
+#define LDC_MEM_WRITE	2
+#define LDC_MEM_EXEC	4
+
+/* ldc_mapin()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_MAPIN
+ * ARG0:	channel ID
+ * ARG1:	cookie
+ * RET0:	status
+ * RET1:	real address
+ * RET2:	LDC_MEM_* permissions
+ */
+#define HV_FAST_LDC_MAPIN		0xed
+
+/* ldc_unmap()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_UNMAP
+ * ARG0:	real address
+ * RET0:	status
+ */
+#define HV_FAST_LDC_UNMAP		0xee
+
+/* ldc_revoke()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_LDC_REVOKE
+ * ARG0:	channel ID
+ * ARG1:	cookie
+ * ARG2:	ldc_mtable_entry cookie
+ * RET0:	status
+ */
+#define HV_FAST_LDC_REVOKE		0xef
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_ldc_tx_qconf(unsigned long channel,
+					unsigned long ra,
+					unsigned long num_entries);
+extern unsigned long sun4v_ldc_tx_qinfo(unsigned long channel,
+					unsigned long *ra,
+					unsigned long *num_entries);
+extern unsigned long sun4v_ldc_tx_get_state(unsigned long channel,
+					    unsigned long *head_off,
+					    unsigned long *tail_off,
+					    unsigned long *chan_state);
+extern unsigned long sun4v_ldc_tx_set_qtail(unsigned long channel,
+					    unsigned long tail_off);
+extern unsigned long sun4v_ldc_rx_qconf(unsigned long channel,
+					unsigned long ra,
+					unsigned long num_entries);
+extern unsigned long sun4v_ldc_rx_qinfo(unsigned long channel,
+					unsigned long *ra,
+					unsigned long *num_entries);
+extern unsigned long sun4v_ldc_rx_get_state(unsigned long channel,
+					    unsigned long *head_off,
+					    unsigned long *tail_off,
+					    unsigned long *chan_state);
+extern unsigned long sun4v_ldc_rx_set_qhead(unsigned long channel,
+					    unsigned long head_off);
+extern unsigned long sun4v_ldc_set_map_table(unsigned long channel,
+					     unsigned long ra,
+					     unsigned long num_entries);
+extern unsigned long sun4v_ldc_get_map_table(unsigned long channel,
+					     unsigned long *ra,
+					     unsigned long *num_entries);
+extern unsigned long sun4v_ldc_copy(unsigned long channel,
+				    unsigned long dir_code,
+				    unsigned long tgt_raddr,
+				    unsigned long lcl_raddr,
+				    unsigned long len,
+				    unsigned long *actual_len);
+extern unsigned long sun4v_ldc_mapin(unsigned long channel,
+				     unsigned long cookie,
+				     unsigned long *ra,
+				     unsigned long *perm);
+extern unsigned long sun4v_ldc_unmap(unsigned long ra);
+extern unsigned long sun4v_ldc_revoke(unsigned long channel,
+				      unsigned long cookie,
+				      unsigned long mte_cookie);
+#endif
+
+/* Performance counter services.  */
+
+#define HV_PERF_JBUS_PERF_CTRL_REG	0x00
+#define HV_PERF_JBUS_PERF_CNT_REG	0x01
+#define HV_PERF_DRAM_PERF_CTRL_REG_0	0x02
+#define HV_PERF_DRAM_PERF_CNT_REG_0	0x03
+#define HV_PERF_DRAM_PERF_CTRL_REG_1	0x04
+#define HV_PERF_DRAM_PERF_CNT_REG_1	0x05
+#define HV_PERF_DRAM_PERF_CTRL_REG_2	0x06
+#define HV_PERF_DRAM_PERF_CNT_REG_2	0x07
+#define HV_PERF_DRAM_PERF_CTRL_REG_3	0x08
+#define HV_PERF_DRAM_PERF_CNT_REG_3	0x09
+
+/* get_perfreg()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_GET_PERFREG
+ * ARG0:	performance reg number
+ * RET0:	status
+ * RET1:	performance reg value
+ * ERRORS:	EINVAL		Invalid performance register number
+ *		ENOACCESS	No access allowed to performance counters
+ *
+ * Read the value of the given DRAM/JBUS performance counter/control register.
+ */
+#define HV_FAST_GET_PERFREG		0x100
+
+/* set_perfreg()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_SET_PERFREG
+ * ARG0:	performance reg number
+ * ARG1:	performance reg value
+ * RET0:	status
+ * ERRORS:	EINVAL		Invalid performance register number
+ *		ENOACCESS	No access allowed to performance counters
+ *
+ * Write the given performance reg value to the given DRAM/JBUS
+ * performance counter/control register.
+ */
+#define HV_FAST_SET_PERFREG		0x101
+
+/* MMU statistics services.
+ *
+ * The hypervisor maintains MMU statistics and privileged code provides
+ * a buffer where these statistics can be collected.  It is continually
+ * updated once configured.  The layout is as follows:
+ */
+#ifndef __ASSEMBLY__
+struct hv_mmu_statistics {
+	unsigned long immu_tsb_hits_ctx0_8k_tte;
+	unsigned long immu_tsb_ticks_ctx0_8k_tte;
+	unsigned long immu_tsb_hits_ctx0_64k_tte;
+	unsigned long immu_tsb_ticks_ctx0_64k_tte;
+	unsigned long __reserved1[2];
+	unsigned long immu_tsb_hits_ctx0_4mb_tte;
+	unsigned long immu_tsb_ticks_ctx0_4mb_tte;
+	unsigned long __reserved2[2];
+	unsigned long immu_tsb_hits_ctx0_256mb_tte;
+	unsigned long immu_tsb_ticks_ctx0_256mb_tte;
+	unsigned long __reserved3[4];
+	unsigned long immu_tsb_hits_ctxnon0_8k_tte;
+	unsigned long immu_tsb_ticks_ctxnon0_8k_tte;
+	unsigned long immu_tsb_hits_ctxnon0_64k_tte;
+	unsigned long immu_tsb_ticks_ctxnon0_64k_tte;
+	unsigned long __reserved4[2];
+	unsigned long immu_tsb_hits_ctxnon0_4mb_tte;
+	unsigned long immu_tsb_ticks_ctxnon0_4mb_tte;
+	unsigned long __reserved5[2];
+	unsigned long immu_tsb_hits_ctxnon0_256mb_tte;
+	unsigned long immu_tsb_ticks_ctxnon0_256mb_tte;
+	unsigned long __reserved6[4];
+	unsigned long dmmu_tsb_hits_ctx0_8k_tte;
+	unsigned long dmmu_tsb_ticks_ctx0_8k_tte;
+	unsigned long dmmu_tsb_hits_ctx0_64k_tte;
+	unsigned long dmmu_tsb_ticks_ctx0_64k_tte;
+	unsigned long __reserved7[2];
+	unsigned long dmmu_tsb_hits_ctx0_4mb_tte;
+	unsigned long dmmu_tsb_ticks_ctx0_4mb_tte;
+	unsigned long __reserved8[2];
+	unsigned long dmmu_tsb_hits_ctx0_256mb_tte;
+	unsigned long dmmu_tsb_ticks_ctx0_256mb_tte;
+	unsigned long __reserved9[4];
+	unsigned long dmmu_tsb_hits_ctxnon0_8k_tte;
+	unsigned long dmmu_tsb_ticks_ctxnon0_8k_tte;
+	unsigned long dmmu_tsb_hits_ctxnon0_64k_tte;
+	unsigned long dmmu_tsb_ticks_ctxnon0_64k_tte;
+	unsigned long __reserved10[2];
+	unsigned long dmmu_tsb_hits_ctxnon0_4mb_tte;
+	unsigned long dmmu_tsb_ticks_ctxnon0_4mb_tte;
+	unsigned long __reserved11[2];
+	unsigned long dmmu_tsb_hits_ctxnon0_256mb_tte;
+	unsigned long dmmu_tsb_ticks_ctxnon0_256mb_tte;
+	unsigned long __reserved12[4];
+};
+#endif
+
+/* mmustat_conf()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_MMUSTAT_CONF
+ * ARG0:	real address
+ * RET0:	status
+ * RET1:	real address
+ * ERRORS:	ENORADDR	Invalid real address
+ *		EBADALIGN	Real address not aligned on 64-byte boundary
+ *		EBADTRAP	API not supported on this processor
+ *
+ * Enable MMU statistic gathering using the buffer at the given real
+ * address on the current virtual CPU.  The new buffer real address
+ * is given in ARG1, and the previously specified buffer real address
+ * is returned in RET1, or is returned as zero for the first invocation.
+ *
+ * If the passed in real address argument is zero, this will disable
+ * MMU statistic collection on the current virtual CPU.  If an error is
+ * returned then no statistics are collected.
+ *
+ * The buffer contents should be initialized to all zeros before being
+ * given to the hypervisor or else the statistics will be meaningless.
+ */
+#define HV_FAST_MMUSTAT_CONF		0x102
+
+/* mmustat_info()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_MMUSTAT_INFO
+ * RET0:	status
+ * RET1:	real address
+ * ERRORS:	EBADTRAP	API not supported on this processor
+ *
+ * Return the current state and real address of the currently configured
+ * MMU statistics buffer on the current virtual CPU.
+ */
+#define HV_FAST_MMUSTAT_INFO		0x103
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_mmustat_conf(unsigned long ra, unsigned long *orig_ra);
+extern unsigned long sun4v_mmustat_info(unsigned long *ra);
+#endif
+
+/* NCS crypto services  */
+
+/* ncs_request() sub-function numbers */
+#define HV_NCS_QCONF			0x01
+#define HV_NCS_QTAIL_UPDATE		0x02
+
+#ifndef __ASSEMBLY__
+struct hv_ncs_queue_entry {
+	/* MAU Control Register */
+	unsigned long	mau_control;
+#define MAU_CONTROL_INV_PARITY	0x0000000000002000
+#define MAU_CONTROL_STRAND	0x0000000000001800
+#define MAU_CONTROL_BUSY	0x0000000000000400
+#define MAU_CONTROL_INT		0x0000000000000200
+#define MAU_CONTROL_OP		0x00000000000001c0
+#define MAU_CONTROL_OP_SHIFT	6
+#define MAU_OP_LOAD_MA_MEMORY	0x0
+#define MAU_OP_STORE_MA_MEMORY	0x1
+#define MAU_OP_MODULAR_MULT	0x2
+#define MAU_OP_MODULAR_REDUCE	0x3
+#define MAU_OP_MODULAR_EXP_LOOP	0x4
+#define MAU_CONTROL_LEN		0x000000000000003f
+#define MAU_CONTROL_LEN_SHIFT	0
+
+	/* Real address of bytes to load or store bytes
+	 * into/out-of the MAU.
+	 */
+	unsigned long	mau_mpa;
+
+	/* Modular Arithmetic MA Offset Register.  */
+	unsigned long	mau_ma;
+
+	/* Modular Arithmetic N Prime Register.  */
+	unsigned long	mau_np;
+};
+
+struct hv_ncs_qconf_arg {
+	unsigned long	mid;      /* MAU ID, 1 per core on Niagara */
+	unsigned long	base;     /* Real address base of queue */
+	unsigned long	end;	  /* Real address end of queue */
+	unsigned long	num_ents; /* Number of entries in queue */
+};
+
+struct hv_ncs_qtail_update_arg {
+	unsigned long	mid;      /* MAU ID, 1 per core on Niagara */
+	unsigned long	tail;     /* New tail index to use */
+	unsigned long	syncflag; /* only SYNCFLAG_SYNC is implemented */
+#define HV_NCS_SYNCFLAG_SYNC	0x00
+#define HV_NCS_SYNCFLAG_ASYNC	0x01
+};
+#endif
+
+/* ncs_request()
+ * TRAP:	HV_FAST_TRAP
+ * FUNCTION:	HV_FAST_NCS_REQUEST
+ * ARG0:	NCS sub-function
+ * ARG1:	sub-function argument real address
+ * ARG2:	size in bytes of sub-function argument
+ * RET0:	status
+ *
+ * The MAU chip of the Niagara processor is not directly accessible
+ * to privileged code, instead it is programmed indirectly via this
+ * hypervisor API.
+ *
+ * The interfaces defines a queue of MAU operations to perform.
+ * Privileged code registers a queue with the hypervisor by invoking
+ * this HVAPI with the HV_NCS_QCONF sub-function, which defines the
+ * base, end, and number of entries of the queue.  Each queue entry
+ * contains a MAU register struct block.
+ *
+ * The privileged code then proceeds to add entries to the queue and
+ * then invoke the HV_NCS_QTAIL_UPDATE sub-function.  Since only
+ * synchronous operations are supported by the current hypervisor,
+ * HV_NCS_QTAIL_UPDATE will run all the pending queue entries to
+ * completion and return HV_EOK, or return an error code.
+ *
+ * The real address of the sub-function argument must be aligned on at
+ * least an 8-byte boundary.
+ *
+ * The tail argument of HV_NCS_QTAIL_UPDATE is an index, not a byte
+ * offset, into the queue and must be less than or equal the 'num_ents'
+ * argument given in the HV_NCS_QCONF call.
+ */
+#define HV_FAST_NCS_REQUEST		0x110
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_ncs_request(unsigned long request,
+				       unsigned long arg_ra,
+				       unsigned long arg_size);
+#endif
+
+#define HV_FAST_FIRE_GET_PERFREG	0x120
+#define HV_FAST_FIRE_SET_PERFREG	0x121
+
+/* Function numbers for HV_CORE_TRAP.  */
+#define HV_CORE_SET_VER			0x00
+#define HV_CORE_PUTCHAR			0x01
+#define HV_CORE_EXIT			0x02
+#define HV_CORE_GET_VER			0x03
+
+/* Hypervisor API groups for use with HV_CORE_SET_VER and
+ * HV_CORE_GET_VER.
+ */
+#define HV_GRP_SUN4V			0x0000
+#define HV_GRP_CORE			0x0001
+#define HV_GRP_INTR			0x0002
+#define HV_GRP_SOFT_STATE		0x0003
+#define HV_GRP_PCI			0x0100
+#define HV_GRP_LDOM			0x0101
+#define HV_GRP_SVC_CHAN			0x0102
+#define HV_GRP_NCS			0x0103
+#define HV_GRP_RNG			0x0104
+#define HV_GRP_NIAG_PERF		0x0200
+#define HV_GRP_FIRE_PERF		0x0201
+#define HV_GRP_N2_CPU			0x0202
+#define HV_GRP_NIU			0x0204
+#define HV_GRP_VF_CPU			0x0205
+#define HV_GRP_DIAG			0x0300
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_get_version(unsigned long group,
+				       unsigned long *major,
+				       unsigned long *minor);
+extern unsigned long sun4v_set_version(unsigned long group,
+				       unsigned long major,
+				       unsigned long minor,
+				       unsigned long *actual_minor);
+
+extern int sun4v_hvapi_register(unsigned long group, unsigned long major,
+				unsigned long *minor);
+extern void sun4v_hvapi_unregister(unsigned long group);
+extern int sun4v_hvapi_get(unsigned long group,
+			   unsigned long *major,
+			   unsigned long *minor);
+extern void sun4v_hvapi_init(void);
+#endif
+
+#endif /* !(_SPARC64_HYPERVISOR_H) */
diff --git a/include/asm-sparc/ide.h b/include/asm-sparc/ide.h
index afd1736..879fcec 100644
--- a/include/asm-sparc/ide.h
+++ b/include/asm-sparc/ide.h
@@ -10,9 +10,16 @@
 
 #ifdef __KERNEL__
 
-#include <asm/pgtable.h>
 #include <asm/io.h>
+#ifdef CONFIG_SPARC64
+#include <asm/pgalloc.h>
+#include <asm/spitfire.h>
+#include <asm/cacheflush.h>
+#include <asm/page.h>
+#else
+#include <asm/pgtable.h>
 #include <asm/psr.h>
+#endif
 
 #undef  MAX_HWIFS
 #define MAX_HWIFS	2
@@ -28,50 +35,46 @@
 #define __ide_mm_outsw	__ide_outsw
 #define __ide_mm_outsl	__ide_outsl
 
-static inline void __ide_insw(unsigned long port,
-				  void *dst,
-				  unsigned long count)
+static inline void __ide_insw(void __iomem *port, void *dst, u32 count)
 {
-	volatile unsigned short *data_port;
-	/* unsigned long end = (unsigned long)dst + (count << 1); */ /* P3 */
+#if defined(CONFIG_SPARC64) && defined(DCACHE_ALIASING_POSSIBLE)
+	unsigned long end = (unsigned long)dst + (count << 1);
+#endif
 	u16 *ps = dst;
 	u32 *pi;
 
-	data_port = (volatile unsigned short *)port;
-
 	if(((unsigned long)ps) & 0x2) {
-		*ps++ = *data_port;
+		*ps++ = __raw_readw(port);
 		count--;
 	}
 	pi = (u32 *)ps;
 	while(count >= 2) {
 		u32 w;
 
-		w  = (*data_port) << 16;
-		w |= (*data_port);
+		w  = __raw_readw(port) << 16;
+		w |= __raw_readw(port);
 		*pi++ = w;
 		count -= 2;
 	}
 	ps = (u16 *)pi;
 	if(count)
-		*ps++ = *data_port;
+		*ps++ = __raw_readw(port);
 
-	/* __flush_dcache_range((unsigned long)dst, end); */ /* P3 see hme */
+#if defined(CONFIG_SPARC64) && defined(DCACHE_ALIASING_POSSIBLE)
+	__flush_dcache_range((unsigned long)dst, end);
+#endif
 }
 
-static inline void __ide_outsw(unsigned long port,
-				   const void *src,
-				   unsigned long count)
+static inline void __ide_outsw(void __iomem *port, const void *src, u32 count)
 {
-	volatile unsigned short *data_port;
-	/* unsigned long end = (unsigned long)src + (count << 1); */
+#if defined(CONFIG_SPARC64) && defined(DCACHE_ALIASING_POSSIBLE)
+	unsigned long end = (unsigned long)src + (count << 1);
+#endif
 	const u16 *ps = src;
 	const u32 *pi;
 
-	data_port = (volatile unsigned short *)port;
-
 	if(((unsigned long)src) & 0x2) {
-		*data_port = *ps++;
+		__raw_writew(*ps++, port);
 		count--;
 	}
 	pi = (const u32 *)ps;
@@ -79,15 +82,17 @@
 		u32 w;
 
 		w = *pi++;
-		*data_port = (w >> 16);
-		*data_port = w;
+		__raw_writew((w >> 16), port);
+		__raw_writew(w, port);
 		count -= 2;
 	}
 	ps = (const u16 *)pi;
 	if(count)
-		*data_port = *ps;
+		__raw_writew(*ps, port);
 
-	/* __flush_dcache_range((unsigned long)src, end); */ /* P3 see hme */
+#if defined(CONFIG_SPARC64) && defined(DCACHE_ALIASING_POSSIBLE)
+	__flush_dcache_range((unsigned long)src, end);
+#endif
 }
 
 #endif /* __KERNEL__ */
diff --git a/include/asm-sparc/idprom.h b/include/asm-sparc/idprom.h
index 41adb41..6976aa2 100644
--- a/include/asm-sparc/idprom.h
+++ b/include/asm-sparc/idprom.h
@@ -1,7 +1,7 @@
 /*
  * idprom.h: Macros and defines for idprom routines
  *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
  */
 
 #ifndef _SPARC_IDPROM_H
diff --git a/include/asm-sparc/intr_queue.h b/include/asm-sparc/intr_queue.h
new file mode 100644
index 0000000..206077d
--- /dev/null
+++ b/include/asm-sparc/intr_queue.h
@@ -0,0 +1,15 @@
+#ifndef _SPARC64_INTR_QUEUE_H
+#define _SPARC64_INTR_QUEUE_H
+
+/* Sun4v interrupt queue registers, accessed via ASI_QUEUE.  */
+
+#define INTRQ_CPU_MONDO_HEAD	  0x3c0 /* CPU mondo head	          */
+#define INTRQ_CPU_MONDO_TAIL	  0x3c8 /* CPU mondo tail	          */
+#define INTRQ_DEVICE_MONDO_HEAD	  0x3d0 /* Device mondo head	          */
+#define INTRQ_DEVICE_MONDO_TAIL	  0x3d8 /* Device mondo tail	          */
+#define INTRQ_RESUM_MONDO_HEAD	  0x3e0 /* Resumable error mondo head     */
+#define INTRQ_RESUM_MONDO_TAIL	  0x3e8 /* Resumable error mondo tail     */
+#define INTRQ_NONRESUM_MONDO_HEAD 0x3f0 /* Non-resumable error mondo head */
+#define INTRQ_NONRESUM_MONDO_TAIL 0x3f8 /* Non-resumable error mondo head */
+
+#endif /* !(_SPARC64_INTR_QUEUE_H) */
diff --git a/include/asm-sparc/io.h b/include/asm-sparc/io.h
index 3a3e7bd..fc9024d 100644
--- a/include/asm-sparc/io.h
+++ b/include/asm-sparc/io.h
@@ -1,325 +1,8 @@
-#ifndef __SPARC_IO_H
-#define __SPARC_IO_H
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/ioport.h>  /* struct resource */
-
-#include <asm/page.h>      /* IO address mapping routines need this */
-#include <asm/system.h>
-
-#define page_to_phys(page)	(((page) - mem_map) << PAGE_SHIFT)
-
-static inline u32 flip_dword (u32 l)
-{
-	return ((l&0xff)<<24) | (((l>>8)&0xff)<<16) | (((l>>16)&0xff)<<8)| ((l>>24)&0xff);
-}
-
-static inline u16 flip_word (u16 w)
-{
-	return ((w&0xff) << 8) | ((w>>8)&0xff);
-}
-
-#define mmiowb()
-
-/*
- * Memory mapped I/O to PCI
- */
-
-static inline u8 __raw_readb(const volatile void __iomem *addr)
-{
-	return *(__force volatile u8 *)addr;
-}
-
-static inline u16 __raw_readw(const volatile void __iomem *addr)
-{
-	return *(__force volatile u16 *)addr;
-}
-
-static inline u32 __raw_readl(const volatile void __iomem *addr)
-{
-	return *(__force volatile u32 *)addr;
-}
-
-static inline void __raw_writeb(u8 b, volatile void __iomem *addr)
-{
-	*(__force volatile u8 *)addr = b;
-}
-
-static inline void __raw_writew(u16 w, volatile void __iomem *addr)
-{
-	*(__force volatile u16 *)addr = w;
-}
-
-static inline void __raw_writel(u32 l, volatile void __iomem *addr)
-{
-	*(__force volatile u32 *)addr = l;
-}
-
-static inline u8 __readb(const volatile void __iomem *addr)
-{
-	return *(__force volatile u8 *)addr;
-}
-
-static inline u16 __readw(const volatile void __iomem *addr)
-{
-	return flip_word(*(__force volatile u16 *)addr);
-}
-
-static inline u32 __readl(const volatile void __iomem *addr)
-{
-	return flip_dword(*(__force volatile u32 *)addr);
-}
-
-static inline void __writeb(u8 b, volatile void __iomem *addr)
-{
-	*(__force volatile u8 *)addr = b;
-}
-
-static inline void __writew(u16 w, volatile void __iomem *addr)
-{
-	*(__force volatile u16 *)addr = flip_word(w);
-}
-
-static inline void __writel(u32 l, volatile void __iomem *addr)
-{
-	*(__force volatile u32 *)addr = flip_dword(l);
-}
-
-#define readb(__addr)		__readb(__addr)
-#define readw(__addr)		__readw(__addr)
-#define readl(__addr)		__readl(__addr)
-#define readb_relaxed(__addr)	readb(__addr)
-#define readw_relaxed(__addr)	readw(__addr)
-#define readl_relaxed(__addr)	readl(__addr)
-
-#define writeb(__b, __addr)	__writeb((__b),(__addr))
-#define writew(__w, __addr)	__writew((__w),(__addr))
-#define writel(__l, __addr)	__writel((__l),(__addr))
-
-/*
- * I/O space operations
- *
- * Arrangement on a Sun is somewhat complicated.
- *
- * First of all, we want to use standard Linux drivers
- * for keyboard, PC serial, etc. These drivers think
- * they access I/O space and use inb/outb.
- * On the other hand, EBus bridge accepts PCI *memory*
- * cycles and converts them into ISA *I/O* cycles.
- * Ergo, we want inb & outb to generate PCI memory cycles.
- *
- * If we want to issue PCI *I/O* cycles, we do this
- * with a low 64K fixed window in PCIC. This window gets
- * mapped somewhere into virtual kernel space and we
- * can use inb/outb again.
- */
-#define inb_local(__addr)	__readb((void __iomem *)(unsigned long)(__addr))
-#define inb(__addr)		__readb((void __iomem *)(unsigned long)(__addr))
-#define inw(__addr)		__readw((void __iomem *)(unsigned long)(__addr))
-#define inl(__addr)		__readl((void __iomem *)(unsigned long)(__addr))
-
-#define outb_local(__b, __addr)	__writeb(__b, (void __iomem *)(unsigned long)(__addr))
-#define outb(__b, __addr)	__writeb(__b, (void __iomem *)(unsigned long)(__addr))
-#define outw(__w, __addr)	__writew(__w, (void __iomem *)(unsigned long)(__addr))
-#define outl(__l, __addr)	__writel(__l, (void __iomem *)(unsigned long)(__addr))
-
-#define inb_p(__addr)		inb(__addr)
-#define outb_p(__b, __addr)	outb(__b, __addr)
-#define inw_p(__addr)		inw(__addr)
-#define outw_p(__w, __addr)	outw(__w, __addr)
-#define inl_p(__addr)		inl(__addr)
-#define outl_p(__l, __addr)	outl(__l, __addr)
-
-void outsb(unsigned long addr, const void *src, unsigned long cnt);
-void outsw(unsigned long addr, const void *src, unsigned long cnt);
-void outsl(unsigned long addr, const void *src, unsigned long cnt);
-void insb(unsigned long addr, void *dst, unsigned long count);
-void insw(unsigned long addr, void *dst, unsigned long count);
-void insl(unsigned long addr, void *dst, unsigned long count);
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-/*
- * SBus accessors.
- *
- * SBus has only one, memory mapped, I/O space.
- * We do not need to flip bytes for SBus of course.
- */
-static inline u8 _sbus_readb(const volatile void __iomem *addr)
-{
-	return *(__force volatile u8 *)addr;
-}
-
-static inline u16 _sbus_readw(const volatile void __iomem *addr)
-{
-	return *(__force volatile u16 *)addr;
-}
-
-static inline u32 _sbus_readl(const volatile void __iomem *addr)
-{
-	return *(__force volatile u32 *)addr;
-}
-
-static inline void _sbus_writeb(u8 b, volatile void __iomem *addr)
-{
-	*(__force volatile u8 *)addr = b;
-}
-
-static inline void _sbus_writew(u16 w, volatile void __iomem *addr)
-{
-	*(__force volatile u16 *)addr = w;
-}
-
-static inline void _sbus_writel(u32 l, volatile void __iomem *addr)
-{
-	*(__force volatile u32 *)addr = l;
-}
-
-/*
- * The only reason for #define's is to hide casts to unsigned long.
- */
-#define sbus_readb(__addr)		_sbus_readb(__addr)
-#define sbus_readw(__addr)		_sbus_readw(__addr)
-#define sbus_readl(__addr)		_sbus_readl(__addr)
-#define sbus_writeb(__b, __addr)	_sbus_writeb(__b, __addr)
-#define sbus_writew(__w, __addr)	_sbus_writew(__w, __addr)
-#define sbus_writel(__l, __addr)	_sbus_writel(__l, __addr)
-
-static inline void sbus_memset_io(volatile void __iomem *__dst, int c, __kernel_size_t n)
-{
-	while(n--) {
-		sbus_writeb(c, __dst);
-		__dst++;
-	}
-}
-
-static inline void
-_memset_io(volatile void __iomem *dst, int c, __kernel_size_t n)
-{
-	volatile void __iomem *d = dst;
-
-	while (n--) {
-		writeb(c, d);
-		d++;
-	}
-}
-
-#define memset_io(d,c,sz)	_memset_io(d,c,sz)
-
-static inline void
-_memcpy_fromio(void *dst, const volatile void __iomem *src, __kernel_size_t n)
-{
-	char *d = dst;
-
-	while (n--) {
-		char tmp = readb(src);
-		*d++ = tmp;
-		src++;
-	}
-}
-
-#define memcpy_fromio(d,s,sz)	_memcpy_fromio(d,s,sz)
-
-static inline void 
-_memcpy_toio(volatile void __iomem *dst, const void *src, __kernel_size_t n)
-{
-	const char *s = src;
-	volatile void __iomem *d = dst;
-
-	while (n--) {
-		char tmp = *s++;
-		writeb(tmp, d);
-		d++;
-	}
-}
-
-#define memcpy_toio(d,s,sz)	_memcpy_toio(d,s,sz)
-
-#ifdef __KERNEL__
-
-/*
- * Bus number may be embedded in the higher bits of the physical address.
- * This is why we have no bus number argument to ioremap().
- */
-extern void __iomem *ioremap(unsigned long offset, unsigned long size);
-#define ioremap_nocache(X,Y)	ioremap((X),(Y))
-extern void iounmap(volatile void __iomem *addr);
-
-#define ioread8(X)			readb(X)
-#define ioread16(X)			readw(X)
-#define ioread32(X)			readl(X)
-#define iowrite8(val,X)			writeb(val,X)
-#define iowrite16(val,X)		writew(val,X)
-#define iowrite32(val,X)		writel(val,X)
-
-static inline void ioread8_rep(void __iomem *port, void *buf, unsigned long count)
-{
-	insb((unsigned long __force)port, buf, count);
-}
-static inline void ioread16_rep(void __iomem *port, void *buf, unsigned long count)
-{
-	insw((unsigned long __force)port, buf, count);
-}
-
-static inline void ioread32_rep(void __iomem *port, void *buf, unsigned long count)
-{
-	insl((unsigned long __force)port, buf, count);
-}
-
-static inline void iowrite8_rep(void __iomem *port, const void *buf, unsigned long count)
-{
-	outsb((unsigned long __force)port, buf, count);
-}
-
-static inline void iowrite16_rep(void __iomem *port, const void *buf, unsigned long count)
-{
-	outsw((unsigned long __force)port, buf, count);
-}
-
-static inline void iowrite32_rep(void __iomem *port, const void *buf, unsigned long count)
-{
-	outsl((unsigned long __force)port, buf, count);
-}
-
-/* Create a virtual mapping cookie for an IO port range */
-extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
-extern void ioport_unmap(void __iomem *);
-
-/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
-struct pci_dev;
-extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
-extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
-
-/*
- * Bus number may be in res->flags... somewhere.
- */
-extern void __iomem *sbus_ioremap(struct resource *res, unsigned long offset,
-    unsigned long size, char *name);
-extern void sbus_iounmap(volatile void __iomem *vaddr, unsigned long size);
-
-
-/*
- * At the moment, we do not use CMOS_READ anywhere outside of rtc.c,
- * so rtc_port is static in it. This should not change unless a new
- * hardware pops up.
- */
-#define RTC_PORT(x)   (rtc_port + (x))
-#define RTC_ALWAYS_BCD  0
-
+#ifndef ___ASM_SPARC_IO_H
+#define ___ASM_SPARC_IO_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/io_64.h>
+#else
+#include <asm-sparc/io_32.h>
 #endif
-
-#define __ARCH_HAS_NO_PAGE_ZERO_MAPPED		1
-
-/*
- * Convert a physical pointer to a virtual kernel pointer for /dev/mem
- * access
- */
-#define xlate_dev_mem_ptr(p)	__va(p)
-
-/*
- * Convert a virtual cached pointer to an uncached pointer
- */
-#define xlate_dev_kmem_ptr(p)	p
-
-#endif /* !(__SPARC_IO_H) */
+#endif
diff --git a/include/asm-sparc/io_32.h b/include/asm-sparc/io_32.h
new file mode 100644
index 0000000..10d7da4
--- /dev/null
+++ b/include/asm-sparc/io_32.h
@@ -0,0 +1,326 @@
+#ifndef __SPARC_IO_H
+#define __SPARC_IO_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/ioport.h>  /* struct resource */
+
+#include <asm/page.h>      /* IO address mapping routines need this */
+#include <asm/system.h>
+
+#define page_to_phys(page)	(((page) - mem_map) << PAGE_SHIFT)
+
+static inline u32 flip_dword (u32 l)
+{
+	return ((l&0xff)<<24) | (((l>>8)&0xff)<<16) | (((l>>16)&0xff)<<8)| ((l>>24)&0xff);
+}
+
+static inline u16 flip_word (u16 w)
+{
+	return ((w&0xff) << 8) | ((w>>8)&0xff);
+}
+
+#define mmiowb()
+
+/*
+ * Memory mapped I/O to PCI
+ */
+
+static inline u8 __raw_readb(const volatile void __iomem *addr)
+{
+	return *(__force volatile u8 *)addr;
+}
+
+static inline u16 __raw_readw(const volatile void __iomem *addr)
+{
+	return *(__force volatile u16 *)addr;
+}
+
+static inline u32 __raw_readl(const volatile void __iomem *addr)
+{
+	return *(__force volatile u32 *)addr;
+}
+
+static inline void __raw_writeb(u8 b, volatile void __iomem *addr)
+{
+	*(__force volatile u8 *)addr = b;
+}
+
+static inline void __raw_writew(u16 w, volatile void __iomem *addr)
+{
+	*(__force volatile u16 *)addr = w;
+}
+
+static inline void __raw_writel(u32 l, volatile void __iomem *addr)
+{
+	*(__force volatile u32 *)addr = l;
+}
+
+static inline u8 __readb(const volatile void __iomem *addr)
+{
+	return *(__force volatile u8 *)addr;
+}
+
+static inline u16 __readw(const volatile void __iomem *addr)
+{
+	return flip_word(*(__force volatile u16 *)addr);
+}
+
+static inline u32 __readl(const volatile void __iomem *addr)
+{
+	return flip_dword(*(__force volatile u32 *)addr);
+}
+
+static inline void __writeb(u8 b, volatile void __iomem *addr)
+{
+	*(__force volatile u8 *)addr = b;
+}
+
+static inline void __writew(u16 w, volatile void __iomem *addr)
+{
+	*(__force volatile u16 *)addr = flip_word(w);
+}
+
+static inline void __writel(u32 l, volatile void __iomem *addr)
+{
+	*(__force volatile u32 *)addr = flip_dword(l);
+}
+
+#define readb(__addr)		__readb(__addr)
+#define readw(__addr)		__readw(__addr)
+#define readl(__addr)		__readl(__addr)
+#define readb_relaxed(__addr)	readb(__addr)
+#define readw_relaxed(__addr)	readw(__addr)
+#define readl_relaxed(__addr)	readl(__addr)
+
+#define writeb(__b, __addr)	__writeb((__b),(__addr))
+#define writew(__w, __addr)	__writew((__w),(__addr))
+#define writel(__l, __addr)	__writel((__l),(__addr))
+
+/*
+ * I/O space operations
+ *
+ * Arrangement on a Sun is somewhat complicated.
+ *
+ * First of all, we want to use standard Linux drivers
+ * for keyboard, PC serial, etc. These drivers think
+ * they access I/O space and use inb/outb.
+ * On the other hand, EBus bridge accepts PCI *memory*
+ * cycles and converts them into ISA *I/O* cycles.
+ * Ergo, we want inb & outb to generate PCI memory cycles.
+ *
+ * If we want to issue PCI *I/O* cycles, we do this
+ * with a low 64K fixed window in PCIC. This window gets
+ * mapped somewhere into virtual kernel space and we
+ * can use inb/outb again.
+ */
+#define inb_local(__addr)	__readb((void __iomem *)(unsigned long)(__addr))
+#define inb(__addr)		__readb((void __iomem *)(unsigned long)(__addr))
+#define inw(__addr)		__readw((void __iomem *)(unsigned long)(__addr))
+#define inl(__addr)		__readl((void __iomem *)(unsigned long)(__addr))
+
+#define outb_local(__b, __addr)	__writeb(__b, (void __iomem *)(unsigned long)(__addr))
+#define outb(__b, __addr)	__writeb(__b, (void __iomem *)(unsigned long)(__addr))
+#define outw(__w, __addr)	__writew(__w, (void __iomem *)(unsigned long)(__addr))
+#define outl(__l, __addr)	__writel(__l, (void __iomem *)(unsigned long)(__addr))
+
+#define inb_p(__addr)		inb(__addr)
+#define outb_p(__b, __addr)	outb(__b, __addr)
+#define inw_p(__addr)		inw(__addr)
+#define outw_p(__w, __addr)	outw(__w, __addr)
+#define inl_p(__addr)		inl(__addr)
+#define outl_p(__l, __addr)	outl(__l, __addr)
+
+void outsb(unsigned long addr, const void *src, unsigned long cnt);
+void outsw(unsigned long addr, const void *src, unsigned long cnt);
+void outsl(unsigned long addr, const void *src, unsigned long cnt);
+void insb(unsigned long addr, void *dst, unsigned long count);
+void insw(unsigned long addr, void *dst, unsigned long count);
+void insl(unsigned long addr, void *dst, unsigned long count);
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+/*
+ * SBus accessors.
+ *
+ * SBus has only one, memory mapped, I/O space.
+ * We do not need to flip bytes for SBus of course.
+ */
+static inline u8 _sbus_readb(const volatile void __iomem *addr)
+{
+	return *(__force volatile u8 *)addr;
+}
+
+static inline u16 _sbus_readw(const volatile void __iomem *addr)
+{
+	return *(__force volatile u16 *)addr;
+}
+
+static inline u32 _sbus_readl(const volatile void __iomem *addr)
+{
+	return *(__force volatile u32 *)addr;
+}
+
+static inline void _sbus_writeb(u8 b, volatile void __iomem *addr)
+{
+	*(__force volatile u8 *)addr = b;
+}
+
+static inline void _sbus_writew(u16 w, volatile void __iomem *addr)
+{
+	*(__force volatile u16 *)addr = w;
+}
+
+static inline void _sbus_writel(u32 l, volatile void __iomem *addr)
+{
+	*(__force volatile u32 *)addr = l;
+}
+
+/*
+ * The only reason for #define's is to hide casts to unsigned long.
+ */
+#define sbus_readb(__addr)		_sbus_readb(__addr)
+#define sbus_readw(__addr)		_sbus_readw(__addr)
+#define sbus_readl(__addr)		_sbus_readl(__addr)
+#define sbus_writeb(__b, __addr)	_sbus_writeb(__b, __addr)
+#define sbus_writew(__w, __addr)	_sbus_writew(__w, __addr)
+#define sbus_writel(__l, __addr)	_sbus_writel(__l, __addr)
+
+static inline void sbus_memset_io(volatile void __iomem *__dst, int c, __kernel_size_t n)
+{
+	while(n--) {
+		sbus_writeb(c, __dst);
+		__dst++;
+	}
+}
+
+static inline void
+_memset_io(volatile void __iomem *dst, int c, __kernel_size_t n)
+{
+	volatile void __iomem *d = dst;
+
+	while (n--) {
+		writeb(c, d);
+		d++;
+	}
+}
+
+#define memset_io(d,c,sz)	_memset_io(d,c,sz)
+
+static inline void
+_memcpy_fromio(void *dst, const volatile void __iomem *src, __kernel_size_t n)
+{
+	char *d = dst;
+
+	while (n--) {
+		char tmp = readb(src);
+		*d++ = tmp;
+		src++;
+	}
+}
+
+#define memcpy_fromio(d,s,sz)	_memcpy_fromio(d,s,sz)
+
+static inline void
+_memcpy_toio(volatile void __iomem *dst, const void *src, __kernel_size_t n)
+{
+	const char *s = src;
+	volatile void __iomem *d = dst;
+
+	while (n--) {
+		char tmp = *s++;
+		writeb(tmp, d);
+		d++;
+	}
+}
+
+#define memcpy_toio(d,s,sz)	_memcpy_toio(d,s,sz)
+
+#ifdef __KERNEL__
+
+/*
+ * Bus number may be embedded in the higher bits of the physical address.
+ * This is why we have no bus number argument to ioremap().
+ */
+extern void __iomem *ioremap(unsigned long offset, unsigned long size);
+#define ioremap_nocache(X,Y)	ioremap((X),(Y))
+#define ioremap_wc(X,Y)		ioremap((X),(Y))
+extern void iounmap(volatile void __iomem *addr);
+
+#define ioread8(X)			readb(X)
+#define ioread16(X)			readw(X)
+#define ioread32(X)			readl(X)
+#define iowrite8(val,X)			writeb(val,X)
+#define iowrite16(val,X)		writew(val,X)
+#define iowrite32(val,X)		writel(val,X)
+
+static inline void ioread8_rep(void __iomem *port, void *buf, unsigned long count)
+{
+	insb((unsigned long __force)port, buf, count);
+}
+static inline void ioread16_rep(void __iomem *port, void *buf, unsigned long count)
+{
+	insw((unsigned long __force)port, buf, count);
+}
+
+static inline void ioread32_rep(void __iomem *port, void *buf, unsigned long count)
+{
+	insl((unsigned long __force)port, buf, count);
+}
+
+static inline void iowrite8_rep(void __iomem *port, const void *buf, unsigned long count)
+{
+	outsb((unsigned long __force)port, buf, count);
+}
+
+static inline void iowrite16_rep(void __iomem *port, const void *buf, unsigned long count)
+{
+	outsw((unsigned long __force)port, buf, count);
+}
+
+static inline void iowrite32_rep(void __iomem *port, const void *buf, unsigned long count)
+{
+	outsl((unsigned long __force)port, buf, count);
+}
+
+/* Create a virtual mapping cookie for an IO port range */
+extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
+extern void ioport_unmap(void __iomem *);
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+struct pci_dev;
+extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
+extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
+
+/*
+ * Bus number may be in res->flags... somewhere.
+ */
+extern void __iomem *sbus_ioremap(struct resource *res, unsigned long offset,
+    unsigned long size, char *name);
+extern void sbus_iounmap(volatile void __iomem *vaddr, unsigned long size);
+
+
+/*
+ * At the moment, we do not use CMOS_READ anywhere outside of rtc.c,
+ * so rtc_port is static in it. This should not change unless a new
+ * hardware pops up.
+ */
+#define RTC_PORT(x)   (rtc_port + (x))
+#define RTC_ALWAYS_BCD  0
+
+#endif
+
+#define __ARCH_HAS_NO_PAGE_ZERO_MAPPED		1
+
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p)	__va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p)	p
+
+#endif /* !(__SPARC_IO_H) */
diff --git a/include/asm-sparc/io_64.h b/include/asm-sparc/io_64.h
new file mode 100644
index 0000000..0bff078
--- /dev/null
+++ b/include/asm-sparc/io_64.h
@@ -0,0 +1,511 @@
+#ifndef __SPARC64_IO_H
+#define __SPARC64_IO_H
+
+#include <linux/kernel.h>
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+#include <asm/page.h>      /* IO address mapping routines need this */
+#include <asm/system.h>
+#include <asm/asi.h>
+
+/* PC crapola... */
+#define __SLOW_DOWN_IO	do { } while (0)
+#define SLOW_DOWN_IO	do { } while (0)
+
+/* BIO layer definitions. */
+extern unsigned long kern_base, kern_size;
+#define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
+
+static inline u8 _inb(unsigned long addr)
+{
+	u8 ret;
+
+	__asm__ __volatile__("lduba\t[%1] %2, %0\t/* pci_inb */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+			     : "memory");
+
+	return ret;
+}
+
+static inline u16 _inw(unsigned long addr)
+{
+	u16 ret;
+
+	__asm__ __volatile__("lduha\t[%1] %2, %0\t/* pci_inw */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+			     : "memory");
+
+	return ret;
+}
+
+static inline u32 _inl(unsigned long addr)
+{
+	u32 ret;
+
+	__asm__ __volatile__("lduwa\t[%1] %2, %0\t/* pci_inl */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+			     : "memory");
+
+	return ret;
+}
+
+static inline void _outb(u8 b, unsigned long addr)
+{
+	__asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_outb */"
+			     : /* no outputs */
+			     : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+			     : "memory");
+}
+
+static inline void _outw(u16 w, unsigned long addr)
+{
+	__asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_outw */"
+			     : /* no outputs */
+			     : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+			     : "memory");
+}
+
+static inline void _outl(u32 l, unsigned long addr)
+{
+	__asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_outl */"
+			     : /* no outputs */
+			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+			     : "memory");
+}
+
+#define inb(__addr)		(_inb((unsigned long)(__addr)))
+#define inw(__addr)		(_inw((unsigned long)(__addr)))
+#define inl(__addr)		(_inl((unsigned long)(__addr)))
+#define outb(__b, __addr)	(_outb((u8)(__b), (unsigned long)(__addr)))
+#define outw(__w, __addr)	(_outw((u16)(__w), (unsigned long)(__addr)))
+#define outl(__l, __addr)	(_outl((u32)(__l), (unsigned long)(__addr)))
+
+#define inb_p(__addr) 		inb(__addr)
+#define outb_p(__b, __addr)	outb(__b, __addr)
+#define inw_p(__addr)		inw(__addr)
+#define outw_p(__w, __addr)	outw(__w, __addr)
+#define inl_p(__addr)		inl(__addr)
+#define outl_p(__l, __addr)	outl(__l, __addr)
+
+extern void outsb(unsigned long, const void *, unsigned long);
+extern void outsw(unsigned long, const void *, unsigned long);
+extern void outsl(unsigned long, const void *, unsigned long);
+extern void insb(unsigned long, void *, unsigned long);
+extern void insw(unsigned long, void *, unsigned long);
+extern void insl(unsigned long, void *, unsigned long);
+
+static inline void ioread8_rep(void __iomem *port, void *buf, unsigned long count)
+{
+	insb((unsigned long __force)port, buf, count);
+}
+static inline void ioread16_rep(void __iomem *port, void *buf, unsigned long count)
+{
+	insw((unsigned long __force)port, buf, count);
+}
+
+static inline void ioread32_rep(void __iomem *port, void *buf, unsigned long count)
+{
+	insl((unsigned long __force)port, buf, count);
+}
+
+static inline void iowrite8_rep(void __iomem *port, const void *buf, unsigned long count)
+{
+	outsb((unsigned long __force)port, buf, count);
+}
+
+static inline void iowrite16_rep(void __iomem *port, const void *buf, unsigned long count)
+{
+	outsw((unsigned long __force)port, buf, count);
+}
+
+static inline void iowrite32_rep(void __iomem *port, const void *buf, unsigned long count)
+{
+	outsl((unsigned long __force)port, buf, count);
+}
+
+/* Memory functions, same as I/O accesses on Ultra. */
+static inline u8 _readb(const volatile void __iomem *addr)
+{	u8 ret;
+
+	__asm__ __volatile__("lduba\t[%1] %2, %0\t/* pci_readb */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+			     : "memory");
+	return ret;
+}
+
+static inline u16 _readw(const volatile void __iomem *addr)
+{	u16 ret;
+
+	__asm__ __volatile__("lduha\t[%1] %2, %0\t/* pci_readw */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+			     : "memory");
+
+	return ret;
+}
+
+static inline u32 _readl(const volatile void __iomem *addr)
+{	u32 ret;
+
+	__asm__ __volatile__("lduwa\t[%1] %2, %0\t/* pci_readl */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+			     : "memory");
+
+	return ret;
+}
+
+static inline u64 _readq(const volatile void __iomem *addr)
+{	u64 ret;
+
+	__asm__ __volatile__("ldxa\t[%1] %2, %0\t/* pci_readq */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+			     : "memory");
+
+	return ret;
+}
+
+static inline void _writeb(u8 b, volatile void __iomem *addr)
+{
+	__asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_writeb */"
+			     : /* no outputs */
+			     : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+			     : "memory");
+}
+
+static inline void _writew(u16 w, volatile void __iomem *addr)
+{
+	__asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_writew */"
+			     : /* no outputs */
+			     : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+			     : "memory");
+}
+
+static inline void _writel(u32 l, volatile void __iomem *addr)
+{
+	__asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_writel */"
+			     : /* no outputs */
+			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+			     : "memory");
+}
+
+static inline void _writeq(u64 q, volatile void __iomem *addr)
+{
+	__asm__ __volatile__("stxa\t%r0, [%1] %2\t/* pci_writeq */"
+			     : /* no outputs */
+			     : "Jr" (q), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+			     : "memory");
+}
+
+#define readb(__addr)		_readb(__addr)
+#define readw(__addr)		_readw(__addr)
+#define readl(__addr)		_readl(__addr)
+#define readq(__addr)		_readq(__addr)
+#define readb_relaxed(__addr)	_readb(__addr)
+#define readw_relaxed(__addr)	_readw(__addr)
+#define readl_relaxed(__addr)	_readl(__addr)
+#define readq_relaxed(__addr)	_readq(__addr)
+#define writeb(__b, __addr)	_writeb(__b, __addr)
+#define writew(__w, __addr)	_writew(__w, __addr)
+#define writel(__l, __addr)	_writel(__l, __addr)
+#define writeq(__q, __addr)	_writeq(__q, __addr)
+
+/* Now versions without byte-swapping. */
+static inline u8 _raw_readb(unsigned long addr)
+{
+	u8 ret;
+
+	__asm__ __volatile__("lduba\t[%1] %2, %0\t/* pci_raw_readb */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+	return ret;
+}
+
+static inline u16 _raw_readw(unsigned long addr)
+{
+	u16 ret;
+
+	__asm__ __volatile__("lduha\t[%1] %2, %0\t/* pci_raw_readw */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+	return ret;
+}
+
+static inline u32 _raw_readl(unsigned long addr)
+{
+	u32 ret;
+
+	__asm__ __volatile__("lduwa\t[%1] %2, %0\t/* pci_raw_readl */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+	return ret;
+}
+
+static inline u64 _raw_readq(unsigned long addr)
+{
+	u64 ret;
+
+	__asm__ __volatile__("ldxa\t[%1] %2, %0\t/* pci_raw_readq */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+	return ret;
+}
+
+static inline void _raw_writeb(u8 b, unsigned long addr)
+{
+	__asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_raw_writeb */"
+			     : /* no outputs */
+			     : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+static inline void _raw_writew(u16 w, unsigned long addr)
+{
+	__asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_raw_writew */"
+			     : /* no outputs */
+			     : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+static inline void _raw_writel(u32 l, unsigned long addr)
+{
+	__asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_raw_writel */"
+			     : /* no outputs */
+			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+static inline void _raw_writeq(u64 q, unsigned long addr)
+{
+	__asm__ __volatile__("stxa\t%r0, [%1] %2\t/* pci_raw_writeq */"
+			     : /* no outputs */
+			     : "Jr" (q), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+#define __raw_readb(__addr)		(_raw_readb((unsigned long)(__addr)))
+#define __raw_readw(__addr)		(_raw_readw((unsigned long)(__addr)))
+#define __raw_readl(__addr)		(_raw_readl((unsigned long)(__addr)))
+#define __raw_readq(__addr)		(_raw_readq((unsigned long)(__addr)))
+#define __raw_writeb(__b, __addr)	(_raw_writeb((u8)(__b), (unsigned long)(__addr)))
+#define __raw_writew(__w, __addr)	(_raw_writew((u16)(__w), (unsigned long)(__addr)))
+#define __raw_writel(__l, __addr)	(_raw_writel((u32)(__l), (unsigned long)(__addr)))
+#define __raw_writeq(__q, __addr)	(_raw_writeq((u64)(__q), (unsigned long)(__addr)))
+
+/* Valid I/O Space regions are anywhere, because each PCI bus supported
+ * can live in an arbitrary area of the physical address range.
+ */
+#define IO_SPACE_LIMIT 0xffffffffffffffffUL
+
+/* Now, SBUS variants, only difference from PCI is that we do
+ * not use little-endian ASIs.
+ */
+static inline u8 _sbus_readb(const volatile void __iomem *addr)
+{
+	u8 ret;
+
+	__asm__ __volatile__("lduba\t[%1] %2, %0\t/* sbus_readb */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
+			     : "memory");
+
+	return ret;
+}
+
+static inline u16 _sbus_readw(const volatile void __iomem *addr)
+{
+	u16 ret;
+
+	__asm__ __volatile__("lduha\t[%1] %2, %0\t/* sbus_readw */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
+			     : "memory");
+
+	return ret;
+}
+
+static inline u32 _sbus_readl(const volatile void __iomem *addr)
+{
+	u32 ret;
+
+	__asm__ __volatile__("lduwa\t[%1] %2, %0\t/* sbus_readl */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
+			     : "memory");
+
+	return ret;
+}
+
+static inline u64 _sbus_readq(const volatile void __iomem *addr)
+{
+	u64 ret;
+
+	__asm__ __volatile__("ldxa\t[%1] %2, %0\t/* sbus_readq */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
+			     : "memory");
+
+	return ret;
+}
+
+static inline void _sbus_writeb(u8 b, volatile void __iomem *addr)
+{
+	__asm__ __volatile__("stba\t%r0, [%1] %2\t/* sbus_writeb */"
+			     : /* no outputs */
+			     : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
+			     : "memory");
+}
+
+static inline void _sbus_writew(u16 w, volatile void __iomem *addr)
+{
+	__asm__ __volatile__("stha\t%r0, [%1] %2\t/* sbus_writew */"
+			     : /* no outputs */
+			     : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
+			     : "memory");
+}
+
+static inline void _sbus_writel(u32 l, volatile void __iomem *addr)
+{
+	__asm__ __volatile__("stwa\t%r0, [%1] %2\t/* sbus_writel */"
+			     : /* no outputs */
+			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
+			     : "memory");
+}
+
+static inline void _sbus_writeq(u64 l, volatile void __iomem *addr)
+{
+	__asm__ __volatile__("stxa\t%r0, [%1] %2\t/* sbus_writeq */"
+			     : /* no outputs */
+			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
+			     : "memory");
+}
+
+#define sbus_readb(__addr)		_sbus_readb(__addr)
+#define sbus_readw(__addr)		_sbus_readw(__addr)
+#define sbus_readl(__addr)		_sbus_readl(__addr)
+#define sbus_readq(__addr)		_sbus_readq(__addr)
+#define sbus_writeb(__b, __addr)	_sbus_writeb(__b, __addr)
+#define sbus_writew(__w, __addr)	_sbus_writew(__w, __addr)
+#define sbus_writel(__l, __addr)	_sbus_writel(__l, __addr)
+#define sbus_writeq(__l, __addr)	_sbus_writeq(__l, __addr)
+
+static inline void _sbus_memset_io(volatile void __iomem *dst, int c, __kernel_size_t n)
+{
+	while(n--) {
+		sbus_writeb(c, dst);
+		dst++;
+	}
+}
+
+#define sbus_memset_io(d,c,sz)	_sbus_memset_io(d,c,sz)
+
+static inline void
+_memset_io(volatile void __iomem *dst, int c, __kernel_size_t n)
+{
+	volatile void __iomem *d = dst;
+
+	while (n--) {
+		writeb(c, d);
+		d++;
+	}
+}
+
+#define memset_io(d,c,sz)	_memset_io(d,c,sz)
+
+static inline void
+_memcpy_fromio(void *dst, const volatile void __iomem *src, __kernel_size_t n)
+{
+	char *d = dst;
+
+	while (n--) {
+		char tmp = readb(src);
+		*d++ = tmp;
+		src++;
+	}
+}
+
+#define memcpy_fromio(d,s,sz)	_memcpy_fromio(d,s,sz)
+
+static inline void
+_memcpy_toio(volatile void __iomem *dst, const void *src, __kernel_size_t n)
+{
+	const char *s = src;
+	volatile void __iomem *d = dst;
+
+	while (n--) {
+		char tmp = *s++;
+		writeb(tmp, d);
+		d++;
+	}
+}
+
+#define memcpy_toio(d,s,sz)	_memcpy_toio(d,s,sz)
+
+#define mmiowb()
+
+#ifdef __KERNEL__
+
+/* On sparc64 we have the whole physical IO address space accessible
+ * using physically addressed loads and stores, so this does nothing.
+ */
+static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
+{
+	return (void __iomem *)offset;
+}
+
+#define ioremap_nocache(X,Y)		ioremap((X),(Y))
+#define ioremap_wc(X,Y)			ioremap((X),(Y))
+
+static inline void iounmap(volatile void __iomem *addr)
+{
+}
+
+#define ioread8(X)			readb(X)
+#define ioread16(X)			readw(X)
+#define ioread32(X)			readl(X)
+#define iowrite8(val,X)			writeb(val,X)
+#define iowrite16(val,X)		writew(val,X)
+#define iowrite32(val,X)		writel(val,X)
+
+/* Create a virtual mapping cookie for an IO port range */
+extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
+extern void ioport_unmap(void __iomem *);
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+struct pci_dev;
+extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
+extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
+
+/* Similarly for SBUS. */
+#define sbus_ioremap(__res, __offset, __size, __name) \
+({	unsigned long __ret; \
+	__ret  = (__res)->start + (((__res)->flags & 0x1ffUL) << 32UL); \
+	__ret += (unsigned long) (__offset); \
+	if (! request_region((__ret), (__size), (__name))) \
+		__ret = 0UL; \
+	(void __iomem *) __ret; \
+})
+
+#define sbus_iounmap(__addr, __size)	\
+	release_region((unsigned long)(__addr), (__size))
+
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p)	__va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p)	p
+
+#endif
+
+#endif /* !(__SPARC64_IO_H) */
diff --git a/include/asm-sparc/ioctls.h b/include/asm-sparc/ioctls.h
index 3f4d008..1fe6855 100644
--- a/include/asm-sparc/ioctls.h
+++ b/include/asm-sparc/ioctls.h
@@ -22,7 +22,7 @@
 
 /* Note that all the ioctls that are not available in Linux have a 
  * double underscore on the front to: a) avoid some programs to
- * thing we support some ioctls under Linux (autoconfiguration stuff)
+ * think we support some ioctls under Linux (autoconfiguration stuff)
  */
 /* Little t */
 #define TIOCGETD	_IOR('t', 0, int)
@@ -110,7 +110,7 @@
 #define TIOCSERGETLSR   0x5459 /* Get line status register */
 #define TIOCSERGETMULTI 0x545A /* Get multiport config  */
 #define TIOCSERSETMULTI 0x545B /* Set multiport config */
-#define TIOCMIWAIT	0x545C /* Wait input */
+#define TIOCMIWAIT	0x545C /* Wait for change on serial input line(s) */
 #define TIOCGICOUNT	0x545D /* Read serial port inline interrupt counts */
 
 /* Kernel definitions */
diff --git a/include/asm-sparc/iommu.h b/include/asm-sparc/iommu.h
index 70c589c..91b072b 100644
--- a/include/asm-sparc/iommu.h
+++ b/include/asm-sparc/iommu.h
@@ -1,121 +1,8 @@
-/* iommu.h: Definitions for the sun4m IOMMU.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-#ifndef _SPARC_IOMMU_H
-#define _SPARC_IOMMU_H
-
-#include <asm/page.h>
-#include <asm/bitext.h>
-
-/* The iommu handles all virtual to physical address translations
- * that occur between the SBUS and physical memory.  Access by
- * the cpu to IO registers and similar go over the mbus so are
- * translated by the on chip SRMMU.  The iommu and the srmmu do
- * not need to have the same translations at all, in fact most
- * of the time the translations they handle are a disjunct set.
- * Basically the iommu handles all dvma sbus activity.
- */
-
-/* The IOMMU registers occupy three pages in IO space. */
-struct iommu_regs {
-	/* First page */
-	volatile unsigned long control;    /* IOMMU control */
-	volatile unsigned long base;       /* Physical base of iopte page table */
-	volatile unsigned long _unused1[3];
-	volatile unsigned long tlbflush;   /* write only */
-	volatile unsigned long pageflush;  /* write only */
-	volatile unsigned long _unused2[1017];
-	/* Second page */
-	volatile unsigned long afsr;       /* Async-fault status register */
-	volatile unsigned long afar;       /* Async-fault physical address */
-	volatile unsigned long _unused3[2];
-	volatile unsigned long sbuscfg0;   /* SBUS configuration registers, per-slot */
-	volatile unsigned long sbuscfg1;
-	volatile unsigned long sbuscfg2;
-	volatile unsigned long sbuscfg3;
-	volatile unsigned long mfsr;       /* Memory-fault status register */
-	volatile unsigned long mfar;       /* Memory-fault physical address */
-	volatile unsigned long _unused4[1014];
-	/* Third page */
-	volatile unsigned long mid;        /* IOMMU module-id */
-};
-
-#define IOMMU_CTRL_IMPL     0xf0000000 /* Implementation */
-#define IOMMU_CTRL_VERS     0x0f000000 /* Version */
-#define IOMMU_CTRL_RNGE     0x0000001c /* Mapping RANGE */
-#define IOMMU_RNGE_16MB     0x00000000 /* 0xff000000 -> 0xffffffff */
-#define IOMMU_RNGE_32MB     0x00000004 /* 0xfe000000 -> 0xffffffff */
-#define IOMMU_RNGE_64MB     0x00000008 /* 0xfc000000 -> 0xffffffff */
-#define IOMMU_RNGE_128MB    0x0000000c /* 0xf8000000 -> 0xffffffff */
-#define IOMMU_RNGE_256MB    0x00000010 /* 0xf0000000 -> 0xffffffff */
-#define IOMMU_RNGE_512MB    0x00000014 /* 0xe0000000 -> 0xffffffff */
-#define IOMMU_RNGE_1GB      0x00000018 /* 0xc0000000 -> 0xffffffff */
-#define IOMMU_RNGE_2GB      0x0000001c /* 0x80000000 -> 0xffffffff */
-#define IOMMU_CTRL_ENAB     0x00000001 /* IOMMU Enable */
-
-#define IOMMU_AFSR_ERR      0x80000000 /* LE, TO, or BE asserted */
-#define IOMMU_AFSR_LE       0x40000000 /* SBUS reports error after transaction */
-#define IOMMU_AFSR_TO       0x20000000 /* Write access took more than 12.8 us. */
-#define IOMMU_AFSR_BE       0x10000000 /* Write access received error acknowledge */
-#define IOMMU_AFSR_SIZE     0x0e000000 /* Size of transaction causing error */
-#define IOMMU_AFSR_S        0x01000000 /* Sparc was in supervisor mode */
-#define IOMMU_AFSR_RESV     0x00f00000 /* Reserver, forced to 0x8 by hardware */
-#define IOMMU_AFSR_ME       0x00080000 /* Multiple errors occurred */
-#define IOMMU_AFSR_RD       0x00040000 /* A read operation was in progress */
-#define IOMMU_AFSR_FAV      0x00020000 /* IOMMU afar has valid contents */
-
-#define IOMMU_SBCFG_SAB30   0x00010000 /* Phys-address bit 30 when bypass enabled */
-#define IOMMU_SBCFG_BA16    0x00000004 /* Slave supports 16 byte bursts */
-#define IOMMU_SBCFG_BA8     0x00000002 /* Slave supports 8 byte bursts */
-#define IOMMU_SBCFG_BYPASS  0x00000001 /* Bypass IOMMU, treat all addresses
-					  produced by this device as pure
-					  physical. */
-
-#define IOMMU_MFSR_ERR      0x80000000 /* One or more of PERR1 or PERR0 */
-#define IOMMU_MFSR_S        0x01000000 /* Sparc was in supervisor mode */
-#define IOMMU_MFSR_CPU      0x00800000 /* CPU transaction caused parity error */
-#define IOMMU_MFSR_ME       0x00080000 /* Multiple parity errors occurred */
-#define IOMMU_MFSR_PERR     0x00006000 /* high bit indicates parity error occurred
-					  on the even word of the access, low bit
-					  indicated odd word caused the parity error */
-#define IOMMU_MFSR_BM       0x00001000 /* Error occurred while in boot mode */
-#define IOMMU_MFSR_C        0x00000800 /* Address causing error was marked cacheable */
-#define IOMMU_MFSR_RTYP     0x000000f0 /* Memory request transaction type */
-
-#define IOMMU_MID_SBAE      0x001f0000 /* SBus arbitration enable */
-#define IOMMU_MID_SE        0x00100000 /* Enables SCSI/ETHERNET arbitration */
-#define IOMMU_MID_SB3       0x00080000 /* Enable SBUS device 3 arbitration */
-#define IOMMU_MID_SB2       0x00040000 /* Enable SBUS device 2 arbitration */
-#define IOMMU_MID_SB1       0x00020000 /* Enable SBUS device 1 arbitration */
-#define IOMMU_MID_SB0       0x00010000 /* Enable SBUS device 0 arbitration */
-#define IOMMU_MID_MID       0x0000000f /* Module-id, hardcoded to 0x8 */
-
-/* The format of an iopte in the page tables */
-#define IOPTE_PAGE          0x07ffff00 /* Physical page number (PA[30:12]) */
-#define IOPTE_CACHE         0x00000080 /* Cached (in vme IOCACHE or Viking/MXCC) */
-#define IOPTE_WRITE         0x00000004 /* Writeable */
-#define IOPTE_VALID         0x00000002 /* IOPTE is valid */
-#define IOPTE_WAZ           0x00000001 /* Write as zeros */
-
-struct iommu_struct {
-	struct iommu_regs *regs;
-	iopte_t *page_table;
-	/* For convenience */
-	unsigned long start; /* First managed virtual address */
-	unsigned long end;   /* Last managed virtual address */
-
-	struct bit_map usemap;
-};
-
-static inline void iommu_invalidate(struct iommu_regs *regs)
-{
-	regs->tlbflush = 0;
-}
-
-static inline void iommu_invalidate_page(struct iommu_regs *regs, unsigned long ba)
-{
-	regs->pageflush = (ba & PAGE_MASK);
-}
-
-#endif /* !(_SPARC_IOMMU_H) */
+#ifndef ___ASM_SPARC_IOMMU_H
+#define ___ASM_SPARC_IOMMU_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/iommu_64.h>
+#else
+#include <asm-sparc/iommu_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/iommu_32.h b/include/asm-sparc/iommu_32.h
new file mode 100644
index 0000000..70c589c
--- /dev/null
+++ b/include/asm-sparc/iommu_32.h
@@ -0,0 +1,121 @@
+/* iommu.h: Definitions for the sun4m IOMMU.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ */
+#ifndef _SPARC_IOMMU_H
+#define _SPARC_IOMMU_H
+
+#include <asm/page.h>
+#include <asm/bitext.h>
+
+/* The iommu handles all virtual to physical address translations
+ * that occur between the SBUS and physical memory.  Access by
+ * the cpu to IO registers and similar go over the mbus so are
+ * translated by the on chip SRMMU.  The iommu and the srmmu do
+ * not need to have the same translations at all, in fact most
+ * of the time the translations they handle are a disjunct set.
+ * Basically the iommu handles all dvma sbus activity.
+ */
+
+/* The IOMMU registers occupy three pages in IO space. */
+struct iommu_regs {
+	/* First page */
+	volatile unsigned long control;    /* IOMMU control */
+	volatile unsigned long base;       /* Physical base of iopte page table */
+	volatile unsigned long _unused1[3];
+	volatile unsigned long tlbflush;   /* write only */
+	volatile unsigned long pageflush;  /* write only */
+	volatile unsigned long _unused2[1017];
+	/* Second page */
+	volatile unsigned long afsr;       /* Async-fault status register */
+	volatile unsigned long afar;       /* Async-fault physical address */
+	volatile unsigned long _unused3[2];
+	volatile unsigned long sbuscfg0;   /* SBUS configuration registers, per-slot */
+	volatile unsigned long sbuscfg1;
+	volatile unsigned long sbuscfg2;
+	volatile unsigned long sbuscfg3;
+	volatile unsigned long mfsr;       /* Memory-fault status register */
+	volatile unsigned long mfar;       /* Memory-fault physical address */
+	volatile unsigned long _unused4[1014];
+	/* Third page */
+	volatile unsigned long mid;        /* IOMMU module-id */
+};
+
+#define IOMMU_CTRL_IMPL     0xf0000000 /* Implementation */
+#define IOMMU_CTRL_VERS     0x0f000000 /* Version */
+#define IOMMU_CTRL_RNGE     0x0000001c /* Mapping RANGE */
+#define IOMMU_RNGE_16MB     0x00000000 /* 0xff000000 -> 0xffffffff */
+#define IOMMU_RNGE_32MB     0x00000004 /* 0xfe000000 -> 0xffffffff */
+#define IOMMU_RNGE_64MB     0x00000008 /* 0xfc000000 -> 0xffffffff */
+#define IOMMU_RNGE_128MB    0x0000000c /* 0xf8000000 -> 0xffffffff */
+#define IOMMU_RNGE_256MB    0x00000010 /* 0xf0000000 -> 0xffffffff */
+#define IOMMU_RNGE_512MB    0x00000014 /* 0xe0000000 -> 0xffffffff */
+#define IOMMU_RNGE_1GB      0x00000018 /* 0xc0000000 -> 0xffffffff */
+#define IOMMU_RNGE_2GB      0x0000001c /* 0x80000000 -> 0xffffffff */
+#define IOMMU_CTRL_ENAB     0x00000001 /* IOMMU Enable */
+
+#define IOMMU_AFSR_ERR      0x80000000 /* LE, TO, or BE asserted */
+#define IOMMU_AFSR_LE       0x40000000 /* SBUS reports error after transaction */
+#define IOMMU_AFSR_TO       0x20000000 /* Write access took more than 12.8 us. */
+#define IOMMU_AFSR_BE       0x10000000 /* Write access received error acknowledge */
+#define IOMMU_AFSR_SIZE     0x0e000000 /* Size of transaction causing error */
+#define IOMMU_AFSR_S        0x01000000 /* Sparc was in supervisor mode */
+#define IOMMU_AFSR_RESV     0x00f00000 /* Reserver, forced to 0x8 by hardware */
+#define IOMMU_AFSR_ME       0x00080000 /* Multiple errors occurred */
+#define IOMMU_AFSR_RD       0x00040000 /* A read operation was in progress */
+#define IOMMU_AFSR_FAV      0x00020000 /* IOMMU afar has valid contents */
+
+#define IOMMU_SBCFG_SAB30   0x00010000 /* Phys-address bit 30 when bypass enabled */
+#define IOMMU_SBCFG_BA16    0x00000004 /* Slave supports 16 byte bursts */
+#define IOMMU_SBCFG_BA8     0x00000002 /* Slave supports 8 byte bursts */
+#define IOMMU_SBCFG_BYPASS  0x00000001 /* Bypass IOMMU, treat all addresses
+					  produced by this device as pure
+					  physical. */
+
+#define IOMMU_MFSR_ERR      0x80000000 /* One or more of PERR1 or PERR0 */
+#define IOMMU_MFSR_S        0x01000000 /* Sparc was in supervisor mode */
+#define IOMMU_MFSR_CPU      0x00800000 /* CPU transaction caused parity error */
+#define IOMMU_MFSR_ME       0x00080000 /* Multiple parity errors occurred */
+#define IOMMU_MFSR_PERR     0x00006000 /* high bit indicates parity error occurred
+					  on the even word of the access, low bit
+					  indicated odd word caused the parity error */
+#define IOMMU_MFSR_BM       0x00001000 /* Error occurred while in boot mode */
+#define IOMMU_MFSR_C        0x00000800 /* Address causing error was marked cacheable */
+#define IOMMU_MFSR_RTYP     0x000000f0 /* Memory request transaction type */
+
+#define IOMMU_MID_SBAE      0x001f0000 /* SBus arbitration enable */
+#define IOMMU_MID_SE        0x00100000 /* Enables SCSI/ETHERNET arbitration */
+#define IOMMU_MID_SB3       0x00080000 /* Enable SBUS device 3 arbitration */
+#define IOMMU_MID_SB2       0x00040000 /* Enable SBUS device 2 arbitration */
+#define IOMMU_MID_SB1       0x00020000 /* Enable SBUS device 1 arbitration */
+#define IOMMU_MID_SB0       0x00010000 /* Enable SBUS device 0 arbitration */
+#define IOMMU_MID_MID       0x0000000f /* Module-id, hardcoded to 0x8 */
+
+/* The format of an iopte in the page tables */
+#define IOPTE_PAGE          0x07ffff00 /* Physical page number (PA[30:12]) */
+#define IOPTE_CACHE         0x00000080 /* Cached (in vme IOCACHE or Viking/MXCC) */
+#define IOPTE_WRITE         0x00000004 /* Writeable */
+#define IOPTE_VALID         0x00000002 /* IOPTE is valid */
+#define IOPTE_WAZ           0x00000001 /* Write as zeros */
+
+struct iommu_struct {
+	struct iommu_regs *regs;
+	iopte_t *page_table;
+	/* For convenience */
+	unsigned long start; /* First managed virtual address */
+	unsigned long end;   /* Last managed virtual address */
+
+	struct bit_map usemap;
+};
+
+static inline void iommu_invalidate(struct iommu_regs *regs)
+{
+	regs->tlbflush = 0;
+}
+
+static inline void iommu_invalidate_page(struct iommu_regs *regs, unsigned long ba)
+{
+	regs->pageflush = (ba & PAGE_MASK);
+}
+
+#endif /* !(_SPARC_IOMMU_H) */
diff --git a/include/asm-sparc/iommu_64.h b/include/asm-sparc/iommu_64.h
new file mode 100644
index 0000000..d7b9afc
--- /dev/null
+++ b/include/asm-sparc/iommu_64.h
@@ -0,0 +1,62 @@
+/* iommu.h: Definitions for the sun5 IOMMU.
+ *
+ * Copyright (C) 1996, 1999, 2007 David S. Miller (davem@davemloft.net)
+ */
+#ifndef _SPARC64_IOMMU_H
+#define _SPARC64_IOMMU_H
+
+/* The format of an iopte in the page tables. */
+#define IOPTE_VALID   0x8000000000000000UL
+#define IOPTE_64K     0x2000000000000000UL
+#define IOPTE_STBUF   0x1000000000000000UL
+#define IOPTE_INTRA   0x0800000000000000UL
+#define IOPTE_CONTEXT 0x07ff800000000000UL
+#define IOPTE_PAGE    0x00007fffffffe000UL
+#define IOPTE_CACHE   0x0000000000000010UL
+#define IOPTE_WRITE   0x0000000000000002UL
+
+#define IOMMU_NUM_CTXS	4096
+
+struct iommu_arena {
+	unsigned long	*map;
+	unsigned int	hint;
+	unsigned int	limit;
+};
+
+struct iommu {
+	spinlock_t		lock;
+	struct iommu_arena	arena;
+	void			(*flush_all)(struct iommu *);
+	iopte_t			*page_table;
+	u32			page_table_map_base;
+	unsigned long		iommu_control;
+	unsigned long		iommu_tsbbase;
+	unsigned long		iommu_flush;
+	unsigned long		iommu_flushinv;
+	unsigned long		iommu_tags;
+	unsigned long		iommu_ctxflush;
+	unsigned long		write_complete_reg;
+	unsigned long		dummy_page;
+	unsigned long		dummy_page_pa;
+	unsigned long		ctx_lowest_free;
+	DECLARE_BITMAP(ctx_bitmap, IOMMU_NUM_CTXS);
+	u32			dma_addr_mask;
+};
+
+struct strbuf {
+	int			strbuf_enabled;
+	unsigned long		strbuf_control;
+	unsigned long		strbuf_pflush;
+	unsigned long		strbuf_fsync;
+	unsigned long		strbuf_ctxflush;
+	unsigned long		strbuf_ctxmatch_base;
+	unsigned long		strbuf_flushflag_pa;
+	volatile unsigned long *strbuf_flushflag;
+	volatile unsigned long	__flushflag_buf[(64+(64-1)) / sizeof(long)];
+};
+
+extern int iommu_table_init(struct iommu *iommu, int tsbsize,
+			    u32 dma_offset, u32 dma_addr_mask,
+			    int numa_node);
+
+#endif /* !(_SPARC64_IOMMU_H) */
diff --git a/include/asm-sparc/ipcbuf.h b/include/asm-sparc/ipcbuf.h
index 9bef02d..037605d 100644
--- a/include/asm-sparc/ipcbuf.h
+++ b/include/asm-sparc/ipcbuf.h
@@ -1,31 +1,8 @@
-#ifndef _SPARC_IPCBUF_H
-#define _SPARC_IPCBUF_H
-
-/* 
- * The ipc64_perm structure for sparc architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 32-bit mode
- * - 32-bit seq
- * - 2 miscellaneous 64-bit values (so that this structure matches
- *				    sparc64 ipc64_perm)
- */
-
-struct ipc64_perm
-{
-	__kernel_key_t		key;
-	__kernel_uid32_t	uid;
-	__kernel_gid32_t	gid;
-	__kernel_uid32_t	cuid;
-	__kernel_gid32_t	cgid;
-	unsigned short		__pad1;
-	__kernel_mode_t		mode;
-	unsigned short		__pad2;
-	unsigned short		seq;
-	unsigned long long	__unused1;
-	unsigned long long	__unused2;
-};
-
-#endif /* _SPARC_IPCBUF_H */
+#ifndef ___ASM_SPARC_IPCBUF_H
+#define ___ASM_SPARC_IPCBUF_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/ipcbuf_64.h>
+#else
+#include <asm-sparc/ipcbuf_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/ipcbuf_32.h b/include/asm-sparc/ipcbuf_32.h
new file mode 100644
index 0000000..6387209
--- /dev/null
+++ b/include/asm-sparc/ipcbuf_32.h
@@ -0,0 +1,31 @@
+#ifndef _SPARC_IPCBUF_H
+#define _SPARC_IPCBUF_H
+
+/*
+ * The ipc64_perm structure for sparc architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 32-bit mode
+ * - 32-bit seq
+ * - 2 miscellaneous 64-bit values (so that this structure matches
+ *				    sparc64 ipc64_perm)
+ */
+
+struct ipc64_perm
+{
+	__kernel_key_t		key;
+	__kernel_uid32_t	uid;
+	__kernel_gid32_t	gid;
+	__kernel_uid32_t	cuid;
+	__kernel_gid32_t	cgid;
+	unsigned short		__pad1;
+	__kernel_mode_t		mode;
+	unsigned short		__pad2;
+	unsigned short		seq;
+	unsigned long long	__unused1;
+	unsigned long long	__unused2;
+};
+
+#endif /* _SPARC_IPCBUF_H */
diff --git a/include/asm-sparc/ipcbuf_64.h b/include/asm-sparc/ipcbuf_64.h
new file mode 100644
index 0000000..a44b855
--- /dev/null
+++ b/include/asm-sparc/ipcbuf_64.h
@@ -0,0 +1,28 @@
+#ifndef _SPARC64_IPCBUF_H
+#define _SPARC64_IPCBUF_H
+
+/*
+ * The ipc64_perm structure for sparc64 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 32-bit seq
+ * - 2 miscellaneous 64-bit values
+ */
+
+struct ipc64_perm
+{
+	__kernel_key_t	key;
+	__kernel_uid_t	uid;
+	__kernel_gid_t	gid;
+	__kernel_uid_t	cuid;
+	__kernel_gid_t	cgid;
+	__kernel_mode_t	mode;
+	unsigned short	__pad1;
+	unsigned short	seq;
+	unsigned long	__unused1;
+	unsigned long	__unused2;
+};
+
+#endif /* _SPARC64_IPCBUF_H */
diff --git a/include/asm-sparc/irq.h b/include/asm-sparc/irq.h
index fe205cc..7af6bb4 100644
--- a/include/asm-sparc/irq.h
+++ b/include/asm-sparc/irq.h
@@ -1,15 +1,8 @@
-/* irq.h: IRQ registers on the Sparc.
- *
- * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
- */
-
-#ifndef _SPARC_IRQ_H
-#define _SPARC_IRQ_H
-
-#include <linux/interrupt.h>
-
-#define NR_IRQS    16
-
-#define irq_canonicalize(irq)	(irq)
-
+#ifndef ___ASM_SPARC_IRQ_H
+#define ___ASM_SPARC_IRQ_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/irq_64.h>
+#else
+#include <asm-sparc/irq_32.h>
+#endif
 #endif
diff --git a/include/asm-sparc/irq_32.h b/include/asm-sparc/irq_32.h
new file mode 100644
index 0000000..fe205cc
--- /dev/null
+++ b/include/asm-sparc/irq_32.h
@@ -0,0 +1,15 @@
+/* irq.h: IRQ registers on the Sparc.
+ *
+ * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
+ */
+
+#ifndef _SPARC_IRQ_H
+#define _SPARC_IRQ_H
+
+#include <linux/interrupt.h>
+
+#define NR_IRQS    16
+
+#define irq_canonicalize(irq)	(irq)
+
+#endif
diff --git a/include/asm-sparc/irq_64.h b/include/asm-sparc/irq_64.h
new file mode 100644
index 0000000..0bb9bf5
--- /dev/null
+++ b/include/asm-sparc/irq_64.h
@@ -0,0 +1,93 @@
+/* irq.h: IRQ registers on the 64-bit Sparc.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
+ */
+
+#ifndef _SPARC64_IRQ_H
+#define _SPARC64_IRQ_H
+
+#include <linux/linkage.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <asm/pil.h>
+#include <asm/ptrace.h>
+
+/* IMAP/ICLR register defines */
+#define IMAP_VALID		0x80000000UL	/* IRQ Enabled		*/
+#define IMAP_TID_UPA		0x7c000000UL	/* UPA TargetID		*/
+#define IMAP_TID_JBUS		0x7c000000UL	/* JBUS TargetID	*/
+#define IMAP_TID_SHIFT		26
+#define IMAP_AID_SAFARI		0x7c000000UL	/* Safari AgentID	*/
+#define IMAP_AID_SHIFT		26
+#define IMAP_NID_SAFARI		0x03e00000UL	/* Safari NodeID	*/
+#define IMAP_NID_SHIFT		21
+#define IMAP_IGN		0x000007c0UL	/* IRQ Group Number	*/
+#define IMAP_INO		0x0000003fUL	/* IRQ Number		*/
+#define IMAP_INR		0x000007ffUL	/* Full interrupt number*/
+
+#define ICLR_IDLE		0x00000000UL	/* Idle state		*/
+#define ICLR_TRANSMIT		0x00000001UL	/* Transmit state	*/
+#define ICLR_PENDING		0x00000003UL	/* Pending state	*/
+
+/* The largest number of unique interrupt sources we support.
+ * If this needs to ever be larger than 255, you need to change
+ * the type of ino_bucket->virt_irq as appropriate.
+ *
+ * ino_bucket->virt_irq allocation is made during {sun4v_,}build_irq().
+ */
+#define NR_IRQS    255
+
+extern void irq_install_pre_handler(int virt_irq,
+				    void (*func)(unsigned int, void *, void *),
+				    void *arg1, void *arg2);
+#define irq_canonicalize(irq)	(irq)
+extern unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap);
+extern unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino);
+extern unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino);
+extern unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p,
+				    unsigned int msi_devino_start,
+				    unsigned int msi_devino_end);
+extern void sun4v_destroy_msi(unsigned int virt_irq);
+extern unsigned int sun4u_build_msi(u32 portid, unsigned int *virt_irq_p,
+				    unsigned int msi_devino_start,
+				    unsigned int msi_devino_end,
+				    unsigned long imap_base,
+				    unsigned long iclr_base);
+extern void sun4u_destroy_msi(unsigned int virt_irq);
+extern unsigned int sbus_build_irq(void *sbus, unsigned int ino);
+
+extern unsigned char virt_irq_alloc(unsigned int dev_handle,
+				    unsigned int dev_ino);
+#ifdef CONFIG_PCI_MSI
+extern void virt_irq_free(unsigned int virt_irq);
+#endif
+
+extern void __init init_IRQ(void);
+extern void fixup_irqs(void);
+
+static inline void set_softint(unsigned long bits)
+{
+	__asm__ __volatile__("wr	%0, 0x0, %%set_softint"
+			     : /* No outputs */
+			     : "r" (bits));
+}
+
+static inline void clear_softint(unsigned long bits)
+{
+	__asm__ __volatile__("wr	%0, 0x0, %%clear_softint"
+			     : /* No outputs */
+			     : "r" (bits));
+}
+
+static inline unsigned long get_softint(void)
+{
+	unsigned long retval;
+
+	__asm__ __volatile__("rd	%%softint, %0"
+			     : "=r" (retval));
+	return retval;
+}
+
+#endif
diff --git a/include/asm-sparc/irqflags.h b/include/asm-sparc/irqflags.h
index db398fb..c6402b1 100644
--- a/include/asm-sparc/irqflags.h
+++ b/include/asm-sparc/irqflags.h
@@ -1,39 +1,8 @@
-/*
- * include/asm-sparc/irqflags.h
- *
- * IRQ flags handling
- *
- * This file gets included from lowlevel asm headers too, to provide
- * wrapped versions of the local_irq_*() APIs, based on the
- * raw_local_irq_*() functions from the lowlevel headers.
- */
-#ifndef _ASM_IRQFLAGS_H
-#define _ASM_IRQFLAGS_H
-
-#ifndef __ASSEMBLY__
-
-extern void raw_local_irq_restore(unsigned long);
-extern unsigned long __raw_local_irq_save(void);
-extern void raw_local_irq_enable(void);
-
-static inline unsigned long getipl(void)
-{
-        unsigned long retval;
-
-        __asm__ __volatile__("rd        %%psr, %0" : "=r" (retval));
-        return retval;
-}
-
-#define raw_local_save_flags(flags) ((flags) = getipl())
-#define raw_local_irq_save(flags)   ((flags) = __raw_local_irq_save())
-#define raw_local_irq_disable()     ((void) __raw_local_irq_save())
-#define raw_irqs_disabled()         ((getipl() & PSR_PIL) != 0)
-
-static inline int raw_irqs_disabled_flags(unsigned long flags)
-{
-        return ((flags & PSR_PIL) != 0);
-}
-
-#endif /* (__ASSEMBLY__) */
-
-#endif /* !(_ASM_IRQFLAGS_H) */
+#ifndef ___ASM_SPARC_IRQFLAGS_H
+#define ___ASM_SPARC_IRQFLAGS_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/irqflags_64.h>
+#else
+#include <asm-sparc/irqflags_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/irqflags_32.h b/include/asm-sparc/irqflags_32.h
new file mode 100644
index 0000000..db398fb
--- /dev/null
+++ b/include/asm-sparc/irqflags_32.h
@@ -0,0 +1,39 @@
+/*
+ * include/asm-sparc/irqflags.h
+ *
+ * IRQ flags handling
+ *
+ * This file gets included from lowlevel asm headers too, to provide
+ * wrapped versions of the local_irq_*() APIs, based on the
+ * raw_local_irq_*() functions from the lowlevel headers.
+ */
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+#ifndef __ASSEMBLY__
+
+extern void raw_local_irq_restore(unsigned long);
+extern unsigned long __raw_local_irq_save(void);
+extern void raw_local_irq_enable(void);
+
+static inline unsigned long getipl(void)
+{
+        unsigned long retval;
+
+        __asm__ __volatile__("rd        %%psr, %0" : "=r" (retval));
+        return retval;
+}
+
+#define raw_local_save_flags(flags) ((flags) = getipl())
+#define raw_local_irq_save(flags)   ((flags) = __raw_local_irq_save())
+#define raw_local_irq_disable()     ((void) __raw_local_irq_save())
+#define raw_irqs_disabled()         ((getipl() & PSR_PIL) != 0)
+
+static inline int raw_irqs_disabled_flags(unsigned long flags)
+{
+        return ((flags & PSR_PIL) != 0);
+}
+
+#endif /* (__ASSEMBLY__) */
+
+#endif /* !(_ASM_IRQFLAGS_H) */
diff --git a/include/asm-sparc/irqflags_64.h b/include/asm-sparc/irqflags_64.h
new file mode 100644
index 0000000..024fc54
--- /dev/null
+++ b/include/asm-sparc/irqflags_64.h
@@ -0,0 +1,89 @@
+/*
+ * include/asm-sparc64/irqflags.h
+ *
+ * IRQ flags handling
+ *
+ * This file gets included from lowlevel asm headers too, to provide
+ * wrapped versions of the local_irq_*() APIs, based on the
+ * raw_local_irq_*() functions from the lowlevel headers.
+ */
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+#ifndef __ASSEMBLY__
+
+static inline unsigned long __raw_local_save_flags(void)
+{
+	unsigned long flags;
+
+	__asm__ __volatile__(
+		"rdpr	%%pil, %0"
+		: "=r" (flags)
+	);
+
+	return flags;
+}
+
+#define raw_local_save_flags(flags) \
+		do { (flags) = __raw_local_save_flags(); } while (0)
+
+static inline void raw_local_irq_restore(unsigned long flags)
+{
+	__asm__ __volatile__(
+		"wrpr	%0, %%pil"
+		: /* no output */
+		: "r" (flags)
+		: "memory"
+	);
+}
+
+static inline void raw_local_irq_disable(void)
+{
+	__asm__ __volatile__(
+		"wrpr	15, %%pil"
+		: /* no outputs */
+		: /* no inputs */
+		: "memory"
+	);
+}
+
+static inline void raw_local_irq_enable(void)
+{
+	__asm__ __volatile__(
+		"wrpr	0, %%pil"
+		: /* no outputs */
+		: /* no inputs */
+		: "memory"
+	);
+}
+
+static inline int raw_irqs_disabled_flags(unsigned long flags)
+{
+	return (flags > 0);
+}
+
+static inline int raw_irqs_disabled(void)
+{
+	unsigned long flags = __raw_local_save_flags();
+
+	return raw_irqs_disabled_flags(flags);
+}
+
+/*
+ * For spinlocks, etc:
+ */
+static inline unsigned long __raw_local_irq_save(void)
+{
+	unsigned long flags = __raw_local_save_flags();
+
+	raw_local_irq_disable();
+
+	return flags;
+}
+
+#define raw_local_irq_save(flags) \
+		do { (flags) = __raw_local_irq_save(); } while (0)
+
+#endif /* (__ASSEMBLY__) */
+
+#endif /* !(_ASM_IRQFLAGS_H) */
diff --git a/include/asm-sparc/kdebug.h b/include/asm-sparc/kdebug.h
index f69fe7d..fe07d00 100644
--- a/include/asm-sparc/kdebug.h
+++ b/include/asm-sparc/kdebug.h
@@ -1,73 +1,8 @@
-/*
- * kdebug.h:  Defines and definitions for debugging the Linux kernel
- *            under various kernel debuggers.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-#ifndef _SPARC_KDEBUG_H
-#define _SPARC_KDEBUG_H
-
-#include <asm/openprom.h>
-#include <asm/vaddrs.h>
-
-/* Breakpoints are enter through trap table entry 126.  So in sparc assembly
- * if you want to drop into the debugger you do:
- *
- * t DEBUG_BP_TRAP
- */
-
-#define DEBUG_BP_TRAP     126
-
-#ifndef __ASSEMBLY__
-/* The debug vector is passed in %o1 at boot time.  It is a pointer to
- * a structure in the debuggers address space.  Here is its format.
- */
-
-typedef unsigned int (*debugger_funct)(void);
-
-struct kernel_debug {
-	/* First the entry point into the debugger.  You jump here
-	 * to give control over to the debugger.
-	 */
-	unsigned long kdebug_entry;
-	unsigned long kdebug_trapme;   /* Figure out later... */
-	/* The following is the number of pages that the debugger has
-	 * taken from to total pool.
-	 */
-	unsigned long *kdebug_stolen_pages;
-	/* Ok, after you remap yourself and/or change the trap table
-	 * from what you were left with at boot time you have to call
-	 * this synchronization function so the debugger can check out
-	 * what you have done.
-	 */
-	debugger_funct teach_debugger;
-}; /* I think that is it... */
-
-extern struct kernel_debug *linux_dbvec;
-
-/* Use this macro in C-code to enter the debugger. */
-static inline void sp_enter_debugger(void)
-{
-	__asm__ __volatile__("jmpl %0, %%o7\n\t"
-			     "nop\n\t" : :
-			     "r" (linux_dbvec) : "o7", "memory");
-}
-
-#define SP_ENTER_DEBUGGER do { \
-	     if((linux_dbvec!=0) && ((*(short *)linux_dbvec)!=-1)) \
-	       sp_enter_debugger(); \
-		       } while(0)
-
-enum die_val {
-	DIE_UNUSED,
-};
-
-#endif /* !(__ASSEMBLY__) */
-
-/* Some nice offset defines for assembler code. */
-#define KDEBUG_ENTRY_OFF    0x0
-#define KDEBUG_DUNNO_OFF    0x4
-#define KDEBUG_DUNNO2_OFF   0x8
-#define KDEBUG_TEACH_OFF    0xc
-
-#endif /* !(_SPARC_KDEBUG_H) */
+#ifndef ___ASM_SPARC_KDEBUG_H
+#define ___ASM_SPARC_KDEBUG_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/kdebug_64.h>
+#else
+#include <asm-sparc/kdebug_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/kdebug_32.h b/include/asm-sparc/kdebug_32.h
new file mode 100644
index 0000000..f69fe7d
--- /dev/null
+++ b/include/asm-sparc/kdebug_32.h
@@ -0,0 +1,73 @@
+/*
+ * kdebug.h:  Defines and definitions for debugging the Linux kernel
+ *            under various kernel debuggers.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+#ifndef _SPARC_KDEBUG_H
+#define _SPARC_KDEBUG_H
+
+#include <asm/openprom.h>
+#include <asm/vaddrs.h>
+
+/* Breakpoints are enter through trap table entry 126.  So in sparc assembly
+ * if you want to drop into the debugger you do:
+ *
+ * t DEBUG_BP_TRAP
+ */
+
+#define DEBUG_BP_TRAP     126
+
+#ifndef __ASSEMBLY__
+/* The debug vector is passed in %o1 at boot time.  It is a pointer to
+ * a structure in the debuggers address space.  Here is its format.
+ */
+
+typedef unsigned int (*debugger_funct)(void);
+
+struct kernel_debug {
+	/* First the entry point into the debugger.  You jump here
+	 * to give control over to the debugger.
+	 */
+	unsigned long kdebug_entry;
+	unsigned long kdebug_trapme;   /* Figure out later... */
+	/* The following is the number of pages that the debugger has
+	 * taken from to total pool.
+	 */
+	unsigned long *kdebug_stolen_pages;
+	/* Ok, after you remap yourself and/or change the trap table
+	 * from what you were left with at boot time you have to call
+	 * this synchronization function so the debugger can check out
+	 * what you have done.
+	 */
+	debugger_funct teach_debugger;
+}; /* I think that is it... */
+
+extern struct kernel_debug *linux_dbvec;
+
+/* Use this macro in C-code to enter the debugger. */
+static inline void sp_enter_debugger(void)
+{
+	__asm__ __volatile__("jmpl %0, %%o7\n\t"
+			     "nop\n\t" : :
+			     "r" (linux_dbvec) : "o7", "memory");
+}
+
+#define SP_ENTER_DEBUGGER do { \
+	     if((linux_dbvec!=0) && ((*(short *)linux_dbvec)!=-1)) \
+	       sp_enter_debugger(); \
+		       } while(0)
+
+enum die_val {
+	DIE_UNUSED,
+};
+
+#endif /* !(__ASSEMBLY__) */
+
+/* Some nice offset defines for assembler code. */
+#define KDEBUG_ENTRY_OFF    0x0
+#define KDEBUG_DUNNO_OFF    0x4
+#define KDEBUG_DUNNO2_OFF   0x8
+#define KDEBUG_TEACH_OFF    0xc
+
+#endif /* !(_SPARC_KDEBUG_H) */
diff --git a/include/asm-sparc/kdebug_64.h b/include/asm-sparc/kdebug_64.h
new file mode 100644
index 0000000..f905b77
--- /dev/null
+++ b/include/asm-sparc/kdebug_64.h
@@ -0,0 +1,19 @@
+#ifndef _SPARC64_KDEBUG_H
+#define _SPARC64_KDEBUG_H
+
+struct pt_regs;
+
+extern void bad_trap(struct pt_regs *, long);
+
+/* Grossly misnamed. */
+enum die_val {
+	DIE_OOPS = 1,
+	DIE_DEBUG,	/* ta 0x70 */
+	DIE_DEBUG_2,	/* ta 0x71 */
+	DIE_DIE,
+	DIE_TRAP,
+	DIE_TRAP_TL1,
+	DIE_CALL,
+};
+
+#endif
diff --git a/include/asm-sparc/kmap_types.h b/include/asm-sparc/kmap_types.h
index e215f71..602f5e0 100644
--- a/include/asm-sparc/kmap_types.h
+++ b/include/asm-sparc/kmap_types.h
@@ -1,6 +1,10 @@
 #ifndef _ASM_KMAP_TYPES_H
 #define _ASM_KMAP_TYPES_H
 
+/* Dummy header just to define km_type.  None of this
+ * is actually used on sparc.  -DaveM
+ */
+
 enum km_type {
 	KM_BOUNCE_READ,
 	KM_SKB_SUNRPC_DATA,
diff --git a/include/asm-sparc/kprobes.h b/include/asm-sparc/kprobes.h
new file mode 100644
index 0000000..5879d71
--- /dev/null
+++ b/include/asm-sparc/kprobes.h
@@ -0,0 +1,49 @@
+#ifndef _SPARC64_KPROBES_H
+#define _SPARC64_KPROBES_H
+
+#include <linux/types.h>
+#include <linux/percpu.h>
+
+typedef u32 kprobe_opcode_t;
+
+#define BREAKPOINT_INSTRUCTION   0x91d02070 /* ta 0x70 */
+#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
+#define MAX_INSN_SIZE 2
+
+#define kretprobe_blacklist_size 0
+
+#define arch_remove_kprobe(p)	do {} while (0)
+
+#define flush_insn_slot(p)		\
+do { 	flushi(&(p)->ainsn.insn[0]);	\
+	flushi(&(p)->ainsn.insn[1]);	\
+} while (0)
+
+void kretprobe_trampoline(void);
+
+/* Architecture specific copy of original instruction*/
+struct arch_specific_insn {
+	/* copy of the original instruction */
+	kprobe_opcode_t insn[MAX_INSN_SIZE];
+};
+
+struct prev_kprobe {
+	struct kprobe *kp;
+	unsigned long status;
+	unsigned long orig_tnpc;
+	unsigned long orig_tstate_pil;
+};
+
+/* per-cpu kprobe control block */
+struct kprobe_ctlblk {
+	unsigned long kprobe_status;
+	unsigned long kprobe_orig_tnpc;
+	unsigned long kprobe_orig_tstate_pil;
+	struct pt_regs jprobe_saved_regs;
+	struct prev_kprobe prev_kprobe;
+};
+
+extern int kprobe_exceptions_notify(struct notifier_block *self,
+				    unsigned long val, void *data);
+extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
+#endif /* _SPARC64_KPROBES_H */
diff --git a/include/asm-sparc/ldc.h b/include/asm-sparc/ldc.h
new file mode 100644
index 0000000..bdb524a
--- /dev/null
+++ b/include/asm-sparc/ldc.h
@@ -0,0 +1,138 @@
+#ifndef _SPARC64_LDC_H
+#define _SPARC64_LDC_H
+
+#include <asm/hypervisor.h>
+
+extern int ldom_domaining_enabled;
+extern void ldom_set_var(const char *var, const char *value);
+extern void ldom_reboot(const char *boot_command);
+extern void ldom_power_off(void);
+
+/* The event handler will be evoked when link state changes
+ * or data becomes available on the receive side.
+ *
+ * For non-RAW links, if the LDC_EVENT_RESET event arrives the
+ * driver should reset all of it's internal state and reinvoke
+ * ldc_connect() to try and bring the link up again.
+ *
+ * For RAW links, ldc_connect() is not used.  Instead the driver
+ * just waits for the LDC_EVENT_UP event.
+ */
+struct ldc_channel_config {
+	void (*event)(void *arg, int event);
+
+	u32			mtu;
+	unsigned int		rx_irq;
+	unsigned int		tx_irq;
+	u8			mode;
+#define LDC_MODE_RAW		0x00
+#define LDC_MODE_UNRELIABLE	0x01
+#define LDC_MODE_RESERVED	0x02
+#define LDC_MODE_STREAM		0x03
+
+	u8			debug;
+#define LDC_DEBUG_HS		0x01
+#define LDC_DEBUG_STATE		0x02
+#define LDC_DEBUG_RX		0x04
+#define LDC_DEBUG_TX		0x08
+#define LDC_DEBUG_DATA		0x10
+};
+
+#define LDC_EVENT_RESET		0x01
+#define LDC_EVENT_UP		0x02
+#define LDC_EVENT_DATA_READY	0x04
+
+#define LDC_STATE_INVALID	0x00
+#define LDC_STATE_INIT		0x01
+#define LDC_STATE_BOUND		0x02
+#define LDC_STATE_READY		0x03
+#define LDC_STATE_CONNECTED	0x04
+
+struct ldc_channel;
+
+/* Allocate state for a channel.  */
+extern struct ldc_channel *ldc_alloc(unsigned long id,
+				     const struct ldc_channel_config *cfgp,
+				     void *event_arg);
+
+/* Shut down and free state for a channel.  */
+extern void ldc_free(struct ldc_channel *lp);
+
+/* Register TX and RX queues of the link with the hypervisor.  */
+extern int ldc_bind(struct ldc_channel *lp, const char *name);
+
+/* For non-RAW protocols we need to complete a handshake before
+ * communication can proceed.  ldc_connect() does that, if the
+ * handshake completes successfully, an LDC_EVENT_UP event will
+ * be sent up to the driver.
+ */
+extern int ldc_connect(struct ldc_channel *lp);
+extern int ldc_disconnect(struct ldc_channel *lp);
+
+extern int ldc_state(struct ldc_channel *lp);
+
+/* Read and write operations.  Only valid when the link is up.  */
+extern int ldc_write(struct ldc_channel *lp, const void *buf,
+		     unsigned int size);
+extern int ldc_read(struct ldc_channel *lp, void *buf, unsigned int size);
+
+#define LDC_MAP_SHADOW	0x01
+#define LDC_MAP_DIRECT	0x02
+#define LDC_MAP_IO	0x04
+#define LDC_MAP_R	0x08
+#define LDC_MAP_W	0x10
+#define LDC_MAP_X	0x20
+#define LDC_MAP_RW	(LDC_MAP_R | LDC_MAP_W)
+#define LDC_MAP_RWX	(LDC_MAP_R | LDC_MAP_W | LDC_MAP_X)
+#define LDC_MAP_ALL	0x03f
+
+struct ldc_trans_cookie {
+	u64			cookie_addr;
+	u64			cookie_size;
+};
+
+struct scatterlist;
+extern int ldc_map_sg(struct ldc_channel *lp,
+		      struct scatterlist *sg, int num_sg,
+		      struct ldc_trans_cookie *cookies, int ncookies,
+		      unsigned int map_perm);
+
+extern int ldc_map_single(struct ldc_channel *lp,
+			  void *buf, unsigned int len,
+			  struct ldc_trans_cookie *cookies, int ncookies,
+			  unsigned int map_perm);
+
+extern void ldc_unmap(struct ldc_channel *lp, struct ldc_trans_cookie *cookies,
+		      int ncookies);
+
+extern int ldc_copy(struct ldc_channel *lp, int copy_dir,
+		    void *buf, unsigned int len, unsigned long offset,
+		    struct ldc_trans_cookie *cookies, int ncookies);
+
+static inline int ldc_get_dring_entry(struct ldc_channel *lp,
+				      void *buf, unsigned int len,
+				      unsigned long offset,
+				      struct ldc_trans_cookie *cookies,
+				      int ncookies)
+{
+	return ldc_copy(lp, LDC_COPY_IN, buf, len, offset, cookies, ncookies);
+}
+
+static inline int ldc_put_dring_entry(struct ldc_channel *lp,
+				      void *buf, unsigned int len,
+				      unsigned long offset,
+				      struct ldc_trans_cookie *cookies,
+				      int ncookies)
+{
+	return ldc_copy(lp, LDC_COPY_OUT, buf, len, offset, cookies, ncookies);
+}
+
+extern void *ldc_alloc_exp_dring(struct ldc_channel *lp, unsigned int len,
+				 struct ldc_trans_cookie *cookies,
+				 int *ncookies, unsigned int map_perm);
+
+extern void ldc_free_exp_dring(struct ldc_channel *lp, void *buf,
+			       unsigned int len,
+			       struct ldc_trans_cookie *cookies, int ncookies);
+
+#endif /* _SPARC64_LDC_H */
diff --git a/include/asm-sparc/lmb.h b/include/asm-sparc/lmb.h
new file mode 100644
index 0000000..6a352cb
--- /dev/null
+++ b/include/asm-sparc/lmb.h
@@ -0,0 +1,10 @@
+#ifndef _SPARC64_LMB_H
+#define _SPARC64_LMB_H
+
+#include <asm/oplib.h>
+
+#define LMB_DBG(fmt...) prom_printf(fmt)
+
+#define LMB_REAL_LIMIT	0
+
+#endif /* !(_SPARC64_LMB_H) */
diff --git a/include/asm-sparc/lsu.h b/include/asm-sparc/lsu.h
new file mode 100644
index 0000000..7190f8d
--- /dev/null
+++ b/include/asm-sparc/lsu.h
@@ -0,0 +1,19 @@
+#ifndef _SPARC64_LSU_H
+#define _SPARC64_LSU_H
+
+#include <linux/const.h>
+
+/* LSU Control Register */
+#define LSU_CONTROL_PM _AC(0x000001fe00000000,UL) /* Phys-watchpoint byte mask*/
+#define LSU_CONTROL_VM _AC(0x00000001fe000000,UL) /* Virt-watchpoint byte mask*/
+#define LSU_CONTROL_PR _AC(0x0000000001000000,UL) /* Phys-rd watchpoint enable*/
+#define LSU_CONTROL_PW _AC(0x0000000000800000,UL) /* Phys-wr watchpoint enable*/
+#define LSU_CONTROL_VR _AC(0x0000000000400000,UL) /* Virt-rd watchpoint enable*/
+#define LSU_CONTROL_VW _AC(0x0000000000200000,UL) /* Virt-wr watchpoint enable*/
+#define LSU_CONTROL_FM _AC(0x00000000000ffff0,UL) /* Parity mask enables.     */
+#define LSU_CONTROL_DM _AC(0x0000000000000008,UL) /* Data MMU enable.         */
+#define LSU_CONTROL_IM _AC(0x0000000000000004,UL) /* Instruction MMU enable.  */
+#define LSU_CONTROL_DC _AC(0x0000000000000002,UL) /* Data cache enable.       */
+#define LSU_CONTROL_IC _AC(0x0000000000000001,UL) /* Instruction cache enable.*/
+
+#endif /* !(_SPARC64_LSU_H) */
diff --git a/include/asm-sparc/machines.h b/include/asm-sparc/machines.h
index d6c6bf8..c28c2f2 100644
--- a/include/asm-sparc/machines.h
+++ b/include/asm-sparc/machines.h
@@ -17,8 +17,6 @@
  */
 #define NUM_SUN_MACHINES   15
 
-extern struct Sun_Machine_Models Sun_Machines[NUM_SUN_MACHINES];
-
 /* The machine type in the idprom area looks like this:
  *
  * ---------------
diff --git a/include/asm-sparc/mbus.h b/include/asm-sparc/mbus.h
index bb5ae61..69f07a0 100644
--- a/include/asm-sparc/mbus.h
+++ b/include/asm-sparc/mbus.h
@@ -43,8 +43,6 @@
 #define HWBUG_SUPERSCALAR_BAD        0x00000080
 #define HWBUG_PACINIT_BITROT         0x00000100
 
-extern unsigned int hwbug_bitmask;
-
 /* First the module type values. To find out which you have, just load
  * the mmu control register from ASI_M_MMUREG alternate address space and
  * shift the value right 28 bits.
diff --git a/include/asm-sparc/mc146818rtc.h b/include/asm-sparc/mc146818rtc.h
index fa7eac9..9ab65c2 100644
--- a/include/asm-sparc/mc146818rtc.h
+++ b/include/asm-sparc/mc146818rtc.h
@@ -1,29 +1,8 @@
-/*
- * Machine dependent access functions for RTC registers.
- */
-#ifndef __ASM_SPARC_MC146818RTC_H
-#define __ASM_SPARC_MC146818RTC_H
-
-#include <asm/io.h>
-
-#ifndef RTC_PORT
-#define RTC_PORT(x)	(0x70 + (x))
-#define RTC_ALWAYS_BCD	1	/* RTC operates in binary mode */
+#ifndef ___ASM_SPARC_MC146818RTC_H
+#define ___ASM_SPARC_MC146818RTC_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/mc146818rtc_64.h>
+#else
+#include <asm-sparc/mc146818rtc_32.h>
 #endif
-
-/*
- * The yet supported machines all access the RTC index register via
- * an ISA port access but the way to access the date register differs ...
- */
-#define CMOS_READ(addr) ({ \
-outb_p((addr),RTC_PORT(0)); \
-inb_p(RTC_PORT(1)); \
-})
-#define CMOS_WRITE(val, addr) ({ \
-outb_p((addr),RTC_PORT(0)); \
-outb_p((val),RTC_PORT(1)); \
-})
-
-#define RTC_IRQ 8
-
-#endif /* __ASM_SPARC_MC146818RTC_H */
+#endif
diff --git a/include/asm-sparc/mc146818rtc_32.h b/include/asm-sparc/mc146818rtc_32.h
new file mode 100644
index 0000000..fa7eac9
--- /dev/null
+++ b/include/asm-sparc/mc146818rtc_32.h
@@ -0,0 +1,29 @@
+/*
+ * Machine dependent access functions for RTC registers.
+ */
+#ifndef __ASM_SPARC_MC146818RTC_H
+#define __ASM_SPARC_MC146818RTC_H
+
+#include <asm/io.h>
+
+#ifndef RTC_PORT
+#define RTC_PORT(x)	(0x70 + (x))
+#define RTC_ALWAYS_BCD	1	/* RTC operates in binary mode */
+#endif
+
+/*
+ * The yet supported machines all access the RTC index register via
+ * an ISA port access but the way to access the date register differs ...
+ */
+#define CMOS_READ(addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+inb_p(RTC_PORT(1)); \
+})
+#define CMOS_WRITE(val, addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+outb_p((val),RTC_PORT(1)); \
+})
+
+#define RTC_IRQ 8
+
+#endif /* __ASM_SPARC_MC146818RTC_H */
diff --git a/include/asm-sparc/mc146818rtc_64.h b/include/asm-sparc/mc146818rtc_64.h
new file mode 100644
index 0000000..e9c0fcc
--- /dev/null
+++ b/include/asm-sparc/mc146818rtc_64.h
@@ -0,0 +1,34 @@
+/*
+ * Machine dependent access functions for RTC registers.
+ */
+#ifndef __ASM_SPARC64_MC146818RTC_H
+#define __ASM_SPARC64_MC146818RTC_H
+
+#include <asm/io.h>
+
+#ifndef RTC_PORT
+#ifdef CONFIG_PCI
+extern unsigned long ds1287_regs;
+#else
+#define ds1287_regs (0UL)
+#endif
+#define RTC_PORT(x)	(ds1287_regs + (x))
+#define RTC_ALWAYS_BCD	0
+#endif
+
+/*
+ * The yet supported machines all access the RTC index register via
+ * an ISA port access but the way to access the date register differs ...
+ */
+#define CMOS_READ(addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+inb_p(RTC_PORT(1)); \
+})
+#define CMOS_WRITE(val, addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+outb_p((val),RTC_PORT(1)); \
+})
+
+#define RTC_IRQ 8
+
+#endif /* __ASM_SPARC64_MC146818RTC_H */
diff --git a/include/asm-sparc/mdesc.h b/include/asm-sparc/mdesc.h
new file mode 100644
index 0000000..1acc727
--- /dev/null
+++ b/include/asm-sparc/mdesc.h
@@ -0,0 +1,78 @@
+#ifndef _SPARC64_MDESC_H
+#define _SPARC64_MDESC_H
+
+#include <linux/types.h>
+#include <linux/cpumask.h>
+#include <asm/prom.h>
+
+struct mdesc_handle;
+
+/* Machine description operations are to be surrounded by grab and
+ * release calls.  The mdesc_handle returned from the grab is
+ * the first argument to all of the operational calls that work
+ * on mdescs.
+ */
+extern struct mdesc_handle *mdesc_grab(void);
+extern void mdesc_release(struct mdesc_handle *);
+
+#define MDESC_NODE_NULL		(~(u64)0)
+
+extern u64 mdesc_node_by_name(struct mdesc_handle *handle,
+			      u64 from_node, const char *name);
+#define mdesc_for_each_node_by_name(__hdl, __node, __name) \
+	for (__node = mdesc_node_by_name(__hdl, MDESC_NODE_NULL, __name); \
+	     (__node) != MDESC_NODE_NULL; \
+	     __node = mdesc_node_by_name(__hdl, __node, __name))
+
+/* Access to property values returned from mdesc_get_property() are
+ * only valid inside of a mdesc_grab()/mdesc_release() sequence.
+ * Once mdesc_release() is called, the memory backed up by these
+ * pointers may reference freed up memory.
+ *
+ * Therefore callers must make copies of any property values
+ * they need.
+ *
+ * These same rules apply to mdesc_node_name().
+ */
+extern const void *mdesc_get_property(struct mdesc_handle *handle,
+				      u64 node, const char *name, int *lenp);
+extern const char *mdesc_node_name(struct mdesc_handle *hp, u64 node);
+
+/* MD arc iteration, the standard sequence is:
+ *
+ *	unsigned long arc;
+ *	mdesc_for_each_arc(arc, handle, node, MDESC_ARC_TYPE_{FWD,BACK}) {
+ *		unsigned long target = mdesc_arc_target(handle, arc);
+ *		...
+ *	}
+ */
+
+#define MDESC_ARC_TYPE_FWD	"fwd"
+#define MDESC_ARC_TYPE_BACK	"back"
+
+extern u64 mdesc_next_arc(struct mdesc_handle *handle, u64 from,
+			  const char *arc_type);
+#define mdesc_for_each_arc(__arc, __hdl, __node, __type) \
+	for (__arc = mdesc_next_arc(__hdl, __node, __type); \
+	     (__arc) != MDESC_NODE_NULL; \
+	     __arc = mdesc_next_arc(__hdl, __arc, __type))
+
+extern u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc);
+
+extern void mdesc_update(void);
+
+struct mdesc_notifier_client {
+	void (*add)(struct mdesc_handle *handle, u64 node);
+	void (*remove)(struct mdesc_handle *handle, u64 node);
+
+	const char			*node_name;
+	struct mdesc_notifier_client	*next;
+};
+
+extern void mdesc_register_notifier(struct mdesc_notifier_client *client);
+
+extern void mdesc_fill_in_cpu_data(cpumask_t mask);
+
+extern void sun4v_mdesc_init(void);
+
+#endif
diff --git a/include/asm-sparc/mmu.h b/include/asm-sparc/mmu.h
index ccd36d2..ee66bf6 100644
--- a/include/asm-sparc/mmu.h
+++ b/include/asm-sparc/mmu.h
@@ -1,7 +1,8 @@
-#ifndef __MMU_H
-#define __MMU_H
-
-/* Default "unsigned long" context */
-typedef unsigned long mm_context_t;
-
+#ifndef ___ASM_SPARC_MMU_H
+#define ___ASM_SPARC_MMU_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/mmu_64.h>
+#else
+#include <asm-sparc/mmu_32.h>
+#endif
 #endif
diff --git a/include/asm-sparc/mmu_32.h b/include/asm-sparc/mmu_32.h
new file mode 100644
index 0000000..ccd36d2
--- /dev/null
+++ b/include/asm-sparc/mmu_32.h
@@ -0,0 +1,7 @@
+#ifndef __MMU_H
+#define __MMU_H
+
+/* Default "unsigned long" context */
+typedef unsigned long mm_context_t;
+
+#endif
diff --git a/include/asm-sparc/mmu_64.h b/include/asm-sparc/mmu_64.h
new file mode 100644
index 0000000..9067dc5
--- /dev/null
+++ b/include/asm-sparc/mmu_64.h
@@ -0,0 +1,123 @@
+#ifndef __MMU_H
+#define __MMU_H
+
+#include <linux/const.h>
+#include <asm/page.h>
+#include <asm/hypervisor.h>
+
+#define CTX_NR_BITS		13
+
+#define TAG_CONTEXT_BITS	((_AC(1,UL) << CTX_NR_BITS) - _AC(1,UL))
+
+/* UltraSPARC-III+ and later have a feature whereby you can
+ * select what page size the various Data-TLB instances in the
+ * chip.  In order to gracefully support this, we put the version
+ * field in a spot outside of the areas of the context register
+ * where this parameter is specified.
+ */
+#define CTX_VERSION_SHIFT	22
+#define CTX_VERSION_MASK	((~0UL) << CTX_VERSION_SHIFT)
+
+#define CTX_PGSZ_8KB		_AC(0x0,UL)
+#define CTX_PGSZ_64KB		_AC(0x1,UL)
+#define CTX_PGSZ_512KB		_AC(0x2,UL)
+#define CTX_PGSZ_4MB		_AC(0x3,UL)
+#define CTX_PGSZ_BITS		_AC(0x7,UL)
+#define CTX_PGSZ0_NUC_SHIFT	61
+#define CTX_PGSZ1_NUC_SHIFT	58
+#define CTX_PGSZ0_SHIFT		16
+#define CTX_PGSZ1_SHIFT		19
+#define CTX_PGSZ_MASK		((CTX_PGSZ_BITS << CTX_PGSZ0_SHIFT) | \
+				 (CTX_PGSZ_BITS << CTX_PGSZ1_SHIFT))
+
+#if defined(CONFIG_SPARC64_PAGE_SIZE_8KB)
+#define CTX_PGSZ_BASE	CTX_PGSZ_8KB
+#elif defined(CONFIG_SPARC64_PAGE_SIZE_64KB)
+#define CTX_PGSZ_BASE	CTX_PGSZ_64KB
+#else
+#error No page size specified in kernel configuration
+#endif
+
+#if defined(CONFIG_HUGETLB_PAGE_SIZE_4MB)
+#define CTX_PGSZ_HUGE		CTX_PGSZ_4MB
+#elif defined(CONFIG_HUGETLB_PAGE_SIZE_512K)
+#define CTX_PGSZ_HUGE		CTX_PGSZ_512KB
+#elif defined(CONFIG_HUGETLB_PAGE_SIZE_64K)
+#define CTX_PGSZ_HUGE		CTX_PGSZ_64KB
+#endif
+
+#define CTX_PGSZ_KERN	CTX_PGSZ_4MB
+
+/* Thus, when running on UltraSPARC-III+ and later, we use the following
+ * PRIMARY_CONTEXT register values for the kernel context.
+ */
+#define CTX_CHEETAH_PLUS_NUC \
+	((CTX_PGSZ_KERN << CTX_PGSZ0_NUC_SHIFT) | \
+	 (CTX_PGSZ_BASE << CTX_PGSZ1_NUC_SHIFT))
+
+#define CTX_CHEETAH_PLUS_CTX0 \
+	((CTX_PGSZ_KERN << CTX_PGSZ0_SHIFT) | \
+	 (CTX_PGSZ_BASE << CTX_PGSZ1_SHIFT))
+
+/* If you want "the TLB context number" use CTX_NR_MASK.  If you
+ * want "the bits I program into the context registers" use
+ * CTX_HW_MASK.
+ */
+#define CTX_NR_MASK		TAG_CONTEXT_BITS
+#define CTX_HW_MASK		(CTX_NR_MASK | CTX_PGSZ_MASK)
+
+#define CTX_FIRST_VERSION	((_AC(1,UL) << CTX_VERSION_SHIFT) + _AC(1,UL))
+#define CTX_VALID(__ctx)	\
+	 (!(((__ctx.sparc64_ctx_val) ^ tlb_context_cache) & CTX_VERSION_MASK))
+#define CTX_HWBITS(__ctx)	((__ctx.sparc64_ctx_val) & CTX_HW_MASK)
+#define CTX_NRBITS(__ctx)	((__ctx.sparc64_ctx_val) & CTX_NR_MASK)
+
+#ifndef __ASSEMBLY__
+
+#define TSB_ENTRY_ALIGNMENT	16
+
+struct tsb {
+	unsigned long tag;
+	unsigned long pte;
+} __attribute__((aligned(TSB_ENTRY_ALIGNMENT)));
+
+extern void __tsb_insert(unsigned long ent, unsigned long tag, unsigned long pte);
+extern void tsb_flush(unsigned long ent, unsigned long tag);
+extern void tsb_init(struct tsb *tsb, unsigned long size);
+
+struct tsb_config {
+	struct tsb		*tsb;
+	unsigned long		tsb_rss_limit;
+	unsigned long		tsb_nentries;
+	unsigned long		tsb_reg_val;
+	unsigned long		tsb_map_vaddr;
+	unsigned long		tsb_map_pte;
+};
+
+#define MM_TSB_BASE	0
+
+#ifdef CONFIG_HUGETLB_PAGE
+#define MM_TSB_HUGE	1
+#define MM_NUM_TSBS	2
+#else
+#define MM_NUM_TSBS	1
+#endif
+
+typedef struct {
+	spinlock_t		lock;
+	unsigned long		sparc64_ctx_val;
+	unsigned long		huge_pte_count;
+	struct tsb_config	tsb_block[MM_NUM_TSBS];
+	struct hv_tsb_descr	tsb_descr[MM_NUM_TSBS];
+} mm_context_t;
+
+#endif /* !__ASSEMBLY__ */
+
+#define TSB_CONFIG_TSB		0x00
+#define TSB_CONFIG_RSS_LIMIT	0x08
+#define TSB_CONFIG_NENTRIES	0x10
+#define TSB_CONFIG_REG_VAL	0x18
+#define TSB_CONFIG_MAP_VADDR	0x20
+#define TSB_CONFIG_MAP_PTE	0x28
+
+#endif /* __MMU_H */
diff --git a/include/asm-sparc/mmu_context.h b/include/asm-sparc/mmu_context.h
index 671a997b..e14efb9 100644
--- a/include/asm-sparc/mmu_context.h
+++ b/include/asm-sparc/mmu_context.h
@@ -1,42 +1,8 @@
-#ifndef __SPARC_MMU_CONTEXT_H
-#define __SPARC_MMU_CONTEXT_H
-
-#include <asm/btfixup.h>
-
-#ifndef __ASSEMBLY__
-
-#include <asm-generic/mm_hooks.h>
-
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
-{
-}
-
-/*
- * Initialize a new mmu context.  This is invoked when a new
- * address space instance (unique or shared) is instantiated.
- */
-#define init_new_context(tsk, mm) (((mm)->context = NO_CONTEXT), 0)
-
-/*
- * Destroy a dead context.  This occurs when mmput drops the
- * mm_users count to zero, the mmaps have been released, and
- * all the page tables have been flushed.  Our job is to destroy
- * any remaining processor-specific state.
- */
-BTFIXUPDEF_CALL(void, destroy_context, struct mm_struct *)
-
-#define destroy_context(mm) BTFIXUP_CALL(destroy_context)(mm)
-
-/* Switch the current MM context. */
-BTFIXUPDEF_CALL(void, switch_mm, struct mm_struct *, struct mm_struct *, struct task_struct *)
-
-#define switch_mm(old_mm, mm, tsk) BTFIXUP_CALL(switch_mm)(old_mm, mm, tsk)
-
-#define deactivate_mm(tsk,mm)	do { } while (0)
-
-/* Activate a new MM instance for the current task. */
-#define activate_mm(active_mm, mm) switch_mm((active_mm), (mm), NULL)
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(__SPARC_MMU_CONTEXT_H) */
+#ifndef ___ASM_SPARC_MMU_CONTEXT_H
+#define ___ASM_SPARC_MMU_CONTEXT_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/mmu_context_64.h>
+#else
+#include <asm-sparc/mmu_context_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/mmu_context_32.h b/include/asm-sparc/mmu_context_32.h
new file mode 100644
index 0000000..671a997b
--- /dev/null
+++ b/include/asm-sparc/mmu_context_32.h
@@ -0,0 +1,42 @@
+#ifndef __SPARC_MMU_CONTEXT_H
+#define __SPARC_MMU_CONTEXT_H
+
+#include <asm/btfixup.h>
+
+#ifndef __ASSEMBLY__
+
+#include <asm-generic/mm_hooks.h>
+
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+{
+}
+
+/*
+ * Initialize a new mmu context.  This is invoked when a new
+ * address space instance (unique or shared) is instantiated.
+ */
+#define init_new_context(tsk, mm) (((mm)->context = NO_CONTEXT), 0)
+
+/*
+ * Destroy a dead context.  This occurs when mmput drops the
+ * mm_users count to zero, the mmaps have been released, and
+ * all the page tables have been flushed.  Our job is to destroy
+ * any remaining processor-specific state.
+ */
+BTFIXUPDEF_CALL(void, destroy_context, struct mm_struct *)
+
+#define destroy_context(mm) BTFIXUP_CALL(destroy_context)(mm)
+
+/* Switch the current MM context. */
+BTFIXUPDEF_CALL(void, switch_mm, struct mm_struct *, struct mm_struct *, struct task_struct *)
+
+#define switch_mm(old_mm, mm, tsk) BTFIXUP_CALL(switch_mm)(old_mm, mm, tsk)
+
+#define deactivate_mm(tsk,mm)	do { } while (0)
+
+/* Activate a new MM instance for the current task. */
+#define activate_mm(active_mm, mm) switch_mm((active_mm), (mm), NULL)
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__SPARC_MMU_CONTEXT_H) */
diff --git a/include/asm-sparc/mmu_context_64.h b/include/asm-sparc/mmu_context_64.h
new file mode 100644
index 0000000..5693ab4
--- /dev/null
+++ b/include/asm-sparc/mmu_context_64.h
@@ -0,0 +1,155 @@
+#ifndef __SPARC64_MMU_CONTEXT_H
+#define __SPARC64_MMU_CONTEXT_H
+
+/* Derived heavily from Linus's Alpha/AXP ASN code... */
+
+#ifndef __ASSEMBLY__
+
+#include <linux/spinlock.h>
+#include <asm/system.h>
+#include <asm/spitfire.h>
+#include <asm-generic/mm_hooks.h>
+
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+{
+}
+
+extern spinlock_t ctx_alloc_lock;
+extern unsigned long tlb_context_cache;
+extern unsigned long mmu_context_bmap[];
+
+extern void get_new_mmu_context(struct mm_struct *mm);
+#ifdef CONFIG_SMP
+extern void smp_new_mmu_context_version(void);
+#else
+#define smp_new_mmu_context_version() do { } while (0)
+#endif
+
+extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
+extern void destroy_context(struct mm_struct *mm);
+
+extern void __tsb_context_switch(unsigned long pgd_pa,
+				 struct tsb_config *tsb_base,
+				 struct tsb_config *tsb_huge,
+				 unsigned long tsb_descr_pa);
+
+static inline void tsb_context_switch(struct mm_struct *mm)
+{
+	__tsb_context_switch(__pa(mm->pgd),
+			     &mm->context.tsb_block[0],
+#ifdef CONFIG_HUGETLB_PAGE
+			     (mm->context.tsb_block[1].tsb ?
+			      &mm->context.tsb_block[1] :
+			      NULL)
+#else
+			     NULL
+#endif
+			     , __pa(&mm->context.tsb_descr[0]));
+}
+
+extern void tsb_grow(struct mm_struct *mm, unsigned long tsb_index, unsigned long mm_rss);
+#ifdef CONFIG_SMP
+extern void smp_tsb_sync(struct mm_struct *mm);
+#else
+#define smp_tsb_sync(__mm) do { } while (0)
+#endif
+
+/* Set MMU context in the actual hardware. */
+#define load_secondary_context(__mm) \
+	__asm__ __volatile__( \
+	"\n661:	stxa		%0, [%1] %2\n" \
+	"	.section	.sun4v_1insn_patch, \"ax\"\n" \
+	"	.word		661b\n" \
+	"	stxa		%0, [%1] %3\n" \
+	"	.previous\n" \
+	"	flush		%%g6\n" \
+	: /* No outputs */ \
+	: "r" (CTX_HWBITS((__mm)->context)), \
+	  "r" (SECONDARY_CONTEXT), "i" (ASI_DMMU), "i" (ASI_MMU))
+
+extern void __flush_tlb_mm(unsigned long, unsigned long);
+
+/* Switch the current MM context.  Interrupts are disabled.  */
+static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, struct task_struct *tsk)
+{
+	unsigned long ctx_valid, flags;
+	int cpu;
+
+	if (unlikely(mm == &init_mm))
+		return;
+
+	spin_lock_irqsave(&mm->context.lock, flags);
+	ctx_valid = CTX_VALID(mm->context);
+	if (!ctx_valid)
+		get_new_mmu_context(mm);
+
+	/* We have to be extremely careful here or else we will miss
+	 * a TSB grow if we switch back and forth between a kernel
+	 * thread and an address space which has it's TSB size increased
+	 * on another processor.
+	 *
+	 * It is possible to play some games in order to optimize the
+	 * switch, but the safest thing to do is to unconditionally
+	 * perform the secondary context load and the TSB context switch.
+	 *
+	 * For reference the bad case is, for address space "A":
+	 *
+	 *		CPU 0			CPU 1
+	 *	run address space A
+	 *	set cpu0's bits in cpu_vm_mask
+	 *	switch to kernel thread, borrow
+	 *	address space A via entry_lazy_tlb
+	 *					run address space A
+	 *					set cpu1's bit in cpu_vm_mask
+	 *					flush_tlb_pending()
+	 *					reset cpu_vm_mask to just cpu1
+	 *					TSB grow
+	 *	run address space A
+	 *	context was valid, so skip
+	 *	TSB context switch
+	 *
+	 * At that point cpu0 continues to use a stale TSB, the one from
+	 * before the TSB grow performed on cpu1.  cpu1 did not cross-call
+	 * cpu0 to update it's TSB because at that point the cpu_vm_mask
+	 * only had cpu1 set in it.
+	 */
+	load_secondary_context(mm);
+	tsb_context_switch(mm);
+
+	/* Any time a processor runs a context on an address space
+	 * for the first time, we must flush that context out of the
+	 * local TLB.
+	 */
+	cpu = smp_processor_id();
+	if (!ctx_valid || !cpu_isset(cpu, mm->cpu_vm_mask)) {
+		cpu_set(cpu, mm->cpu_vm_mask);
+		__flush_tlb_mm(CTX_HWBITS(mm->context),
+			       SECONDARY_CONTEXT);
+	}
+	spin_unlock_irqrestore(&mm->context.lock, flags);
+}
+
+#define deactivate_mm(tsk,mm)	do { } while (0)
+
+/* Activate a new MM instance for the current task. */
+static inline void activate_mm(struct mm_struct *active_mm, struct mm_struct *mm)
+{
+	unsigned long flags;
+	int cpu;
+
+	spin_lock_irqsave(&mm->context.lock, flags);
+	if (!CTX_VALID(mm->context))
+		get_new_mmu_context(mm);
+	cpu = smp_processor_id();
+	if (!cpu_isset(cpu, mm->cpu_vm_mask))
+		cpu_set(cpu, mm->cpu_vm_mask);
+
+	load_secondary_context(mm);
+	__flush_tlb_mm(CTX_HWBITS(mm->context), SECONDARY_CONTEXT);
+	tsb_context_switch(mm);
+	spin_unlock_irqrestore(&mm->context.lock, flags);
+}
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__SPARC64_MMU_CONTEXT_H) */
diff --git a/include/asm-sparc/mmzone.h b/include/asm-sparc/mmzone.h
new file mode 100644
index 0000000..ebf5986
--- /dev/null
+++ b/include/asm-sparc/mmzone.h
@@ -0,0 +1,17 @@
+#ifndef _SPARC64_MMZONE_H
+#define _SPARC64_MMZONE_H
+
+#ifdef CONFIG_NEED_MULTIPLE_NODES
+
+extern struct pglist_data *node_data[];
+
+#define NODE_DATA(nid)		(node_data[nid])
+#define node_start_pfn(nid)	(NODE_DATA(nid)->node_start_pfn)
+#define node_end_pfn(nid)	(NODE_DATA(nid)->node_end_pfn)
+
+extern int numa_cpu_lookup_table[];
+extern cpumask_t numa_cpumask_lookup_table[];
+
+#endif /* CONFIG_NEED_MULTIPLE_NODES */
+
+#endif /* _SPARC64_MMZONE_H */
diff --git a/include/asm-sparc/module.h b/include/asm-sparc/module.h
index cbd9e67..516138f 100644
--- a/include/asm-sparc/module.h
+++ b/include/asm-sparc/module.h
@@ -1,7 +1,8 @@
-#ifndef _ASM_SPARC_MODULE_H
-#define _ASM_SPARC_MODULE_H
-struct mod_arch_specific { };
-#define Elf_Shdr Elf32_Shdr
-#define Elf_Sym Elf32_Sym
-#define Elf_Ehdr Elf32_Ehdr
-#endif /* _ASM_SPARC_MODULE_H */
+#ifndef ___ASM_SPARC_MODULE_H
+#define ___ASM_SPARC_MODULE_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/module_64.h>
+#else
+#include <asm-sparc/module_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/module_32.h b/include/asm-sparc/module_32.h
new file mode 100644
index 0000000..cbd9e67
--- /dev/null
+++ b/include/asm-sparc/module_32.h
@@ -0,0 +1,7 @@
+#ifndef _ASM_SPARC_MODULE_H
+#define _ASM_SPARC_MODULE_H
+struct mod_arch_specific { };
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Ehdr Elf32_Ehdr
+#endif /* _ASM_SPARC_MODULE_H */
diff --git a/include/asm-sparc/module_64.h b/include/asm-sparc/module_64.h
new file mode 100644
index 0000000..3d77ba4
--- /dev/null
+++ b/include/asm-sparc/module_64.h
@@ -0,0 +1,7 @@
+#ifndef _ASM_SPARC64_MODULE_H
+#define _ASM_SPARC64_MODULE_H
+struct mod_arch_specific { };
+#define Elf_Shdr Elf64_Shdr
+#define Elf_Sym Elf64_Sym
+#define Elf_Ehdr Elf64_Ehdr
+#endif /* _ASM_SPARC64_MODULE_H */
diff --git a/include/asm-sparc/mostek.h b/include/asm-sparc/mostek.h
index 29aad11..5b9f7fe 100644
--- a/include/asm-sparc/mostek.h
+++ b/include/asm-sparc/mostek.h
@@ -1,173 +1,8 @@
-/*
- * mostek.h:  Describes the various Mostek time of day clock registers.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu)
- * Added intersil code 05/25/98 Chris Davis (cdavis@cois.on.ca)
- */
-
-#ifndef _SPARC_MOSTEK_H
-#define _SPARC_MOSTEK_H
-
-#include <asm/idprom.h>
-#include <asm/io.h>
-
-/*       M48T02 Register Map (adapted from Sun NVRAM/Hostid FAQ)
- *
- *                             Data
- * Address                                                 Function
- *        Bit 7 Bit 6 Bit 5 Bit 4Bit 3 Bit 2 Bit 1 Bit 0
- *   7ff  -     -     -     -    -     -     -     -       Year 00-99
- *   7fe  0     0     0     -    -     -     -     -      Month 01-12
- *   7fd  0     0     -     -    -     -     -     -       Date 01-31
- *   7fc  0     FT    0     0    0     -     -     -        Day 01-07
- *   7fb  KS    0     -     -    -     -     -     -      Hours 00-23
- *   7fa  0     -     -     -    -     -     -     -    Minutes 00-59
- *   7f9  ST    -     -     -    -     -     -     -    Seconds 00-59
- *   7f8  W     R     S     -    -     -     -     -    Control
- *
- *   * ST is STOP BIT
- *   * W is WRITE BIT
- *   * R is READ BIT
- *   * S is SIGN BIT
- *   * FT is FREQ TEST BIT
- *   * KS is KICK START BIT
- */
-
-/* The Mostek 48t02 real time clock and NVRAM chip. The registers
- * other than the control register are in binary coded decimal. Some
- * control bits also live outside the control register.
- */
-#define mostek_read(_addr)		readb(_addr)
-#define mostek_write(_addr,_val)	writeb(_val, _addr)
-#define MOSTEK_EEPROM		0x0000UL
-#define MOSTEK_IDPROM		0x07d8UL
-#define MOSTEK_CREG		0x07f8UL
-#define MOSTEK_SEC		0x07f9UL
-#define MOSTEK_MIN		0x07faUL
-#define MOSTEK_HOUR		0x07fbUL
-#define MOSTEK_DOW		0x07fcUL
-#define MOSTEK_DOM		0x07fdUL
-#define MOSTEK_MONTH		0x07feUL
-#define MOSTEK_YEAR		0x07ffUL
-
-struct mostek48t02 {
-	volatile char eeprom[2008];	/* This is the eeprom, don't touch! */
-	struct idprom idprom;		/* The idprom lives here. */
-	volatile unsigned char creg;	/* Control register */
-	volatile unsigned char sec;	/* Seconds (0-59) */
-	volatile unsigned char min;	/* Minutes (0-59) */
-	volatile unsigned char hour;	/* Hour (0-23) */
-	volatile unsigned char dow;	/* Day of the week (1-7) */
-	volatile unsigned char dom;	/* Day of the month (1-31) */
-	volatile unsigned char month;	/* Month of year (1-12) */
-	volatile unsigned char year;	/* Year (0-99) */
-};
-
-extern spinlock_t mostek_lock;
-extern void __iomem *mstk48t02_regs;
-
-/* Control register values. */
-#define	MSTK_CREG_WRITE	0x80	/* Must set this before placing values. */
-#define	MSTK_CREG_READ	0x40	/* Stop updates to allow a clean read. */
-#define	MSTK_CREG_SIGN	0x20	/* Slow/speed clock in calibration mode. */
-
-/* Control bits that live in the other registers. */
-#define	MSTK_STOP	0x80	/* Stop the clock oscillator. (sec) */
-#define	MSTK_KICK_START	0x80	/* Kick start the clock chip. (hour) */
-#define MSTK_FREQ_TEST	0x40	/* Frequency test mode. (day) */
-
-#define MSTK_YEAR_ZERO       1968   /* If year reg has zero, it is 1968. */
-#define MSTK_CVT_YEAR(yr)  ((yr) + MSTK_YEAR_ZERO)
-
-/* Masks that define how much space each value takes up. */
-#define	MSTK_SEC_MASK	0x7f
-#define	MSTK_MIN_MASK	0x7f
-#define	MSTK_HOUR_MASK	0x3f
-#define	MSTK_DOW_MASK	0x07
-#define	MSTK_DOM_MASK	0x3f
-#define	MSTK_MONTH_MASK	0x1f
-#define	MSTK_YEAR_MASK	0xffU
-
-/* Binary coded decimal conversion macros. */
-#define MSTK_REGVAL_TO_DECIMAL(x)  (((x) & 0x0F) + 0x0A * ((x) >> 0x04))
-#define MSTK_DECIMAL_TO_REGVAL(x)  ((((x) / 0x0A) << 0x04) + ((x) % 0x0A))
-
-/* Generic register set and get macros for internal use. */
-#define MSTK_GET(regs,var,mask) (MSTK_REGVAL_TO_DECIMAL(((struct mostek48t02 *)regs)->var & MSTK_ ## mask ## _MASK))
-#define MSTK_SET(regs,var,value,mask) do { ((struct mostek48t02 *)regs)->var &= ~(MSTK_ ## mask ## _MASK); ((struct mostek48t02 *)regs)->var |= MSTK_DECIMAL_TO_REGVAL(value) & (MSTK_ ## mask ## _MASK); } while (0)
-
-/* Macros to make register access easier on our fingers. These give you
- * the decimal value of the register requested if applicable. You pass
- * the a pointer to a 'struct mostek48t02'.
- */
-#define	MSTK_REG_CREG(regs)	(((struct mostek48t02 *)regs)->creg)
-#define	MSTK_REG_SEC(regs)	MSTK_GET(regs,sec,SEC)
-#define	MSTK_REG_MIN(regs)	MSTK_GET(regs,min,MIN)
-#define	MSTK_REG_HOUR(regs)	MSTK_GET(regs,hour,HOUR)
-#define	MSTK_REG_DOW(regs)	MSTK_GET(regs,dow,DOW)
-#define	MSTK_REG_DOM(regs)	MSTK_GET(regs,dom,DOM)
-#define	MSTK_REG_MONTH(regs)	MSTK_GET(regs,month,MONTH)
-#define	MSTK_REG_YEAR(regs)	MSTK_GET(regs,year,YEAR)
-
-#define	MSTK_SET_REG_SEC(regs,value)	MSTK_SET(regs,sec,value,SEC)
-#define	MSTK_SET_REG_MIN(regs,value)	MSTK_SET(regs,min,value,MIN)
-#define	MSTK_SET_REG_HOUR(regs,value)	MSTK_SET(regs,hour,value,HOUR)
-#define	MSTK_SET_REG_DOW(regs,value)	MSTK_SET(regs,dow,value,DOW)
-#define	MSTK_SET_REG_DOM(regs,value)	MSTK_SET(regs,dom,value,DOM)
-#define	MSTK_SET_REG_MONTH(regs,value)	MSTK_SET(regs,month,value,MONTH)
-#define	MSTK_SET_REG_YEAR(regs,value)	MSTK_SET(regs,year,value,YEAR)
-
-
-/* The Mostek 48t08 clock chip. Found on Sun4m's I think. It has the
- * same (basically) layout of the 48t02 chip except for the extra
- * NVRAM on board (8 KB against the 48t02's 2 KB).
- */
-struct mostek48t08 {
-	char offset[6*1024];         /* Magic things may be here, who knows? */
-	struct mostek48t02 regs;     /* Here is what we are interested in.   */
-};
-
-extern enum sparc_clock_type sp_clock_typ;
-
-#ifdef CONFIG_SUN4
-enum sparc_clock_type {	MSTK48T02, MSTK48T08, \
-INTERSIL, MSTK_INVALID };
+#ifndef ___ASM_SPARC_MOSTEK_H
+#define ___ASM_SPARC_MOSTEK_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/mostek_64.h>
 #else
-enum sparc_clock_type {	MSTK48T02, MSTK48T08, \
-MSTK_INVALID };
+#include <asm-sparc/mostek_32.h>
 #endif
-
-#ifdef CONFIG_SUN4
-/* intersil on a sun 4/260 code  data from harris doc */
-struct intersil_dt {
-        volatile unsigned char int_csec;
-        volatile unsigned char int_hour;
-        volatile unsigned char int_min;
-        volatile unsigned char int_sec;
-        volatile unsigned char int_month;
-        volatile unsigned char int_day;
-        volatile unsigned char int_year;
-        volatile unsigned char int_dow;
-};
-
-struct intersil {
-	struct intersil_dt clk;
-	struct intersil_dt cmp;
-	volatile unsigned char int_intr_reg;
-	volatile unsigned char int_cmd_reg;
-};
-
-#define INTERSIL_STOP        0x0
-#define INTERSIL_START       0x8
-#define INTERSIL_INTR_DISABLE   0x0
-#define INTERSIL_INTR_ENABLE   0x10
-#define INTERSIL_32K		0x0
-#define INTERSIL_NORMAL		0x0
-#define INTERSIL_24H		0x4 
-#define INTERSIL_INT_100HZ	0x2
-
-/* end of intersil info */
 #endif
-
-#endif /* !(_SPARC_MOSTEK_H) */
diff --git a/include/asm-sparc/mostek_32.h b/include/asm-sparc/mostek_32.h
new file mode 100644
index 0000000..a99590c
--- /dev/null
+++ b/include/asm-sparc/mostek_32.h
@@ -0,0 +1,171 @@
+/*
+ * mostek.h:  Describes the various Mostek time of day clock registers.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu)
+ * Added intersil code 05/25/98 Chris Davis (cdavis@cois.on.ca)
+ */
+
+#ifndef _SPARC_MOSTEK_H
+#define _SPARC_MOSTEK_H
+
+#include <asm/idprom.h>
+#include <asm/io.h>
+
+/*       M48T02 Register Map (adapted from Sun NVRAM/Hostid FAQ)
+ *
+ *                             Data
+ * Address                                                 Function
+ *        Bit 7 Bit 6 Bit 5 Bit 4Bit 3 Bit 2 Bit 1 Bit 0
+ *   7ff  -     -     -     -    -     -     -     -       Year 00-99
+ *   7fe  0     0     0     -    -     -     -     -      Month 01-12
+ *   7fd  0     0     -     -    -     -     -     -       Date 01-31
+ *   7fc  0     FT    0     0    0     -     -     -        Day 01-07
+ *   7fb  KS    0     -     -    -     -     -     -      Hours 00-23
+ *   7fa  0     -     -     -    -     -     -     -    Minutes 00-59
+ *   7f9  ST    -     -     -    -     -     -     -    Seconds 00-59
+ *   7f8  W     R     S     -    -     -     -     -    Control
+ *
+ *   * ST is STOP BIT
+ *   * W is WRITE BIT
+ *   * R is READ BIT
+ *   * S is SIGN BIT
+ *   * FT is FREQ TEST BIT
+ *   * KS is KICK START BIT
+ */
+
+/* The Mostek 48t02 real time clock and NVRAM chip. The registers
+ * other than the control register are in binary coded decimal. Some
+ * control bits also live outside the control register.
+ */
+#define mostek_read(_addr)		readb(_addr)
+#define mostek_write(_addr,_val)	writeb(_val, _addr)
+#define MOSTEK_EEPROM		0x0000UL
+#define MOSTEK_IDPROM		0x07d8UL
+#define MOSTEK_CREG		0x07f8UL
+#define MOSTEK_SEC		0x07f9UL
+#define MOSTEK_MIN		0x07faUL
+#define MOSTEK_HOUR		0x07fbUL
+#define MOSTEK_DOW		0x07fcUL
+#define MOSTEK_DOM		0x07fdUL
+#define MOSTEK_MONTH		0x07feUL
+#define MOSTEK_YEAR		0x07ffUL
+
+struct mostek48t02 {
+	volatile char eeprom[2008];	/* This is the eeprom, don't touch! */
+	struct idprom idprom;		/* The idprom lives here. */
+	volatile unsigned char creg;	/* Control register */
+	volatile unsigned char sec;	/* Seconds (0-59) */
+	volatile unsigned char min;	/* Minutes (0-59) */
+	volatile unsigned char hour;	/* Hour (0-23) */
+	volatile unsigned char dow;	/* Day of the week (1-7) */
+	volatile unsigned char dom;	/* Day of the month (1-31) */
+	volatile unsigned char month;	/* Month of year (1-12) */
+	volatile unsigned char year;	/* Year (0-99) */
+};
+
+extern spinlock_t mostek_lock;
+extern void __iomem *mstk48t02_regs;
+
+/* Control register values. */
+#define	MSTK_CREG_WRITE	0x80	/* Must set this before placing values. */
+#define	MSTK_CREG_READ	0x40	/* Stop updates to allow a clean read. */
+#define	MSTK_CREG_SIGN	0x20	/* Slow/speed clock in calibration mode. */
+
+/* Control bits that live in the other registers. */
+#define	MSTK_STOP	0x80	/* Stop the clock oscillator. (sec) */
+#define	MSTK_KICK_START	0x80	/* Kick start the clock chip. (hour) */
+#define MSTK_FREQ_TEST	0x40	/* Frequency test mode. (day) */
+
+#define MSTK_YEAR_ZERO       1968   /* If year reg has zero, it is 1968. */
+#define MSTK_CVT_YEAR(yr)  ((yr) + MSTK_YEAR_ZERO)
+
+/* Masks that define how much space each value takes up. */
+#define	MSTK_SEC_MASK	0x7f
+#define	MSTK_MIN_MASK	0x7f
+#define	MSTK_HOUR_MASK	0x3f
+#define	MSTK_DOW_MASK	0x07
+#define	MSTK_DOM_MASK	0x3f
+#define	MSTK_MONTH_MASK	0x1f
+#define	MSTK_YEAR_MASK	0xffU
+
+/* Binary coded decimal conversion macros. */
+#define MSTK_REGVAL_TO_DECIMAL(x)  (((x) & 0x0F) + 0x0A * ((x) >> 0x04))
+#define MSTK_DECIMAL_TO_REGVAL(x)  ((((x) / 0x0A) << 0x04) + ((x) % 0x0A))
+
+/* Generic register set and get macros for internal use. */
+#define MSTK_GET(regs,var,mask) (MSTK_REGVAL_TO_DECIMAL(((struct mostek48t02 *)regs)->var & MSTK_ ## mask ## _MASK))
+#define MSTK_SET(regs,var,value,mask) do { ((struct mostek48t02 *)regs)->var &= ~(MSTK_ ## mask ## _MASK); ((struct mostek48t02 *)regs)->var |= MSTK_DECIMAL_TO_REGVAL(value) & (MSTK_ ## mask ## _MASK); } while (0)
+
+/* Macros to make register access easier on our fingers. These give you
+ * the decimal value of the register requested if applicable. You pass
+ * the a pointer to a 'struct mostek48t02'.
+ */
+#define	MSTK_REG_CREG(regs)	(((struct mostek48t02 *)regs)->creg)
+#define	MSTK_REG_SEC(regs)	MSTK_GET(regs,sec,SEC)
+#define	MSTK_REG_MIN(regs)	MSTK_GET(regs,min,MIN)
+#define	MSTK_REG_HOUR(regs)	MSTK_GET(regs,hour,HOUR)
+#define	MSTK_REG_DOW(regs)	MSTK_GET(regs,dow,DOW)
+#define	MSTK_REG_DOM(regs)	MSTK_GET(regs,dom,DOM)
+#define	MSTK_REG_MONTH(regs)	MSTK_GET(regs,month,MONTH)
+#define	MSTK_REG_YEAR(regs)	MSTK_GET(regs,year,YEAR)
+
+#define	MSTK_SET_REG_SEC(regs,value)	MSTK_SET(regs,sec,value,SEC)
+#define	MSTK_SET_REG_MIN(regs,value)	MSTK_SET(regs,min,value,MIN)
+#define	MSTK_SET_REG_HOUR(regs,value)	MSTK_SET(regs,hour,value,HOUR)
+#define	MSTK_SET_REG_DOW(regs,value)	MSTK_SET(regs,dow,value,DOW)
+#define	MSTK_SET_REG_DOM(regs,value)	MSTK_SET(regs,dom,value,DOM)
+#define	MSTK_SET_REG_MONTH(regs,value)	MSTK_SET(regs,month,value,MONTH)
+#define	MSTK_SET_REG_YEAR(regs,value)	MSTK_SET(regs,year,value,YEAR)
+
+
+/* The Mostek 48t08 clock chip. Found on Sun4m's I think. It has the
+ * same (basically) layout of the 48t02 chip except for the extra
+ * NVRAM on board (8 KB against the 48t02's 2 KB).
+ */
+struct mostek48t08 {
+	char offset[6*1024];         /* Magic things may be here, who knows? */
+	struct mostek48t02 regs;     /* Here is what we are interested in.   */
+};
+
+#ifdef CONFIG_SUN4
+enum sparc_clock_type {	MSTK48T02, MSTK48T08, \
+INTERSIL, MSTK_INVALID };
+#else
+enum sparc_clock_type {	MSTK48T02, MSTK48T08, \
+MSTK_INVALID };
+#endif
+
+#ifdef CONFIG_SUN4
+/* intersil on a sun 4/260 code  data from harris doc */
+struct intersil_dt {
+        volatile unsigned char int_csec;
+        volatile unsigned char int_hour;
+        volatile unsigned char int_min;
+        volatile unsigned char int_sec;
+        volatile unsigned char int_month;
+        volatile unsigned char int_day;
+        volatile unsigned char int_year;
+        volatile unsigned char int_dow;
+};
+
+struct intersil {
+	struct intersil_dt clk;
+	struct intersil_dt cmp;
+	volatile unsigned char int_intr_reg;
+	volatile unsigned char int_cmd_reg;
+};
+
+#define INTERSIL_STOP        0x0
+#define INTERSIL_START       0x8
+#define INTERSIL_INTR_DISABLE   0x0
+#define INTERSIL_INTR_ENABLE   0x10
+#define INTERSIL_32K		0x0
+#define INTERSIL_NORMAL		0x0
+#define INTERSIL_24H		0x4
+#define INTERSIL_INT_100HZ	0x2
+
+/* end of intersil info */
+#endif
+
+#endif /* !(_SPARC_MOSTEK_H) */
diff --git a/include/asm-sparc/mostek_64.h b/include/asm-sparc/mostek_64.h
new file mode 100644
index 0000000..c5652de
--- /dev/null
+++ b/include/asm-sparc/mostek_64.h
@@ -0,0 +1,143 @@
+/* mostek.h:  Describes the various Mostek time of day clock registers.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu)
+ */
+
+#ifndef _SPARC64_MOSTEK_H
+#define _SPARC64_MOSTEK_H
+
+#include <asm/idprom.h>
+
+/*       M48T02 Register Map (adapted from Sun NVRAM/Hostid FAQ)
+ *
+ *                             Data
+ * Address                                                 Function
+ *        Bit 7 Bit 6 Bit 5 Bit 4Bit 3 Bit 2 Bit 1 Bit 0
+ *   7ff  -     -     -     -    -     -     -     -       Year 00-99
+ *   7fe  0     0     0     -    -     -     -     -      Month 01-12
+ *   7fd  0     0     -     -    -     -     -     -       Date 01-31
+ *   7fc  0     FT    0     0    0     -     -     -        Day 01-07
+ *   7fb  KS    0     -     -    -     -     -     -      Hours 00-23
+ *   7fa  0     -     -     -    -     -     -     -    Minutes 00-59
+ *   7f9  ST    -     -     -    -     -     -     -    Seconds 00-59
+ *   7f8  W     R     S     -    -     -     -     -    Control
+ *
+ *   * ST is STOP BIT
+ *   * W is WRITE BIT
+ *   * R is READ BIT
+ *   * S is SIGN BIT
+ *   * FT is FREQ TEST BIT
+ *   * KS is KICK START BIT
+ */
+
+/* The Mostek 48t02 real time clock and NVRAM chip. The registers
+ * other than the control register are in binary coded decimal. Some
+ * control bits also live outside the control register.
+ *
+ * We now deal with physical addresses for I/O to the chip. -DaveM
+ */
+static inline u8 mostek_read(void __iomem *addr)
+{
+	u8 ret;
+
+	__asm__ __volatile__("lduba	[%1] %2, %0"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+	return ret;
+}
+
+static inline void mostek_write(void __iomem *addr, u8 val)
+{
+	__asm__ __volatile__("stba	%0, [%1] %2"
+			     : /* no outputs */
+			     : "r" (val), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+#define MOSTEK_EEPROM		0x0000UL
+#define MOSTEK_IDPROM		0x07d8UL
+#define MOSTEK_CREG		0x07f8UL
+#define MOSTEK_SEC		0x07f9UL
+#define MOSTEK_MIN		0x07faUL
+#define MOSTEK_HOUR		0x07fbUL
+#define MOSTEK_DOW		0x07fcUL
+#define MOSTEK_DOM		0x07fdUL
+#define MOSTEK_MONTH		0x07feUL
+#define MOSTEK_YEAR		0x07ffUL
+
+extern spinlock_t mostek_lock;
+extern void __iomem *mstk48t02_regs;
+
+/* Control register values. */
+#define	MSTK_CREG_WRITE	0x80	/* Must set this before placing values. */
+#define	MSTK_CREG_READ	0x40	/* Stop updates to allow a clean read. */
+#define	MSTK_CREG_SIGN	0x20	/* Slow/speed clock in calibration mode. */
+
+/* Control bits that live in the other registers. */
+#define	MSTK_STOP	0x80	/* Stop the clock oscillator. (sec) */
+#define	MSTK_KICK_START	0x80	/* Kick start the clock chip. (hour) */
+#define MSTK_FREQ_TEST	0x40	/* Frequency test mode. (day) */
+
+#define MSTK_YEAR_ZERO       1968   /* If year reg has zero, it is 1968. */
+#define MSTK_CVT_YEAR(yr)  ((yr) + MSTK_YEAR_ZERO)
+
+/* Masks that define how much space each value takes up. */
+#define	MSTK_SEC_MASK	0x7f
+#define	MSTK_MIN_MASK	0x7f
+#define	MSTK_HOUR_MASK	0x3f
+#define	MSTK_DOW_MASK	0x07
+#define	MSTK_DOM_MASK	0x3f
+#define	MSTK_MONTH_MASK	0x1f
+#define	MSTK_YEAR_MASK	0xffU
+
+/* Binary coded decimal conversion macros. */
+#define MSTK_REGVAL_TO_DECIMAL(x)  (((x) & 0x0F) + 0x0A * ((x) >> 0x04))
+#define MSTK_DECIMAL_TO_REGVAL(x)  ((((x) / 0x0A) << 0x04) + ((x) % 0x0A))
+
+/* Generic register set and get macros for internal use. */
+#define MSTK_GET(regs,name)	\
+	(MSTK_REGVAL_TO_DECIMAL(mostek_read(regs + MOSTEK_ ## name) & MSTK_ ## name ## _MASK))
+#define MSTK_SET(regs,name,value) \
+do {	u8 __val = mostek_read(regs + MOSTEK_ ## name); \
+	__val &= ~(MSTK_ ## name ## _MASK); \
+	__val |= (MSTK_DECIMAL_TO_REGVAL(value) & \
+		  (MSTK_ ## name ## _MASK)); \
+	mostek_write(regs + MOSTEK_ ## name, __val); \
+} while(0)
+
+/* Macros to make register access easier on our fingers. These give you
+ * the decimal value of the register requested if applicable. You pass
+ * the a pointer to a 'struct mostek48t02'.
+ */
+#define	MSTK_REG_CREG(regs)	(mostek_read((regs) + MOSTEK_CREG))
+#define	MSTK_REG_SEC(regs)	MSTK_GET(regs,SEC)
+#define	MSTK_REG_MIN(regs)	MSTK_GET(regs,MIN)
+#define	MSTK_REG_HOUR(regs)	MSTK_GET(regs,HOUR)
+#define	MSTK_REG_DOW(regs)	MSTK_GET(regs,DOW)
+#define	MSTK_REG_DOM(regs)	MSTK_GET(regs,DOM)
+#define	MSTK_REG_MONTH(regs)	MSTK_GET(regs,MONTH)
+#define	MSTK_REG_YEAR(regs)	MSTK_GET(regs,YEAR)
+
+#define	MSTK_SET_REG_SEC(regs,value)	MSTK_SET(regs,SEC,value)
+#define	MSTK_SET_REG_MIN(regs,value)	MSTK_SET(regs,MIN,value)
+#define	MSTK_SET_REG_HOUR(regs,value)	MSTK_SET(regs,HOUR,value)
+#define	MSTK_SET_REG_DOW(regs,value)	MSTK_SET(regs,DOW,value)
+#define	MSTK_SET_REG_DOM(regs,value)	MSTK_SET(regs,DOM,value)
+#define	MSTK_SET_REG_MONTH(regs,value)	MSTK_SET(regs,MONTH,value)
+#define	MSTK_SET_REG_YEAR(regs,value)	MSTK_SET(regs,YEAR,value)
+
+
+/* The Mostek 48t08 clock chip. Found on Sun4m's I think. It has the
+ * same (basically) layout of the 48t02 chip except for the extra
+ * NVRAM on board (8 KB against the 48t02's 2 KB).
+ */
+#define MOSTEK_48T08_OFFSET	0x0000UL	/* Lower NVRAM portions */
+#define MOSTEK_48T08_48T02	0x1800UL	/* Offset to 48T02 chip */
+
+/* SUN5 systems usually have 48t59 model clock chipsets.  But we keep the older
+ * clock chip definitions around just in case.
+ */
+#define MOSTEK_48T59_OFFSET	0x0000UL	/* Lower NVRAM portions */
+#define MOSTEK_48T59_48T02	0x1800UL	/* Offset to 48T02 chip */
+
+#endif /* !(_SPARC64_MOSTEK_H) */
diff --git a/include/asm-sparc/msgbuf.h b/include/asm-sparc/msgbuf.h
index 8cec9ad..efc7cbe9 100644
--- a/include/asm-sparc/msgbuf.h
+++ b/include/asm-sparc/msgbuf.h
@@ -1,7 +1,7 @@
-#ifndef _SPARC64_MSGBUF_H
-#define _SPARC64_MSGBUF_H
+#ifndef _SPARC_MSGBUF_H
+#define _SPARC_MSGBUF_H
 
-/* 
+/*
  * The msqid64_ds structure for sparc64 architecture.
  * Note extra padding because this structure is passed back and forth
  * between kernel and user space.
@@ -11,13 +11,20 @@
  * - 2 miscellaneous 32-bit values
  */
 
+#if defined(__sparc__) && defined(__arch64__)
+# define PADDING(x)
+#else
+# define PADDING(x) unsigned int x;
+#endif
+
+
 struct msqid64_ds {
 	struct ipc64_perm msg_perm;
-	unsigned int   __pad1;
+	PADDING(__pad1)
 	__kernel_time_t msg_stime;	/* last msgsnd time */
-	unsigned int   __pad2;
+	PADDING(__pad2)
 	__kernel_time_t msg_rtime;	/* last msgrcv time */
-	unsigned int   __pad3;
+	PADDING(__pad3)
 	__kernel_time_t msg_ctime;	/* last change time */
 	unsigned long  msg_cbytes;	/* current number of bytes on queue */
 	unsigned long  msg_qnum;	/* number of messages in queue */
@@ -27,5 +34,5 @@
 	unsigned long  __unused1;
 	unsigned long  __unused2;
 };
-
-#endif /* _SPARC64_MSGBUF_H */
+#undef PADDING
+#endif /* _SPARC_MSGBUF_H */
diff --git a/include/asm-sparc/namei.h b/include/asm-sparc/namei.h
index 0646102..eff944b 100644
--- a/include/asm-sparc/namei.h
+++ b/include/asm-sparc/namei.h
@@ -1,13 +1,8 @@
-/*
- * linux/include/asm-sparc/namei.h
- *
- * Routines to handle famous /usr/gnemul/s*.
- * Included from linux/fs/namei.c
- */
-
-#ifndef __SPARC_NAMEI_H
-#define __SPARC_NAMEI_H
-
-#define __emul_prefix() NULL
-
-#endif /* __SPARC_NAMEI_H */
+#ifndef ___ASM_SPARC_NAMEI_H
+#define ___ASM_SPARC_NAMEI_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/namei_64.h>
+#else
+#include <asm-sparc/namei_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/namei_32.h b/include/asm-sparc/namei_32.h
new file mode 100644
index 0000000..0646102
--- /dev/null
+++ b/include/asm-sparc/namei_32.h
@@ -0,0 +1,13 @@
+/*
+ * linux/include/asm-sparc/namei.h
+ *
+ * Routines to handle famous /usr/gnemul/s*.
+ * Included from linux/fs/namei.c
+ */
+
+#ifndef __SPARC_NAMEI_H
+#define __SPARC_NAMEI_H
+
+#define __emul_prefix() NULL
+
+#endif /* __SPARC_NAMEI_H */
diff --git a/include/asm-sparc/namei_64.h b/include/asm-sparc/namei_64.h
new file mode 100644
index 0000000..cbc1b4c
--- /dev/null
+++ b/include/asm-sparc/namei_64.h
@@ -0,0 +1,13 @@
+/*
+ * linux/include/asm-sparc64/namei.h
+ *
+ * Routines to handle famous /usr/gnemul/s*.
+ * Included from linux/fs/namei.c
+ */
+
+#ifndef __SPARC64_NAMEI_H
+#define __SPARC64_NAMEI_H
+
+#define __emul_prefix() NULL
+
+#endif /* __SPARC64_NAMEI_H */
diff --git a/include/asm-sparc/ns87303.h b/include/asm-sparc/ns87303.h
new file mode 100644
index 0000000..686defe
--- /dev/null
+++ b/include/asm-sparc/ns87303.h
@@ -0,0 +1,118 @@
+/* ns87303.h: Configuration Register Description for the
+ *            National Semiconductor PC87303 (SuperIO).
+ *
+ * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
+ */
+
+#ifndef _SPARC_NS87303_H
+#define _SPARC_NS87303_H 1
+
+/*
+ * Control Register Index Values
+ */
+#define FER	0x00
+#define FAR	0x01
+#define PTR	0x02
+#define FCR	0x03
+#define PCR	0x04
+#define KRR	0x05
+#define PMC	0x06
+#define TUP	0x07
+#define SID	0x08
+#define ASC	0x09
+#define CS0CF0	0x0a
+#define CS0CF1	0x0b
+#define CS1CF0	0x0c
+#define CS1CF1	0x0d
+
+/* Function Enable Register (FER) bits */
+#define FER_EDM		0x10	/* Encoded Drive and Motor pin information   */
+
+/* Function Address Register (FAR) bits */
+#define FAR_LPT_MASK	0x03
+#define FAR_LPTB	0x00
+#define FAR_LPTA	0x01
+#define FAR_LPTC	0x02
+
+/* Power and Test Register (PTR) bits */
+#define PTR_LPTB_IRQ7	0x08
+#define PTR_LEVEL_IRQ	0x80	/* When not ECP/EPP: Use level IRQ           */
+#define PTR_LPT_REG_DIR	0x80	/* When ECP/EPP: LPT CTR controlls direction */
+				/*               of the parallel port	     */
+
+/* Function Control Register (FCR) bits */
+#define FCR_LDE		0x10	/* Logical Drive Exchange                    */
+#define FCR_ZWS_ENA	0x20	/* Enable short host read/write in ECP/EPP   */
+
+/* Printer Control Register (PCR) bits */
+#define PCR_EPP_ENABLE	0x01
+#define PCR_EPP_IEEE	0x02	/* Enable EPP Version 1.9 (IEEE 1284)        */
+#define PCR_ECP_ENABLE	0x04
+#define PCR_ECP_CLK_ENA	0x08	/* If 0 ECP Clock is stopped on Power down   */
+#define PCR_IRQ_POLAR	0x20	/* If 0 IRQ is level high or negative pulse, */
+				/* if 1 polarity is inverted                 */
+#define PCR_IRQ_ODRAIN	0x40	/* If 1, IRQ is open drain                   */
+
+/* Tape UARTs and Parallel Port Config Register (TUP) bits */
+#define TUP_EPP_TIMO	0x02	/* Enable EPP timeout IRQ                    */
+
+/* Advanced SuperIO Config Register (ASC) bits */
+#define ASC_LPT_IRQ7	0x01	/* Always use IRQ7 for LPT                  */
+#define ASC_DRV2_SEL	0x02	/* Logical Drive Exchange controlled by TDR  */
+
+#define FER_RESERVED	0x00
+#define FAR_RESERVED	0x00
+#define PTR_RESERVED	0x73
+#define FCR_RESERVED	0xc4
+#define PCR_RESERVED	0x10
+#define KRR_RESERVED	0x00
+#define PMC_RESERVED	0x98
+#define TUP_RESERVED	0xfb
+#define SIP_RESERVED	0x00
+#define ASC_RESERVED	0x18
+#define CS0CF0_RESERVED	0x00
+#define CS0CF1_RESERVED	0x08
+#define CS1CF0_RESERVED	0x00
+#define CS1CF1_RESERVED	0x08
+
+#ifdef __KERNEL__
+
+#include <linux/spinlock.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+extern spinlock_t ns87303_lock;
+
+static inline int ns87303_modify(unsigned long port, unsigned int index,
+				     unsigned char clr, unsigned char set)
+{
+	static unsigned char reserved[] = {
+		FER_RESERVED, FAR_RESERVED, PTR_RESERVED, FCR_RESERVED,
+		PCR_RESERVED, KRR_RESERVED, PMC_RESERVED, TUP_RESERVED,
+		SIP_RESERVED, ASC_RESERVED, CS0CF0_RESERVED, CS0CF1_RESERVED,
+		CS1CF0_RESERVED, CS1CF1_RESERVED
+	};
+	unsigned long flags;
+	unsigned char value;
+
+	if (index > 0x0d)
+		return -EINVAL;
+
+	spin_lock_irqsave(&ns87303_lock, flags);
+
+	outb(index, port);
+	value = inb(port + 1);
+	value &= ~(reserved[index] | clr);
+	value |= set;
+	outb(value, port + 1);
+	outb(value, port + 1);
+
+	spin_unlock_irqrestore(&ns87303_lock, flags);
+
+	return 0;
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* !(_SPARC_NS87303_H) */
diff --git a/include/asm-sparc/of_platform.h b/include/asm-sparc/of_platform.h
index 3833435..851eb84 100644
--- a/include/asm-sparc/of_platform.h
+++ b/include/asm-sparc/of_platform.h
@@ -1,24 +1,8 @@
-#ifndef _ASM_SPARC_OF_PLATFORM_H
-#define _ASM_SPARC_OF_PLATFORM_H
-/*
- *    Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
- *			 <benh@kernel.crashing.org>
- *    Modified for Sparc by merging parts of asm-sparc/of_device.h
- *		by Stephen Rothwell
- *
- *  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 is just here during the transition */
-#include <linux/of_platform.h>
-
-extern struct bus_type ebus_bus_type;
-extern struct bus_type sbus_bus_type;
-
-#define of_bus_type	of_platform_bus_type	/* for compatibility */
-
-#endif	/* _ASM_SPARC_OF_PLATFORM_H */
+#ifndef ___ASM_SPARC_OF_PLATFORM_H
+#define ___ASM_SPARC_OF_PLATFORM_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/of_platform_64.h>
+#else
+#include <asm-sparc/of_platform_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/of_platform_32.h b/include/asm-sparc/of_platform_32.h
new file mode 100644
index 0000000..3833435
--- /dev/null
+++ b/include/asm-sparc/of_platform_32.h
@@ -0,0 +1,24 @@
+#ifndef _ASM_SPARC_OF_PLATFORM_H
+#define _ASM_SPARC_OF_PLATFORM_H
+/*
+ *    Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
+ *			 <benh@kernel.crashing.org>
+ *    Modified for Sparc by merging parts of asm-sparc/of_device.h
+ *		by Stephen Rothwell
+ *
+ *  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 is just here during the transition */
+#include <linux/of_platform.h>
+
+extern struct bus_type ebus_bus_type;
+extern struct bus_type sbus_bus_type;
+
+#define of_bus_type	of_platform_bus_type	/* for compatibility */
+
+#endif	/* _ASM_SPARC_OF_PLATFORM_H */
diff --git a/include/asm-sparc/of_platform_64.h b/include/asm-sparc/of_platform_64.h
new file mode 100644
index 0000000..78aa032
--- /dev/null
+++ b/include/asm-sparc/of_platform_64.h
@@ -0,0 +1,25 @@
+#ifndef _ASM_SPARC64_OF_PLATFORM_H
+#define _ASM_SPARC64_OF_PLATFORM_H
+/*
+ *    Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
+ *			 <benh@kernel.crashing.org>
+ *    Modified for Sparc by merging parts of asm-sparc/of_device.h
+ *		by Stephen Rothwell
+ *
+ *  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 is just here during the transition */
+#include <linux/of_platform.h>
+
+extern struct bus_type isa_bus_type;
+extern struct bus_type ebus_bus_type;
+extern struct bus_type sbus_bus_type;
+
+#define of_bus_type	of_platform_bus_type	/* for compatibility */
+
+#endif	/* _ASM_SPARC64_OF_PLATFORM_H */
diff --git a/include/asm-sparc/openprom.h b/include/asm-sparc/openprom.h
index ed4b6bc..8c349f0 100644
--- a/include/asm-sparc/openprom.h
+++ b/include/asm-sparc/openprom.h
@@ -1,257 +1,8 @@
-#ifndef __SPARC_OPENPROM_H
-#define __SPARC_OPENPROM_H
-
-/* openprom.h:  Prom structures and defines for access to the OPENBOOT
- *              prom routines and data areas.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <asm/vaddrs.h>
-
-/* Empirical constants... */
-#define	LINUX_OPPROM_MAGIC      0x10010407
-
-#ifndef __ASSEMBLY__
-/* V0 prom device operations. */
-struct linux_dev_v0_funcs {
-	int (*v0_devopen)(char *device_str);
-	int (*v0_devclose)(int dev_desc);
-	int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
-	int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
-	int (*v0_wrnetdev)(int dev_desc, int num_bytes, char *buf);
-	int (*v0_rdnetdev)(int dev_desc, int num_bytes, char *buf);
-	int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
-	int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
-	int (*v0_seekdev)(int dev_desc, long logical_offst, int from);
-};
-
-/* V2 and later prom device operations. */
-struct linux_dev_v2_funcs {
-	int (*v2_inst2pkg)(int d);	/* Convert ihandle to phandle */
-	char * (*v2_dumb_mem_alloc)(char *va, unsigned sz);
-	void (*v2_dumb_mem_free)(char *va, unsigned sz);
-
-	/* To map devices into virtual I/O space. */
-	char * (*v2_dumb_mmap)(char *virta, int which_io, unsigned paddr, unsigned sz);
-	void (*v2_dumb_munmap)(char *virta, unsigned size);
-
-	int (*v2_dev_open)(char *devpath);
-	void (*v2_dev_close)(int d);
-	int (*v2_dev_read)(int d, char *buf, int nbytes);
-	int (*v2_dev_write)(int d, char *buf, int nbytes);
-	int (*v2_dev_seek)(int d, int hi, int lo);
-
-	/* Never issued (multistage load support) */
-	void (*v2_wheee2)(void);
-	void (*v2_wheee3)(void);
-};
-
-struct linux_mlist_v0 {
-	struct linux_mlist_v0 *theres_more;
-	char *start_adr;
-	unsigned num_bytes;
-};
-
-struct linux_mem_v0 {
-	struct linux_mlist_v0 **v0_totphys;
-	struct linux_mlist_v0 **v0_prommap;
-	struct linux_mlist_v0 **v0_available; /* What we can use */
-};
-
-/* Arguments sent to the kernel from the boot prompt. */
-struct linux_arguments_v0 {
-	char *argv[8];
-	char args[100];
-	char boot_dev[2];
-	int boot_dev_ctrl;
-	int boot_dev_unit;
-	int dev_partition;
-	char *kernel_file_name;
-	void *aieee1;           /* XXX */
-};
-
-/* V2 and up boot things. */
-struct linux_bootargs_v2 {
-	char **bootpath;
-	char **bootargs;
-	int *fd_stdin;
-	int *fd_stdout;
-};
-
-/* The top level PROM vector. */
-struct linux_romvec {
-	/* Version numbers. */
-	unsigned int pv_magic_cookie;
-	unsigned int pv_romvers;
-	unsigned int pv_plugin_revision;
-	unsigned int pv_printrev;
-
-	/* Version 0 memory descriptors. */
-	struct linux_mem_v0 pv_v0mem;
-
-	/* Node operations. */
-	struct linux_nodeops *pv_nodeops;
-
-	char **pv_bootstr;
-	struct linux_dev_v0_funcs pv_v0devops;
-
-	char *pv_stdin;
-	char *pv_stdout;
-#define	PROMDEV_KBD	0		/* input from keyboard */
-#define	PROMDEV_SCREEN	0		/* output to screen */
-#define	PROMDEV_TTYA	1		/* in/out to ttya */
-#define	PROMDEV_TTYB	2		/* in/out to ttyb */
-
-	/* Blocking getchar/putchar.  NOT REENTRANT! (grr) */
-	int (*pv_getchar)(void);
-	void (*pv_putchar)(int ch);
-
-	/* Non-blocking variants. */
-	int (*pv_nbgetchar)(void);
-	int (*pv_nbputchar)(int ch);
-
-	void (*pv_putstr)(char *str, int len);
-
-	/* Miscellany. */
-	void (*pv_reboot)(char *bootstr);
-	void (*pv_printf)(__const__ char *fmt, ...);
-	void (*pv_abort)(void);
-	__volatile__ int *pv_ticks;
-	void (*pv_halt)(void);
-	void (**pv_synchook)(void);
-
-	/* Evaluate a forth string, not different proto for V0 and V2->up. */
-	union {
-		void (*v0_eval)(int len, char *str);
-		void (*v2_eval)(char *str);
-	} pv_fortheval;
-
-	struct linux_arguments_v0 **pv_v0bootargs;
-
-	/* Get ether address. */
-	unsigned int (*pv_enaddr)(int d, char *enaddr);
-
-	struct linux_bootargs_v2 pv_v2bootargs;
-	struct linux_dev_v2_funcs pv_v2devops;
-
-	int filler[15];
-
-	/* This one is sun4c/sun4 only. */
-	void (*pv_setctxt)(int ctxt, char *va, int pmeg);
-
-	/* Prom version 3 Multiprocessor routines. This stuff is crazy.
-	 * No joke. Calling these when there is only one cpu probably
-	 * crashes the machine, have to test this. :-)
-	 */
-
-	/* v3_cpustart() will start the cpu 'whichcpu' in mmu-context
-	 * 'thiscontext' executing at address 'prog_counter'
-	 */
-	int (*v3_cpustart)(unsigned int whichcpu, int ctxtbl_ptr,
-			   int thiscontext, char *prog_counter);
-
-	/* v3_cpustop() will cause cpu 'whichcpu' to stop executing
-	 * until a resume cpu call is made.
-	 */
-	int (*v3_cpustop)(unsigned int whichcpu);
-
-	/* v3_cpuidle() will idle cpu 'whichcpu' until a stop or
-	 * resume cpu call is made.
-	 */
-	int (*v3_cpuidle)(unsigned int whichcpu);
-
-	/* v3_cpuresume() will resume processor 'whichcpu' executing
-	 * starting with whatever 'pc' and 'npc' were left at the
-	 * last 'idle' or 'stop' call.
-	 */
-	int (*v3_cpuresume)(unsigned int whichcpu);
-};
-
-/* Routines for traversing the prom device tree. */
-struct linux_nodeops {
-	int (*no_nextnode)(int node);
-	int (*no_child)(int node);
-	int (*no_proplen)(int node, char *name);
-	int (*no_getprop)(int node, char *name, char *val);
-	int (*no_setprop)(int node, char *name, char *val, int len);
-	char * (*no_nextprop)(int node, char *name);
-};
-
-/* More fun PROM structures for device probing. */
-#define PROMREG_MAX     16
-#define PROMVADDR_MAX   16
-#define PROMINTR_MAX    15
-
-struct linux_prom_registers {
-	unsigned int which_io;         /* is this in OBIO space? */
-	unsigned int phys_addr;        /* The physical address of this register */
-	unsigned int reg_size;         /* How many bytes does this register take up? */
-};
-
-struct linux_prom_irqs {
-	int pri;    /* IRQ priority */
-	int vector; /* This is foobar, what does it do? */
-};
-
-/* Element of the "ranges" vector */
-struct linux_prom_ranges {
-	unsigned int ot_child_space;
-	unsigned int ot_child_base;		/* Bus feels this */
-	unsigned int ot_parent_space;
-	unsigned int ot_parent_base;		/* CPU looks from here */
-	unsigned int or_size;
-};
-
-/* Ranges and reg properties are a bit different for PCI. */
-struct linux_prom_pci_registers {
-	/* 
-	 * We don't know what information this field contain.
-	 * We guess, PCI device function is in bits 15:8
-	 * So, ...
-	 */
-	unsigned int which_io;  /* Let it be which_io */
-
-	unsigned int phys_hi;
-	unsigned int phys_lo;
-
-	unsigned int size_hi;
-	unsigned int size_lo;
-};
-
-struct linux_prom_pci_ranges {
-	unsigned int child_phys_hi;	/* Only certain bits are encoded here. */
-	unsigned int child_phys_mid;
-	unsigned int child_phys_lo;
-
-	unsigned int parent_phys_hi;
-	unsigned int parent_phys_lo;
-
-	unsigned int size_hi;
-	unsigned int size_lo;
-};
-
-struct linux_prom_pci_assigned_addresses {
-	unsigned int which_io;
-
-	unsigned int phys_hi;
-	unsigned int phys_lo;
-
-	unsigned int size_hi;
-	unsigned int size_lo;
-};
-
-struct linux_prom_ebus_ranges {
-	unsigned int child_phys_hi;
-	unsigned int child_phys_lo;
-
-	unsigned int parent_phys_hi;
-	unsigned int parent_phys_mid;
-	unsigned int parent_phys_lo;
-
-	unsigned int size;
-};
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(__SPARC_OPENPROM_H) */
+#ifndef ___ASM_SPARC_OPENPROM_H
+#define ___ASM_SPARC_OPENPROM_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/openprom_64.h>
+#else
+#include <asm-sparc/openprom_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/openprom_32.h b/include/asm-sparc/openprom_32.h
new file mode 100644
index 0000000..8b1649f
--- /dev/null
+++ b/include/asm-sparc/openprom_32.h
@@ -0,0 +1,255 @@
+#ifndef __SPARC_OPENPROM_H
+#define __SPARC_OPENPROM_H
+
+/* openprom.h:  Prom structures and defines for access to the OPENBOOT
+ *              prom routines and data areas.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+/* Empirical constants... */
+#define	LINUX_OPPROM_MAGIC      0x10010407
+
+#ifndef __ASSEMBLY__
+/* V0 prom device operations. */
+struct linux_dev_v0_funcs {
+	int (*v0_devopen)(char *device_str);
+	int (*v0_devclose)(int dev_desc);
+	int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
+	int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
+	int (*v0_wrnetdev)(int dev_desc, int num_bytes, char *buf);
+	int (*v0_rdnetdev)(int dev_desc, int num_bytes, char *buf);
+	int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
+	int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
+	int (*v0_seekdev)(int dev_desc, long logical_offst, int from);
+};
+
+/* V2 and later prom device operations. */
+struct linux_dev_v2_funcs {
+	int (*v2_inst2pkg)(int d);	/* Convert ihandle to phandle */
+	char * (*v2_dumb_mem_alloc)(char *va, unsigned sz);
+	void (*v2_dumb_mem_free)(char *va, unsigned sz);
+
+	/* To map devices into virtual I/O space. */
+	char * (*v2_dumb_mmap)(char *virta, int which_io, unsigned paddr, unsigned sz);
+	void (*v2_dumb_munmap)(char *virta, unsigned size);
+
+	int (*v2_dev_open)(char *devpath);
+	void (*v2_dev_close)(int d);
+	int (*v2_dev_read)(int d, char *buf, int nbytes);
+	int (*v2_dev_write)(int d, char *buf, int nbytes);
+	int (*v2_dev_seek)(int d, int hi, int lo);
+
+	/* Never issued (multistage load support) */
+	void (*v2_wheee2)(void);
+	void (*v2_wheee3)(void);
+};
+
+struct linux_mlist_v0 {
+	struct linux_mlist_v0 *theres_more;
+	char *start_adr;
+	unsigned num_bytes;
+};
+
+struct linux_mem_v0 {
+	struct linux_mlist_v0 **v0_totphys;
+	struct linux_mlist_v0 **v0_prommap;
+	struct linux_mlist_v0 **v0_available; /* What we can use */
+};
+
+/* Arguments sent to the kernel from the boot prompt. */
+struct linux_arguments_v0 {
+	char *argv[8];
+	char args[100];
+	char boot_dev[2];
+	int boot_dev_ctrl;
+	int boot_dev_unit;
+	int dev_partition;
+	char *kernel_file_name;
+	void *aieee1;           /* XXX */
+};
+
+/* V2 and up boot things. */
+struct linux_bootargs_v2 {
+	char **bootpath;
+	char **bootargs;
+	int *fd_stdin;
+	int *fd_stdout;
+};
+
+/* The top level PROM vector. */
+struct linux_romvec {
+	/* Version numbers. */
+	unsigned int pv_magic_cookie;
+	unsigned int pv_romvers;
+	unsigned int pv_plugin_revision;
+	unsigned int pv_printrev;
+
+	/* Version 0 memory descriptors. */
+	struct linux_mem_v0 pv_v0mem;
+
+	/* Node operations. */
+	struct linux_nodeops *pv_nodeops;
+
+	char **pv_bootstr;
+	struct linux_dev_v0_funcs pv_v0devops;
+
+	char *pv_stdin;
+	char *pv_stdout;
+#define	PROMDEV_KBD	0		/* input from keyboard */
+#define	PROMDEV_SCREEN	0		/* output to screen */
+#define	PROMDEV_TTYA	1		/* in/out to ttya */
+#define	PROMDEV_TTYB	2		/* in/out to ttyb */
+
+	/* Blocking getchar/putchar.  NOT REENTRANT! (grr) */
+	int (*pv_getchar)(void);
+	void (*pv_putchar)(int ch);
+
+	/* Non-blocking variants. */
+	int (*pv_nbgetchar)(void);
+	int (*pv_nbputchar)(int ch);
+
+	void (*pv_putstr)(char *str, int len);
+
+	/* Miscellany. */
+	void (*pv_reboot)(char *bootstr);
+	void (*pv_printf)(__const__ char *fmt, ...);
+	void (*pv_abort)(void);
+	__volatile__ int *pv_ticks;
+	void (*pv_halt)(void);
+	void (**pv_synchook)(void);
+
+	/* Evaluate a forth string, not different proto for V0 and V2->up. */
+	union {
+		void (*v0_eval)(int len, char *str);
+		void (*v2_eval)(char *str);
+	} pv_fortheval;
+
+	struct linux_arguments_v0 **pv_v0bootargs;
+
+	/* Get ether address. */
+	unsigned int (*pv_enaddr)(int d, char *enaddr);
+
+	struct linux_bootargs_v2 pv_v2bootargs;
+	struct linux_dev_v2_funcs pv_v2devops;
+
+	int filler[15];
+
+	/* This one is sun4c/sun4 only. */
+	void (*pv_setctxt)(int ctxt, char *va, int pmeg);
+
+	/* Prom version 3 Multiprocessor routines. This stuff is crazy.
+	 * No joke. Calling these when there is only one cpu probably
+	 * crashes the machine, have to test this. :-)
+	 */
+
+	/* v3_cpustart() will start the cpu 'whichcpu' in mmu-context
+	 * 'thiscontext' executing at address 'prog_counter'
+	 */
+	int (*v3_cpustart)(unsigned int whichcpu, int ctxtbl_ptr,
+			   int thiscontext, char *prog_counter);
+
+	/* v3_cpustop() will cause cpu 'whichcpu' to stop executing
+	 * until a resume cpu call is made.
+	 */
+	int (*v3_cpustop)(unsigned int whichcpu);
+
+	/* v3_cpuidle() will idle cpu 'whichcpu' until a stop or
+	 * resume cpu call is made.
+	 */
+	int (*v3_cpuidle)(unsigned int whichcpu);
+
+	/* v3_cpuresume() will resume processor 'whichcpu' executing
+	 * starting with whatever 'pc' and 'npc' were left at the
+	 * last 'idle' or 'stop' call.
+	 */
+	int (*v3_cpuresume)(unsigned int whichcpu);
+};
+
+/* Routines for traversing the prom device tree. */
+struct linux_nodeops {
+	int (*no_nextnode)(int node);
+	int (*no_child)(int node);
+	int (*no_proplen)(int node, char *name);
+	int (*no_getprop)(int node, char *name, char *val);
+	int (*no_setprop)(int node, char *name, char *val, int len);
+	char * (*no_nextprop)(int node, char *name);
+};
+
+/* More fun PROM structures for device probing. */
+#define PROMREG_MAX     16
+#define PROMVADDR_MAX   16
+#define PROMINTR_MAX    15
+
+struct linux_prom_registers {
+	unsigned int which_io;         /* is this in OBIO space? */
+	unsigned int phys_addr;        /* The physical address of this register */
+	unsigned int reg_size;         /* How many bytes does this register take up? */
+};
+
+struct linux_prom_irqs {
+	int pri;    /* IRQ priority */
+	int vector; /* This is foobar, what does it do? */
+};
+
+/* Element of the "ranges" vector */
+struct linux_prom_ranges {
+	unsigned int ot_child_space;
+	unsigned int ot_child_base;		/* Bus feels this */
+	unsigned int ot_parent_space;
+	unsigned int ot_parent_base;		/* CPU looks from here */
+	unsigned int or_size;
+};
+
+/* Ranges and reg properties are a bit different for PCI. */
+struct linux_prom_pci_registers {
+	/*
+	 * We don't know what information this field contain.
+	 * We guess, PCI device function is in bits 15:8
+	 * So, ...
+	 */
+	unsigned int which_io;  /* Let it be which_io */
+
+	unsigned int phys_hi;
+	unsigned int phys_lo;
+
+	unsigned int size_hi;
+	unsigned int size_lo;
+};
+
+struct linux_prom_pci_ranges {
+	unsigned int child_phys_hi;	/* Only certain bits are encoded here. */
+	unsigned int child_phys_mid;
+	unsigned int child_phys_lo;
+
+	unsigned int parent_phys_hi;
+	unsigned int parent_phys_lo;
+
+	unsigned int size_hi;
+	unsigned int size_lo;
+};
+
+struct linux_prom_pci_assigned_addresses {
+	unsigned int which_io;
+
+	unsigned int phys_hi;
+	unsigned int phys_lo;
+
+	unsigned int size_hi;
+	unsigned int size_lo;
+};
+
+struct linux_prom_ebus_ranges {
+	unsigned int child_phys_hi;
+	unsigned int child_phys_lo;
+
+	unsigned int parent_phys_hi;
+	unsigned int parent_phys_mid;
+	unsigned int parent_phys_lo;
+
+	unsigned int size;
+};
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__SPARC_OPENPROM_H) */
diff --git a/include/asm-sparc/openprom_64.h b/include/asm-sparc/openprom_64.h
new file mode 100644
index 0000000..b69e4a8
--- /dev/null
+++ b/include/asm-sparc/openprom_64.h
@@ -0,0 +1,280 @@
+#ifndef __SPARC64_OPENPROM_H
+#define __SPARC64_OPENPROM_H
+
+/* openprom.h:  Prom structures and defines for access to the OPENBOOT
+ *              prom routines and data areas.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef __ASSEMBLY__
+/* V0 prom device operations. */
+struct linux_dev_v0_funcs {
+	int (*v0_devopen)(char *device_str);
+	int (*v0_devclose)(int dev_desc);
+	int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
+	int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
+	int (*v0_wrnetdev)(int dev_desc, int num_bytes, char *buf);
+	int (*v0_rdnetdev)(int dev_desc, int num_bytes, char *buf);
+	int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
+	int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
+	int (*v0_seekdev)(int dev_desc, long logical_offst, int from);
+};
+
+/* V2 and later prom device operations. */
+struct linux_dev_v2_funcs {
+	int (*v2_inst2pkg)(int d);	/* Convert ihandle to phandle */
+	char * (*v2_dumb_mem_alloc)(char *va, unsigned sz);
+	void (*v2_dumb_mem_free)(char *va, unsigned sz);
+
+	/* To map devices into virtual I/O space. */
+	char * (*v2_dumb_mmap)(char *virta, int which_io, unsigned paddr, unsigned sz);
+	void (*v2_dumb_munmap)(char *virta, unsigned size);
+
+	int (*v2_dev_open)(char *devpath);
+	void (*v2_dev_close)(int d);
+	int (*v2_dev_read)(int d, char *buf, int nbytes);
+	int (*v2_dev_write)(int d, char *buf, int nbytes);
+	int (*v2_dev_seek)(int d, int hi, int lo);
+
+	/* Never issued (multistage load support) */
+	void (*v2_wheee2)(void);
+	void (*v2_wheee3)(void);
+};
+
+struct linux_mlist_v0 {
+	struct linux_mlist_v0 *theres_more;
+	unsigned start_adr;
+	unsigned num_bytes;
+};
+
+struct linux_mem_v0 {
+	struct linux_mlist_v0 **v0_totphys;
+	struct linux_mlist_v0 **v0_prommap;
+	struct linux_mlist_v0 **v0_available; /* What we can use */
+};
+
+/* Arguments sent to the kernel from the boot prompt. */
+struct linux_arguments_v0 {
+	char *argv[8];
+	char args[100];
+	char boot_dev[2];
+	int boot_dev_ctrl;
+	int boot_dev_unit;
+	int dev_partition;
+	char *kernel_file_name;
+	void *aieee1;           /* XXX */
+};
+
+/* V2 and up boot things. */
+struct linux_bootargs_v2 {
+	char **bootpath;
+	char **bootargs;
+	int *fd_stdin;
+	int *fd_stdout;
+};
+
+/* The top level PROM vector. */
+struct linux_romvec {
+	/* Version numbers. */
+	unsigned int pv_magic_cookie;
+	unsigned int pv_romvers;
+	unsigned int pv_plugin_revision;
+	unsigned int pv_printrev;
+
+	/* Version 0 memory descriptors. */
+	struct linux_mem_v0 pv_v0mem;
+
+	/* Node operations. */
+	struct linux_nodeops *pv_nodeops;
+
+	char **pv_bootstr;
+	struct linux_dev_v0_funcs pv_v0devops;
+
+	char *pv_stdin;
+	char *pv_stdout;
+#define	PROMDEV_KBD	0		/* input from keyboard */
+#define	PROMDEV_SCREEN	0		/* output to screen */
+#define	PROMDEV_TTYA	1		/* in/out to ttya */
+#define	PROMDEV_TTYB	2		/* in/out to ttyb */
+
+	/* Blocking getchar/putchar.  NOT REENTRANT! (grr) */
+	int (*pv_getchar)(void);
+	void (*pv_putchar)(int ch);
+
+	/* Non-blocking variants. */
+	int (*pv_nbgetchar)(void);
+	int (*pv_nbputchar)(int ch);
+
+	void (*pv_putstr)(char *str, int len);
+
+	/* Miscellany. */
+	void (*pv_reboot)(char *bootstr);
+	void (*pv_printf)(__const__ char *fmt, ...);
+	void (*pv_abort)(void);
+	__volatile__ int *pv_ticks;
+	void (*pv_halt)(void);
+	void (**pv_synchook)(void);
+
+	/* Evaluate a forth string, not different proto for V0 and V2->up. */
+	union {
+		void (*v0_eval)(int len, char *str);
+		void (*v2_eval)(char *str);
+	} pv_fortheval;
+
+	struct linux_arguments_v0 **pv_v0bootargs;
+
+	/* Get ether address. */
+	unsigned int (*pv_enaddr)(int d, char *enaddr);
+
+	struct linux_bootargs_v2 pv_v2bootargs;
+	struct linux_dev_v2_funcs pv_v2devops;
+
+	int filler[15];
+
+	/* This one is sun4c/sun4 only. */
+	void (*pv_setctxt)(int ctxt, char *va, int pmeg);
+
+	/* Prom version 3 Multiprocessor routines. This stuff is crazy.
+	 * No joke. Calling these when there is only one cpu probably
+	 * crashes the machine, have to test this. :-)
+	 */
+
+	/* v3_cpustart() will start the cpu 'whichcpu' in mmu-context
+	 * 'thiscontext' executing at address 'prog_counter'
+	 */
+	int (*v3_cpustart)(unsigned int whichcpu, int ctxtbl_ptr,
+			   int thiscontext, char *prog_counter);
+
+	/* v3_cpustop() will cause cpu 'whichcpu' to stop executing
+	 * until a resume cpu call is made.
+	 */
+	int (*v3_cpustop)(unsigned int whichcpu);
+
+	/* v3_cpuidle() will idle cpu 'whichcpu' until a stop or
+	 * resume cpu call is made.
+	 */
+	int (*v3_cpuidle)(unsigned int whichcpu);
+
+	/* v3_cpuresume() will resume processor 'whichcpu' executing
+	 * starting with whatever 'pc' and 'npc' were left at the
+	 * last 'idle' or 'stop' call.
+	 */
+	int (*v3_cpuresume)(unsigned int whichcpu);
+};
+
+/* Routines for traversing the prom device tree. */
+struct linux_nodeops {
+	int (*no_nextnode)(int node);
+	int (*no_child)(int node);
+	int (*no_proplen)(int node, char *name);
+	int (*no_getprop)(int node, char *name, char *val);
+	int (*no_setprop)(int node, char *name, char *val, int len);
+	char * (*no_nextprop)(int node, char *name);
+};
+
+/* More fun PROM structures for device probing. */
+#define PROMREG_MAX     24
+#define PROMVADDR_MAX   16
+#define PROMINTR_MAX    32
+
+struct linux_prom_registers {
+	unsigned which_io;	/* hi part of physical address			*/
+	unsigned phys_addr;	/* The physical address of this register	*/
+	int reg_size;		/* How many bytes does this register take up?	*/
+};
+
+struct linux_prom64_registers {
+	unsigned long phys_addr;
+	unsigned long reg_size;
+};
+
+struct linux_prom_irqs {
+	int pri;    /* IRQ priority */
+	int vector; /* This is foobar, what does it do? */
+};
+
+/* Element of the "ranges" vector */
+struct linux_prom_ranges {
+	unsigned int ot_child_space;
+	unsigned int ot_child_base;		/* Bus feels this */
+	unsigned int ot_parent_space;
+	unsigned int ot_parent_base;		/* CPU looks from here */
+	unsigned int or_size;
+};
+
+struct linux_prom64_ranges {
+	unsigned long ot_child_base;		/* Bus feels this */
+	unsigned long ot_parent_base;		/* CPU looks from here */
+	unsigned long or_size;
+};
+
+/* Ranges and reg properties are a bit different for PCI. */
+struct linux_prom_pci_registers {
+	unsigned int phys_hi;
+	unsigned int phys_mid;
+	unsigned int phys_lo;
+
+	unsigned int size_hi;
+	unsigned int size_lo;
+};
+
+struct linux_prom_pci_ranges {
+	unsigned int child_phys_hi;	/* Only certain bits are encoded here. */
+	unsigned int child_phys_mid;
+	unsigned int child_phys_lo;
+
+	unsigned int parent_phys_hi;
+	unsigned int parent_phys_lo;
+
+	unsigned int size_hi;
+	unsigned int size_lo;
+};
+
+struct linux_prom_pci_intmap {
+	unsigned int phys_hi;
+	unsigned int phys_mid;
+	unsigned int phys_lo;
+
+	unsigned int interrupt;
+
+	int          cnode;
+	unsigned int cinterrupt;
+};
+
+struct linux_prom_pci_intmask {
+	unsigned int phys_hi;
+	unsigned int phys_mid;
+	unsigned int phys_lo;
+	unsigned int interrupt;
+};
+
+struct linux_prom_ebus_ranges {
+	unsigned int child_phys_hi;
+	unsigned int child_phys_lo;
+
+	unsigned int parent_phys_hi;
+	unsigned int parent_phys_mid;
+	unsigned int parent_phys_lo;
+
+	unsigned int size;
+};
+
+struct linux_prom_ebus_intmap {
+	unsigned int phys_hi;
+	unsigned int phys_lo;
+
+	unsigned int interrupt;
+
+	int          cnode;
+	unsigned int cinterrupt;
+};
+
+struct linux_prom_ebus_intmask {
+	unsigned int phys_hi;
+	unsigned int phys_lo;
+	unsigned int interrupt;
+};
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__SPARC64_OPENPROM_H) */
diff --git a/include/asm-sparc/oplib.h b/include/asm-sparc/oplib.h
index 61c3ca6..e88d7c0 100644
--- a/include/asm-sparc/oplib.h
+++ b/include/asm-sparc/oplib.h
@@ -1,273 +1,8 @@
-/*
- * oplib.h:  Describes the interface and available routines in the
- *           Linux Prom library.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef __SPARC_OPLIB_H
-#define __SPARC_OPLIB_H
-
-#include <asm/openprom.h>
-#include <linux/spinlock.h>
-#include <linux/compiler.h>
-
-/* The master romvec pointer... */
-extern struct linux_romvec *romvec;
-
-/* Enumeration to describe the prom major version we have detected. */
-enum prom_major_version {
-	PROM_V0,      /* Original sun4c V0 prom */
-	PROM_V2,      /* sun4c and early sun4m V2 prom */
-	PROM_V3,      /* sun4m and later, up to sun4d/sun4e machines V3 */
-	PROM_P1275,   /* IEEE compliant ISA based Sun PROM, only sun4u */
-        PROM_AP1000,  /* actually no prom at all */
-	PROM_SUN4,    /* Old sun4 proms are totally different, but we'll shoehorn it to make it fit */
-};
-
-extern enum prom_major_version prom_vers;
-/* Revision, and firmware revision. */
-extern unsigned int prom_rev, prom_prev;
-
-/* Root node of the prom device tree, this stays constant after
- * initialization is complete.
- */
-extern int prom_root_node;
-
-/* Pointer to prom structure containing the device tree traversal
- * and usage utility functions.  Only prom-lib should use these,
- * users use the interface defined by the library only!
- */
-extern struct linux_nodeops *prom_nodeops;
-
-/* The functions... */
-
-/* You must call prom_init() before using any of the library services,
- * preferably as early as possible.  Pass it the romvec pointer.
- */
-extern void prom_init(struct linux_romvec *rom_ptr);
-
-/* Boot argument acquisition, returns the boot command line string. */
-extern char *prom_getbootargs(void);
-
-/* Device utilities. */
-
-/* Map and unmap devices in IO space at virtual addresses. Note that the
- * virtual address you pass is a request and the prom may put your mappings
- * somewhere else, so check your return value as that is where your new
- * mappings really are!
- *
- * Another note, these are only available on V2 or higher proms!
- */
-extern char *prom_mapio(char *virt_hint, int io_space, unsigned int phys_addr, unsigned int num_bytes);
-extern void prom_unmapio(char *virt_addr, unsigned int num_bytes);
-
-/* Device operations. */
-
-/* Open the device described by the passed string.  Note, that the format
- * of the string is different on V0 vs. V2->higher proms.  The caller must
- * know what he/she is doing!  Returns the device descriptor, an int.
- */
-extern int prom_devopen(char *device_string);
-
-/* Close a previously opened device described by the passed integer
- * descriptor.
- */
-extern int prom_devclose(int device_handle);
-
-/* Do a seek operation on the device described by the passed integer
- * descriptor.
- */
-extern void prom_seek(int device_handle, unsigned int seek_hival,
-		      unsigned int seek_lowval);
-
-/* Miscellaneous routines, don't really fit in any category per se. */
-
-/* Reboot the machine with the command line passed. */
-extern void prom_reboot(char *boot_command);
-
-/* Evaluate the forth string passed. */
-extern void prom_feval(char *forth_string);
-
-/* Enter the prom, with possibility of continuation with the 'go'
- * command in newer proms.
- */
-extern void prom_cmdline(void);
-
-/* Enter the prom, with no chance of continuation for the stand-alone
- * which calls this.
- */
-extern void prom_halt(void) __attribute__ ((noreturn));
-
-/* Set the PROM 'sync' callback function to the passed function pointer.
- * When the user gives the 'sync' command at the prom prompt while the
- * kernel is still active, the prom will call this routine.
- *
- * XXX The arguments are different on V0 vs. V2->higher proms, grrr! XXX
- */
-typedef void (*sync_func_t)(void);
-extern void prom_setsync(sync_func_t func_ptr);
-
-/* Acquire the IDPROM of the root node in the prom device tree.  This
- * gets passed a buffer where you would like it stuffed.  The return value
- * is the format type of this idprom or 0xff on error.
- */
-extern unsigned char prom_get_idprom(char *idp_buffer, int idpbuf_size);
-
-/* Get the prom major version. */
-extern int prom_version(void);
-
-/* Get the prom plugin revision. */
-extern int prom_getrev(void);
-
-/* Get the prom firmware revision. */
-extern int prom_getprev(void);
-
-/* Character operations to/from the console.... */
-
-/* Non-blocking get character from console. */
-extern int prom_nbgetchar(void);
-
-/* Non-blocking put character to console. */
-extern int prom_nbputchar(char character);
-
-/* Blocking get character from console. */
-extern char prom_getchar(void);
-
-/* Blocking put character to console. */
-extern void prom_putchar(char character);
-
-/* Prom's internal routines, don't use in kernel/boot code. */
-extern void prom_printf(char *fmt, ...);
-extern void prom_write(const char *buf, unsigned int len);
-
-/* Multiprocessor operations... */
-
-/* Start the CPU with the given device tree node, context table, and context
- * at the passed program counter.
- */
-extern int prom_startcpu(int cpunode, struct linux_prom_registers *context_table,
-			 int context, char *program_counter);
-
-/* Stop the CPU with the passed device tree node. */
-extern int prom_stopcpu(int cpunode);
-
-/* Idle the CPU with the passed device tree node. */
-extern int prom_idlecpu(int cpunode);
-
-/* Re-Start the CPU with the passed device tree node. */
-extern int prom_restartcpu(int cpunode);
-
-/* PROM memory allocation facilities... */
-
-/* Allocated at possibly the given virtual address a chunk of the
- * indicated size.
- */
-extern char *prom_alloc(char *virt_hint, unsigned int size);
-
-/* Free a previously allocated chunk. */
-extern void prom_free(char *virt_addr, unsigned int size);
-
-/* Sun4/sun4c specific memory-management startup hook. */
-
-/* Map the passed segment in the given context at the passed
- * virtual address.
- */
-extern void prom_putsegment(int context, unsigned long virt_addr,
-			    int physical_segment);
-
-
-/* PROM device tree traversal functions... */
-
-#ifdef PROMLIB_INTERNAL
-
-/* Internal version of prom_getchild. */
-extern int __prom_getchild(int parent_node);
-
-/* Internal version of prom_getsibling. */
-extern int __prom_getsibling(int node);
-
+#ifndef ___ASM_SPARC_OPLIB_H
+#define ___ASM_SPARC_OPLIB_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/oplib_64.h>
+#else
+#include <asm-sparc/oplib_32.h>
 #endif
-
-
-/* Get the child node of the given node, or zero if no child exists. */
-extern int prom_getchild(int parent_node);
-
-/* Get the next sibling node of the given node, or zero if no further
- * siblings exist.
- */
-extern int prom_getsibling(int node);
-
-/* Get the length, at the passed node, of the given property type.
- * Returns -1 on error (ie. no such property at this node).
- */
-extern int prom_getproplen(int thisnode, char *property);
-
-/* Fetch the requested property using the given buffer.  Returns
- * the number of bytes the prom put into your buffer or -1 on error.
- */
-extern int __must_check prom_getproperty(int thisnode, char *property,
-					 char *prop_buffer, int propbuf_size);
-
-/* Acquire an integer property. */
-extern int prom_getint(int node, char *property);
-
-/* Acquire an integer property, with a default value. */
-extern int prom_getintdefault(int node, char *property, int defval);
-
-/* Acquire a boolean property, 0=FALSE 1=TRUE. */
-extern int prom_getbool(int node, char *prop);
-
-/* Acquire a string property, null string on error. */
-extern void prom_getstring(int node, char *prop, char *buf, int bufsize);
-
-/* Does the passed node have the given "name"? YES=1 NO=0 */
-extern int prom_nodematch(int thisnode, char *name);
-
-/* Search all siblings starting at the passed node for "name" matching
- * the given string.  Returns the node on success, zero on failure.
- */
-extern int prom_searchsiblings(int node_start, char *name);
-
-/* Return the first property type, as a string, for the given node.
- * Returns a null string on error.
- */
-extern char *prom_firstprop(int node, char *buffer);
-
-/* Returns the next property after the passed property for the given
- * node.  Returns null string on failure.
- */
-extern char *prom_nextprop(int node, char *prev_property, char *buffer);
-
-/* Returns phandle of the path specified */
-extern int prom_finddevice(char *name);
-
-/* Returns 1 if the specified node has given property. */
-extern int prom_node_has_property(int node, char *property);
-
-/* Set the indicated property at the given node with the passed value.
- * Returns the number of bytes of your value that the prom took.
- */
-extern int prom_setprop(int node, char *prop_name, char *prop_value,
-			int value_size);
-			
-extern int prom_pathtoinode(char *path);
-extern int prom_inst2pkg(int);
-
-/* Dorking with Bus ranges... */
-
-/* Apply promlib probes OBIO ranges to registers. */
-extern void prom_apply_obio_ranges(struct linux_prom_registers *obioregs, int nregs);
-
-/* Apply ranges of any prom node (and optionally parent node as well) to registers. */
-extern void prom_apply_generic_ranges(int node, int parent, 
-				      struct linux_prom_registers *sbusregs, int nregs);
-
-/* CPU probing helpers.  */
-int cpu_find_by_instance(int instance, int *prom_node, int *mid);
-int cpu_find_by_mid(int mid, int *prom_node);
-int cpu_get_hwmid(int prom_node);
-
-extern spinlock_t prom_lock;
-
-#endif /* !(__SPARC_OPLIB_H) */
+#endif
diff --git a/include/asm-sparc/oplib_32.h b/include/asm-sparc/oplib_32.h
new file mode 100644
index 0000000..b2631da
--- /dev/null
+++ b/include/asm-sparc/oplib_32.h
@@ -0,0 +1,272 @@
+/*
+ * oplib.h:  Describes the interface and available routines in the
+ *           Linux Prom library.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef __SPARC_OPLIB_H
+#define __SPARC_OPLIB_H
+
+#include <asm/openprom.h>
+#include <linux/spinlock.h>
+#include <linux/compiler.h>
+
+/* The master romvec pointer... */
+extern struct linux_romvec *romvec;
+
+/* Enumeration to describe the prom major version we have detected. */
+enum prom_major_version {
+	PROM_V0,      /* Original sun4c V0 prom */
+	PROM_V2,      /* sun4c and early sun4m V2 prom */
+	PROM_V3,      /* sun4m and later, up to sun4d/sun4e machines V3 */
+	PROM_P1275,   /* IEEE compliant ISA based Sun PROM, only sun4u */
+	PROM_SUN4,    /* Old sun4 proms are totally different, but we'll shoehorn it to make it fit */
+};
+
+extern enum prom_major_version prom_vers;
+/* Revision, and firmware revision. */
+extern unsigned int prom_rev, prom_prev;
+
+/* Root node of the prom device tree, this stays constant after
+ * initialization is complete.
+ */
+extern int prom_root_node;
+
+/* Pointer to prom structure containing the device tree traversal
+ * and usage utility functions.  Only prom-lib should use these,
+ * users use the interface defined by the library only!
+ */
+extern struct linux_nodeops *prom_nodeops;
+
+/* The functions... */
+
+/* You must call prom_init() before using any of the library services,
+ * preferably as early as possible.  Pass it the romvec pointer.
+ */
+extern void prom_init(struct linux_romvec *rom_ptr);
+
+/* Boot argument acquisition, returns the boot command line string. */
+extern char *prom_getbootargs(void);
+
+/* Device utilities. */
+
+/* Map and unmap devices in IO space at virtual addresses. Note that the
+ * virtual address you pass is a request and the prom may put your mappings
+ * somewhere else, so check your return value as that is where your new
+ * mappings really are!
+ *
+ * Another note, these are only available on V2 or higher proms!
+ */
+extern char *prom_mapio(char *virt_hint, int io_space, unsigned int phys_addr, unsigned int num_bytes);
+extern void prom_unmapio(char *virt_addr, unsigned int num_bytes);
+
+/* Device operations. */
+
+/* Open the device described by the passed string.  Note, that the format
+ * of the string is different on V0 vs. V2->higher proms.  The caller must
+ * know what he/she is doing!  Returns the device descriptor, an int.
+ */
+extern int prom_devopen(char *device_string);
+
+/* Close a previously opened device described by the passed integer
+ * descriptor.
+ */
+extern int prom_devclose(int device_handle);
+
+/* Do a seek operation on the device described by the passed integer
+ * descriptor.
+ */
+extern void prom_seek(int device_handle, unsigned int seek_hival,
+		      unsigned int seek_lowval);
+
+/* Miscellaneous routines, don't really fit in any category per se. */
+
+/* Reboot the machine with the command line passed. */
+extern void prom_reboot(char *boot_command);
+
+/* Evaluate the forth string passed. */
+extern void prom_feval(char *forth_string);
+
+/* Enter the prom, with possibility of continuation with the 'go'
+ * command in newer proms.
+ */
+extern void prom_cmdline(void);
+
+/* Enter the prom, with no chance of continuation for the stand-alone
+ * which calls this.
+ */
+extern void prom_halt(void) __attribute__ ((noreturn));
+
+/* Set the PROM 'sync' callback function to the passed function pointer.
+ * When the user gives the 'sync' command at the prom prompt while the
+ * kernel is still active, the prom will call this routine.
+ *
+ * XXX The arguments are different on V0 vs. V2->higher proms, grrr! XXX
+ */
+typedef void (*sync_func_t)(void);
+extern void prom_setsync(sync_func_t func_ptr);
+
+/* Acquire the IDPROM of the root node in the prom device tree.  This
+ * gets passed a buffer where you would like it stuffed.  The return value
+ * is the format type of this idprom or 0xff on error.
+ */
+extern unsigned char prom_get_idprom(char *idp_buffer, int idpbuf_size);
+
+/* Get the prom major version. */
+extern int prom_version(void);
+
+/* Get the prom plugin revision. */
+extern int prom_getrev(void);
+
+/* Get the prom firmware revision. */
+extern int prom_getprev(void);
+
+/* Character operations to/from the console.... */
+
+/* Non-blocking get character from console. */
+extern int prom_nbgetchar(void);
+
+/* Non-blocking put character to console. */
+extern int prom_nbputchar(char character);
+
+/* Blocking get character from console. */
+extern char prom_getchar(void);
+
+/* Blocking put character to console. */
+extern void prom_putchar(char character);
+
+/* Prom's internal routines, don't use in kernel/boot code. */
+extern void prom_printf(char *fmt, ...);
+extern void prom_write(const char *buf, unsigned int len);
+
+/* Multiprocessor operations... */
+
+/* Start the CPU with the given device tree node, context table, and context
+ * at the passed program counter.
+ */
+extern int prom_startcpu(int cpunode, struct linux_prom_registers *context_table,
+			 int context, char *program_counter);
+
+/* Stop the CPU with the passed device tree node. */
+extern int prom_stopcpu(int cpunode);
+
+/* Idle the CPU with the passed device tree node. */
+extern int prom_idlecpu(int cpunode);
+
+/* Re-Start the CPU with the passed device tree node. */
+extern int prom_restartcpu(int cpunode);
+
+/* PROM memory allocation facilities... */
+
+/* Allocated at possibly the given virtual address a chunk of the
+ * indicated size.
+ */
+extern char *prom_alloc(char *virt_hint, unsigned int size);
+
+/* Free a previously allocated chunk. */
+extern void prom_free(char *virt_addr, unsigned int size);
+
+/* Sun4/sun4c specific memory-management startup hook. */
+
+/* Map the passed segment in the given context at the passed
+ * virtual address.
+ */
+extern void prom_putsegment(int context, unsigned long virt_addr,
+			    int physical_segment);
+
+
+/* PROM device tree traversal functions... */
+
+#ifdef PROMLIB_INTERNAL
+
+/* Internal version of prom_getchild. */
+extern int __prom_getchild(int parent_node);
+
+/* Internal version of prom_getsibling. */
+extern int __prom_getsibling(int node);
+
+#endif
+
+
+/* Get the child node of the given node, or zero if no child exists. */
+extern int prom_getchild(int parent_node);
+
+/* Get the next sibling node of the given node, or zero if no further
+ * siblings exist.
+ */
+extern int prom_getsibling(int node);
+
+/* Get the length, at the passed node, of the given property type.
+ * Returns -1 on error (ie. no such property at this node).
+ */
+extern int prom_getproplen(int thisnode, char *property);
+
+/* Fetch the requested property using the given buffer.  Returns
+ * the number of bytes the prom put into your buffer or -1 on error.
+ */
+extern int __must_check prom_getproperty(int thisnode, char *property,
+					 char *prop_buffer, int propbuf_size);
+
+/* Acquire an integer property. */
+extern int prom_getint(int node, char *property);
+
+/* Acquire an integer property, with a default value. */
+extern int prom_getintdefault(int node, char *property, int defval);
+
+/* Acquire a boolean property, 0=FALSE 1=TRUE. */
+extern int prom_getbool(int node, char *prop);
+
+/* Acquire a string property, null string on error. */
+extern void prom_getstring(int node, char *prop, char *buf, int bufsize);
+
+/* Does the passed node have the given "name"? YES=1 NO=0 */
+extern int prom_nodematch(int thisnode, char *name);
+
+/* Search all siblings starting at the passed node for "name" matching
+ * the given string.  Returns the node on success, zero on failure.
+ */
+extern int prom_searchsiblings(int node_start, char *name);
+
+/* Return the first property type, as a string, for the given node.
+ * Returns a null string on error.
+ */
+extern char *prom_firstprop(int node, char *buffer);
+
+/* Returns the next property after the passed property for the given
+ * node.  Returns null string on failure.
+ */
+extern char *prom_nextprop(int node, char *prev_property, char *buffer);
+
+/* Returns phandle of the path specified */
+extern int prom_finddevice(char *name);
+
+/* Returns 1 if the specified node has given property. */
+extern int prom_node_has_property(int node, char *property);
+
+/* Set the indicated property at the given node with the passed value.
+ * Returns the number of bytes of your value that the prom took.
+ */
+extern int prom_setprop(int node, char *prop_name, char *prop_value,
+			int value_size);
+
+extern int prom_pathtoinode(char *path);
+extern int prom_inst2pkg(int);
+
+/* Dorking with Bus ranges... */
+
+/* Apply promlib probes OBIO ranges to registers. */
+extern void prom_apply_obio_ranges(struct linux_prom_registers *obioregs, int nregs);
+
+/* Apply ranges of any prom node (and optionally parent node as well) to registers. */
+extern void prom_apply_generic_ranges(int node, int parent,
+				      struct linux_prom_registers *sbusregs, int nregs);
+
+/* CPU probing helpers.  */
+int cpu_find_by_instance(int instance, int *prom_node, int *mid);
+int cpu_find_by_mid(int mid, int *prom_node);
+int cpu_get_hwmid(int prom_node);
+
+extern spinlock_t prom_lock;
+
+#endif /* !(__SPARC_OPLIB_H) */
diff --git a/include/asm-sparc/oplib_64.h b/include/asm-sparc/oplib_64.h
new file mode 100644
index 0000000..6d2c2ca
--- /dev/null
+++ b/include/asm-sparc/oplib_64.h
@@ -0,0 +1,322 @@
+/* oplib.h:  Describes the interface and available routines in the
+ *           Linux Prom library.
+ *
+ * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#ifndef __SPARC64_OPLIB_H
+#define __SPARC64_OPLIB_H
+
+#include <asm/openprom.h>
+
+/* OBP version string. */
+extern char prom_version[];
+
+/* Root node of the prom device tree, this stays constant after
+ * initialization is complete.
+ */
+extern int prom_root_node;
+
+/* PROM stdin and stdout */
+extern int prom_stdin, prom_stdout;
+
+/* /chosen node of the prom device tree, this stays constant after
+ * initialization is complete.
+ */
+extern int prom_chosen_node;
+
+/* Helper values and strings in arch/sparc64/kernel/head.S */
+extern const char prom_peer_name[];
+extern const char prom_compatible_name[];
+extern const char prom_root_compatible[];
+extern const char prom_cpu_compatible[];
+extern const char prom_finddev_name[];
+extern const char prom_chosen_path[];
+extern const char prom_cpu_path[];
+extern const char prom_getprop_name[];
+extern const char prom_mmu_name[];
+extern const char prom_callmethod_name[];
+extern const char prom_translate_name[];
+extern const char prom_map_name[];
+extern const char prom_unmap_name[];
+extern int prom_mmu_ihandle_cache;
+extern unsigned int prom_boot_mapped_pc;
+extern unsigned int prom_boot_mapping_mode;
+extern unsigned long prom_boot_mapping_phys_high, prom_boot_mapping_phys_low;
+
+struct linux_mlist_p1275 {
+	struct linux_mlist_p1275 *theres_more;
+	unsigned long start_adr;
+	unsigned long num_bytes;
+};
+
+struct linux_mem_p1275 {
+	struct linux_mlist_p1275 **p1275_totphys;
+	struct linux_mlist_p1275 **p1275_prommap;
+	struct linux_mlist_p1275 **p1275_available; /* What we can use */
+};
+
+/* The functions... */
+
+/* You must call prom_init() before using any of the library services,
+ * preferably as early as possible.  Pass it the romvec pointer.
+ */
+extern void prom_init(void *cif_handler, void *cif_stack);
+
+/* Boot argument acquisition, returns the boot command line string. */
+extern char *prom_getbootargs(void);
+
+/* Device utilities. */
+
+/* Device operations. */
+
+/* Open the device described by the passed string.  Note, that the format
+ * of the string is different on V0 vs. V2->higher proms.  The caller must
+ * know what he/she is doing!  Returns the device descriptor, an int.
+ */
+extern int prom_devopen(const char *device_string);
+
+/* Close a previously opened device described by the passed integer
+ * descriptor.
+ */
+extern int prom_devclose(int device_handle);
+
+/* Do a seek operation on the device described by the passed integer
+ * descriptor.
+ */
+extern void prom_seek(int device_handle, unsigned int seek_hival,
+		      unsigned int seek_lowval);
+
+/* Miscellaneous routines, don't really fit in any category per se. */
+
+/* Reboot the machine with the command line passed. */
+extern void prom_reboot(const char *boot_command);
+
+/* Evaluate the forth string passed. */
+extern void prom_feval(const char *forth_string);
+
+/* Enter the prom, with possibility of continuation with the 'go'
+ * command in newer proms.
+ */
+extern void prom_cmdline(void);
+
+/* Enter the prom, with no chance of continuation for the stand-alone
+ * which calls this.
+ */
+extern void prom_halt(void) __attribute__ ((noreturn));
+
+/* Halt and power-off the machine. */
+extern void prom_halt_power_off(void) __attribute__ ((noreturn));
+
+/* Set the PROM 'sync' callback function to the passed function pointer.
+ * When the user gives the 'sync' command at the prom prompt while the
+ * kernel is still active, the prom will call this routine.
+ *
+ */
+typedef int (*callback_func_t)(long *cmd);
+extern void prom_setcallback(callback_func_t func_ptr);
+
+/* Acquire the IDPROM of the root node in the prom device tree.  This
+ * gets passed a buffer where you would like it stuffed.  The return value
+ * is the format type of this idprom or 0xff on error.
+ */
+extern unsigned char prom_get_idprom(char *idp_buffer, int idpbuf_size);
+
+/* Character operations to/from the console.... */
+
+/* Non-blocking get character from console. */
+extern int prom_nbgetchar(void);
+
+/* Non-blocking put character to console. */
+extern int prom_nbputchar(char character);
+
+/* Blocking get character from console. */
+extern char prom_getchar(void);
+
+/* Blocking put character to console. */
+extern void prom_putchar(char character);
+
+/* Prom's internal routines, don't use in kernel/boot code. */
+extern void prom_printf(const char *fmt, ...);
+extern void prom_write(const char *buf, unsigned int len);
+
+/* Multiprocessor operations... */
+#ifdef CONFIG_SMP
+/* Start the CPU with the given device tree node at the passed program
+ * counter with the given arg passed in via register %o0.
+ */
+extern void prom_startcpu(int cpunode, unsigned long pc, unsigned long arg);
+
+/* Start the CPU with the given cpu ID at the passed program
+ * counter with the given arg passed in via register %o0.
+ */
+extern void prom_startcpu_cpuid(int cpuid, unsigned long pc, unsigned long arg);
+
+/* Stop the CPU with the given cpu ID.  */
+extern void prom_stopcpu_cpuid(int cpuid);
+
+/* Stop the current CPU. */
+extern void prom_stopself(void);
+
+/* Idle the current CPU. */
+extern void prom_idleself(void);
+
+/* Resume the CPU with the passed device tree node. */
+extern void prom_resumecpu(int cpunode);
+#endif
+
+/* Power management interfaces. */
+
+/* Put the current CPU to sleep. */
+extern void prom_sleepself(void);
+
+/* Put the entire system to sleep. */
+extern int prom_sleepsystem(void);
+
+/* Initiate a wakeup event. */
+extern int prom_wakeupsystem(void);
+
+/* MMU and memory related OBP interfaces. */
+
+/* Get unique string identifying SIMM at given physical address. */
+extern int prom_getunumber(int syndrome_code,
+			   unsigned long phys_addr,
+			   char *buf, int buflen);
+
+/* Retain physical memory to the caller across soft resets. */
+extern unsigned long prom_retain(const char *name,
+				 unsigned long pa_low, unsigned long pa_high,
+				 long size, long align);
+
+/* Load explicit I/D TLB entries into the calling processor. */
+extern long prom_itlb_load(unsigned long index,
+			   unsigned long tte_data,
+			   unsigned long vaddr);
+
+extern long prom_dtlb_load(unsigned long index,
+			   unsigned long tte_data,
+			   unsigned long vaddr);
+
+/* Map/Unmap client program address ranges.  First the format of
+ * the mapping mode argument.
+ */
+#define PROM_MAP_WRITE	0x0001 /* Writable */
+#define PROM_MAP_READ	0x0002 /* Readable - sw */
+#define PROM_MAP_EXEC	0x0004 /* Executable - sw */
+#define PROM_MAP_LOCKED	0x0010 /* Locked, use i/dtlb load calls for this instead */
+#define PROM_MAP_CACHED	0x0020 /* Cacheable in both L1 and L2 caches */
+#define PROM_MAP_SE	0x0040 /* Side-Effects */
+#define PROM_MAP_GLOB	0x0080 /* Global */
+#define PROM_MAP_IE	0x0100 /* Invert-Endianness */
+#define PROM_MAP_DEFAULT (PROM_MAP_WRITE | PROM_MAP_READ | PROM_MAP_EXEC | PROM_MAP_CACHED)
+
+extern int prom_map(int mode, unsigned long size,
+		    unsigned long vaddr, unsigned long paddr);
+extern void prom_unmap(unsigned long size, unsigned long vaddr);
+
+
+/* PROM device tree traversal functions... */
+
+#ifdef PROMLIB_INTERNAL
+
+/* Internal version of prom_getchild. */
+extern int __prom_getchild(int parent_node);
+
+/* Internal version of prom_getsibling. */
+extern int __prom_getsibling(int node);
+
+#endif
+
+/* Get the child node of the given node, or zero if no child exists. */
+extern int prom_getchild(int parent_node);
+
+/* Get the next sibling node of the given node, or zero if no further
+ * siblings exist.
+ */
+extern int prom_getsibling(int node);
+
+/* Get the length, at the passed node, of the given property type.
+ * Returns -1 on error (ie. no such property at this node).
+ */
+extern int prom_getproplen(int thisnode, const char *property);
+
+/* Fetch the requested property using the given buffer.  Returns
+ * the number of bytes the prom put into your buffer or -1 on error.
+ */
+extern int prom_getproperty(int thisnode, const char *property,
+			    char *prop_buffer, int propbuf_size);
+
+/* Acquire an integer property. */
+extern int prom_getint(int node, const char *property);
+
+/* Acquire an integer property, with a default value. */
+extern int prom_getintdefault(int node, const char *property, int defval);
+
+/* Acquire a boolean property, 0=FALSE 1=TRUE. */
+extern int prom_getbool(int node, const char *prop);
+
+/* Acquire a string property, null string on error. */
+extern void prom_getstring(int node, const char *prop, char *buf, int bufsize);
+
+/* Does the passed node have the given "name"? YES=1 NO=0 */
+extern int prom_nodematch(int thisnode, const char *name);
+
+/* Search all siblings starting at the passed node for "name" matching
+ * the given string.  Returns the node on success, zero on failure.
+ */
+extern int prom_searchsiblings(int node_start, const char *name);
+
+/* Return the first property type, as a string, for the given node.
+ * Returns a null string on error. Buffer should be at least 32B long.
+ */
+extern char *prom_firstprop(int node, char *buffer);
+
+/* Returns the next property after the passed property for the given
+ * node.  Returns null string on failure. Buffer should be at least 32B long.
+ */
+extern char *prom_nextprop(int node, const char *prev_property, char *buffer);
+
+/* Returns 1 if the specified node has given property. */
+extern int prom_node_has_property(int node, const char *property);
+
+/* Returns phandle of the path specified */
+extern int prom_finddevice(const char *name);
+
+/* Set the indicated property at the given node with the passed value.
+ * Returns the number of bytes of your value that the prom took.
+ */
+extern int prom_setprop(int node, const char *prop_name, char *prop_value,
+			int value_size);
+
+extern int prom_pathtoinode(const char *path);
+extern int prom_inst2pkg(int);
+extern int prom_service_exists(const char *service_name);
+extern void prom_sun4v_guest_soft_state(void);
+
+extern int prom_ihandle2path(int handle, char *buffer, int bufsize);
+
+/* Client interface level routines. */
+extern long p1275_cmd(const char *, long, ...);
+
+#if 0
+#define P1275_SIZE(x) ((((long)((x) / 32)) << 32) | (x))
+#else
+#define P1275_SIZE(x) x
+#endif
+
+/* We support at most 16 input and 1 output argument */
+#define P1275_ARG_NUMBER		0
+#define P1275_ARG_IN_STRING		1
+#define P1275_ARG_OUT_BUF		2
+#define P1275_ARG_OUT_32B		3
+#define P1275_ARG_IN_FUNCTION		4
+#define P1275_ARG_IN_BUF		5
+#define P1275_ARG_IN_64B		6
+
+#define P1275_IN(x) ((x) & 0xf)
+#define P1275_OUT(x) (((x) << 4) & 0xf0)
+#define P1275_INOUT(i,o) (P1275_IN(i)|P1275_OUT(o))
+#define P1275_ARG(n,x) ((x) << ((n)*3 + 8))
+
+#endif /* !(__SPARC64_OPLIB_H) */
diff --git a/include/asm-sparc/page.h b/include/asm-sparc/page.h
index 6aa9e4c..f32f49f 100644
--- a/include/asm-sparc/page.h
+++ b/include/asm-sparc/page.h
@@ -1,165 +1,8 @@
-/*
- * page.h:  Various defines and such for MMU operations on the Sparc for
- *          the Linux kernel.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef _SPARC_PAGE_H
-#define _SPARC_PAGE_H
-
-#ifdef CONFIG_SUN4
-#define PAGE_SHIFT   13
+#ifndef ___ASM_SPARC_PAGE_H
+#define ___ASM_SPARC_PAGE_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/page_64.h>
 #else
-#define PAGE_SHIFT   12
+#include <asm-sparc/page_32.h>
 #endif
-#ifndef __ASSEMBLY__
-/* I have my suspicions... -DaveM */
-#define PAGE_SIZE    (1UL << PAGE_SHIFT)
-#else
-#define PAGE_SIZE    (1 << PAGE_SHIFT)
 #endif
-#define PAGE_MASK    (~(PAGE_SIZE-1))
-
-#include <asm/btfixup.h>
-
-#ifndef __ASSEMBLY__
-
-#define clear_page(page)	 memset((void *)(page), 0, PAGE_SIZE)
-#define copy_page(to,from) 	memcpy((void *)(to), (void *)(from), PAGE_SIZE)
-#define clear_user_page(addr, vaddr, page)	\
-	do { 	clear_page(addr);		\
-		sparc_flush_page_to_ram(page);	\
-	} while (0)
-#define copy_user_page(to, from, vaddr, page)	\
-	do {	copy_page(to, from);		\
-		sparc_flush_page_to_ram(page);	\
-	} while (0)
-
-/* The following structure is used to hold the physical
- * memory configuration of the machine.  This is filled in
- * prom_meminit() and is later used by mem_init() to set up
- * mem_map[].  We statically allocate SPARC_PHYS_BANKS+1 of
- * these structs, this is arbitrary.  The entry after the
- * last valid one has num_bytes==0.
- */
-struct sparc_phys_banks {
-  unsigned long base_addr;
-  unsigned long num_bytes;
-};
-
-#define SPARC_PHYS_BANKS 32
-
-extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS+1];
-
-/* Cache alias structure.  Entry is valid if context != -1. */
-struct cache_palias {
-	unsigned long vaddr;
-	int context;
-};
-
-extern struct cache_palias *sparc_aliases;
-
-/* passing structs on the Sparc slow us down tremendously... */
-
-/* #define STRICT_MM_TYPECHECKS */
-
-#ifdef STRICT_MM_TYPECHECKS
-/*
- * These are used to make use of C type-checking..
- */
-typedef struct { unsigned long pte; } pte_t;
-typedef struct { unsigned long iopte; } iopte_t;
-typedef struct { unsigned long pmdv[16]; } pmd_t;
-typedef struct { unsigned long pgd; } pgd_t;
-typedef struct { unsigned long ctxd; } ctxd_t;
-typedef struct { unsigned long pgprot; } pgprot_t;
-typedef struct { unsigned long iopgprot; } iopgprot_t;
-
-#define pte_val(x)	((x).pte)
-#define iopte_val(x)	((x).iopte)
-#define pmd_val(x)      ((x).pmdv[0])
-#define pgd_val(x)	((x).pgd)
-#define ctxd_val(x)	((x).ctxd)
-#define pgprot_val(x)	((x).pgprot)
-#define iopgprot_val(x)	((x).iopgprot)
-
-#define __pte(x)	((pte_t) { (x) } )
-#define __iopte(x)	((iopte_t) { (x) } )
-/* #define __pmd(x)        ((pmd_t) { (x) } ) */ /* XXX procedure with loop */
-#define __pgd(x)	((pgd_t) { (x) } )
-#define __ctxd(x)	((ctxd_t) { (x) } )
-#define __pgprot(x)	((pgprot_t) { (x) } )
-#define __iopgprot(x)	((iopgprot_t) { (x) } )
-
-#else
-/*
- * .. while these make it easier on the compiler
- */
-typedef unsigned long pte_t;
-typedef unsigned long iopte_t;
-typedef struct { unsigned long pmdv[16]; } pmd_t;
-typedef unsigned long pgd_t;
-typedef unsigned long ctxd_t;
-typedef unsigned long pgprot_t;
-typedef unsigned long iopgprot_t;
-
-#define pte_val(x)	(x)
-#define iopte_val(x)	(x)
-#define pmd_val(x)      ((x).pmdv[0])
-#define pgd_val(x)	(x)
-#define ctxd_val(x)	(x)
-#define pgprot_val(x)	(x)
-#define iopgprot_val(x)	(x)
-
-#define __pte(x)	(x)
-#define __iopte(x)	(x)
-/* #define __pmd(x)        (x) */ /* XXX later */
-#define __pgd(x)	(x)
-#define __ctxd(x)	(x)
-#define __pgprot(x)	(x)
-#define __iopgprot(x)	(x)
-
-#endif
-
-typedef struct page *pgtable_t;
-
-extern unsigned long sparc_unmapped_base;
-
-BTFIXUPDEF_SETHI(sparc_unmapped_base)
-
-#define TASK_UNMAPPED_BASE	BTFIXUP_SETHI(sparc_unmapped_base)
-
-#else /* !(__ASSEMBLY__) */
-
-#define __pgprot(x)	(x)
-
-#endif /* !(__ASSEMBLY__) */
-
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)  (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
-#define PAGE_OFFSET	0xf0000000
-#ifndef __ASSEMBLY__
-extern unsigned long phys_base;
-extern unsigned long pfn_base;
-#endif
-#define __pa(x)			((unsigned long)(x) - PAGE_OFFSET + phys_base)
-#define __va(x)			((void *)((unsigned long) (x) - phys_base + PAGE_OFFSET))
-
-#define virt_to_phys		__pa
-#define phys_to_virt		__va
-
-#define ARCH_PFN_OFFSET		(pfn_base)
-#define virt_to_page(kaddr)	(mem_map + ((((unsigned long)(kaddr)-PAGE_OFFSET)>>PAGE_SHIFT)))
-
-#define pfn_valid(pfn)		(((pfn) >= (pfn_base)) && (((pfn)-(pfn_base)) < max_mapnr))
-#define virt_addr_valid(kaddr)	((((unsigned long)(kaddr)-PAGE_OFFSET)>>PAGE_SHIFT) < max_mapnr)
-
-#define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
-				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-
-#include <asm-generic/memory_model.h>
-#include <asm-generic/page.h>
-
-#endif /* _SPARC_PAGE_H */
diff --git a/include/asm-sparc/page_32.h b/include/asm-sparc/page_32.h
new file mode 100644
index 0000000..14de518
--- /dev/null
+++ b/include/asm-sparc/page_32.h
@@ -0,0 +1,163 @@
+/*
+ * page.h:  Various defines and such for MMU operations on the Sparc for
+ *          the Linux kernel.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_PAGE_H
+#define _SPARC_PAGE_H
+
+#ifdef CONFIG_SUN4
+#define PAGE_SHIFT   13
+#else
+#define PAGE_SHIFT   12
+#endif
+#ifndef __ASSEMBLY__
+/* I have my suspicions... -DaveM */
+#define PAGE_SIZE    (1UL << PAGE_SHIFT)
+#else
+#define PAGE_SIZE    (1 << PAGE_SHIFT)
+#endif
+#define PAGE_MASK    (~(PAGE_SIZE-1))
+
+#include <asm/btfixup.h>
+
+#ifndef __ASSEMBLY__
+
+#define clear_page(page)	 memset((void *)(page), 0, PAGE_SIZE)
+#define copy_page(to,from) 	memcpy((void *)(to), (void *)(from), PAGE_SIZE)
+#define clear_user_page(addr, vaddr, page)	\
+	do { 	clear_page(addr);		\
+		sparc_flush_page_to_ram(page);	\
+	} while (0)
+#define copy_user_page(to, from, vaddr, page)	\
+	do {	copy_page(to, from);		\
+		sparc_flush_page_to_ram(page);	\
+	} while (0)
+
+/* The following structure is used to hold the physical
+ * memory configuration of the machine.  This is filled in
+ * prom_meminit() and is later used by mem_init() to set up
+ * mem_map[].  We statically allocate SPARC_PHYS_BANKS+1 of
+ * these structs, this is arbitrary.  The entry after the
+ * last valid one has num_bytes==0.
+ */
+struct sparc_phys_banks {
+  unsigned long base_addr;
+  unsigned long num_bytes;
+};
+
+#define SPARC_PHYS_BANKS 32
+
+extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS+1];
+
+/* Cache alias structure.  Entry is valid if context != -1. */
+struct cache_palias {
+	unsigned long vaddr;
+	int context;
+};
+
+/* passing structs on the Sparc slow us down tremendously... */
+
+/* #define STRICT_MM_TYPECHECKS */
+
+#ifdef STRICT_MM_TYPECHECKS
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long iopte; } iopte_t;
+typedef struct { unsigned long pmdv[16]; } pmd_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long ctxd; } ctxd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+typedef struct { unsigned long iopgprot; } iopgprot_t;
+
+#define pte_val(x)	((x).pte)
+#define iopte_val(x)	((x).iopte)
+#define pmd_val(x)      ((x).pmdv[0])
+#define pgd_val(x)	((x).pgd)
+#define ctxd_val(x)	((x).ctxd)
+#define pgprot_val(x)	((x).pgprot)
+#define iopgprot_val(x)	((x).iopgprot)
+
+#define __pte(x)	((pte_t) { (x) } )
+#define __iopte(x)	((iopte_t) { (x) } )
+/* #define __pmd(x)        ((pmd_t) { (x) } ) */ /* XXX procedure with loop */
+#define __pgd(x)	((pgd_t) { (x) } )
+#define __ctxd(x)	((ctxd_t) { (x) } )
+#define __pgprot(x)	((pgprot_t) { (x) } )
+#define __iopgprot(x)	((iopgprot_t) { (x) } )
+
+#else
+/*
+ * .. while these make it easier on the compiler
+ */
+typedef unsigned long pte_t;
+typedef unsigned long iopte_t;
+typedef struct { unsigned long pmdv[16]; } pmd_t;
+typedef unsigned long pgd_t;
+typedef unsigned long ctxd_t;
+typedef unsigned long pgprot_t;
+typedef unsigned long iopgprot_t;
+
+#define pte_val(x)	(x)
+#define iopte_val(x)	(x)
+#define pmd_val(x)      ((x).pmdv[0])
+#define pgd_val(x)	(x)
+#define ctxd_val(x)	(x)
+#define pgprot_val(x)	(x)
+#define iopgprot_val(x)	(x)
+
+#define __pte(x)	(x)
+#define __iopte(x)	(x)
+/* #define __pmd(x)        (x) */ /* XXX later */
+#define __pgd(x)	(x)
+#define __ctxd(x)	(x)
+#define __pgprot(x)	(x)
+#define __iopgprot(x)	(x)
+
+#endif
+
+typedef struct page *pgtable_t;
+
+extern unsigned long sparc_unmapped_base;
+
+BTFIXUPDEF_SETHI(sparc_unmapped_base)
+
+#define TASK_UNMAPPED_BASE	BTFIXUP_SETHI(sparc_unmapped_base)
+
+#else /* !(__ASSEMBLY__) */
+
+#define __pgprot(x)	(x)
+
+#endif /* !(__ASSEMBLY__) */
+
+/* to align the pointer to the (next) page boundary */
+#define PAGE_ALIGN(addr)  (((addr)+PAGE_SIZE-1)&PAGE_MASK)
+
+#define PAGE_OFFSET	0xf0000000
+#ifndef __ASSEMBLY__
+extern unsigned long phys_base;
+extern unsigned long pfn_base;
+#endif
+#define __pa(x)			((unsigned long)(x) - PAGE_OFFSET + phys_base)
+#define __va(x)			((void *)((unsigned long) (x) - phys_base + PAGE_OFFSET))
+
+#define virt_to_phys		__pa
+#define phys_to_virt		__va
+
+#define ARCH_PFN_OFFSET		(pfn_base)
+#define virt_to_page(kaddr)	(mem_map + ((((unsigned long)(kaddr)-PAGE_OFFSET)>>PAGE_SHIFT)))
+
+#define pfn_valid(pfn)		(((pfn) >= (pfn_base)) && (((pfn)-(pfn_base)) < max_mapnr))
+#define virt_addr_valid(kaddr)	((((unsigned long)(kaddr)-PAGE_OFFSET)>>PAGE_SHIFT) < max_mapnr)
+
+#define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
+				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#include <asm-generic/memory_model.h>
+#include <asm-generic/page.h>
+
+#endif /* _SPARC_PAGE_H */
diff --git a/include/asm-sparc/page_64.h b/include/asm-sparc/page_64.h
new file mode 100644
index 0000000..a8a2bba
--- /dev/null
+++ b/include/asm-sparc/page_64.h
@@ -0,0 +1,138 @@
+#ifndef _SPARC64_PAGE_H
+#define _SPARC64_PAGE_H
+
+#include <linux/const.h>
+
+#if defined(CONFIG_SPARC64_PAGE_SIZE_8KB)
+#define PAGE_SHIFT   13
+#elif defined(CONFIG_SPARC64_PAGE_SIZE_64KB)
+#define PAGE_SHIFT   16
+#else
+#error No page size specified in kernel configuration
+#endif
+
+#define PAGE_SIZE    (_AC(1,UL) << PAGE_SHIFT)
+#define PAGE_MASK    (~(PAGE_SIZE-1))
+
+/* Flushing for D-cache alias handling is only needed if
+ * the page size is smaller than 16K.
+ */
+#if PAGE_SHIFT < 14
+#define DCACHE_ALIASING_POSSIBLE
+#endif
+
+#if defined(CONFIG_HUGETLB_PAGE_SIZE_4MB)
+#define HPAGE_SHIFT		22
+#elif defined(CONFIG_HUGETLB_PAGE_SIZE_512K)
+#define HPAGE_SHIFT		19
+#elif defined(CONFIG_HUGETLB_PAGE_SIZE_64K)
+#define HPAGE_SHIFT		16
+#endif
+
+#ifdef CONFIG_HUGETLB_PAGE
+#define HPAGE_SIZE		(_AC(1,UL) << HPAGE_SHIFT)
+#define HPAGE_MASK		(~(HPAGE_SIZE - 1UL))
+#define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
+#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
+#endif
+
+#ifndef __ASSEMBLY__
+
+extern void _clear_page(void *page);
+#define clear_page(X)	_clear_page((void *)(X))
+struct page;
+extern void clear_user_page(void *addr, unsigned long vaddr, struct page *page);
+#define copy_page(X,Y)	memcpy((void *)(X), (void *)(Y), PAGE_SIZE)
+extern void copy_user_page(void *to, void *from, unsigned long vaddr, struct page *topage);
+
+/* Unlike sparc32, sparc64's parameter passing API is more
+ * sane in that structures which as small enough are passed
+ * in registers instead of on the stack.  Thus, setting
+ * STRICT_MM_TYPECHECKS does not generate worse code so
+ * let's enable it to get the type checking.
+ */
+
+#define STRICT_MM_TYPECHECKS
+
+#ifdef STRICT_MM_TYPECHECKS
+/* These are used to make use of C type-checking.. */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long iopte; } iopte_t;
+typedef struct { unsigned int pmd; } pmd_t;
+typedef struct { unsigned int pgd; } pgd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+
+#define pte_val(x)	((x).pte)
+#define iopte_val(x)	((x).iopte)
+#define pmd_val(x)      ((x).pmd)
+#define pgd_val(x)	((x).pgd)
+#define pgprot_val(x)	((x).pgprot)
+
+#define __pte(x)	((pte_t) { (x) } )
+#define __iopte(x)	((iopte_t) { (x) } )
+#define __pmd(x)        ((pmd_t) { (x) } )
+#define __pgd(x)	((pgd_t) { (x) } )
+#define __pgprot(x)	((pgprot_t) { (x) } )
+
+#else
+/* .. while these make it easier on the compiler */
+typedef unsigned long pte_t;
+typedef unsigned long iopte_t;
+typedef unsigned int pmd_t;
+typedef unsigned int pgd_t;
+typedef unsigned long pgprot_t;
+
+#define pte_val(x)	(x)
+#define iopte_val(x)	(x)
+#define pmd_val(x)      (x)
+#define pgd_val(x)	(x)
+#define pgprot_val(x)	(x)
+
+#define __pte(x)	(x)
+#define __iopte(x)	(x)
+#define __pmd(x)        (x)
+#define __pgd(x)	(x)
+#define __pgprot(x)	(x)
+
+#endif /* (STRICT_MM_TYPECHECKS) */
+
+typedef struct page *pgtable_t;
+
+#define TASK_UNMAPPED_BASE	(test_thread_flag(TIF_32BIT) ? \
+				 (_AC(0x0000000070000000,UL)) : \
+				 (_AC(0xfffff80000000000,UL) + (1UL << 32UL)))
+
+#include <asm-generic/memory_model.h>
+
+#endif /* !(__ASSEMBLY__) */
+
+/* to align the pointer to the (next) page boundary */
+#define PAGE_ALIGN(addr)	(((addr)+PAGE_SIZE-1)&PAGE_MASK)
+
+/* We used to stick this into a hard-coded global register (%g4)
+ * but that does not make sense anymore.
+ */
+#define PAGE_OFFSET		_AC(0xFFFFF80000000000,UL)
+
+#ifndef __ASSEMBLY__
+
+#define __pa(x)			((unsigned long)(x) - PAGE_OFFSET)
+#define __va(x)			((void *)((unsigned long) (x) + PAGE_OFFSET))
+
+#define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
+
+#define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr)>>PAGE_SHIFT)
+
+#define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+
+#define virt_to_phys __pa
+#define phys_to_virt __va
+
+#endif /* !(__ASSEMBLY__) */
+
+#define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
+				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#include <asm-generic/page.h>
+
+#endif /* _SPARC64_PAGE_H */
diff --git a/include/asm-sparc/parport.h b/include/asm-sparc/parport.h
new file mode 100644
index 0000000..7818b25
--- /dev/null
+++ b/include/asm-sparc/parport.h
@@ -0,0 +1,246 @@
+/* parport.h: sparc64 specific parport initialization and dma.
+ *
+ * Copyright (C) 1999  Eddie C. Dost  (ecd@skynet.be)
+ */
+
+#ifndef _ASM_SPARC64_PARPORT_H
+#define _ASM_SPARC64_PARPORT_H 1
+
+#include <asm/ebus.h>
+#include <asm/ns87303.h>
+#include <asm/of_device.h>
+#include <asm/prom.h>
+
+#define PARPORT_PC_MAX_PORTS	PARPORT_MAX
+
+/*
+ * While sparc64 doesn't have an ISA DMA API, we provide something that looks
+ * close enough to make parport_pc happy
+ */
+#define HAS_DMA
+
+static DEFINE_SPINLOCK(dma_spin_lock);
+
+#define claim_dma_lock() \
+({	unsigned long flags; \
+	spin_lock_irqsave(&dma_spin_lock, flags); \
+	flags; \
+})
+
+#define release_dma_lock(__flags) \
+	spin_unlock_irqrestore(&dma_spin_lock, __flags);
+
+static struct sparc_ebus_info {
+	struct ebus_dma_info info;
+	unsigned int addr;
+	unsigned int count;
+	int lock;
+
+	struct parport *port;
+} sparc_ebus_dmas[PARPORT_PC_MAX_PORTS];
+
+static DECLARE_BITMAP(dma_slot_map, PARPORT_PC_MAX_PORTS);
+
+static inline int request_dma(unsigned int dmanr, const char *device_id)
+{
+	if (dmanr >= PARPORT_PC_MAX_PORTS)
+		return -EINVAL;
+	if (xchg(&sparc_ebus_dmas[dmanr].lock, 1) != 0)
+		return -EBUSY;
+	return 0;
+}
+
+static inline void free_dma(unsigned int dmanr)
+{
+	if (dmanr >= PARPORT_PC_MAX_PORTS) {
+		printk(KERN_WARNING "Trying to free DMA%d\n", dmanr);
+		return;
+	}
+	if (xchg(&sparc_ebus_dmas[dmanr].lock, 0) == 0) {
+		printk(KERN_WARNING "Trying to free free DMA%d\n", dmanr);
+		return;
+	}
+}
+
+static inline void enable_dma(unsigned int dmanr)
+{
+	ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 1);
+
+	if (ebus_dma_request(&sparc_ebus_dmas[dmanr].info,
+			     sparc_ebus_dmas[dmanr].addr,
+			     sparc_ebus_dmas[dmanr].count))
+		BUG();
+}
+
+static inline void disable_dma(unsigned int dmanr)
+{
+	ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 0);
+}
+
+static inline void clear_dma_ff(unsigned int dmanr)
+{
+	/* nothing */
+}
+
+static inline void set_dma_mode(unsigned int dmanr, char mode)
+{
+	ebus_dma_prepare(&sparc_ebus_dmas[dmanr].info, (mode != DMA_MODE_WRITE));
+}
+
+static inline void set_dma_addr(unsigned int dmanr, unsigned int addr)
+{
+	sparc_ebus_dmas[dmanr].addr = addr;
+}
+
+static inline void set_dma_count(unsigned int dmanr, unsigned int count)
+{
+	sparc_ebus_dmas[dmanr].count = count;
+}
+
+static inline unsigned int get_dma_residue(unsigned int dmanr)
+{
+	return ebus_dma_residue(&sparc_ebus_dmas[dmanr].info);
+}
+
+static int __devinit ecpp_probe(struct of_device *op, const struct of_device_id *match)
+{
+	unsigned long base = op->resource[0].start;
+	unsigned long config = op->resource[1].start;
+	unsigned long d_base = op->resource[2].start;
+	unsigned long d_len;
+	struct device_node *parent;
+	struct parport *p;
+	int slot, err;
+
+	parent = op->node->parent;
+	if (!strcmp(parent->name, "dma")) {
+		p = parport_pc_probe_port(base, base + 0x400,
+					  op->irqs[0], PARPORT_DMA_NOFIFO,
+					  op->dev.parent->parent);
+		if (!p)
+			return -ENOMEM;
+		dev_set_drvdata(&op->dev, p);
+		return 0;
+	}
+
+	for (slot = 0; slot < PARPORT_PC_MAX_PORTS; slot++) {
+		if (!test_and_set_bit(slot, dma_slot_map))
+			break;
+	}
+	err = -ENODEV;
+	if (slot >= PARPORT_PC_MAX_PORTS)
+		goto out_err;
+
+	spin_lock_init(&sparc_ebus_dmas[slot].info.lock);
+
+	d_len = (op->resource[2].end - d_base) + 1UL;
+	sparc_ebus_dmas[slot].info.regs =
+		of_ioremap(&op->resource[2], 0, d_len, "ECPP DMA");
+
+	if (!sparc_ebus_dmas[slot].info.regs)
+		goto out_clear_map;
+
+	sparc_ebus_dmas[slot].info.flags = 0;
+	sparc_ebus_dmas[slot].info.callback = NULL;
+	sparc_ebus_dmas[slot].info.client_cookie = NULL;
+	sparc_ebus_dmas[slot].info.irq = 0xdeadbeef;
+	strcpy(sparc_ebus_dmas[slot].info.name, "parport");
+	if (ebus_dma_register(&sparc_ebus_dmas[slot].info))
+		goto out_unmap_regs;
+
+	ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 1);
+
+	/* Configure IRQ to Push Pull, Level Low */
+	/* Enable ECP, set bit 2 of the CTR first */
+	outb(0x04, base + 0x02);
+	ns87303_modify(config, PCR,
+		       PCR_EPP_ENABLE |
+		       PCR_IRQ_ODRAIN,
+		       PCR_ECP_ENABLE |
+		       PCR_ECP_CLK_ENA |
+		       PCR_IRQ_POLAR);
+
+	/* CTR bit 5 controls direction of port */
+	ns87303_modify(config, PTR,
+		       0, PTR_LPT_REG_DIR);
+
+	p = parport_pc_probe_port(base, base + 0x400,
+				  op->irqs[0],
+				  slot,
+				  op->dev.parent);
+	err = -ENOMEM;
+	if (!p)
+		goto out_disable_irq;
+
+	dev_set_drvdata(&op->dev, p);
+
+	return 0;
+
+out_disable_irq:
+	ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0);
+	ebus_dma_unregister(&sparc_ebus_dmas[slot].info);
+
+out_unmap_regs:
+	of_iounmap(&op->resource[2], sparc_ebus_dmas[slot].info.regs, d_len);
+
+out_clear_map:
+	clear_bit(slot, dma_slot_map);
+
+out_err:
+	return err;
+}
+
+static int __devexit ecpp_remove(struct of_device *op)
+{
+	struct parport *p = dev_get_drvdata(&op->dev);
+	int slot = p->dma;
+
+	parport_pc_unregister_port(p);
+
+	if (slot != PARPORT_DMA_NOFIFO) {
+		unsigned long d_base = op->resource[2].start;
+		unsigned long d_len;
+
+		d_len = (op->resource[2].end - d_base) + 1UL;
+
+		ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0);
+		ebus_dma_unregister(&sparc_ebus_dmas[slot].info);
+		of_iounmap(&op->resource[2],
+			   sparc_ebus_dmas[slot].info.regs,
+			   d_len);
+		clear_bit(slot, dma_slot_map);
+	}
+
+	return 0;
+}
+
+static struct of_device_id ecpp_match[] = {
+	{
+		.name = "ecpp",
+	},
+	{
+		.name = "parallel",
+		.compatible = "ecpp",
+	},
+	{
+		.name = "parallel",
+		.compatible = "ns87317-ecpp",
+	},
+	{},
+};
+
+static struct of_platform_driver ecpp_driver = {
+	.name			= "ecpp",
+	.match_table		= ecpp_match,
+	.probe			= ecpp_probe,
+	.remove			= __devexit_p(ecpp_remove),
+};
+
+static int parport_pc_find_nonpci_ports(int autoirq, int autodma)
+{
+	of_register_driver(&ecpp_driver, &of_bus_type);
+
+	return 0;
+}
+
+#endif /* !(_ASM_SPARC64_PARPORT_H */
diff --git a/include/asm-sparc/pci.h b/include/asm-sparc/pci.h
index b93b6c7..b807d52 100644
--- a/include/asm-sparc/pci.h
+++ b/include/asm-sparc/pci.h
@@ -1,170 +1,8 @@
-#ifndef __SPARC_PCI_H
-#define __SPARC_PCI_H
-
-#ifdef __KERNEL__
-
-/* Can be used to override the logic in pci_scan_bus for skipping
- * already-configured bus numbers - to be used for buggy BIOSes
- * or architectures with incomplete PCI setup by the loader.
- */
-#define pcibios_assign_all_busses()	0
-#define pcibios_scan_all_fns(a, b)	0
-
-#define PCIBIOS_MIN_IO		0UL
-#define PCIBIOS_MIN_MEM		0UL
-
-#define PCI_IRQ_NONE		0xffffffff
-
-static inline void pcibios_set_master(struct pci_dev *dev)
-{
-	/* No special bus mastering setup handling */
-}
-
-static inline void pcibios_penalize_isa_irq(int irq, int active)
-{
-	/* We don't do dynamic PCI IRQ allocation */
-}
-
-/* Dynamic DMA mapping stuff.
- */
-#define PCI_DMA_BUS_IS_PHYS	(0)
-
-#include <asm/scatterlist.h>
-
-struct pci_dev;
-
-/* Allocate and map kernel buffer using consistent mode DMA for a device.
- * hwdev should be valid struct pci_dev pointer for PCI devices.
- */
-extern void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle);
-
-/* Free and unmap a consistent DMA buffer.
- * cpu_addr is what was returned from pci_alloc_consistent,
- * size must be the same as what as passed into pci_alloc_consistent,
- * and likewise dma_addr must be the same as what *dma_addrp was set to.
- *
- * References to the memory and mappings assosciated with cpu_addr/dma_addr
- * past this call are illegal.
- */
-extern void pci_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle);
-
-/* Map a single buffer of the indicated size for DMA in streaming mode.
- * The 32-bit bus address to use is returned.
- *
- * Once the device is given the dma address, the device owns this memory
- * until either pci_unmap_single or pci_dma_sync_single_for_cpu is performed.
- */
-extern dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction);
-
-/* Unmap a single streaming mode DMA translation.  The dma_addr and size
- * must match what was provided for in a previous pci_map_single call.  All
- * other usages are undefined.
- *
- * After this call, reads by the cpu to the buffer are guaranteed to see
- * whatever the device wrote there.
- */
-extern void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size, int direction);
-
-/* pci_unmap_{single,page} is not a nop, thus... */
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)	\
-	dma_addr_t ADDR_NAME;
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		\
-	__u32 LEN_NAME;
-#define pci_unmap_addr(PTR, ADDR_NAME)			\
-	((PTR)->ADDR_NAME)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)		\
-	(((PTR)->ADDR_NAME) = (VAL))
-#define pci_unmap_len(PTR, LEN_NAME)			\
-	((PTR)->LEN_NAME)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
-	(((PTR)->LEN_NAME) = (VAL))
-
-/*
- * Same as above, only with pages instead of mapped addresses.
- */
-extern dma_addr_t pci_map_page(struct pci_dev *hwdev, struct page *page,
-			unsigned long offset, size_t size, int direction);
-extern void pci_unmap_page(struct pci_dev *hwdev,
-			dma_addr_t dma_address, size_t size, int direction);
-
-/* Map a set of buffers described by scatterlist in streaming
- * mode for DMA.  This is the scather-gather version of the
- * above pci_map_single interface.  Here the scatter gather list
- * elements are each tagged with the appropriate dma address
- * and length.  They are obtained via sg_dma_{address,length}(SG).
- *
- * NOTE: An implementation may be able to use a smaller number of
- *       DMA address/length pairs than there are SG table elements.
- *       (for example via virtual mapping capabilities)
- *       The routine returns the number of addr/length pairs actually
- *       used, at most nents.
- *
- * Device ownership issues as mentioned above for pci_map_single are
- * the same here.
- */
-extern int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction);
-
-/* Unmap a set of streaming mode DMA translations.
- * Again, cpu read rules concerning calls here are the same as for
- * pci_unmap_single() above.
- */
-extern void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nhwents, int direction);
-
-/* Make physical memory consistent for a single
- * streaming mode DMA translation after a transfer.
- *
- * If you perform a pci_map_single() but wish to interrogate the
- * buffer using the cpu, yet do not wish to teardown the PCI dma
- * mapping, you must call this function before doing so.  At the
- * next point you give the PCI dma address back to the card, you
- * must first perform a pci_dma_sync_for_device, and then the device
- * again owns the buffer.
- */
-extern void pci_dma_sync_single_for_cpu(struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size, int direction);
-extern void pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size, int direction);
-
-/* Make physical memory consistent for a set of streaming
- * mode DMA translations after a transfer.
- *
- * The same as pci_dma_sync_single_* but for a scatter-gather list,
- * same rules and usage.
- */
-extern void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction);
-extern void pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction);
-
-/* Return whether the given PCI device DMA address mask can
- * be supported properly.  For example, if your device can
- * only drive the low 24-bits during PCI bus mastering, then
- * you would pass 0x00ffffff as the mask to this function.
- */
-static inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask)
-{
-	return 1;
-}
-
-#ifdef CONFIG_PCI
-static inline void pci_dma_burst_advice(struct pci_dev *pdev,
-					enum pci_dma_burst_strategy *strat,
-					unsigned long *strategy_parameter)
-{
-	*strat = PCI_DMA_BURST_INFINITY;
-	*strategy_parameter = ~0UL;
-}
+#ifndef ___ASM_SPARC_PCI_H
+#define ___ASM_SPARC_PCI_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/pci_64.h>
+#else
+#include <asm-sparc/pci_32.h>
 #endif
-
-#define PCI_DMA_ERROR_CODE      (~(dma_addr_t)0x0)
-
-static inline int pci_dma_mapping_error(dma_addr_t dma_addr)
-{
-        return (dma_addr == PCI_DMA_ERROR_CODE);
-}
-
-struct device_node;
-extern struct device_node *pci_device_to_OF_node(struct pci_dev *pdev);
-
-#endif /* __KERNEL__ */
-
-/* generic pci stuff */
-#include <asm-generic/pci.h>
-
-#endif /* __SPARC_PCI_H */
+#endif
diff --git a/include/asm-sparc/pci_32.h b/include/asm-sparc/pci_32.h
new file mode 100644
index 0000000..b93b6c7
--- /dev/null
+++ b/include/asm-sparc/pci_32.h
@@ -0,0 +1,170 @@
+#ifndef __SPARC_PCI_H
+#define __SPARC_PCI_H
+
+#ifdef __KERNEL__
+
+/* Can be used to override the logic in pci_scan_bus for skipping
+ * already-configured bus numbers - to be used for buggy BIOSes
+ * or architectures with incomplete PCI setup by the loader.
+ */
+#define pcibios_assign_all_busses()	0
+#define pcibios_scan_all_fns(a, b)	0
+
+#define PCIBIOS_MIN_IO		0UL
+#define PCIBIOS_MIN_MEM		0UL
+
+#define PCI_IRQ_NONE		0xffffffff
+
+static inline void pcibios_set_master(struct pci_dev *dev)
+{
+	/* No special bus mastering setup handling */
+}
+
+static inline void pcibios_penalize_isa_irq(int irq, int active)
+{
+	/* We don't do dynamic PCI IRQ allocation */
+}
+
+/* Dynamic DMA mapping stuff.
+ */
+#define PCI_DMA_BUS_IS_PHYS	(0)
+
+#include <asm/scatterlist.h>
+
+struct pci_dev;
+
+/* Allocate and map kernel buffer using consistent mode DMA for a device.
+ * hwdev should be valid struct pci_dev pointer for PCI devices.
+ */
+extern void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle);
+
+/* Free and unmap a consistent DMA buffer.
+ * cpu_addr is what was returned from pci_alloc_consistent,
+ * size must be the same as what as passed into pci_alloc_consistent,
+ * and likewise dma_addr must be the same as what *dma_addrp was set to.
+ *
+ * References to the memory and mappings assosciated with cpu_addr/dma_addr
+ * past this call are illegal.
+ */
+extern void pci_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle);
+
+/* Map a single buffer of the indicated size for DMA in streaming mode.
+ * The 32-bit bus address to use is returned.
+ *
+ * Once the device is given the dma address, the device owns this memory
+ * until either pci_unmap_single or pci_dma_sync_single_for_cpu is performed.
+ */
+extern dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction);
+
+/* Unmap a single streaming mode DMA translation.  The dma_addr and size
+ * must match what was provided for in a previous pci_map_single call.  All
+ * other usages are undefined.
+ *
+ * After this call, reads by the cpu to the buffer are guaranteed to see
+ * whatever the device wrote there.
+ */
+extern void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size, int direction);
+
+/* pci_unmap_{single,page} is not a nop, thus... */
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)	\
+	dma_addr_t ADDR_NAME;
+#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		\
+	__u32 LEN_NAME;
+#define pci_unmap_addr(PTR, ADDR_NAME)			\
+	((PTR)->ADDR_NAME)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)		\
+	(((PTR)->ADDR_NAME) = (VAL))
+#define pci_unmap_len(PTR, LEN_NAME)			\
+	((PTR)->LEN_NAME)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
+	(((PTR)->LEN_NAME) = (VAL))
+
+/*
+ * Same as above, only with pages instead of mapped addresses.
+ */
+extern dma_addr_t pci_map_page(struct pci_dev *hwdev, struct page *page,
+			unsigned long offset, size_t size, int direction);
+extern void pci_unmap_page(struct pci_dev *hwdev,
+			dma_addr_t dma_address, size_t size, int direction);
+
+/* Map a set of buffers described by scatterlist in streaming
+ * mode for DMA.  This is the scather-gather version of the
+ * above pci_map_single interface.  Here the scatter gather list
+ * elements are each tagged with the appropriate dma address
+ * and length.  They are obtained via sg_dma_{address,length}(SG).
+ *
+ * NOTE: An implementation may be able to use a smaller number of
+ *       DMA address/length pairs than there are SG table elements.
+ *       (for example via virtual mapping capabilities)
+ *       The routine returns the number of addr/length pairs actually
+ *       used, at most nents.
+ *
+ * Device ownership issues as mentioned above for pci_map_single are
+ * the same here.
+ */
+extern int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction);
+
+/* Unmap a set of streaming mode DMA translations.
+ * Again, cpu read rules concerning calls here are the same as for
+ * pci_unmap_single() above.
+ */
+extern void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nhwents, int direction);
+
+/* Make physical memory consistent for a single
+ * streaming mode DMA translation after a transfer.
+ *
+ * If you perform a pci_map_single() but wish to interrogate the
+ * buffer using the cpu, yet do not wish to teardown the PCI dma
+ * mapping, you must call this function before doing so.  At the
+ * next point you give the PCI dma address back to the card, you
+ * must first perform a pci_dma_sync_for_device, and then the device
+ * again owns the buffer.
+ */
+extern void pci_dma_sync_single_for_cpu(struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size, int direction);
+extern void pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size, int direction);
+
+/* Make physical memory consistent for a set of streaming
+ * mode DMA translations after a transfer.
+ *
+ * The same as pci_dma_sync_single_* but for a scatter-gather list,
+ * same rules and usage.
+ */
+extern void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction);
+extern void pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction);
+
+/* Return whether the given PCI device DMA address mask can
+ * be supported properly.  For example, if your device can
+ * only drive the low 24-bits during PCI bus mastering, then
+ * you would pass 0x00ffffff as the mask to this function.
+ */
+static inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask)
+{
+	return 1;
+}
+
+#ifdef CONFIG_PCI
+static inline void pci_dma_burst_advice(struct pci_dev *pdev,
+					enum pci_dma_burst_strategy *strat,
+					unsigned long *strategy_parameter)
+{
+	*strat = PCI_DMA_BURST_INFINITY;
+	*strategy_parameter = ~0UL;
+}
+#endif
+
+#define PCI_DMA_ERROR_CODE      (~(dma_addr_t)0x0)
+
+static inline int pci_dma_mapping_error(dma_addr_t dma_addr)
+{
+        return (dma_addr == PCI_DMA_ERROR_CODE);
+}
+
+struct device_node;
+extern struct device_node *pci_device_to_OF_node(struct pci_dev *pdev);
+
+#endif /* __KERNEL__ */
+
+/* generic pci stuff */
+#include <asm-generic/pci.h>
+
+#endif /* __SPARC_PCI_H */
diff --git a/include/asm-sparc/pci_64.h b/include/asm-sparc/pci_64.h
new file mode 100644
index 0000000..f59f257
--- /dev/null
+++ b/include/asm-sparc/pci_64.h
@@ -0,0 +1,209 @@
+#ifndef __SPARC64_PCI_H
+#define __SPARC64_PCI_H
+
+#ifdef __KERNEL__
+
+#include <linux/dma-mapping.h>
+
+/* Can be used to override the logic in pci_scan_bus for skipping
+ * already-configured bus numbers - to be used for buggy BIOSes
+ * or architectures with incomplete PCI setup by the loader.
+ */
+#define pcibios_assign_all_busses()	0
+#define pcibios_scan_all_fns(a, b)	0
+
+#define PCIBIOS_MIN_IO		0UL
+#define PCIBIOS_MIN_MEM		0UL
+
+#define PCI_IRQ_NONE		0xffffffff
+
+#define PCI_CACHE_LINE_BYTES	64
+
+static inline void pcibios_set_master(struct pci_dev *dev)
+{
+	/* No special bus mastering setup handling */
+}
+
+static inline void pcibios_penalize_isa_irq(int irq, int active)
+{
+	/* We don't do dynamic PCI IRQ allocation */
+}
+
+/* The PCI address space does not equal the physical memory
+ * address space.  The networking and block device layers use
+ * this boolean for bounce buffer decisions.
+ */
+#define PCI_DMA_BUS_IS_PHYS	(0)
+
+static inline void *pci_alloc_consistent(struct pci_dev *pdev, size_t size,
+					 dma_addr_t *dma_handle)
+{
+	return dma_alloc_coherent(&pdev->dev, size, dma_handle, GFP_ATOMIC);
+}
+
+static inline void pci_free_consistent(struct pci_dev *pdev, size_t size,
+				       void *vaddr, dma_addr_t dma_handle)
+{
+	return dma_free_coherent(&pdev->dev, size, vaddr, dma_handle);
+}
+
+static inline dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr,
+					size_t size, int direction)
+{
+	return dma_map_single(&pdev->dev, ptr, size,
+			      (enum dma_data_direction) direction);
+}
+
+static inline void pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr,
+				    size_t size, int direction)
+{
+	dma_unmap_single(&pdev->dev, dma_addr, size,
+			 (enum dma_data_direction) direction);
+}
+
+#define pci_map_page(dev, page, off, size, dir) \
+	pci_map_single(dev, (page_address(page) + (off)), size, dir)
+#define pci_unmap_page(dev,addr,sz,dir) \
+	pci_unmap_single(dev,addr,sz,dir)
+
+/* pci_unmap_{single,page} is not a nop, thus... */
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)	\
+	dma_addr_t ADDR_NAME;
+#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		\
+	__u32 LEN_NAME;
+#define pci_unmap_addr(PTR, ADDR_NAME)			\
+	((PTR)->ADDR_NAME)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)		\
+	(((PTR)->ADDR_NAME) = (VAL))
+#define pci_unmap_len(PTR, LEN_NAME)			\
+	((PTR)->LEN_NAME)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
+	(((PTR)->LEN_NAME) = (VAL))
+
+static inline int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg,
+			     int nents, int direction)
+{
+	return dma_map_sg(&pdev->dev, sg, nents,
+			  (enum dma_data_direction) direction);
+}
+
+static inline void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg,
+				int nents, int direction)
+{
+	dma_unmap_sg(&pdev->dev, sg, nents,
+		     (enum dma_data_direction) direction);
+}
+
+static inline void pci_dma_sync_single_for_cpu(struct pci_dev *pdev,
+					       dma_addr_t dma_handle,
+					       size_t size, int direction)
+{
+	dma_sync_single_for_cpu(&pdev->dev, dma_handle, size,
+				(enum dma_data_direction) direction);
+}
+
+static inline void pci_dma_sync_single_for_device(struct pci_dev *pdev,
+						  dma_addr_t dma_handle,
+						  size_t size, int direction)
+{
+	/* No flushing needed to sync cpu writes to the device.  */
+}
+
+static inline void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev,
+					   struct scatterlist *sg,
+					   int nents, int direction)
+{
+	dma_sync_sg_for_cpu(&pdev->dev, sg, nents,
+			    (enum dma_data_direction) direction);
+}
+
+static inline void pci_dma_sync_sg_for_device(struct pci_dev *pdev,
+					      struct scatterlist *sg,
+					      int nelems, int direction)
+{
+	/* No flushing needed to sync cpu writes to the device.  */
+}
+
+/* Return whether the given PCI device DMA address mask can
+ * be supported properly.  For example, if your device can
+ * only drive the low 24-bits during PCI bus mastering, then
+ * you would pass 0x00ffffff as the mask to this function.
+ */
+extern int pci_dma_supported(struct pci_dev *hwdev, u64 mask);
+
+/* PCI IOMMU mapping bypass support. */
+
+/* PCI 64-bit addressing works for all slots on all controller
+ * types on sparc64.  However, it requires that the device
+ * can drive enough of the 64 bits.
+ */
+#define PCI64_REQUIRED_MASK	(~(dma64_addr_t)0)
+#define PCI64_ADDR_BASE		0xfffc000000000000UL
+
+static inline int pci_dma_mapping_error(dma_addr_t dma_addr)
+{
+	return dma_mapping_error(dma_addr);
+}
+
+#ifdef CONFIG_PCI
+static inline void pci_dma_burst_advice(struct pci_dev *pdev,
+					enum pci_dma_burst_strategy *strat,
+					unsigned long *strategy_parameter)
+{
+	unsigned long cacheline_size;
+	u8 byte;
+
+	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &byte);
+	if (byte == 0)
+		cacheline_size = 1024;
+	else
+		cacheline_size = (int) byte * 4;
+
+	*strat = PCI_DMA_BURST_BOUNDARY;
+	*strategy_parameter = cacheline_size;
+}
+#endif
+
+/* Return the index of the PCI controller for device PDEV. */
+
+extern int pci_domain_nr(struct pci_bus *bus);
+static inline int pci_proc_domain(struct pci_bus *bus)
+{
+	return 1;
+}
+
+/* Platform support for /proc/bus/pci/X/Y mmap()s. */
+
+#define HAVE_PCI_MMAP
+#define HAVE_ARCH_PCI_GET_UNMAPPED_AREA
+#define get_pci_unmapped_area get_fb_unmapped_area
+
+extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+			       enum pci_mmap_state mmap_state,
+			       int write_combine);
+
+extern void
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+			struct resource *res);
+
+extern void
+pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+			struct pci_bus_region *region);
+
+extern struct resource *pcibios_select_root(struct pci_dev *, struct resource *);
+
+static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
+{
+	return PCI_IRQ_NONE;
+}
+
+struct device_node;
+extern struct device_node *pci_device_to_OF_node(struct pci_dev *pdev);
+
+#define HAVE_ARCH_PCI_RESOURCE_TO_USER
+extern void pci_resource_to_user(const struct pci_dev *dev, int bar,
+				 const struct resource *rsrc,
+				 resource_size_t *start, resource_size_t *end);
+#endif /* __KERNEL__ */
+
+#endif /* __SPARC64_PCI_H */
diff --git a/include/asm-sparc/percpu.h b/include/asm-sparc/percpu.h
index 06066a7..d98ed6c 100644
--- a/include/asm-sparc/percpu.h
+++ b/include/asm-sparc/percpu.h
@@ -1,6 +1,8 @@
-#ifndef __ARCH_SPARC_PERCPU__
-#define __ARCH_SPARC_PERCPU__
-
-#include <asm-generic/percpu.h>
-
-#endif /* __ARCH_SPARC_PERCPU__ */
+#ifndef ___ASM_SPARC_PERCPU_H
+#define ___ASM_SPARC_PERCPU_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/percpu_64.h>
+#else
+#include <asm-sparc/percpu_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/percpu_32.h b/include/asm-sparc/percpu_32.h
new file mode 100644
index 0000000..06066a7
--- /dev/null
+++ b/include/asm-sparc/percpu_32.h
@@ -0,0 +1,6 @@
+#ifndef __ARCH_SPARC_PERCPU__
+#define __ARCH_SPARC_PERCPU__
+
+#include <asm-generic/percpu.h>
+
+#endif /* __ARCH_SPARC_PERCPU__ */
diff --git a/include/asm-sparc/percpu_64.h b/include/asm-sparc/percpu_64.h
new file mode 100644
index 0000000..bee6459
--- /dev/null
+++ b/include/asm-sparc/percpu_64.h
@@ -0,0 +1,28 @@
+#ifndef __ARCH_SPARC64_PERCPU__
+#define __ARCH_SPARC64_PERCPU__
+
+#include <linux/compiler.h>
+
+register unsigned long __local_per_cpu_offset asm("g5");
+
+#ifdef CONFIG_SMP
+
+extern void real_setup_per_cpu_areas(void);
+
+extern unsigned long __per_cpu_base;
+extern unsigned long __per_cpu_shift;
+#define __per_cpu_offset(__cpu) \
+	(__per_cpu_base + ((unsigned long)(__cpu) << __per_cpu_shift))
+#define per_cpu_offset(x) (__per_cpu_offset(x))
+
+#define __my_cpu_offset __local_per_cpu_offset
+
+#else /* ! SMP */
+
+#define real_setup_per_cpu_areas()		do { } while (0)
+
+#endif	/* SMP */
+
+#include <asm-generic/percpu.h>
+
+#endif /* __ARCH_SPARC64_PERCPU__ */
diff --git a/include/asm-sparc/pgalloc.h b/include/asm-sparc/pgalloc.h
index 681582d..7fa02b5 100644
--- a/include/asm-sparc/pgalloc.h
+++ b/include/asm-sparc/pgalloc.h
@@ -1,68 +1,8 @@
-#ifndef _SPARC_PGALLOC_H
-#define _SPARC_PGALLOC_H
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-
-#include <asm/page.h>
-#include <asm/btfixup.h>
-
-struct page;
-
-extern struct pgtable_cache_struct {
-	unsigned long *pgd_cache;
-	unsigned long *pte_cache;
-	unsigned long pgtable_cache_sz;
-	unsigned long pgd_cache_sz;
-} pgt_quicklists;
-#define pgd_quicklist           (pgt_quicklists.pgd_cache)
-#define pmd_quicklist           ((unsigned long *)0)
-#define pte_quicklist           (pgt_quicklists.pte_cache)
-#define pgtable_cache_size      (pgt_quicklists.pgtable_cache_sz)
-#define pgd_cache_size		(pgt_quicklists.pgd_cache_sz)
-
-extern void check_pgt_cache(void);
-BTFIXUPDEF_CALL(void,	 do_check_pgt_cache, int, int)
-#define do_check_pgt_cache(low,high) BTFIXUP_CALL(do_check_pgt_cache)(low,high)
-
-BTFIXUPDEF_CALL(pgd_t *, get_pgd_fast, void)
-#define get_pgd_fast()		BTFIXUP_CALL(get_pgd_fast)()
-
-BTFIXUPDEF_CALL(void, free_pgd_fast, pgd_t *)
-#define free_pgd_fast(pgd)	BTFIXUP_CALL(free_pgd_fast)(pgd)
-
-#define pgd_free(mm, pgd)	free_pgd_fast(pgd)
-#define pgd_alloc(mm)	get_pgd_fast()
-
-BTFIXUPDEF_CALL(void, pgd_set, pgd_t *, pmd_t *)
-#define pgd_set(pgdp,pmdp) BTFIXUP_CALL(pgd_set)(pgdp,pmdp)
-#define pgd_populate(MM, PGD, PMD)      pgd_set(PGD, PMD)
-
-BTFIXUPDEF_CALL(pmd_t *, pmd_alloc_one, struct mm_struct *, unsigned long)
-#define pmd_alloc_one(mm, address)	BTFIXUP_CALL(pmd_alloc_one)(mm, address)
-
-BTFIXUPDEF_CALL(void, free_pmd_fast, pmd_t *)
-#define free_pmd_fast(pmd)	BTFIXUP_CALL(free_pmd_fast)(pmd)
-
-#define pmd_free(mm, pmd)	free_pmd_fast(pmd)
-#define __pmd_free_tlb(tlb, pmd) pmd_free((tlb)->mm, pmd)
-
-BTFIXUPDEF_CALL(void, pmd_populate, pmd_t *, struct page *)
-#define pmd_populate(MM, PMD, PTE)        BTFIXUP_CALL(pmd_populate)(PMD, PTE)
-#define pmd_pgtable(pmd) pmd_page(pmd)
-BTFIXUPDEF_CALL(void, pmd_set, pmd_t *, pte_t *)
-#define pmd_populate_kernel(MM, PMD, PTE) BTFIXUP_CALL(pmd_set)(PMD, PTE)
-
-BTFIXUPDEF_CALL(pgtable_t , pte_alloc_one, struct mm_struct *, unsigned long)
-#define pte_alloc_one(mm, address)	BTFIXUP_CALL(pte_alloc_one)(mm, address)
-BTFIXUPDEF_CALL(pte_t *, pte_alloc_one_kernel, struct mm_struct *, unsigned long)
-#define pte_alloc_one_kernel(mm, addr)	BTFIXUP_CALL(pte_alloc_one_kernel)(mm, addr)
-
-BTFIXUPDEF_CALL(void, free_pte_fast, pte_t *)
-#define pte_free_kernel(mm, pte)	BTFIXUP_CALL(free_pte_fast)(pte)
-
-BTFIXUPDEF_CALL(void, pte_free, pgtable_t )
-#define pte_free(mm, pte)	BTFIXUP_CALL(pte_free)(pte)
-#define __pte_free_tlb(tlb, pte)	pte_free((tlb)->mm, pte)
-
-#endif /* _SPARC_PGALLOC_H */
+#ifndef ___ASM_SPARC_PGALLOC_H
+#define ___ASM_SPARC_PGALLOC_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/pgalloc_64.h>
+#else
+#include <asm-sparc/pgalloc_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/pgalloc_32.h b/include/asm-sparc/pgalloc_32.h
new file mode 100644
index 0000000..681582d
--- /dev/null
+++ b/include/asm-sparc/pgalloc_32.h
@@ -0,0 +1,68 @@
+#ifndef _SPARC_PGALLOC_H
+#define _SPARC_PGALLOC_H
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/page.h>
+#include <asm/btfixup.h>
+
+struct page;
+
+extern struct pgtable_cache_struct {
+	unsigned long *pgd_cache;
+	unsigned long *pte_cache;
+	unsigned long pgtable_cache_sz;
+	unsigned long pgd_cache_sz;
+} pgt_quicklists;
+#define pgd_quicklist           (pgt_quicklists.pgd_cache)
+#define pmd_quicklist           ((unsigned long *)0)
+#define pte_quicklist           (pgt_quicklists.pte_cache)
+#define pgtable_cache_size      (pgt_quicklists.pgtable_cache_sz)
+#define pgd_cache_size		(pgt_quicklists.pgd_cache_sz)
+
+extern void check_pgt_cache(void);
+BTFIXUPDEF_CALL(void,	 do_check_pgt_cache, int, int)
+#define do_check_pgt_cache(low,high) BTFIXUP_CALL(do_check_pgt_cache)(low,high)
+
+BTFIXUPDEF_CALL(pgd_t *, get_pgd_fast, void)
+#define get_pgd_fast()		BTFIXUP_CALL(get_pgd_fast)()
+
+BTFIXUPDEF_CALL(void, free_pgd_fast, pgd_t *)
+#define free_pgd_fast(pgd)	BTFIXUP_CALL(free_pgd_fast)(pgd)
+
+#define pgd_free(mm, pgd)	free_pgd_fast(pgd)
+#define pgd_alloc(mm)	get_pgd_fast()
+
+BTFIXUPDEF_CALL(void, pgd_set, pgd_t *, pmd_t *)
+#define pgd_set(pgdp,pmdp) BTFIXUP_CALL(pgd_set)(pgdp,pmdp)
+#define pgd_populate(MM, PGD, PMD)      pgd_set(PGD, PMD)
+
+BTFIXUPDEF_CALL(pmd_t *, pmd_alloc_one, struct mm_struct *, unsigned long)
+#define pmd_alloc_one(mm, address)	BTFIXUP_CALL(pmd_alloc_one)(mm, address)
+
+BTFIXUPDEF_CALL(void, free_pmd_fast, pmd_t *)
+#define free_pmd_fast(pmd)	BTFIXUP_CALL(free_pmd_fast)(pmd)
+
+#define pmd_free(mm, pmd)	free_pmd_fast(pmd)
+#define __pmd_free_tlb(tlb, pmd) pmd_free((tlb)->mm, pmd)
+
+BTFIXUPDEF_CALL(void, pmd_populate, pmd_t *, struct page *)
+#define pmd_populate(MM, PMD, PTE)        BTFIXUP_CALL(pmd_populate)(PMD, PTE)
+#define pmd_pgtable(pmd) pmd_page(pmd)
+BTFIXUPDEF_CALL(void, pmd_set, pmd_t *, pte_t *)
+#define pmd_populate_kernel(MM, PMD, PTE) BTFIXUP_CALL(pmd_set)(PMD, PTE)
+
+BTFIXUPDEF_CALL(pgtable_t , pte_alloc_one, struct mm_struct *, unsigned long)
+#define pte_alloc_one(mm, address)	BTFIXUP_CALL(pte_alloc_one)(mm, address)
+BTFIXUPDEF_CALL(pte_t *, pte_alloc_one_kernel, struct mm_struct *, unsigned long)
+#define pte_alloc_one_kernel(mm, addr)	BTFIXUP_CALL(pte_alloc_one_kernel)(mm, addr)
+
+BTFIXUPDEF_CALL(void, free_pte_fast, pte_t *)
+#define pte_free_kernel(mm, pte)	BTFIXUP_CALL(free_pte_fast)(pte)
+
+BTFIXUPDEF_CALL(void, pte_free, pgtable_t )
+#define pte_free(mm, pte)	BTFIXUP_CALL(pte_free)(pte)
+#define __pte_free_tlb(tlb, pte)	pte_free((tlb)->mm, pte)
+
+#endif /* _SPARC_PGALLOC_H */
diff --git a/include/asm-sparc/pgalloc_64.h b/include/asm-sparc/pgalloc_64.h
new file mode 100644
index 0000000..5bdfa2c
--- /dev/null
+++ b/include/asm-sparc/pgalloc_64.h
@@ -0,0 +1,81 @@
+#ifndef _SPARC64_PGALLOC_H
+#define _SPARC64_PGALLOC_H
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/quicklist.h>
+
+#include <asm/spitfire.h>
+#include <asm/cpudata.h>
+#include <asm/cacheflush.h>
+#include <asm/page.h>
+
+/* Page table allocation/freeing. */
+
+static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+	return quicklist_alloc(0, GFP_KERNEL, NULL);
+}
+
+static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+	quicklist_free(0, NULL, pgd);
+}
+
+#define pud_populate(MM, PUD, PMD)	pud_set(PUD, PMD)
+
+static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
+{
+	return quicklist_alloc(0, GFP_KERNEL, NULL);
+}
+
+static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+{
+	quicklist_free(0, NULL, pmd);
+}
+
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
+					  unsigned long address)
+{
+	return quicklist_alloc(0, GFP_KERNEL, NULL);
+}
+
+static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
+					unsigned long address)
+{
+	struct page *page;
+	void *pg;
+
+	pg = quicklist_alloc(0, GFP_KERNEL, NULL);
+	if (!pg)
+		return NULL;
+	page = virt_to_page(pg);
+	pgtable_page_ctor(page);
+	return page;
+}
+
+static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+{
+	quicklist_free(0, NULL, pte);
+}
+
+static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
+{
+	pgtable_page_dtor(ptepage);
+	quicklist_free_page(0, NULL, ptepage);
+}
+
+
+#define pmd_populate_kernel(MM, PMD, PTE)	pmd_set(PMD, PTE)
+#define pmd_populate(MM,PMD,PTE_PAGE)		\
+	pmd_populate_kernel(MM,PMD,page_address(PTE_PAGE))
+#define pmd_pgtable(pmd) pmd_page(pmd)
+
+static inline void check_pgt_cache(void)
+{
+	quicklist_trim(0, NULL, 25, 16);
+}
+
+#endif /* _SPARC64_PGALLOC_H */
diff --git a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h
index 6051229..63cdef5 100644
--- a/include/asm-sparc/pgtable.h
+++ b/include/asm-sparc/pgtable.h
@@ -1,475 +1,8 @@
-#ifndef _SPARC_PGTABLE_H
-#define _SPARC_PGTABLE_H
-
-/*  asm-sparc/pgtable.h:  Defines and functions used to work
- *                        with Sparc page tables.
- *
- *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- *  Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- */
-
-#include <asm-generic/4level-fixup.h>
-
-#include <linux/spinlock.h>
-#include <linux/swap.h>
-#include <asm/types.h>
-#ifdef CONFIG_SUN4
-#include <asm/pgtsun4.h>
+#ifndef ___ASM_SPARC_PGTABLE_H
+#define ___ASM_SPARC_PGTABLE_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/pgtable_64.h>
 #else
-#include <asm/pgtsun4c.h>
+#include <asm-sparc/pgtable_32.h>
 #endif
-#include <asm/pgtsrmmu.h>
-#include <asm/vac-ops.h>
-#include <asm/oplib.h>
-#include <asm/btfixup.h>
-#include <asm/system.h>
-
-#ifndef __ASSEMBLY__
-
-struct vm_area_struct;
-struct page;
-
-extern void load_mmu(void);
-extern unsigned long calc_highpages(void);
-
-BTFIXUPDEF_SIMM13(pgdir_shift)
-BTFIXUPDEF_SETHI(pgdir_size)
-BTFIXUPDEF_SETHI(pgdir_mask)
-
-BTFIXUPDEF_SIMM13(ptrs_per_pmd)
-BTFIXUPDEF_SIMM13(ptrs_per_pgd)
-BTFIXUPDEF_SIMM13(user_ptrs_per_pgd)
-
-#define pte_ERROR(e)   __builtin_trap()
-#define pmd_ERROR(e)   __builtin_trap()
-#define pgd_ERROR(e)   __builtin_trap()
-
-BTFIXUPDEF_INT(page_none)
-BTFIXUPDEF_INT(page_copy)
-BTFIXUPDEF_INT(page_readonly)
-BTFIXUPDEF_INT(page_kernel)
-
-#define PMD_SHIFT		SUN4C_PMD_SHIFT
-#define PMD_SIZE        	(1UL << PMD_SHIFT)
-#define PMD_MASK        	(~(PMD_SIZE-1))
-#define PMD_ALIGN(__addr) 	(((__addr) + ~PMD_MASK) & PMD_MASK)
-#define PGDIR_SHIFT     	BTFIXUP_SIMM13(pgdir_shift)
-#define PGDIR_SIZE      	BTFIXUP_SETHI(pgdir_size)
-#define PGDIR_MASK      	BTFIXUP_SETHI(pgdir_mask)
-#define PTRS_PER_PTE    	1024
-#define PTRS_PER_PMD    	BTFIXUP_SIMM13(ptrs_per_pmd)
-#define PTRS_PER_PGD    	BTFIXUP_SIMM13(ptrs_per_pgd)
-#define USER_PTRS_PER_PGD	BTFIXUP_SIMM13(user_ptrs_per_pgd)
-#define FIRST_USER_ADDRESS	0
-#define PTE_SIZE		(PTRS_PER_PTE*4)
-
-#define PAGE_NONE      __pgprot(BTFIXUP_INT(page_none))
-extern pgprot_t PAGE_SHARED;
-#define PAGE_COPY      __pgprot(BTFIXUP_INT(page_copy))
-#define PAGE_READONLY  __pgprot(BTFIXUP_INT(page_readonly))
-
-extern unsigned long page_kernel;
-
-#ifdef MODULE
-#define PAGE_KERNEL	page_kernel
-#else
-#define PAGE_KERNEL    __pgprot(BTFIXUP_INT(page_kernel))
 #endif
-
-/* Top-level page directory */
-extern pgd_t swapper_pg_dir[1024];
-
-extern void paging_init(void);
-
-/* Page table for 0-4MB for everybody, on the Sparc this
- * holds the same as on the i386.
- */
-extern pte_t pg0[1024];
-extern pte_t pg1[1024];
-extern pte_t pg2[1024];
-extern pte_t pg3[1024];
-
-extern unsigned long ptr_in_current_pgd;
-
-/* Here is a trick, since mmap.c need the initializer elements for
- * protection_map[] to be constant at compile time, I set the following
- * to all zeros.  I set it to the real values after I link in the
- * appropriate MMU page table routines at boot time.
- */
-#define __P000  __pgprot(0)
-#define __P001  __pgprot(0)
-#define __P010  __pgprot(0)
-#define __P011  __pgprot(0)
-#define __P100  __pgprot(0)
-#define __P101  __pgprot(0)
-#define __P110  __pgprot(0)
-#define __P111  __pgprot(0)
-
-#define __S000	__pgprot(0)
-#define __S001	__pgprot(0)
-#define __S010	__pgprot(0)
-#define __S011	__pgprot(0)
-#define __S100	__pgprot(0)
-#define __S101	__pgprot(0)
-#define __S110	__pgprot(0)
-#define __S111	__pgprot(0)
-
-extern int num_contexts;
-
-/* First physical page can be anywhere, the following is needed so that
- * va-->pa and vice versa conversions work properly without performance
- * hit for all __pa()/__va() operations.
- */
-extern unsigned long phys_base;
-extern unsigned long pfn_base;
-
-/*
- * BAD_PAGETABLE is used when we need a bogus page-table, while
- * BAD_PAGE is used for a bogus page.
- *
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc..
- */
-extern pte_t * __bad_pagetable(void);
-extern pte_t __bad_page(void);
-extern unsigned long empty_zero_page;
-
-#define BAD_PAGETABLE __bad_pagetable()
-#define BAD_PAGE __bad_page()
-#define ZERO_PAGE(vaddr) (virt_to_page(&empty_zero_page))
-
-/*
- */
-BTFIXUPDEF_CALL_CONST(struct page *, pmd_page, pmd_t)
-BTFIXUPDEF_CALL_CONST(unsigned long, pgd_page_vaddr, pgd_t)
-
-#define pmd_page(pmd) BTFIXUP_CALL(pmd_page)(pmd)
-#define pgd_page_vaddr(pgd) BTFIXUP_CALL(pgd_page_vaddr)(pgd)
-
-BTFIXUPDEF_SETHI(none_mask)
-BTFIXUPDEF_CALL_CONST(int, pte_present, pte_t)
-BTFIXUPDEF_CALL(void, pte_clear, pte_t *)
-
-static inline int pte_none(pte_t pte)
-{
-	return !(pte_val(pte) & ~BTFIXUP_SETHI(none_mask));
-}
-
-#define pte_present(pte) BTFIXUP_CALL(pte_present)(pte)
-#define pte_clear(mm,addr,pte) BTFIXUP_CALL(pte_clear)(pte)
-
-BTFIXUPDEF_CALL_CONST(int, pmd_bad, pmd_t)
-BTFIXUPDEF_CALL_CONST(int, pmd_present, pmd_t)
-BTFIXUPDEF_CALL(void, pmd_clear, pmd_t *)
-
-static inline int pmd_none(pmd_t pmd)
-{
-	return !(pmd_val(pmd) & ~BTFIXUP_SETHI(none_mask));
-}
-
-#define pmd_bad(pmd) BTFIXUP_CALL(pmd_bad)(pmd)
-#define pmd_present(pmd) BTFIXUP_CALL(pmd_present)(pmd)
-#define pmd_clear(pmd) BTFIXUP_CALL(pmd_clear)(pmd)
-
-BTFIXUPDEF_CALL_CONST(int, pgd_none, pgd_t)
-BTFIXUPDEF_CALL_CONST(int, pgd_bad, pgd_t)
-BTFIXUPDEF_CALL_CONST(int, pgd_present, pgd_t)
-BTFIXUPDEF_CALL(void, pgd_clear, pgd_t *)
-
-#define pgd_none(pgd) BTFIXUP_CALL(pgd_none)(pgd)
-#define pgd_bad(pgd) BTFIXUP_CALL(pgd_bad)(pgd)
-#define pgd_present(pgd) BTFIXUP_CALL(pgd_present)(pgd)
-#define pgd_clear(pgd) BTFIXUP_CALL(pgd_clear)(pgd)
-
-/*
- * The following only work if pte_present() is true.
- * Undefined behaviour if not..
- */
-BTFIXUPDEF_HALF(pte_writei)
-BTFIXUPDEF_HALF(pte_dirtyi)
-BTFIXUPDEF_HALF(pte_youngi)
-
-static int pte_write(pte_t pte) __attribute_const__;
-static inline int pte_write(pte_t pte)
-{
-	return pte_val(pte) & BTFIXUP_HALF(pte_writei);
-}
-
-static int pte_dirty(pte_t pte) __attribute_const__;
-static inline int pte_dirty(pte_t pte)
-{
-	return pte_val(pte) & BTFIXUP_HALF(pte_dirtyi);
-}
-
-static int pte_young(pte_t pte) __attribute_const__;
-static inline int pte_young(pte_t pte)
-{
-	return pte_val(pte) & BTFIXUP_HALF(pte_youngi);
-}
-
-/*
- * The following only work if pte_present() is not true.
- */
-BTFIXUPDEF_HALF(pte_filei)
-
-static int pte_file(pte_t pte) __attribute_const__;
-static inline int pte_file(pte_t pte)
-{
-	return pte_val(pte) & BTFIXUP_HALF(pte_filei);
-}
-
-static inline int pte_special(pte_t pte)
-{
-	return 0;
-}
-
-/*
- */
-BTFIXUPDEF_HALF(pte_wrprotecti)
-BTFIXUPDEF_HALF(pte_mkcleani)
-BTFIXUPDEF_HALF(pte_mkoldi)
-
-static pte_t pte_wrprotect(pte_t pte) __attribute_const__;
-static inline pte_t pte_wrprotect(pte_t pte)
-{
-	return __pte(pte_val(pte) & ~BTFIXUP_HALF(pte_wrprotecti));
-}
-
-static pte_t pte_mkclean(pte_t pte) __attribute_const__;
-static inline pte_t pte_mkclean(pte_t pte)
-{
-	return __pte(pte_val(pte) & ~BTFIXUP_HALF(pte_mkcleani));
-}
-
-static pte_t pte_mkold(pte_t pte) __attribute_const__;
-static inline pte_t pte_mkold(pte_t pte)
-{
-	return __pte(pte_val(pte) & ~BTFIXUP_HALF(pte_mkoldi));
-}
-
-BTFIXUPDEF_CALL_CONST(pte_t, pte_mkwrite, pte_t)
-BTFIXUPDEF_CALL_CONST(pte_t, pte_mkdirty, pte_t)
-BTFIXUPDEF_CALL_CONST(pte_t, pte_mkyoung, pte_t)
-
-#define pte_mkwrite(pte) BTFIXUP_CALL(pte_mkwrite)(pte)
-#define pte_mkdirty(pte) BTFIXUP_CALL(pte_mkdirty)(pte)
-#define pte_mkyoung(pte) BTFIXUP_CALL(pte_mkyoung)(pte)
-
-#define pte_mkspecial(pte)    (pte)
-
-#define pfn_pte(pfn, prot)		mk_pte(pfn_to_page(pfn), prot)
-
-BTFIXUPDEF_CALL(unsigned long,	 pte_pfn, pte_t)
-#define pte_pfn(pte) BTFIXUP_CALL(pte_pfn)(pte)
-#define pte_page(pte)	pfn_to_page(pte_pfn(pte))
-
-/*
- * Conversion functions: convert a page and protection to a page entry,
- * and a page entry and page directory to the page they refer to.
- */
-BTFIXUPDEF_CALL_CONST(pte_t, mk_pte, struct page *, pgprot_t)
-
-BTFIXUPDEF_CALL_CONST(pte_t, mk_pte_phys, unsigned long, pgprot_t)
-BTFIXUPDEF_CALL_CONST(pte_t, mk_pte_io, unsigned long, pgprot_t, int)
-BTFIXUPDEF_CALL_CONST(pgprot_t, pgprot_noncached, pgprot_t)
-
-#define mk_pte(page,pgprot) BTFIXUP_CALL(mk_pte)(page,pgprot)
-#define mk_pte_phys(page,pgprot) BTFIXUP_CALL(mk_pte_phys)(page,pgprot)
-#define mk_pte_io(page,pgprot,space) BTFIXUP_CALL(mk_pte_io)(page,pgprot,space)
-
-#define pgprot_noncached(pgprot) BTFIXUP_CALL(pgprot_noncached)(pgprot)
-
-BTFIXUPDEF_INT(pte_modify_mask)
-
-static pte_t pte_modify(pte_t pte, pgprot_t newprot) __attribute_const__;
-static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
-{
-	return __pte((pte_val(pte) & BTFIXUP_INT(pte_modify_mask)) |
-		pgprot_val(newprot));
-}
-
-#define pgd_index(address) ((address) >> PGDIR_SHIFT)
-
-/* to find an entry in a page-table-directory */
-#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address))
-
-/* to find an entry in a kernel page-table-directory */
-#define pgd_offset_k(address) pgd_offset(&init_mm, address)
-
-/* Find an entry in the second-level page table.. */
-BTFIXUPDEF_CALL(pmd_t *, pmd_offset, pgd_t *, unsigned long)
-#define pmd_offset(dir,addr) BTFIXUP_CALL(pmd_offset)(dir,addr)
-
-/* Find an entry in the third-level page table.. */ 
-BTFIXUPDEF_CALL(pte_t *, pte_offset_kernel, pmd_t *, unsigned long)
-#define pte_offset_kernel(dir,addr) BTFIXUP_CALL(pte_offset_kernel)(dir,addr)
-
-/*
- * This shortcut works on sun4m (and sun4d) because the nocache area is static,
- * and sun4c is guaranteed to have no highmem anyway.
- */
-#define pte_offset_map(d, a)		pte_offset_kernel(d,a)
-#define pte_offset_map_nested(d, a)	pte_offset_kernel(d,a)
-
-#define pte_unmap(pte)		do{}while(0)
-#define pte_unmap_nested(pte)	do{}while(0)
-
-/* Certain architectures need to do special things when pte's
- * within a page table are directly modified.  Thus, the following
- * hook is made available.
- */
-
-BTFIXUPDEF_CALL(void, set_pte, pte_t *, pte_t)
-
-#define set_pte(ptep,pteval) BTFIXUP_CALL(set_pte)(ptep,pteval)
-#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
-
-struct seq_file;
-BTFIXUPDEF_CALL(void, mmu_info, struct seq_file *)
-
-#define mmu_info(p) BTFIXUP_CALL(mmu_info)(p)
-
-/* Fault handler stuff... */
-#define FAULT_CODE_PROT     0x1
-#define FAULT_CODE_WRITE    0x2
-#define FAULT_CODE_USER     0x4
-
-BTFIXUPDEF_CALL(void, update_mmu_cache, struct vm_area_struct *, unsigned long, pte_t)
-
-#define update_mmu_cache(vma,addr,pte) BTFIXUP_CALL(update_mmu_cache)(vma,addr,pte)
-
-BTFIXUPDEF_CALL(void, sparc_mapiorange, unsigned int, unsigned long,
-    unsigned long, unsigned int)
-BTFIXUPDEF_CALL(void, sparc_unmapiorange, unsigned long, unsigned int)
-#define sparc_mapiorange(bus,pa,va,len) BTFIXUP_CALL(sparc_mapiorange)(bus,pa,va,len)
-#define sparc_unmapiorange(va,len) BTFIXUP_CALL(sparc_unmapiorange)(va,len)
-
-extern int invalid_segment;
-
-/* Encode and de-code a swap entry */
-BTFIXUPDEF_CALL(unsigned long, __swp_type, swp_entry_t)
-BTFIXUPDEF_CALL(unsigned long, __swp_offset, swp_entry_t)
-BTFIXUPDEF_CALL(swp_entry_t, __swp_entry, unsigned long, unsigned long)
-
-#define __swp_type(__x)			BTFIXUP_CALL(__swp_type)(__x)
-#define __swp_offset(__x)		BTFIXUP_CALL(__swp_offset)(__x)
-#define __swp_entry(__type,__off)	BTFIXUP_CALL(__swp_entry)(__type,__off)
-
-#define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
-#define __swp_entry_to_pte(x)		((pte_t) { (x).val })
-
-/* file-offset-in-pte helpers */
-BTFIXUPDEF_CALL(unsigned long, pte_to_pgoff, pte_t pte);
-BTFIXUPDEF_CALL(pte_t, pgoff_to_pte, unsigned long pgoff);
-
-#define pte_to_pgoff(pte) BTFIXUP_CALL(pte_to_pgoff)(pte)
-#define pgoff_to_pte(off) BTFIXUP_CALL(pgoff_to_pte)(off)
-
-/*
- * This is made a constant because mm/fremap.c required a constant.
- * Note that layout of these bits is different between sun4c.c and srmmu.c.
- */
-#define PTE_FILE_MAX_BITS 24
-
-/*
- */
-struct ctx_list {
-	struct ctx_list *next;
-	struct ctx_list *prev;
-	unsigned int ctx_number;
-	struct mm_struct *ctx_mm;
-};
-
-extern struct ctx_list *ctx_list_pool;  /* Dynamically allocated */
-extern struct ctx_list ctx_free;        /* Head of free list */
-extern struct ctx_list ctx_used;        /* Head of used contexts list */
-
-#define NO_CONTEXT     -1
-
-static inline void remove_from_ctx_list(struct ctx_list *entry)
-{
-	entry->next->prev = entry->prev;
-	entry->prev->next = entry->next;
-}
-
-static inline void add_to_ctx_list(struct ctx_list *head, struct ctx_list *entry)
-{
-	entry->next = head;
-	(entry->prev = head->prev)->next = entry;
-	head->prev = entry;
-}
-#define add_to_free_ctxlist(entry) add_to_ctx_list(&ctx_free, entry)
-#define add_to_used_ctxlist(entry) add_to_ctx_list(&ctx_used, entry)
-
-static inline unsigned long
-__get_phys (unsigned long addr)
-{
-	switch (sparc_cpu_model){
-	case sun4:
-	case sun4c:
-		return sun4c_get_pte (addr) << PAGE_SHIFT;
-	case sun4m:
-	case sun4d:
-		return ((srmmu_get_pte (addr) & 0xffffff00) << 4);
-	default:
-		return 0;
-	}
-}
-
-static inline int
-__get_iospace (unsigned long addr)
-{
-	switch (sparc_cpu_model){
-	case sun4:
-	case sun4c:
-		return -1; /* Don't check iospace on sun4c */
-	case sun4m:
-	case sun4d:
-		return (srmmu_get_pte (addr) >> 28);
-	default:
-		return -1;
-	}
-}
-
-extern unsigned long *sparc_valid_addr_bitmap;
-
-/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
-#define kern_addr_valid(addr) \
-	(test_bit(__pa((unsigned long)(addr))>>20, sparc_valid_addr_bitmap))
-
-extern int io_remap_pfn_range(struct vm_area_struct *vma,
-			      unsigned long from, unsigned long pfn,
-			      unsigned long size, pgprot_t prot);
-
-/*
- * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
- * its high 4 bits.  These macros/functions put it there or get it from there.
- */
-#define MK_IOSPACE_PFN(space, pfn)	(pfn | (space << (BITS_PER_LONG - 4)))
-#define GET_IOSPACE(pfn)		(pfn >> (BITS_PER_LONG - 4))
-#define GET_PFN(pfn)			(pfn & 0x0fffffffUL)
-
-#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
-#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
-({									  \
-	int __changed = !pte_same(*(__ptep), __entry);			  \
-	if (__changed) {						  \
-		set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \
-		flush_tlb_page(__vma, __address);			  \
-	}								  \
-	(sparc_cpu_model == sun4c) || __changed;			  \
-})
-
-#include <asm-generic/pgtable.h>
-
-#endif /* !(__ASSEMBLY__) */
-
-/* We provide our own get_unmapped_area to cope with VA holes for userland */
-#define HAVE_ARCH_UNMAPPED_AREA
-
-/*
- * No page table caches to initialise
- */
-#define pgtable_cache_init()	do { } while (0)
-
-#endif /* !(_SPARC_PGTABLE_H) */
diff --git a/include/asm-sparc/pgtable_32.h b/include/asm-sparc/pgtable_32.h
new file mode 100644
index 0000000..781bd46
--- /dev/null
+++ b/include/asm-sparc/pgtable_32.h
@@ -0,0 +1,480 @@
+#ifndef _SPARC_PGTABLE_H
+#define _SPARC_PGTABLE_H
+
+/*  asm-sparc/pgtable.h:  Defines and functions used to work
+ *                        with Sparc page tables.
+ *
+ *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ *  Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#ifndef __ASSEMBLY__
+#include <asm-generic/4level-fixup.h>
+
+#include <linux/spinlock.h>
+#include <linux/swap.h>
+#include <asm/types.h>
+#ifdef CONFIG_SUN4
+#include <asm/pgtsun4.h>
+#else
+#include <asm/pgtsun4c.h>
+#endif
+#include <asm/pgtsrmmu.h>
+#include <asm/vac-ops.h>
+#include <asm/oplib.h>
+#include <asm/btfixup.h>
+#include <asm/system.h>
+
+
+struct vm_area_struct;
+struct page;
+
+extern void load_mmu(void);
+extern unsigned long calc_highpages(void);
+
+BTFIXUPDEF_SIMM13(pgdir_shift)
+BTFIXUPDEF_SETHI(pgdir_size)
+BTFIXUPDEF_SETHI(pgdir_mask)
+
+BTFIXUPDEF_SIMM13(ptrs_per_pmd)
+BTFIXUPDEF_SIMM13(ptrs_per_pgd)
+BTFIXUPDEF_SIMM13(user_ptrs_per_pgd)
+
+#define pte_ERROR(e)   __builtin_trap()
+#define pmd_ERROR(e)   __builtin_trap()
+#define pgd_ERROR(e)   __builtin_trap()
+
+BTFIXUPDEF_INT(page_none)
+BTFIXUPDEF_INT(page_copy)
+BTFIXUPDEF_INT(page_readonly)
+BTFIXUPDEF_INT(page_kernel)
+
+#define PMD_SHIFT		SUN4C_PMD_SHIFT
+#define PMD_SIZE        	(1UL << PMD_SHIFT)
+#define PMD_MASK        	(~(PMD_SIZE-1))
+#define PMD_ALIGN(__addr) 	(((__addr) + ~PMD_MASK) & PMD_MASK)
+#define PGDIR_SHIFT     	BTFIXUP_SIMM13(pgdir_shift)
+#define PGDIR_SIZE      	BTFIXUP_SETHI(pgdir_size)
+#define PGDIR_MASK      	BTFIXUP_SETHI(pgdir_mask)
+#define PTRS_PER_PTE    	1024
+#define PTRS_PER_PMD    	BTFIXUP_SIMM13(ptrs_per_pmd)
+#define PTRS_PER_PGD    	BTFIXUP_SIMM13(ptrs_per_pgd)
+#define USER_PTRS_PER_PGD	BTFIXUP_SIMM13(user_ptrs_per_pgd)
+#define FIRST_USER_ADDRESS	0
+#define PTE_SIZE		(PTRS_PER_PTE*4)
+
+#define PAGE_NONE      __pgprot(BTFIXUP_INT(page_none))
+extern pgprot_t PAGE_SHARED;
+#define PAGE_COPY      __pgprot(BTFIXUP_INT(page_copy))
+#define PAGE_READONLY  __pgprot(BTFIXUP_INT(page_readonly))
+
+extern unsigned long page_kernel;
+
+#ifdef MODULE
+#define PAGE_KERNEL	page_kernel
+#else
+#define PAGE_KERNEL    __pgprot(BTFIXUP_INT(page_kernel))
+#endif
+
+/* Top-level page directory */
+extern pgd_t swapper_pg_dir[1024];
+
+extern void paging_init(void);
+
+/* Page table for 0-4MB for everybody, on the Sparc this
+ * holds the same as on the i386.
+ */
+extern pte_t pg0[1024];
+extern pte_t pg1[1024];
+extern pte_t pg2[1024];
+extern pte_t pg3[1024];
+
+extern unsigned long ptr_in_current_pgd;
+
+/* Here is a trick, since mmap.c need the initializer elements for
+ * protection_map[] to be constant at compile time, I set the following
+ * to all zeros.  I set it to the real values after I link in the
+ * appropriate MMU page table routines at boot time.
+ */
+#define __P000  __pgprot(0)
+#define __P001  __pgprot(0)
+#define __P010  __pgprot(0)
+#define __P011  __pgprot(0)
+#define __P100  __pgprot(0)
+#define __P101  __pgprot(0)
+#define __P110  __pgprot(0)
+#define __P111  __pgprot(0)
+
+#define __S000	__pgprot(0)
+#define __S001	__pgprot(0)
+#define __S010	__pgprot(0)
+#define __S011	__pgprot(0)
+#define __S100	__pgprot(0)
+#define __S101	__pgprot(0)
+#define __S110	__pgprot(0)
+#define __S111	__pgprot(0)
+
+extern int num_contexts;
+
+/* First physical page can be anywhere, the following is needed so that
+ * va-->pa and vice versa conversions work properly without performance
+ * hit for all __pa()/__va() operations.
+ */
+extern unsigned long phys_base;
+extern unsigned long pfn_base;
+
+/*
+ * BAD_PAGETABLE is used when we need a bogus page-table, while
+ * BAD_PAGE is used for a bogus page.
+ *
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern pte_t * __bad_pagetable(void);
+extern pte_t __bad_page(void);
+extern unsigned long empty_zero_page;
+
+#define BAD_PAGETABLE __bad_pagetable()
+#define BAD_PAGE __bad_page()
+#define ZERO_PAGE(vaddr) (virt_to_page(&empty_zero_page))
+
+/*
+ */
+BTFIXUPDEF_CALL_CONST(struct page *, pmd_page, pmd_t)
+BTFIXUPDEF_CALL_CONST(unsigned long, pgd_page_vaddr, pgd_t)
+
+#define pmd_page(pmd) BTFIXUP_CALL(pmd_page)(pmd)
+#define pgd_page_vaddr(pgd) BTFIXUP_CALL(pgd_page_vaddr)(pgd)
+
+BTFIXUPDEF_SETHI(none_mask)
+BTFIXUPDEF_CALL_CONST(int, pte_present, pte_t)
+BTFIXUPDEF_CALL(void, pte_clear, pte_t *)
+
+static inline int pte_none(pte_t pte)
+{
+	return !(pte_val(pte) & ~BTFIXUP_SETHI(none_mask));
+}
+
+#define pte_present(pte) BTFIXUP_CALL(pte_present)(pte)
+#define pte_clear(mm,addr,pte) BTFIXUP_CALL(pte_clear)(pte)
+
+BTFIXUPDEF_CALL_CONST(int, pmd_bad, pmd_t)
+BTFIXUPDEF_CALL_CONST(int, pmd_present, pmd_t)
+BTFIXUPDEF_CALL(void, pmd_clear, pmd_t *)
+
+static inline int pmd_none(pmd_t pmd)
+{
+	return !(pmd_val(pmd) & ~BTFIXUP_SETHI(none_mask));
+}
+
+#define pmd_bad(pmd) BTFIXUP_CALL(pmd_bad)(pmd)
+#define pmd_present(pmd) BTFIXUP_CALL(pmd_present)(pmd)
+#define pmd_clear(pmd) BTFIXUP_CALL(pmd_clear)(pmd)
+
+BTFIXUPDEF_CALL_CONST(int, pgd_none, pgd_t)
+BTFIXUPDEF_CALL_CONST(int, pgd_bad, pgd_t)
+BTFIXUPDEF_CALL_CONST(int, pgd_present, pgd_t)
+BTFIXUPDEF_CALL(void, pgd_clear, pgd_t *)
+
+#define pgd_none(pgd) BTFIXUP_CALL(pgd_none)(pgd)
+#define pgd_bad(pgd) BTFIXUP_CALL(pgd_bad)(pgd)
+#define pgd_present(pgd) BTFIXUP_CALL(pgd_present)(pgd)
+#define pgd_clear(pgd) BTFIXUP_CALL(pgd_clear)(pgd)
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+BTFIXUPDEF_HALF(pte_writei)
+BTFIXUPDEF_HALF(pte_dirtyi)
+BTFIXUPDEF_HALF(pte_youngi)
+
+static int pte_write(pte_t pte) __attribute_const__;
+static inline int pte_write(pte_t pte)
+{
+	return pte_val(pte) & BTFIXUP_HALF(pte_writei);
+}
+
+static int pte_dirty(pte_t pte) __attribute_const__;
+static inline int pte_dirty(pte_t pte)
+{
+	return pte_val(pte) & BTFIXUP_HALF(pte_dirtyi);
+}
+
+static int pte_young(pte_t pte) __attribute_const__;
+static inline int pte_young(pte_t pte)
+{
+	return pte_val(pte) & BTFIXUP_HALF(pte_youngi);
+}
+
+/*
+ * The following only work if pte_present() is not true.
+ */
+BTFIXUPDEF_HALF(pte_filei)
+
+static int pte_file(pte_t pte) __attribute_const__;
+static inline int pte_file(pte_t pte)
+{
+	return pte_val(pte) & BTFIXUP_HALF(pte_filei);
+}
+
+static inline int pte_special(pte_t pte)
+{
+	return 0;
+}
+
+/*
+ */
+BTFIXUPDEF_HALF(pte_wrprotecti)
+BTFIXUPDEF_HALF(pte_mkcleani)
+BTFIXUPDEF_HALF(pte_mkoldi)
+
+static pte_t pte_wrprotect(pte_t pte) __attribute_const__;
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+	return __pte(pte_val(pte) & ~BTFIXUP_HALF(pte_wrprotecti));
+}
+
+static pte_t pte_mkclean(pte_t pte) __attribute_const__;
+static inline pte_t pte_mkclean(pte_t pte)
+{
+	return __pte(pte_val(pte) & ~BTFIXUP_HALF(pte_mkcleani));
+}
+
+static pte_t pte_mkold(pte_t pte) __attribute_const__;
+static inline pte_t pte_mkold(pte_t pte)
+{
+	return __pte(pte_val(pte) & ~BTFIXUP_HALF(pte_mkoldi));
+}
+
+BTFIXUPDEF_CALL_CONST(pte_t, pte_mkwrite, pte_t)
+BTFIXUPDEF_CALL_CONST(pte_t, pte_mkdirty, pte_t)
+BTFIXUPDEF_CALL_CONST(pte_t, pte_mkyoung, pte_t)
+
+#define pte_mkwrite(pte) BTFIXUP_CALL(pte_mkwrite)(pte)
+#define pte_mkdirty(pte) BTFIXUP_CALL(pte_mkdirty)(pte)
+#define pte_mkyoung(pte) BTFIXUP_CALL(pte_mkyoung)(pte)
+
+#define pte_mkspecial(pte)    (pte)
+
+#define pfn_pte(pfn, prot)		mk_pte(pfn_to_page(pfn), prot)
+
+BTFIXUPDEF_CALL(unsigned long,	 pte_pfn, pte_t)
+#define pte_pfn(pte) BTFIXUP_CALL(pte_pfn)(pte)
+#define pte_page(pte)	pfn_to_page(pte_pfn(pte))
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+BTFIXUPDEF_CALL_CONST(pte_t, mk_pte, struct page *, pgprot_t)
+
+BTFIXUPDEF_CALL_CONST(pte_t, mk_pte_phys, unsigned long, pgprot_t)
+BTFIXUPDEF_CALL_CONST(pte_t, mk_pte_io, unsigned long, pgprot_t, int)
+BTFIXUPDEF_CALL_CONST(pgprot_t, pgprot_noncached, pgprot_t)
+
+#define mk_pte(page,pgprot) BTFIXUP_CALL(mk_pte)(page,pgprot)
+#define mk_pte_phys(page,pgprot) BTFIXUP_CALL(mk_pte_phys)(page,pgprot)
+#define mk_pte_io(page,pgprot,space) BTFIXUP_CALL(mk_pte_io)(page,pgprot,space)
+
+#define pgprot_noncached(pgprot) BTFIXUP_CALL(pgprot_noncached)(pgprot)
+
+BTFIXUPDEF_INT(pte_modify_mask)
+
+static pte_t pte_modify(pte_t pte, pgprot_t newprot) __attribute_const__;
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+	return __pte((pte_val(pte) & BTFIXUP_INT(pte_modify_mask)) |
+		pgprot_val(newprot));
+}
+
+#define pgd_index(address) ((address) >> PGDIR_SHIFT)
+
+/* to find an entry in a page-table-directory */
+#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address))
+
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+
+/* Find an entry in the second-level page table.. */
+BTFIXUPDEF_CALL(pmd_t *, pmd_offset, pgd_t *, unsigned long)
+#define pmd_offset(dir,addr) BTFIXUP_CALL(pmd_offset)(dir,addr)
+
+/* Find an entry in the third-level page table.. */
+BTFIXUPDEF_CALL(pte_t *, pte_offset_kernel, pmd_t *, unsigned long)
+#define pte_offset_kernel(dir,addr) BTFIXUP_CALL(pte_offset_kernel)(dir,addr)
+
+/*
+ * This shortcut works on sun4m (and sun4d) because the nocache area is static,
+ * and sun4c is guaranteed to have no highmem anyway.
+ */
+#define pte_offset_map(d, a)		pte_offset_kernel(d,a)
+#define pte_offset_map_nested(d, a)	pte_offset_kernel(d,a)
+
+#define pte_unmap(pte)		do{}while(0)
+#define pte_unmap_nested(pte)	do{}while(0)
+
+/* Certain architectures need to do special things when pte's
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
+
+BTFIXUPDEF_CALL(void, set_pte, pte_t *, pte_t)
+
+#define set_pte(ptep,pteval) BTFIXUP_CALL(set_pte)(ptep,pteval)
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
+
+struct seq_file;
+BTFIXUPDEF_CALL(void, mmu_info, struct seq_file *)
+
+#define mmu_info(p) BTFIXUP_CALL(mmu_info)(p)
+
+/* Fault handler stuff... */
+#define FAULT_CODE_PROT     0x1
+#define FAULT_CODE_WRITE    0x2
+#define FAULT_CODE_USER     0x4
+
+BTFIXUPDEF_CALL(void, update_mmu_cache, struct vm_area_struct *, unsigned long, pte_t)
+
+#define update_mmu_cache(vma,addr,pte) BTFIXUP_CALL(update_mmu_cache)(vma,addr,pte)
+
+BTFIXUPDEF_CALL(void, sparc_mapiorange, unsigned int, unsigned long,
+    unsigned long, unsigned int)
+BTFIXUPDEF_CALL(void, sparc_unmapiorange, unsigned long, unsigned int)
+#define sparc_mapiorange(bus,pa,va,len) BTFIXUP_CALL(sparc_mapiorange)(bus,pa,va,len)
+#define sparc_unmapiorange(va,len) BTFIXUP_CALL(sparc_unmapiorange)(va,len)
+
+extern int invalid_segment;
+
+/* Encode and de-code a swap entry */
+BTFIXUPDEF_CALL(unsigned long, __swp_type, swp_entry_t)
+BTFIXUPDEF_CALL(unsigned long, __swp_offset, swp_entry_t)
+BTFIXUPDEF_CALL(swp_entry_t, __swp_entry, unsigned long, unsigned long)
+
+#define __swp_type(__x)			BTFIXUP_CALL(__swp_type)(__x)
+#define __swp_offset(__x)		BTFIXUP_CALL(__swp_offset)(__x)
+#define __swp_entry(__type,__off)	BTFIXUP_CALL(__swp_entry)(__type,__off)
+
+#define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
+#define __swp_entry_to_pte(x)		((pte_t) { (x).val })
+
+/* file-offset-in-pte helpers */
+BTFIXUPDEF_CALL(unsigned long, pte_to_pgoff, pte_t pte);
+BTFIXUPDEF_CALL(pte_t, pgoff_to_pte, unsigned long pgoff);
+
+#define pte_to_pgoff(pte) BTFIXUP_CALL(pte_to_pgoff)(pte)
+#define pgoff_to_pte(off) BTFIXUP_CALL(pgoff_to_pte)(off)
+
+/*
+ * This is made a constant because mm/fremap.c required a constant.
+ * Note that layout of these bits is different between sun4c.c and srmmu.c.
+ */
+#define PTE_FILE_MAX_BITS 24
+
+/*
+ */
+struct ctx_list {
+	struct ctx_list *next;
+	struct ctx_list *prev;
+	unsigned int ctx_number;
+	struct mm_struct *ctx_mm;
+};
+
+extern struct ctx_list *ctx_list_pool;  /* Dynamically allocated */
+extern struct ctx_list ctx_free;        /* Head of free list */
+extern struct ctx_list ctx_used;        /* Head of used contexts list */
+
+#define NO_CONTEXT     -1
+
+static inline void remove_from_ctx_list(struct ctx_list *entry)
+{
+	entry->next->prev = entry->prev;
+	entry->prev->next = entry->next;
+}
+
+static inline void add_to_ctx_list(struct ctx_list *head, struct ctx_list *entry)
+{
+	entry->next = head;
+	(entry->prev = head->prev)->next = entry;
+	head->prev = entry;
+}
+#define add_to_free_ctxlist(entry) add_to_ctx_list(&ctx_free, entry)
+#define add_to_used_ctxlist(entry) add_to_ctx_list(&ctx_used, entry)
+
+static inline unsigned long
+__get_phys (unsigned long addr)
+{
+	switch (sparc_cpu_model){
+	case sun4:
+	case sun4c:
+		return sun4c_get_pte (addr) << PAGE_SHIFT;
+	case sun4m:
+	case sun4d:
+		return ((srmmu_get_pte (addr) & 0xffffff00) << 4);
+	default:
+		return 0;
+	}
+}
+
+static inline int
+__get_iospace (unsigned long addr)
+{
+	switch (sparc_cpu_model){
+	case sun4:
+	case sun4c:
+		return -1; /* Don't check iospace on sun4c */
+	case sun4m:
+	case sun4d:
+		return (srmmu_get_pte (addr) >> 28);
+	default:
+		return -1;
+	}
+}
+
+extern unsigned long *sparc_valid_addr_bitmap;
+
+/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
+#define kern_addr_valid(addr) \
+	(test_bit(__pa((unsigned long)(addr))>>20, sparc_valid_addr_bitmap))
+
+extern int io_remap_pfn_range(struct vm_area_struct *vma,
+			      unsigned long from, unsigned long pfn,
+			      unsigned long size, pgprot_t prot);
+
+/*
+ * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
+ * its high 4 bits.  These macros/functions put it there or get it from there.
+ */
+#define MK_IOSPACE_PFN(space, pfn)	(pfn | (space << (BITS_PER_LONG - 4)))
+#define GET_IOSPACE(pfn)		(pfn >> (BITS_PER_LONG - 4))
+#define GET_PFN(pfn)			(pfn & 0x0fffffffUL)
+
+#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
+({									  \
+	int __changed = !pte_same(*(__ptep), __entry);			  \
+	if (__changed) {						  \
+		set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \
+		flush_tlb_page(__vma, __address);			  \
+	}								  \
+	(sparc_cpu_model == sun4c) || __changed;			  \
+})
+
+#include <asm-generic/pgtable.h>
+
+#endif /* !(__ASSEMBLY__) */
+
+#define VMALLOC_START           0xfe600000
+/* XXX Alter this when I get around to fixing sun4c - Anton */
+#define VMALLOC_END             0xffc00000
+
+
+/* We provide our own get_unmapped_area to cope with VA holes for userland */
+#define HAVE_ARCH_UNMAPPED_AREA
+
+/*
+ * No page table caches to initialise
+ */
+#define pgtable_cache_init()	do { } while (0)
+
+#endif /* !(_SPARC_PGTABLE_H) */
diff --git a/include/asm-sparc/pgtable_64.h b/include/asm-sparc/pgtable_64.h
new file mode 100644
index 0000000..bb9ec2c
--- /dev/null
+++ b/include/asm-sparc/pgtable_64.h
@@ -0,0 +1,775 @@
+/*
+ * pgtable.h: SpitFire page table operations.
+ *
+ * Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#ifndef _SPARC64_PGTABLE_H
+#define _SPARC64_PGTABLE_H
+
+/* This file contains the functions and defines necessary to modify and use
+ * the SpitFire page tables.
+ */
+
+#include <asm-generic/pgtable-nopud.h>
+
+#include <linux/compiler.h>
+#include <linux/const.h>
+#include <asm/types.h>
+#include <asm/spitfire.h>
+#include <asm/asi.h>
+#include <asm/system.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+
+/* The kernel image occupies 0x4000000 to 0x6000000 (4MB --> 96MB).
+ * The page copy blockops can use 0x6000000 to 0x8000000.
+ * The TSB is mapped in the 0x8000000 to 0xa000000 range.
+ * The PROM resides in an area spanning 0xf0000000 to 0x100000000.
+ * The vmalloc area spans 0x100000000 to 0x200000000.
+ * Since modules need to be in the lowest 32-bits of the address space,
+ * we place them right before the OBP area from 0x10000000 to 0xf0000000.
+ * There is a single static kernel PMD which maps from 0x0 to address
+ * 0x400000000.
+ */
+#define	TLBTEMP_BASE		_AC(0x0000000006000000,UL)
+#define	TSBMAP_BASE		_AC(0x0000000008000000,UL)
+#define MODULES_VADDR		_AC(0x0000000010000000,UL)
+#define MODULES_LEN		_AC(0x00000000e0000000,UL)
+#define MODULES_END		_AC(0x00000000f0000000,UL)
+#define LOW_OBP_ADDRESS		_AC(0x00000000f0000000,UL)
+#define HI_OBP_ADDRESS		_AC(0x0000000100000000,UL)
+#define VMALLOC_START		_AC(0x0000000100000000,UL)
+#define VMALLOC_END		_AC(0x0000000200000000,UL)
+#define VMEMMAP_BASE		_AC(0x0000000200000000,UL)
+
+#define vmemmap			((struct page *)VMEMMAP_BASE)
+
+/* XXX All of this needs to be rethought so we can take advantage
+ * XXX cheetah's full 64-bit virtual address space, ie. no more hole
+ * XXX in the middle like on spitfire. -DaveM
+ */
+/*
+ * Given a virtual address, the lowest PAGE_SHIFT bits determine offset
+ * into the page; the next higher PAGE_SHIFT-3 bits determine the pte#
+ * in the proper pagetable (the -3 is from the 8 byte ptes, and each page
+ * table is a single page long). The next higher PMD_BITS determine pmd#
+ * in the proper pmdtable (where we must have PMD_BITS <= (PAGE_SHIFT-2)
+ * since the pmd entries are 4 bytes, and each pmd page is a single page
+ * long). Finally, the higher few bits determine pgde#.
+ */
+
+/* PMD_SHIFT determines the size of the area a second-level page
+ * table can map
+ */
+#define PMD_SHIFT	(PAGE_SHIFT + (PAGE_SHIFT-3))
+#define PMD_SIZE	(_AC(1,UL) << PMD_SHIFT)
+#define PMD_MASK	(~(PMD_SIZE-1))
+#define PMD_BITS	(PAGE_SHIFT - 2)
+
+/* PGDIR_SHIFT determines what a third-level page table entry can map */
+#define PGDIR_SHIFT	(PAGE_SHIFT + (PAGE_SHIFT-3) + PMD_BITS)
+#define PGDIR_SIZE	(_AC(1,UL) << PGDIR_SHIFT)
+#define PGDIR_MASK	(~(PGDIR_SIZE-1))
+#define PGDIR_BITS	(PAGE_SHIFT - 2)
+
+#ifndef __ASSEMBLY__
+
+#include <linux/sched.h>
+
+/* Entries per page directory level. */
+#define PTRS_PER_PTE	(1UL << (PAGE_SHIFT-3))
+#define PTRS_PER_PMD	(1UL << PMD_BITS)
+#define PTRS_PER_PGD	(1UL << PGDIR_BITS)
+
+/* Kernel has a separate 44bit address space. */
+#define FIRST_USER_ADDRESS	0
+
+#define pte_ERROR(e)	__builtin_trap()
+#define pmd_ERROR(e)	__builtin_trap()
+#define pgd_ERROR(e)	__builtin_trap()
+
+#endif /* !(__ASSEMBLY__) */
+
+/* PTE bits which are the same in SUN4U and SUN4V format.  */
+#define _PAGE_VALID	  _AC(0x8000000000000000,UL) /* Valid TTE            */
+#define _PAGE_R	  	  _AC(0x8000000000000000,UL) /* Keep ref bit uptodate*/
+
+/* SUN4U pte bits... */
+#define _PAGE_SZ4MB_4U	  _AC(0x6000000000000000,UL) /* 4MB Page             */
+#define _PAGE_SZ512K_4U	  _AC(0x4000000000000000,UL) /* 512K Page            */
+#define _PAGE_SZ64K_4U	  _AC(0x2000000000000000,UL) /* 64K Page             */
+#define _PAGE_SZ8K_4U	  _AC(0x0000000000000000,UL) /* 8K Page              */
+#define _PAGE_NFO_4U	  _AC(0x1000000000000000,UL) /* No Fault Only        */
+#define _PAGE_IE_4U	  _AC(0x0800000000000000,UL) /* Invert Endianness    */
+#define _PAGE_SOFT2_4U	  _AC(0x07FC000000000000,UL) /* Software bits, set 2 */
+#define _PAGE_RES1_4U	  _AC(0x0002000000000000,UL) /* Reserved             */
+#define _PAGE_SZ32MB_4U	  _AC(0x0001000000000000,UL) /* (Panther) 32MB page  */
+#define _PAGE_SZ256MB_4U  _AC(0x2001000000000000,UL) /* (Panther) 256MB page */
+#define _PAGE_SZALL_4U	  _AC(0x6001000000000000,UL) /* All pgsz bits        */
+#define _PAGE_SN_4U	  _AC(0x0000800000000000,UL) /* (Cheetah) Snoop      */
+#define _PAGE_RES2_4U	  _AC(0x0000780000000000,UL) /* Reserved             */
+#define _PAGE_PADDR_4U	  _AC(0x000007FFFFFFE000,UL) /* (Cheetah) pa[42:13]  */
+#define _PAGE_SOFT_4U	  _AC(0x0000000000001F80,UL) /* Software bits:       */
+#define _PAGE_EXEC_4U	  _AC(0x0000000000001000,UL) /* Executable SW bit    */
+#define _PAGE_MODIFIED_4U _AC(0x0000000000000800,UL) /* Modified (dirty)     */
+#define _PAGE_FILE_4U	  _AC(0x0000000000000800,UL) /* Pagecache page       */
+#define _PAGE_ACCESSED_4U _AC(0x0000000000000400,UL) /* Accessed (ref'd)     */
+#define _PAGE_READ_4U	  _AC(0x0000000000000200,UL) /* Readable SW Bit      */
+#define _PAGE_WRITE_4U	  _AC(0x0000000000000100,UL) /* Writable SW Bit      */
+#define _PAGE_PRESENT_4U  _AC(0x0000000000000080,UL) /* Present              */
+#define _PAGE_L_4U	  _AC(0x0000000000000040,UL) /* Locked TTE           */
+#define _PAGE_CP_4U	  _AC(0x0000000000000020,UL) /* Cacheable in P-Cache */
+#define _PAGE_CV_4U	  _AC(0x0000000000000010,UL) /* Cacheable in V-Cache */
+#define _PAGE_E_4U	  _AC(0x0000000000000008,UL) /* side-Effect          */
+#define _PAGE_P_4U	  _AC(0x0000000000000004,UL) /* Privileged Page      */
+#define _PAGE_W_4U	  _AC(0x0000000000000002,UL) /* Writable             */
+
+/* SUN4V pte bits... */
+#define _PAGE_NFO_4V	  _AC(0x4000000000000000,UL) /* No Fault Only        */
+#define _PAGE_SOFT2_4V	  _AC(0x3F00000000000000,UL) /* Software bits, set 2 */
+#define _PAGE_MODIFIED_4V _AC(0x2000000000000000,UL) /* Modified (dirty)     */
+#define _PAGE_ACCESSED_4V _AC(0x1000000000000000,UL) /* Accessed (ref'd)     */
+#define _PAGE_READ_4V	  _AC(0x0800000000000000,UL) /* Readable SW Bit      */
+#define _PAGE_WRITE_4V	  _AC(0x0400000000000000,UL) /* Writable SW Bit      */
+#define _PAGE_PADDR_4V	  _AC(0x00FFFFFFFFFFE000,UL) /* paddr[55:13]         */
+#define _PAGE_IE_4V	  _AC(0x0000000000001000,UL) /* Invert Endianness    */
+#define _PAGE_E_4V	  _AC(0x0000000000000800,UL) /* side-Effect          */
+#define _PAGE_CP_4V	  _AC(0x0000000000000400,UL) /* Cacheable in P-Cache */
+#define _PAGE_CV_4V	  _AC(0x0000000000000200,UL) /* Cacheable in V-Cache */
+#define _PAGE_P_4V	  _AC(0x0000000000000100,UL) /* Privileged Page      */
+#define _PAGE_EXEC_4V	  _AC(0x0000000000000080,UL) /* Executable Page      */
+#define _PAGE_W_4V	  _AC(0x0000000000000040,UL) /* Writable             */
+#define _PAGE_SOFT_4V	  _AC(0x0000000000000030,UL) /* Software bits        */
+#define _PAGE_FILE_4V	  _AC(0x0000000000000020,UL) /* Pagecache page       */
+#define _PAGE_PRESENT_4V  _AC(0x0000000000000010,UL) /* Present              */
+#define _PAGE_RESV_4V	  _AC(0x0000000000000008,UL) /* Reserved             */
+#define _PAGE_SZ16GB_4V	  _AC(0x0000000000000007,UL) /* 16GB Page            */
+#define _PAGE_SZ2GB_4V	  _AC(0x0000000000000006,UL) /* 2GB Page             */
+#define _PAGE_SZ256MB_4V  _AC(0x0000000000000005,UL) /* 256MB Page           */
+#define _PAGE_SZ32MB_4V	  _AC(0x0000000000000004,UL) /* 32MB Page            */
+#define _PAGE_SZ4MB_4V	  _AC(0x0000000000000003,UL) /* 4MB Page             */
+#define _PAGE_SZ512K_4V	  _AC(0x0000000000000002,UL) /* 512K Page            */
+#define _PAGE_SZ64K_4V	  _AC(0x0000000000000001,UL) /* 64K Page             */
+#define _PAGE_SZ8K_4V	  _AC(0x0000000000000000,UL) /* 8K Page              */
+#define _PAGE_SZALL_4V	  _AC(0x0000000000000007,UL) /* All pgsz bits        */
+
+#if PAGE_SHIFT == 13
+#define _PAGE_SZBITS_4U	_PAGE_SZ8K_4U
+#define _PAGE_SZBITS_4V	_PAGE_SZ8K_4V
+#elif PAGE_SHIFT == 16
+#define _PAGE_SZBITS_4U	_PAGE_SZ64K_4U
+#define _PAGE_SZBITS_4V	_PAGE_SZ64K_4V
+#else
+#error Wrong PAGE_SHIFT specified
+#endif
+
+#if defined(CONFIG_HUGETLB_PAGE_SIZE_4MB)
+#define _PAGE_SZHUGE_4U	_PAGE_SZ4MB_4U
+#define _PAGE_SZHUGE_4V	_PAGE_SZ4MB_4V
+#elif defined(CONFIG_HUGETLB_PAGE_SIZE_512K)
+#define _PAGE_SZHUGE_4U	_PAGE_SZ512K_4U
+#define _PAGE_SZHUGE_4V	_PAGE_SZ512K_4V
+#elif defined(CONFIG_HUGETLB_PAGE_SIZE_64K)
+#define _PAGE_SZHUGE_4U	_PAGE_SZ64K_4U
+#define _PAGE_SZHUGE_4V	_PAGE_SZ64K_4V
+#endif
+
+/* These are actually filled in at boot time by sun4{u,v}_pgprot_init() */
+#define __P000	__pgprot(0)
+#define __P001	__pgprot(0)
+#define __P010	__pgprot(0)
+#define __P011	__pgprot(0)
+#define __P100	__pgprot(0)
+#define __P101	__pgprot(0)
+#define __P110	__pgprot(0)
+#define __P111	__pgprot(0)
+
+#define __S000	__pgprot(0)
+#define __S001	__pgprot(0)
+#define __S010	__pgprot(0)
+#define __S011	__pgprot(0)
+#define __S100	__pgprot(0)
+#define __S101	__pgprot(0)
+#define __S110	__pgprot(0)
+#define __S111	__pgprot(0)
+
+#ifndef __ASSEMBLY__
+
+extern pte_t mk_pte_io(unsigned long, pgprot_t, int, unsigned long);
+
+extern unsigned long pte_sz_bits(unsigned long size);
+
+extern pgprot_t PAGE_KERNEL;
+extern pgprot_t PAGE_KERNEL_LOCKED;
+extern pgprot_t PAGE_COPY;
+extern pgprot_t PAGE_SHARED;
+
+/* XXX This uglyness is for the atyfb driver's sparc mmap() support. XXX */
+extern unsigned long _PAGE_IE;
+extern unsigned long _PAGE_E;
+extern unsigned long _PAGE_CACHE;
+
+extern unsigned long pg_iobits;
+extern unsigned long _PAGE_ALL_SZ_BITS;
+extern unsigned long _PAGE_SZBITS;
+
+extern struct page *mem_map_zero;
+#define ZERO_PAGE(vaddr)	(mem_map_zero)
+
+/* PFNs are real physical page numbers.  However, mem_map only begins to record
+ * per-page information starting at pfn_base.  This is to handle systems where
+ * the first physical page in the machine is at some huge physical address,
+ * such as 4GB.   This is common on a partitioned E10000, for example.
+ */
+static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot)
+{
+	unsigned long paddr = pfn << PAGE_SHIFT;
+	unsigned long sz_bits;
+
+	sz_bits = 0UL;
+	if (_PAGE_SZBITS_4U != 0UL || _PAGE_SZBITS_4V != 0UL) {
+		__asm__ __volatile__(
+		"\n661:	sethi		%%uhi(%1), %0\n"
+		"	sllx		%0, 32, %0\n"
+		"	.section	.sun4v_2insn_patch, \"ax\"\n"
+		"	.word		661b\n"
+		"	mov		%2, %0\n"
+		"	nop\n"
+		"	.previous\n"
+		: "=r" (sz_bits)
+		: "i" (_PAGE_SZBITS_4U), "i" (_PAGE_SZBITS_4V));
+	}
+	return __pte(paddr | sz_bits | pgprot_val(prot));
+}
+#define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
+
+/* This one can be done with two shifts.  */
+static inline unsigned long pte_pfn(pte_t pte)
+{
+	unsigned long ret;
+
+	__asm__ __volatile__(
+	"\n661:	sllx		%1, %2, %0\n"
+	"	srlx		%0, %3, %0\n"
+	"	.section	.sun4v_2insn_patch, \"ax\"\n"
+	"	.word		661b\n"
+	"	sllx		%1, %4, %0\n"
+	"	srlx		%0, %5, %0\n"
+	"	.previous\n"
+	: "=r" (ret)
+	: "r" (pte_val(pte)),
+	  "i" (21), "i" (21 + PAGE_SHIFT),
+	  "i" (8), "i" (8 + PAGE_SHIFT));
+
+	return ret;
+}
+#define pte_page(x) pfn_to_page(pte_pfn(x))
+
+static inline pte_t pte_modify(pte_t pte, pgprot_t prot)
+{
+	unsigned long mask, tmp;
+
+	/* SUN4U: 0x600307ffffffecb8 (negated == 0x9ffcf80000001347)
+	 * SUN4V: 0x30ffffffffffee17 (negated == 0xcf000000000011e8)
+	 *
+	 * Even if we use negation tricks the result is still a 6
+	 * instruction sequence, so don't try to play fancy and just
+	 * do the most straightforward implementation.
+	 *
+	 * Note: We encode this into 3 sun4v 2-insn patch sequences.
+	 */
+
+	__asm__ __volatile__(
+	"\n661:	sethi		%%uhi(%2), %1\n"
+	"	sethi		%%hi(%2), %0\n"
+	"\n662:	or		%1, %%ulo(%2), %1\n"
+	"	or		%0, %%lo(%2), %0\n"
+	"\n663:	sllx		%1, 32, %1\n"
+	"	or		%0, %1, %0\n"
+	"	.section	.sun4v_2insn_patch, \"ax\"\n"
+	"	.word		661b\n"
+	"	sethi		%%uhi(%3), %1\n"
+	"	sethi		%%hi(%3), %0\n"
+	"	.word		662b\n"
+	"	or		%1, %%ulo(%3), %1\n"
+	"	or		%0, %%lo(%3), %0\n"
+	"	.word		663b\n"
+	"	sllx		%1, 32, %1\n"
+	"	or		%0, %1, %0\n"
+	"	.previous\n"
+	: "=r" (mask), "=r" (tmp)
+	: "i" (_PAGE_PADDR_4U | _PAGE_MODIFIED_4U | _PAGE_ACCESSED_4U |
+	       _PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U | _PAGE_PRESENT_4U |
+	       _PAGE_SZBITS_4U),
+	  "i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V |
+	       _PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V | _PAGE_PRESENT_4V |
+	       _PAGE_SZBITS_4V));
+
+	return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask));
+}
+
+static inline pte_t pgoff_to_pte(unsigned long off)
+{
+	off <<= PAGE_SHIFT;
+
+	__asm__ __volatile__(
+	"\n661:	or		%0, %2, %0\n"
+	"	.section	.sun4v_1insn_patch, \"ax\"\n"
+	"	.word		661b\n"
+	"	or		%0, %3, %0\n"
+	"	.previous\n"
+	: "=r" (off)
+	: "0" (off), "i" (_PAGE_FILE_4U), "i" (_PAGE_FILE_4V));
+
+	return __pte(off);
+}
+
+static inline pgprot_t pgprot_noncached(pgprot_t prot)
+{
+	unsigned long val = pgprot_val(prot);
+
+	__asm__ __volatile__(
+	"\n661:	andn		%0, %2, %0\n"
+	"	or		%0, %3, %0\n"
+	"	.section	.sun4v_2insn_patch, \"ax\"\n"
+	"	.word		661b\n"
+	"	andn		%0, %4, %0\n"
+	"	or		%0, %5, %0\n"
+	"	.previous\n"
+	: "=r" (val)
+	: "0" (val), "i" (_PAGE_CP_4U | _PAGE_CV_4U), "i" (_PAGE_E_4U),
+	             "i" (_PAGE_CP_4V | _PAGE_CV_4V), "i" (_PAGE_E_4V));
+
+	return __pgprot(val);
+}
+/* Various pieces of code check for platform support by ifdef testing
+ * on "pgprot_noncached".  That's broken and should be fixed, but for
+ * now...
+ */
+#define pgprot_noncached pgprot_noncached
+
+#ifdef CONFIG_HUGETLB_PAGE
+static inline pte_t pte_mkhuge(pte_t pte)
+{
+	unsigned long mask;
+
+	__asm__ __volatile__(
+	"\n661:	sethi		%%uhi(%1), %0\n"
+	"	sllx		%0, 32, %0\n"
+	"	.section	.sun4v_2insn_patch, \"ax\"\n"
+	"	.word		661b\n"
+	"	mov		%2, %0\n"
+	"	nop\n"
+	"	.previous\n"
+	: "=r" (mask)
+	: "i" (_PAGE_SZHUGE_4U), "i" (_PAGE_SZHUGE_4V));
+
+	return __pte(pte_val(pte) | mask);
+}
+#endif
+
+static inline pte_t pte_mkdirty(pte_t pte)
+{
+	unsigned long val = pte_val(pte), tmp;
+
+	__asm__ __volatile__(
+	"\n661:	or		%0, %3, %0\n"
+	"	nop\n"
+	"\n662:	nop\n"
+	"	nop\n"
+	"	.section	.sun4v_2insn_patch, \"ax\"\n"
+	"	.word		661b\n"
+	"	sethi		%%uhi(%4), %1\n"
+	"	sllx		%1, 32, %1\n"
+	"	.word		662b\n"
+	"	or		%1, %%lo(%4), %1\n"
+	"	or		%0, %1, %0\n"
+	"	.previous\n"
+	: "=r" (val), "=r" (tmp)
+	: "0" (val), "i" (_PAGE_MODIFIED_4U | _PAGE_W_4U),
+	  "i" (_PAGE_MODIFIED_4V | _PAGE_W_4V));
+
+	return __pte(val);
+}
+
+static inline pte_t pte_mkclean(pte_t pte)
+{
+	unsigned long val = pte_val(pte), tmp;
+
+	__asm__ __volatile__(
+	"\n661:	andn		%0, %3, %0\n"
+	"	nop\n"
+	"\n662:	nop\n"
+	"	nop\n"
+	"	.section	.sun4v_2insn_patch, \"ax\"\n"
+	"	.word		661b\n"
+	"	sethi		%%uhi(%4), %1\n"
+	"	sllx		%1, 32, %1\n"
+	"	.word		662b\n"
+	"	or		%1, %%lo(%4), %1\n"
+	"	andn		%0, %1, %0\n"
+	"	.previous\n"
+	: "=r" (val), "=r" (tmp)
+	: "0" (val), "i" (_PAGE_MODIFIED_4U | _PAGE_W_4U),
+	  "i" (_PAGE_MODIFIED_4V | _PAGE_W_4V));
+
+	return __pte(val);
+}
+
+static inline pte_t pte_mkwrite(pte_t pte)
+{
+	unsigned long val = pte_val(pte), mask;
+
+	__asm__ __volatile__(
+	"\n661:	mov		%1, %0\n"
+	"	nop\n"
+	"	.section	.sun4v_2insn_patch, \"ax\"\n"
+	"	.word		661b\n"
+	"	sethi		%%uhi(%2), %0\n"
+	"	sllx		%0, 32, %0\n"
+	"	.previous\n"
+	: "=r" (mask)
+	: "i" (_PAGE_WRITE_4U), "i" (_PAGE_WRITE_4V));
+
+	return __pte(val | mask);
+}
+
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+	unsigned long val = pte_val(pte), tmp;
+
+	__asm__ __volatile__(
+	"\n661:	andn		%0, %3, %0\n"
+	"	nop\n"
+	"\n662:	nop\n"
+	"	nop\n"
+	"	.section	.sun4v_2insn_patch, \"ax\"\n"
+	"	.word		661b\n"
+	"	sethi		%%uhi(%4), %1\n"
+	"	sllx		%1, 32, %1\n"
+	"	.word		662b\n"
+	"	or		%1, %%lo(%4), %1\n"
+	"	andn		%0, %1, %0\n"
+	"	.previous\n"
+	: "=r" (val), "=r" (tmp)
+	: "0" (val), "i" (_PAGE_WRITE_4U | _PAGE_W_4U),
+	  "i" (_PAGE_WRITE_4V | _PAGE_W_4V));
+
+	return __pte(val);
+}
+
+static inline pte_t pte_mkold(pte_t pte)
+{
+	unsigned long mask;
+
+	__asm__ __volatile__(
+	"\n661:	mov		%1, %0\n"
+	"	nop\n"
+	"	.section	.sun4v_2insn_patch, \"ax\"\n"
+	"	.word		661b\n"
+	"	sethi		%%uhi(%2), %0\n"
+	"	sllx		%0, 32, %0\n"
+	"	.previous\n"
+	: "=r" (mask)
+	: "i" (_PAGE_ACCESSED_4U), "i" (_PAGE_ACCESSED_4V));
+
+	mask |= _PAGE_R;
+
+	return __pte(pte_val(pte) & ~mask);
+}
+
+static inline pte_t pte_mkyoung(pte_t pte)
+{
+	unsigned long mask;
+
+	__asm__ __volatile__(
+	"\n661:	mov		%1, %0\n"
+	"	nop\n"
+	"	.section	.sun4v_2insn_patch, \"ax\"\n"
+	"	.word		661b\n"
+	"	sethi		%%uhi(%2), %0\n"
+	"	sllx		%0, 32, %0\n"
+	"	.previous\n"
+	: "=r" (mask)
+	: "i" (_PAGE_ACCESSED_4U), "i" (_PAGE_ACCESSED_4V));
+
+	mask |= _PAGE_R;
+
+	return __pte(pte_val(pte) | mask);
+}
+
+static inline pte_t pte_mkspecial(pte_t pte)
+{
+	return pte;
+}
+
+static inline unsigned long pte_young(pte_t pte)
+{
+	unsigned long mask;
+
+	__asm__ __volatile__(
+	"\n661:	mov		%1, %0\n"
+	"	nop\n"
+	"	.section	.sun4v_2insn_patch, \"ax\"\n"
+	"	.word		661b\n"
+	"	sethi		%%uhi(%2), %0\n"
+	"	sllx		%0, 32, %0\n"
+	"	.previous\n"
+	: "=r" (mask)
+	: "i" (_PAGE_ACCESSED_4U), "i" (_PAGE_ACCESSED_4V));
+
+	return (pte_val(pte) & mask);
+}
+
+static inline unsigned long pte_dirty(pte_t pte)
+{
+	unsigned long mask;
+
+	__asm__ __volatile__(
+	"\n661:	mov		%1, %0\n"
+	"	nop\n"
+	"	.section	.sun4v_2insn_patch, \"ax\"\n"
+	"	.word		661b\n"
+	"	sethi		%%uhi(%2), %0\n"
+	"	sllx		%0, 32, %0\n"
+	"	.previous\n"
+	: "=r" (mask)
+	: "i" (_PAGE_MODIFIED_4U), "i" (_PAGE_MODIFIED_4V));
+
+	return (pte_val(pte) & mask);
+}
+
+static inline unsigned long pte_write(pte_t pte)
+{
+	unsigned long mask;
+
+	__asm__ __volatile__(
+	"\n661:	mov		%1, %0\n"
+	"	nop\n"
+	"	.section	.sun4v_2insn_patch, \"ax\"\n"
+	"	.word		661b\n"
+	"	sethi		%%uhi(%2), %0\n"
+	"	sllx		%0, 32, %0\n"
+	"	.previous\n"
+	: "=r" (mask)
+	: "i" (_PAGE_WRITE_4U), "i" (_PAGE_WRITE_4V));
+
+	return (pte_val(pte) & mask);
+}
+
+static inline unsigned long pte_exec(pte_t pte)
+{
+	unsigned long mask;
+
+	__asm__ __volatile__(
+	"\n661:	sethi		%%hi(%1), %0\n"
+	"	.section	.sun4v_1insn_patch, \"ax\"\n"
+	"	.word		661b\n"
+	"	mov		%2, %0\n"
+	"	.previous\n"
+	: "=r" (mask)
+	: "i" (_PAGE_EXEC_4U), "i" (_PAGE_EXEC_4V));
+
+	return (pte_val(pte) & mask);
+}
+
+static inline unsigned long pte_file(pte_t pte)
+{
+	unsigned long val = pte_val(pte);
+
+	__asm__ __volatile__(
+	"\n661:	and		%0, %2, %0\n"
+	"	.section	.sun4v_1insn_patch, \"ax\"\n"
+	"	.word		661b\n"
+	"	and		%0, %3, %0\n"
+	"	.previous\n"
+	: "=r" (val)
+	: "0" (val), "i" (_PAGE_FILE_4U), "i" (_PAGE_FILE_4V));
+
+	return val;
+}
+
+static inline unsigned long pte_present(pte_t pte)
+{
+	unsigned long val = pte_val(pte);
+
+	__asm__ __volatile__(
+	"\n661:	and		%0, %2, %0\n"
+	"	.section	.sun4v_1insn_patch, \"ax\"\n"
+	"	.word		661b\n"
+	"	and		%0, %3, %0\n"
+	"	.previous\n"
+	: "=r" (val)
+	: "0" (val), "i" (_PAGE_PRESENT_4U), "i" (_PAGE_PRESENT_4V));
+
+	return val;
+}
+
+static inline int pte_special(pte_t pte)
+{
+	return 0;
+}
+
+#define pmd_set(pmdp, ptep)	\
+	(pmd_val(*(pmdp)) = (__pa((unsigned long) (ptep)) >> 11UL))
+#define pud_set(pudp, pmdp)	\
+	(pud_val(*(pudp)) = (__pa((unsigned long) (pmdp)) >> 11UL))
+#define __pmd_page(pmd)		\
+	((unsigned long) __va((((unsigned long)pmd_val(pmd))<<11UL)))
+#define pmd_page(pmd) 			virt_to_page((void *)__pmd_page(pmd))
+#define pud_page_vaddr(pud)		\
+	((unsigned long) __va((((unsigned long)pud_val(pud))<<11UL)))
+#define pud_page(pud) 			virt_to_page((void *)pud_page_vaddr(pud))
+#define pmd_none(pmd)			(!pmd_val(pmd))
+#define pmd_bad(pmd)			(0)
+#define pmd_present(pmd)		(pmd_val(pmd) != 0U)
+#define pmd_clear(pmdp)			(pmd_val(*(pmdp)) = 0U)
+#define pud_none(pud)			(!pud_val(pud))
+#define pud_bad(pud)			(0)
+#define pud_present(pud)		(pud_val(pud) != 0U)
+#define pud_clear(pudp)			(pud_val(*(pudp)) = 0U)
+
+/* Same in both SUN4V and SUN4U.  */
+#define pte_none(pte) 			(!pte_val(pte))
+
+/* to find an entry in a page-table-directory. */
+#define pgd_index(address)	(((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
+#define pgd_offset(mm, address)	((mm)->pgd + pgd_index(address))
+
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+
+/* Find an entry in the second-level page table.. */
+#define pmd_offset(pudp, address)	\
+	((pmd_t *) pud_page_vaddr(*(pudp)) + \
+	 (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)))
+
+/* Find an entry in the third-level page table.. */
+#define pte_index(dir, address)	\
+	((pte_t *) __pmd_page(*(dir)) + \
+	 ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
+#define pte_offset_kernel		pte_index
+#define pte_offset_map			pte_index
+#define pte_offset_map_nested		pte_index
+#define pte_unmap(pte)			do { } while (0)
+#define pte_unmap_nested(pte)		do { } while (0)
+
+/* Actual page table PTE updates.  */
+extern void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t orig);
+
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte)
+{
+	pte_t orig = *ptep;
+
+	*ptep = pte;
+
+	/* It is more efficient to let flush_tlb_kernel_range()
+	 * handle init_mm tlb flushes.
+	 *
+	 * SUN4V NOTE: _PAGE_VALID is the same value in both the SUN4U
+	 *             and SUN4V pte layout, so this inline test is fine.
+	 */
+	if (likely(mm != &init_mm) && (pte_val(orig) & _PAGE_VALID))
+		tlb_batch_add(mm, addr, ptep, orig);
+}
+
+#define pte_clear(mm,addr,ptep)		\
+	set_pte_at((mm), (addr), (ptep), __pte(0UL))
+
+#ifdef DCACHE_ALIASING_POSSIBLE
+#define __HAVE_ARCH_MOVE_PTE
+#define move_pte(pte, prot, old_addr, new_addr)				\
+({									\
+	pte_t newpte = (pte);						\
+	if (tlb_type != hypervisor && pte_present(pte)) {		\
+		unsigned long this_pfn = pte_pfn(pte);			\
+									\
+		if (pfn_valid(this_pfn) &&				\
+		    (((old_addr) ^ (new_addr)) & (1 << 13)))		\
+			flush_dcache_page_all(current->mm,		\
+					      pfn_to_page(this_pfn));	\
+	}								\
+	newpte;								\
+})
+#endif
+
+extern pgd_t swapper_pg_dir[2048];
+extern pmd_t swapper_low_pmd_dir[2048];
+
+extern void paging_init(void);
+extern unsigned long find_ecache_flush_span(unsigned long size);
+
+/* These do nothing with the way I have things setup. */
+#define mmu_lockarea(vaddr, len)		(vaddr)
+#define mmu_unlockarea(vaddr, len)		do { } while(0)
+
+struct vm_area_struct;
+extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
+
+/* Encode and de-code a swap entry */
+#define __swp_type(entry)	(((entry).val >> PAGE_SHIFT) & 0xffUL)
+#define __swp_offset(entry)	((entry).val >> (PAGE_SHIFT + 8UL))
+#define __swp_entry(type, offset)	\
+	( (swp_entry_t) \
+	  { \
+		(((long)(type) << PAGE_SHIFT) | \
+                 ((long)(offset) << (PAGE_SHIFT + 8UL))) \
+	  } )
+#define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
+#define __swp_entry_to_pte(x)		((pte_t) { (x).val })
+
+/* File offset in PTE support. */
+extern unsigned long pte_file(pte_t);
+#define pte_to_pgoff(pte)	(pte_val(pte) >> PAGE_SHIFT)
+extern pte_t pgoff_to_pte(unsigned long);
+#define PTE_FILE_MAX_BITS	(64UL - PAGE_SHIFT - 1UL)
+
+extern unsigned long *sparc64_valid_addr_bitmap;
+
+/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
+#define kern_addr_valid(addr)	\
+	(test_bit(__pa((unsigned long)(addr))>>22, sparc64_valid_addr_bitmap))
+
+extern int page_in_phys_avail(unsigned long paddr);
+
+extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
+			       unsigned long pfn,
+			       unsigned long size, pgprot_t prot);
+
+/*
+ * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
+ * its high 4 bits.  These macros/functions put it there or get it from there.
+ */
+#define MK_IOSPACE_PFN(space, pfn)	(pfn | (space << (BITS_PER_LONG - 4)))
+#define GET_IOSPACE(pfn)		(pfn >> (BITS_PER_LONG - 4))
+#define GET_PFN(pfn)			(pfn & 0x0fffffffffffffffUL)
+
+#include <asm-generic/pgtable.h>
+
+/* We provide our own get_unmapped_area to cope with VA holes and
+ * SHM area cache aliasing for userland.
+ */
+#define HAVE_ARCH_UNMAPPED_AREA
+#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
+
+/* We provide a special get_unmapped_area for framebuffer mmaps to try and use
+ * the largest alignment possible such that larget PTEs can be used.
+ */
+extern unsigned long get_fb_unmapped_area(struct file *filp, unsigned long,
+					  unsigned long, unsigned long,
+					  unsigned long);
+#define HAVE_ARCH_FB_UNMAPPED_AREA
+
+extern void pgtable_cache_init(void);
+extern void sun4v_register_fault_status(void);
+extern void sun4v_ktsb_register(void);
+extern void __init cheetah_ecache_flush_init(void);
+extern void sun4v_patch_tlb_handlers(void);
+
+extern unsigned long cmdline_memory_size;
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(_SPARC64_PGTABLE_H) */
diff --git a/include/asm-sparc/pil.h b/include/asm-sparc/pil.h
new file mode 100644
index 0000000..71819bb
--- /dev/null
+++ b/include/asm-sparc/pil.h
@@ -0,0 +1,22 @@
+#ifndef _SPARC64_PIL_H
+#define _SPARC64_PIL_H
+
+/* To avoid some locking problems, we hard allocate certain PILs
+ * for SMP cross call messages that must do a etrap/rtrap.
+ *
+ * A local_irq_disable() does not block the cross call delivery, so
+ * when SMP locking is an issue we reschedule the event into a PIL
+ * interrupt which is blocked by local_irq_disable().
+ *
+ * In fact any XCALL which has to etrap/rtrap has a problem because
+ * it is difficult to prevent rtrap from running BH's, and that would
+ * need to be done if the XCALL arrived while %pil==15.
+ */
+#define PIL_SMP_CALL_FUNC	1
+#define PIL_SMP_RECEIVE_SIGNAL	2
+#define PIL_SMP_CAPTURE		3
+#define PIL_SMP_CTX_NEW_VERSION	4
+#define PIL_DEVICE_IRQ		5
+#define PIL_SMP_CALL_FUNC_SNGL	6
+
+#endif /* !(_SPARC64_PIL_H) */
diff --git a/include/asm-sparc/posix_types.h b/include/asm-sparc/posix_types.h
index dcc07eb..58c820d 100644
--- a/include/asm-sparc/posix_types.h
+++ b/include/asm-sparc/posix_types.h
@@ -1,118 +1,8 @@
-#ifndef __ARCH_SPARC_POSIX_TYPES_H
-#define __ARCH_SPARC_POSIX_TYPES_H
-
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc.  Also, we cannot
- * assume GCC is being used.
- */
-
-typedef unsigned int           __kernel_size_t;
-typedef int                    __kernel_ssize_t;
-typedef long int               __kernel_ptrdiff_t;
-typedef long                   __kernel_time_t;
-typedef long		       __kernel_suseconds_t;
-typedef long                   __kernel_clock_t;
-typedef int                    __kernel_pid_t;
-typedef unsigned short         __kernel_ipc_pid_t;
-typedef unsigned short         __kernel_uid_t;
-typedef unsigned short         __kernel_gid_t;
-typedef unsigned long          __kernel_ino_t;
-typedef unsigned short         __kernel_mode_t;
-typedef unsigned short         __kernel_umode_t;
-typedef short                  __kernel_nlink_t;
-typedef long                   __kernel_daddr_t;
-typedef long                   __kernel_off_t;
-typedef char *                 __kernel_caddr_t;
-typedef unsigned short	       __kernel_uid16_t;
-typedef unsigned short	       __kernel_gid16_t;
-typedef unsigned int	       __kernel_uid32_t;
-typedef unsigned int	       __kernel_gid32_t;
-typedef unsigned short	       __kernel_old_uid_t;
-typedef unsigned short	       __kernel_old_gid_t;
-typedef unsigned short	       __kernel_old_dev_t;
-typedef int                    __kernel_clockid_t;
-typedef int                    __kernel_timer_t;
-
-#ifdef __GNUC__
-typedef long long	__kernel_loff_t;
+#ifndef ___ASM_SPARC_POSIX_TYPES_H
+#define ___ASM_SPARC_POSIX_TYPES_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/posix_types_64.h>
+#else
+#include <asm-sparc/posix_types_32.h>
 #endif
-
-typedef struct {
-	int	val[2];
-} __kernel_fsid_t;
-
-#if defined(__KERNEL__)
-
-#undef __FD_SET
-static inline void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
-{
-	unsigned long _tmp = fd / __NFDBITS;
-	unsigned long _rem = fd % __NFDBITS;
-	fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
-}
-
-#undef __FD_CLR
-static inline void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
-{
-	unsigned long _tmp = fd / __NFDBITS;
-	unsigned long _rem = fd % __NFDBITS;
-	fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
-}
-
-#undef __FD_ISSET
-static inline int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
-{ 
-	unsigned long _tmp = fd / __NFDBITS;
-	unsigned long _rem = fd % __NFDBITS;
-	return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
-}
-
-/*
- * This will unroll the loop for the normal constant cases (8 or 32 longs,
- * for 256 and 1024-bit fd_sets respectively)
- */
-#undef __FD_ZERO
-static inline void __FD_ZERO(__kernel_fd_set *p)
-{
-	unsigned long *tmp = p->fds_bits;
-	int i;
-
-	if (__builtin_constant_p(__FDSET_LONGS)) {
-		switch (__FDSET_LONGS) {
-			case 32:
-			  tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
-			  tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
-			  tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
-			  tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
-			  tmp[16] = 0; tmp[17] = 0; tmp[18] = 0; tmp[19] = 0;
-			  tmp[20] = 0; tmp[21] = 0; tmp[22] = 0; tmp[23] = 0;
-			  tmp[24] = 0; tmp[25] = 0; tmp[26] = 0; tmp[27] = 0;
-			  tmp[28] = 0; tmp[29] = 0; tmp[30] = 0; tmp[31] = 0;
-			  return;
-			case 16:
-			  tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
-			  tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
-			  tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
-			  tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
-			  return;
-			case 8:
-			  tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
-			  tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
-			  return;
-			case 4:
-			  tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
-			  return;
-		}
-	}
-	i = __FDSET_LONGS;
-	while (i) {
-		i--;
-		*tmp = 0;
-		tmp++;
-	}
-}
-
-#endif /* defined(__KERNEL__) */
-
-#endif /* !(__ARCH_SPARC_POSIX_TYPES_H) */
+#endif
diff --git a/include/asm-sparc/posix_types_32.h b/include/asm-sparc/posix_types_32.h
new file mode 100644
index 0000000..6bb6eb1
--- /dev/null
+++ b/include/asm-sparc/posix_types_32.h
@@ -0,0 +1,118 @@
+#ifndef __ARCH_SPARC_POSIX_TYPES_H
+#define __ARCH_SPARC_POSIX_TYPES_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned int           __kernel_size_t;
+typedef int                    __kernel_ssize_t;
+typedef long int               __kernel_ptrdiff_t;
+typedef long                   __kernel_time_t;
+typedef long		       __kernel_suseconds_t;
+typedef long                   __kernel_clock_t;
+typedef int                    __kernel_pid_t;
+typedef unsigned short         __kernel_ipc_pid_t;
+typedef unsigned short         __kernel_uid_t;
+typedef unsigned short         __kernel_gid_t;
+typedef unsigned long          __kernel_ino_t;
+typedef unsigned short         __kernel_mode_t;
+typedef unsigned short         __kernel_umode_t;
+typedef short                  __kernel_nlink_t;
+typedef long                   __kernel_daddr_t;
+typedef long                   __kernel_off_t;
+typedef char *                 __kernel_caddr_t;
+typedef unsigned short	       __kernel_uid16_t;
+typedef unsigned short	       __kernel_gid16_t;
+typedef unsigned int	       __kernel_uid32_t;
+typedef unsigned int	       __kernel_gid32_t;
+typedef unsigned short	       __kernel_old_uid_t;
+typedef unsigned short	       __kernel_old_gid_t;
+typedef unsigned short	       __kernel_old_dev_t;
+typedef int                    __kernel_clockid_t;
+typedef int                    __kernel_timer_t;
+
+#ifdef __GNUC__
+typedef long long	__kernel_loff_t;
+#endif
+
+typedef struct {
+	int	val[2];
+} __kernel_fsid_t;
+
+#if defined(__KERNEL__)
+
+#undef __FD_SET
+static inline void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
+{
+	unsigned long _tmp = fd / __NFDBITS;
+	unsigned long _rem = fd % __NFDBITS;
+	fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
+}
+
+#undef __FD_CLR
+static inline void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
+{
+	unsigned long _tmp = fd / __NFDBITS;
+	unsigned long _rem = fd % __NFDBITS;
+	fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
+}
+
+#undef __FD_ISSET
+static inline int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
+{
+	unsigned long _tmp = fd / __NFDBITS;
+	unsigned long _rem = fd % __NFDBITS;
+	return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
+}
+
+/*
+ * This will unroll the loop for the normal constant cases (8 or 32 longs,
+ * for 256 and 1024-bit fd_sets respectively)
+ */
+#undef __FD_ZERO
+static inline void __FD_ZERO(__kernel_fd_set *p)
+{
+	unsigned long *tmp = p->fds_bits;
+	int i;
+
+	if (__builtin_constant_p(__FDSET_LONGS)) {
+		switch (__FDSET_LONGS) {
+			case 32:
+			  tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+			  tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
+			  tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
+			  tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
+			  tmp[16] = 0; tmp[17] = 0; tmp[18] = 0; tmp[19] = 0;
+			  tmp[20] = 0; tmp[21] = 0; tmp[22] = 0; tmp[23] = 0;
+			  tmp[24] = 0; tmp[25] = 0; tmp[26] = 0; tmp[27] = 0;
+			  tmp[28] = 0; tmp[29] = 0; tmp[30] = 0; tmp[31] = 0;
+			  return;
+			case 16:
+			  tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+			  tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
+			  tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
+			  tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
+			  return;
+			case 8:
+			  tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+			  tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
+			  return;
+			case 4:
+			  tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+			  return;
+		}
+	}
+	i = __FDSET_LONGS;
+	while (i) {
+		i--;
+		*tmp = 0;
+		tmp++;
+	}
+}
+
+#endif /* defined(__KERNEL__) */
+
+#endif /* !(__ARCH_SPARC_POSIX_TYPES_H) */
diff --git a/include/asm-sparc/posix_types_64.h b/include/asm-sparc/posix_types_64.h
new file mode 100644
index 0000000..ba8f932
--- /dev/null
+++ b/include/asm-sparc/posix_types_64.h
@@ -0,0 +1,122 @@
+#ifndef __ARCH_SPARC64_POSIX_TYPES_H
+#define __ARCH_SPARC64_POSIX_TYPES_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned long          __kernel_size_t;
+typedef long                   __kernel_ssize_t;
+typedef long                   __kernel_ptrdiff_t;
+typedef long                   __kernel_time_t;
+typedef long                   __kernel_clock_t;
+typedef int                    __kernel_pid_t;
+typedef int                    __kernel_ipc_pid_t;
+typedef unsigned int           __kernel_uid_t;
+typedef unsigned int           __kernel_gid_t;
+typedef unsigned long          __kernel_ino_t;
+typedef unsigned int           __kernel_mode_t;
+typedef unsigned short         __kernel_umode_t;
+typedef unsigned int           __kernel_nlink_t;
+typedef int                    __kernel_daddr_t;
+typedef long                   __kernel_off_t;
+typedef char *                 __kernel_caddr_t;
+typedef unsigned short	       __kernel_uid16_t;
+typedef unsigned short	       __kernel_gid16_t;
+typedef int                    __kernel_clockid_t;
+typedef int                    __kernel_timer_t;
+
+typedef unsigned short 	       __kernel_old_uid_t;
+typedef unsigned short         __kernel_old_gid_t;
+typedef __kernel_uid_t	       __kernel_uid32_t;
+typedef __kernel_gid_t	       __kernel_gid32_t;
+
+typedef unsigned int	       __kernel_old_dev_t;
+
+/* Note this piece of asymmetry from the v9 ABI.  */
+typedef int		       __kernel_suseconds_t;
+
+#ifdef __GNUC__
+typedef long long              __kernel_loff_t;
+#endif
+
+typedef struct {
+	int	val[2];
+} __kernel_fsid_t;
+
+#if defined(__KERNEL__)
+
+#undef __FD_SET
+static inline void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
+{
+	unsigned long _tmp = fd / __NFDBITS;
+	unsigned long _rem = fd % __NFDBITS;
+	fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
+}
+
+#undef __FD_CLR
+static inline void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
+{
+	unsigned long _tmp = fd / __NFDBITS;
+	unsigned long _rem = fd % __NFDBITS;
+	fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
+}
+
+#undef __FD_ISSET
+static inline int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
+{
+	unsigned long _tmp = fd / __NFDBITS;
+	unsigned long _rem = fd % __NFDBITS;
+	return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
+}
+
+/*
+ * This will unroll the loop for the normal constant cases (8 or 32 longs,
+ * for 256 and 1024-bit fd_sets respectively)
+ */
+#undef __FD_ZERO
+static inline void __FD_ZERO(__kernel_fd_set *p)
+{
+	unsigned long *tmp = p->fds_bits;
+	int i;
+
+	if (__builtin_constant_p(__FDSET_LONGS)) {
+		switch (__FDSET_LONGS) {
+			case 32:
+			  tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+			  tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
+			  tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
+			  tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
+			  tmp[16] = 0; tmp[17] = 0; tmp[18] = 0; tmp[19] = 0;
+			  tmp[20] = 0; tmp[21] = 0; tmp[22] = 0; tmp[23] = 0;
+			  tmp[24] = 0; tmp[25] = 0; tmp[26] = 0; tmp[27] = 0;
+			  tmp[28] = 0; tmp[29] = 0; tmp[30] = 0; tmp[31] = 0;
+			  return;
+			case 16:
+			  tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+			  tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
+			  tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
+			  tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
+			  return;
+			case 8:
+			  tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+			  tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
+			  return;
+			case 4:
+			  tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+			  return;
+		}
+	}
+	i = __FDSET_LONGS;
+	while (i) {
+		i--;
+		*tmp = 0;
+		tmp++;
+	}
+}
+
+#endif /* defined(__KERNEL__) */
+
+#endif /* !(__ARCH_SPARC64_POSIX_TYPES_H) */
diff --git a/include/asm-sparc/processor.h b/include/asm-sparc/processor.h
index 8898efb..11a66bb 100644
--- a/include/asm-sparc/processor.h
+++ b/include/asm-sparc/processor.h
@@ -1,128 +1,8 @@
-/* include/asm-sparc/processor.h
- *
- * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef __ASM_SPARC_PROCESSOR_H
-#define __ASM_SPARC_PROCESSOR_H
-
-/*
- * Sparc32 implementation of macro that returns current
- * instruction pointer ("program counter").
- */
-#define current_text_addr() ({ void *pc; __asm__("sethi %%hi(1f), %0; or %0, %%lo(1f), %0;\n1:" : "=r" (pc)); pc; })
-
-#include <asm/psr.h>
-#include <asm/ptrace.h>
-#include <asm/head.h>
-#include <asm/signal.h>
-#include <asm/btfixup.h>
-#include <asm/page.h>
-
-/*
- * The sparc has no problems with write protection
- */
-#define wp_works_ok 1
-#define wp_works_ok__is_a_macro /* for versions in ksyms.c */
-
-/* Whee, this is STACK_TOP + PAGE_SIZE and the lowest kernel address too... 
- * That one page is used to protect kernel from intruders, so that
- * we can make our access_ok test faster
- */
-#define TASK_SIZE	PAGE_OFFSET
-#ifdef __KERNEL__
-#define STACK_TOP	(PAGE_OFFSET - PAGE_SIZE)
-#define STACK_TOP_MAX	STACK_TOP
-#endif /* __KERNEL__ */
-
-struct task_struct;
-
-#ifdef __KERNEL__
-struct fpq {
-	unsigned long *insn_addr;
-	unsigned long insn;
-};
+#ifndef ___ASM_SPARC_PROCESSOR_H
+#define ___ASM_SPARC_PROCESSOR_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/processor_64.h>
+#else
+#include <asm-sparc/processor_32.h>
 #endif
-
-typedef struct {
-	int seg;
-} mm_segment_t;
-
-/* The Sparc processor specific thread struct. */
-struct thread_struct {
-	struct pt_regs *kregs;
-	unsigned int _pad1;
-
-	/* Special child fork kpsr/kwim values. */
-	unsigned long fork_kpsr __attribute__ ((aligned (8)));
-	unsigned long fork_kwim;
-
-	/* Floating point regs */
-	unsigned long   float_regs[32] __attribute__ ((aligned (8)));
-	unsigned long   fsr;
-	unsigned long   fpqdepth;
-	struct fpq	fpqueue[16];
-	unsigned long flags;
-	mm_segment_t current_ds;
-};
-
-#define SPARC_FLAG_KTHREAD      0x1    /* task is a kernel thread */
-#define SPARC_FLAG_UNALIGNED    0x2    /* is allowed to do unaligned accesses */
-
-#define INIT_THREAD  { \
-	.flags = SPARC_FLAG_KTHREAD, \
-	.current_ds = KERNEL_DS, \
-}
-
-/* Return saved PC of a blocked thread. */
-extern unsigned long thread_saved_pc(struct task_struct *t);
-
-/* Do necessary setup to start up a newly executed thread. */
-static inline void start_thread(struct pt_regs * regs, unsigned long pc,
-				    unsigned long sp)
-{
-	register unsigned long zero asm("g1");
-
-	regs->psr = (regs->psr & (PSR_CWP)) | PSR_S;
-	regs->pc = ((pc & (~3)) - 4);
-	regs->npc = regs->pc + 4;
-	regs->y = 0;
-	zero = 0;
-	__asm__ __volatile__("std\t%%g0, [%0 + %3 + 0x00]\n\t"
-			     "std\t%%g0, [%0 + %3 + 0x08]\n\t"
-			     "std\t%%g0, [%0 + %3 + 0x10]\n\t"
-			     "std\t%%g0, [%0 + %3 + 0x18]\n\t"
-			     "std\t%%g0, [%0 + %3 + 0x20]\n\t"
-			     "std\t%%g0, [%0 + %3 + 0x28]\n\t"
-			     "std\t%%g0, [%0 + %3 + 0x30]\n\t"
-			     "st\t%1, [%0 + %3 + 0x38]\n\t"
-			     "st\t%%g0, [%0 + %3 + 0x3c]"
-			     : /* no outputs */
-			     : "r" (regs),
-			       "r" (sp - sizeof(struct reg_window)),
-			       "r" (zero),
-			       "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))
-			     : "memory");
-}
-
-/* Free all resources held by a thread. */
-#define release_thread(tsk)		do { } while(0)
-extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
-/* Prepare to copy thread state - unlazy all lazy status */
-#define prepare_to_copy(tsk)	do { } while (0)
-
-extern unsigned long get_wchan(struct task_struct *);
-
-#define KSTK_EIP(tsk)  ((tsk)->thread.kregs->pc)
-#define KSTK_ESP(tsk)  ((tsk)->thread.kregs->u_regs[UREG_FP])
-
-#ifdef __KERNEL__
-
-extern struct task_struct *last_task_used_math;
-
-#define cpu_relax()	barrier()
-
 #endif
-
-#endif /* __ASM_SPARC_PROCESSOR_H */
diff --git a/include/asm-sparc/processor_32.h b/include/asm-sparc/processor_32.h
new file mode 100644
index 0000000..562c0d6
--- /dev/null
+++ b/include/asm-sparc/processor_32.h
@@ -0,0 +1,128 @@
+/* include/asm-sparc/processor.h
+ *
+ * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef __ASM_SPARC_PROCESSOR_H
+#define __ASM_SPARC_PROCESSOR_H
+
+/*
+ * Sparc32 implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ void *pc; __asm__("sethi %%hi(1f), %0; or %0, %%lo(1f), %0;\n1:" : "=r" (pc)); pc; })
+
+#include <asm/psr.h>
+#include <asm/ptrace.h>
+#include <asm/head.h>
+#include <asm/signal.h>
+#include <asm/btfixup.h>
+#include <asm/page.h>
+
+/*
+ * The sparc has no problems with write protection
+ */
+#define wp_works_ok 1
+#define wp_works_ok__is_a_macro /* for versions in ksyms.c */
+
+/* Whee, this is STACK_TOP + PAGE_SIZE and the lowest kernel address too...
+ * That one page is used to protect kernel from intruders, so that
+ * we can make our access_ok test faster
+ */
+#define TASK_SIZE	PAGE_OFFSET
+#ifdef __KERNEL__
+#define STACK_TOP	(PAGE_OFFSET - PAGE_SIZE)
+#define STACK_TOP_MAX	STACK_TOP
+#endif /* __KERNEL__ */
+
+struct task_struct;
+
+#ifdef __KERNEL__
+struct fpq {
+	unsigned long *insn_addr;
+	unsigned long insn;
+};
+#endif
+
+typedef struct {
+	int seg;
+} mm_segment_t;
+
+/* The Sparc processor specific thread struct. */
+struct thread_struct {
+	struct pt_regs *kregs;
+	unsigned int _pad1;
+
+	/* Special child fork kpsr/kwim values. */
+	unsigned long fork_kpsr __attribute__ ((aligned (8)));
+	unsigned long fork_kwim;
+
+	/* Floating point regs */
+	unsigned long   float_regs[32] __attribute__ ((aligned (8)));
+	unsigned long   fsr;
+	unsigned long   fpqdepth;
+	struct fpq	fpqueue[16];
+	unsigned long flags;
+	mm_segment_t current_ds;
+};
+
+#define SPARC_FLAG_KTHREAD      0x1    /* task is a kernel thread */
+#define SPARC_FLAG_UNALIGNED    0x2    /* is allowed to do unaligned accesses */
+
+#define INIT_THREAD  { \
+	.flags = SPARC_FLAG_KTHREAD, \
+	.current_ds = KERNEL_DS, \
+}
+
+/* Return saved PC of a blocked thread. */
+extern unsigned long thread_saved_pc(struct task_struct *t);
+
+/* Do necessary setup to start up a newly executed thread. */
+static inline void start_thread(struct pt_regs * regs, unsigned long pc,
+				    unsigned long sp)
+{
+	register unsigned long zero asm("g1");
+
+	regs->psr = (regs->psr & (PSR_CWP)) | PSR_S;
+	regs->pc = ((pc & (~3)) - 4);
+	regs->npc = regs->pc + 4;
+	regs->y = 0;
+	zero = 0;
+	__asm__ __volatile__("std\t%%g0, [%0 + %3 + 0x00]\n\t"
+			     "std\t%%g0, [%0 + %3 + 0x08]\n\t"
+			     "std\t%%g0, [%0 + %3 + 0x10]\n\t"
+			     "std\t%%g0, [%0 + %3 + 0x18]\n\t"
+			     "std\t%%g0, [%0 + %3 + 0x20]\n\t"
+			     "std\t%%g0, [%0 + %3 + 0x28]\n\t"
+			     "std\t%%g0, [%0 + %3 + 0x30]\n\t"
+			     "st\t%1, [%0 + %3 + 0x38]\n\t"
+			     "st\t%%g0, [%0 + %3 + 0x3c]"
+			     : /* no outputs */
+			     : "r" (regs),
+			       "r" (sp - sizeof(struct reg_window)),
+			       "r" (zero),
+			       "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))
+			     : "memory");
+}
+
+/* Free all resources held by a thread. */
+#define release_thread(tsk)		do { } while(0)
+extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
+extern unsigned long get_wchan(struct task_struct *);
+
+#define KSTK_EIP(tsk)  ((tsk)->thread.kregs->pc)
+#define KSTK_ESP(tsk)  ((tsk)->thread.kregs->u_regs[UREG_FP])
+
+#ifdef __KERNEL__
+
+extern struct task_struct *last_task_used_math;
+
+#define cpu_relax()	barrier()
+
+#endif
+
+#endif /* __ASM_SPARC_PROCESSOR_H */
diff --git a/include/asm-sparc/processor_64.h b/include/asm-sparc/processor_64.h
new file mode 100644
index 0000000..70d4280
--- /dev/null
+++ b/include/asm-sparc/processor_64.h
@@ -0,0 +1,237 @@
+/*
+ * include/asm-sparc64/processor.h
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef __ASM_SPARC64_PROCESSOR_H
+#define __ASM_SPARC64_PROCESSOR_H
+
+/*
+ * Sparc64 implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ void *pc; __asm__("rd %%pc, %0" : "=r" (pc)); pc; })
+
+#include <asm/asi.h>
+#include <asm/pstate.h>
+#include <asm/ptrace.h>
+#include <asm/page.h>
+
+/* The sparc has no problems with write protection */
+#define wp_works_ok 1
+#define wp_works_ok__is_a_macro /* for versions in ksyms.c */
+
+/*
+ * User lives in his very own context, and cannot reference us. Note
+ * that TASK_SIZE is a misnomer, it really gives maximum user virtual
+ * address that the kernel will allocate out.
+ *
+ * XXX No longer using virtual page tables, kill this upper limit...
+ */
+#define VA_BITS		44
+#ifndef __ASSEMBLY__
+#define VPTE_SIZE	(1UL << (VA_BITS - PAGE_SHIFT + 3))
+#else
+#define VPTE_SIZE	(1 << (VA_BITS - PAGE_SHIFT + 3))
+#endif
+
+#define TASK_SIZE	((unsigned long)-VPTE_SIZE)
+#define TASK_SIZE_OF(tsk) \
+	(test_tsk_thread_flag(tsk,TIF_32BIT) ? \
+	 (1UL << 32UL) : TASK_SIZE)
+#ifdef __KERNEL__
+
+#define STACK_TOP32	((1UL << 32UL) - PAGE_SIZE)
+#define STACK_TOP64	(0x0000080000000000UL - (1UL << 32UL))
+
+#define STACK_TOP	(test_thread_flag(TIF_32BIT) ? \
+			 STACK_TOP32 : STACK_TOP64)
+
+#define STACK_TOP_MAX	STACK_TOP64
+
+#endif
+
+#ifndef __ASSEMBLY__
+
+typedef struct {
+	unsigned char seg;
+} mm_segment_t;
+
+/* The Sparc processor specific thread struct. */
+/* XXX This should die, everything can go into thread_info now. */
+struct thread_struct {
+#ifdef CONFIG_DEBUG_SPINLOCK
+	/* How many spinlocks held by this thread.
+	 * Used with spin lock debugging to catch tasks
+	 * sleeping illegally with locks held.
+	 */
+	int smp_lock_count;
+	unsigned int smp_lock_pc;
+#else
+	int dummy; /* f'in gcc bug... */
+#endif
+};
+
+#endif /* !(__ASSEMBLY__) */
+
+#ifndef CONFIG_DEBUG_SPINLOCK
+#define INIT_THREAD  {			\
+	0,				\
+}
+#else /* CONFIG_DEBUG_SPINLOCK */
+#define INIT_THREAD  {					\
+/* smp_lock_count, smp_lock_pc, */			\
+   0,		   0,					\
+}
+#endif /* !(CONFIG_DEBUG_SPINLOCK) */
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+/* Return saved PC of a blocked thread. */
+struct task_struct;
+extern unsigned long thread_saved_pc(struct task_struct *);
+
+/* On Uniprocessor, even in RMO processes see TSO semantics */
+#ifdef CONFIG_SMP
+#define TSTATE_INITIAL_MM	TSTATE_TSO
+#else
+#define TSTATE_INITIAL_MM	TSTATE_RMO
+#endif
+
+/* Do necessary setup to start up a newly executed thread. */
+#define start_thread(regs, pc, sp) \
+do { \
+	unsigned long __asi = ASI_PNF; \
+	regs->tstate = (regs->tstate & (TSTATE_CWP)) | (TSTATE_INITIAL_MM|TSTATE_IE) | (__asi << 24UL); \
+	regs->tpc = ((pc & (~3)) - 4); \
+	regs->tnpc = regs->tpc + 4; \
+	regs->y = 0; \
+	set_thread_wstate(1 << 3); \
+	if (current_thread_info()->utraps) { \
+		if (*(current_thread_info()->utraps) < 2) \
+			kfree(current_thread_info()->utraps); \
+		else \
+			(*(current_thread_info()->utraps))--; \
+		current_thread_info()->utraps = NULL; \
+	} \
+	__asm__ __volatile__( \
+	"stx		%%g0, [%0 + %2 + 0x00]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x08]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x10]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x18]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x20]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x28]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x30]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x38]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x40]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x48]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x50]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x58]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x60]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x68]\n\t" \
+	"stx		%1,   [%0 + %2 + 0x70]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x78]\n\t" \
+	"wrpr		%%g0, (1 << 3), %%wstate\n\t" \
+	: \
+	: "r" (regs), "r" (sp - sizeof(struct reg_window) - STACK_BIAS), \
+	  "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \
+} while (0)
+
+#define start_thread32(regs, pc, sp) \
+do { \
+	unsigned long __asi = ASI_PNF; \
+	pc &= 0x00000000ffffffffUL; \
+	sp &= 0x00000000ffffffffUL; \
+	regs->tstate = (regs->tstate & (TSTATE_CWP))|(TSTATE_INITIAL_MM|TSTATE_IE|TSTATE_AM) | (__asi << 24UL); \
+	regs->tpc = ((pc & (~3)) - 4); \
+	regs->tnpc = regs->tpc + 4; \
+	regs->y = 0; \
+	set_thread_wstate(2 << 3); \
+	if (current_thread_info()->utraps) { \
+		if (*(current_thread_info()->utraps) < 2) \
+			kfree(current_thread_info()->utraps); \
+		else \
+			(*(current_thread_info()->utraps))--; \
+		current_thread_info()->utraps = NULL; \
+	} \
+	__asm__ __volatile__( \
+	"stx		%%g0, [%0 + %2 + 0x00]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x08]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x10]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x18]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x20]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x28]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x30]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x38]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x40]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x48]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x50]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x58]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x60]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x68]\n\t" \
+	"stx		%1,   [%0 + %2 + 0x70]\n\t" \
+	"stx		%%g0, [%0 + %2 + 0x78]\n\t" \
+	"wrpr		%%g0, (2 << 3), %%wstate\n\t" \
+	: \
+	: "r" (regs), "r" (sp - sizeof(struct reg_window32)), \
+	  "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \
+} while (0)
+
+/* Free all resources held by a thread. */
+#define release_thread(tsk)		do { } while (0)
+
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
+extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+
+extern unsigned long get_wchan(struct task_struct *task);
+
+#define task_pt_regs(tsk) (task_thread_info(tsk)->kregs)
+#define KSTK_EIP(tsk)  (task_pt_regs(tsk)->tpc)
+#define KSTK_ESP(tsk)  (task_pt_regs(tsk)->u_regs[UREG_FP])
+
+#define cpu_relax()	barrier()
+
+/* Prefetch support.  This is tuned for UltraSPARC-III and later.
+ * UltraSPARC-I will treat these as nops, and UltraSPARC-II has
+ * a shallower prefetch queue than later chips.
+ */
+#define ARCH_HAS_PREFETCH
+#define ARCH_HAS_PREFETCHW
+#define ARCH_HAS_SPINLOCK_PREFETCH
+
+static inline void prefetch(const void *x)
+{
+	/* We do not use the read prefetch mnemonic because that
+	 * prefetches into the prefetch-cache which only is accessible
+	 * by floating point operations in UltraSPARC-III and later.
+	 * By contrast, "#one_write" prefetches into the L2 cache
+	 * in shared state.
+	 */
+	__asm__ __volatile__("prefetch [%0], #one_write"
+			     : /* no outputs */
+			     : "r" (x));
+}
+
+static inline void prefetchw(const void *x)
+{
+	/* The most optimal prefetch to use for writes is
+	 * "#n_writes".  This brings the cacheline into the
+	 * L2 cache in "owned" state.
+	 */
+	__asm__ __volatile__("prefetch [%0], #n_writes"
+			     : /* no outputs */
+			     : "r" (x));
+}
+
+#define spin_lock_prefetch(x)	prefetchw(x)
+
+#define HAVE_ARCH_PICK_MMAP_LAYOUT
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__ASM_SPARC64_PROCESSOR_H) */
diff --git a/include/asm-sparc/psrcompat.h b/include/asm-sparc/psrcompat.h
new file mode 100644
index 0000000..44b6327
--- /dev/null
+++ b/include/asm-sparc/psrcompat.h
@@ -0,0 +1,45 @@
+#ifndef _SPARC64_PSRCOMPAT_H
+#define _SPARC64_PSRCOMPAT_H
+
+#include <asm/pstate.h>
+
+/* Old 32-bit PSR fields for the compatibility conversion code. */
+#define PSR_CWP     0x0000001f         /* current window pointer     */
+#define PSR_ET      0x00000020         /* enable traps field         */
+#define PSR_PS      0x00000040         /* previous privilege level   */
+#define PSR_S       0x00000080         /* current privilege level    */
+#define PSR_PIL     0x00000f00         /* processor interrupt level  */
+#define PSR_EF      0x00001000         /* enable floating point      */
+#define PSR_EC      0x00002000         /* enable co-processor        */
+#define PSR_SYSCALL 0x00004000         /* inside of a syscall        */
+#define PSR_LE      0x00008000         /* SuperSparcII little-endian */
+#define PSR_ICC     0x00f00000         /* integer condition codes    */
+#define PSR_C       0x00100000         /* carry bit                  */
+#define PSR_V       0x00200000         /* overflow bit               */
+#define PSR_Z       0x00400000         /* zero bit                   */
+#define PSR_N       0x00800000         /* negative bit               */
+#define PSR_VERS    0x0f000000         /* cpu-version field          */
+#define PSR_IMPL    0xf0000000         /* cpu-implementation field   */
+
+#define PSR_V8PLUS  0xff000000         /* fake impl/ver, meaning a 64bit CPU is present */
+#define PSR_XCC	    0x000f0000         /* if PSR_V8PLUS, this is %xcc */
+
+static inline unsigned int tstate_to_psr(unsigned long tstate)
+{
+	return ((tstate & TSTATE_CWP)			|
+		PSR_S					|
+		((tstate & TSTATE_ICC) >> 12)		|
+		((tstate & TSTATE_XCC) >> 20)		|
+		((tstate & TSTATE_SYSCALL) ? PSR_SYSCALL : 0) |
+		PSR_V8PLUS);
+}
+
+static inline unsigned long psr_to_tstate_icc(unsigned int psr)
+{
+	unsigned long tstate = ((unsigned long)(psr & PSR_ICC)) << 12;
+	if ((psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS)
+		tstate |= ((unsigned long)(psr & PSR_XCC)) << 20;
+	return tstate;
+}
+
+#endif /* !(_SPARC64_PSRCOMPAT_H) */
diff --git a/include/asm-sparc/pstate.h b/include/asm-sparc/pstate.h
new file mode 100644
index 0000000..a26a537
--- /dev/null
+++ b/include/asm-sparc/pstate.h
@@ -0,0 +1,91 @@
+#ifndef _SPARC64_PSTATE_H
+#define _SPARC64_PSTATE_H
+
+#include <linux/const.h>
+
+/* The V9 PSTATE Register (with SpitFire extensions).
+ *
+ * -----------------------------------------------------------------------
+ * | Resv | IG | MG | CLE | TLE |  MM  | RED | PEF | AM | PRIV | IE | AG |
+ * -----------------------------------------------------------------------
+ *  63  12  11   10    9     8    7   6   5     4     3     2     1    0
+ */
+#define PSTATE_IG   _AC(0x0000000000000800,UL) /* Interrupt Globals.	*/
+#define PSTATE_MG   _AC(0x0000000000000400,UL) /* MMU Globals.		*/
+#define PSTATE_CLE  _AC(0x0000000000000200,UL) /* Current Little Endian.*/
+#define PSTATE_TLE  _AC(0x0000000000000100,UL) /* Trap Little Endian.	*/
+#define PSTATE_MM   _AC(0x00000000000000c0,UL) /* Memory Model.		*/
+#define PSTATE_TSO  _AC(0x0000000000000000,UL) /* MM: TotalStoreOrder	*/
+#define PSTATE_PSO  _AC(0x0000000000000040,UL) /* MM: PartialStoreOrder	*/
+#define PSTATE_RMO  _AC(0x0000000000000080,UL) /* MM: RelaxedMemoryOrder*/
+#define PSTATE_RED  _AC(0x0000000000000020,UL) /* Reset Error Debug.	*/
+#define PSTATE_PEF  _AC(0x0000000000000010,UL) /* Floating Point Enable.*/
+#define PSTATE_AM   _AC(0x0000000000000008,UL) /* Address Mask.		*/
+#define PSTATE_PRIV _AC(0x0000000000000004,UL) /* Privilege.		*/
+#define PSTATE_IE   _AC(0x0000000000000002,UL) /* Interrupt Enable.	*/
+#define PSTATE_AG   _AC(0x0000000000000001,UL) /* Alternate Globals.	*/
+
+/* The V9 TSTATE Register (with SpitFire and Linux extensions).
+ *
+ * ---------------------------------------------------------------------
+ * |  Resv |  GL  |  CCR  |  ASI  |  %pil  |  PSTATE  |  Resv  |  CWP  |
+ * ---------------------------------------------------------------------
+ *  63   43 42  40 39   32 31   24 23    20 19       8 7      5 4     0
+ */
+#define TSTATE_GL	_AC(0x0000070000000000,UL) /* Global reg level  */
+#define TSTATE_CCR	_AC(0x000000ff00000000,UL) /* Condition Codes.	*/
+#define TSTATE_XCC	_AC(0x000000f000000000,UL) /* Condition Codes.	*/
+#define TSTATE_XNEG	_AC(0x0000008000000000,UL) /* %xcc Negative.	*/
+#define TSTATE_XZERO	_AC(0x0000004000000000,UL) /* %xcc Zero.	*/
+#define TSTATE_XOVFL	_AC(0x0000002000000000,UL) /* %xcc Overflow.	*/
+#define TSTATE_XCARRY	_AC(0x0000001000000000,UL) /* %xcc Carry.	*/
+#define TSTATE_ICC	_AC(0x0000000f00000000,UL) /* Condition Codes.	*/
+#define TSTATE_INEG	_AC(0x0000000800000000,UL) /* %icc Negative.	*/
+#define TSTATE_IZERO	_AC(0x0000000400000000,UL) /* %icc Zero.	*/
+#define TSTATE_IOVFL	_AC(0x0000000200000000,UL) /* %icc Overflow.	*/
+#define TSTATE_ICARRY	_AC(0x0000000100000000,UL) /* %icc Carry.	*/
+#define TSTATE_ASI	_AC(0x00000000ff000000,UL) /* AddrSpace ID.	*/
+#define TSTATE_PIL	_AC(0x0000000000f00000,UL) /* %pil (Linux traps)*/
+#define TSTATE_PSTATE	_AC(0x00000000000fff00,UL) /* PSTATE.		*/
+#define TSTATE_IG	_AC(0x0000000000080000,UL) /* Interrupt Globals.*/
+#define TSTATE_MG	_AC(0x0000000000040000,UL) /* MMU Globals.	*/
+#define TSTATE_CLE	_AC(0x0000000000020000,UL) /* CurrLittleEndian.	*/
+#define TSTATE_TLE	_AC(0x0000000000010000,UL) /* TrapLittleEndian.	*/
+#define TSTATE_MM	_AC(0x000000000000c000,UL) /* Memory Model.	*/
+#define TSTATE_TSO	_AC(0x0000000000000000,UL) /* MM: TSO		*/
+#define TSTATE_PSO	_AC(0x0000000000004000,UL) /* MM: PSO		*/
+#define TSTATE_RMO	_AC(0x0000000000008000,UL) /* MM: RMO		*/
+#define TSTATE_RED	_AC(0x0000000000002000,UL) /* Reset Error Debug.*/
+#define TSTATE_PEF	_AC(0x0000000000001000,UL) /* FPU Enable.	*/
+#define TSTATE_AM	_AC(0x0000000000000800,UL) /* Address Mask.	*/
+#define TSTATE_PRIV	_AC(0x0000000000000400,UL) /* Privilege.	*/
+#define TSTATE_IE	_AC(0x0000000000000200,UL) /* Interrupt Enable.	*/
+#define TSTATE_AG	_AC(0x0000000000000100,UL) /* Alternate Globals.*/
+#define TSTATE_SYSCALL	_AC(0x0000000000000020,UL) /* in syscall trap   */
+#define TSTATE_CWP	_AC(0x000000000000001f,UL) /* Curr Win-Pointer.	*/
+
+/* Floating-Point Registers State Register.
+ *
+ * --------------------------------
+ * |  Resv  |  FEF  |  DU  |  DL  |
+ * --------------------------------
+ *  63     3    2       1      0
+ */
+#define FPRS_FEF	_AC(0x0000000000000004,UL) /* FPU Enable.	*/
+#define FPRS_DU		_AC(0x0000000000000002,UL) /* Dirty Upper.	*/
+#define FPRS_DL		_AC(0x0000000000000001,UL) /* Dirty Lower.	*/
+
+/* Version Register.
+ *
+ * ------------------------------------------------------
+ * | MANUF | IMPL | MASK | Resv | MAXTL | Resv | MAXWIN |
+ * ------------------------------------------------------
+ *  63   48 47  32 31  24 23  16 15    8 7    5 4      0
+ */
+#define VERS_MANUF	_AC(0xffff000000000000,UL) /* Manufacturer.	*/
+#define VERS_IMPL	_AC(0x0000ffff00000000,UL) /* Implementation.	*/
+#define VERS_MASK	_AC(0x00000000ff000000,UL) /* Mask Set Revision.*/
+#define VERS_MAXTL	_AC(0x000000000000ff00,UL) /* Max Trap Level.	*/
+#define VERS_MAXWIN	_AC(0x000000000000001f,UL) /* Max RegWindow Idx.*/
+
+#endif /* !(_SPARC64_PSTATE_H) */
diff --git a/include/asm-sparc/ptrace.h b/include/asm-sparc/ptrace.h
index 11f3bc2..f36ab6c 100644
--- a/include/asm-sparc/ptrace.h
+++ b/include/asm-sparc/ptrace.h
@@ -1,175 +1,8 @@
-#ifndef _SPARC_PTRACE_H
-#define _SPARC_PTRACE_H
-
-#include <asm/psr.h>
-
-/* This struct defines the way the registers are stored on the 
- * stack during a system call and basically all traps.
- */
-
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-
-struct pt_regs {
-	unsigned long psr;
-	unsigned long pc;
-	unsigned long npc;
-	unsigned long y;
-	unsigned long u_regs[16]; /* globals and ins */
-};
-
-#define UREG_G0        0
-#define UREG_G1        1
-#define UREG_G2        2
-#define UREG_G3        3
-#define UREG_G4        4
-#define UREG_G5        5
-#define UREG_G6        6
-#define UREG_G7        7
-#define UREG_I0        8
-#define UREG_I1        9
-#define UREG_I2        10
-#define UREG_I3        11
-#define UREG_I4        12
-#define UREG_I5        13
-#define UREG_I6        14
-#define UREG_I7        15
-#define UREG_WIM       UREG_G0
-#define UREG_FADDR     UREG_G0
-#define UREG_FP        UREG_I6
-#define UREG_RETPC     UREG_I7
-
-static inline bool pt_regs_is_syscall(struct pt_regs *regs)
-{
-	return (regs->psr & PSR_SYSCALL);
-}
-
-static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
-{
-	return (regs->psr &= ~PSR_SYSCALL);
-}
-
-/* A register window */
-struct reg_window {
-	unsigned long locals[8];
-	unsigned long ins[8];
-};
-
-/* A Sparc stack frame */
-struct sparc_stackf {
-	unsigned long locals[8];
-        unsigned long ins[6];
-	struct sparc_stackf *fp;
-	unsigned long callers_pc;
-	char *structptr;
-	unsigned long xargs[6];
-	unsigned long xxargs[1];
-};	
-
-#define TRACEREG_SZ   sizeof(struct pt_regs)
-#define STACKFRAME_SZ sizeof(struct sparc_stackf)
-
-#ifdef __KERNEL__
-
-#define user_mode(regs) (!((regs)->psr & PSR_PS))
-#define instruction_pointer(regs) ((regs)->pc)
-unsigned long profile_pc(struct pt_regs *);
-extern void show_regs(struct pt_regs *);
+#ifndef ___ASM_SPARC_PTRACE_H
+#define ___ASM_SPARC_PTRACE_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/ptrace_64.h>
+#else
+#include <asm-sparc/ptrace_32.h>
 #endif
-
-#else /* __ASSEMBLY__ */
-/* For assembly code. */
-#define TRACEREG_SZ       0x50
-#define STACKFRAME_SZ     0x60
 #endif
-
-/*
- * The asm-offsets.h is a generated file, so we cannot include it.
- * It may be OK for glibc headers, but it's utterly pointless for C code.
- * The assembly code using those offsets has to include it explicitly.
- */
-/* #include <asm/asm-offsets.h> */
-
-/* These are for pt_regs. */
-#define PT_PSR    0x0
-#define PT_PC     0x4
-#define PT_NPC    0x8
-#define PT_Y      0xc
-#define PT_G0     0x10
-#define PT_WIM    PT_G0
-#define PT_G1     0x14
-#define PT_G2     0x18
-#define PT_G3     0x1c
-#define PT_G4     0x20
-#define PT_G5     0x24
-#define PT_G6     0x28
-#define PT_G7     0x2c
-#define PT_I0     0x30
-#define PT_I1     0x34
-#define PT_I2     0x38
-#define PT_I3     0x3c
-#define PT_I4     0x40
-#define PT_I5     0x44
-#define PT_I6     0x48
-#define PT_FP     PT_I6
-#define PT_I7     0x4c
-
-/* Reg_window offsets */
-#define RW_L0     0x00
-#define RW_L1     0x04
-#define RW_L2     0x08
-#define RW_L3     0x0c
-#define RW_L4     0x10
-#define RW_L5     0x14
-#define RW_L6     0x18
-#define RW_L7     0x1c
-#define RW_I0     0x20
-#define RW_I1     0x24
-#define RW_I2     0x28
-#define RW_I3     0x2c
-#define RW_I4     0x30
-#define RW_I5     0x34
-#define RW_I6     0x38
-#define RW_I7     0x3c
-
-/* Stack_frame offsets */
-#define SF_L0     0x00
-#define SF_L1     0x04
-#define SF_L2     0x08
-#define SF_L3     0x0c
-#define SF_L4     0x10
-#define SF_L5     0x14
-#define SF_L6     0x18
-#define SF_L7     0x1c
-#define SF_I0     0x20
-#define SF_I1     0x24
-#define SF_I2     0x28
-#define SF_I3     0x2c
-#define SF_I4     0x30
-#define SF_I5     0x34
-#define SF_FP     0x38
-#define SF_PC     0x3c
-#define SF_RETP   0x40
-#define SF_XARG0  0x44
-#define SF_XARG1  0x48
-#define SF_XARG2  0x4c
-#define SF_XARG3  0x50
-#define SF_XARG4  0x54
-#define SF_XARG5  0x58
-#define SF_XXARG  0x5c
-
-/* Stuff for the ptrace system call */
-#define PTRACE_SPARC_DETACH       11
-#define PTRACE_GETREGS            12
-#define PTRACE_SETREGS            13
-#define PTRACE_GETFPREGS          14
-#define PTRACE_SETFPREGS          15
-#define PTRACE_READDATA           16
-#define PTRACE_WRITEDATA          17
-#define PTRACE_READTEXT           18
-#define PTRACE_WRITETEXT          19
-#define PTRACE_GETFPAREGS         20
-#define PTRACE_SETFPAREGS         21
-
-#endif /* !(_SPARC_PTRACE_H) */
diff --git a/include/asm-sparc/ptrace_32.h b/include/asm-sparc/ptrace_32.h
new file mode 100644
index 0000000..0401cc7
--- /dev/null
+++ b/include/asm-sparc/ptrace_32.h
@@ -0,0 +1,175 @@
+#ifndef _SPARC_PTRACE_H
+#define _SPARC_PTRACE_H
+
+#include <asm/psr.h>
+
+/* This struct defines the way the registers are stored on the
+ * stack during a system call and basically all traps.
+ */
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+struct pt_regs {
+	unsigned long psr;
+	unsigned long pc;
+	unsigned long npc;
+	unsigned long y;
+	unsigned long u_regs[16]; /* globals and ins */
+};
+
+#define UREG_G0        0
+#define UREG_G1        1
+#define UREG_G2        2
+#define UREG_G3        3
+#define UREG_G4        4
+#define UREG_G5        5
+#define UREG_G6        6
+#define UREG_G7        7
+#define UREG_I0        8
+#define UREG_I1        9
+#define UREG_I2        10
+#define UREG_I3        11
+#define UREG_I4        12
+#define UREG_I5        13
+#define UREG_I6        14
+#define UREG_I7        15
+#define UREG_WIM       UREG_G0
+#define UREG_FADDR     UREG_G0
+#define UREG_FP        UREG_I6
+#define UREG_RETPC     UREG_I7
+
+static inline bool pt_regs_is_syscall(struct pt_regs *regs)
+{
+	return (regs->psr & PSR_SYSCALL);
+}
+
+static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
+{
+	return (regs->psr &= ~PSR_SYSCALL);
+}
+
+/* A register window */
+struct reg_window {
+	unsigned long locals[8];
+	unsigned long ins[8];
+};
+
+/* A Sparc stack frame */
+struct sparc_stackf {
+	unsigned long locals[8];
+        unsigned long ins[6];
+	struct sparc_stackf *fp;
+	unsigned long callers_pc;
+	char *structptr;
+	unsigned long xargs[6];
+	unsigned long xxargs[1];
+};
+
+#define TRACEREG_SZ   sizeof(struct pt_regs)
+#define STACKFRAME_SZ sizeof(struct sparc_stackf)
+
+#ifdef __KERNEL__
+
+#define user_mode(regs) (!((regs)->psr & PSR_PS))
+#define instruction_pointer(regs) ((regs)->pc)
+unsigned long profile_pc(struct pt_regs *);
+extern void show_regs(struct pt_regs *);
+#endif
+
+#else /* __ASSEMBLY__ */
+/* For assembly code. */
+#define TRACEREG_SZ       0x50
+#define STACKFRAME_SZ     0x60
+#endif
+
+/*
+ * The asm-offsets.h is a generated file, so we cannot include it.
+ * It may be OK for glibc headers, but it's utterly pointless for C code.
+ * The assembly code using those offsets has to include it explicitly.
+ */
+/* #include <asm/asm-offsets.h> */
+
+/* These are for pt_regs. */
+#define PT_PSR    0x0
+#define PT_PC     0x4
+#define PT_NPC    0x8
+#define PT_Y      0xc
+#define PT_G0     0x10
+#define PT_WIM    PT_G0
+#define PT_G1     0x14
+#define PT_G2     0x18
+#define PT_G3     0x1c
+#define PT_G4     0x20
+#define PT_G5     0x24
+#define PT_G6     0x28
+#define PT_G7     0x2c
+#define PT_I0     0x30
+#define PT_I1     0x34
+#define PT_I2     0x38
+#define PT_I3     0x3c
+#define PT_I4     0x40
+#define PT_I5     0x44
+#define PT_I6     0x48
+#define PT_FP     PT_I6
+#define PT_I7     0x4c
+
+/* Reg_window offsets */
+#define RW_L0     0x00
+#define RW_L1     0x04
+#define RW_L2     0x08
+#define RW_L3     0x0c
+#define RW_L4     0x10
+#define RW_L5     0x14
+#define RW_L6     0x18
+#define RW_L7     0x1c
+#define RW_I0     0x20
+#define RW_I1     0x24
+#define RW_I2     0x28
+#define RW_I3     0x2c
+#define RW_I4     0x30
+#define RW_I5     0x34
+#define RW_I6     0x38
+#define RW_I7     0x3c
+
+/* Stack_frame offsets */
+#define SF_L0     0x00
+#define SF_L1     0x04
+#define SF_L2     0x08
+#define SF_L3     0x0c
+#define SF_L4     0x10
+#define SF_L5     0x14
+#define SF_L6     0x18
+#define SF_L7     0x1c
+#define SF_I0     0x20
+#define SF_I1     0x24
+#define SF_I2     0x28
+#define SF_I3     0x2c
+#define SF_I4     0x30
+#define SF_I5     0x34
+#define SF_FP     0x38
+#define SF_PC     0x3c
+#define SF_RETP   0x40
+#define SF_XARG0  0x44
+#define SF_XARG1  0x48
+#define SF_XARG2  0x4c
+#define SF_XARG3  0x50
+#define SF_XARG4  0x54
+#define SF_XARG5  0x58
+#define SF_XXARG  0x5c
+
+/* Stuff for the ptrace system call */
+#define PTRACE_SPARC_DETACH       11
+#define PTRACE_GETREGS            12
+#define PTRACE_SETREGS            13
+#define PTRACE_GETFPREGS          14
+#define PTRACE_SETFPREGS          15
+#define PTRACE_READDATA           16
+#define PTRACE_WRITEDATA          17
+#define PTRACE_READTEXT           18
+#define PTRACE_WRITETEXT          19
+#define PTRACE_GETFPAREGS         20
+#define PTRACE_SETFPAREGS         21
+
+#endif /* !(_SPARC_PTRACE_H) */
diff --git a/include/asm-sparc/ptrace_64.h b/include/asm-sparc/ptrace_64.h
new file mode 100644
index 0000000..a682e66
--- /dev/null
+++ b/include/asm-sparc/ptrace_64.h
@@ -0,0 +1,346 @@
+#ifndef _SPARC64_PTRACE_H
+#define _SPARC64_PTRACE_H
+
+#include <asm/pstate.h>
+
+/* This struct defines the way the registers are stored on the
+ * stack during a system call and basically all traps.
+ */
+
+/* This magic value must have the low 9 bits clear,
+ * as that is where we encode the %tt value, see below.
+ */
+#define PT_REGS_MAGIC 0x57ac6c00
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+struct pt_regs {
+	unsigned long u_regs[16]; /* globals and ins */
+	unsigned long tstate;
+	unsigned long tpc;
+	unsigned long tnpc;
+	unsigned int y;
+
+	/* We encode a magic number, PT_REGS_MAGIC, along
+	 * with the %tt (trap type) register value at trap
+	 * entry time.  The magic number allows us to identify
+	 * accurately a trap stack frame in the stack
+	 * unwinder, and the %tt value allows us to test
+	 * things like "in a system call" etc. for an arbitray
+	 * process.
+	 *
+	 * The PT_REGS_MAGIC is choosen such that it can be
+	 * loaded completely using just a sethi instruction.
+	 */
+	unsigned int magic;
+};
+
+static inline int pt_regs_trap_type(struct pt_regs *regs)
+{
+	return regs->magic & 0x1ff;
+}
+
+static inline bool pt_regs_is_syscall(struct pt_regs *regs)
+{
+	return (regs->tstate & TSTATE_SYSCALL);
+}
+
+static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
+{
+	return (regs->tstate &= ~TSTATE_SYSCALL);
+}
+
+struct pt_regs32 {
+	unsigned int psr;
+	unsigned int pc;
+	unsigned int npc;
+	unsigned int y;
+	unsigned int u_regs[16]; /* globals and ins */
+};
+
+#define UREG_G0        0
+#define UREG_G1        1
+#define UREG_G2        2
+#define UREG_G3        3
+#define UREG_G4        4
+#define UREG_G5        5
+#define UREG_G6        6
+#define UREG_G7        7
+#define UREG_I0        8
+#define UREG_I1        9
+#define UREG_I2        10
+#define UREG_I3        11
+#define UREG_I4        12
+#define UREG_I5        13
+#define UREG_I6        14
+#define UREG_I7        15
+#define UREG_FP        UREG_I6
+#define UREG_RETPC     UREG_I7
+
+/* A V9 register window */
+struct reg_window {
+	unsigned long locals[8];
+	unsigned long ins[8];
+};
+
+/* A 32-bit register window. */
+struct reg_window32 {
+	unsigned int locals[8];
+	unsigned int ins[8];
+};
+
+/* A V9 Sparc stack frame */
+struct sparc_stackf {
+	unsigned long locals[8];
+        unsigned long ins[6];
+	struct sparc_stackf *fp;
+	unsigned long callers_pc;
+	char *structptr;
+	unsigned long xargs[6];
+	unsigned long xxargs[1];
+};
+
+/* A 32-bit Sparc stack frame */
+struct sparc_stackf32 {
+	unsigned int locals[8];
+        unsigned int ins[6];
+	unsigned int fp;
+	unsigned int callers_pc;
+	unsigned int structptr;
+	unsigned int xargs[6];
+	unsigned int xxargs[1];
+};
+
+struct sparc_trapf {
+	unsigned long locals[8];
+	unsigned long ins[8];
+	unsigned long _unused;
+	struct pt_regs *regs;
+};
+
+#define TRACEREG_SZ	sizeof(struct pt_regs)
+#define STACKFRAME_SZ	sizeof(struct sparc_stackf)
+
+#define TRACEREG32_SZ	sizeof(struct pt_regs32)
+#define STACKFRAME32_SZ	sizeof(struct sparc_stackf32)
+
+#ifdef __KERNEL__
+
+struct global_reg_snapshot {
+	unsigned long		tstate;
+	unsigned long		tpc;
+	unsigned long		tnpc;
+	unsigned long		o7;
+	unsigned long		i7;
+	struct thread_info	*thread;
+	unsigned long		pad1;
+	unsigned long		pad2;
+};
+
+#define __ARCH_WANT_COMPAT_SYS_PTRACE
+
+#define force_successful_syscall_return()	    \
+do {	current_thread_info()->syscall_noerror = 1; \
+} while (0)
+#define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
+#define instruction_pointer(regs) ((regs)->tpc)
+#define regs_return_value(regs) ((regs)->u_regs[UREG_I0])
+#ifdef CONFIG_SMP
+extern unsigned long profile_pc(struct pt_regs *);
+#else
+#define profile_pc(regs) instruction_pointer(regs)
+#endif
+extern void show_regs(struct pt_regs *);
+extern void __show_regs(struct pt_regs *);
+#endif
+
+#else /* __ASSEMBLY__ */
+/* For assembly code. */
+#define TRACEREG_SZ		0xa0
+#define STACKFRAME_SZ		0xc0
+
+#define TRACEREG32_SZ		0x50
+#define STACKFRAME32_SZ		0x60
+#endif
+
+#ifdef __KERNEL__
+#define STACK_BIAS		2047
+#endif
+
+/* These are for pt_regs. */
+#define PT_V9_G0     0x00
+#define PT_V9_G1     0x08
+#define PT_V9_G2     0x10
+#define PT_V9_G3     0x18
+#define PT_V9_G4     0x20
+#define PT_V9_G5     0x28
+#define PT_V9_G6     0x30
+#define PT_V9_G7     0x38
+#define PT_V9_I0     0x40
+#define PT_V9_I1     0x48
+#define PT_V9_I2     0x50
+#define PT_V9_I3     0x58
+#define PT_V9_I4     0x60
+#define PT_V9_I5     0x68
+#define PT_V9_I6     0x70
+#define PT_V9_FP     PT_V9_I6
+#define PT_V9_I7     0x78
+#define PT_V9_TSTATE 0x80
+#define PT_V9_TPC    0x88
+#define PT_V9_TNPC   0x90
+#define PT_V9_Y      0x98
+#define PT_V9_MAGIC  0x9c
+#define PT_TSTATE	PT_V9_TSTATE
+#define PT_TPC		PT_V9_TPC
+#define PT_TNPC		PT_V9_TNPC
+
+/* These for pt_regs32. */
+#define PT_PSR    0x0
+#define PT_PC     0x4
+#define PT_NPC    0x8
+#define PT_Y      0xc
+#define PT_G0     0x10
+#define PT_WIM    PT_G0
+#define PT_G1     0x14
+#define PT_G2     0x18
+#define PT_G3     0x1c
+#define PT_G4     0x20
+#define PT_G5     0x24
+#define PT_G6     0x28
+#define PT_G7     0x2c
+#define PT_I0     0x30
+#define PT_I1     0x34
+#define PT_I2     0x38
+#define PT_I3     0x3c
+#define PT_I4     0x40
+#define PT_I5     0x44
+#define PT_I6     0x48
+#define PT_FP     PT_I6
+#define PT_I7     0x4c
+
+/* Reg_window offsets */
+#define RW_V9_L0     0x00
+#define RW_V9_L1     0x08
+#define RW_V9_L2     0x10
+#define RW_V9_L3     0x18
+#define RW_V9_L4     0x20
+#define RW_V9_L5     0x28
+#define RW_V9_L6     0x30
+#define RW_V9_L7     0x38
+#define RW_V9_I0     0x40
+#define RW_V9_I1     0x48
+#define RW_V9_I2     0x50
+#define RW_V9_I3     0x58
+#define RW_V9_I4     0x60
+#define RW_V9_I5     0x68
+#define RW_V9_I6     0x70
+#define RW_V9_I7     0x78
+
+#define RW_L0     0x00
+#define RW_L1     0x04
+#define RW_L2     0x08
+#define RW_L3     0x0c
+#define RW_L4     0x10
+#define RW_L5     0x14
+#define RW_L6     0x18
+#define RW_L7     0x1c
+#define RW_I0     0x20
+#define RW_I1     0x24
+#define RW_I2     0x28
+#define RW_I3     0x2c
+#define RW_I4     0x30
+#define RW_I5     0x34
+#define RW_I6     0x38
+#define RW_I7     0x3c
+
+/* Stack_frame offsets */
+#define SF_V9_L0     0x00
+#define SF_V9_L1     0x08
+#define SF_V9_L2     0x10
+#define SF_V9_L3     0x18
+#define SF_V9_L4     0x20
+#define SF_V9_L5     0x28
+#define SF_V9_L6     0x30
+#define SF_V9_L7     0x38
+#define SF_V9_I0     0x40
+#define SF_V9_I1     0x48
+#define SF_V9_I2     0x50
+#define SF_V9_I3     0x58
+#define SF_V9_I4     0x60
+#define SF_V9_I5     0x68
+#define SF_V9_FP     0x70
+#define SF_V9_PC     0x78
+#define SF_V9_RETP   0x80
+#define SF_V9_XARG0  0x88
+#define SF_V9_XARG1  0x90
+#define SF_V9_XARG2  0x98
+#define SF_V9_XARG3  0xa0
+#define SF_V9_XARG4  0xa8
+#define SF_V9_XARG5  0xb0
+#define SF_V9_XXARG  0xb8
+
+#define SF_L0     0x00
+#define SF_L1     0x04
+#define SF_L2     0x08
+#define SF_L3     0x0c
+#define SF_L4     0x10
+#define SF_L5     0x14
+#define SF_L6     0x18
+#define SF_L7     0x1c
+#define SF_I0     0x20
+#define SF_I1     0x24
+#define SF_I2     0x28
+#define SF_I3     0x2c
+#define SF_I4     0x30
+#define SF_I5     0x34
+#define SF_FP     0x38
+#define SF_PC     0x3c
+#define SF_RETP   0x40
+#define SF_XARG0  0x44
+#define SF_XARG1  0x48
+#define SF_XARG2  0x4c
+#define SF_XARG3  0x50
+#define SF_XARG4  0x54
+#define SF_XARG5  0x58
+#define SF_XXARG  0x5c
+
+#ifdef __KERNEL__
+
+/* global_reg_snapshot offsets */
+#define GR_SNAP_TSTATE	0x00
+#define GR_SNAP_TPC	0x08
+#define GR_SNAP_TNPC	0x10
+#define GR_SNAP_O7	0x18
+#define GR_SNAP_I7	0x20
+#define GR_SNAP_THREAD	0x28
+#define GR_SNAP_PAD1	0x30
+#define GR_SNAP_PAD2	0x38
+
+#endif  /*  __KERNEL__  */
+
+/* Stuff for the ptrace system call */
+#define PTRACE_SPARC_DETACH       11
+#define PTRACE_GETREGS            12
+#define PTRACE_SETREGS            13
+#define PTRACE_GETFPREGS          14
+#define PTRACE_SETFPREGS          15
+#define PTRACE_READDATA           16
+#define PTRACE_WRITEDATA          17
+#define PTRACE_READTEXT           18
+#define PTRACE_WRITETEXT          19
+#define PTRACE_GETFPAREGS         20
+#define PTRACE_SETFPAREGS         21
+
+/* There are for debugging 64-bit processes, either from a 32 or 64 bit
+ * parent.  Thus their complements are for debugging 32-bit processes only.
+ */
+
+#define PTRACE_GETREGS64	  22
+#define PTRACE_SETREGS64	  23
+/* PTRACE_SYSCALL is 24 */
+#define PTRACE_GETFPREGS64	  25
+#define PTRACE_SETFPREGS64	  26
+
+#endif /* !(_SPARC64_PTRACE_H) */
diff --git a/include/asm-sparc/reboot.h b/include/asm-sparc/reboot.h
new file mode 100644
index 0000000..3f3f43f
--- /dev/null
+++ b/include/asm-sparc/reboot.h
@@ -0,0 +1,6 @@
+#ifndef _SPARC64_REBOOT_H
+#define _SPARC64_REBOOT_H
+
+extern void machine_alt_power_off(void);
+
+#endif /* _SPARC64_REBOOT_H */
diff --git a/include/asm-sparc/reg.h b/include/asm-sparc/reg.h
index ea0a7e5..cb34b0a 100644
--- a/include/asm-sparc/reg.h
+++ b/include/asm-sparc/reg.h
@@ -1,79 +1,8 @@
-/*
- * linux/include/asm-sparc/reg.h
- * Layout of the registers as expected by gdb on the Sparc
- * we should replace the user.h definitions with those in
- * this file, we don't even use the other 
- * -miguel
- *
- * The names of the structures, constants and aliases in this file
- * have the same names as the sunos ones, some programs rely on these
- * names (gdb for example).
- *
- */
-
-#ifndef __SPARC_REG_H
-#define __SPARC_REG_H
-
-struct regs {
-	int     r_psr;
-#define r_ps r_psr
-        int     r_pc; 
-        int     r_npc;
-        int     r_y;  
-        int     r_g1; 
-        int     r_g2;
-        int     r_g3;
-        int     r_g4;
-        int     r_g5;
-        int     r_g6;
-        int     r_g7;
-        int     r_o0;
-        int     r_o1;
-        int     r_o2;
-        int     r_o3;
-        int     r_o4;
-        int     r_o5;
-        int     r_o6;
-        int     r_o7;
-};
-
-struct fpq {
-        unsigned long *addr;
-        unsigned long instr;
-};
-
-struct  fq {
-        union {
-                double  whole;
-                struct  fpq fpq;
-        } FQu;
-};
-
-#define FPU_REGS_TYPE unsigned int
-#define FPU_FSR_TYPE unsigned
-
-struct fp_status {
-        union {
-                FPU_REGS_TYPE Fpu_regs[32];
-                double  Fpu_dregs[16];
-        } fpu_fr;
-        FPU_FSR_TYPE Fpu_fsr;
-        unsigned Fpu_flags;
-        unsigned Fpu_extra;
-        unsigned Fpu_qcnt;
-        struct fq Fpu_q[16];
-};
-
-#define fpu_regs  f_fpstatus.fpu_fr.Fpu_regs
-#define fpu_dregs f_fpstatus.fpu_fr.Fpu_dregs
-#define fpu_fsr   f_fpstatus.Fpu_fsr
-#define fpu_flags f_fpstatus.Fpu_flags
-#define fpu_extra f_fpstatus.Fpu_extra
-#define fpu_q     f_fpstatus.Fpu_q
-#define fpu_qcnt  f_fpstatus.Fpu_qcnt
-
-struct fpu {
-        struct fp_status f_fpstatus;
-};
-
-#endif /* __SPARC_REG_H */
+#ifndef ___ASM_SPARC_REG_H
+#define ___ASM_SPARC_REG_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/reg_64.h>
+#else
+#include <asm-sparc/reg_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/reg_32.h b/include/asm-sparc/reg_32.h
new file mode 100644
index 0000000..42fecfc
--- /dev/null
+++ b/include/asm-sparc/reg_32.h
@@ -0,0 +1,79 @@
+/*
+ * linux/include/asm-sparc/reg.h
+ * Layout of the registers as expected by gdb on the Sparc
+ * we should replace the user.h definitions with those in
+ * this file, we don't even use the other
+ * -miguel
+ *
+ * The names of the structures, constants and aliases in this file
+ * have the same names as the sunos ones, some programs rely on these
+ * names (gdb for example).
+ *
+ */
+
+#ifndef __SPARC_REG_H
+#define __SPARC_REG_H
+
+struct regs {
+	int     r_psr;
+#define r_ps r_psr
+        int     r_pc;
+        int     r_npc;
+        int     r_y;
+        int     r_g1;
+        int     r_g2;
+        int     r_g3;
+        int     r_g4;
+        int     r_g5;
+        int     r_g6;
+        int     r_g7;
+        int     r_o0;
+        int     r_o1;
+        int     r_o2;
+        int     r_o3;
+        int     r_o4;
+        int     r_o5;
+        int     r_o6;
+        int     r_o7;
+};
+
+struct fpq {
+        unsigned long *addr;
+        unsigned long instr;
+};
+
+struct  fq {
+        union {
+                double  whole;
+                struct  fpq fpq;
+        } FQu;
+};
+
+#define FPU_REGS_TYPE unsigned int
+#define FPU_FSR_TYPE unsigned
+
+struct fp_status {
+        union {
+                FPU_REGS_TYPE Fpu_regs[32];
+                double  Fpu_dregs[16];
+        } fpu_fr;
+        FPU_FSR_TYPE Fpu_fsr;
+        unsigned Fpu_flags;
+        unsigned Fpu_extra;
+        unsigned Fpu_qcnt;
+        struct fq Fpu_q[16];
+};
+
+#define fpu_regs  f_fpstatus.fpu_fr.Fpu_regs
+#define fpu_dregs f_fpstatus.fpu_fr.Fpu_dregs
+#define fpu_fsr   f_fpstatus.Fpu_fsr
+#define fpu_flags f_fpstatus.Fpu_flags
+#define fpu_extra f_fpstatus.Fpu_extra
+#define fpu_q     f_fpstatus.Fpu_q
+#define fpu_qcnt  f_fpstatus.Fpu_qcnt
+
+struct fpu {
+        struct fp_status f_fpstatus;
+};
+
+#endif /* __SPARC_REG_H */
diff --git a/include/asm-sparc/reg_64.h b/include/asm-sparc/reg_64.h
new file mode 100644
index 0000000..eb24a07
--- /dev/null
+++ b/include/asm-sparc/reg_64.h
@@ -0,0 +1,56 @@
+/*
+ * linux/asm-sparc64/reg.h
+ * Layout of the registers as expected by gdb on the Sparc
+ * we should replace the user.h definitions with those in
+ * this file, we don't even use the other
+ * -miguel
+ *
+ * The names of the structures, constants and aliases in this file
+ * have the same names as the sunos ones, some programs rely on these
+ * names (gdb for example).
+ *
+ */
+
+#ifndef __SPARC64_REG_H
+#define __SPARC64_REG_H
+
+struct regs {
+        unsigned long r_g1;
+        unsigned long r_g2;
+        unsigned long r_g3;
+        unsigned long r_g4;
+        unsigned long r_g5;
+        unsigned long r_g6;
+        unsigned long r_g7;
+        unsigned long r_o0;
+        unsigned long r_o1;
+        unsigned long r_o2;
+        unsigned long r_o3;
+        unsigned long r_o4;
+        unsigned long r_o5;
+        unsigned long r_o6;
+        unsigned long r_o7;
+        unsigned long __pad;
+        unsigned long r_tstate;
+        unsigned long r_tpc;
+        unsigned long r_tnpc;
+        unsigned int  r_y;
+        unsigned int  r_fprs;
+};
+
+#define FPU_REGS_TYPE unsigned int
+#define FPU_FSR_TYPE unsigned long
+
+struct fp_status {
+        unsigned long fpu_fr[32];
+        unsigned long Fpu_fsr;
+};
+
+struct fpu {
+	struct fp_status f_fpstatus;
+};
+
+#define fpu_regs  f_fpstatus.fpu_fr
+#define fpu_fsr   f_fpstatus.Fpu_fsr
+
+#endif /* __SPARC64_REG_H */
diff --git a/include/asm-sparc/resource.h b/include/asm-sparc/resource.h
index 985948a..fe163ca 100644
--- a/include/asm-sparc/resource.h
+++ b/include/asm-sparc/resource.h
@@ -1,7 +1,7 @@
 /*
  * resource.h: Resource definitions.
  *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
  */
 
 #ifndef _SPARC_RESOURCE_H
@@ -14,12 +14,16 @@
 #define RLIMIT_NOFILE		6	/* max number of open files */
 #define RLIMIT_NPROC		7	/* max number of processes */
 
+#if defined(__sparc__) && defined(__arch64__)
+/* Use generic version */
+#else
 /*
  * SuS says limits have to be unsigned.
  * We make this unsigned, but keep the
  * old value for compatibility:
  */
 #define RLIM_INFINITY		0x7fffffff
+#endif
 
 #include <asm-generic/resource.h>
 
diff --git a/include/asm-sparc/rwsem-const.h b/include/asm-sparc/rwsem-const.h
new file mode 100644
index 0000000..a303c9d
--- /dev/null
+++ b/include/asm-sparc/rwsem-const.h
@@ -0,0 +1,12 @@
+/* rwsem-const.h: RW semaphore counter constants.  */
+#ifndef _SPARC64_RWSEM_CONST_H
+#define _SPARC64_RWSEM_CONST_H
+
+#define RWSEM_UNLOCKED_VALUE		0x00000000
+#define RWSEM_ACTIVE_BIAS		0x00000001
+#define RWSEM_ACTIVE_MASK		0x0000ffff
+#define RWSEM_WAITING_BIAS		0xffff0000
+#define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
+#define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
+
+#endif /* _SPARC64_RWSEM_CONST_H */
diff --git a/include/asm-sparc/rwsem.h b/include/asm-sparc/rwsem.h
new file mode 100644
index 0000000..1dc129a
--- /dev/null
+++ b/include/asm-sparc/rwsem.h
@@ -0,0 +1,84 @@
+/*
+ * rwsem.h: R/W semaphores implemented using CAS
+ *
+ * Written by David S. Miller (davem@redhat.com), 2001.
+ * Derived from asm-i386/rwsem.h
+ */
+#ifndef _SPARC64_RWSEM_H
+#define _SPARC64_RWSEM_H
+
+#ifndef _LINUX_RWSEM_H
+#error "please don't include asm/rwsem.h directly, use linux/rwsem.h instead"
+#endif
+
+#ifdef __KERNEL__
+
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <asm/rwsem-const.h>
+
+struct rwsem_waiter;
+
+struct rw_semaphore {
+	signed int count;
+	spinlock_t		wait_lock;
+	struct list_head	wait_list;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+	struct lockdep_map	dep_map;
+#endif
+};
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
+#else
+# define __RWSEM_DEP_MAP_INIT(lockname)
+#endif
+
+#define __RWSEM_INITIALIZER(name) \
+{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, LIST_HEAD_INIT((name).wait_list) \
+  __RWSEM_DEP_MAP_INIT(name) }
+
+#define DECLARE_RWSEM(name) \
+	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
+
+extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
+			 struct lock_class_key *key);
+
+#define init_rwsem(sem)						\
+do {								\
+	static struct lock_class_key __key;			\
+								\
+	__init_rwsem((sem), #sem, &__key);			\
+} while (0)
+
+extern void __down_read(struct rw_semaphore *sem);
+extern int __down_read_trylock(struct rw_semaphore *sem);
+extern void __down_write(struct rw_semaphore *sem);
+extern int __down_write_trylock(struct rw_semaphore *sem);
+extern void __up_read(struct rw_semaphore *sem);
+extern void __up_write(struct rw_semaphore *sem);
+extern void __downgrade_write(struct rw_semaphore *sem);
+
+static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
+{
+	__down_write(sem);
+}
+
+static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
+{
+	return atomic_add_return(delta, (atomic_t *)(&sem->count));
+}
+
+static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
+{
+	atomic_add(delta, (atomic_t *)(&sem->count));
+}
+
+static inline int rwsem_is_locked(struct rw_semaphore *sem)
+{
+	return (sem->count != 0);
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* _SPARC64_RWSEM_H */
diff --git a/include/asm-sparc/sbus.h b/include/asm-sparc/sbus.h
index f1d2fe1..8f29a19 100644
--- a/include/asm-sparc/sbus.h
+++ b/include/asm-sparc/sbus.h
@@ -1,153 +1,8 @@
-/*
- * sbus.h:  Defines for the Sun SBus.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef _SPARC_SBUS_H
-#define _SPARC_SBUS_H
-
-#include <linux/dma-mapping.h>
-#include <linux/ioport.h>
-
-#include <asm/oplib.h>
-#include <asm/prom.h>
-#include <asm/of_device.h>
-#include <asm/scatterlist.h>
-
-/* We scan which devices are on the SBus using the PROM node device
- * tree.  SBus devices are described in two different ways.  You can
- * either get an absolute address at which to access the device, or
- * you can get a SBus 'slot' number and an offset within that slot.
- */
-
-/* The base address at which to calculate device OBIO addresses. */
-#define SUN_SBUS_BVADDR        0xf8000000
-#define SBUS_OFF_MASK          0x01ffffff
-
-/* These routines are used to calculate device address from slot
- * numbers + offsets, and vice versa.
- */
-
-static inline unsigned long sbus_devaddr(int slotnum, unsigned long offset)
-{
-  return (unsigned long) (SUN_SBUS_BVADDR+((slotnum)<<25)+(offset));
-}
-
-static inline int sbus_dev_slot(unsigned long dev_addr)
-{
-  return (int) (((dev_addr)-SUN_SBUS_BVADDR)>>25);
-}
-
-struct sbus_bus;
-
-/* Linux SBUS device tables */
-struct sbus_dev {
-	struct of_device	ofdev;
-	struct sbus_bus		*bus;
-	struct sbus_dev		*next;
-	struct sbus_dev		*child;
-	struct sbus_dev		*parent;
-	int prom_node;	
-	char prom_name[64];
-	int slot;
-
-	struct resource resource[PROMREG_MAX];
-
-	struct linux_prom_registers reg_addrs[PROMREG_MAX];
-	int num_registers;
-
-	struct linux_prom_ranges device_ranges[PROMREG_MAX];
-	int num_device_ranges;
-
-	unsigned int irqs[4];
-	int num_irqs;
-};
-#define to_sbus_device(d) container_of(d, struct sbus_dev, ofdev.dev)
-
-/* This struct describes the SBus(s) found on this machine. */
-struct sbus_bus {
-	struct of_device	ofdev;
-	struct sbus_dev		*devices;	/* Link to devices on this SBus */
-	struct sbus_bus		*next;		/* next SBus, if more than one SBus */
-	int			prom_node;	/* PROM device tree node for this SBus */
-	char			prom_name[64];  /* Usually "sbus" or "sbi" */
-	int			clock_freq;
-
-	struct linux_prom_ranges sbus_ranges[PROMREG_MAX];
-	int num_sbus_ranges;
-
-	int devid;
-	int board;
-};
-#define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev)
-
-extern struct sbus_bus *sbus_root;
-
-static inline int
-sbus_is_slave(struct sbus_dev *dev)
-{
-	/* XXX Have to write this for sun4c's */
-	return 0;
-}
-
-/* Device probing routines could find these handy */
-#define for_each_sbus(bus) \
-        for((bus) = sbus_root; (bus); (bus)=(bus)->next)
-
-#define for_each_sbusdev(device, bus) \
-        for((device) = (bus)->devices; (device); (device)=(device)->next)
-        
-#define for_all_sbusdev(device, bus) \
-	for ((bus) = sbus_root; (bus); (bus) = (bus)->next) \
-		for ((device) = (bus)->devices; (device); (device) = (device)->next)
-
-/* Driver DVMA interfaces. */
-#define sbus_can_dma_64bit(sdev)	(0) /* actually, sparc_cpu_model==sun4d */
-#define sbus_can_burst64(sdev)		(0) /* actually, sparc_cpu_model==sun4d */
-extern void sbus_set_sbus64(struct sbus_dev *, int);
-extern void sbus_fill_device_irq(struct sbus_dev *);
-
-/* These yield IOMMU mappings in consistent mode. */
-extern void *sbus_alloc_consistent(struct sbus_dev *, long, u32 *dma_addrp);
-extern void sbus_free_consistent(struct sbus_dev *, long, void *, u32);
-void prom_adjust_ranges(struct linux_prom_ranges *, int,
-			struct linux_prom_ranges *, int);
-
-#define SBUS_DMA_BIDIRECTIONAL	DMA_BIDIRECTIONAL
-#define SBUS_DMA_TODEVICE	DMA_TO_DEVICE
-#define SBUS_DMA_FROMDEVICE	DMA_FROM_DEVICE
-#define	SBUS_DMA_NONE		DMA_NONE
-
-/* All the rest use streaming mode mappings. */
-extern dma_addr_t sbus_map_single(struct sbus_dev *, void *, size_t, int);
-extern void sbus_unmap_single(struct sbus_dev *, dma_addr_t, size_t, int);
-extern int sbus_map_sg(struct sbus_dev *, struct scatterlist *, int, int);
-extern void sbus_unmap_sg(struct sbus_dev *, struct scatterlist *, int, int);
-
-/* Finally, allow explicit synchronization of streamable mappings. */
-extern void sbus_dma_sync_single_for_cpu(struct sbus_dev *, dma_addr_t, size_t, int);
-#define sbus_dma_sync_single sbus_dma_sync_single_for_cpu
-extern void sbus_dma_sync_single_for_device(struct sbus_dev *, dma_addr_t, size_t, int);
-extern void sbus_dma_sync_sg_for_cpu(struct sbus_dev *, struct scatterlist *, int, int);
-#define sbus_dma_sync_sg sbus_dma_sync_sg_for_cpu
-extern void sbus_dma_sync_sg_for_device(struct sbus_dev *, struct scatterlist *, int, int);
-
-/* Eric Brower (ebrower@usa.net)
- * Translate SBus interrupt levels to ino values--
- * this is used when converting sbus "interrupts" OBP 
- * node values to "intr" node values, and is platform 
- * dependent.  If only we could call OBP with 
- * "sbus-intr>cpu (sbint -- ino)" from kernel...
- * See .../drivers/sbus/sbus.c for details.
- */
-BTFIXUPDEF_CALL(unsigned int, sbint_to_irq, struct sbus_dev *sdev, unsigned int)
-#define sbint_to_irq(sdev, sbint) BTFIXUP_CALL(sbint_to_irq)(sdev, sbint)
-
-extern void sbus_arch_bus_ranges_init(struct device_node *, struct sbus_bus *);
-extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *);
-extern void sbus_setup_arch_props(struct sbus_bus *, struct device_node *);
-extern int sbus_arch_preinit(void);
-extern void sbus_arch_postinit(void);
-
-#endif /* !(_SPARC_SBUS_H) */
+#ifndef ___ASM_SPARC_SBUS_H
+#define ___ASM_SPARC_SBUS_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/sbus_64.h>
+#else
+#include <asm-sparc/sbus_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/sbus_32.h b/include/asm-sparc/sbus_32.h
new file mode 100644
index 0000000..77b5d3a
--- /dev/null
+++ b/include/asm-sparc/sbus_32.h
@@ -0,0 +1,153 @@
+/*
+ * sbus.h:  Defines for the Sun SBus.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_SBUS_H
+#define _SPARC_SBUS_H
+
+#include <linux/dma-mapping.h>
+#include <linux/ioport.h>
+
+#include <asm/oplib.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
+#include <asm/scatterlist.h>
+
+/* We scan which devices are on the SBus using the PROM node device
+ * tree.  SBus devices are described in two different ways.  You can
+ * either get an absolute address at which to access the device, or
+ * you can get a SBus 'slot' number and an offset within that slot.
+ */
+
+/* The base address at which to calculate device OBIO addresses. */
+#define SUN_SBUS_BVADDR        0xf8000000
+#define SBUS_OFF_MASK          0x01ffffff
+
+/* These routines are used to calculate device address from slot
+ * numbers + offsets, and vice versa.
+ */
+
+static inline unsigned long sbus_devaddr(int slotnum, unsigned long offset)
+{
+  return (unsigned long) (SUN_SBUS_BVADDR+((slotnum)<<25)+(offset));
+}
+
+static inline int sbus_dev_slot(unsigned long dev_addr)
+{
+  return (int) (((dev_addr)-SUN_SBUS_BVADDR)>>25);
+}
+
+struct sbus_bus;
+
+/* Linux SBUS device tables */
+struct sbus_dev {
+	struct of_device	ofdev;
+	struct sbus_bus		*bus;
+	struct sbus_dev		*next;
+	struct sbus_dev		*child;
+	struct sbus_dev		*parent;
+	int prom_node;
+	char prom_name[64];
+	int slot;
+
+	struct resource resource[PROMREG_MAX];
+
+	struct linux_prom_registers reg_addrs[PROMREG_MAX];
+	int num_registers;
+
+	struct linux_prom_ranges device_ranges[PROMREG_MAX];
+	int num_device_ranges;
+
+	unsigned int irqs[4];
+	int num_irqs;
+};
+#define to_sbus_device(d) container_of(d, struct sbus_dev, ofdev.dev)
+
+/* This struct describes the SBus(s) found on this machine. */
+struct sbus_bus {
+	struct of_device	ofdev;
+	struct sbus_dev		*devices;	/* Link to devices on this SBus */
+	struct sbus_bus		*next;		/* next SBus, if more than one SBus */
+	int			prom_node;	/* PROM device tree node for this SBus */
+	char			prom_name[64];  /* Usually "sbus" or "sbi" */
+	int			clock_freq;
+
+	struct linux_prom_ranges sbus_ranges[PROMREG_MAX];
+	int num_sbus_ranges;
+
+	int devid;
+	int board;
+};
+#define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev)
+
+extern struct sbus_bus *sbus_root;
+
+static inline int
+sbus_is_slave(struct sbus_dev *dev)
+{
+	/* XXX Have to write this for sun4c's */
+	return 0;
+}
+
+/* Device probing routines could find these handy */
+#define for_each_sbus(bus) \
+        for((bus) = sbus_root; (bus); (bus)=(bus)->next)
+
+#define for_each_sbusdev(device, bus) \
+        for((device) = (bus)->devices; (device); (device)=(device)->next)
+
+#define for_all_sbusdev(device, bus) \
+	for ((bus) = sbus_root; (bus); (bus) = (bus)->next) \
+		for ((device) = (bus)->devices; (device); (device) = (device)->next)
+
+/* Driver DVMA interfaces. */
+#define sbus_can_dma_64bit(sdev)	(0) /* actually, sparc_cpu_model==sun4d */
+#define sbus_can_burst64(sdev)		(0) /* actually, sparc_cpu_model==sun4d */
+extern void sbus_set_sbus64(struct sbus_dev *, int);
+extern void sbus_fill_device_irq(struct sbus_dev *);
+
+/* These yield IOMMU mappings in consistent mode. */
+extern void *sbus_alloc_consistent(struct sbus_dev *, long, u32 *dma_addrp);
+extern void sbus_free_consistent(struct sbus_dev *, long, void *, u32);
+void prom_adjust_ranges(struct linux_prom_ranges *, int,
+			struct linux_prom_ranges *, int);
+
+#define SBUS_DMA_BIDIRECTIONAL	DMA_BIDIRECTIONAL
+#define SBUS_DMA_TODEVICE	DMA_TO_DEVICE
+#define SBUS_DMA_FROMDEVICE	DMA_FROM_DEVICE
+#define	SBUS_DMA_NONE		DMA_NONE
+
+/* All the rest use streaming mode mappings. */
+extern dma_addr_t sbus_map_single(struct sbus_dev *, void *, size_t, int);
+extern void sbus_unmap_single(struct sbus_dev *, dma_addr_t, size_t, int);
+extern int sbus_map_sg(struct sbus_dev *, struct scatterlist *, int, int);
+extern void sbus_unmap_sg(struct sbus_dev *, struct scatterlist *, int, int);
+
+/* Finally, allow explicit synchronization of streamable mappings. */
+extern void sbus_dma_sync_single_for_cpu(struct sbus_dev *, dma_addr_t, size_t, int);
+#define sbus_dma_sync_single sbus_dma_sync_single_for_cpu
+extern void sbus_dma_sync_single_for_device(struct sbus_dev *, dma_addr_t, size_t, int);
+extern void sbus_dma_sync_sg_for_cpu(struct sbus_dev *, struct scatterlist *, int, int);
+#define sbus_dma_sync_sg sbus_dma_sync_sg_for_cpu
+extern void sbus_dma_sync_sg_for_device(struct sbus_dev *, struct scatterlist *, int, int);
+
+/* Eric Brower (ebrower@usa.net)
+ * Translate SBus interrupt levels to ino values--
+ * this is used when converting sbus "interrupts" OBP
+ * node values to "intr" node values, and is platform
+ * dependent.  If only we could call OBP with
+ * "sbus-intr>cpu (sbint -- ino)" from kernel...
+ * See .../drivers/sbus/sbus.c for details.
+ */
+BTFIXUPDEF_CALL(unsigned int, sbint_to_irq, struct sbus_dev *sdev, unsigned int)
+#define sbint_to_irq(sdev, sbint) BTFIXUP_CALL(sbint_to_irq)(sdev, sbint)
+
+extern void sbus_arch_bus_ranges_init(struct device_node *, struct sbus_bus *);
+extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *);
+extern void sbus_setup_arch_props(struct sbus_bus *, struct device_node *);
+extern int sbus_arch_preinit(void);
+extern void sbus_arch_postinit(void);
+
+#endif /* !(_SPARC_SBUS_H) */
diff --git a/include/asm-sparc/sbus_64.h b/include/asm-sparc/sbus_64.h
new file mode 100644
index 0000000..0e16b6d
--- /dev/null
+++ b/include/asm-sparc/sbus_64.h
@@ -0,0 +1,190 @@
+/* sbus.h: Defines for the Sun SBus.
+ *
+ * Copyright (C) 1996, 1999, 2007 David S. Miller (davem@davemloft.net)
+ */
+
+#ifndef _SPARC64_SBUS_H
+#define _SPARC64_SBUS_H
+
+#include <linux/dma-mapping.h>
+#include <linux/ioport.h>
+
+#include <asm/oplib.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
+#include <asm/iommu.h>
+#include <asm/scatterlist.h>
+
+/* We scan which devices are on the SBus using the PROM node device
+ * tree.  SBus devices are described in two different ways.  You can
+ * either get an absolute address at which to access the device, or
+ * you can get a SBus 'slot' number and an offset within that slot.
+ */
+
+/* The base address at which to calculate device OBIO addresses. */
+#define SUN_SBUS_BVADDR        0x00000000
+#define SBUS_OFF_MASK          0x0fffffff
+
+/* These routines are used to calculate device address from slot
+ * numbers + offsets, and vice versa.
+ */
+
+static inline unsigned long sbus_devaddr(int slotnum, unsigned long offset)
+{
+  return (unsigned long) (SUN_SBUS_BVADDR+((slotnum)<<28)+(offset));
+}
+
+static inline int sbus_dev_slot(unsigned long dev_addr)
+{
+  return (int) (((dev_addr)-SUN_SBUS_BVADDR)>>28);
+}
+
+struct sbus_bus;
+
+/* Linux SBUS device tables */
+struct sbus_dev {
+	struct of_device	ofdev;
+	struct sbus_bus		*bus;
+	struct sbus_dev		*next;
+	struct sbus_dev		*child;
+	struct sbus_dev		*parent;
+	int prom_node;
+	char prom_name[64];
+	int slot;
+
+	struct resource resource[PROMREG_MAX];
+
+	struct linux_prom_registers reg_addrs[PROMREG_MAX];
+	int num_registers;
+
+	struct linux_prom_ranges device_ranges[PROMREG_MAX];
+	int num_device_ranges;
+
+	unsigned int irqs[4];
+	int num_irqs;
+};
+#define to_sbus_device(d) container_of(d, struct sbus_dev, ofdev.dev)
+
+/* This struct describes the SBus(s) found on this machine. */
+struct sbus_bus {
+	struct of_device	ofdev;
+	struct sbus_dev		*devices;	/* Tree of SBUS devices	*/
+	struct sbus_bus		*next;		/* Next SBUS in system	*/
+	int			prom_node;      /* OBP node of SBUS	*/
+	char			prom_name[64];	/* Usually "sbus" or "sbi" */
+	int			clock_freq;
+
+	struct linux_prom_ranges sbus_ranges[PROMREG_MAX];
+	int num_sbus_ranges;
+
+	int portid;
+};
+#define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev)
+
+extern struct sbus_bus *sbus_root;
+
+/* Device probing routines could find these handy */
+#define for_each_sbus(bus) \
+        for((bus) = sbus_root; (bus); (bus)=(bus)->next)
+
+#define for_each_sbusdev(device, bus) \
+        for((device) = (bus)->devices; (device); (device)=(device)->next)
+
+#define for_all_sbusdev(device, bus) \
+	for ((bus) = sbus_root; (bus); (bus) = (bus)->next) \
+		for ((device) = (bus)->devices; (device); (device) = (device)->next)
+
+/* Driver DVMA interfaces. */
+#define sbus_can_dma_64bit(sdev)	(1)
+#define sbus_can_burst64(sdev)		(1)
+extern void sbus_set_sbus64(struct sbus_dev *, int);
+extern void sbus_fill_device_irq(struct sbus_dev *);
+
+static inline void *sbus_alloc_consistent(struct sbus_dev *sdev , size_t size,
+					  dma_addr_t *dma_handle)
+{
+	return dma_alloc_coherent(&sdev->ofdev.dev, size,
+				  dma_handle, GFP_ATOMIC);
+}
+
+static inline void sbus_free_consistent(struct sbus_dev *sdev, size_t size,
+					void *vaddr, dma_addr_t dma_handle)
+{
+	return dma_free_coherent(&sdev->ofdev.dev, size, vaddr, dma_handle);
+}
+
+#define SBUS_DMA_BIDIRECTIONAL	DMA_BIDIRECTIONAL
+#define SBUS_DMA_TODEVICE	DMA_TO_DEVICE
+#define SBUS_DMA_FROMDEVICE	DMA_FROM_DEVICE
+#define	SBUS_DMA_NONE		DMA_NONE
+
+/* All the rest use streaming mode mappings. */
+static inline dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr,
+					 size_t size, int direction)
+{
+	return dma_map_single(&sdev->ofdev.dev, ptr, size,
+			      (enum dma_data_direction) direction);
+}
+
+static inline void sbus_unmap_single(struct sbus_dev *sdev,
+				     dma_addr_t dma_addr, size_t size,
+				     int direction)
+{
+	dma_unmap_single(&sdev->ofdev.dev, dma_addr, size,
+			 (enum dma_data_direction) direction);
+}
+
+static inline int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg,
+			      int nents, int direction)
+{
+	return dma_map_sg(&sdev->ofdev.dev, sg, nents,
+			  (enum dma_data_direction) direction);
+}
+
+static inline void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg,
+				 int nents, int direction)
+{
+	dma_unmap_sg(&sdev->ofdev.dev, sg, nents,
+		     (enum dma_data_direction) direction);
+}
+
+/* Finally, allow explicit synchronization of streamable mappings. */
+static inline void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev,
+						dma_addr_t dma_handle,
+						size_t size, int direction)
+{
+	dma_sync_single_for_cpu(&sdev->ofdev.dev, dma_handle, size,
+				(enum dma_data_direction) direction);
+}
+#define sbus_dma_sync_single sbus_dma_sync_single_for_cpu
+
+static inline void sbus_dma_sync_single_for_device(struct sbus_dev *sdev,
+						   dma_addr_t dma_handle,
+						   size_t size, int direction)
+{
+	/* No flushing needed to sync cpu writes to the device.  */
+}
+
+static inline void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev,
+					    struct scatterlist *sg,
+					    int nents, int direction)
+{
+	dma_sync_sg_for_cpu(&sdev->ofdev.dev, sg, nents,
+			    (enum dma_data_direction) direction);
+}
+#define sbus_dma_sync_sg sbus_dma_sync_sg_for_cpu
+
+static inline void sbus_dma_sync_sg_for_device(struct sbus_dev *sdev,
+					       struct scatterlist *sg,
+					       int nents, int direction)
+{
+	/* No flushing needed to sync cpu writes to the device.  */
+}
+
+extern void sbus_arch_bus_ranges_init(struct device_node *, struct sbus_bus *);
+extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *);
+extern void sbus_setup_arch_props(struct sbus_bus *, struct device_node *);
+extern int sbus_arch_preinit(void);
+extern void sbus_arch_postinit(void);
+
+#endif /* !(_SPARC64_SBUS_H) */
diff --git a/include/asm-sparc/scatterlist.h b/include/asm-sparc/scatterlist.h
index c82609c..b1a0e31 100644
--- a/include/asm-sparc/scatterlist.h
+++ b/include/asm-sparc/scatterlist.h
@@ -1,26 +1,8 @@
-#ifndef _SPARC_SCATTERLIST_H
-#define _SPARC_SCATTERLIST_H
-
-#include <linux/types.h>
-
-struct scatterlist {
-#ifdef CONFIG_DEBUG_SG
-	unsigned long sg_magic;
+#ifndef ___ASM_SPARC_SCATTERLIST_H
+#define ___ASM_SPARC_SCATTERLIST_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/scatterlist_64.h>
+#else
+#include <asm-sparc/scatterlist_32.h>
 #endif
-	unsigned long page_link;
-	unsigned int offset;
-
-	unsigned int length;
-
-	__u32 dvma_address; /* A place to hang host-specific addresses at. */
-	__u32 dvma_length;
-};
-
-#define sg_dma_address(sg) ((sg)->dvma_address)
-#define sg_dma_len(sg)     ((sg)->dvma_length)
-
-#define ISA_DMA_THRESHOLD (~0UL)
-
-#define ARCH_HAS_SG_CHAIN
-
-#endif /* !(_SPARC_SCATTERLIST_H) */
+#endif
diff --git a/include/asm-sparc/scatterlist_32.h b/include/asm-sparc/scatterlist_32.h
new file mode 100644
index 0000000..c82609c
--- /dev/null
+++ b/include/asm-sparc/scatterlist_32.h
@@ -0,0 +1,26 @@
+#ifndef _SPARC_SCATTERLIST_H
+#define _SPARC_SCATTERLIST_H
+
+#include <linux/types.h>
+
+struct scatterlist {
+#ifdef CONFIG_DEBUG_SG
+	unsigned long sg_magic;
+#endif
+	unsigned long page_link;
+	unsigned int offset;
+
+	unsigned int length;
+
+	__u32 dvma_address; /* A place to hang host-specific addresses at. */
+	__u32 dvma_length;
+};
+
+#define sg_dma_address(sg) ((sg)->dvma_address)
+#define sg_dma_len(sg)     ((sg)->dvma_length)
+
+#define ISA_DMA_THRESHOLD (~0UL)
+
+#define ARCH_HAS_SG_CHAIN
+
+#endif /* !(_SPARC_SCATTERLIST_H) */
diff --git a/include/asm-sparc/scatterlist_64.h b/include/asm-sparc/scatterlist_64.h
new file mode 100644
index 0000000..81bd058
--- /dev/null
+++ b/include/asm-sparc/scatterlist_64.h
@@ -0,0 +1,27 @@
+#ifndef _SPARC64_SCATTERLIST_H
+#define _SPARC64_SCATTERLIST_H
+
+#include <asm/page.h>
+#include <asm/types.h>
+
+struct scatterlist {
+#ifdef CONFIG_DEBUG_SG
+	unsigned long	sg_magic;
+#endif
+	unsigned long	page_link;
+	unsigned int	offset;
+
+	unsigned int	length;
+
+	dma_addr_t	dma_address;
+	__u32		dma_length;
+};
+
+#define sg_dma_address(sg)	((sg)->dma_address)
+#define sg_dma_len(sg)     	((sg)->dma_length)
+
+#define ISA_DMA_THRESHOLD	(~0UL)
+
+#define ARCH_HAS_SG_CHAIN
+
+#endif /* !(_SPARC64_SCATTERLIST_H) */
diff --git a/include/asm-sparc/scratchpad.h b/include/asm-sparc/scratchpad.h
new file mode 100644
index 0000000..5e8b01f
--- /dev/null
+++ b/include/asm-sparc/scratchpad.h
@@ -0,0 +1,14 @@
+#ifndef _SPARC64_SCRATCHPAD_H
+#define _SPARC64_SCRATCHPAD_H
+
+/* Sun4v scratchpad registers, accessed via ASI_SCRATCHPAD.  */
+
+#define SCRATCHPAD_MMU_MISS	0x00 /* Shared with OBP - set by OBP	    */
+#define SCRATCHPAD_CPUID	0x08 /* Shared with OBP - set by hypervisor */
+#define SCRATCHPAD_UTSBREG1	0x10
+#define SCRATCHPAD_UTSBREG2	0x18
+	/* 0x20 and 0x28, hypervisor only... */
+#define SCRATCHPAD_UNUSED1	0x30
+#define SCRATCHPAD_UNUSED2	0x38 /* Reserved for OBP		    */
+
+#endif /* !(_SPARC64_SCRATCHPAD_H) */
diff --git a/include/asm-sparc/seccomp.h b/include/asm-sparc/seccomp.h
new file mode 100644
index 0000000..7fcd996
--- /dev/null
+++ b/include/asm-sparc/seccomp.h
@@ -0,0 +1,21 @@
+#ifndef _ASM_SECCOMP_H
+
+#include <linux/thread_info.h> /* already defines TIF_32BIT */
+
+#ifndef TIF_32BIT
+#error "unexpected TIF_32BIT on sparc64"
+#endif
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_read __NR_read
+#define __NR_seccomp_write __NR_write
+#define __NR_seccomp_exit __NR_exit
+#define __NR_seccomp_sigreturn __NR_rt_sigreturn
+
+#define __NR_seccomp_read_32 __NR_read
+#define __NR_seccomp_write_32 __NR_write
+#define __NR_seccomp_exit_32 __NR_exit
+#define __NR_seccomp_sigreturn_32 __NR_sigreturn
+
+#endif /* _ASM_SECCOMP_H */
diff --git a/include/asm-sparc/sections.h b/include/asm-sparc/sections.h
index 6832841..cbd0191 100644
--- a/include/asm-sparc/sections.h
+++ b/include/asm-sparc/sections.h
@@ -1,6 +1,8 @@
-#ifndef _SPARC_SECTIONS_H
-#define _SPARC_SECTIONS_H
-
-#include <asm-generic/sections.h>
-
+#ifndef ___ASM_SPARC_SECTIONS_H
+#define ___ASM_SPARC_SECTIONS_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/sections_64.h>
+#else
+#include <asm-sparc/sections_32.h>
+#endif
 #endif
diff --git a/include/asm-sparc/sections_32.h b/include/asm-sparc/sections_32.h
new file mode 100644
index 0000000..6832841
--- /dev/null
+++ b/include/asm-sparc/sections_32.h
@@ -0,0 +1,6 @@
+#ifndef _SPARC_SECTIONS_H
+#define _SPARC_SECTIONS_H
+
+#include <asm-generic/sections.h>
+
+#endif
diff --git a/include/asm-sparc/sections_64.h b/include/asm-sparc/sections_64.h
new file mode 100644
index 0000000..3f4b9fd
--- /dev/null
+++ b/include/asm-sparc/sections_64.h
@@ -0,0 +1,9 @@
+#ifndef _SPARC64_SECTIONS_H
+#define _SPARC64_SECTIONS_H
+
+/* nothing to see, move along */
+#include <asm-generic/sections.h>
+
+extern char _start[];
+
+#endif
diff --git a/include/asm-sparc/sembuf.h b/include/asm-sparc/sembuf.h
index a79c4bb..faee1be 100644
--- a/include/asm-sparc/sembuf.h
+++ b/include/asm-sparc/sembuf.h
@@ -1,7 +1,7 @@
 #ifndef _SPARC_SEMBUF_H
 #define _SPARC_SEMBUF_H
 
-/* 
+/*
  * The semid64_ds structure for sparc architecture.
  * Note extra padding because this structure is passed back and forth
  * between kernel and user space.
@@ -10,16 +10,22 @@
  * - 64-bit time_t to solve y2038 problem
  * - 2 miscellaneous 32-bit values
  */
+#if defined(__sparc__) && defined(__arch64__)
+# define PADDING(x)
+#else
+# define PADDING(x) unsigned int x;
+#endif
 
 struct semid64_ds {
 	struct ipc64_perm sem_perm;		/* permissions .. see ipc.h */
-	unsigned int	__pad1;
+	PADDING(__pad1)
 	__kernel_time_t	sem_otime;		/* last semop time */
-	unsigned int	__pad2;
+	PADDING(__pad2)
 	__kernel_time_t	sem_ctime;		/* last change time */
 	unsigned long	sem_nsems;		/* no. of semaphores in array */
 	unsigned long	__unused1;
 	unsigned long	__unused2;
 };
+#undef PADDING
 
 #endif /* _SPARC64_SEMBUF_H */
diff --git a/include/asm-sparc/setup.h b/include/asm-sparc/setup.h
index b3af958..2643c62 100644
--- a/include/asm-sparc/setup.h
+++ b/include/asm-sparc/setup.h
@@ -5,6 +5,10 @@
 #ifndef _SPARC_SETUP_H
 #define _SPARC_SETUP_H
 
-#define COMMAND_LINE_SIZE	256
+#if defined(__sparc__) && defined(__arch64__)
+# define COMMAND_LINE_SIZE 2048
+#else
+# define COMMAND_LINE_SIZE 256
+#endif
 
 #endif /* _SPARC_SETUP_H */
diff --git a/include/asm-sparc/sfafsr.h b/include/asm-sparc/sfafsr.h
new file mode 100644
index 0000000..e96137b
--- /dev/null
+++ b/include/asm-sparc/sfafsr.h
@@ -0,0 +1,82 @@
+#ifndef _SPARC64_SFAFSR_H
+#define _SPARC64_SFAFSR_H
+
+#include <linux/const.h>
+
+/* Spitfire Asynchronous Fault Status register, ASI=0x4C VA<63:0>=0x0 */
+
+#define SFAFSR_ME		(_AC(1,UL) << SFAFSR_ME_SHIFT)
+#define SFAFSR_ME_SHIFT		32
+#define SFAFSR_PRIV		(_AC(1,UL) << SFAFSR_PRIV_SHIFT)
+#define SFAFSR_PRIV_SHIFT	31
+#define SFAFSR_ISAP		(_AC(1,UL) << SFAFSR_ISAP_SHIFT)
+#define SFAFSR_ISAP_SHIFT	30
+#define SFAFSR_ETP		(_AC(1,UL) << SFAFSR_ETP_SHIFT)
+#define SFAFSR_ETP_SHIFT	29
+#define SFAFSR_IVUE		(_AC(1,UL) << SFAFSR_IVUE_SHIFT)
+#define SFAFSR_IVUE_SHIFT	28
+#define SFAFSR_TO		(_AC(1,UL) << SFAFSR_TO_SHIFT)
+#define SFAFSR_TO_SHIFT		27
+#define SFAFSR_BERR		(_AC(1,UL) << SFAFSR_BERR_SHIFT)
+#define SFAFSR_BERR_SHIFT	26
+#define SFAFSR_LDP		(_AC(1,UL) << SFAFSR_LDP_SHIFT)
+#define SFAFSR_LDP_SHIFT	25
+#define SFAFSR_CP		(_AC(1,UL) << SFAFSR_CP_SHIFT)
+#define SFAFSR_CP_SHIFT		24
+#define SFAFSR_WP		(_AC(1,UL) << SFAFSR_WP_SHIFT)
+#define SFAFSR_WP_SHIFT		23
+#define SFAFSR_EDP		(_AC(1,UL) << SFAFSR_EDP_SHIFT)
+#define SFAFSR_EDP_SHIFT	22
+#define SFAFSR_UE		(_AC(1,UL) << SFAFSR_UE_SHIFT)
+#define SFAFSR_UE_SHIFT		21
+#define SFAFSR_CE		(_AC(1,UL) << SFAFSR_CE_SHIFT)
+#define SFAFSR_CE_SHIFT		20
+#define SFAFSR_ETS		(_AC(0xf,UL) << SFAFSR_ETS_SHIFT)
+#define SFAFSR_ETS_SHIFT	16
+#define SFAFSR_PSYND		(_AC(0xffff,UL) << SFAFSR_PSYND_SHIFT)
+#define SFAFSR_PSYND_SHIFT	0
+
+/* UDB Error Register, ASI=0x7f VA<63:0>=0x0(High),0x18(Low) for read
+ *                     ASI=0x77 VA<63:0>=0x0(High),0x18(Low) for write
+ */
+
+#define UDBE_UE			(_AC(1,UL) << 9)
+#define UDBE_CE			(_AC(1,UL) << 8)
+#define UDBE_E_SYNDR		(_AC(0xff,UL) << 0)
+
+/* The trap handlers for asynchronous errors encode the AFSR and
+ * other pieces of information into a 64-bit argument for C code
+ * encoded as follows:
+ *
+ * -----------------------------------------------
+ * |  UDB_H  |  UDB_L  | TL>1  |  TT  |   AFSR   |
+ * -----------------------------------------------
+ *  63     54 53     44    42   41  33 32       0
+ *
+ * The AFAR is passed in unchanged.
+ */
+#define SFSTAT_UDBH_MASK	(_AC(0x3ff,UL) << SFSTAT_UDBH_SHIFT)
+#define SFSTAT_UDBH_SHIFT	54
+#define SFSTAT_UDBL_MASK	(_AC(0x3ff,UL) << SFSTAT_UDBH_SHIFT)
+#define SFSTAT_UDBL_SHIFT	44
+#define SFSTAT_TL_GT_ONE	(_AC(1,UL) << SFSTAT_TL_GT_ONE_SHIFT)
+#define SFSTAT_TL_GT_ONE_SHIFT	42
+#define SFSTAT_TRAP_TYPE	(_AC(0x1FF,UL) << SFSTAT_TRAP_TYPE_SHIFT)
+#define SFSTAT_TRAP_TYPE_SHIFT	33
+#define SFSTAT_AFSR_MASK	(_AC(0x1ffffffff,UL) << SFSTAT_AFSR_SHIFT)
+#define SFSTAT_AFSR_SHIFT	0
+
+/* ESTATE Error Enable Register, ASI=0x4b VA<63:0>=0x0 */
+#define ESTATE_ERR_CE		0x1 /* Correctable errors                    */
+#define ESTATE_ERR_NCE		0x2 /* TO, BERR, LDP, ETP, EDP, WP, UE, IVUE */
+#define ESTATE_ERR_ISAP		0x4 /* System address parity error           */
+#define ESTATE_ERR_ALL		(ESTATE_ERR_CE | \
+				 ESTATE_ERR_NCE | \
+				 ESTATE_ERR_ISAP)
+
+/* The various trap types that report using the above state. */
+#define TRAP_TYPE_IAE		0x09 /* Instruction Access Error             */
+#define TRAP_TYPE_DAE		0x32 /* Data Access Error                    */
+#define TRAP_TYPE_CEE		0x63 /* Correctable ECC Error                */
+
+#endif /* _SPARC64_SFAFSR_H */
diff --git a/include/asm-sparc/sfp-machine.h b/include/asm-sparc/sfp-machine.h
index 266a42b..c676fcc 100644
--- a/include/asm-sparc/sfp-machine.h
+++ b/include/asm-sparc/sfp-machine.h
@@ -1,212 +1,8 @@
-/* Machine-dependent software floating-point definitions.
-   Sparc userland (_Q_*) version.
-   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Richard Henderson (rth@cygnus.com),
-		  Jakub Jelinek (jj@ultra.linux.cz),
-		  David S. Miller (davem@redhat.com) and
-		  Peter Maydell (pmaydell@chiark.greenend.org.uk).
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Library General Public License for more details.
-
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If
-   not, write to the Free Software Foundation, Inc.,
-   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
-
-#ifndef _SFP_MACHINE_H
-#define _SFP_MACHINE_H
-
-   
-#define _FP_W_TYPE_SIZE		32
-#define _FP_W_TYPE		unsigned long
-#define _FP_WS_TYPE		signed long
-#define _FP_I_TYPE		long
-
-#define _FP_MUL_MEAT_S(R,X,Y)					\
-  _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
-#define _FP_MUL_MEAT_D(R,X,Y)					\
-  _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
-#define _FP_MUL_MEAT_Q(R,X,Y)					\
-  _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
-
-#define _FP_DIV_MEAT_S(R,X,Y)	_FP_DIV_MEAT_1_udiv(S,R,X,Y)
-#define _FP_DIV_MEAT_D(R,X,Y)	_FP_DIV_MEAT_2_udiv(D,R,X,Y)
-#define _FP_DIV_MEAT_Q(R,X,Y)	_FP_DIV_MEAT_4_udiv(Q,R,X,Y)
-
-#define _FP_NANFRAC_S		((_FP_QNANBIT_S << 1) - 1)
-#define _FP_NANFRAC_D		((_FP_QNANBIT_D << 1) - 1), -1
-#define _FP_NANFRAC_Q		((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
-#define _FP_NANSIGN_S		0
-#define _FP_NANSIGN_D		0
-#define _FP_NANSIGN_Q		0
-
-#define _FP_KEEPNANFRACP 1
-
-/* If one NaN is signaling and the other is not,
- * we choose that one, otherwise we choose X.
- */
-/* For _Qp_* and _Q_*, this should prefer X, for
- * CPU instruction emulation this should prefer Y.
- * (see SPAMv9 B.2.2 section).
- */
-#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)			\
-  do {								\
-    if ((_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs)		\
-	&& !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))	\
-      {								\
-	R##_s = X##_s;						\
-	_FP_FRAC_COPY_##wc(R,X);				\
-      }								\
-    else							\
-      {								\
-	R##_s = Y##_s;						\
-	_FP_FRAC_COPY_##wc(R,Y);				\
-      }								\
-    R##_c = FP_CLS_NAN;						\
-  } while (0)
-
-/* Some assembly to speed things up. */
-#define __FP_FRAC_ADD_3(r2,r1,r0,x2,x1,x0,y2,y1,y0)			\
-  __asm__ ("addcc %r7,%8,%2\n\t"					\
-	   "addxcc %r5,%6,%1\n\t"					\
-	   "addx %r3,%4,%0\n"						\
-	   : "=r" ((USItype)(r2)),					\
-	     "=&r" ((USItype)(r1)),					\
-	     "=&r" ((USItype)(r0))					\
-	   : "%rJ" ((USItype)(x2)),					\
-	     "rI" ((USItype)(y2)),					\
-	     "%rJ" ((USItype)(x1)),					\
-	     "rI" ((USItype)(y1)),					\
-	     "%rJ" ((USItype)(x0)),					\
-	     "rI" ((USItype)(y0))					\
-	   : "cc")
-
-#define __FP_FRAC_SUB_3(r2,r1,r0,x2,x1,x0,y2,y1,y0)			\
-  __asm__ ("subcc %r7,%8,%2\n\t"					\
-	    "subxcc %r5,%6,%1\n\t"					\
-	    "subx %r3,%4,%0\n"						\
-	   : "=r" ((USItype)(r2)),					\
-	     "=&r" ((USItype)(r1)),					\
-	     "=&r" ((USItype)(r0))					\
-	   : "%rJ" ((USItype)(x2)),					\
-	     "rI" ((USItype)(y2)),					\
-	     "%rJ" ((USItype)(x1)),					\
-	     "rI" ((USItype)(y1)),					\
-	     "%rJ" ((USItype)(x0)),					\
-	     "rI" ((USItype)(y0))					\
-	   : "cc")
-
-#define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)		\
-  do {									\
-    /* We need to fool gcc,  as we need to pass more than 10		\
-       input/outputs.  */						\
-    register USItype _t1 __asm__ ("g1"), _t2 __asm__ ("g2");		\
-    __asm__ __volatile__ (						\
-	    "addcc %r8,%9,%1\n\t"					\
-	    "addxcc %r6,%7,%0\n\t"					\
-	    "addxcc %r4,%5,%%g2\n\t"					\
-	    "addx %r2,%3,%%g1\n\t"					\
-	   : "=&r" ((USItype)(r1)),					\
-	     "=&r" ((USItype)(r0))					\
-	   : "%rJ" ((USItype)(x3)),					\
-	     "rI" ((USItype)(y3)),					\
-	     "%rJ" ((USItype)(x2)),					\
-	     "rI" ((USItype)(y2)),					\
-	     "%rJ" ((USItype)(x1)),					\
-	     "rI" ((USItype)(y1)),					\
-	     "%rJ" ((USItype)(x0)),					\
-	     "rI" ((USItype)(y0))					\
-	   : "cc", "g1", "g2");						\
-    __asm__ __volatile__ ("" : "=r" (_t1), "=r" (_t2));			\
-    r3 = _t1; r2 = _t2;							\
-  } while (0)
-
-#define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)		\
-  do {									\
-    /* We need to fool gcc,  as we need to pass more than 10		\
-       input/outputs.  */						\
-    register USItype _t1 __asm__ ("g1"), _t2 __asm__ ("g2");		\
-    __asm__ __volatile__ (						\
-	    "subcc %r8,%9,%1\n\t"					\
-	    "subxcc %r6,%7,%0\n\t"					\
-	    "subxcc %r4,%5,%%g2\n\t"					\
-	    "subx %r2,%3,%%g1\n\t"					\
-	   : "=&r" ((USItype)(r1)),					\
-	     "=&r" ((USItype)(r0))					\
-	   : "%rJ" ((USItype)(x3)),					\
-	     "rI" ((USItype)(y3)),					\
-	     "%rJ" ((USItype)(x2)),					\
-	     "rI" ((USItype)(y2)),					\
-	     "%rJ" ((USItype)(x1)),					\
-	     "rI" ((USItype)(y1)),					\
-	     "%rJ" ((USItype)(x0)),					\
-	     "rI" ((USItype)(y0))					\
-	   : "cc", "g1", "g2");						\
-    __asm__ __volatile__ ("" : "=r" (_t1), "=r" (_t2));			\
-    r3 = _t1; r2 = _t2;							\
-  } while (0)
-
-#define __FP_FRAC_DEC_3(x2,x1,x0,y2,y1,y0) __FP_FRAC_SUB_3(x2,x1,x0,x2,x1,x0,y2,y1,y0)
-
-#define __FP_FRAC_DEC_4(x3,x2,x1,x0,y3,y2,y1,y0) __FP_FRAC_SUB_4(x3,x2,x1,x0,x3,x2,x1,x0,y3,y2,y1,y0)
-
-#define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i)					\
-  __asm__ ("addcc %3,%4,%3\n\t"						\
-	   "addxcc %2,%%g0,%2\n\t"					\
-	   "addxcc %1,%%g0,%1\n\t"					\
-	   "addx %0,%%g0,%0\n\t"					\
-	   : "=&r" ((USItype)(x3)),					\
-	     "=&r" ((USItype)(x2)),					\
-	     "=&r" ((USItype)(x1)),					\
-	     "=&r" ((USItype)(x0))					\
-	   : "rI" ((USItype)(i)),					\
-	     "0" ((USItype)(x3)),					\
-	     "1" ((USItype)(x2)),					\
-	     "2" ((USItype)(x1)),					\
-	     "3" ((USItype)(x0))					\
-	   : "cc")
-
-#ifndef CONFIG_SMP
-extern struct task_struct *last_task_used_math;
-#endif
-
-/* Obtain the current rounding mode. */
-#ifndef FP_ROUNDMODE
-#ifdef CONFIG_SMP
-#define FP_ROUNDMODE	((current->thread.fsr >> 30) & 0x3)
+#ifndef ___ASM_SPARC_SFP_MACHINE_H
+#define ___ASM_SPARC_SFP_MACHINE_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/sfp-machine_64.h>
 #else
-#define FP_ROUNDMODE	((last_task_used_math->thread.fsr >> 30) & 0x3)
+#include <asm-sparc/sfp-machine_32.h>
 #endif
 #endif
-
-/* Exception flags. */
-#define FP_EX_INVALID		(1 << 4)
-#define FP_EX_OVERFLOW		(1 << 3)
-#define FP_EX_UNDERFLOW		(1 << 2)
-#define FP_EX_DIVZERO		(1 << 1)
-#define FP_EX_INEXACT		(1 << 0)
-
-#define FP_HANDLE_EXCEPTIONS return _fex
-
-#ifdef CONFIG_SMP
-#define FP_INHIBIT_RESULTS ((current->thread.fsr >> 23) & _fex)
-#else
-#define FP_INHIBIT_RESULTS ((last_task_used_math->thread.fsr >> 23) & _fex)
-#endif
-
-#ifdef CONFIG_SMP
-#define FP_TRAPPING_EXCEPTIONS ((current->thread.fsr >> 23) & 0x1f)
-#else
-#define FP_TRAPPING_EXCEPTIONS ((last_task_used_math->thread.fsr >> 23) & 0x1f)
-#endif
-
-#endif
diff --git a/include/asm-sparc/sfp-machine_32.h b/include/asm-sparc/sfp-machine_32.h
new file mode 100644
index 0000000..01d9c3b
--- /dev/null
+++ b/include/asm-sparc/sfp-machine_32.h
@@ -0,0 +1,212 @@
+/* Machine-dependent software floating-point definitions.
+   Sparc userland (_Q_*) version.
+   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson (rth@cygnus.com),
+		  Jakub Jelinek (jj@ultra.linux.cz),
+		  David S. Miller (davem@redhat.com) and
+		  Peter Maydell (pmaydell@chiark.greenend.org.uk).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifndef _SFP_MACHINE_H
+#define _SFP_MACHINE_H
+
+
+#define _FP_W_TYPE_SIZE		32
+#define _FP_W_TYPE		unsigned long
+#define _FP_WS_TYPE		signed long
+#define _FP_I_TYPE		long
+
+#define _FP_MUL_MEAT_S(R,X,Y)					\
+  _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_D(R,X,Y)					\
+  _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y)					\
+  _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y)	_FP_DIV_MEAT_1_udiv(S,R,X,Y)
+#define _FP_DIV_MEAT_D(R,X,Y)	_FP_DIV_MEAT_2_udiv(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y)	_FP_DIV_MEAT_4_udiv(Q,R,X,Y)
+
+#define _FP_NANFRAC_S		((_FP_QNANBIT_S << 1) - 1)
+#define _FP_NANFRAC_D		((_FP_QNANBIT_D << 1) - 1), -1
+#define _FP_NANFRAC_Q		((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
+#define _FP_NANSIGN_S		0
+#define _FP_NANSIGN_D		0
+#define _FP_NANSIGN_Q		0
+
+#define _FP_KEEPNANFRACP 1
+
+/* If one NaN is signaling and the other is not,
+ * we choose that one, otherwise we choose X.
+ */
+/* For _Qp_* and _Q_*, this should prefer X, for
+ * CPU instruction emulation this should prefer Y.
+ * (see SPAMv9 B.2.2 section).
+ */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)			\
+  do {								\
+    if ((_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs)		\
+	&& !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))	\
+      {								\
+	R##_s = X##_s;						\
+	_FP_FRAC_COPY_##wc(R,X);				\
+      }								\
+    else							\
+      {								\
+	R##_s = Y##_s;						\
+	_FP_FRAC_COPY_##wc(R,Y);				\
+      }								\
+    R##_c = FP_CLS_NAN;						\
+  } while (0)
+
+/* Some assembly to speed things up. */
+#define __FP_FRAC_ADD_3(r2,r1,r0,x2,x1,x0,y2,y1,y0)			\
+  __asm__ ("addcc %r7,%8,%2\n\t"					\
+	   "addxcc %r5,%6,%1\n\t"					\
+	   "addx %r3,%4,%0\n"						\
+	   : "=r" ((USItype)(r2)),					\
+	     "=&r" ((USItype)(r1)),					\
+	     "=&r" ((USItype)(r0))					\
+	   : "%rJ" ((USItype)(x2)),					\
+	     "rI" ((USItype)(y2)),					\
+	     "%rJ" ((USItype)(x1)),					\
+	     "rI" ((USItype)(y1)),					\
+	     "%rJ" ((USItype)(x0)),					\
+	     "rI" ((USItype)(y0))					\
+	   : "cc")
+
+#define __FP_FRAC_SUB_3(r2,r1,r0,x2,x1,x0,y2,y1,y0)			\
+  __asm__ ("subcc %r7,%8,%2\n\t"					\
+	    "subxcc %r5,%6,%1\n\t"					\
+	    "subx %r3,%4,%0\n"						\
+	   : "=r" ((USItype)(r2)),					\
+	     "=&r" ((USItype)(r1)),					\
+	     "=&r" ((USItype)(r0))					\
+	   : "%rJ" ((USItype)(x2)),					\
+	     "rI" ((USItype)(y2)),					\
+	     "%rJ" ((USItype)(x1)),					\
+	     "rI" ((USItype)(y1)),					\
+	     "%rJ" ((USItype)(x0)),					\
+	     "rI" ((USItype)(y0))					\
+	   : "cc")
+
+#define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)		\
+  do {									\
+    /* We need to fool gcc,  as we need to pass more than 10		\
+       input/outputs.  */						\
+    register USItype _t1 __asm__ ("g1"), _t2 __asm__ ("g2");		\
+    __asm__ __volatile__ (						\
+	    "addcc %r8,%9,%1\n\t"					\
+	    "addxcc %r6,%7,%0\n\t"					\
+	    "addxcc %r4,%5,%%g2\n\t"					\
+	    "addx %r2,%3,%%g1\n\t"					\
+	   : "=&r" ((USItype)(r1)),					\
+	     "=&r" ((USItype)(r0))					\
+	   : "%rJ" ((USItype)(x3)),					\
+	     "rI" ((USItype)(y3)),					\
+	     "%rJ" ((USItype)(x2)),					\
+	     "rI" ((USItype)(y2)),					\
+	     "%rJ" ((USItype)(x1)),					\
+	     "rI" ((USItype)(y1)),					\
+	     "%rJ" ((USItype)(x0)),					\
+	     "rI" ((USItype)(y0))					\
+	   : "cc", "g1", "g2");						\
+    __asm__ __volatile__ ("" : "=r" (_t1), "=r" (_t2));			\
+    r3 = _t1; r2 = _t2;							\
+  } while (0)
+
+#define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)		\
+  do {									\
+    /* We need to fool gcc,  as we need to pass more than 10		\
+       input/outputs.  */						\
+    register USItype _t1 __asm__ ("g1"), _t2 __asm__ ("g2");		\
+    __asm__ __volatile__ (						\
+	    "subcc %r8,%9,%1\n\t"					\
+	    "subxcc %r6,%7,%0\n\t"					\
+	    "subxcc %r4,%5,%%g2\n\t"					\
+	    "subx %r2,%3,%%g1\n\t"					\
+	   : "=&r" ((USItype)(r1)),					\
+	     "=&r" ((USItype)(r0))					\
+	   : "%rJ" ((USItype)(x3)),					\
+	     "rI" ((USItype)(y3)),					\
+	     "%rJ" ((USItype)(x2)),					\
+	     "rI" ((USItype)(y2)),					\
+	     "%rJ" ((USItype)(x1)),					\
+	     "rI" ((USItype)(y1)),					\
+	     "%rJ" ((USItype)(x0)),					\
+	     "rI" ((USItype)(y0))					\
+	   : "cc", "g1", "g2");						\
+    __asm__ __volatile__ ("" : "=r" (_t1), "=r" (_t2));			\
+    r3 = _t1; r2 = _t2;							\
+  } while (0)
+
+#define __FP_FRAC_DEC_3(x2,x1,x0,y2,y1,y0) __FP_FRAC_SUB_3(x2,x1,x0,x2,x1,x0,y2,y1,y0)
+
+#define __FP_FRAC_DEC_4(x3,x2,x1,x0,y3,y2,y1,y0) __FP_FRAC_SUB_4(x3,x2,x1,x0,x3,x2,x1,x0,y3,y2,y1,y0)
+
+#define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i)					\
+  __asm__ ("addcc %3,%4,%3\n\t"						\
+	   "addxcc %2,%%g0,%2\n\t"					\
+	   "addxcc %1,%%g0,%1\n\t"					\
+	   "addx %0,%%g0,%0\n\t"					\
+	   : "=&r" ((USItype)(x3)),					\
+	     "=&r" ((USItype)(x2)),					\
+	     "=&r" ((USItype)(x1)),					\
+	     "=&r" ((USItype)(x0))					\
+	   : "rI" ((USItype)(i)),					\
+	     "0" ((USItype)(x3)),					\
+	     "1" ((USItype)(x2)),					\
+	     "2" ((USItype)(x1)),					\
+	     "3" ((USItype)(x0))					\
+	   : "cc")
+
+#ifndef CONFIG_SMP
+extern struct task_struct *last_task_used_math;
+#endif
+
+/* Obtain the current rounding mode. */
+#ifndef FP_ROUNDMODE
+#ifdef CONFIG_SMP
+#define FP_ROUNDMODE	((current->thread.fsr >> 30) & 0x3)
+#else
+#define FP_ROUNDMODE	((last_task_used_math->thread.fsr >> 30) & 0x3)
+#endif
+#endif
+
+/* Exception flags. */
+#define FP_EX_INVALID		(1 << 4)
+#define FP_EX_OVERFLOW		(1 << 3)
+#define FP_EX_UNDERFLOW		(1 << 2)
+#define FP_EX_DIVZERO		(1 << 1)
+#define FP_EX_INEXACT		(1 << 0)
+
+#define FP_HANDLE_EXCEPTIONS return _fex
+
+#ifdef CONFIG_SMP
+#define FP_INHIBIT_RESULTS ((current->thread.fsr >> 23) & _fex)
+#else
+#define FP_INHIBIT_RESULTS ((last_task_used_math->thread.fsr >> 23) & _fex)
+#endif
+
+#ifdef CONFIG_SMP
+#define FP_TRAPPING_EXCEPTIONS ((current->thread.fsr >> 23) & 0x1f)
+#else
+#define FP_TRAPPING_EXCEPTIONS ((last_task_used_math->thread.fsr >> 23) & 0x1f)
+#endif
+
+#endif
diff --git a/include/asm-sparc/sfp-machine_64.h b/include/asm-sparc/sfp-machine_64.h
new file mode 100644
index 0000000..ca913ef
--- /dev/null
+++ b/include/asm-sparc/sfp-machine_64.h
@@ -0,0 +1,93 @@
+/* Machine-dependent software floating-point definitions.
+   Sparc64 kernel version.
+   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson (rth@cygnus.com),
+		  Jakub Jelinek (jj@ultra.linux.cz) and
+		  David S. Miller (davem@redhat.com).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifndef _SFP_MACHINE_H
+#define _SFP_MACHINE_H
+
+#define _FP_W_TYPE_SIZE		64
+#define _FP_W_TYPE		unsigned long
+#define _FP_WS_TYPE		signed long
+#define _FP_I_TYPE		long
+
+#define _FP_MUL_MEAT_S(R,X,Y)					\
+  _FP_MUL_MEAT_1_imm(_FP_WFRACBITS_S,R,X,Y)
+#define _FP_MUL_MEAT_D(R,X,Y)					\
+  _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y)					\
+  _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y)	_FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm)
+#define _FP_DIV_MEAT_D(R,X,Y)	_FP_DIV_MEAT_1_udiv_norm(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y)	_FP_DIV_MEAT_2_udiv(Q,R,X,Y)
+
+#define _FP_NANFRAC_S		((_FP_QNANBIT_S << 1) - 1)
+#define _FP_NANFRAC_D		((_FP_QNANBIT_D << 1) - 1)
+#define _FP_NANFRAC_Q		((_FP_QNANBIT_Q << 1) - 1), -1
+#define _FP_NANSIGN_S		0
+#define _FP_NANSIGN_D		0
+#define _FP_NANSIGN_Q		0
+
+#define _FP_KEEPNANFRACP 1
+
+/* If one NaN is signaling and the other is not,
+ * we choose that one, otherwise we choose X.
+ */
+/* For _Qp_* and _Q_*, this should prefer X, for
+ * CPU instruction emulation this should prefer Y.
+ * (see SPAMv9 B.2.2 section).
+ */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)			\
+  do {								\
+    if ((_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs)		\
+	&& !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))	\
+      {								\
+	R##_s = X##_s;						\
+	_FP_FRAC_COPY_##wc(R,X);				\
+      }								\
+    else							\
+      {								\
+	R##_s = Y##_s;						\
+	_FP_FRAC_COPY_##wc(R,Y);				\
+      }								\
+    R##_c = FP_CLS_NAN;						\
+  } while (0)
+
+/* Obtain the current rounding mode. */
+#ifndef FP_ROUNDMODE
+#define FP_ROUNDMODE	((current_thread_info()->xfsr[0] >> 30) & 0x3)
+#endif
+
+/* Exception flags. */
+#define FP_EX_INVALID		(1 << 4)
+#define FP_EX_OVERFLOW		(1 << 3)
+#define FP_EX_UNDERFLOW		(1 << 2)
+#define FP_EX_DIVZERO		(1 << 1)
+#define FP_EX_INEXACT		(1 << 0)
+
+#define FP_HANDLE_EXCEPTIONS return _fex
+
+#define FP_INHIBIT_RESULTS ((current_thread_info()->xfsr[0] >> 23) & _fex)
+
+#define FP_TRAPPING_EXCEPTIONS ((current_thread_info()->xfsr[0] >> 23) & 0x1f)
+
+#endif
diff --git a/include/asm-sparc/shmbuf.h b/include/asm-sparc/shmbuf.h
index 1ff9da8..83a1605 100644
--- a/include/asm-sparc/shmbuf.h
+++ b/include/asm-sparc/shmbuf.h
@@ -11,13 +11,19 @@
  * - 2 miscellaneous 32-bit values
  */
 
+#if defined(__sparc__) && defined(__arch64__)
+# define PADDING(x)
+#else
+# define PADDING(x) unsigned int x;
+#endif
+
 struct shmid64_ds {
 	struct ipc64_perm	shm_perm;	/* operation perms */
-	unsigned int		__pad1;
+	PADDING(__pad1)
 	__kernel_time_t		shm_atime;	/* last attach time */
-	unsigned int		__pad2;
+	PADDING(__pad2)
 	__kernel_time_t		shm_dtime;	/* last detach time */
-	unsigned int		__pad3;
+	PADDING(__pad3)
 	__kernel_time_t		shm_ctime;	/* last change time */
 	size_t			shm_segsz;	/* size of segment (bytes) */
 	__kernel_pid_t		shm_cpid;	/* pid of creator */
@@ -39,4 +45,6 @@
 	unsigned long	__unused4;
 };
 
+#undef PADDING
+
 #endif /* _SPARC_SHMBUF_H */
diff --git a/include/asm-sparc/shmparam.h b/include/asm-sparc/shmparam.h
index 59a1243..16fda7e 100644
--- a/include/asm-sparc/shmparam.h
+++ b/include/asm-sparc/shmparam.h
@@ -1,11 +1,8 @@
-#ifndef _ASMSPARC_SHMPARAM_H
-#define _ASMSPARC_SHMPARAM_H
-
-#define __ARCH_FORCE_SHMLBA 	1
-
-extern int vac_cache_size;
-#define SHMLBA (vac_cache_size ? vac_cache_size : \
-		(sparc_cpu_model == sun4c ? (64 * 1024) : \
-		 (sparc_cpu_model == sun4 ? (128 * 1024) : PAGE_SIZE)))
-
-#endif /* _ASMSPARC_SHMPARAM_H */
+#ifndef ___ASM_SPARC_SHMPARAM_H
+#define ___ASM_SPARC_SHMPARAM_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/shmparam_64.h>
+#else
+#include <asm-sparc/shmparam_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/shmparam_32.h b/include/asm-sparc/shmparam_32.h
new file mode 100644
index 0000000..59a1243
--- /dev/null
+++ b/include/asm-sparc/shmparam_32.h
@@ -0,0 +1,11 @@
+#ifndef _ASMSPARC_SHMPARAM_H
+#define _ASMSPARC_SHMPARAM_H
+
+#define __ARCH_FORCE_SHMLBA 	1
+
+extern int vac_cache_size;
+#define SHMLBA (vac_cache_size ? vac_cache_size : \
+		(sparc_cpu_model == sun4c ? (64 * 1024) : \
+		 (sparc_cpu_model == sun4 ? (128 * 1024) : PAGE_SIZE)))
+
+#endif /* _ASMSPARC_SHMPARAM_H */
diff --git a/include/asm-sparc/shmparam_64.h b/include/asm-sparc/shmparam_64.h
new file mode 100644
index 0000000..1ed0d67
--- /dev/null
+++ b/include/asm-sparc/shmparam_64.h
@@ -0,0 +1,10 @@
+#ifndef _ASMSPARC64_SHMPARAM_H
+#define _ASMSPARC64_SHMPARAM_H
+
+#include <asm/spitfire.h>
+
+#define __ARCH_FORCE_SHMLBA	1
+/* attach addr a multiple of this */
+#define	SHMLBA	((PAGE_SIZE > L1DCACHE_SIZE) ? PAGE_SIZE : L1DCACHE_SIZE)
+
+#endif /* _ASMSPARC64_SHMPARAM_H */
diff --git a/include/asm-sparc/sigcontext.h b/include/asm-sparc/sigcontext.h
index c5fb60d..82fc7d5 100644
--- a/include/asm-sparc/sigcontext.h
+++ b/include/asm-sparc/sigcontext.h
@@ -1,62 +1,8 @@
-#ifndef __SPARC_SIGCONTEXT_H
-#define __SPARC_SIGCONTEXT_H
-
-#ifdef __KERNEL__
-#include <asm/ptrace.h>
-
-#ifndef __ASSEMBLY__
-
-#define __SUNOS_MAXWIN   31
-
-/* This is what SunOS does, so shall I. */
-struct sigcontext {
-	int sigc_onstack;      /* state to restore */
-	int sigc_mask;         /* sigmask to restore */
-	int sigc_sp;           /* stack pointer */
-	int sigc_pc;           /* program counter */
-	int sigc_npc;          /* next program counter */
-	int sigc_psr;          /* for condition codes etc */
-	int sigc_g1;           /* User uses these two registers */
-	int sigc_o0;           /* within the trampoline code. */
-
-	/* Now comes information regarding the users window set
-	 * at the time of the signal.
-	 */
-	int sigc_oswins;       /* outstanding windows */
-
-	/* stack ptrs for each regwin buf */
-	char *sigc_spbuf[__SUNOS_MAXWIN];
-
-	/* Windows to restore after signal */
-	struct {
-		unsigned long	locals[8];
-		unsigned long	ins[8];
-	} sigc_wbuf[__SUNOS_MAXWIN];
-};
-
-typedef struct {
-	struct {
-		unsigned long psr;
-		unsigned long pc;
-		unsigned long npc;
-		unsigned long y;
-		unsigned long u_regs[16]; /* globals and ins */
-	}		si_regs;
-	int		si_mask;
-} __siginfo_t;
-
-typedef struct {
-	unsigned   long si_float_regs [32];
-	unsigned   long si_fsr;
-	unsigned   long si_fpqdepth;
-	struct {
-		unsigned long *insn_addr;
-		unsigned long insn;
-	} si_fpqueue [16];
-} __siginfo_fpu_t;
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* (__KERNEL__) */
-
-#endif /* !(__SPARC_SIGCONTEXT_H) */
+#ifndef ___ASM_SPARC_SIGCONTEXT_H
+#define ___ASM_SPARC_SIGCONTEXT_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/sigcontext_64.h>
+#else
+#include <asm-sparc/sigcontext_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/sigcontext_32.h b/include/asm-sparc/sigcontext_32.h
new file mode 100644
index 0000000..c5fb60d
--- /dev/null
+++ b/include/asm-sparc/sigcontext_32.h
@@ -0,0 +1,62 @@
+#ifndef __SPARC_SIGCONTEXT_H
+#define __SPARC_SIGCONTEXT_H
+
+#ifdef __KERNEL__
+#include <asm/ptrace.h>
+
+#ifndef __ASSEMBLY__
+
+#define __SUNOS_MAXWIN   31
+
+/* This is what SunOS does, so shall I. */
+struct sigcontext {
+	int sigc_onstack;      /* state to restore */
+	int sigc_mask;         /* sigmask to restore */
+	int sigc_sp;           /* stack pointer */
+	int sigc_pc;           /* program counter */
+	int sigc_npc;          /* next program counter */
+	int sigc_psr;          /* for condition codes etc */
+	int sigc_g1;           /* User uses these two registers */
+	int sigc_o0;           /* within the trampoline code. */
+
+	/* Now comes information regarding the users window set
+	 * at the time of the signal.
+	 */
+	int sigc_oswins;       /* outstanding windows */
+
+	/* stack ptrs for each regwin buf */
+	char *sigc_spbuf[__SUNOS_MAXWIN];
+
+	/* Windows to restore after signal */
+	struct {
+		unsigned long	locals[8];
+		unsigned long	ins[8];
+	} sigc_wbuf[__SUNOS_MAXWIN];
+};
+
+typedef struct {
+	struct {
+		unsigned long psr;
+		unsigned long pc;
+		unsigned long npc;
+		unsigned long y;
+		unsigned long u_regs[16]; /* globals and ins */
+	}		si_regs;
+	int		si_mask;
+} __siginfo_t;
+
+typedef struct {
+	unsigned   long si_float_regs [32];
+	unsigned   long si_fsr;
+	unsigned   long si_fpqdepth;
+	struct {
+		unsigned long *insn_addr;
+		unsigned long insn;
+	} si_fpqueue [16];
+} __siginfo_fpu_t;
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* (__KERNEL__) */
+
+#endif /* !(__SPARC_SIGCONTEXT_H) */
diff --git a/include/asm-sparc/sigcontext_64.h b/include/asm-sparc/sigcontext_64.h
new file mode 100644
index 0000000..1c868d6
--- /dev/null
+++ b/include/asm-sparc/sigcontext_64.h
@@ -0,0 +1,87 @@
+#ifndef __SPARC64_SIGCONTEXT_H
+#define __SPARC64_SIGCONTEXT_H
+
+#ifdef __KERNEL__
+#include <asm/ptrace.h>
+#endif
+
+#ifndef __ASSEMBLY__
+
+#ifdef __KERNEL__
+
+#define __SUNOS_MAXWIN   31
+
+/* This is what SunOS does, so shall I unless we use new 32bit signals or rt signals. */
+struct sigcontext32 {
+	int sigc_onstack;      /* state to restore */
+	int sigc_mask;         /* sigmask to restore */
+	int sigc_sp;           /* stack pointer */
+	int sigc_pc;           /* program counter */
+	int sigc_npc;          /* next program counter */
+	int sigc_psr;          /* for condition codes etc */
+	int sigc_g1;           /* User uses these two registers */
+	int sigc_o0;           /* within the trampoline code. */
+
+	/* Now comes information regarding the users window set
+	 * at the time of the signal.
+	 */
+	int sigc_oswins;       /* outstanding windows */
+
+	/* stack ptrs for each regwin buf */
+	unsigned sigc_spbuf[__SUNOS_MAXWIN];
+
+	/* Windows to restore after signal */
+	struct reg_window32 sigc_wbuf[__SUNOS_MAXWIN];
+};
+
+#endif
+
+#ifdef __KERNEL__
+
+/* This is what we use for 32bit new non-rt signals. */
+
+typedef struct {
+	struct {
+		unsigned int psr;
+		unsigned int pc;
+		unsigned int npc;
+		unsigned int y;
+		unsigned int u_regs[16]; /* globals and ins */
+	}			si_regs;
+	int			si_mask;
+} __siginfo32_t;
+
+#endif
+
+typedef struct {
+	unsigned   int si_float_regs [64];
+	unsigned   long si_fsr;
+	unsigned   long si_gsr;
+	unsigned   long si_fprs;
+} __siginfo_fpu_t;
+
+/* This is what SunOS doesn't, so we have to write this alone
+   and do it properly. */
+struct sigcontext {
+	/* The size of this array has to match SI_MAX_SIZE from siginfo.h */
+	char			sigc_info[128];
+	struct {
+		unsigned long	u_regs[16]; /* globals and ins */
+		unsigned long	tstate;
+		unsigned long	tpc;
+		unsigned long	tnpc;
+		unsigned int	y;
+		unsigned int	fprs;
+	}			sigc_regs;
+	__siginfo_fpu_t *	sigc_fpu_save;
+	struct {
+		void	*	ss_sp;
+		int		ss_flags;
+		unsigned long	ss_size;
+	}			sigc_stack;
+	unsigned long		sigc_mask;
+};
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__SPARC64_SIGCONTEXT_H) */
diff --git a/include/asm-sparc/siginfo.h b/include/asm-sparc/siginfo.h
index 3c71af1..2c9fccf 100644
--- a/include/asm-sparc/siginfo.h
+++ b/include/asm-sparc/siginfo.h
@@ -1,17 +1,8 @@
-#ifndef _SPARC_SIGINFO_H
-#define _SPARC_SIGINFO_H
-
-#define __ARCH_SI_UID_T		unsigned int
-#define __ARCH_SI_TRAPNO
-
-#include <asm-generic/siginfo.h>
-
-#define SI_NOINFO	32767		/* no information in siginfo_t */
-
-/*
- * SIGEMT si_codes
- */
-#define EMT_TAGOVF	(__SI_FAULT|1)	/* tag overflow */
-#define NSIGEMT		1
-
-#endif /* !(_SPARC_SIGINFO_H) */
+#ifndef ___ASM_SPARC_SIGINFO_H
+#define ___ASM_SPARC_SIGINFO_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/siginfo_64.h>
+#else
+#include <asm-sparc/siginfo_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/siginfo_32.h b/include/asm-sparc/siginfo_32.h
new file mode 100644
index 0000000..3c71af1
--- /dev/null
+++ b/include/asm-sparc/siginfo_32.h
@@ -0,0 +1,17 @@
+#ifndef _SPARC_SIGINFO_H
+#define _SPARC_SIGINFO_H
+
+#define __ARCH_SI_UID_T		unsigned int
+#define __ARCH_SI_TRAPNO
+
+#include <asm-generic/siginfo.h>
+
+#define SI_NOINFO	32767		/* no information in siginfo_t */
+
+/*
+ * SIGEMT si_codes
+ */
+#define EMT_TAGOVF	(__SI_FAULT|1)	/* tag overflow */
+#define NSIGEMT		1
+
+#endif /* !(_SPARC_SIGINFO_H) */
diff --git a/include/asm-sparc/siginfo_64.h b/include/asm-sparc/siginfo_64.h
new file mode 100644
index 0000000..c96e6c3
--- /dev/null
+++ b/include/asm-sparc/siginfo_64.h
@@ -0,0 +1,32 @@
+#ifndef _SPARC64_SIGINFO_H
+#define _SPARC64_SIGINFO_H
+
+#define SI_PAD_SIZE32	((SI_MAX_SIZE/sizeof(int)) - 3)
+
+#define __ARCH_SI_PREAMBLE_SIZE	(4 * sizeof(int))
+#define __ARCH_SI_TRAPNO
+#define __ARCH_SI_BAND_T int
+
+#include <asm-generic/siginfo.h>
+
+#ifdef __KERNEL__
+
+#include <linux/compat.h>
+
+#ifdef CONFIG_COMPAT
+
+struct compat_siginfo;
+
+#endif /* CONFIG_COMPAT */
+
+#endif /* __KERNEL__ */
+
+#define SI_NOINFO	32767		/* no information in siginfo_t */
+
+/*
+ * SIGEMT si_codes
+ */
+#define EMT_TAGOVF	(__SI_FAULT|1)	/* tag overflow */
+#define NSIGEMT		1
+
+#endif
diff --git a/include/asm-sparc/signal.h b/include/asm-sparc/signal.h
index 683657d..36f5f9e 100644
--- a/include/asm-sparc/signal.h
+++ b/include/asm-sparc/signal.h
@@ -1,207 +1,8 @@
-#ifndef _ASMSPARC_SIGNAL_H
-#define _ASMSPARC_SIGNAL_H
-
-#include <asm/sigcontext.h>
-#include <linux/compiler.h>
-
-#ifdef __KERNEL__
-#ifndef __ASSEMBLY__
-#include <linux/personality.h>
-#include <linux/types.h>
-#endif
-#endif
-
-/* On the Sparc the signal handlers get passed a 'sub-signal' code
- * for certain signal types, which we document here.
- */
-#define SIGHUP		 1
-#define SIGINT		 2
-#define SIGQUIT		 3
-#define SIGILL		 4
-#define    SUBSIG_STACK       0
-#define    SUBSIG_ILLINST     2
-#define    SUBSIG_PRIVINST    3
-#define    SUBSIG_BADTRAP(t)  (0x80 + (t))
-
-#define SIGTRAP		 5
-#define SIGABRT		 6
-#define SIGIOT		 6
-
-#define SIGEMT           7
-#define    SUBSIG_TAG    10
-
-#define SIGFPE		 8
-#define    SUBSIG_FPDISABLED     0x400
-#define    SUBSIG_FPERROR        0x404
-#define    SUBSIG_FPINTOVFL      0x001
-#define    SUBSIG_FPSTSIG        0x002
-#define    SUBSIG_IDIVZERO       0x014
-#define    SUBSIG_FPINEXACT      0x0c4
-#define    SUBSIG_FPDIVZERO      0x0c8
-#define    SUBSIG_FPUNFLOW       0x0cc
-#define    SUBSIG_FPOPERROR      0x0d0
-#define    SUBSIG_FPOVFLOW       0x0d4
-
-#define SIGKILL		 9
-#define SIGBUS          10
-#define    SUBSIG_BUSTIMEOUT    1
-#define    SUBSIG_ALIGNMENT     2
-#define    SUBSIG_MISCERROR     5
-
-#define SIGSEGV		11
-#define    SUBSIG_NOMAPPING     3
-#define    SUBSIG_PROTECTION    4
-#define    SUBSIG_SEGERROR      5
-
-#define SIGSYS		12
-
-#define SIGPIPE		13
-#define SIGALRM		14
-#define SIGTERM		15
-#define SIGURG          16
-
-/* SunOS values which deviate from the Linux/i386 ones */
-#define SIGSTOP		17
-#define SIGTSTP		18
-#define SIGCONT		19
-#define SIGCHLD		20
-#define SIGTTIN		21
-#define SIGTTOU		22
-#define SIGIO		23
-#define SIGPOLL		SIGIO   /* SysV name for SIGIO */
-#define SIGXCPU		24
-#define SIGXFSZ		25
-#define SIGVTALRM	26
-#define SIGPROF		27
-#define SIGWINCH	28
-#define SIGLOST		29
-#define SIGPWR		SIGLOST
-#define SIGUSR1		30
-#define SIGUSR2		31
-
-/* Most things should be clean enough to redefine this at will, if care
- * is taken to make libc match.
- */
-
-#define __OLD_NSIG	32
-#define __NEW_NSIG	64
-#define _NSIG_BPW	32
-#define _NSIG_WORDS	(__NEW_NSIG / _NSIG_BPW)
-
-#define SIGRTMIN	32
-#define SIGRTMAX	__NEW_NSIG
-
-#if defined(__KERNEL__) || defined(__WANT_POSIX1B_SIGNALS__)
-#define	_NSIG		__NEW_NSIG
-#define __new_sigset_t	sigset_t
-#define __new_sigaction	sigaction
-#define __old_sigset_t	old_sigset_t
-#define __old_sigaction	old_sigaction
+#ifndef ___ASM_SPARC_SIGNAL_H
+#define ___ASM_SPARC_SIGNAL_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/signal_64.h>
 #else
-#define _NSIG		__OLD_NSIG
-#define __old_sigset_t	sigset_t
-#define __old_sigaction	sigaction
+#include <asm-sparc/signal_32.h>
 #endif
-
-#ifndef __ASSEMBLY__
-
-typedef unsigned long __old_sigset_t;
-
-typedef struct {
-	unsigned long	sig[_NSIG_WORDS];
-} __new_sigset_t;
-
-
-#ifdef __KERNEL__
-/* A SunOS sigstack */
-struct sigstack {
-	char *the_stack;
-	int   cur_status;
-};
 #endif
-
-/* Sigvec flags */
-#define _SV_SSTACK    1u    /* This signal handler should use sig-stack */
-#define _SV_INTR      2u    /* Sig return should not restart system call */
-#define _SV_RESET     4u    /* Set handler to SIG_DFL upon taken signal */
-#define _SV_IGNCHILD  8u    /* Do not send SIGCHLD */
-
-/*
- * sa_flags values: SA_STACK is not currently supported, but will allow the
- * usage of signal stacks by using the (now obsolete) sa_restorer field in
- * the sigaction structure as a stack pointer. This is now possible due to
- * the changes in signal handling. LBT 010493.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- */
-#define SA_NOCLDSTOP	_SV_IGNCHILD
-#define SA_STACK	_SV_SSTACK
-#define SA_ONSTACK	_SV_SSTACK
-#define SA_RESTART	_SV_INTR
-#define SA_ONESHOT	_SV_RESET
-#define SA_NOMASK	0x20u
-#define SA_NOCLDWAIT	0x100u
-#define SA_SIGINFO	0x200u
-
-#define SIG_BLOCK          0x01	/* for blocking signals */
-#define SIG_UNBLOCK        0x02	/* for unblocking signals */
-#define SIG_SETMASK        0x04	/* for setting the signal mask */
-
-/* 
- * sigaltstack controls
- */
-#define SS_ONSTACK	1
-#define SS_DISABLE	2
-
-#define MINSIGSTKSZ	4096
-#define SIGSTKSZ	16384
-
-#ifdef __KERNEL__
-/*
- * DJHR
- * SA_STATIC_ALLOC is used for the SPARC system to indicate that this
- * interrupt handler's irq structure should be statically allocated
- * by the request_irq routine.
- * The alternative is that arch/sparc/kernel/irq.c has carnal knowledge
- * of interrupt usage and that sucks. Also without a flag like this
- * it may be possible for the free_irq routine to attempt to free
- * statically allocated data.. which is NOT GOOD.
- *
- */
-#define SA_STATIC_ALLOC		0x8000
-#endif
-
-#include <asm-generic/signal.h>
-
-#ifdef __KERNEL__
-struct __new_sigaction {
-	__sighandler_t	sa_handler;
-	unsigned long	sa_flags;
-	void		(*sa_restorer)(void);	/* Not used by Linux/SPARC */
-	__new_sigset_t	sa_mask;
-};
-
-struct k_sigaction {
-	struct __new_sigaction	sa;
-	void			__user *ka_restorer;
-};
-
-struct __old_sigaction {
-	__sighandler_t	sa_handler;
-	__old_sigset_t	sa_mask;
-	unsigned long	sa_flags;
-	void		(*sa_restorer) (void);	/* not used by Linux/SPARC */
-};
-
-typedef struct sigaltstack {
-	void		__user *ss_sp;
-	int		ss_flags;
-	size_t		ss_size;
-} stack_t;
-
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
-#endif /* !(__KERNEL__) */
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(_ASMSPARC_SIGNAL_H) */
diff --git a/include/asm-sparc/signal_32.h b/include/asm-sparc/signal_32.h
new file mode 100644
index 0000000..96a60ab
--- /dev/null
+++ b/include/asm-sparc/signal_32.h
@@ -0,0 +1,207 @@
+#ifndef _ASMSPARC_SIGNAL_H
+#define _ASMSPARC_SIGNAL_H
+
+#include <asm/sigcontext.h>
+#include <linux/compiler.h>
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+#include <linux/personality.h>
+#include <linux/types.h>
+#endif
+#endif
+
+/* On the Sparc the signal handlers get passed a 'sub-signal' code
+ * for certain signal types, which we document here.
+ */
+#define SIGHUP		 1
+#define SIGINT		 2
+#define SIGQUIT		 3
+#define SIGILL		 4
+#define    SUBSIG_STACK       0
+#define    SUBSIG_ILLINST     2
+#define    SUBSIG_PRIVINST    3
+#define    SUBSIG_BADTRAP(t)  (0x80 + (t))
+
+#define SIGTRAP		 5
+#define SIGABRT		 6
+#define SIGIOT		 6
+
+#define SIGEMT           7
+#define    SUBSIG_TAG    10
+
+#define SIGFPE		 8
+#define    SUBSIG_FPDISABLED     0x400
+#define    SUBSIG_FPERROR        0x404
+#define    SUBSIG_FPINTOVFL      0x001
+#define    SUBSIG_FPSTSIG        0x002
+#define    SUBSIG_IDIVZERO       0x014
+#define    SUBSIG_FPINEXACT      0x0c4
+#define    SUBSIG_FPDIVZERO      0x0c8
+#define    SUBSIG_FPUNFLOW       0x0cc
+#define    SUBSIG_FPOPERROR      0x0d0
+#define    SUBSIG_FPOVFLOW       0x0d4
+
+#define SIGKILL		 9
+#define SIGBUS          10
+#define    SUBSIG_BUSTIMEOUT    1
+#define    SUBSIG_ALIGNMENT     2
+#define    SUBSIG_MISCERROR     5
+
+#define SIGSEGV		11
+#define    SUBSIG_NOMAPPING     3
+#define    SUBSIG_PROTECTION    4
+#define    SUBSIG_SEGERROR      5
+
+#define SIGSYS		12
+
+#define SIGPIPE		13
+#define SIGALRM		14
+#define SIGTERM		15
+#define SIGURG          16
+
+/* SunOS values which deviate from the Linux/i386 ones */
+#define SIGSTOP		17
+#define SIGTSTP		18
+#define SIGCONT		19
+#define SIGCHLD		20
+#define SIGTTIN		21
+#define SIGTTOU		22
+#define SIGIO		23
+#define SIGPOLL		SIGIO   /* SysV name for SIGIO */
+#define SIGXCPU		24
+#define SIGXFSZ		25
+#define SIGVTALRM	26
+#define SIGPROF		27
+#define SIGWINCH	28
+#define SIGLOST		29
+#define SIGPWR		SIGLOST
+#define SIGUSR1		30
+#define SIGUSR2		31
+
+/* Most things should be clean enough to redefine this at will, if care
+ * is taken to make libc match.
+ */
+
+#define __OLD_NSIG	32
+#define __NEW_NSIG	64
+#define _NSIG_BPW	32
+#define _NSIG_WORDS	(__NEW_NSIG / _NSIG_BPW)
+
+#define SIGRTMIN	32
+#define SIGRTMAX	__NEW_NSIG
+
+#if defined(__KERNEL__) || defined(__WANT_POSIX1B_SIGNALS__)
+#define	_NSIG		__NEW_NSIG
+#define __new_sigset_t	sigset_t
+#define __new_sigaction	sigaction
+#define __old_sigset_t	old_sigset_t
+#define __old_sigaction	old_sigaction
+#else
+#define _NSIG		__OLD_NSIG
+#define __old_sigset_t	sigset_t
+#define __old_sigaction	sigaction
+#endif
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned long __old_sigset_t;
+
+typedef struct {
+	unsigned long	sig[_NSIG_WORDS];
+} __new_sigset_t;
+
+
+#ifdef __KERNEL__
+/* A SunOS sigstack */
+struct sigstack {
+	char *the_stack;
+	int   cur_status;
+};
+#endif
+
+/* Sigvec flags */
+#define _SV_SSTACK    1u    /* This signal handler should use sig-stack */
+#define _SV_INTR      2u    /* Sig return should not restart system call */
+#define _SV_RESET     4u    /* Set handler to SIG_DFL upon taken signal */
+#define _SV_IGNCHILD  8u    /* Do not send SIGCHLD */
+
+/*
+ * sa_flags values: SA_STACK is not currently supported, but will allow the
+ * usage of signal stacks by using the (now obsolete) sa_restorer field in
+ * the sigaction structure as a stack pointer. This is now possible due to
+ * the changes in signal handling. LBT 010493.
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ */
+#define SA_NOCLDSTOP	_SV_IGNCHILD
+#define SA_STACK	_SV_SSTACK
+#define SA_ONSTACK	_SV_SSTACK
+#define SA_RESTART	_SV_INTR
+#define SA_ONESHOT	_SV_RESET
+#define SA_NOMASK	0x20u
+#define SA_NOCLDWAIT	0x100u
+#define SA_SIGINFO	0x200u
+
+#define SIG_BLOCK          0x01	/* for blocking signals */
+#define SIG_UNBLOCK        0x02	/* for unblocking signals */
+#define SIG_SETMASK        0x04	/* for setting the signal mask */
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK	1
+#define SS_DISABLE	2
+
+#define MINSIGSTKSZ	4096
+#define SIGSTKSZ	16384
+
+#ifdef __KERNEL__
+/*
+ * DJHR
+ * SA_STATIC_ALLOC is used for the SPARC system to indicate that this
+ * interrupt handler's irq structure should be statically allocated
+ * by the request_irq routine.
+ * The alternative is that arch/sparc/kernel/irq.c has carnal knowledge
+ * of interrupt usage and that sucks. Also without a flag like this
+ * it may be possible for the free_irq routine to attempt to free
+ * statically allocated data.. which is NOT GOOD.
+ *
+ */
+#define SA_STATIC_ALLOC		0x8000
+#endif
+
+#include <asm-generic/signal.h>
+
+#ifdef __KERNEL__
+struct __new_sigaction {
+	__sighandler_t	sa_handler;
+	unsigned long	sa_flags;
+	void		(*sa_restorer)(void);	/* Not used by Linux/SPARC */
+	__new_sigset_t	sa_mask;
+};
+
+struct k_sigaction {
+	struct __new_sigaction	sa;
+	void			__user *ka_restorer;
+};
+
+struct __old_sigaction {
+	__sighandler_t	sa_handler;
+	__old_sigset_t	sa_mask;
+	unsigned long	sa_flags;
+	void		(*sa_restorer) (void);	/* not used by Linux/SPARC */
+};
+
+typedef struct sigaltstack {
+	void		__user *ss_sp;
+	int		ss_flags;
+	size_t		ss_size;
+} stack_t;
+
+#define ptrace_signal_deliver(regs, cookie) do { } while (0)
+
+#endif /* !(__KERNEL__) */
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(_ASMSPARC_SIGNAL_H) */
diff --git a/include/asm-sparc/signal_64.h b/include/asm-sparc/signal_64.h
new file mode 100644
index 0000000..ab1509a
--- /dev/null
+++ b/include/asm-sparc/signal_64.h
@@ -0,0 +1,194 @@
+#ifndef _ASMSPARC64_SIGNAL_H
+#define _ASMSPARC64_SIGNAL_H
+
+#include <asm/sigcontext.h>
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+#include <linux/personality.h>
+#include <linux/types.h>
+#endif
+#endif
+
+/* On the Sparc the signal handlers get passed a 'sub-signal' code
+ * for certain signal types, which we document here.
+ */
+#define SIGHUP		 1
+#define SIGINT		 2
+#define SIGQUIT		 3
+#define SIGILL		 4
+#define    SUBSIG_STACK       0
+#define    SUBSIG_ILLINST     2
+#define    SUBSIG_PRIVINST    3
+#define    SUBSIG_BADTRAP(t)  (0x80 + (t))
+
+#define SIGTRAP		 5
+#define SIGABRT		 6
+#define SIGIOT		 6
+
+#define SIGEMT           7
+#define    SUBSIG_TAG    10
+
+#define SIGFPE		 8
+#define    SUBSIG_FPDISABLED     0x400
+#define    SUBSIG_FPERROR        0x404
+#define    SUBSIG_FPINTOVFL      0x001
+#define    SUBSIG_FPSTSIG        0x002
+#define    SUBSIG_IDIVZERO       0x014
+#define    SUBSIG_FPINEXACT      0x0c4
+#define    SUBSIG_FPDIVZERO      0x0c8
+#define    SUBSIG_FPUNFLOW       0x0cc
+#define    SUBSIG_FPOPERROR      0x0d0
+#define    SUBSIG_FPOVFLOW       0x0d4
+
+#define SIGKILL		 9
+#define SIGBUS          10
+#define    SUBSIG_BUSTIMEOUT    1
+#define    SUBSIG_ALIGNMENT     2
+#define    SUBSIG_MISCERROR     5
+
+#define SIGSEGV		11
+#define    SUBSIG_NOMAPPING     3
+#define    SUBSIG_PROTECTION    4
+#define    SUBSIG_SEGERROR      5
+
+#define SIGSYS		12
+
+#define SIGPIPE		13
+#define SIGALRM		14
+#define SIGTERM		15
+#define SIGURG          16
+
+/* SunOS values which deviate from the Linux/i386 ones */
+#define SIGSTOP		17
+#define SIGTSTP		18
+#define SIGCONT		19
+#define SIGCHLD		20
+#define SIGTTIN		21
+#define SIGTTOU		22
+#define SIGIO		23
+#define SIGPOLL		SIGIO   /* SysV name for SIGIO */
+#define SIGXCPU		24
+#define SIGXFSZ		25
+#define SIGVTALRM	26
+#define SIGPROF		27
+#define SIGWINCH	28
+#define SIGLOST		29
+#define SIGPWR		SIGLOST
+#define SIGUSR1		30
+#define SIGUSR2		31
+
+/* Most things should be clean enough to redefine this at will, if care
+   is taken to make libc match.  */
+
+#define __OLD_NSIG	32
+#define __NEW_NSIG      64
+#define _NSIG_BPW     	64
+#define _NSIG_WORDS   	(__NEW_NSIG / _NSIG_BPW)
+
+#define SIGRTMIN       32
+#define SIGRTMAX       __NEW_NSIG
+
+#if defined(__KERNEL__) || defined(__WANT_POSIX1B_SIGNALS__)
+#define _NSIG			__NEW_NSIG
+#define __new_sigset_t		sigset_t
+#define __new_sigaction		sigaction
+#define __new_sigaction32	sigaction32
+#define __old_sigset_t		old_sigset_t
+#define __old_sigaction		old_sigaction
+#define __old_sigaction32	old_sigaction32
+#else
+#define _NSIG			__OLD_NSIG
+#define NSIG			_NSIG
+#define __old_sigset_t		sigset_t
+#define __old_sigaction		sigaction
+#define __old_sigaction32	sigaction32
+#endif
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned long __old_sigset_t;            /* at least 32 bits */
+
+typedef struct {
+       unsigned long sig[_NSIG_WORDS];
+} __new_sigset_t;
+
+/* A SunOS sigstack */
+struct sigstack {
+	/* XXX 32-bit pointers pinhead XXX */
+	char *the_stack;
+	int   cur_status;
+};
+
+/* Sigvec flags */
+#define _SV_SSTACK    1u    /* This signal handler should use sig-stack */
+#define _SV_INTR      2u    /* Sig return should not restart system call */
+#define _SV_RESET     4u    /* Set handler to SIG_DFL upon taken signal */
+#define _SV_IGNCHILD  8u    /* Do not send SIGCHLD */
+
+/*
+ * sa_flags values: SA_STACK is not currently supported, but will allow the
+ * usage of signal stacks by using the (now obsolete) sa_restorer field in
+ * the sigaction structure as a stack pointer. This is now possible due to
+ * the changes in signal handling. LBT 010493.
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ */
+#define SA_NOCLDSTOP	_SV_IGNCHILD
+#define SA_STACK	_SV_SSTACK
+#define SA_ONSTACK	_SV_SSTACK
+#define SA_RESTART	_SV_INTR
+#define SA_ONESHOT	_SV_RESET
+#define SA_NOMASK	0x20u
+#define SA_NOCLDWAIT    0x100u
+#define SA_SIGINFO      0x200u
+
+
+#define SIG_BLOCK          0x01	/* for blocking signals */
+#define SIG_UNBLOCK        0x02	/* for unblocking signals */
+#define SIG_SETMASK        0x04	/* for setting the signal mask */
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK	1
+#define SS_DISABLE	2
+
+#define MINSIGSTKSZ	4096
+#define SIGSTKSZ	16384
+
+#include <asm-generic/signal.h>
+
+struct __new_sigaction {
+	__sighandler_t		sa_handler;
+	unsigned long		sa_flags;
+	__sigrestore_t 		sa_restorer;  /* not used by Linux/SPARC yet */
+	__new_sigset_t		sa_mask;
+};
+
+struct __old_sigaction {
+	__sighandler_t  	sa_handler;
+	__old_sigset_t  	sa_mask;
+	unsigned long   	sa_flags;
+	void 			(*sa_restorer)(void);     /* not used by Linux/SPARC yet */
+};
+
+typedef struct sigaltstack {
+	void			__user *ss_sp;
+	int			ss_flags;
+	size_t			ss_size;
+} stack_t;
+
+#ifdef __KERNEL__
+
+struct k_sigaction {
+	struct __new_sigaction 	sa;
+	void __user		*ka_restorer;
+};
+
+#define ptrace_signal_deliver(regs, cookie) do { } while (0)
+
+#endif /* !(__KERNEL__) */
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(_ASMSPARC64_SIGNAL_H) */
diff --git a/include/asm-sparc/smp.h b/include/asm-sparc/smp.h
index b61e74b..1f9dedf 100644
--- a/include/asm-sparc/smp.h
+++ b/include/asm-sparc/smp.h
@@ -1,173 +1,8 @@
-/* smp.h: Sparc specific SMP stuff.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef _SPARC_SMP_H
-#define _SPARC_SMP_H
-
-#include <linux/threads.h>
-#include <asm/head.h>
-#include <asm/btfixup.h>
-
-#ifndef __ASSEMBLY__
-
-#include <linux/cpumask.h>
-
-#endif /* __ASSEMBLY__ */
-
-#ifdef CONFIG_SMP
-
-#ifndef __ASSEMBLY__
-
-#include <asm/ptrace.h>
-#include <asm/asi.h>
-#include <asm/atomic.h>
-
-/*
- *	Private routines/data
- */
- 
-extern unsigned char boot_cpu_id;
-extern cpumask_t phys_cpu_present_map;
-#define cpu_possible_map phys_cpu_present_map
-
-typedef void (*smpfunc_t)(unsigned long, unsigned long, unsigned long,
-		       unsigned long, unsigned long);
-
-/*
- *	General functions that each host system must provide.
- */
- 
-void sun4m_init_smp(void);
-void sun4d_init_smp(void);
-
-void smp_callin(void);
-void smp_boot_cpus(void);
-void smp_store_cpu_info(int);
-
-struct seq_file;
-void smp_bogo(struct seq_file *);
-void smp_info(struct seq_file *);
-
-BTFIXUPDEF_CALL(void, smp_cross_call, smpfunc_t, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)
-BTFIXUPDEF_CALL(int, __hard_smp_processor_id, void)
-BTFIXUPDEF_BLACKBOX(hard_smp_processor_id)
-BTFIXUPDEF_BLACKBOX(load_current)
-
-#define smp_cross_call(func,arg1,arg2,arg3,arg4,arg5) BTFIXUP_CALL(smp_cross_call)(func,arg1,arg2,arg3,arg4,arg5)
-
-static inline void xc0(smpfunc_t func) { smp_cross_call(func, 0, 0, 0, 0, 0); }
-static inline void xc1(smpfunc_t func, unsigned long arg1)
-{ smp_cross_call(func, arg1, 0, 0, 0, 0); }
-static inline void xc2(smpfunc_t func, unsigned long arg1, unsigned long arg2)
-{ smp_cross_call(func, arg1, arg2, 0, 0, 0); }
-static inline void xc3(smpfunc_t func, unsigned long arg1, unsigned long arg2,
-			   unsigned long arg3)
-{ smp_cross_call(func, arg1, arg2, arg3, 0, 0); }
-static inline void xc4(smpfunc_t func, unsigned long arg1, unsigned long arg2,
-			   unsigned long arg3, unsigned long arg4)
-{ smp_cross_call(func, arg1, arg2, arg3, arg4, 0); }
-static inline void xc5(smpfunc_t func, unsigned long arg1, unsigned long arg2,
-			   unsigned long arg3, unsigned long arg4, unsigned long arg5)
-{ smp_cross_call(func, arg1, arg2, arg3, arg4, arg5); }
-
-static inline int smp_call_function(void (*func)(void *info), void *info, int wait)
-{
-	xc1((smpfunc_t)func, (unsigned long)info);
-	return 0;
-}
-
-static inline int cpu_logical_map(int cpu)
-{
-	return cpu;
-}
-
-static inline int hard_smp4m_processor_id(void)
-{
-	int cpuid;
-
-	__asm__ __volatile__("rd %%tbr, %0\n\t"
-			     "srl %0, 12, %0\n\t"
-			     "and %0, 3, %0\n\t" :
-			     "=&r" (cpuid));
-	return cpuid;
-}
-
-static inline int hard_smp4d_processor_id(void)
-{
-	int cpuid;
-
-	__asm__ __volatile__("lda [%%g0] %1, %0\n\t" :
-			     "=&r" (cpuid) : "i" (ASI_M_VIKING_TMP1));
-	return cpuid;
-}
-
-#ifndef MODULE
-static inline int hard_smp_processor_id(void)
-{
-	int cpuid;
-
-	/* Black box - sun4m
-		__asm__ __volatile__("rd %%tbr, %0\n\t"
-				     "srl %0, 12, %0\n\t"
-				     "and %0, 3, %0\n\t" :
-				     "=&r" (cpuid));
-	             - sun4d
-	   	__asm__ __volatile__("lda [%g0] ASI_M_VIKING_TMP1, %0\n\t"
-	   			     "nop; nop" :
-	   			     "=&r" (cpuid));
-	   See btfixup.h and btfixupprep.c to understand how a blackbox works.
-	 */
-	__asm__ __volatile__("sethi %%hi(___b_hard_smp_processor_id), %0\n\t"
-			     "sethi %%hi(boot_cpu_id), %0\n\t"
-			     "ldub [%0 + %%lo(boot_cpu_id)], %0\n\t" :
-			     "=&r" (cpuid));
-	return cpuid;
-}
+#ifndef ___ASM_SPARC_SMP_H
+#define ___ASM_SPARC_SMP_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/smp_64.h>
 #else
-static inline int hard_smp_processor_id(void)
-{
-	int cpuid;
-	
-	__asm__ __volatile__("mov %%o7, %%g1\n\t"
-			     "call ___f___hard_smp_processor_id\n\t"
-			     " nop\n\t"
-			     "mov %%g2, %0\n\t" : "=r"(cpuid) : : "g1", "g2");
-	return cpuid;
-}
+#include <asm-sparc/smp_32.h>
 #endif
-
-#define raw_smp_processor_id()		(current_thread_info()->cpu)
-
-#define prof_multiplier(__cpu)		cpu_data(__cpu).multiplier
-#define prof_counter(__cpu)		cpu_data(__cpu).counter
-
-void smp_setup_cpu_possible_map(void);
-
-#endif /* !(__ASSEMBLY__) */
-
-/* Sparc specific messages. */
-#define MSG_CROSS_CALL         0x0005       /* run func on cpus */
-
-/* Empirical PROM processor mailbox constants.  If the per-cpu mailbox
- * contains something other than one of these then the ipi is from
- * Linux's active_kernel_processor.  This facility exists so that
- * the boot monitor can capture all the other cpus when one catches
- * a watchdog reset or the user enters the monitor using L1-A keys.
- */
-#define MBOX_STOPCPU          0xFB
-#define MBOX_IDLECPU          0xFC
-#define MBOX_IDLECPU2         0xFD
-#define MBOX_STOPCPU2         0xFE
-
-#else /* SMP */
-
-#define hard_smp_processor_id()		0
-#define smp_setup_cpu_possible_map() do { } while (0)
-
-#endif /* !(SMP) */
-
-#define NO_PROC_ID            0xFF
-
-#endif /* !(_SPARC_SMP_H) */
+#endif
diff --git a/include/asm-sparc/smp_32.h b/include/asm-sparc/smp_32.h
new file mode 100644
index 0000000..7201752
--- /dev/null
+++ b/include/asm-sparc/smp_32.h
@@ -0,0 +1,173 @@
+/* smp.h: Sparc specific SMP stuff.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_SMP_H
+#define _SPARC_SMP_H
+
+#include <linux/threads.h>
+#include <asm/head.h>
+#include <asm/btfixup.h>
+
+#ifndef __ASSEMBLY__
+
+#include <linux/cpumask.h>
+
+#endif /* __ASSEMBLY__ */
+
+#ifdef CONFIG_SMP
+
+#ifndef __ASSEMBLY__
+
+#include <asm/ptrace.h>
+#include <asm/asi.h>
+#include <asm/atomic.h>
+
+/*
+ *	Private routines/data
+ */
+
+extern unsigned char boot_cpu_id;
+extern cpumask_t phys_cpu_present_map;
+#define cpu_possible_map phys_cpu_present_map
+
+typedef void (*smpfunc_t)(unsigned long, unsigned long, unsigned long,
+		       unsigned long, unsigned long);
+
+/*
+ *	General functions that each host system must provide.
+ */
+
+void sun4m_init_smp(void);
+void sun4d_init_smp(void);
+
+void smp_callin(void);
+void smp_boot_cpus(void);
+void smp_store_cpu_info(int);
+
+struct seq_file;
+void smp_bogo(struct seq_file *);
+void smp_info(struct seq_file *);
+
+BTFIXUPDEF_CALL(void, smp_cross_call, smpfunc_t, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)
+BTFIXUPDEF_CALL(int, __hard_smp_processor_id, void)
+BTFIXUPDEF_BLACKBOX(hard_smp_processor_id)
+BTFIXUPDEF_BLACKBOX(load_current)
+
+#define smp_cross_call(func,arg1,arg2,arg3,arg4,arg5) BTFIXUP_CALL(smp_cross_call)(func,arg1,arg2,arg3,arg4,arg5)
+
+static inline void xc0(smpfunc_t func) { smp_cross_call(func, 0, 0, 0, 0, 0); }
+static inline void xc1(smpfunc_t func, unsigned long arg1)
+{ smp_cross_call(func, arg1, 0, 0, 0, 0); }
+static inline void xc2(smpfunc_t func, unsigned long arg1, unsigned long arg2)
+{ smp_cross_call(func, arg1, arg2, 0, 0, 0); }
+static inline void xc3(smpfunc_t func, unsigned long arg1, unsigned long arg2,
+			   unsigned long arg3)
+{ smp_cross_call(func, arg1, arg2, arg3, 0, 0); }
+static inline void xc4(smpfunc_t func, unsigned long arg1, unsigned long arg2,
+			   unsigned long arg3, unsigned long arg4)
+{ smp_cross_call(func, arg1, arg2, arg3, arg4, 0); }
+static inline void xc5(smpfunc_t func, unsigned long arg1, unsigned long arg2,
+			   unsigned long arg3, unsigned long arg4, unsigned long arg5)
+{ smp_cross_call(func, arg1, arg2, arg3, arg4, arg5); }
+
+static inline int smp_call_function(void (*func)(void *info), void *info, int wait)
+{
+	xc1((smpfunc_t)func, (unsigned long)info);
+	return 0;
+}
+
+static inline int cpu_logical_map(int cpu)
+{
+	return cpu;
+}
+
+static inline int hard_smp4m_processor_id(void)
+{
+	int cpuid;
+
+	__asm__ __volatile__("rd %%tbr, %0\n\t"
+			     "srl %0, 12, %0\n\t"
+			     "and %0, 3, %0\n\t" :
+			     "=&r" (cpuid));
+	return cpuid;
+}
+
+static inline int hard_smp4d_processor_id(void)
+{
+	int cpuid;
+
+	__asm__ __volatile__("lda [%%g0] %1, %0\n\t" :
+			     "=&r" (cpuid) : "i" (ASI_M_VIKING_TMP1));
+	return cpuid;
+}
+
+#ifndef MODULE
+static inline int hard_smp_processor_id(void)
+{
+	int cpuid;
+
+	/* Black box - sun4m
+		__asm__ __volatile__("rd %%tbr, %0\n\t"
+				     "srl %0, 12, %0\n\t"
+				     "and %0, 3, %0\n\t" :
+				     "=&r" (cpuid));
+	             - sun4d
+		__asm__ __volatile__("lda [%g0] ASI_M_VIKING_TMP1, %0\n\t"
+				     "nop; nop" :
+				     "=&r" (cpuid));
+	   See btfixup.h and btfixupprep.c to understand how a blackbox works.
+	 */
+	__asm__ __volatile__("sethi %%hi(___b_hard_smp_processor_id), %0\n\t"
+			     "sethi %%hi(boot_cpu_id), %0\n\t"
+			     "ldub [%0 + %%lo(boot_cpu_id)], %0\n\t" :
+			     "=&r" (cpuid));
+	return cpuid;
+}
+#else
+static inline int hard_smp_processor_id(void)
+{
+	int cpuid;
+
+	__asm__ __volatile__("mov %%o7, %%g1\n\t"
+			     "call ___f___hard_smp_processor_id\n\t"
+			     " nop\n\t"
+			     "mov %%g2, %0\n\t" : "=r"(cpuid) : : "g1", "g2");
+	return cpuid;
+}
+#endif
+
+#define raw_smp_processor_id()		(current_thread_info()->cpu)
+
+#define prof_multiplier(__cpu)		cpu_data(__cpu).multiplier
+#define prof_counter(__cpu)		cpu_data(__cpu).counter
+
+void smp_setup_cpu_possible_map(void);
+
+#endif /* !(__ASSEMBLY__) */
+
+/* Sparc specific messages. */
+#define MSG_CROSS_CALL         0x0005       /* run func on cpus */
+
+/* Empirical PROM processor mailbox constants.  If the per-cpu mailbox
+ * contains something other than one of these then the ipi is from
+ * Linux's active_kernel_processor.  This facility exists so that
+ * the boot monitor can capture all the other cpus when one catches
+ * a watchdog reset or the user enters the monitor using L1-A keys.
+ */
+#define MBOX_STOPCPU          0xFB
+#define MBOX_IDLECPU          0xFC
+#define MBOX_IDLECPU2         0xFD
+#define MBOX_STOPCPU2         0xFE
+
+#else /* SMP */
+
+#define hard_smp_processor_id()		0
+#define smp_setup_cpu_possible_map() do { } while (0)
+
+#endif /* !(SMP) */
+
+#define NO_PROC_ID            0xFF
+
+#endif /* !(_SPARC_SMP_H) */
diff --git a/include/asm-sparc/smp_64.h b/include/asm-sparc/smp_64.h
new file mode 100644
index 0000000..57224dd
--- /dev/null
+++ b/include/asm-sparc/smp_64.h
@@ -0,0 +1,67 @@
+/* smp.h: Sparc64 specific SMP stuff.
+ *
+ * Copyright (C) 1996, 2008 David S. Miller (davem@davemloft.net)
+ */
+
+#ifndef _SPARC64_SMP_H
+#define _SPARC64_SMP_H
+
+#include <linux/threads.h>
+#include <asm/asi.h>
+#include <asm/starfire.h>
+#include <asm/spitfire.h>
+
+#ifndef __ASSEMBLY__
+
+#include <linux/cpumask.h>
+#include <linux/cache.h>
+
+#endif /* !(__ASSEMBLY__) */
+
+#ifdef CONFIG_SMP
+
+#ifndef __ASSEMBLY__
+
+/*
+ *	Private routines/data
+ */
+
+#include <linux/bitops.h>
+#include <asm/atomic.h>
+#include <asm/percpu.h>
+
+DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
+extern cpumask_t cpu_core_map[NR_CPUS];
+extern int sparc64_multi_core;
+
+extern void arch_send_call_function_single_ipi(int cpu);
+extern void arch_send_call_function_ipi(cpumask_t mask);
+
+/*
+ *	General functions that each host system must provide.
+ */
+
+extern int hard_smp_processor_id(void);
+#define raw_smp_processor_id() (current_thread_info()->cpu)
+
+extern void smp_fill_in_sib_core_maps(void);
+extern void cpu_play_dead(void);
+
+extern void smp_fetch_global_regs(void);
+
+#ifdef CONFIG_HOTPLUG_CPU
+extern int __cpu_disable(void);
+extern void __cpu_die(unsigned int cpu);
+#endif
+
+#endif /* !(__ASSEMBLY__) */
+
+#else
+
+#define hard_smp_processor_id()		0
+#define smp_fill_in_sib_core_maps() do { } while (0)
+#define smp_fetch_global_regs() do { } while (0)
+
+#endif /* !(CONFIG_SMP) */
+
+#endif /* !(_SPARC64_SMP_H) */
diff --git a/include/asm-sparc/sparsemem.h b/include/asm-sparc/sparsemem.h
new file mode 100644
index 0000000..b99d4e4
--- /dev/null
+++ b/include/asm-sparc/sparsemem.h
@@ -0,0 +1,12 @@
+#ifndef _SPARC64_SPARSEMEM_H
+#define _SPARC64_SPARSEMEM_H
+
+#ifdef __KERNEL__
+
+#define SECTION_SIZE_BITS       30
+#define MAX_PHYSADDR_BITS       42
+#define MAX_PHYSMEM_BITS        42
+
+#endif /* !(__KERNEL__) */
+
+#endif /* !(_SPARC64_SPARSEMEM_H) */
diff --git a/include/asm-sparc/spinlock.h b/include/asm-sparc/spinlock.h
index de2249b..3b71c50 100644
--- a/include/asm-sparc/spinlock.h
+++ b/include/asm-sparc/spinlock.h
@@ -1,192 +1,8 @@
-/* spinlock.h: 32-bit Sparc spinlock support.
- *
- * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef __SPARC_SPINLOCK_H
-#define __SPARC_SPINLOCK_H
-
-#include <linux/threads.h>	/* For NR_CPUS */
-
-#ifndef __ASSEMBLY__
-
-#include <asm/psr.h>
-
-#define __raw_spin_is_locked(lock) (*((volatile unsigned char *)(lock)) != 0)
-
-#define __raw_spin_unlock_wait(lock) \
-	do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
-
-static inline void __raw_spin_lock(raw_spinlock_t *lock)
-{
-	__asm__ __volatile__(
-	"\n1:\n\t"
-	"ldstub	[%0], %%g2\n\t"
-	"orcc	%%g2, 0x0, %%g0\n\t"
-	"bne,a	2f\n\t"
-	" ldub	[%0], %%g2\n\t"
-	".subsection	2\n"
-	"2:\n\t"
-	"orcc	%%g2, 0x0, %%g0\n\t"
-	"bne,a	2b\n\t"
-	" ldub	[%0], %%g2\n\t"
-	"b,a	1b\n\t"
-	".previous\n"
-	: /* no outputs */
-	: "r" (lock)
-	: "g2", "memory", "cc");
-}
-
-static inline int __raw_spin_trylock(raw_spinlock_t *lock)
-{
-	unsigned int result;
-	__asm__ __volatile__("ldstub [%1], %0"
-			     : "=r" (result)
-			     : "r" (lock)
-			     : "memory");
-	return (result == 0);
-}
-
-static inline void __raw_spin_unlock(raw_spinlock_t *lock)
-{
-	__asm__ __volatile__("stb %%g0, [%0]" : : "r" (lock) : "memory");
-}
-
-/* Read-write spinlocks, allowing multiple readers
- * but only one writer.
- *
- * NOTE! it is quite common to have readers in interrupts
- * but no interrupt writers. For those circumstances we
- * can "mix" irq-safe locks - any writer needs to get a
- * irq-safe write-lock, but readers can get non-irqsafe
- * read-locks.
- *
- * XXX This might create some problems with my dual spinlock
- * XXX scheme, deadlocks etc. -DaveM
- *
- * Sort of like atomic_t's on Sparc, but even more clever.
- *
- *	------------------------------------
- *	| 24-bit counter           | wlock |  raw_rwlock_t
- *	------------------------------------
- *	 31                       8 7     0
- *
- * wlock signifies the one writer is in or somebody is updating
- * counter. For a writer, if he successfully acquires the wlock,
- * but counter is non-zero, he has to release the lock and wait,
- * till both counter and wlock are zero.
- *
- * Unfortunately this scheme limits us to ~16,000,000 cpus.
- */
-static inline void __read_lock(raw_rwlock_t *rw)
-{
-	register raw_rwlock_t *lp asm("g1");
-	lp = rw;
-	__asm__ __volatile__(
-	"mov	%%o7, %%g4\n\t"
-	"call	___rw_read_enter\n\t"
-	" ldstub	[%%g1 + 3], %%g2\n"
-	: /* no outputs */
-	: "r" (lp)
-	: "g2", "g4", "memory", "cc");
-}
-
-#define __raw_read_lock(lock) \
-do {	unsigned long flags; \
-	local_irq_save(flags); \
-	__read_lock(lock); \
-	local_irq_restore(flags); \
-} while(0)
-
-static inline void __read_unlock(raw_rwlock_t *rw)
-{
-	register raw_rwlock_t *lp asm("g1");
-	lp = rw;
-	__asm__ __volatile__(
-	"mov	%%o7, %%g4\n\t"
-	"call	___rw_read_exit\n\t"
-	" ldstub	[%%g1 + 3], %%g2\n"
-	: /* no outputs */
-	: "r" (lp)
-	: "g2", "g4", "memory", "cc");
-}
-
-#define __raw_read_unlock(lock) \
-do {	unsigned long flags; \
-	local_irq_save(flags); \
-	__read_unlock(lock); \
-	local_irq_restore(flags); \
-} while(0)
-
-static inline void __raw_write_lock(raw_rwlock_t *rw)
-{
-	register raw_rwlock_t *lp asm("g1");
-	lp = rw;
-	__asm__ __volatile__(
-	"mov	%%o7, %%g4\n\t"
-	"call	___rw_write_enter\n\t"
-	" ldstub	[%%g1 + 3], %%g2\n"
-	: /* no outputs */
-	: "r" (lp)
-	: "g2", "g4", "memory", "cc");
-	*(volatile __u32 *)&lp->lock = ~0U;
-}
-
-static inline int __raw_write_trylock(raw_rwlock_t *rw)
-{
-	unsigned int val;
-
-	__asm__ __volatile__("ldstub [%1 + 3], %0"
-			     : "=r" (val)
-			     : "r" (&rw->lock)
-			     : "memory");
-
-	if (val == 0) {
-		val = rw->lock & ~0xff;
-		if (val)
-			((volatile u8*)&rw->lock)[3] = 0;
-		else
-			*(volatile u32*)&rw->lock = ~0U;
-	}
-
-	return (val == 0);
-}
-
-static inline int __read_trylock(raw_rwlock_t *rw)
-{
-	register raw_rwlock_t *lp asm("g1");
-	register int res asm("o0");
-	lp = rw;
-	__asm__ __volatile__(
-	"mov	%%o7, %%g4\n\t"
-	"call	___rw_read_try\n\t"
-	" ldstub	[%%g1 + 3], %%g2\n"
-	: "=r" (res)
-	: "r" (lp)
-	: "g2", "g4", "memory", "cc");
-	return res;
-}
-
-#define __raw_read_trylock(lock) \
-({	unsigned long flags; \
-	int res; \
-	local_irq_save(flags); \
-	res = __read_trylock(lock); \
-	local_irq_restore(flags); \
-	res; \
-})
-
-#define __raw_write_unlock(rw)	do { (rw)->lock = 0; } while(0)
-
-#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
-
-#define _raw_spin_relax(lock)	cpu_relax()
-#define _raw_read_relax(lock)	cpu_relax()
-#define _raw_write_relax(lock)	cpu_relax()
-
-#define __raw_read_can_lock(rw) (!((rw)->lock & 0xff))
-#define __raw_write_can_lock(rw) (!(rw)->lock)
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* __SPARC_SPINLOCK_H */
+#ifndef ___ASM_SPARC_SPINLOCK_H
+#define ___ASM_SPARC_SPINLOCK_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/spinlock_64.h>
+#else
+#include <asm-sparc/spinlock_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/spinlock_32.h b/include/asm-sparc/spinlock_32.h
new file mode 100644
index 0000000..de2249b
--- /dev/null
+++ b/include/asm-sparc/spinlock_32.h
@@ -0,0 +1,192 @@
+/* spinlock.h: 32-bit Sparc spinlock support.
+ *
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef __SPARC_SPINLOCK_H
+#define __SPARC_SPINLOCK_H
+
+#include <linux/threads.h>	/* For NR_CPUS */
+
+#ifndef __ASSEMBLY__
+
+#include <asm/psr.h>
+
+#define __raw_spin_is_locked(lock) (*((volatile unsigned char *)(lock)) != 0)
+
+#define __raw_spin_unlock_wait(lock) \
+	do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
+
+static inline void __raw_spin_lock(raw_spinlock_t *lock)
+{
+	__asm__ __volatile__(
+	"\n1:\n\t"
+	"ldstub	[%0], %%g2\n\t"
+	"orcc	%%g2, 0x0, %%g0\n\t"
+	"bne,a	2f\n\t"
+	" ldub	[%0], %%g2\n\t"
+	".subsection	2\n"
+	"2:\n\t"
+	"orcc	%%g2, 0x0, %%g0\n\t"
+	"bne,a	2b\n\t"
+	" ldub	[%0], %%g2\n\t"
+	"b,a	1b\n\t"
+	".previous\n"
+	: /* no outputs */
+	: "r" (lock)
+	: "g2", "memory", "cc");
+}
+
+static inline int __raw_spin_trylock(raw_spinlock_t *lock)
+{
+	unsigned int result;
+	__asm__ __volatile__("ldstub [%1], %0"
+			     : "=r" (result)
+			     : "r" (lock)
+			     : "memory");
+	return (result == 0);
+}
+
+static inline void __raw_spin_unlock(raw_spinlock_t *lock)
+{
+	__asm__ __volatile__("stb %%g0, [%0]" : : "r" (lock) : "memory");
+}
+
+/* Read-write spinlocks, allowing multiple readers
+ * but only one writer.
+ *
+ * NOTE! it is quite common to have readers in interrupts
+ * but no interrupt writers. For those circumstances we
+ * can "mix" irq-safe locks - any writer needs to get a
+ * irq-safe write-lock, but readers can get non-irqsafe
+ * read-locks.
+ *
+ * XXX This might create some problems with my dual spinlock
+ * XXX scheme, deadlocks etc. -DaveM
+ *
+ * Sort of like atomic_t's on Sparc, but even more clever.
+ *
+ *	------------------------------------
+ *	| 24-bit counter           | wlock |  raw_rwlock_t
+ *	------------------------------------
+ *	 31                       8 7     0
+ *
+ * wlock signifies the one writer is in or somebody is updating
+ * counter. For a writer, if he successfully acquires the wlock,
+ * but counter is non-zero, he has to release the lock and wait,
+ * till both counter and wlock are zero.
+ *
+ * Unfortunately this scheme limits us to ~16,000,000 cpus.
+ */
+static inline void __read_lock(raw_rwlock_t *rw)
+{
+	register raw_rwlock_t *lp asm("g1");
+	lp = rw;
+	__asm__ __volatile__(
+	"mov	%%o7, %%g4\n\t"
+	"call	___rw_read_enter\n\t"
+	" ldstub	[%%g1 + 3], %%g2\n"
+	: /* no outputs */
+	: "r" (lp)
+	: "g2", "g4", "memory", "cc");
+}
+
+#define __raw_read_lock(lock) \
+do {	unsigned long flags; \
+	local_irq_save(flags); \
+	__read_lock(lock); \
+	local_irq_restore(flags); \
+} while(0)
+
+static inline void __read_unlock(raw_rwlock_t *rw)
+{
+	register raw_rwlock_t *lp asm("g1");
+	lp = rw;
+	__asm__ __volatile__(
+	"mov	%%o7, %%g4\n\t"
+	"call	___rw_read_exit\n\t"
+	" ldstub	[%%g1 + 3], %%g2\n"
+	: /* no outputs */
+	: "r" (lp)
+	: "g2", "g4", "memory", "cc");
+}
+
+#define __raw_read_unlock(lock) \
+do {	unsigned long flags; \
+	local_irq_save(flags); \
+	__read_unlock(lock); \
+	local_irq_restore(flags); \
+} while(0)
+
+static inline void __raw_write_lock(raw_rwlock_t *rw)
+{
+	register raw_rwlock_t *lp asm("g1");
+	lp = rw;
+	__asm__ __volatile__(
+	"mov	%%o7, %%g4\n\t"
+	"call	___rw_write_enter\n\t"
+	" ldstub	[%%g1 + 3], %%g2\n"
+	: /* no outputs */
+	: "r" (lp)
+	: "g2", "g4", "memory", "cc");
+	*(volatile __u32 *)&lp->lock = ~0U;
+}
+
+static inline int __raw_write_trylock(raw_rwlock_t *rw)
+{
+	unsigned int val;
+
+	__asm__ __volatile__("ldstub [%1 + 3], %0"
+			     : "=r" (val)
+			     : "r" (&rw->lock)
+			     : "memory");
+
+	if (val == 0) {
+		val = rw->lock & ~0xff;
+		if (val)
+			((volatile u8*)&rw->lock)[3] = 0;
+		else
+			*(volatile u32*)&rw->lock = ~0U;
+	}
+
+	return (val == 0);
+}
+
+static inline int __read_trylock(raw_rwlock_t *rw)
+{
+	register raw_rwlock_t *lp asm("g1");
+	register int res asm("o0");
+	lp = rw;
+	__asm__ __volatile__(
+	"mov	%%o7, %%g4\n\t"
+	"call	___rw_read_try\n\t"
+	" ldstub	[%%g1 + 3], %%g2\n"
+	: "=r" (res)
+	: "r" (lp)
+	: "g2", "g4", "memory", "cc");
+	return res;
+}
+
+#define __raw_read_trylock(lock) \
+({	unsigned long flags; \
+	int res; \
+	local_irq_save(flags); \
+	res = __read_trylock(lock); \
+	local_irq_restore(flags); \
+	res; \
+})
+
+#define __raw_write_unlock(rw)	do { (rw)->lock = 0; } while(0)
+
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+
+#define _raw_spin_relax(lock)	cpu_relax()
+#define _raw_read_relax(lock)	cpu_relax()
+#define _raw_write_relax(lock)	cpu_relax()
+
+#define __raw_read_can_lock(rw) (!((rw)->lock & 0xff))
+#define __raw_write_can_lock(rw) (!(rw)->lock)
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* __SPARC_SPINLOCK_H */
diff --git a/include/asm-sparc/spinlock_64.h b/include/asm-sparc/spinlock_64.h
new file mode 100644
index 0000000..0006fe9
--- /dev/null
+++ b/include/asm-sparc/spinlock_64.h
@@ -0,0 +1,250 @@
+/* spinlock.h: 64-bit Sparc spinlock support.
+ *
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef __SPARC64_SPINLOCK_H
+#define __SPARC64_SPINLOCK_H
+
+#include <linux/threads.h>	/* For NR_CPUS */
+
+#ifndef __ASSEMBLY__
+
+/* To get debugging spinlocks which detect and catch
+ * deadlock situations, set CONFIG_DEBUG_SPINLOCK
+ * and rebuild your kernel.
+ */
+
+/* All of these locking primitives are expected to work properly
+ * even in an RMO memory model, which currently is what the kernel
+ * runs in.
+ *
+ * There is another issue.  Because we play games to save cycles
+ * in the non-contention case, we need to be extra careful about
+ * branch targets into the "spinning" code.  They live in their
+ * own section, but the newer V9 branches have a shorter range
+ * than the traditional 32-bit sparc branch variants.  The rule
+ * is that the branches that go into and out of the spinner sections
+ * must be pre-V9 branches.
+ */
+
+#define __raw_spin_is_locked(lp)	((lp)->lock != 0)
+
+#define __raw_spin_unlock_wait(lp)	\
+	do {	rmb();			\
+	} while((lp)->lock)
+
+static inline void __raw_spin_lock(raw_spinlock_t *lock)
+{
+	unsigned long tmp;
+
+	__asm__ __volatile__(
+"1:	ldstub		[%1], %0\n"
+"	membar		#StoreLoad | #StoreStore\n"
+"	brnz,pn		%0, 2f\n"
+"	 nop\n"
+"	.subsection	2\n"
+"2:	ldub		[%1], %0\n"
+"	membar		#LoadLoad\n"
+"	brnz,pt		%0, 2b\n"
+"	 nop\n"
+"	ba,a,pt		%%xcc, 1b\n"
+"	.previous"
+	: "=&r" (tmp)
+	: "r" (lock)
+	: "memory");
+}
+
+static inline int __raw_spin_trylock(raw_spinlock_t *lock)
+{
+	unsigned long result;
+
+	__asm__ __volatile__(
+"	ldstub		[%1], %0\n"
+"	membar		#StoreLoad | #StoreStore"
+	: "=r" (result)
+	: "r" (lock)
+	: "memory");
+
+	return (result == 0UL);
+}
+
+static inline void __raw_spin_unlock(raw_spinlock_t *lock)
+{
+	__asm__ __volatile__(
+"	membar		#StoreStore | #LoadStore\n"
+"	stb		%%g0, [%0]"
+	: /* No outputs */
+	: "r" (lock)
+	: "memory");
+}
+
+static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags)
+{
+	unsigned long tmp1, tmp2;
+
+	__asm__ __volatile__(
+"1:	ldstub		[%2], %0\n"
+"	membar		#StoreLoad | #StoreStore\n"
+"	brnz,pn		%0, 2f\n"
+"	 nop\n"
+"	.subsection	2\n"
+"2:	rdpr		%%pil, %1\n"
+"	wrpr		%3, %%pil\n"
+"3:	ldub		[%2], %0\n"
+"	membar		#LoadLoad\n"
+"	brnz,pt		%0, 3b\n"
+"	 nop\n"
+"	ba,pt		%%xcc, 1b\n"
+"	 wrpr		%1, %%pil\n"
+"	.previous"
+	: "=&r" (tmp1), "=&r" (tmp2)
+	: "r"(lock), "r"(flags)
+	: "memory");
+}
+
+/* Multi-reader locks, these are much saner than the 32-bit Sparc ones... */
+
+static void inline __read_lock(raw_rwlock_t *lock)
+{
+	unsigned long tmp1, tmp2;
+
+	__asm__ __volatile__ (
+"1:	ldsw		[%2], %0\n"
+"	brlz,pn		%0, 2f\n"
+"4:	 add		%0, 1, %1\n"
+"	cas		[%2], %0, %1\n"
+"	cmp		%0, %1\n"
+"	membar		#StoreLoad | #StoreStore\n"
+"	bne,pn		%%icc, 1b\n"
+"	 nop\n"
+"	.subsection	2\n"
+"2:	ldsw		[%2], %0\n"
+"	membar		#LoadLoad\n"
+"	brlz,pt		%0, 2b\n"
+"	 nop\n"
+"	ba,a,pt		%%xcc, 4b\n"
+"	.previous"
+	: "=&r" (tmp1), "=&r" (tmp2)
+	: "r" (lock)
+	: "memory");
+}
+
+static int inline __read_trylock(raw_rwlock_t *lock)
+{
+	int tmp1, tmp2;
+
+	__asm__ __volatile__ (
+"1:	ldsw		[%2], %0\n"
+"	brlz,a,pn	%0, 2f\n"
+"	 mov		0, %0\n"
+"	add		%0, 1, %1\n"
+"	cas		[%2], %0, %1\n"
+"	cmp		%0, %1\n"
+"	membar		#StoreLoad | #StoreStore\n"
+"	bne,pn		%%icc, 1b\n"
+"	 mov		1, %0\n"
+"2:"
+	: "=&r" (tmp1), "=&r" (tmp2)
+	: "r" (lock)
+	: "memory");
+
+	return tmp1;
+}
+
+static void inline __read_unlock(raw_rwlock_t *lock)
+{
+	unsigned long tmp1, tmp2;
+
+	__asm__ __volatile__(
+"	membar	#StoreLoad | #LoadLoad\n"
+"1:	lduw	[%2], %0\n"
+"	sub	%0, 1, %1\n"
+"	cas	[%2], %0, %1\n"
+"	cmp	%0, %1\n"
+"	bne,pn	%%xcc, 1b\n"
+"	 nop"
+	: "=&r" (tmp1), "=&r" (tmp2)
+	: "r" (lock)
+	: "memory");
+}
+
+static void inline __write_lock(raw_rwlock_t *lock)
+{
+	unsigned long mask, tmp1, tmp2;
+
+	mask = 0x80000000UL;
+
+	__asm__ __volatile__(
+"1:	lduw		[%2], %0\n"
+"	brnz,pn		%0, 2f\n"
+"4:	 or		%0, %3, %1\n"
+"	cas		[%2], %0, %1\n"
+"	cmp		%0, %1\n"
+"	membar		#StoreLoad | #StoreStore\n"
+"	bne,pn		%%icc, 1b\n"
+"	 nop\n"
+"	.subsection	2\n"
+"2:	lduw		[%2], %0\n"
+"	membar		#LoadLoad\n"
+"	brnz,pt		%0, 2b\n"
+"	 nop\n"
+"	ba,a,pt		%%xcc, 4b\n"
+"	.previous"
+	: "=&r" (tmp1), "=&r" (tmp2)
+	: "r" (lock), "r" (mask)
+	: "memory");
+}
+
+static void inline __write_unlock(raw_rwlock_t *lock)
+{
+	__asm__ __volatile__(
+"	membar		#LoadStore | #StoreStore\n"
+"	stw		%%g0, [%0]"
+	: /* no outputs */
+	: "r" (lock)
+	: "memory");
+}
+
+static int inline __write_trylock(raw_rwlock_t *lock)
+{
+	unsigned long mask, tmp1, tmp2, result;
+
+	mask = 0x80000000UL;
+
+	__asm__ __volatile__(
+"	mov		0, %2\n"
+"1:	lduw		[%3], %0\n"
+"	brnz,pn		%0, 2f\n"
+"	 or		%0, %4, %1\n"
+"	cas		[%3], %0, %1\n"
+"	cmp		%0, %1\n"
+"	membar		#StoreLoad | #StoreStore\n"
+"	bne,pn		%%icc, 1b\n"
+"	 nop\n"
+"	mov		1, %2\n"
+"2:"
+	: "=&r" (tmp1), "=&r" (tmp2), "=&r" (result)
+	: "r" (lock), "r" (mask)
+	: "memory");
+
+	return result;
+}
+
+#define __raw_read_lock(p)	__read_lock(p)
+#define __raw_read_trylock(p)	__read_trylock(p)
+#define __raw_read_unlock(p)	__read_unlock(p)
+#define __raw_write_lock(p)	__write_lock(p)
+#define __raw_write_unlock(p)	__write_unlock(p)
+#define __raw_write_trylock(p)	__write_trylock(p)
+
+#define __raw_read_can_lock(rw)		(!((rw)->lock & 0x80000000UL))
+#define __raw_write_can_lock(rw)	(!(rw)->lock)
+
+#define _raw_spin_relax(lock)	cpu_relax()
+#define _raw_read_relax(lock)	cpu_relax()
+#define _raw_write_relax(lock)	cpu_relax()
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__SPARC64_SPINLOCK_H) */
diff --git a/include/asm-sparc/spinlock_types.h b/include/asm-sparc/spinlock_types.h
index 0a0fb11..37cbe01 100644
--- a/include/asm-sparc/spinlock_types.h
+++ b/include/asm-sparc/spinlock_types.h
@@ -6,7 +6,7 @@
 #endif
 
 typedef struct {
-	unsigned char lock;
+	volatile unsigned char lock;
 } raw_spinlock_t;
 
 #define __RAW_SPIN_LOCK_UNLOCKED	{ 0 }
diff --git a/include/asm-sparc/spitfire.h b/include/asm-sparc/spitfire.h
new file mode 100644
index 0000000..985ea7e
--- /dev/null
+++ b/include/asm-sparc/spitfire.h
@@ -0,0 +1,342 @@
+/* spitfire.h: SpitFire/BlackBird/Cheetah inline MMU operations.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
+ */
+
+#ifndef _SPARC64_SPITFIRE_H
+#define _SPARC64_SPITFIRE_H
+
+#include <asm/asi.h>
+
+/* The following register addresses are accessible via ASI_DMMU
+ * and ASI_IMMU, that is there is a distinct and unique copy of
+ * each these registers for each TLB.
+ */
+#define TSB_TAG_TARGET		0x0000000000000000 /* All chips				*/
+#define TLB_SFSR		0x0000000000000018 /* All chips				*/
+#define TSB_REG			0x0000000000000028 /* All chips				*/
+#define TLB_TAG_ACCESS		0x0000000000000030 /* All chips				*/
+#define VIRT_WATCHPOINT		0x0000000000000038 /* All chips				*/
+#define PHYS_WATCHPOINT		0x0000000000000040 /* All chips				*/
+#define TSB_EXTENSION_P		0x0000000000000048 /* Ultra-III and later		*/
+#define TSB_EXTENSION_S		0x0000000000000050 /* Ultra-III and later, D-TLB only	*/
+#define TSB_EXTENSION_N		0x0000000000000058 /* Ultra-III and later		*/
+#define TLB_TAG_ACCESS_EXT	0x0000000000000060 /* Ultra-III+ and later		*/
+
+/* These registers only exist as one entity, and are accessed
+ * via ASI_DMMU only.
+ */
+#define PRIMARY_CONTEXT		0x0000000000000008
+#define SECONDARY_CONTEXT	0x0000000000000010
+#define DMMU_SFAR		0x0000000000000020
+#define VIRT_WATCHPOINT		0x0000000000000038
+#define PHYS_WATCHPOINT		0x0000000000000040
+
+#define SPITFIRE_HIGHEST_LOCKED_TLBENT	(64 - 1)
+#define CHEETAH_HIGHEST_LOCKED_TLBENT	(16 - 1)
+
+#define L1DCACHE_SIZE		0x4000
+
+#define SUN4V_CHIP_INVALID	0x00
+#define SUN4V_CHIP_NIAGARA1	0x01
+#define SUN4V_CHIP_NIAGARA2	0x02
+#define SUN4V_CHIP_UNKNOWN	0xff
+
+#ifndef __ASSEMBLY__
+
+enum ultra_tlb_layout {
+	spitfire = 0,
+	cheetah = 1,
+	cheetah_plus = 2,
+	hypervisor = 3,
+};
+
+extern enum ultra_tlb_layout tlb_type;
+
+extern int sun4v_chip_type;
+
+extern int cheetah_pcache_forced_on;
+extern void cheetah_enable_pcache(void);
+
+#define sparc64_highest_locked_tlbent()	\
+	(tlb_type == spitfire ? \
+	 SPITFIRE_HIGHEST_LOCKED_TLBENT : \
+	 CHEETAH_HIGHEST_LOCKED_TLBENT)
+
+extern int num_kernel_image_mappings;
+
+/* The data cache is write through, so this just invalidates the
+ * specified line.
+ */
+static inline void spitfire_put_dcache_tag(unsigned long addr, unsigned long tag)
+{
+	__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
+			     "membar	#Sync"
+			     : /* No outputs */
+			     : "r" (tag), "r" (addr), "i" (ASI_DCACHE_TAG));
+}
+
+/* The instruction cache lines are flushed with this, but note that
+ * this does not flush the pipeline.  It is possible for a line to
+ * get flushed but stale instructions to still be in the pipeline,
+ * a flush instruction (to any address) is sufficient to handle
+ * this issue after the line is invalidated.
+ */
+static inline void spitfire_put_icache_tag(unsigned long addr, unsigned long tag)
+{
+	__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
+			     "membar	#Sync"
+			     : /* No outputs */
+			     : "r" (tag), "r" (addr), "i" (ASI_IC_TAG));
+}
+
+static inline unsigned long spitfire_get_dtlb_data(int entry)
+{
+	unsigned long data;
+
+	__asm__ __volatile__("ldxa	[%1] %2, %0"
+			     : "=r" (data)
+			     : "r" (entry << 3), "i" (ASI_DTLB_DATA_ACCESS));
+
+	/* Clear TTE diag bits. */
+	data &= ~0x0003fe0000000000UL;
+
+	return data;
+}
+
+static inline unsigned long spitfire_get_dtlb_tag(int entry)
+{
+	unsigned long tag;
+
+	__asm__ __volatile__("ldxa	[%1] %2, %0"
+			     : "=r" (tag)
+			     : "r" (entry << 3), "i" (ASI_DTLB_TAG_READ));
+	return tag;
+}
+
+static inline void spitfire_put_dtlb_data(int entry, unsigned long data)
+{
+	__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
+			     "membar	#Sync"
+			     : /* No outputs */
+			     : "r" (data), "r" (entry << 3),
+			       "i" (ASI_DTLB_DATA_ACCESS));
+}
+
+static inline unsigned long spitfire_get_itlb_data(int entry)
+{
+	unsigned long data;
+
+	__asm__ __volatile__("ldxa	[%1] %2, %0"
+			     : "=r" (data)
+			     : "r" (entry << 3), "i" (ASI_ITLB_DATA_ACCESS));
+
+	/* Clear TTE diag bits. */
+	data &= ~0x0003fe0000000000UL;
+
+	return data;
+}
+
+static inline unsigned long spitfire_get_itlb_tag(int entry)
+{
+	unsigned long tag;
+
+	__asm__ __volatile__("ldxa	[%1] %2, %0"
+			     : "=r" (tag)
+			     : "r" (entry << 3), "i" (ASI_ITLB_TAG_READ));
+	return tag;
+}
+
+static inline void spitfire_put_itlb_data(int entry, unsigned long data)
+{
+	__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
+			     "membar	#Sync"
+			     : /* No outputs */
+			     : "r" (data), "r" (entry << 3),
+			       "i" (ASI_ITLB_DATA_ACCESS));
+}
+
+static inline void spitfire_flush_dtlb_nucleus_page(unsigned long page)
+{
+	__asm__ __volatile__("stxa	%%g0, [%0] %1\n\t"
+			     "membar	#Sync"
+			     : /* No outputs */
+			     : "r" (page | 0x20), "i" (ASI_DMMU_DEMAP));
+}
+
+static inline void spitfire_flush_itlb_nucleus_page(unsigned long page)
+{
+	__asm__ __volatile__("stxa	%%g0, [%0] %1\n\t"
+			     "membar	#Sync"
+			     : /* No outputs */
+			     : "r" (page | 0x20), "i" (ASI_IMMU_DEMAP));
+}
+
+/* Cheetah has "all non-locked" tlb flushes. */
+static inline void cheetah_flush_dtlb_all(void)
+{
+	__asm__ __volatile__("stxa	%%g0, [%0] %1\n\t"
+			     "membar	#Sync"
+			     : /* No outputs */
+			     : "r" (0x80), "i" (ASI_DMMU_DEMAP));
+}
+
+static inline void cheetah_flush_itlb_all(void)
+{
+	__asm__ __volatile__("stxa	%%g0, [%0] %1\n\t"
+			     "membar	#Sync"
+			     : /* No outputs */
+			     : "r" (0x80), "i" (ASI_IMMU_DEMAP));
+}
+
+/* Cheetah has a 4-tlb layout so direct access is a bit different.
+ * The first two TLBs are fully assosciative, hold 16 entries, and are
+ * used only for locked and >8K sized translations.  One exists for
+ * data accesses and one for instruction accesses.
+ *
+ * The third TLB is for data accesses to 8K non-locked translations, is
+ * 2 way assosciative, and holds 512 entries.  The fourth TLB is for
+ * instruction accesses to 8K non-locked translations, is 2 way
+ * assosciative, and holds 128 entries.
+ *
+ * Cheetah has some bug where bogus data can be returned from
+ * ASI_{D,I}TLB_DATA_ACCESS loads, doing the load twice fixes
+ * the problem for me. -DaveM
+ */
+static inline unsigned long cheetah_get_ldtlb_data(int entry)
+{
+	unsigned long data;
+
+	__asm__ __volatile__("ldxa	[%1] %2, %%g0\n\t"
+			     "ldxa	[%1] %2, %0"
+			     : "=r" (data)
+			     : "r" ((0 << 16) | (entry << 3)),
+			     "i" (ASI_DTLB_DATA_ACCESS));
+
+	return data;
+}
+
+static inline unsigned long cheetah_get_litlb_data(int entry)
+{
+	unsigned long data;
+
+	__asm__ __volatile__("ldxa	[%1] %2, %%g0\n\t"
+			     "ldxa	[%1] %2, %0"
+			     : "=r" (data)
+			     : "r" ((0 << 16) | (entry << 3)),
+			     "i" (ASI_ITLB_DATA_ACCESS));
+
+	return data;
+}
+
+static inline unsigned long cheetah_get_ldtlb_tag(int entry)
+{
+	unsigned long tag;
+
+	__asm__ __volatile__("ldxa	[%1] %2, %0"
+			     : "=r" (tag)
+			     : "r" ((0 << 16) | (entry << 3)),
+			     "i" (ASI_DTLB_TAG_READ));
+
+	return tag;
+}
+
+static inline unsigned long cheetah_get_litlb_tag(int entry)
+{
+	unsigned long tag;
+
+	__asm__ __volatile__("ldxa	[%1] %2, %0"
+			     : "=r" (tag)
+			     : "r" ((0 << 16) | (entry << 3)),
+			     "i" (ASI_ITLB_TAG_READ));
+
+	return tag;
+}
+
+static inline void cheetah_put_ldtlb_data(int entry, unsigned long data)
+{
+	__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
+			     "membar	#Sync"
+			     : /* No outputs */
+			     : "r" (data),
+			       "r" ((0 << 16) | (entry << 3)),
+			       "i" (ASI_DTLB_DATA_ACCESS));
+}
+
+static inline void cheetah_put_litlb_data(int entry, unsigned long data)
+{
+	__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
+			     "membar	#Sync"
+			     : /* No outputs */
+			     : "r" (data),
+			       "r" ((0 << 16) | (entry << 3)),
+			       "i" (ASI_ITLB_DATA_ACCESS));
+}
+
+static inline unsigned long cheetah_get_dtlb_data(int entry, int tlb)
+{
+	unsigned long data;
+
+	__asm__ __volatile__("ldxa	[%1] %2, %%g0\n\t"
+			     "ldxa	[%1] %2, %0"
+			     : "=r" (data)
+			     : "r" ((tlb << 16) | (entry << 3)), "i" (ASI_DTLB_DATA_ACCESS));
+
+	return data;
+}
+
+static inline unsigned long cheetah_get_dtlb_tag(int entry, int tlb)
+{
+	unsigned long tag;
+
+	__asm__ __volatile__("ldxa	[%1] %2, %0"
+			     : "=r" (tag)
+			     : "r" ((tlb << 16) | (entry << 3)), "i" (ASI_DTLB_TAG_READ));
+	return tag;
+}
+
+static inline void cheetah_put_dtlb_data(int entry, unsigned long data, int tlb)
+{
+	__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
+			     "membar	#Sync"
+			     : /* No outputs */
+			     : "r" (data),
+			       "r" ((tlb << 16) | (entry << 3)),
+			       "i" (ASI_DTLB_DATA_ACCESS));
+}
+
+static inline unsigned long cheetah_get_itlb_data(int entry)
+{
+	unsigned long data;
+
+	__asm__ __volatile__("ldxa	[%1] %2, %%g0\n\t"
+			     "ldxa	[%1] %2, %0"
+			     : "=r" (data)
+			     : "r" ((2 << 16) | (entry << 3)),
+                               "i" (ASI_ITLB_DATA_ACCESS));
+
+	return data;
+}
+
+static inline unsigned long cheetah_get_itlb_tag(int entry)
+{
+	unsigned long tag;
+
+	__asm__ __volatile__("ldxa	[%1] %2, %0"
+			     : "=r" (tag)
+			     : "r" ((2 << 16) | (entry << 3)), "i" (ASI_ITLB_TAG_READ));
+	return tag;
+}
+
+static inline void cheetah_put_itlb_data(int entry, unsigned long data)
+{
+	__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
+			     "membar	#Sync"
+			     : /* No outputs */
+			     : "r" (data), "r" ((2 << 16) | (entry << 3)),
+			       "i" (ASI_ITLB_DATA_ACCESS));
+}
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(_SPARC64_SPITFIRE_H) */
diff --git a/include/asm-sparc/sstate.h b/include/asm-sparc/sstate.h
new file mode 100644
index 0000000..a7c35db
--- /dev/null
+++ b/include/asm-sparc/sstate.h
@@ -0,0 +1,13 @@
+#ifndef _SPARC64_SSTATE_H
+#define _SPARC64_SSTATE_H
+
+extern void sstate_booting(void);
+extern void sstate_running(void);
+extern void sstate_halt(void);
+extern void sstate_poweroff(void);
+extern void sstate_panic(void);
+extern void sstate_reboot(void);
+
+extern void sun4v_sstate_init(void);
+
+#endif /* _SPARC64_SSTATE_H */
diff --git a/include/asm-sparc/stacktrace.h b/include/asm-sparc/stacktrace.h
new file mode 100644
index 0000000..6cee39a
--- /dev/null
+++ b/include/asm-sparc/stacktrace.h
@@ -0,0 +1,6 @@
+#ifndef _SPARC64_STACKTRACE_H
+#define _SPARC64_STACKTRACE_H
+
+extern void stack_trace_flush(void);
+
+#endif /* _SPARC64_STACKTRACE_H */
diff --git a/include/asm-sparc/starfire.h b/include/asm-sparc/starfire.h
new file mode 100644
index 0000000..07bafd3
--- /dev/null
+++ b/include/asm-sparc/starfire.h
@@ -0,0 +1,21 @@
+/*
+ * starfire.h: Group all starfire specific code together.
+ *
+ * Copyright (C) 2000 Anton Blanchard (anton@samba.org)
+ */
+
+#ifndef _SPARC64_STARFIRE_H
+#define _SPARC64_STARFIRE_H
+
+#ifndef __ASSEMBLY__
+
+extern int this_is_starfire;
+
+extern void check_if_starfire(void);
+extern void starfire_cpu_setup(void);
+extern int starfire_hard_smp_processor_id(void);
+extern void starfire_hookup(int);
+extern unsigned int starfire_translate(unsigned long imap, unsigned int upaid);
+
+#endif
+#endif
diff --git a/include/asm-sparc/stat.h b/include/asm-sparc/stat.h
index 2299e1d5..9fdcaf8 100644
--- a/include/asm-sparc/stat.h
+++ b/include/asm-sparc/stat.h
@@ -1,76 +1,8 @@
-#ifndef _SPARC_STAT_H
-#define _SPARC_STAT_H
-
-#include <linux/types.h>
-
-struct __old_kernel_stat {
-	unsigned short st_dev;
-	unsigned short st_ino;
-	unsigned short st_mode;
-	unsigned short st_nlink;
-	unsigned short st_uid;
-	unsigned short st_gid;
-	unsigned short st_rdev;
-	unsigned long  st_size;
-	unsigned long  st_atime;
-	unsigned long  st_mtime;
-	unsigned long  st_ctime;
-};
-
-struct stat {
-	unsigned short	st_dev;
-	unsigned long	st_ino;
-	unsigned short	st_mode;
-	short		st_nlink;
-	unsigned short	st_uid;
-	unsigned short	st_gid;
-	unsigned short	st_rdev;
-	long		st_size;
-	long		st_atime;
-	unsigned long	st_atime_nsec;
-	long		st_mtime;
-	unsigned long	st_mtime_nsec;
-	long		st_ctime;
-	unsigned long	st_ctime_nsec;
-	long		st_blksize;
-	long		st_blocks;
-	unsigned long	__unused4[2];
-};
-
-#define STAT_HAVE_NSEC 1
-
-struct stat64 {
-	unsigned long long st_dev;
-
-	unsigned long long st_ino;
-
-	unsigned int	st_mode;
-	unsigned int	st_nlink;
-
-	unsigned int	st_uid;
-	unsigned int	st_gid;
-
-	unsigned long long st_rdev;
-
-	unsigned char	__pad3[8];
-
-	long long	st_size;
-	unsigned int	st_blksize;
-
-	unsigned char	__pad4[8];
-	unsigned int	st_blocks;
-
-	unsigned int	st_atime;
-	unsigned int	st_atime_nsec;
-
-	unsigned int	st_mtime;
-	unsigned int	st_mtime_nsec;
-
-	unsigned int	st_ctime;
-	unsigned int	st_ctime_nsec;
-
-	unsigned int	__unused4;
-	unsigned int	__unused5;
-};
-
+#ifndef ___ASM_SPARC_STAT_H
+#define ___ASM_SPARC_STAT_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/stat_64.h>
+#else
+#include <asm-sparc/stat_32.h>
+#endif
 #endif
diff --git a/include/asm-sparc/stat_32.h b/include/asm-sparc/stat_32.h
new file mode 100644
index 0000000..2299e1d5
--- /dev/null
+++ b/include/asm-sparc/stat_32.h
@@ -0,0 +1,76 @@
+#ifndef _SPARC_STAT_H
+#define _SPARC_STAT_H
+
+#include <linux/types.h>
+
+struct __old_kernel_stat {
+	unsigned short st_dev;
+	unsigned short st_ino;
+	unsigned short st_mode;
+	unsigned short st_nlink;
+	unsigned short st_uid;
+	unsigned short st_gid;
+	unsigned short st_rdev;
+	unsigned long  st_size;
+	unsigned long  st_atime;
+	unsigned long  st_mtime;
+	unsigned long  st_ctime;
+};
+
+struct stat {
+	unsigned short	st_dev;
+	unsigned long	st_ino;
+	unsigned short	st_mode;
+	short		st_nlink;
+	unsigned short	st_uid;
+	unsigned short	st_gid;
+	unsigned short	st_rdev;
+	long		st_size;
+	long		st_atime;
+	unsigned long	st_atime_nsec;
+	long		st_mtime;
+	unsigned long	st_mtime_nsec;
+	long		st_ctime;
+	unsigned long	st_ctime_nsec;
+	long		st_blksize;
+	long		st_blocks;
+	unsigned long	__unused4[2];
+};
+
+#define STAT_HAVE_NSEC 1
+
+struct stat64 {
+	unsigned long long st_dev;
+
+	unsigned long long st_ino;
+
+	unsigned int	st_mode;
+	unsigned int	st_nlink;
+
+	unsigned int	st_uid;
+	unsigned int	st_gid;
+
+	unsigned long long st_rdev;
+
+	unsigned char	__pad3[8];
+
+	long long	st_size;
+	unsigned int	st_blksize;
+
+	unsigned char	__pad4[8];
+	unsigned int	st_blocks;
+
+	unsigned int	st_atime;
+	unsigned int	st_atime_nsec;
+
+	unsigned int	st_mtime;
+	unsigned int	st_mtime_nsec;
+
+	unsigned int	st_ctime;
+	unsigned int	st_ctime_nsec;
+
+	unsigned int	__unused4;
+	unsigned int	__unused5;
+};
+
+#endif
diff --git a/include/asm-sparc/stat_64.h b/include/asm-sparc/stat_64.h
new file mode 100644
index 0000000..9650fde
--- /dev/null
+++ b/include/asm-sparc/stat_64.h
@@ -0,0 +1,47 @@
+#ifndef _SPARC64_STAT_H
+#define _SPARC64_STAT_H
+
+#include <linux/types.h>
+
+struct stat {
+	unsigned   st_dev;
+	ino_t   st_ino;
+	mode_t  st_mode;
+	short   st_nlink;
+	uid_t   st_uid;
+	gid_t   st_gid;
+	unsigned   st_rdev;
+	off_t   st_size;
+	time_t  st_atime;
+	time_t  st_mtime;
+	time_t  st_ctime;
+	off_t   st_blksize;
+	off_t   st_blocks;
+	unsigned long  __unused4[2];
+};
+
+struct stat64 {
+	unsigned long	st_dev;
+	unsigned long	st_ino;
+	unsigned long	st_nlink;
+
+	unsigned int	st_mode;
+	unsigned int	st_uid;
+	unsigned int	st_gid;
+	unsigned int	__pad0;
+
+	unsigned long	st_rdev;
+	long		st_size;
+	long		st_blksize;
+	long		st_blocks;
+
+	unsigned long	st_atime;
+	unsigned long	st_atime_nsec;
+	unsigned long	st_mtime;
+	unsigned long	st_mtime_nsec;
+	unsigned long	st_ctime;
+	unsigned long	st_ctime_nsec;
+	long		__unused[3];
+};
+
+#endif
diff --git a/include/asm-sparc/statfs.h b/include/asm-sparc/statfs.h
index 304520f..a70cc52 100644
--- a/include/asm-sparc/statfs.h
+++ b/include/asm-sparc/statfs.h
@@ -1,6 +1,8 @@
-#ifndef _SPARC_STATFS_H
-#define _SPARC_STATFS_H
-
-#include <asm-generic/statfs.h>
-
+#ifndef ___ASM_SPARC_STATFS_H
+#define ___ASM_SPARC_STATFS_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/statfs_64.h>
+#else
+#include <asm-sparc/statfs_32.h>
+#endif
 #endif
diff --git a/include/asm-sparc/statfs_32.h b/include/asm-sparc/statfs_32.h
new file mode 100644
index 0000000..304520f
--- /dev/null
+++ b/include/asm-sparc/statfs_32.h
@@ -0,0 +1,6 @@
+#ifndef _SPARC_STATFS_H
+#define _SPARC_STATFS_H
+
+#include <asm-generic/statfs.h>
+
+#endif
diff --git a/include/asm-sparc/statfs_64.h b/include/asm-sparc/statfs_64.h
new file mode 100644
index 0000000..79b3c89
--- /dev/null
+++ b/include/asm-sparc/statfs_64.h
@@ -0,0 +1,54 @@
+#ifndef _SPARC64_STATFS_H
+#define _SPARC64_STATFS_H
+
+#ifndef __KERNEL_STRICT_NAMES
+
+#include <linux/types.h>
+
+typedef __kernel_fsid_t	fsid_t;
+
+#endif
+
+struct statfs {
+	long f_type;
+	long f_bsize;
+	long f_blocks;
+	long f_bfree;
+	long f_bavail;
+	long f_files;
+	long f_ffree;
+	__kernel_fsid_t f_fsid;
+	long f_namelen;
+	long f_frsize;
+	long f_spare[5];
+};
+
+struct statfs64 {
+	long f_type;
+	long f_bsize;
+	long f_blocks;
+	long f_bfree;
+	long f_bavail;
+	long f_files;
+	long f_ffree;
+	__kernel_fsid_t f_fsid;
+	long f_namelen;
+	long f_frsize;
+	long f_spare[5];
+};
+
+struct compat_statfs64 {
+	__u32 f_type;
+	__u32 f_bsize;
+	__u64 f_blocks;
+	__u64 f_bfree;
+	__u64 f_bavail;
+	__u64 f_files;
+	__u64 f_ffree;
+	__kernel_fsid_t f_fsid;
+	__u32 f_namelen;
+	__u32 f_frsize;
+	__u32 f_spare[5];
+};
+
+#endif
diff --git a/include/asm-sparc/string.h b/include/asm-sparc/string.h
index 8d7c0dd..14c04c7 100644
--- a/include/asm-sparc/string.h
+++ b/include/asm-sparc/string.h
@@ -1,205 +1,8 @@
-/*
- * string.h: External definitions for optimized assembly string
- *           routines for the Linux Kernel.
- *
- * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- */
-
-#ifndef __SPARC_STRING_H__
-#define __SPARC_STRING_H__
-
-#include <asm/page.h>
-
-/* Really, userland/ksyms should not see any of this stuff. */
-
-#ifdef __KERNEL__
-
-extern void __memmove(void *,const void *,__kernel_size_t);
-extern __kernel_size_t __memcpy(void *,const void *,__kernel_size_t);
-extern __kernel_size_t __memset(void *,int,__kernel_size_t);
-
-#ifndef EXPORT_SYMTAB_STROPS
-
-/* First the mem*() things. */
-#define __HAVE_ARCH_MEMMOVE
-#undef memmove
-#define memmove(_to, _from, _n) \
-({ \
-	void *_t = (_to); \
-	__memmove(_t, (_from), (_n)); \
-	_t; \
-})
-
-#define __HAVE_ARCH_MEMCPY
-
-static inline void *__constant_memcpy(void *to, const void *from, __kernel_size_t n)
-{
-	extern void __copy_1page(void *, const void *);
-
-	if(n <= 32) {
-		__builtin_memcpy(to, from, n);
-	} else if (((unsigned int) to & 7) != 0) {
-		/* Destination is not aligned on the double-word boundary */
-		__memcpy(to, from, n);
-	} else {
-		switch(n) {
-		case PAGE_SIZE:
-			__copy_1page(to, from);
-			break;
-		default:
-			__memcpy(to, from, n);
-			break;
-		}
-	}
-	return to;
-}
-
-static inline void *__nonconstant_memcpy(void *to, const void *from, __kernel_size_t n)
-{
-	__memcpy(to, from, n);
-	return to;
-}
-
-#undef memcpy
-#define memcpy(t, f, n) \
-(__builtin_constant_p(n) ? \
- __constant_memcpy((t),(f),(n)) : \
- __nonconstant_memcpy((t),(f),(n)))
-
-#define __HAVE_ARCH_MEMSET
-
-static inline void *__constant_c_and_count_memset(void *s, char c, __kernel_size_t count)
-{
-	extern void bzero_1page(void *);
-	extern __kernel_size_t __bzero(void *, __kernel_size_t);
-
-	if(!c) {
-		if(count == PAGE_SIZE)
-			bzero_1page(s);
-		else
-			__bzero(s, count);
-	} else {
-		__memset(s, c, count);
-	}
-	return s;
-}
-
-static inline void *__constant_c_memset(void *s, char c, __kernel_size_t count)
-{
-	extern __kernel_size_t __bzero(void *, __kernel_size_t);
-
-	if(!c)
-		__bzero(s, count);
-	else
-		__memset(s, c, count);
-	return s;
-}
-
-static inline void *__nonconstant_memset(void *s, char c, __kernel_size_t count)
-{
-	__memset(s, c, count);
-	return s;
-}
-
-#undef memset
-#define memset(s, c, count) \
-(__builtin_constant_p(c) ? (__builtin_constant_p(count) ? \
-                            __constant_c_and_count_memset((s), (c), (count)) : \
-                            __constant_c_memset((s), (c), (count))) \
-                          : __nonconstant_memset((s), (c), (count)))
-
-#define __HAVE_ARCH_MEMSCAN
-
-#undef memscan
-#define memscan(__arg0, __char, __arg2)						\
-({										\
-	extern void *__memscan_zero(void *, size_t);				\
-	extern void *__memscan_generic(void *, int, size_t);			\
-	void *__retval, *__addr = (__arg0);					\
-	size_t __size = (__arg2);						\
-										\
-	if(__builtin_constant_p(__char) && !(__char))				\
-		__retval = __memscan_zero(__addr, __size);			\
-	else									\
-		__retval = __memscan_generic(__addr, (__char), __size);		\
-										\
-	__retval;								\
-})
-
-#define __HAVE_ARCH_MEMCMP
-extern int memcmp(const void *,const void *,__kernel_size_t);
-
-/* Now the str*() stuff... */
-#define __HAVE_ARCH_STRLEN
-extern __kernel_size_t strlen(const char *);
-
-#define __HAVE_ARCH_STRNCMP
-
-extern int __strncmp(const char *, const char *, __kernel_size_t);
-
-static inline int __constant_strncmp(const char *src, const char *dest, __kernel_size_t count)
-{
-	register int retval;
-	switch(count) {
-	case 0: return 0;
-	case 1: return (src[0] - dest[0]);
-	case 2: retval = (src[0] - dest[0]);
-		if(!retval && src[0])
-		  retval = (src[1] - dest[1]);
-		return retval;
-	case 3: retval = (src[0] - dest[0]);
-		if(!retval && src[0]) {
-		  retval = (src[1] - dest[1]);
-		  if(!retval && src[1])
-		    retval = (src[2] - dest[2]);
-		}
-		return retval;
-	case 4: retval = (src[0] - dest[0]);
-		if(!retval && src[0]) {
-		  retval = (src[1] - dest[1]);
-		  if(!retval && src[1]) {
-		    retval = (src[2] - dest[2]);
-		    if (!retval && src[2])
-		      retval = (src[3] - dest[3]);
-		  }
-		}
-		return retval;
-	case 5: retval = (src[0] - dest[0]);
-		if(!retval && src[0]) {
-		  retval = (src[1] - dest[1]);
-		  if(!retval && src[1]) {
-		    retval = (src[2] - dest[2]);
-		    if (!retval && src[2]) {
-		      retval = (src[3] - dest[3]);
-		      if (!retval && src[3])
-		        retval = (src[4] - dest[4]);
-		    }
-		  }
-		}
-		return retval;
-	default:
-		retval = (src[0] - dest[0]);
-		if(!retval && src[0]) {
-		  retval = (src[1] - dest[1]);
-		  if(!retval && src[1]) {
-		    retval = (src[2] - dest[2]);
-		    if(!retval && src[2])
-		      retval = __strncmp(src+3,dest+3,count-3);
-		  }
-		}
-		return retval;
-	}
-}
-
-#undef strncmp
-#define strncmp(__arg0, __arg1, __arg2)	\
-(__builtin_constant_p(__arg2) ?	\
- __constant_strncmp(__arg0, __arg1, __arg2) : \
- __strncmp(__arg0, __arg1, __arg2))
- 
-#endif /* !EXPORT_SYMTAB_STROPS */
-
-#endif /* __KERNEL__ */
-
-#endif /* !(__SPARC_STRING_H__) */
+#ifndef ___ASM_SPARC_STRING_H
+#define ___ASM_SPARC_STRING_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/string_64.h>
+#else
+#include <asm-sparc/string_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/string_32.h b/include/asm-sparc/string_32.h
new file mode 100644
index 0000000..6c5fddb
--- /dev/null
+++ b/include/asm-sparc/string_32.h
@@ -0,0 +1,205 @@
+/*
+ * string.h: External definitions for optimized assembly string
+ *           routines for the Linux Kernel.
+ *
+ * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#ifndef __SPARC_STRING_H__
+#define __SPARC_STRING_H__
+
+#include <asm/page.h>
+
+/* Really, userland/ksyms should not see any of this stuff. */
+
+#ifdef __KERNEL__
+
+extern void __memmove(void *,const void *,__kernel_size_t);
+extern __kernel_size_t __memcpy(void *,const void *,__kernel_size_t);
+extern __kernel_size_t __memset(void *,int,__kernel_size_t);
+
+#ifndef EXPORT_SYMTAB_STROPS
+
+/* First the mem*() things. */
+#define __HAVE_ARCH_MEMMOVE
+#undef memmove
+#define memmove(_to, _from, _n) \
+({ \
+	void *_t = (_to); \
+	__memmove(_t, (_from), (_n)); \
+	_t; \
+})
+
+#define __HAVE_ARCH_MEMCPY
+
+static inline void *__constant_memcpy(void *to, const void *from, __kernel_size_t n)
+{
+	extern void __copy_1page(void *, const void *);
+
+	if(n <= 32) {
+		__builtin_memcpy(to, from, n);
+	} else if (((unsigned int) to & 7) != 0) {
+		/* Destination is not aligned on the double-word boundary */
+		__memcpy(to, from, n);
+	} else {
+		switch(n) {
+		case PAGE_SIZE:
+			__copy_1page(to, from);
+			break;
+		default:
+			__memcpy(to, from, n);
+			break;
+		}
+	}
+	return to;
+}
+
+static inline void *__nonconstant_memcpy(void *to, const void *from, __kernel_size_t n)
+{
+	__memcpy(to, from, n);
+	return to;
+}
+
+#undef memcpy
+#define memcpy(t, f, n) \
+(__builtin_constant_p(n) ? \
+ __constant_memcpy((t),(f),(n)) : \
+ __nonconstant_memcpy((t),(f),(n)))
+
+#define __HAVE_ARCH_MEMSET
+
+static inline void *__constant_c_and_count_memset(void *s, char c, __kernel_size_t count)
+{
+	extern void bzero_1page(void *);
+	extern __kernel_size_t __bzero(void *, __kernel_size_t);
+
+	if(!c) {
+		if(count == PAGE_SIZE)
+			bzero_1page(s);
+		else
+			__bzero(s, count);
+	} else {
+		__memset(s, c, count);
+	}
+	return s;
+}
+
+static inline void *__constant_c_memset(void *s, char c, __kernel_size_t count)
+{
+	extern __kernel_size_t __bzero(void *, __kernel_size_t);
+
+	if(!c)
+		__bzero(s, count);
+	else
+		__memset(s, c, count);
+	return s;
+}
+
+static inline void *__nonconstant_memset(void *s, char c, __kernel_size_t count)
+{
+	__memset(s, c, count);
+	return s;
+}
+
+#undef memset
+#define memset(s, c, count) \
+(__builtin_constant_p(c) ? (__builtin_constant_p(count) ? \
+                            __constant_c_and_count_memset((s), (c), (count)) : \
+                            __constant_c_memset((s), (c), (count))) \
+                          : __nonconstant_memset((s), (c), (count)))
+
+#define __HAVE_ARCH_MEMSCAN
+
+#undef memscan
+#define memscan(__arg0, __char, __arg2)						\
+({										\
+	extern void *__memscan_zero(void *, size_t);				\
+	extern void *__memscan_generic(void *, int, size_t);			\
+	void *__retval, *__addr = (__arg0);					\
+	size_t __size = (__arg2);						\
+										\
+	if(__builtin_constant_p(__char) && !(__char))				\
+		__retval = __memscan_zero(__addr, __size);			\
+	else									\
+		__retval = __memscan_generic(__addr, (__char), __size);		\
+										\
+	__retval;								\
+})
+
+#define __HAVE_ARCH_MEMCMP
+extern int memcmp(const void *,const void *,__kernel_size_t);
+
+/* Now the str*() stuff... */
+#define __HAVE_ARCH_STRLEN
+extern __kernel_size_t strlen(const char *);
+
+#define __HAVE_ARCH_STRNCMP
+
+extern int __strncmp(const char *, const char *, __kernel_size_t);
+
+static inline int __constant_strncmp(const char *src, const char *dest, __kernel_size_t count)
+{
+	register int retval;
+	switch(count) {
+	case 0: return 0;
+	case 1: return (src[0] - dest[0]);
+	case 2: retval = (src[0] - dest[0]);
+		if(!retval && src[0])
+		  retval = (src[1] - dest[1]);
+		return retval;
+	case 3: retval = (src[0] - dest[0]);
+		if(!retval && src[0]) {
+		  retval = (src[1] - dest[1]);
+		  if(!retval && src[1])
+		    retval = (src[2] - dest[2]);
+		}
+		return retval;
+	case 4: retval = (src[0] - dest[0]);
+		if(!retval && src[0]) {
+		  retval = (src[1] - dest[1]);
+		  if(!retval && src[1]) {
+		    retval = (src[2] - dest[2]);
+		    if (!retval && src[2])
+		      retval = (src[3] - dest[3]);
+		  }
+		}
+		return retval;
+	case 5: retval = (src[0] - dest[0]);
+		if(!retval && src[0]) {
+		  retval = (src[1] - dest[1]);
+		  if(!retval && src[1]) {
+		    retval = (src[2] - dest[2]);
+		    if (!retval && src[2]) {
+		      retval = (src[3] - dest[3]);
+		      if (!retval && src[3])
+		        retval = (src[4] - dest[4]);
+		    }
+		  }
+		}
+		return retval;
+	default:
+		retval = (src[0] - dest[0]);
+		if(!retval && src[0]) {
+		  retval = (src[1] - dest[1]);
+		  if(!retval && src[1]) {
+		    retval = (src[2] - dest[2]);
+		    if(!retval && src[2])
+		      retval = __strncmp(src+3,dest+3,count-3);
+		  }
+		}
+		return retval;
+	}
+}
+
+#undef strncmp
+#define strncmp(__arg0, __arg1, __arg2)	\
+(__builtin_constant_p(__arg2) ?	\
+ __constant_strncmp(__arg0, __arg1, __arg2) : \
+ __strncmp(__arg0, __arg1, __arg2))
+
+#endif /* !EXPORT_SYMTAB_STROPS */
+
+#endif /* __KERNEL__ */
+
+#endif /* !(__SPARC_STRING_H__) */
diff --git a/include/asm-sparc/string_64.h b/include/asm-sparc/string_64.h
new file mode 100644
index 0000000..43161f2
--- /dev/null
+++ b/include/asm-sparc/string_64.h
@@ -0,0 +1,83 @@
+/*
+ * string.h: External definitions for optimized assembly string
+ *           routines for the Linux Kernel.
+ *
+ * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996,1997,1999 Jakub Jelinek (jakub@redhat.com)
+ */
+
+#ifndef __SPARC64_STRING_H__
+#define __SPARC64_STRING_H__
+
+/* Really, userland/ksyms should not see any of this stuff. */
+
+#ifdef __KERNEL__
+
+#include <asm/asi.h>
+
+extern void *__memset(void *,int,__kernel_size_t);
+
+#ifndef EXPORT_SYMTAB_STROPS
+
+/* First the mem*() things. */
+#define __HAVE_ARCH_MEMMOVE
+extern void *memmove(void *, const void *, __kernel_size_t);
+
+#define __HAVE_ARCH_MEMCPY
+extern void *memcpy(void *, const void *, __kernel_size_t);
+
+#define __HAVE_ARCH_MEMSET
+extern void *__builtin_memset(void *,int,__kernel_size_t);
+
+static inline void *__constant_memset(void *s, int c, __kernel_size_t count)
+{
+	extern __kernel_size_t __bzero(void *, __kernel_size_t);
+
+	if (!c) {
+		__bzero(s, count);
+		return s;
+	} else
+		return __memset(s, c, count);
+}
+
+#undef memset
+#define memset(s, c, count) \
+((__builtin_constant_p(count) && (count) <= 32) ? \
+ __builtin_memset((s), (c), (count)) : \
+ (__builtin_constant_p(c) ? \
+  __constant_memset((s), (c), (count)) : \
+  __memset((s), (c), (count))))
+
+#define __HAVE_ARCH_MEMSCAN
+
+#undef memscan
+#define memscan(__arg0, __char, __arg2)					\
+({									\
+	extern void *__memscan_zero(void *, size_t);			\
+	extern void *__memscan_generic(void *, int, size_t);		\
+	void *__retval, *__addr = (__arg0);				\
+	size_t __size = (__arg2);					\
+									\
+	if(__builtin_constant_p(__char) && !(__char))			\
+		__retval = __memscan_zero(__addr, __size);		\
+	else								\
+		__retval = __memscan_generic(__addr, (__char), __size);	\
+									\
+	__retval;							\
+})
+
+#define __HAVE_ARCH_MEMCMP
+extern int memcmp(const void *,const void *,__kernel_size_t);
+
+/* Now the str*() stuff... */
+#define __HAVE_ARCH_STRLEN
+extern __kernel_size_t strlen(const char *);
+
+#define __HAVE_ARCH_STRNCMP
+extern int strncmp(const char *, const char *, __kernel_size_t);
+
+#endif /* !EXPORT_SYMTAB_STROPS */
+
+#endif /* __KERNEL__ */
+
+#endif /* !(__SPARC64_STRING_H__) */
diff --git a/include/asm-sparc/syscalls.h b/include/asm-sparc/syscalls.h
new file mode 100644
index 0000000..45a43f6
--- /dev/null
+++ b/include/asm-sparc/syscalls.h
@@ -0,0 +1,13 @@
+#ifndef _SPARC64_SYSCALLS_H
+#define _SPARC64_SYSCALLS_H
+
+struct pt_regs;
+
+extern asmlinkage long sparc_do_fork(unsigned long clone_flags,
+				     unsigned long stack_start,
+				     struct pt_regs *regs,
+				     unsigned long stack_size);
+
+extern asmlinkage int sparc_execve(struct pt_regs *regs);
+
+#endif /* _SPARC64_SYSCALLS_H */
diff --git a/include/asm-sparc/system.h b/include/asm-sparc/system.h
index b4b0244..15e2a3b 100644
--- a/include/asm-sparc/system.h
+++ b/include/asm-sparc/system.h
@@ -1,288 +1,8 @@
-#ifndef __SPARC_SYSTEM_H
-#define __SPARC_SYSTEM_H
-
-#include <linux/kernel.h>
-#include <linux/threads.h>	/* NR_CPUS */
-#include <linux/thread_info.h>
-
-#include <asm/page.h>
-#include <asm/psr.h>
-#include <asm/ptrace.h>
-#include <asm/btfixup.h>
-#include <asm/smp.h>
-
-#ifndef __ASSEMBLY__
-
-#include <linux/irqflags.h>
-
-/*
- * Sparc (general) CPU types
- */
-enum sparc_cpu {
-  sun4        = 0x00,
-  sun4c       = 0x01,
-  sun4m       = 0x02,
-  sun4d       = 0x03,
-  sun4e       = 0x04,
-  sun4u       = 0x05, /* V8 ploos ploos */
-  sun_unknown = 0x06,
-  ap1000      = 0x07, /* almost a sun4m */
-};
-
-/* Really, userland should not be looking at any of this... */
-#ifdef __KERNEL__
-
-extern enum sparc_cpu sparc_cpu_model;
-
-#ifndef CONFIG_SUN4
-#define ARCH_SUN4C_SUN4 (sparc_cpu_model==sun4c)
-#define ARCH_SUN4 0
+#ifndef ___ASM_SPARC_SYSTEM_H
+#define ___ASM_SPARC_SYSTEM_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/system_64.h>
 #else
-#define ARCH_SUN4C_SUN4 1
-#define ARCH_SUN4 1
+#include <asm-sparc/system_32.h>
 #endif
-
-#define SUN4M_NCPUS            4              /* Architectural limit of sun4m. */
-
-extern char reboot_command[];
-
-extern struct thread_info *current_set[NR_CPUS];
-
-extern unsigned long empty_bad_page;
-extern unsigned long empty_bad_page_table;
-extern unsigned long empty_zero_page;
-
-extern void sun_do_break(void);
-extern int serial_console;
-extern int stop_a_enabled;
-
-static inline int con_is_present(void)
-{
-	return serial_console ? 0 : 1;
-}
-
-/* When a context switch happens we must flush all user windows so that
- * the windows of the current process are flushed onto its stack. This
- * way the windows are all clean for the next process and the stack
- * frames are up to date.
- */
-extern void flush_user_windows(void);
-extern void kill_user_windows(void);
-extern void synchronize_user_stack(void);
-extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
-		   void *fpqueue, unsigned long *fpqdepth);
-
-#ifdef CONFIG_SMP
-#define SWITCH_ENTER(prv) \
-	do {			\
-	if (test_tsk_thread_flag(prv, TIF_USEDFPU)) { \
-		put_psr(get_psr() | PSR_EF); \
-		fpsave(&(prv)->thread.float_regs[0], &(prv)->thread.fsr, \
-		       &(prv)->thread.fpqueue[0], &(prv)->thread.fpqdepth); \
-		clear_tsk_thread_flag(prv, TIF_USEDFPU); \
-		(prv)->thread.kregs->psr &= ~PSR_EF; \
-	} \
-	} while(0)
-
-#define SWITCH_DO_LAZY_FPU(next)	/* */
-#else
-#define SWITCH_ENTER(prv)		/* */
-#define SWITCH_DO_LAZY_FPU(nxt)	\
-	do {			\
-	if (last_task_used_math != (nxt))		\
-		(nxt)->thread.kregs->psr&=~PSR_EF;	\
-	} while(0)
 #endif
-
-extern void flushw_all(void);
-
-/*
- * Flush windows so that the VM switch which follows
- * would not pull the stack from under us.
- *
- * SWITCH_ENTER and SWITH_DO_LAZY_FPU do not work yet (e.g. SMP does not work)
- * XXX WTF is the above comment? Found in late teen 2.4.x.
- */
-#define prepare_arch_switch(next) do { \
-	__asm__ __volatile__( \
-	".globl\tflush_patch_switch\nflush_patch_switch:\n\t" \
-	"save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \
-	"save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \
-	"save %sp, -0x40, %sp\n\t" \
-	"restore; restore; restore; restore; restore; restore; restore"); \
-} while(0)
-
-	/* Much care has gone into this code, do not touch it.
-	 *
-	 * We need to loadup regs l0/l1 for the newly forked child
-	 * case because the trap return path relies on those registers
-	 * holding certain values, gcc is told that they are clobbered.
-	 * Gcc needs registers for 3 values in and 1 value out, so we
-	 * clobber every non-fixed-usage register besides l2/l3/o4/o5.  -DaveM
-	 *
-	 * Hey Dave, that do not touch sign is too much of an incentive
-	 * - Anton & Pete
-	 */
-#define switch_to(prev, next, last) do {						\
-	SWITCH_ENTER(prev);								\
-	SWITCH_DO_LAZY_FPU(next);							\
-	cpu_set(smp_processor_id(), next->active_mm->cpu_vm_mask);			\
-	__asm__ __volatile__(								\
-	"sethi	%%hi(here - 0x8), %%o7\n\t"						\
-	"mov	%%g6, %%g3\n\t"								\
-	"or	%%o7, %%lo(here - 0x8), %%o7\n\t"					\
-	"rd	%%psr, %%g4\n\t"							\
-	"std	%%sp, [%%g6 + %4]\n\t"							\
-	"rd	%%wim, %%g5\n\t"							\
-	"wr	%%g4, 0x20, %%psr\n\t"							\
-	"nop\n\t"									\
-	"std	%%g4, [%%g6 + %3]\n\t"							\
-	"ldd	[%2 + %3], %%g4\n\t"							\
-	"mov	%2, %%g6\n\t"								\
-	".globl	patchme_store_new_current\n"						\
-"patchme_store_new_current:\n\t"							\
-	"st	%2, [%1]\n\t"								\
-	"wr	%%g4, 0x20, %%psr\n\t"							\
-	"nop\n\t"									\
-	"nop\n\t"									\
-	"nop\n\t"	/* LEON needs all 3 nops: load to %sp depends on CWP. */		\
-	"ldd	[%%g6 + %4], %%sp\n\t"							\
-	"wr	%%g5, 0x0, %%wim\n\t"							\
-	"ldd	[%%sp + 0x00], %%l0\n\t"						\
-	"ldd	[%%sp + 0x38], %%i6\n\t"						\
-	"wr	%%g4, 0x0, %%psr\n\t"							\
-	"nop\n\t"									\
-	"nop\n\t"									\
-	"jmpl	%%o7 + 0x8, %%g0\n\t"							\
-	" ld	[%%g3 + %5], %0\n\t"							\
-	"here:\n"									\
-        : "=&r" (last)									\
-        : "r" (&(current_set[hard_smp_processor_id()])),	\
-	  "r" (task_thread_info(next)),				\
-	  "i" (TI_KPSR),					\
-	  "i" (TI_KSP),						\
-	  "i" (TI_TASK)						\
-	:       "g1", "g2", "g3", "g4", "g5",       "g7",	\
-	  "l0", "l1",       "l3", "l4", "l5", "l6", "l7",	\
-	  "i0", "i1", "i2", "i3", "i4", "i5",			\
-	  "o0", "o1", "o2", "o3",                   "o7");	\
-	} while(0)
-
-/* XXX Change this if we ever use a PSO mode kernel. */
-#define mb()	__asm__ __volatile__ ("" : : : "memory")
-#define rmb()	mb()
-#define wmb()	mb()
-#define read_barrier_depends()	do { } while(0)
-#define set_mb(__var, __value)  do { __var = __value; mb(); } while(0)
-#define smp_mb()	__asm__ __volatile__("":::"memory")
-#define smp_rmb()	__asm__ __volatile__("":::"memory")
-#define smp_wmb()	__asm__ __volatile__("":::"memory")
-#define smp_read_barrier_depends()	do { } while(0)
-
-#define nop() __asm__ __volatile__ ("nop")
-
-/* This has special calling conventions */
-#ifndef CONFIG_SMP
-BTFIXUPDEF_CALL(void, ___xchg32, void)
-#endif
-
-static inline unsigned long xchg_u32(__volatile__ unsigned long *m, unsigned long val)
-{
-#ifdef CONFIG_SMP
-	__asm__ __volatile__("swap [%2], %0"
-			     : "=&r" (val)
-			     : "0" (val), "r" (m)
-			     : "memory");
-	return val;
-#else
-	register unsigned long *ptr asm("g1");
-	register unsigned long ret asm("g2");
-
-	ptr = (unsigned long *) m;
-	ret = val;
-
-	/* Note: this is magic and the nop there is
-	   really needed. */
-	__asm__ __volatile__(
-	"mov	%%o7, %%g4\n\t"
-	"call	___f____xchg32\n\t"
-	" nop\n\t"
-	: "=&r" (ret)
-	: "0" (ret), "r" (ptr)
-	: "g3", "g4", "g7", "memory", "cc");
-
-	return ret;
-#endif
-}
-
-#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-extern void __xchg_called_with_bad_pointer(void);
-
-static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr, int size)
-{
-	switch (size) {
-	case 4:
-		return xchg_u32(ptr, x);
-	};
-	__xchg_called_with_bad_pointer();
-	return x;
-}
-
-/* Emulate cmpxchg() the same way we emulate atomics,
- * by hashing the object address and indexing into an array
- * of spinlocks to get a bit of performance...
- *
- * See arch/sparc/lib/atomic32.c for implementation.
- *
- * Cribbed from <asm-parisc/atomic.h>
- */
-#define __HAVE_ARCH_CMPXCHG	1
-
-/* bug catcher for when unsupported size is used - won't link */
-extern void __cmpxchg_called_with_bad_pointer(void);
-/* we only need to support cmpxchg of a u32 on sparc */
-extern unsigned long __cmpxchg_u32(volatile u32 *m, u32 old, u32 new_);
-
-/* don't worry...optimizer will get rid of most of this */
-static inline unsigned long
-__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size)
-{
-	switch (size) {
-	case 4:
-		return __cmpxchg_u32((u32 *)ptr, (u32)old, (u32)new_);
-	default:
-		__cmpxchg_called_with_bad_pointer();
-		break;
-	}
-	return old;
-}
-
-#define cmpxchg(ptr, o, n)						\
-({									\
-	__typeof__(*(ptr)) _o_ = (o);					\
-	__typeof__(*(ptr)) _n_ = (n);					\
-	(__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,	\
-			(unsigned long)_n_, sizeof(*(ptr)));		\
-})
-
-#include <asm-generic/cmpxchg-local.h>
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)				  	       \
-	((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
-			(unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-extern void die_if_kernel(char *str, struct pt_regs *regs) __attribute__ ((noreturn));
-
-#endif /* __KERNEL__ */
-
-#endif /* __ASSEMBLY__ */
-
-#define arch_align_stack(x) (x)
-
-#endif /* !(__SPARC_SYSTEM_H) */
diff --git a/include/asm-sparc/system_32.h b/include/asm-sparc/system_32.h
new file mode 100644
index 0000000..b4b0244
--- /dev/null
+++ b/include/asm-sparc/system_32.h
@@ -0,0 +1,288 @@
+#ifndef __SPARC_SYSTEM_H
+#define __SPARC_SYSTEM_H
+
+#include <linux/kernel.h>
+#include <linux/threads.h>	/* NR_CPUS */
+#include <linux/thread_info.h>
+
+#include <asm/page.h>
+#include <asm/psr.h>
+#include <asm/ptrace.h>
+#include <asm/btfixup.h>
+#include <asm/smp.h>
+
+#ifndef __ASSEMBLY__
+
+#include <linux/irqflags.h>
+
+/*
+ * Sparc (general) CPU types
+ */
+enum sparc_cpu {
+  sun4        = 0x00,
+  sun4c       = 0x01,
+  sun4m       = 0x02,
+  sun4d       = 0x03,
+  sun4e       = 0x04,
+  sun4u       = 0x05, /* V8 ploos ploos */
+  sun_unknown = 0x06,
+  ap1000      = 0x07, /* almost a sun4m */
+};
+
+/* Really, userland should not be looking at any of this... */
+#ifdef __KERNEL__
+
+extern enum sparc_cpu sparc_cpu_model;
+
+#ifndef CONFIG_SUN4
+#define ARCH_SUN4C_SUN4 (sparc_cpu_model==sun4c)
+#define ARCH_SUN4 0
+#else
+#define ARCH_SUN4C_SUN4 1
+#define ARCH_SUN4 1
+#endif
+
+#define SUN4M_NCPUS            4              /* Architectural limit of sun4m. */
+
+extern char reboot_command[];
+
+extern struct thread_info *current_set[NR_CPUS];
+
+extern unsigned long empty_bad_page;
+extern unsigned long empty_bad_page_table;
+extern unsigned long empty_zero_page;
+
+extern void sun_do_break(void);
+extern int serial_console;
+extern int stop_a_enabled;
+
+static inline int con_is_present(void)
+{
+	return serial_console ? 0 : 1;
+}
+
+/* When a context switch happens we must flush all user windows so that
+ * the windows of the current process are flushed onto its stack. This
+ * way the windows are all clean for the next process and the stack
+ * frames are up to date.
+ */
+extern void flush_user_windows(void);
+extern void kill_user_windows(void);
+extern void synchronize_user_stack(void);
+extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
+		   void *fpqueue, unsigned long *fpqdepth);
+
+#ifdef CONFIG_SMP
+#define SWITCH_ENTER(prv) \
+	do {			\
+	if (test_tsk_thread_flag(prv, TIF_USEDFPU)) { \
+		put_psr(get_psr() | PSR_EF); \
+		fpsave(&(prv)->thread.float_regs[0], &(prv)->thread.fsr, \
+		       &(prv)->thread.fpqueue[0], &(prv)->thread.fpqdepth); \
+		clear_tsk_thread_flag(prv, TIF_USEDFPU); \
+		(prv)->thread.kregs->psr &= ~PSR_EF; \
+	} \
+	} while(0)
+
+#define SWITCH_DO_LAZY_FPU(next)	/* */
+#else
+#define SWITCH_ENTER(prv)		/* */
+#define SWITCH_DO_LAZY_FPU(nxt)	\
+	do {			\
+	if (last_task_used_math != (nxt))		\
+		(nxt)->thread.kregs->psr&=~PSR_EF;	\
+	} while(0)
+#endif
+
+extern void flushw_all(void);
+
+/*
+ * Flush windows so that the VM switch which follows
+ * would not pull the stack from under us.
+ *
+ * SWITCH_ENTER and SWITH_DO_LAZY_FPU do not work yet (e.g. SMP does not work)
+ * XXX WTF is the above comment? Found in late teen 2.4.x.
+ */
+#define prepare_arch_switch(next) do { \
+	__asm__ __volatile__( \
+	".globl\tflush_patch_switch\nflush_patch_switch:\n\t" \
+	"save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \
+	"save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \
+	"save %sp, -0x40, %sp\n\t" \
+	"restore; restore; restore; restore; restore; restore; restore"); \
+} while(0)
+
+	/* Much care has gone into this code, do not touch it.
+	 *
+	 * We need to loadup regs l0/l1 for the newly forked child
+	 * case because the trap return path relies on those registers
+	 * holding certain values, gcc is told that they are clobbered.
+	 * Gcc needs registers for 3 values in and 1 value out, so we
+	 * clobber every non-fixed-usage register besides l2/l3/o4/o5.  -DaveM
+	 *
+	 * Hey Dave, that do not touch sign is too much of an incentive
+	 * - Anton & Pete
+	 */
+#define switch_to(prev, next, last) do {						\
+	SWITCH_ENTER(prev);								\
+	SWITCH_DO_LAZY_FPU(next);							\
+	cpu_set(smp_processor_id(), next->active_mm->cpu_vm_mask);			\
+	__asm__ __volatile__(								\
+	"sethi	%%hi(here - 0x8), %%o7\n\t"						\
+	"mov	%%g6, %%g3\n\t"								\
+	"or	%%o7, %%lo(here - 0x8), %%o7\n\t"					\
+	"rd	%%psr, %%g4\n\t"							\
+	"std	%%sp, [%%g6 + %4]\n\t"							\
+	"rd	%%wim, %%g5\n\t"							\
+	"wr	%%g4, 0x20, %%psr\n\t"							\
+	"nop\n\t"									\
+	"std	%%g4, [%%g6 + %3]\n\t"							\
+	"ldd	[%2 + %3], %%g4\n\t"							\
+	"mov	%2, %%g6\n\t"								\
+	".globl	patchme_store_new_current\n"						\
+"patchme_store_new_current:\n\t"							\
+	"st	%2, [%1]\n\t"								\
+	"wr	%%g4, 0x20, %%psr\n\t"							\
+	"nop\n\t"									\
+	"nop\n\t"									\
+	"nop\n\t"	/* LEON needs all 3 nops: load to %sp depends on CWP. */		\
+	"ldd	[%%g6 + %4], %%sp\n\t"							\
+	"wr	%%g5, 0x0, %%wim\n\t"							\
+	"ldd	[%%sp + 0x00], %%l0\n\t"						\
+	"ldd	[%%sp + 0x38], %%i6\n\t"						\
+	"wr	%%g4, 0x0, %%psr\n\t"							\
+	"nop\n\t"									\
+	"nop\n\t"									\
+	"jmpl	%%o7 + 0x8, %%g0\n\t"							\
+	" ld	[%%g3 + %5], %0\n\t"							\
+	"here:\n"									\
+        : "=&r" (last)									\
+        : "r" (&(current_set[hard_smp_processor_id()])),	\
+	  "r" (task_thread_info(next)),				\
+	  "i" (TI_KPSR),					\
+	  "i" (TI_KSP),						\
+	  "i" (TI_TASK)						\
+	:       "g1", "g2", "g3", "g4", "g5",       "g7",	\
+	  "l0", "l1",       "l3", "l4", "l5", "l6", "l7",	\
+	  "i0", "i1", "i2", "i3", "i4", "i5",			\
+	  "o0", "o1", "o2", "o3",                   "o7");	\
+	} while(0)
+
+/* XXX Change this if we ever use a PSO mode kernel. */
+#define mb()	__asm__ __volatile__ ("" : : : "memory")
+#define rmb()	mb()
+#define wmb()	mb()
+#define read_barrier_depends()	do { } while(0)
+#define set_mb(__var, __value)  do { __var = __value; mb(); } while(0)
+#define smp_mb()	__asm__ __volatile__("":::"memory")
+#define smp_rmb()	__asm__ __volatile__("":::"memory")
+#define smp_wmb()	__asm__ __volatile__("":::"memory")
+#define smp_read_barrier_depends()	do { } while(0)
+
+#define nop() __asm__ __volatile__ ("nop")
+
+/* This has special calling conventions */
+#ifndef CONFIG_SMP
+BTFIXUPDEF_CALL(void, ___xchg32, void)
+#endif
+
+static inline unsigned long xchg_u32(__volatile__ unsigned long *m, unsigned long val)
+{
+#ifdef CONFIG_SMP
+	__asm__ __volatile__("swap [%2], %0"
+			     : "=&r" (val)
+			     : "0" (val), "r" (m)
+			     : "memory");
+	return val;
+#else
+	register unsigned long *ptr asm("g1");
+	register unsigned long ret asm("g2");
+
+	ptr = (unsigned long *) m;
+	ret = val;
+
+	/* Note: this is magic and the nop there is
+	   really needed. */
+	__asm__ __volatile__(
+	"mov	%%o7, %%g4\n\t"
+	"call	___f____xchg32\n\t"
+	" nop\n\t"
+	: "=&r" (ret)
+	: "0" (ret), "r" (ptr)
+	: "g3", "g4", "g7", "memory", "cc");
+
+	return ret;
+#endif
+}
+
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+extern void __xchg_called_with_bad_pointer(void);
+
+static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr, int size)
+{
+	switch (size) {
+	case 4:
+		return xchg_u32(ptr, x);
+	};
+	__xchg_called_with_bad_pointer();
+	return x;
+}
+
+/* Emulate cmpxchg() the same way we emulate atomics,
+ * by hashing the object address and indexing into an array
+ * of spinlocks to get a bit of performance...
+ *
+ * See arch/sparc/lib/atomic32.c for implementation.
+ *
+ * Cribbed from <asm-parisc/atomic.h>
+ */
+#define __HAVE_ARCH_CMPXCHG	1
+
+/* bug catcher for when unsupported size is used - won't link */
+extern void __cmpxchg_called_with_bad_pointer(void);
+/* we only need to support cmpxchg of a u32 on sparc */
+extern unsigned long __cmpxchg_u32(volatile u32 *m, u32 old, u32 new_);
+
+/* don't worry...optimizer will get rid of most of this */
+static inline unsigned long
+__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size)
+{
+	switch (size) {
+	case 4:
+		return __cmpxchg_u32((u32 *)ptr, (u32)old, (u32)new_);
+	default:
+		__cmpxchg_called_with_bad_pointer();
+		break;
+	}
+	return old;
+}
+
+#define cmpxchg(ptr, o, n)						\
+({									\
+	__typeof__(*(ptr)) _o_ = (o);					\
+	__typeof__(*(ptr)) _n_ = (n);					\
+	(__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,	\
+			(unsigned long)_n_, sizeof(*(ptr)));		\
+})
+
+#include <asm-generic/cmpxchg-local.h>
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)				  	       \
+	((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
+			(unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+extern void die_if_kernel(char *str, struct pt_regs *regs) __attribute__ ((noreturn));
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASSEMBLY__ */
+
+#define arch_align_stack(x) (x)
+
+#endif /* !(__SPARC_SYSTEM_H) */
diff --git a/include/asm-sparc/system_64.h b/include/asm-sparc/system_64.h
new file mode 100644
index 0000000..db9e742
--- /dev/null
+++ b/include/asm-sparc/system_64.h
@@ -0,0 +1,355 @@
+#ifndef __SPARC64_SYSTEM_H
+#define __SPARC64_SYSTEM_H
+
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+#include <asm/visasm.h>
+
+#ifndef __ASSEMBLY__
+
+#include <linux/irqflags.h>
+#include <asm-generic/cmpxchg-local.h>
+
+/*
+ * Sparc (general) CPU types
+ */
+enum sparc_cpu {
+  sun4        = 0x00,
+  sun4c       = 0x01,
+  sun4m       = 0x02,
+  sun4d       = 0x03,
+  sun4e       = 0x04,
+  sun4u       = 0x05, /* V8 ploos ploos */
+  sun_unknown = 0x06,
+  ap1000      = 0x07, /* almost a sun4m */
+};
+
+#define sparc_cpu_model sun4u
+
+/* This cannot ever be a sun4c nor sun4 :) That's just history. */
+#define ARCH_SUN4C_SUN4 0
+#define ARCH_SUN4 0
+
+extern char reboot_command[];
+
+/* These are here in an effort to more fully work around Spitfire Errata
+ * #51.  Essentially, if a memory barrier occurs soon after a mispredicted
+ * branch, the chip can stop executing instructions until a trap occurs.
+ * Therefore, if interrupts are disabled, the chip can hang forever.
+ *
+ * It used to be believed that the memory barrier had to be right in the
+ * delay slot, but a case has been traced recently wherein the memory barrier
+ * was one instruction after the branch delay slot and the chip still hung.
+ * The offending sequence was the following in sym_wakeup_done() of the
+ * sym53c8xx_2 driver:
+ *
+ *	call	sym_ccb_from_dsa, 0
+ *	 movge	%icc, 0, %l0
+ *	brz,pn	%o0, .LL1303
+ *	 mov	%o0, %l2
+ *	membar	#LoadLoad
+ *
+ * The branch has to be mispredicted for the bug to occur.  Therefore, we put
+ * the memory barrier explicitly into a "branch always, predicted taken"
+ * delay slot to avoid the problem case.
+ */
+#define membar_safe(type) \
+do {	__asm__ __volatile__("ba,pt	%%xcc, 1f\n\t" \
+			     " membar	" type "\n" \
+			     "1:\n" \
+			     : : : "memory"); \
+} while (0)
+
+#define mb()	\
+	membar_safe("#LoadLoad | #LoadStore | #StoreStore | #StoreLoad")
+#define rmb()	\
+	membar_safe("#LoadLoad")
+#define wmb()	\
+	membar_safe("#StoreStore")
+#define membar_storeload() \
+	membar_safe("#StoreLoad")
+#define membar_storeload_storestore() \
+	membar_safe("#StoreLoad | #StoreStore")
+#define membar_storeload_loadload() \
+	membar_safe("#StoreLoad | #LoadLoad")
+#define membar_storestore_loadstore() \
+	membar_safe("#StoreStore | #LoadStore")
+
+#endif
+
+#define nop() 		__asm__ __volatile__ ("nop")
+
+#define read_barrier_depends()		do { } while(0)
+#define set_mb(__var, __value) \
+	do { __var = __value; membar_storeload_storestore(); } while(0)
+
+#ifdef CONFIG_SMP
+#define smp_mb()	mb()
+#define smp_rmb()	rmb()
+#define smp_wmb()	wmb()
+#define smp_read_barrier_depends()	read_barrier_depends()
+#else
+#define smp_mb()	__asm__ __volatile__("":::"memory")
+#define smp_rmb()	__asm__ __volatile__("":::"memory")
+#define smp_wmb()	__asm__ __volatile__("":::"memory")
+#define smp_read_barrier_depends()	do { } while(0)
+#endif
+
+#define flushi(addr)	__asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory")
+
+#define flushw_all()	__asm__ __volatile__("flushw")
+
+/* Performance counter register access. */
+#define read_pcr(__p)  __asm__ __volatile__("rd	%%pcr, %0" : "=r" (__p))
+#define write_pcr(__p) __asm__ __volatile__("wr	%0, 0x0, %%pcr" : : "r" (__p))
+#define read_pic(__p)  __asm__ __volatile__("rd %%pic, %0" : "=r" (__p))
+
+/* Blackbird errata workaround.  See commentary in
+ * arch/sparc64/kernel/smp.c:smp_percpu_timer_interrupt()
+ * for more information.
+ */
+#define reset_pic()    						\
+	__asm__ __volatile__("ba,pt	%xcc, 99f\n\t"		\
+			     ".align	64\n"			\
+			  "99:wr	%g0, 0x0, %pic\n\t"	\
+			     "rd	%pic, %g0")
+
+#ifndef __ASSEMBLY__
+
+extern void sun_do_break(void);
+extern int stop_a_enabled;
+
+extern void fault_in_user_windows(void);
+extern void synchronize_user_stack(void);
+
+extern void __flushw_user(void);
+#define flushw_user() __flushw_user()
+
+#define flush_user_windows flushw_user
+#define flush_register_windows flushw_all
+
+/* Don't hold the runqueue lock over context switch */
+#define __ARCH_WANT_UNLOCKED_CTXSW
+#define prepare_arch_switch(next)		\
+do {						\
+	flushw_all();				\
+} while (0)
+
+	/* See what happens when you design the chip correctly?
+	 *
+	 * We tell gcc we clobber all non-fixed-usage registers except
+	 * for l0/l1.  It will use one for 'next' and the other to hold
+	 * the output value of 'last'.  'next' is not referenced again
+	 * past the invocation of switch_to in the scheduler, so we need
+	 * not preserve it's value.  Hairy, but it lets us remove 2 loads
+	 * and 2 stores in this critical code path.  -DaveM
+	 */
+#define switch_to(prev, next, last)					\
+do {	if (test_thread_flag(TIF_PERFCTR)) {				\
+		unsigned long __tmp;					\
+		read_pcr(__tmp);					\
+		current_thread_info()->pcr_reg = __tmp;			\
+		read_pic(__tmp);					\
+		current_thread_info()->kernel_cntd0 += (unsigned int)(__tmp);\
+		current_thread_info()->kernel_cntd1 += ((__tmp) >> 32);	\
+	}								\
+	flush_tlb_pending();						\
+	save_and_clear_fpu();						\
+	/* If you are tempted to conditionalize the following */	\
+	/* so that ASI is only written if it changes, think again. */	\
+	__asm__ __volatile__("wr %%g0, %0, %%asi"			\
+	: : "r" (__thread_flag_byte_ptr(task_thread_info(next))[TI_FLAG_BYTE_CURRENT_DS]));\
+	trap_block[current_thread_info()->cpu].thread =			\
+		task_thread_info(next);					\
+	__asm__ __volatile__(						\
+	"mov	%%g4, %%g7\n\t"						\
+	"stx	%%i6, [%%sp + 2047 + 0x70]\n\t"				\
+	"stx	%%i7, [%%sp + 2047 + 0x78]\n\t"				\
+	"rdpr	%%wstate, %%o5\n\t"					\
+	"stx	%%o6, [%%g6 + %6]\n\t"					\
+	"stb	%%o5, [%%g6 + %5]\n\t"					\
+	"rdpr	%%cwp, %%o5\n\t"					\
+	"stb	%%o5, [%%g6 + %8]\n\t"					\
+	"mov	%4, %%g6\n\t"						\
+	"ldub	[%4 + %8], %%g1\n\t"					\
+	"wrpr	%%g1, %%cwp\n\t"					\
+	"ldx	[%%g6 + %6], %%o6\n\t"					\
+	"ldub	[%%g6 + %5], %%o5\n\t"					\
+	"ldub	[%%g6 + %7], %%o7\n\t"					\
+	"wrpr	%%o5, 0x0, %%wstate\n\t"				\
+	"ldx	[%%sp + 2047 + 0x70], %%i6\n\t"				\
+	"ldx	[%%sp + 2047 + 0x78], %%i7\n\t"				\
+	"ldx	[%%g6 + %9], %%g4\n\t"					\
+	"brz,pt %%o7, switch_to_pc\n\t"					\
+	" mov	%%g7, %0\n\t"						\
+	"sethi	%%hi(ret_from_syscall), %%g1\n\t"			\
+	"jmpl	%%g1 + %%lo(ret_from_syscall), %%g0\n\t"		\
+	" nop\n\t"							\
+	".globl switch_to_pc\n\t"					\
+	"switch_to_pc:\n\t"						\
+	: "=&r" (last), "=r" (current), "=r" (current_thread_info_reg),	\
+	  "=r" (__local_per_cpu_offset)					\
+	: "0" (task_thread_info(next)),					\
+	  "i" (TI_WSTATE), "i" (TI_KSP), "i" (TI_NEW_CHILD),            \
+	  "i" (TI_CWP), "i" (TI_TASK)					\
+	: "cc",								\
+	        "g1", "g2", "g3",                   "g7",		\
+	        "l1", "l2", "l3", "l4", "l5", "l6", "l7",		\
+	  "i0", "i1", "i2", "i3", "i4", "i5",				\
+	  "o0", "o1", "o2", "o3", "o4", "o5",       "o7");		\
+	/* If you fuck with this, update ret_from_syscall code too. */	\
+	if (test_thread_flag(TIF_PERFCTR)) {				\
+		write_pcr(current_thread_info()->pcr_reg);		\
+		reset_pic();						\
+	}								\
+} while(0)
+
+static inline unsigned long xchg32(__volatile__ unsigned int *m, unsigned int val)
+{
+	unsigned long tmp1, tmp2;
+
+	__asm__ __volatile__(
+"	membar		#StoreLoad | #LoadLoad\n"
+"	mov		%0, %1\n"
+"1:	lduw		[%4], %2\n"
+"	cas		[%4], %2, %0\n"
+"	cmp		%2, %0\n"
+"	bne,a,pn	%%icc, 1b\n"
+"	 mov		%1, %0\n"
+"	membar		#StoreLoad | #StoreStore\n"
+	: "=&r" (val), "=&r" (tmp1), "=&r" (tmp2)
+	: "0" (val), "r" (m)
+	: "cc", "memory");
+	return val;
+}
+
+static inline unsigned long xchg64(__volatile__ unsigned long *m, unsigned long val)
+{
+	unsigned long tmp1, tmp2;
+
+	__asm__ __volatile__(
+"	membar		#StoreLoad | #LoadLoad\n"
+"	mov		%0, %1\n"
+"1:	ldx		[%4], %2\n"
+"	casx		[%4], %2, %0\n"
+"	cmp		%2, %0\n"
+"	bne,a,pn	%%xcc, 1b\n"
+"	 mov		%1, %0\n"
+"	membar		#StoreLoad | #StoreStore\n"
+	: "=&r" (val), "=&r" (tmp1), "=&r" (tmp2)
+	: "0" (val), "r" (m)
+	: "cc", "memory");
+	return val;
+}
+
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+extern void __xchg_called_with_bad_pointer(void);
+
+static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr,
+				       int size)
+{
+	switch (size) {
+	case 4:
+		return xchg32(ptr, x);
+	case 8:
+		return xchg64(ptr, x);
+	};
+	__xchg_called_with_bad_pointer();
+	return x;
+}
+
+extern void die_if_kernel(char *str, struct pt_regs *regs) __attribute__ ((noreturn));
+
+/*
+ * Atomic compare and exchange.  Compare OLD with MEM, if identical,
+ * store NEW in MEM.  Return the initial value in MEM.  Success is
+ * indicated by comparing RETURN with OLD.
+ */
+
+#define __HAVE_ARCH_CMPXCHG 1
+
+static inline unsigned long
+__cmpxchg_u32(volatile int *m, int old, int new)
+{
+	__asm__ __volatile__("membar #StoreLoad | #LoadLoad\n"
+			     "cas [%2], %3, %0\n\t"
+			     "membar #StoreLoad | #StoreStore"
+			     : "=&r" (new)
+			     : "0" (new), "r" (m), "r" (old)
+			     : "memory");
+
+	return new;
+}
+
+static inline unsigned long
+__cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new)
+{
+	__asm__ __volatile__("membar #StoreLoad | #LoadLoad\n"
+			     "casx [%2], %3, %0\n\t"
+			     "membar #StoreLoad | #StoreStore"
+			     : "=&r" (new)
+			     : "0" (new), "r" (m), "r" (old)
+			     : "memory");
+
+	return new;
+}
+
+/* This function doesn't exist, so you'll get a linker error
+   if something tries to do an invalid cmpxchg().  */
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+static inline unsigned long
+__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
+{
+	switch (size) {
+		case 4:
+			return __cmpxchg_u32(ptr, old, new);
+		case 8:
+			return __cmpxchg_u64(ptr, old, new);
+	}
+	__cmpxchg_called_with_bad_pointer();
+	return old;
+}
+
+#define cmpxchg(ptr,o,n)						 \
+  ({									 \
+     __typeof__(*(ptr)) _o_ = (o);					 \
+     __typeof__(*(ptr)) _n_ = (n);					 \
+     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,		 \
+				    (unsigned long)_n_, sizeof(*(ptr))); \
+  })
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+
+static inline unsigned long __cmpxchg_local(volatile void *ptr,
+				      unsigned long old,
+				      unsigned long new, int size)
+{
+	switch (size) {
+	case 4:
+	case 8:	return __cmpxchg(ptr, old, new, size);
+	default:
+		return __cmpxchg_local_generic(ptr, old, new, size);
+	}
+
+	return old;
+}
+
+#define cmpxchg_local(ptr, o, n)				  	\
+	((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o),	\
+			(unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n)					\
+  ({									\
+	BUILD_BUG_ON(sizeof(*(ptr)) != 8);				\
+	cmpxchg_local((ptr), (o), (n));					\
+  })
+
+#endif /* !(__ASSEMBLY__) */
+
+#define arch_align_stack(x) (x)
+
+#endif /* !(__SPARC64_SYSTEM_H) */
diff --git a/include/asm-sparc/termbits.h b/include/asm-sparc/termbits.h
index 90cf221..d6ca3e2 100644
--- a/include/asm-sparc/termbits.h
+++ b/include/asm-sparc/termbits.h
@@ -5,7 +5,12 @@
 
 typedef unsigned char   cc_t;
 typedef unsigned int    speed_t;
+
+#if defined(__sparc__) && defined(__arch64__)
+typedef unsigned int    tcflag_t;
+#else
 typedef unsigned long   tcflag_t;
+#endif
 
 #define NCC 8
 struct termio {
diff --git a/include/asm-sparc/termios.h b/include/asm-sparc/termios.h
index f7b4409..e8ba953 100644
--- a/include/asm-sparc/termios.h
+++ b/include/asm-sparc/termios.h
@@ -53,7 +53,6 @@
 #define _VMIN	4
 #define _VTIME	5
 
-
 /*	intr=^C		quit=^\		erase=del	kill=^U
 	eof=^D		eol=\0		eol2=\0		sxtc=\0
 	start=^Q	stop=^S		susp=^Z		dsusp=^Y
@@ -68,16 +67,17 @@
 #define user_termio_to_kernel_termios(termios, termio) \
 ({ \
 	unsigned short tmp; \
-	get_user(tmp, &(termio)->c_iflag); \
+	int err; \
+	err = get_user(tmp, &(termio)->c_iflag); \
 	(termios)->c_iflag = (0xffff0000 & ((termios)->c_iflag)) | tmp; \
-	get_user(tmp, &(termio)->c_oflag); \
+	err |= get_user(tmp, &(termio)->c_oflag); \
 	(termios)->c_oflag = (0xffff0000 & ((termios)->c_oflag)) | tmp; \
-	get_user(tmp, &(termio)->c_cflag); \
+	err |= get_user(tmp, &(termio)->c_cflag); \
 	(termios)->c_cflag = (0xffff0000 & ((termios)->c_cflag)) | tmp; \
-	get_user(tmp, &(termio)->c_lflag); \
+	err |= get_user(tmp, &(termio)->c_lflag); \
 	(termios)->c_lflag = (0xffff0000 & ((termios)->c_lflag)) | tmp; \
-	copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
-	0; \
+	err |= copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
+	err; \
 })
 
 /*
@@ -87,17 +87,18 @@
  */
 #define kernel_termios_to_user_termio(termio, termios) \
 ({ \
-	put_user((termios)->c_iflag, &(termio)->c_iflag); \
-	put_user((termios)->c_oflag, &(termio)->c_oflag); \
-	put_user((termios)->c_cflag, &(termio)->c_cflag); \
-	put_user((termios)->c_lflag, &(termio)->c_lflag); \
-	put_user((termios)->c_line,  &(termio)->c_line); \
-	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
+	int err; \
+	err  = put_user((termios)->c_iflag, &(termio)->c_iflag); \
+	err |= put_user((termios)->c_oflag, &(termio)->c_oflag); \
+	err |= put_user((termios)->c_cflag, &(termio)->c_cflag); \
+	err |= put_user((termios)->c_lflag, &(termio)->c_lflag); \
+	err |= put_user((termios)->c_line,  &(termio)->c_line); \
+	err |= copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
 	if (!((termios)->c_lflag & ICANON)) { \
-		put_user((termios)->c_cc[VMIN], &(termio)->c_cc[_VMIN]); \
-		put_user((termios)->c_cc[VTIME], &(termio)->c_cc[_VTIME]); \
+		err |= put_user((termios)->c_cc[VMIN], &(termio)->c_cc[_VMIN]); \
+		err |= put_user((termios)->c_cc[VTIME], &(termio)->c_cc[_VTIME]); \
 	} \
-	0; \
+	err; \
 })
 
 #define user_termios_to_kernel_termios(k, u) \
@@ -144,38 +145,40 @@
 
 #define user_termios_to_kernel_termios_1(k, u) \
 ({ \
-	get_user((k)->c_iflag, &(u)->c_iflag); \
-	get_user((k)->c_oflag, &(u)->c_oflag); \
-	get_user((k)->c_cflag, &(u)->c_cflag); \
-	get_user((k)->c_lflag, &(u)->c_lflag); \
-	get_user((k)->c_line,  &(u)->c_line); \
-	copy_from_user((k)->c_cc, (u)->c_cc, NCCS); \
+	int err; \
+	err  = get_user((k)->c_iflag, &(u)->c_iflag); \
+	err |= get_user((k)->c_oflag, &(u)->c_oflag); \
+	err |= get_user((k)->c_cflag, &(u)->c_cflag); \
+	err |= get_user((k)->c_lflag, &(u)->c_lflag); \
+	err |= get_user((k)->c_line,  &(u)->c_line); \
+	err |= copy_from_user((k)->c_cc, (u)->c_cc, NCCS); \
 	if ((k)->c_lflag & ICANON) { \
-		get_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \
-		get_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \
+		err |= get_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \
+		err |= get_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \
 	} else { \
-		get_user((k)->c_cc[VMIN],  &(u)->c_cc[_VMIN]); \
-		get_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \
+		err |= get_user((k)->c_cc[VMIN],  &(u)->c_cc[_VMIN]); \
+		err |= get_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \
 	} \
-	0; \
+	err; \
 })
 
 #define kernel_termios_to_user_termios_1(u, k) \
 ({ \
-	put_user((k)->c_iflag, &(u)->c_iflag); \
-	put_user((k)->c_oflag, &(u)->c_oflag); \
-	put_user((k)->c_cflag, &(u)->c_cflag); \
-	put_user((k)->c_lflag, &(u)->c_lflag); \
-	put_user((k)->c_line, &(u)->c_line); \
-	copy_to_user((u)->c_cc, (k)->c_cc, NCCS); \
+	int err; \
+	err  = put_user((k)->c_iflag, &(u)->c_iflag); \
+	err |= put_user((k)->c_oflag, &(u)->c_oflag); \
+	err |= put_user((k)->c_cflag, &(u)->c_cflag); \
+	err |= put_user((k)->c_lflag, &(u)->c_lflag); \
+	err |= put_user((k)->c_line, &(u)->c_line); \
+	err |= copy_to_user((u)->c_cc, (k)->c_cc, NCCS); \
 	if (!((k)->c_lflag & ICANON)) { \
-		put_user((k)->c_cc[VMIN],  &(u)->c_cc[_VMIN]); \
-		put_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \
+		err |= put_user((k)->c_cc[VMIN],  &(u)->c_cc[_VMIN]); \
+		err |= put_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \
 	} else { \
-		put_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \
-		put_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \
+		err |= put_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \
+		err |= put_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \
 	} \
-	0; \
+	err; \
 })
 
 #endif	/* __KERNEL__ */
diff --git a/include/asm-sparc/thread_info.h b/include/asm-sparc/thread_info.h
index 91b9f58..64155cf 100644
--- a/include/asm-sparc/thread_info.h
+++ b/include/asm-sparc/thread_info.h
@@ -1,151 +1,8 @@
-/*
- * thread_info.h: sparc low-level thread information
- * adapted from the ppc version by Pete Zaitcev, which was
- * adapted from the i386 version by Paul Mackerras
- *
- * Copyright (C) 2002  David Howells (dhowells@redhat.com)
- * Copyright (c) 2002  Pete Zaitcev (zaitcev@yahoo.com)
- * - Incorporating suggestions made by Linus Torvalds and Dave Miller
- */
-
-#ifndef _ASM_THREAD_INFO_H
-#define _ASM_THREAD_INFO_H
-
-#ifdef __KERNEL__
-
-#ifndef __ASSEMBLY__
-
-#include <asm/btfixup.h>
-#include <asm/ptrace.h>
-#include <asm/page.h>
-
-/*
- * Low level task data.
- *
- * If you change this, change the TI_* offsets below to match.
- */
-#define NSWINS 8
-struct thread_info {
-	unsigned long		uwinmask;
-	struct task_struct	*task;		/* main task structure */
-	struct exec_domain	*exec_domain;	/* execution domain */
-	unsigned long		flags;		/* low level flags */
-	int			cpu;		/* cpu we're on */
-	int			preempt_count;	/* 0 => preemptable,
-						   <0 => BUG */
-	int			softirq_count;
-	int			hardirq_count;
-
-	/* Context switch saved kernel state. */
-	unsigned long ksp;	/* ... ksp __attribute__ ((aligned (8))); */
-	unsigned long kpc;
-	unsigned long kpsr;
-	unsigned long kwim;
-
-	/* A place to store user windows and stack pointers
-	 * when the stack needs inspection.
-	 */
-	struct reg_window	reg_window[NSWINS];	/* align for ldd! */
-	unsigned long		rwbuf_stkptrs[NSWINS];
-	unsigned long		w_saved;
-
-	struct restart_block	restart_block;
-};
-
-/*
- * macros/functions for gaining access to the thread information structure
- *
- * preempt_count needs to be 1 initially, until the scheduler is functional.
- */
-#define INIT_THREAD_INFO(tsk)				\
-{							\
-	.uwinmask	=	0,			\
-	.task		=	&tsk,			\
-	.exec_domain	=	&default_exec_domain,	\
-	.flags		=	0,			\
-	.cpu		=	0,			\
-	.preempt_count	=	1,			\
-	.restart_block	= {				\
-		.fn	=	do_no_restart_syscall,	\
-	},						\
-}
-
-#define init_thread_info	(init_thread_union.thread_info)
-#define init_stack		(init_thread_union.stack)
-
-/* how to get the thread information struct from C */
-register struct thread_info *current_thread_info_reg asm("g6");
-#define current_thread_info()   (current_thread_info_reg)
-
-/*
- * thread information allocation
- */
-#if PAGE_SHIFT == 13
-#define THREAD_INFO_ORDER  0
-#else /* PAGE_SHIFT */
-#define THREAD_INFO_ORDER  1
+#ifndef ___ASM_SPARC_THREAD_INFO_H
+#define ___ASM_SPARC_THREAD_INFO_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/thread_info_64.h>
+#else
+#include <asm-sparc/thread_info_32.h>
 #endif
-
-BTFIXUPDEF_CALL(struct thread_info *, alloc_thread_info, void)
-#define alloc_thread_info(tsk) BTFIXUP_CALL(alloc_thread_info)()
-
-BTFIXUPDEF_CALL(void, free_thread_info, struct thread_info *)
-#define free_thread_info(ti) BTFIXUP_CALL(free_thread_info)(ti)
-
-#endif /* __ASSEMBLY__ */
-
-/*
- * Size of kernel stack for each process.
- * Observe the order of get_free_pages() in alloc_thread_info().
- * The sun4 has 8K stack too, because it's short on memory, and 16K is a waste.
- */
-#define THREAD_SIZE		8192
-
-/*
- * Offsets in thread_info structure, used in assembly code
- * The "#define REGWIN_SZ 0x40" was abolished, so no multiplications.
- */
-#define TI_UWINMASK	0x00	/* uwinmask */
-#define TI_TASK		0x04
-#define TI_EXECDOMAIN	0x08	/* exec_domain */
-#define TI_FLAGS	0x0c
-#define TI_CPU		0x10
-#define TI_PREEMPT	0x14	/* preempt_count */
-#define TI_SOFTIRQ	0x18	/* softirq_count */
-#define TI_HARDIRQ	0x1c	/* hardirq_count */
-#define TI_KSP		0x20	/* ksp */
-#define TI_KPC		0x24	/* kpc (ldd'ed with kpc) */
-#define TI_KPSR		0x28	/* kpsr */
-#define TI_KWIM		0x2c	/* kwim (ldd'ed with kpsr) */
-#define TI_REG_WINDOW	0x30
-#define TI_RWIN_SPTRS	0x230
-#define TI_W_SAVED	0x250
-/* #define TI_RESTART_BLOCK 0x25n */ /* Nobody cares */
-
-#define PREEMPT_ACTIVE		0x4000000
-
-/*
- * thread information flag bit numbers
- */
-#define TIF_SYSCALL_TRACE	0	/* syscall trace active */
-/* flag bit 1 is available */
-#define TIF_SIGPENDING		2	/* signal pending */
-#define TIF_NEED_RESCHED	3	/* rescheduling necessary */
-#define TIF_RESTORE_SIGMASK	4	/* restore signal mask in do_signal() */
-#define TIF_USEDFPU		8	/* FPU was used by this task
-					 * this quantum (SMP) */
-#define TIF_POLLING_NRFLAG	9	/* true if poll_idle() is polling
-					 * TIF_NEED_RESCHED */
-#define TIF_MEMDIE		10
-
-/* as above, but as bit values */
-#define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
-#define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
-#define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
-#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
-#define _TIF_USEDFPU		(1<<TIF_USEDFPU)
-#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
-
-#endif /* __KERNEL__ */
-
-#endif /* _ASM_THREAD_INFO_H */
+#endif
diff --git a/include/asm-sparc/thread_info_32.h b/include/asm-sparc/thread_info_32.h
new file mode 100644
index 0000000..91b9f58
--- /dev/null
+++ b/include/asm-sparc/thread_info_32.h
@@ -0,0 +1,151 @@
+/*
+ * thread_info.h: sparc low-level thread information
+ * adapted from the ppc version by Pete Zaitcev, which was
+ * adapted from the i386 version by Paul Mackerras
+ *
+ * Copyright (C) 2002  David Howells (dhowells@redhat.com)
+ * Copyright (c) 2002  Pete Zaitcev (zaitcev@yahoo.com)
+ * - Incorporating suggestions made by Linus Torvalds and Dave Miller
+ */
+
+#ifndef _ASM_THREAD_INFO_H
+#define _ASM_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+
+#include <asm/btfixup.h>
+#include <asm/ptrace.h>
+#include <asm/page.h>
+
+/*
+ * Low level task data.
+ *
+ * If you change this, change the TI_* offsets below to match.
+ */
+#define NSWINS 8
+struct thread_info {
+	unsigned long		uwinmask;
+	struct task_struct	*task;		/* main task structure */
+	struct exec_domain	*exec_domain;	/* execution domain */
+	unsigned long		flags;		/* low level flags */
+	int			cpu;		/* cpu we're on */
+	int			preempt_count;	/* 0 => preemptable,
+						   <0 => BUG */
+	int			softirq_count;
+	int			hardirq_count;
+
+	/* Context switch saved kernel state. */
+	unsigned long ksp;	/* ... ksp __attribute__ ((aligned (8))); */
+	unsigned long kpc;
+	unsigned long kpsr;
+	unsigned long kwim;
+
+	/* A place to store user windows and stack pointers
+	 * when the stack needs inspection.
+	 */
+	struct reg_window	reg_window[NSWINS];	/* align for ldd! */
+	unsigned long		rwbuf_stkptrs[NSWINS];
+	unsigned long		w_saved;
+
+	struct restart_block	restart_block;
+};
+
+/*
+ * macros/functions for gaining access to the thread information structure
+ *
+ * preempt_count needs to be 1 initially, until the scheduler is functional.
+ */
+#define INIT_THREAD_INFO(tsk)				\
+{							\
+	.uwinmask	=	0,			\
+	.task		=	&tsk,			\
+	.exec_domain	=	&default_exec_domain,	\
+	.flags		=	0,			\
+	.cpu		=	0,			\
+	.preempt_count	=	1,			\
+	.restart_block	= {				\
+		.fn	=	do_no_restart_syscall,	\
+	},						\
+}
+
+#define init_thread_info	(init_thread_union.thread_info)
+#define init_stack		(init_thread_union.stack)
+
+/* how to get the thread information struct from C */
+register struct thread_info *current_thread_info_reg asm("g6");
+#define current_thread_info()   (current_thread_info_reg)
+
+/*
+ * thread information allocation
+ */
+#if PAGE_SHIFT == 13
+#define THREAD_INFO_ORDER  0
+#else /* PAGE_SHIFT */
+#define THREAD_INFO_ORDER  1
+#endif
+
+BTFIXUPDEF_CALL(struct thread_info *, alloc_thread_info, void)
+#define alloc_thread_info(tsk) BTFIXUP_CALL(alloc_thread_info)()
+
+BTFIXUPDEF_CALL(void, free_thread_info, struct thread_info *)
+#define free_thread_info(ti) BTFIXUP_CALL(free_thread_info)(ti)
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * Size of kernel stack for each process.
+ * Observe the order of get_free_pages() in alloc_thread_info().
+ * The sun4 has 8K stack too, because it's short on memory, and 16K is a waste.
+ */
+#define THREAD_SIZE		8192
+
+/*
+ * Offsets in thread_info structure, used in assembly code
+ * The "#define REGWIN_SZ 0x40" was abolished, so no multiplications.
+ */
+#define TI_UWINMASK	0x00	/* uwinmask */
+#define TI_TASK		0x04
+#define TI_EXECDOMAIN	0x08	/* exec_domain */
+#define TI_FLAGS	0x0c
+#define TI_CPU		0x10
+#define TI_PREEMPT	0x14	/* preempt_count */
+#define TI_SOFTIRQ	0x18	/* softirq_count */
+#define TI_HARDIRQ	0x1c	/* hardirq_count */
+#define TI_KSP		0x20	/* ksp */
+#define TI_KPC		0x24	/* kpc (ldd'ed with kpc) */
+#define TI_KPSR		0x28	/* kpsr */
+#define TI_KWIM		0x2c	/* kwim (ldd'ed with kpsr) */
+#define TI_REG_WINDOW	0x30
+#define TI_RWIN_SPTRS	0x230
+#define TI_W_SAVED	0x250
+/* #define TI_RESTART_BLOCK 0x25n */ /* Nobody cares */
+
+#define PREEMPT_ACTIVE		0x4000000
+
+/*
+ * thread information flag bit numbers
+ */
+#define TIF_SYSCALL_TRACE	0	/* syscall trace active */
+/* flag bit 1 is available */
+#define TIF_SIGPENDING		2	/* signal pending */
+#define TIF_NEED_RESCHED	3	/* rescheduling necessary */
+#define TIF_RESTORE_SIGMASK	4	/* restore signal mask in do_signal() */
+#define TIF_USEDFPU		8	/* FPU was used by this task
+					 * this quantum (SMP) */
+#define TIF_POLLING_NRFLAG	9	/* true if poll_idle() is polling
+					 * TIF_NEED_RESCHED */
+#define TIF_MEMDIE		10
+
+/* as above, but as bit values */
+#define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
+#define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
+#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
+#define _TIF_USEDFPU		(1<<TIF_USEDFPU)
+#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_THREAD_INFO_H */
diff --git a/include/asm-sparc/thread_info_64.h b/include/asm-sparc/thread_info_64.h
new file mode 100644
index 0000000..c6d2e6c
--- /dev/null
+++ b/include/asm-sparc/thread_info_64.h
@@ -0,0 +1,277 @@
+/* thread_info.h: sparc64 low-level thread information
+ *
+ * Copyright (C) 2002  David S. Miller (davem@redhat.com)
+ */
+
+#ifndef _ASM_THREAD_INFO_H
+#define _ASM_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#define NSWINS		7
+
+#define TI_FLAG_BYTE_FAULT_CODE		0
+#define TI_FLAG_FAULT_CODE_SHIFT	56
+#define TI_FLAG_BYTE_WSTATE		1
+#define TI_FLAG_WSTATE_SHIFT		48
+#define TI_FLAG_BYTE_CWP		2
+#define TI_FLAG_CWP_SHIFT		40
+#define TI_FLAG_BYTE_CURRENT_DS		3
+#define TI_FLAG_CURRENT_DS_SHIFT	32
+#define TI_FLAG_BYTE_FPDEPTH		4
+#define TI_FLAG_FPDEPTH_SHIFT		24
+#define TI_FLAG_BYTE_WSAVED		5
+#define TI_FLAG_WSAVED_SHIFT		16
+
+#include <asm/page.h>
+
+#ifndef __ASSEMBLY__
+
+#include <asm/ptrace.h>
+#include <asm/types.h>
+
+struct task_struct;
+struct exec_domain;
+
+struct thread_info {
+	/* D$ line 1 */
+	struct task_struct	*task;
+	unsigned long		flags;
+	__u8			fpsaved[7];
+	__u8			status;
+	unsigned long		ksp;
+
+	/* D$ line 2 */
+	unsigned long		fault_address;
+	struct pt_regs		*kregs;
+	struct exec_domain	*exec_domain;
+	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	__u8			new_child;
+	__u8			syscall_noerror;
+	__u16			cpu;
+
+	unsigned long		*utraps;
+
+	struct reg_window 	reg_window[NSWINS];
+	unsigned long 		rwbuf_stkptrs[NSWINS];
+
+	unsigned long		gsr[7];
+	unsigned long		xfsr[7];
+
+	__u64			__user *user_cntd0;
+	__u64			__user *user_cntd1;
+	__u64			kernel_cntd0, kernel_cntd1;
+	__u64			pcr_reg;
+
+	struct restart_block	restart_block;
+
+	struct pt_regs		*kern_una_regs;
+	unsigned int		kern_una_insn;
+
+	unsigned long		fpregs[0] __attribute__ ((aligned(64)));
+};
+
+#endif /* !(__ASSEMBLY__) */
+
+/* offsets into the thread_info struct for assembly code access */
+#define TI_TASK		0x00000000
+#define TI_FLAGS	0x00000008
+#define TI_FAULT_CODE	(TI_FLAGS + TI_FLAG_BYTE_FAULT_CODE)
+#define TI_WSTATE	(TI_FLAGS + TI_FLAG_BYTE_WSTATE)
+#define TI_CWP		(TI_FLAGS + TI_FLAG_BYTE_CWP)
+#define TI_CURRENT_DS	(TI_FLAGS + TI_FLAG_BYTE_CURRENT_DS)
+#define TI_FPDEPTH	(TI_FLAGS + TI_FLAG_BYTE_FPDEPTH)
+#define TI_WSAVED	(TI_FLAGS + TI_FLAG_BYTE_WSAVED)
+#define TI_FPSAVED	0x00000010
+#define TI_KSP		0x00000018
+#define TI_FAULT_ADDR	0x00000020
+#define TI_KREGS	0x00000028
+#define TI_EXEC_DOMAIN	0x00000030
+#define TI_PRE_COUNT	0x00000038
+#define TI_NEW_CHILD	0x0000003c
+#define TI_SYS_NOERROR	0x0000003d
+#define TI_CPU		0x0000003e
+#define TI_UTRAPS	0x00000040
+#define TI_REG_WINDOW	0x00000048
+#define TI_RWIN_SPTRS	0x000003c8
+#define TI_GSR		0x00000400
+#define TI_XFSR		0x00000438
+#define TI_USER_CNTD0	0x00000470
+#define TI_USER_CNTD1	0x00000478
+#define TI_KERN_CNTD0	0x00000480
+#define TI_KERN_CNTD1	0x00000488
+#define TI_PCR		0x00000490
+#define TI_RESTART_BLOCK 0x00000498
+#define TI_KUNA_REGS	0x000004c0
+#define TI_KUNA_INSN	0x000004c8
+#define TI_FPREGS	0x00000500
+
+/* We embed this in the uppermost byte of thread_info->flags */
+#define FAULT_CODE_WRITE	0x01	/* Write access, implies D-TLB	   */
+#define FAULT_CODE_DTLB		0x02	/* Miss happened in D-TLB	   */
+#define FAULT_CODE_ITLB		0x04	/* Miss happened in I-TLB	   */
+#define FAULT_CODE_WINFIXUP	0x08	/* Miss happened during spill/fill */
+#define FAULT_CODE_BLKCOMMIT	0x10	/* Use blk-commit ASI in copy_page */
+
+#if PAGE_SHIFT == 13
+#define THREAD_SIZE (2*PAGE_SIZE)
+#define THREAD_SHIFT (PAGE_SHIFT + 1)
+#else /* PAGE_SHIFT == 13 */
+#define THREAD_SIZE PAGE_SIZE
+#define THREAD_SHIFT PAGE_SHIFT
+#endif /* PAGE_SHIFT == 13 */
+
+#define PREEMPT_ACTIVE		0x4000000
+
+/*
+ * macros/functions for gaining access to the thread information structure
+ *
+ * preempt_count needs to be 1 initially, until the scheduler is functional.
+ */
+#ifndef __ASSEMBLY__
+
+#define INIT_THREAD_INFO(tsk)				\
+{							\
+	.task		=	&tsk,			\
+	.flags		= ((unsigned long)ASI_P) << TI_FLAG_CURRENT_DS_SHIFT,	\
+	.exec_domain	=	&default_exec_domain,	\
+	.preempt_count	=	1,			\
+	.restart_block	= {				\
+		.fn	=	do_no_restart_syscall,	\
+	},						\
+}
+
+#define init_thread_info	(init_thread_union.thread_info)
+#define init_stack		(init_thread_union.stack)
+
+/* how to get the thread information struct from C */
+register struct thread_info *current_thread_info_reg asm("g6");
+#define current_thread_info()	(current_thread_info_reg)
+
+/* thread information allocation */
+#if PAGE_SHIFT == 13
+#define __THREAD_INFO_ORDER	1
+#else /* PAGE_SHIFT == 13 */
+#define __THREAD_INFO_ORDER	0
+#endif /* PAGE_SHIFT == 13 */
+
+#ifdef CONFIG_DEBUG_STACK_USAGE
+#define alloc_thread_info(tsk)					\
+({								\
+	struct thread_info *ret;				\
+								\
+	ret = (struct thread_info *)				\
+	  __get_free_pages(GFP_KERNEL, __THREAD_INFO_ORDER);	\
+	if (ret)						\
+		memset(ret, 0, PAGE_SIZE<<__THREAD_INFO_ORDER);	\
+	ret;							\
+})
+#else
+#define alloc_thread_info(tsk) \
+	((struct thread_info *)__get_free_pages(GFP_KERNEL, __THREAD_INFO_ORDER))
+#endif
+
+#define free_thread_info(ti) \
+	free_pages((unsigned long)(ti),__THREAD_INFO_ORDER)
+
+#define __thread_flag_byte_ptr(ti)	\
+	((unsigned char *)(&((ti)->flags)))
+#define __cur_thread_flag_byte_ptr	__thread_flag_byte_ptr(current_thread_info())
+
+#define get_thread_fault_code()		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FAULT_CODE])
+#define set_thread_fault_code(val)	(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FAULT_CODE] = (val))
+#define get_thread_wstate()		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSTATE])
+#define set_thread_wstate(val)		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSTATE] = (val))
+#define get_thread_cwp()		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP])
+#define set_thread_cwp(val)		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP] = (val))
+#define get_thread_current_ds()		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CURRENT_DS])
+#define set_thread_current_ds(val)	(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CURRENT_DS] = (val))
+#define get_thread_fpdepth()		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH])
+#define set_thread_fpdepth(val)		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH] = (val))
+#define get_thread_wsaved()		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED])
+#define set_thread_wsaved(val)		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED] = (val))
+
+#endif /* !(__ASSEMBLY__) */
+
+/*
+ * Thread information flags, only 16 bits are available as we encode
+ * other values into the upper 6 bytes.
+ *
+ * On trap return we need to test several values:
+ *
+ * user:	need_resched, notify_resume, sigpending, wsaved, perfctr
+ * kernel:	fpdepth
+ *
+ * So to check for work in the kernel case we simply load the fpdepth
+ * byte out of the flags and test it.  For the user case we encode the
+ * lower 3 bytes of flags as follows:
+ *	----------------------------------------
+ *	| wsaved | flags byte 1 | flags byte 2 |
+ *	----------------------------------------
+ * This optimizes the user test into:
+ *	ldx		[%g6 + TI_FLAGS], REG1
+ *	sethi		%hi(_TIF_USER_WORK_MASK), REG2
+ *	or		REG2, %lo(_TIF_USER_WORK_MASK), REG2
+ *	andcc		REG1, REG2, %g0
+ *	be,pt		no_work_to_do
+ *	 nop
+ */
+#define TIF_SYSCALL_TRACE	0	/* syscall trace active */
+/* flags bit 1 is available */
+#define TIF_SIGPENDING		2	/* signal pending */
+#define TIF_NEED_RESCHED	3	/* rescheduling necessary */
+#define TIF_PERFCTR		4	/* performance counters active */
+#define TIF_UNALIGNED		5	/* allowed to do unaligned accesses */
+/* flag bit 6 is available */
+#define TIF_32BIT		7	/* 32-bit binary */
+/* flag bit 8 is available */
+#define TIF_SECCOMP		9	/* secure computing */
+#define TIF_SYSCALL_AUDIT	10	/* syscall auditing active */
+/* flag bit 11 is available */
+/* NOTE: Thread flags >= 12 should be ones we have no interest
+ *       in using in assembly, else we can't use the mask as
+ *       an immediate value in instructions such as andcc.
+ */
+#define TIF_ABI_PENDING		12
+#define TIF_MEMDIE		13
+#define TIF_POLLING_NRFLAG	14
+
+#define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
+#define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
+#define _TIF_PERFCTR		(1<<TIF_PERFCTR)
+#define _TIF_UNALIGNED		(1<<TIF_UNALIGNED)
+#define _TIF_32BIT		(1<<TIF_32BIT)
+#define _TIF_SECCOMP		(1<<TIF_SECCOMP)
+#define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
+#define _TIF_ABI_PENDING	(1<<TIF_ABI_PENDING)
+#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+
+#define _TIF_USER_WORK_MASK	((0xff << TI_FLAG_WSAVED_SHIFT) | \
+				 (_TIF_SIGPENDING | \
+				  _TIF_NEED_RESCHED | _TIF_PERFCTR))
+
+/*
+ * Thread-synchronous status.
+ *
+ * This is different from the flags in that nobody else
+ * ever touches our thread-synchronous status, so we don't
+ * have to worry about atomic accesses.
+ *
+ * Note that there are only 8 bits available.
+ */
+#define TS_RESTORE_SIGMASK	0x0001	/* restore signal mask in do_signal() */
+
+#ifndef __ASSEMBLY__
+#define HAVE_SET_RESTORE_SIGMASK	1
+static inline void set_restore_sigmask(void)
+{
+	struct thread_info *ti = current_thread_info();
+	ti->status |= TS_RESTORE_SIGMASK;
+	set_bit(TIF_SIGPENDING, &ti->flags);
+}
+#endif	/* !__ASSEMBLY__ */
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_THREAD_INFO_H */
diff --git a/include/asm-sparc/timer.h b/include/asm-sparc/timer.h
index d909565..475baa0 100644
--- a/include/asm-sparc/timer.h
+++ b/include/asm-sparc/timer.h
@@ -1,109 +1,8 @@
-/*
- * timer.h:  Definitions for the timer chips on the Sparc.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-
-
-#ifndef _SPARC_TIMER_H
-#define _SPARC_TIMER_H
-
-#include <asm/system.h>  /* For SUN4M_NCPUS */
-#include <asm/sun4paddr.h>
-#include <asm/btfixup.h>
-
-/* Timer structures. The interrupt timer has two properties which
- * are the counter (which is handled in do_timer in sched.c) and the limit.
- * This limit is where the timer's counter 'wraps' around. Oddly enough,
- * the sun4c timer when it hits the limit wraps back to 1 and not zero
- * thus when calculating the value at which it will fire a microsecond you
- * must adjust by one.  Thanks SUN for designing such great hardware ;(
- */
-
-/* Note that I am only going to use the timer that interrupts at
- * Sparc IRQ 10.  There is another one available that can fire at
- * IRQ 14. Currently it is left untouched, we keep the PROM's limit
- * register value and let the prom take these interrupts.  This allows
- * L1-A to work.
- */
-
-struct sun4c_timer_info {
-  __volatile__ unsigned int cur_count10;
-  __volatile__ unsigned int timer_limit10;
-  __volatile__ unsigned int cur_count14;
-  __volatile__ unsigned int timer_limit14;
-};
-
-#define SUN4C_TIMER_PHYSADDR   0xf3000000
-#ifdef CONFIG_SUN4
-#define SUN_TIMER_PHYSADDR SUN4_300_TIMER_PHYSADDR
+#ifndef ___ASM_SPARC_TIMER_H
+#define ___ASM_SPARC_TIMER_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/timer_64.h>
 #else
-#define SUN_TIMER_PHYSADDR SUN4C_TIMER_PHYSADDR
+#include <asm-sparc/timer_32.h>
 #endif
-
-/* A sun4m has two blocks of registers which are probably of the same
- * structure. LSI Logic's L64851 is told to _decrement_ from the limit
- * value. Aurora behaves similarly but its limit value is compacted in
- * other fashion (it's wider). Documented fields are defined here.
- */
-
-/* As with the interrupt register, we have two classes of timer registers
- * which are per-cpu and master.  Per-cpu timers only hit that cpu and are
- * only level 14 ticks, master timer hits all cpus and is level 10.
- */
-
-#define SUN4M_PRM_CNT_L       0x80000000
-#define SUN4M_PRM_CNT_LVALUE  0x7FFFFC00
-
-struct sun4m_timer_percpu_info {
-  __volatile__ unsigned int l14_timer_limit;    /* Initial value is 0x009c4000 */
-  __volatile__ unsigned int l14_cur_count;
-
-  /* This register appears to be write only and/or inaccessible
-   * on Uni-Processor sun4m machines.
-   */
-  __volatile__ unsigned int l14_limit_noclear;  /* Data access error is here */
-
-  __volatile__ unsigned int cntrl;            /* =1 after POST on Aurora */
-  __volatile__ unsigned char space[PAGE_SIZE - 16];
-};
-
-struct sun4m_timer_regs {
-	struct sun4m_timer_percpu_info cpu_timers[SUN4M_NCPUS];
-	volatile unsigned int l10_timer_limit;
-	volatile unsigned int l10_cur_count;
-
-	/* Again, this appears to be write only and/or inaccessible
-	 * on uni-processor sun4m machines.
-	 */
-	volatile unsigned int l10_limit_noclear;
-
-	/* This register too, it must be magic. */
-	volatile unsigned int foobar;
-
-	volatile unsigned int cfg;     /* equals zero at boot time... */
-};
-
-extern struct sun4m_timer_regs *sun4m_timers;
-
-#define SUN4D_PRM_CNT_L       0x80000000
-#define SUN4D_PRM_CNT_LVALUE  0x7FFFFC00
-
-struct sun4d_timer_regs {
-	volatile unsigned int l10_timer_limit;
-	volatile unsigned int l10_cur_countx;
-	volatile unsigned int l10_limit_noclear;
-	volatile unsigned int ctrl;
-	volatile unsigned int l10_cur_count;
-};
-
-extern struct sun4d_timer_regs *sun4d_timers;
-
-extern __volatile__ unsigned int *master_l10_counter;
-extern __volatile__ unsigned int *master_l10_limit;
-
-/* FIXME: Make do_[gs]ettimeofday btfixup calls */
-BTFIXUPDEF_CALL(int, bus_do_settimeofday, struct timespec *tv)
-#define bus_do_settimeofday(tv) BTFIXUP_CALL(bus_do_settimeofday)(tv)
-
-#endif /* !(_SPARC_TIMER_H) */
+#endif
diff --git a/include/asm-sparc/timer_32.h b/include/asm-sparc/timer_32.h
new file mode 100644
index 0000000..361e538
--- /dev/null
+++ b/include/asm-sparc/timer_32.h
@@ -0,0 +1,107 @@
+/*
+ * timer.h:  Definitions for the timer chips on the Sparc.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+
+#ifndef _SPARC_TIMER_H
+#define _SPARC_TIMER_H
+
+#include <asm/system.h>  /* For SUN4M_NCPUS */
+#include <asm/sun4paddr.h>
+#include <asm/btfixup.h>
+
+/* Timer structures. The interrupt timer has two properties which
+ * are the counter (which is handled in do_timer in sched.c) and the limit.
+ * This limit is where the timer's counter 'wraps' around. Oddly enough,
+ * the sun4c timer when it hits the limit wraps back to 1 and not zero
+ * thus when calculating the value at which it will fire a microsecond you
+ * must adjust by one.  Thanks SUN for designing such great hardware ;(
+ */
+
+/* Note that I am only going to use the timer that interrupts at
+ * Sparc IRQ 10.  There is another one available that can fire at
+ * IRQ 14. Currently it is left untouched, we keep the PROM's limit
+ * register value and let the prom take these interrupts.  This allows
+ * L1-A to work.
+ */
+
+struct sun4c_timer_info {
+  __volatile__ unsigned int cur_count10;
+  __volatile__ unsigned int timer_limit10;
+  __volatile__ unsigned int cur_count14;
+  __volatile__ unsigned int timer_limit14;
+};
+
+#define SUN4C_TIMER_PHYSADDR   0xf3000000
+#ifdef CONFIG_SUN4
+#define SUN_TIMER_PHYSADDR SUN4_300_TIMER_PHYSADDR
+#else
+#define SUN_TIMER_PHYSADDR SUN4C_TIMER_PHYSADDR
+#endif
+
+/* A sun4m has two blocks of registers which are probably of the same
+ * structure. LSI Logic's L64851 is told to _decrement_ from the limit
+ * value. Aurora behaves similarly but its limit value is compacted in
+ * other fashion (it's wider). Documented fields are defined here.
+ */
+
+/* As with the interrupt register, we have two classes of timer registers
+ * which are per-cpu and master.  Per-cpu timers only hit that cpu and are
+ * only level 14 ticks, master timer hits all cpus and is level 10.
+ */
+
+#define SUN4M_PRM_CNT_L       0x80000000
+#define SUN4M_PRM_CNT_LVALUE  0x7FFFFC00
+
+struct sun4m_timer_percpu_info {
+  __volatile__ unsigned int l14_timer_limit;    /* Initial value is 0x009c4000 */
+  __volatile__ unsigned int l14_cur_count;
+
+  /* This register appears to be write only and/or inaccessible
+   * on Uni-Processor sun4m machines.
+   */
+  __volatile__ unsigned int l14_limit_noclear;  /* Data access error is here */
+
+  __volatile__ unsigned int cntrl;            /* =1 after POST on Aurora */
+  __volatile__ unsigned char space[PAGE_SIZE - 16];
+};
+
+struct sun4m_timer_regs {
+	struct sun4m_timer_percpu_info cpu_timers[SUN4M_NCPUS];
+	volatile unsigned int l10_timer_limit;
+	volatile unsigned int l10_cur_count;
+
+	/* Again, this appears to be write only and/or inaccessible
+	 * on uni-processor sun4m machines.
+	 */
+	volatile unsigned int l10_limit_noclear;
+
+	/* This register too, it must be magic. */
+	volatile unsigned int foobar;
+
+	volatile unsigned int cfg;     /* equals zero at boot time... */
+};
+
+#define SUN4D_PRM_CNT_L       0x80000000
+#define SUN4D_PRM_CNT_LVALUE  0x7FFFFC00
+
+struct sun4d_timer_regs {
+	volatile unsigned int l10_timer_limit;
+	volatile unsigned int l10_cur_countx;
+	volatile unsigned int l10_limit_noclear;
+	volatile unsigned int ctrl;
+	volatile unsigned int l10_cur_count;
+};
+
+extern struct sun4d_timer_regs *sun4d_timers;
+
+extern __volatile__ unsigned int *master_l10_counter;
+extern __volatile__ unsigned int *master_l10_limit;
+
+/* FIXME: Make do_[gs]ettimeofday btfixup calls */
+BTFIXUPDEF_CALL(int, bus_do_settimeofday, struct timespec *tv)
+#define bus_do_settimeofday(tv) BTFIXUP_CALL(bus_do_settimeofday)(tv)
+
+#endif /* !(_SPARC_TIMER_H) */
diff --git a/include/asm-sparc/timer_64.h b/include/asm-sparc/timer_64.h
new file mode 100644
index 0000000..5b779fd
--- /dev/null
+++ b/include/asm-sparc/timer_64.h
@@ -0,0 +1,30 @@
+/* timer.h: System timer definitions for sun5.
+ *
+ * Copyright (C) 1997, 2008 David S. Miller (davem@davemloft.net)
+ */
+
+#ifndef _SPARC64_TIMER_H
+#define _SPARC64_TIMER_H
+
+#include <linux/types.h>
+#include <linux/init.h>
+
+struct sparc64_tick_ops {
+	unsigned long (*get_tick)(void);
+	int (*add_compare)(unsigned long);
+	unsigned long softint_mask;
+	void (*disable_irq)(void);
+
+	void (*init_tick)(void);
+	unsigned long (*add_tick)(unsigned long);
+
+	char *name;
+};
+
+extern struct sparc64_tick_ops *tick_ops;
+
+extern unsigned long sparc64_get_clock_tick(unsigned int cpu);
+extern void __devinit setup_sparc64_timer(void);
+extern void __init time_init(void);
+
+#endif /* _SPARC64_TIMER_H */
diff --git a/include/asm-sparc/timex.h b/include/asm-sparc/timex.h
index 71b45c9..01d9f19 100644
--- a/include/asm-sparc/timex.h
+++ b/include/asm-sparc/timex.h
@@ -1,15 +1,8 @@
-/*
- * linux/include/asm-sparc/timex.h
- *
- * sparc architecture timex specifications
- */
-#ifndef _ASMsparc_TIMEX_H
-#define _ASMsparc_TIMEX_H
-
-#define CLOCK_TICK_RATE	1193180 /* Underlying HZ */
-
-/* XXX Maybe do something better at some point... -DaveM */
-typedef unsigned long cycles_t;
-#define get_cycles()	(0)
-
+#ifndef ___ASM_SPARC_TIMEX_H
+#define ___ASM_SPARC_TIMEX_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/timex_64.h>
+#else
+#include <asm-sparc/timex_32.h>
+#endif
 #endif
diff --git a/include/asm-sparc/timex_32.h b/include/asm-sparc/timex_32.h
new file mode 100644
index 0000000..71b45c9
--- /dev/null
+++ b/include/asm-sparc/timex_32.h
@@ -0,0 +1,15 @@
+/*
+ * linux/include/asm-sparc/timex.h
+ *
+ * sparc architecture timex specifications
+ */
+#ifndef _ASMsparc_TIMEX_H
+#define _ASMsparc_TIMEX_H
+
+#define CLOCK_TICK_RATE	1193180 /* Underlying HZ */
+
+/* XXX Maybe do something better at some point... -DaveM */
+typedef unsigned long cycles_t;
+#define get_cycles()	(0)
+
+#endif
diff --git a/include/asm-sparc/timex_64.h b/include/asm-sparc/timex_64.h
new file mode 100644
index 0000000..c622535
--- /dev/null
+++ b/include/asm-sparc/timex_64.h
@@ -0,0 +1,19 @@
+/*
+ * linux/include/asm-sparc64/timex.h
+ *
+ * sparc64 architecture timex specifications
+ */
+#ifndef _ASMsparc64_TIMEX_H
+#define _ASMsparc64_TIMEX_H
+
+#include <asm/timer.h>
+
+#define CLOCK_TICK_RATE	1193180 /* Underlying HZ */
+
+/* Getting on the cycle counter on sparc64. */
+typedef unsigned long cycles_t;
+#define get_cycles()	tick_ops->get_tick()
+
+#define ARCH_HAS_READ_CURRENT_TIMER
+
+#endif
diff --git a/include/asm-sparc/tlb.h b/include/asm-sparc/tlb.h
index 6d02d1c..a821057 100644
--- a/include/asm-sparc/tlb.h
+++ b/include/asm-sparc/tlb.h
@@ -1,24 +1,8 @@
-#ifndef _SPARC_TLB_H
-#define _SPARC_TLB_H
-
-#define tlb_start_vma(tlb, vma) \
-do {								\
-	flush_cache_range(vma, vma->vm_start, vma->vm_end);	\
-} while (0)
-
-#define tlb_end_vma(tlb, vma) \
-do {								\
-	flush_tlb_range(vma, vma->vm_start, vma->vm_end);	\
-} while (0)
-
-#define __tlb_remove_tlb_entry(tlb, pte, address) \
-	do { } while (0)
-
-#define tlb_flush(tlb) \
-do {								\
-	flush_tlb_mm((tlb)->mm);				\
-} while (0)
-
-#include <asm-generic/tlb.h>
-
-#endif /* _SPARC_TLB_H */
+#ifndef ___ASM_SPARC_TLB_H
+#define ___ASM_SPARC_TLB_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/tlb_64.h>
+#else
+#include <asm-sparc/tlb_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/tlb_32.h b/include/asm-sparc/tlb_32.h
new file mode 100644
index 0000000..6d02d1c
--- /dev/null
+++ b/include/asm-sparc/tlb_32.h
@@ -0,0 +1,24 @@
+#ifndef _SPARC_TLB_H
+#define _SPARC_TLB_H
+
+#define tlb_start_vma(tlb, vma) \
+do {								\
+	flush_cache_range(vma, vma->vm_start, vma->vm_end);	\
+} while (0)
+
+#define tlb_end_vma(tlb, vma) \
+do {								\
+	flush_tlb_range(vma, vma->vm_start, vma->vm_end);	\
+} while (0)
+
+#define __tlb_remove_tlb_entry(tlb, pte, address) \
+	do { } while (0)
+
+#define tlb_flush(tlb) \
+do {								\
+	flush_tlb_mm((tlb)->mm);				\
+} while (0)
+
+#include <asm-generic/tlb.h>
+
+#endif /* _SPARC_TLB_H */
diff --git a/include/asm-sparc/tlb_64.h b/include/asm-sparc/tlb_64.h
new file mode 100644
index 0000000..ec81cde
--- /dev/null
+++ b/include/asm-sparc/tlb_64.h
@@ -0,0 +1,111 @@
+#ifndef _SPARC64_TLB_H
+#define _SPARC64_TLB_H
+
+#include <linux/swap.h>
+#include <linux/pagemap.h>
+#include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
+#include <asm/mmu_context.h>
+
+#define TLB_BATCH_NR	192
+
+/*
+ * For UP we don't need to worry about TLB flush
+ * and page free order so much..
+ */
+#ifdef CONFIG_SMP
+  #define FREE_PTE_NR	506
+  #define tlb_fast_mode(bp) ((bp)->pages_nr == ~0U)
+#else
+  #define FREE_PTE_NR	1
+  #define tlb_fast_mode(bp) 1
+#endif
+
+struct mmu_gather {
+	struct mm_struct *mm;
+	unsigned int pages_nr;
+	unsigned int need_flush;
+	unsigned int fullmm;
+	unsigned int tlb_nr;
+	unsigned long vaddrs[TLB_BATCH_NR];
+	struct page *pages[FREE_PTE_NR];
+};
+
+DECLARE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+#ifdef CONFIG_SMP
+extern void smp_flush_tlb_pending(struct mm_struct *,
+				  unsigned long, unsigned long *);
+#endif
+
+extern void __flush_tlb_pending(unsigned long, unsigned long, unsigned long *);
+extern void flush_tlb_pending(void);
+
+static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
+{
+	struct mmu_gather *mp = &get_cpu_var(mmu_gathers);
+
+	BUG_ON(mp->tlb_nr);
+
+	mp->mm = mm;
+	mp->pages_nr = num_online_cpus() > 1 ? 0U : ~0U;
+	mp->fullmm = full_mm_flush;
+
+	return mp;
+}
+
+
+static inline void tlb_flush_mmu(struct mmu_gather *mp)
+{
+	if (mp->need_flush) {
+		free_pages_and_swap_cache(mp->pages, mp->pages_nr);
+		mp->pages_nr = 0;
+		mp->need_flush = 0;
+	}
+
+}
+
+#ifdef CONFIG_SMP
+extern void smp_flush_tlb_mm(struct mm_struct *mm);
+#define do_flush_tlb_mm(mm) smp_flush_tlb_mm(mm)
+#else
+#define do_flush_tlb_mm(mm) __flush_tlb_mm(CTX_HWBITS(mm->context), SECONDARY_CONTEXT)
+#endif
+
+static inline void tlb_finish_mmu(struct mmu_gather *mp, unsigned long start, unsigned long end)
+{
+	tlb_flush_mmu(mp);
+
+	if (mp->fullmm)
+		mp->fullmm = 0;
+	else
+		flush_tlb_pending();
+
+	/* keep the page table cache within bounds */
+	check_pgt_cache();
+
+	put_cpu_var(mmu_gathers);
+}
+
+static inline void tlb_remove_page(struct mmu_gather *mp, struct page *page)
+{
+	if (tlb_fast_mode(mp)) {
+		free_page_and_swap_cache(page);
+		return;
+	}
+	mp->need_flush = 1;
+	mp->pages[mp->pages_nr++] = page;
+	if (mp->pages_nr >= FREE_PTE_NR)
+		tlb_flush_mmu(mp);
+}
+
+#define tlb_remove_tlb_entry(mp,ptep,addr) do { } while (0)
+#define pte_free_tlb(mp, ptepage) pte_free((mp)->mm, ptepage)
+#define pmd_free_tlb(mp, pmdp) pmd_free((mp)->mm, pmdp)
+#define pud_free_tlb(tlb,pudp) __pud_free_tlb(tlb,pudp)
+
+#define tlb_migrate_finish(mm)	do { } while (0)
+#define tlb_start_vma(tlb, vma) do { } while (0)
+#define tlb_end_vma(tlb, vma)	do { } while (0)
+
+#endif /* _SPARC64_TLB_H */
diff --git a/include/asm-sparc/tlbflush.h b/include/asm-sparc/tlbflush.h
index b957e29..6e6bc12 100644
--- a/include/asm-sparc/tlbflush.h
+++ b/include/asm-sparc/tlbflush.h
@@ -1,60 +1,8 @@
-#ifndef _SPARC_TLBFLUSH_H
-#define _SPARC_TLBFLUSH_H
-
-#include <linux/mm.h>
-// #include <asm/processor.h>
-
-/*
- * TLB flushing:
- *
- *  - flush_tlb() flushes the current mm struct TLBs	XXX Exists?
- *  - flush_tlb_all() flushes all processes TLBs 
- *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
- *  - flush_tlb_page(vma, vmaddr) flushes one page
- *  - flush_tlb_range(vma, start, end) flushes a range of pages
- *  - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
- */
-
-#ifdef CONFIG_SMP
-
-BTFIXUPDEF_CALL(void, local_flush_tlb_all, void)
-BTFIXUPDEF_CALL(void, local_flush_tlb_mm, struct mm_struct *)
-BTFIXUPDEF_CALL(void, local_flush_tlb_range, struct vm_area_struct *, unsigned long, unsigned long)
-BTFIXUPDEF_CALL(void, local_flush_tlb_page, struct vm_area_struct *, unsigned long)
-
-#define local_flush_tlb_all() BTFIXUP_CALL(local_flush_tlb_all)()
-#define local_flush_tlb_mm(mm) BTFIXUP_CALL(local_flush_tlb_mm)(mm)
-#define local_flush_tlb_range(vma,start,end) BTFIXUP_CALL(local_flush_tlb_range)(vma,start,end)
-#define local_flush_tlb_page(vma,addr) BTFIXUP_CALL(local_flush_tlb_page)(vma,addr)
-
-extern void smp_flush_tlb_all(void);
-extern void smp_flush_tlb_mm(struct mm_struct *mm);
-extern void smp_flush_tlb_range(struct vm_area_struct *vma,
-				  unsigned long start,
-				  unsigned long end);
-extern void smp_flush_tlb_page(struct vm_area_struct *mm, unsigned long page);
-
-#endif /* CONFIG_SMP */
-
-BTFIXUPDEF_CALL(void, flush_tlb_all, void)
-BTFIXUPDEF_CALL(void, flush_tlb_mm, struct mm_struct *)
-BTFIXUPDEF_CALL(void, flush_tlb_range, struct vm_area_struct *, unsigned long, unsigned long)
-BTFIXUPDEF_CALL(void, flush_tlb_page, struct vm_area_struct *, unsigned long)
-
-#define flush_tlb_all() BTFIXUP_CALL(flush_tlb_all)()
-#define flush_tlb_mm(mm) BTFIXUP_CALL(flush_tlb_mm)(mm)
-#define flush_tlb_range(vma,start,end) BTFIXUP_CALL(flush_tlb_range)(vma,start,end)
-#define flush_tlb_page(vma,addr) BTFIXUP_CALL(flush_tlb_page)(vma,addr)
-
-// #define flush_tlb() flush_tlb_mm(current->active_mm)	/* XXX Sure? */
-
-/*
- * This is a kludge, until I know better. --zaitcev XXX
- */
-static inline void flush_tlb_kernel_range(unsigned long start,
-					  unsigned long end)
-{
-	flush_tlb_all();
-}
-
-#endif /* _SPARC_TLBFLUSH_H */
+#ifndef ___ASM_SPARC_TLBFLUSH_H
+#define ___ASM_SPARC_TLBFLUSH_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/tlbflush_64.h>
+#else
+#include <asm-sparc/tlbflush_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/tlbflush_32.h b/include/asm-sparc/tlbflush_32.h
new file mode 100644
index 0000000..fe0a71a
--- /dev/null
+++ b/include/asm-sparc/tlbflush_32.h
@@ -0,0 +1,60 @@
+#ifndef _SPARC_TLBFLUSH_H
+#define _SPARC_TLBFLUSH_H
+
+#include <linux/mm.h>
+// #include <asm/processor.h>
+
+/*
+ * TLB flushing:
+ *
+ *  - flush_tlb() flushes the current mm struct TLBs	XXX Exists?
+ *  - flush_tlb_all() flushes all processes TLBs
+ *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
+ *  - flush_tlb_page(vma, vmaddr) flushes one page
+ *  - flush_tlb_range(vma, start, end) flushes a range of pages
+ *  - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
+ */
+
+#ifdef CONFIG_SMP
+
+BTFIXUPDEF_CALL(void, local_flush_tlb_all, void)
+BTFIXUPDEF_CALL(void, local_flush_tlb_mm, struct mm_struct *)
+BTFIXUPDEF_CALL(void, local_flush_tlb_range, struct vm_area_struct *, unsigned long, unsigned long)
+BTFIXUPDEF_CALL(void, local_flush_tlb_page, struct vm_area_struct *, unsigned long)
+
+#define local_flush_tlb_all() BTFIXUP_CALL(local_flush_tlb_all)()
+#define local_flush_tlb_mm(mm) BTFIXUP_CALL(local_flush_tlb_mm)(mm)
+#define local_flush_tlb_range(vma,start,end) BTFIXUP_CALL(local_flush_tlb_range)(vma,start,end)
+#define local_flush_tlb_page(vma,addr) BTFIXUP_CALL(local_flush_tlb_page)(vma,addr)
+
+extern void smp_flush_tlb_all(void);
+extern void smp_flush_tlb_mm(struct mm_struct *mm);
+extern void smp_flush_tlb_range(struct vm_area_struct *vma,
+				  unsigned long start,
+				  unsigned long end);
+extern void smp_flush_tlb_page(struct vm_area_struct *mm, unsigned long page);
+
+#endif /* CONFIG_SMP */
+
+BTFIXUPDEF_CALL(void, flush_tlb_all, void)
+BTFIXUPDEF_CALL(void, flush_tlb_mm, struct mm_struct *)
+BTFIXUPDEF_CALL(void, flush_tlb_range, struct vm_area_struct *, unsigned long, unsigned long)
+BTFIXUPDEF_CALL(void, flush_tlb_page, struct vm_area_struct *, unsigned long)
+
+#define flush_tlb_all() BTFIXUP_CALL(flush_tlb_all)()
+#define flush_tlb_mm(mm) BTFIXUP_CALL(flush_tlb_mm)(mm)
+#define flush_tlb_range(vma,start,end) BTFIXUP_CALL(flush_tlb_range)(vma,start,end)
+#define flush_tlb_page(vma,addr) BTFIXUP_CALL(flush_tlb_page)(vma,addr)
+
+// #define flush_tlb() flush_tlb_mm(current->active_mm)	/* XXX Sure? */
+
+/*
+ * This is a kludge, until I know better. --zaitcev XXX
+ */
+static inline void flush_tlb_kernel_range(unsigned long start,
+					  unsigned long end)
+{
+	flush_tlb_all();
+}
+
+#endif /* _SPARC_TLBFLUSH_H */
diff --git a/include/asm-sparc/tlbflush_64.h b/include/asm-sparc/tlbflush_64.h
new file mode 100644
index 0000000..fbb675d
--- /dev/null
+++ b/include/asm-sparc/tlbflush_64.h
@@ -0,0 +1,44 @@
+#ifndef _SPARC64_TLBFLUSH_H
+#define _SPARC64_TLBFLUSH_H
+
+#include <linux/mm.h>
+#include <asm/mmu_context.h>
+
+/* TSB flush operations. */
+struct mmu_gather;
+extern void flush_tsb_kernel_range(unsigned long start, unsigned long end);
+extern void flush_tsb_user(struct mmu_gather *mp);
+
+/* TLB flush operations. */
+
+extern void flush_tlb_pending(void);
+
+#define flush_tlb_range(vma,start,end)	\
+	do { (void)(start); flush_tlb_pending(); } while (0)
+#define flush_tlb_page(vma,addr)	flush_tlb_pending()
+#define flush_tlb_mm(mm)		flush_tlb_pending()
+
+/* Local cpu only.  */
+extern void __flush_tlb_all(void);
+
+extern void __flush_tlb_kernel_range(unsigned long start, unsigned long end);
+
+#ifndef CONFIG_SMP
+
+#define flush_tlb_kernel_range(start,end) \
+do {	flush_tsb_kernel_range(start,end); \
+	__flush_tlb_kernel_range(start,end); \
+} while (0)
+
+#else /* CONFIG_SMP */
+
+extern void smp_flush_tlb_kernel_range(unsigned long start, unsigned long end);
+
+#define flush_tlb_kernel_range(start, end) \
+do {	flush_tsb_kernel_range(start,end); \
+	smp_flush_tlb_kernel_range(start, end); \
+} while (0)
+
+#endif /* ! CONFIG_SMP */
+
+#endif /* _SPARC64_TLBFLUSH_H */
diff --git a/include/asm-sparc/topology.h b/include/asm-sparc/topology.h
index ee5ac9c..ed13630 100644
--- a/include/asm-sparc/topology.h
+++ b/include/asm-sparc/topology.h
@@ -1,6 +1,8 @@
-#ifndef _ASM_SPARC_TOPOLOGY_H
-#define _ASM_SPARC_TOPOLOGY_H
-
-#include <asm-generic/topology.h>
-
-#endif /* _ASM_SPARC_TOPOLOGY_H */
+#ifndef ___ASM_SPARC_TOPOLOGY_H
+#define ___ASM_SPARC_TOPOLOGY_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/topology_64.h>
+#else
+#include <asm-sparc/topology_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/topology_32.h b/include/asm-sparc/topology_32.h
new file mode 100644
index 0000000..ee5ac9c
--- /dev/null
+++ b/include/asm-sparc/topology_32.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_SPARC_TOPOLOGY_H
+#define _ASM_SPARC_TOPOLOGY_H
+
+#include <asm-generic/topology.h>
+
+#endif /* _ASM_SPARC_TOPOLOGY_H */
diff --git a/include/asm-sparc/topology_64.h b/include/asm-sparc/topology_64.h
new file mode 100644
index 0000000..001c040
--- /dev/null
+++ b/include/asm-sparc/topology_64.h
@@ -0,0 +1,86 @@
+#ifndef _ASM_SPARC64_TOPOLOGY_H
+#define _ASM_SPARC64_TOPOLOGY_H
+
+#ifdef CONFIG_NUMA
+
+#include <asm/mmzone.h>
+
+static inline int cpu_to_node(int cpu)
+{
+	return numa_cpu_lookup_table[cpu];
+}
+
+#define parent_node(node)	(node)
+
+static inline cpumask_t node_to_cpumask(int node)
+{
+	return numa_cpumask_lookup_table[node];
+}
+
+/* Returns a pointer to the cpumask of CPUs on Node 'node'. */
+#define node_to_cpumask_ptr(v, node)		\
+		cpumask_t *v = &(numa_cpumask_lookup_table[node])
+
+#define node_to_cpumask_ptr_next(v, node)	\
+			   v = &(numa_cpumask_lookup_table[node])
+
+static inline int node_to_first_cpu(int node)
+{
+	cpumask_t tmp;
+	tmp = node_to_cpumask(node);
+	return first_cpu(tmp);
+}
+
+struct pci_bus;
+#ifdef CONFIG_PCI
+extern int pcibus_to_node(struct pci_bus *pbus);
+#else
+static inline int pcibus_to_node(struct pci_bus *pbus)
+{
+	return -1;
+}
+#endif
+
+#define pcibus_to_cpumask(bus)	\
+	(pcibus_to_node(bus) == -1 ? \
+	 CPU_MASK_ALL : \
+	 node_to_cpumask(pcibus_to_node(bus)))
+
+#define SD_NODE_INIT (struct sched_domain) {		\
+	.min_interval		= 8,			\
+	.max_interval		= 32,			\
+	.busy_factor		= 32,			\
+	.imbalance_pct		= 125,			\
+	.cache_nice_tries	= 2,			\
+	.busy_idx		= 3,			\
+	.idle_idx		= 2,			\
+	.newidle_idx		= 0, 			\
+	.wake_idx		= 1,			\
+	.forkexec_idx		= 1,			\
+	.flags			= SD_LOAD_BALANCE	\
+				| SD_BALANCE_FORK	\
+				| SD_BALANCE_EXEC	\
+				| SD_SERIALIZE		\
+				| SD_WAKE_BALANCE,	\
+	.last_balance		= jiffies,		\
+	.balance_interval	= 1,			\
+}
+
+#else /* CONFIG_NUMA */
+
+#include <asm-generic/topology.h>
+
+#endif /* !(CONFIG_NUMA) */
+
+#ifdef CONFIG_SMP
+#define topology_physical_package_id(cpu)	(cpu_data(cpu).proc_id)
+#define topology_core_id(cpu)			(cpu_data(cpu).core_id)
+#define topology_core_siblings(cpu)		(cpu_core_map[cpu])
+#define topology_thread_siblings(cpu)		(per_cpu(cpu_sibling_map, cpu))
+#define mc_capable()				(sparc64_multi_core)
+#define smt_capable()				(sparc64_multi_core)
+#endif /* CONFIG_SMP */
+
+#define cpu_coregroup_map(cpu)			(cpu_core_map[cpu])
+
+#endif /* _ASM_SPARC64_TOPOLOGY_H */
diff --git a/include/asm-sparc/tsb.h b/include/asm-sparc/tsb.h
new file mode 100644
index 0000000..76e4299
--- /dev/null
+++ b/include/asm-sparc/tsb.h
@@ -0,0 +1,283 @@
+#ifndef _SPARC64_TSB_H
+#define _SPARC64_TSB_H
+
+/* The sparc64 TSB is similar to the powerpc hashtables.  It's a
+ * power-of-2 sized table of TAG/PTE pairs.  The cpu precomputes
+ * pointers into this table for 8K and 64K page sizes, and also a
+ * comparison TAG based upon the virtual address and context which
+ * faults.
+ *
+ * TLB miss trap handler software does the actual lookup via something
+ * of the form:
+ *
+ * 	ldxa		[%g0] ASI_{D,I}MMU_TSB_8KB_PTR, %g1
+ * 	ldxa		[%g0] ASI_{D,I}MMU, %g6
+ *	sllx		%g6, 22, %g6
+ *	srlx		%g6, 22, %g6
+ * 	ldda		[%g1] ASI_NUCLEUS_QUAD_LDD, %g4
+ * 	cmp		%g4, %g6
+ * 	bne,pn	%xcc, tsb_miss_{d,i}tlb
+ * 	 mov		FAULT_CODE_{D,I}TLB, %g3
+ * 	stxa		%g5, [%g0] ASI_{D,I}TLB_DATA_IN
+ * 	retry
+ *
+ *
+ * Each 16-byte slot of the TSB is the 8-byte tag and then the 8-byte
+ * PTE.  The TAG is of the same layout as the TLB TAG TARGET mmu
+ * register which is:
+ *
+ * -------------------------------------------------
+ * |  -  |  CONTEXT |  -  |    VADDR bits 63:22    |
+ * -------------------------------------------------
+ *  63 61 60      48 47 42 41                     0
+ *
+ * But actually, since we use per-mm TSB's, we zero out the CONTEXT
+ * field.
+ *
+ * Like the powerpc hashtables we need to use locking in order to
+ * synchronize while we update the entries.  PTE updates need locking
+ * as well.
+ *
+ * We need to carefully choose a lock bits for the TSB entry.  We
+ * choose to use bit 47 in the tag.  Also, since we never map anything
+ * at page zero in context zero, we use zero as an invalid tag entry.
+ * When the lock bit is set, this forces a tag comparison failure.
+ */
+
+#define TSB_TAG_LOCK_BIT	47
+#define TSB_TAG_LOCK_HIGH	(1 << (TSB_TAG_LOCK_BIT - 32))
+
+#define TSB_TAG_INVALID_BIT	46
+#define TSB_TAG_INVALID_HIGH	(1 << (TSB_TAG_INVALID_BIT - 32))
+
+#define TSB_MEMBAR	membar	#StoreStore
+
+/* Some cpus support physical address quad loads.  We want to use
+ * those if possible so we don't need to hard-lock the TSB mapping
+ * into the TLB.  We encode some instruction patching in order to
+ * support this.
+ *
+ * The kernel TSB is locked into the TLB by virtue of being in the
+ * kernel image, so we don't play these games for swapper_tsb access.
+ */
+#ifndef __ASSEMBLY__
+struct tsb_ldquad_phys_patch_entry {
+	unsigned int	addr;
+	unsigned int	sun4u_insn;
+	unsigned int	sun4v_insn;
+};
+extern struct tsb_ldquad_phys_patch_entry __tsb_ldquad_phys_patch,
+	__tsb_ldquad_phys_patch_end;
+
+struct tsb_phys_patch_entry {
+	unsigned int	addr;
+	unsigned int	insn;
+};
+extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
+#endif
+#define TSB_LOAD_QUAD(TSB, REG)	\
+661:	ldda		[TSB] ASI_NUCLEUS_QUAD_LDD, REG; \
+	.section	.tsb_ldquad_phys_patch, "ax"; \
+	.word		661b; \
+	ldda		[TSB] ASI_QUAD_LDD_PHYS, REG; \
+	ldda		[TSB] ASI_QUAD_LDD_PHYS_4V, REG; \
+	.previous
+
+#define TSB_LOAD_TAG_HIGH(TSB, REG) \
+661:	lduwa		[TSB] ASI_N, REG; \
+	.section	.tsb_phys_patch, "ax"; \
+	.word		661b; \
+	lduwa		[TSB] ASI_PHYS_USE_EC, REG; \
+	.previous
+
+#define TSB_LOAD_TAG(TSB, REG) \
+661:	ldxa		[TSB] ASI_N, REG; \
+	.section	.tsb_phys_patch, "ax"; \
+	.word		661b; \
+	ldxa		[TSB] ASI_PHYS_USE_EC, REG; \
+	.previous
+
+#define TSB_CAS_TAG_HIGH(TSB, REG1, REG2) \
+661:	casa		[TSB] ASI_N, REG1, REG2; \
+	.section	.tsb_phys_patch, "ax"; \
+	.word		661b; \
+	casa		[TSB] ASI_PHYS_USE_EC, REG1, REG2; \
+	.previous
+
+#define TSB_CAS_TAG(TSB, REG1, REG2) \
+661:	casxa		[TSB] ASI_N, REG1, REG2; \
+	.section	.tsb_phys_patch, "ax"; \
+	.word		661b; \
+	casxa		[TSB] ASI_PHYS_USE_EC, REG1, REG2; \
+	.previous
+
+#define TSB_STORE(ADDR, VAL) \
+661:	stxa		VAL, [ADDR] ASI_N; \
+	.section	.tsb_phys_patch, "ax"; \
+	.word		661b; \
+	stxa		VAL, [ADDR] ASI_PHYS_USE_EC; \
+	.previous
+
+#define TSB_LOCK_TAG(TSB, REG1, REG2)	\
+99:	TSB_LOAD_TAG_HIGH(TSB, REG1);	\
+	sethi	%hi(TSB_TAG_LOCK_HIGH), REG2;\
+	andcc	REG1, REG2, %g0;	\
+	bne,pn	%icc, 99b;		\
+	 nop;				\
+	TSB_CAS_TAG_HIGH(TSB, REG1, REG2);	\
+	cmp	REG1, REG2;		\
+	bne,pn	%icc, 99b;		\
+	 nop;				\
+	TSB_MEMBAR
+
+#define TSB_WRITE(TSB, TTE, TAG) \
+	add	TSB, 0x8, TSB;   \
+	TSB_STORE(TSB, TTE);     \
+	sub	TSB, 0x8, TSB;   \
+	TSB_MEMBAR;              \
+	TSB_STORE(TSB, TAG);
+
+#define KTSB_LOAD_QUAD(TSB, REG) \
+	ldda		[TSB] ASI_NUCLEUS_QUAD_LDD, REG;
+
+#define KTSB_STORE(ADDR, VAL) \
+	stxa		VAL, [ADDR] ASI_N;
+
+#define KTSB_LOCK_TAG(TSB, REG1, REG2)	\
+99:	lduwa	[TSB] ASI_N, REG1;	\
+	sethi	%hi(TSB_TAG_LOCK_HIGH), REG2;\
+	andcc	REG1, REG2, %g0;	\
+	bne,pn	%icc, 99b;		\
+	 nop;				\
+	casa	[TSB] ASI_N, REG1, REG2;\
+	cmp	REG1, REG2;		\
+	bne,pn	%icc, 99b;		\
+	 nop;				\
+	TSB_MEMBAR
+
+#define KTSB_WRITE(TSB, TTE, TAG) \
+	add	TSB, 0x8, TSB;   \
+	stxa	TTE, [TSB] ASI_N;     \
+	sub	TSB, 0x8, TSB;   \
+	TSB_MEMBAR;              \
+	stxa	TAG, [TSB] ASI_N;
+
+	/* Do a kernel page table walk.  Leaves physical PTE pointer in
+	 * REG1.  Jumps to FAIL_LABEL on early page table walk termination.
+	 * VADDR will not be clobbered, but REG2 will.
+	 */
+#define KERN_PGTABLE_WALK(VADDR, REG1, REG2, FAIL_LABEL)	\
+	sethi		%hi(swapper_pg_dir), REG1; \
+	or		REG1, %lo(swapper_pg_dir), REG1; \
+	sllx		VADDR, 64 - (PGDIR_SHIFT + PGDIR_BITS), REG2; \
+	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
+	andn		REG2, 0x3, REG2; \
+	lduw		[REG1 + REG2], REG1; \
+	brz,pn		REG1, FAIL_LABEL; \
+	 sllx		VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \
+	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
+	sllx		REG1, 11, REG1; \
+	andn		REG2, 0x3, REG2; \
+	lduwa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
+	brz,pn		REG1, FAIL_LABEL; \
+	 sllx		VADDR, 64 - PMD_SHIFT, REG2; \
+	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
+	sllx		REG1, 11, REG1; \
+	andn		REG2, 0x7, REG2; \
+	add		REG1, REG2, REG1;
+
+	/* Do a user page table walk in MMU globals.  Leaves physical PTE
+	 * pointer in REG1.  Jumps to FAIL_LABEL on early page table walk
+	 * termination.  Physical base of page tables is in PHYS_PGD which
+	 * will not be modified.
+	 *
+	 * VADDR will not be clobbered, but REG1 and REG2 will.
+	 */
+#define USER_PGTABLE_WALK_TL1(VADDR, PHYS_PGD, REG1, REG2, FAIL_LABEL)	\
+	sllx		VADDR, 64 - (PGDIR_SHIFT + PGDIR_BITS), REG2; \
+	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
+	andn		REG2, 0x3, REG2; \
+	lduwa		[PHYS_PGD + REG2] ASI_PHYS_USE_EC, REG1; \
+	brz,pn		REG1, FAIL_LABEL; \
+	 sllx		VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \
+	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
+	sllx		REG1, 11, REG1; \
+	andn		REG2, 0x3, REG2; \
+	lduwa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
+	brz,pn		REG1, FAIL_LABEL; \
+	 sllx		VADDR, 64 - PMD_SHIFT, REG2; \
+	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
+	sllx		REG1, 11, REG1; \
+	andn		REG2, 0x7, REG2; \
+	add		REG1, REG2, REG1;
+
+/* Lookup a OBP mapping on VADDR in the prom_trans[] table at TL>0.
+ * If no entry is found, FAIL_LABEL will be branched to.  On success
+ * the resulting PTE value will be left in REG1.  VADDR is preserved
+ * by this routine.
+ */
+#define OBP_TRANS_LOOKUP(VADDR, REG1, REG2, REG3, FAIL_LABEL) \
+	sethi		%hi(prom_trans), REG1; \
+	or		REG1, %lo(prom_trans), REG1; \
+97:	ldx		[REG1 + 0x00], REG2; \
+	brz,pn		REG2, FAIL_LABEL; \
+	 nop; \
+	ldx		[REG1 + 0x08], REG3; \
+	add		REG2, REG3, REG3; \
+	cmp		REG2, VADDR; \
+	bgu,pt		%xcc, 98f; \
+	 cmp		VADDR, REG3; \
+	bgeu,pt		%xcc, 98f; \
+	 ldx		[REG1 + 0x10], REG3; \
+	sub		VADDR, REG2, REG2; \
+	ba,pt		%xcc, 99f; \
+	 add		REG3, REG2, REG1; \
+98:	ba,pt		%xcc, 97b; \
+	 add		REG1, (3 * 8), REG1; \
+99:
+
+	/* We use a 32K TSB for the whole kernel, this allows to
+	 * handle about 16MB of modules and vmalloc mappings without
+	 * incurring many hash conflicts.
+	 */
+#define KERNEL_TSB_SIZE_BYTES	(32 * 1024)
+#define KERNEL_TSB_NENTRIES	\
+	(KERNEL_TSB_SIZE_BYTES / 16)
+#define KERNEL_TSB4M_NENTRIES	4096
+
+	/* Do a kernel TSB lookup at tl>0 on VADDR+TAG, branch to OK_LABEL
+	 * on TSB hit.  REG1, REG2, REG3, and REG4 are used as temporaries
+	 * and the found TTE will be left in REG1.  REG3 and REG4 must
+	 * be an even/odd pair of registers.
+	 *
+	 * VADDR and TAG will be preserved and not clobbered by this macro.
+	 */
+#define KERN_TSB_LOOKUP_TL1(VADDR, TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
+	sethi		%hi(swapper_tsb), REG1; \
+	or		REG1, %lo(swapper_tsb), REG1; \
+	srlx		VADDR, PAGE_SHIFT, REG2; \
+	and		REG2, (KERNEL_TSB_NENTRIES - 1), REG2; \
+	sllx		REG2, 4, REG2; \
+	add		REG1, REG2, REG2; \
+	KTSB_LOAD_QUAD(REG2, REG3); \
+	cmp		REG3, TAG; \
+	be,a,pt		%xcc, OK_LABEL; \
+	 mov		REG4, REG1;
+
+#ifndef CONFIG_DEBUG_PAGEALLOC
+	/* This version uses a trick, the TAG is already (VADDR >> 22) so
+	 * we can make use of that for the index computation.
+	 */
+#define KERN_TSB4M_LOOKUP_TL1(TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
+	sethi		%hi(swapper_4m_tsb), REG1; \
+	or		REG1, %lo(swapper_4m_tsb), REG1; \
+	and		TAG, (KERNEL_TSB4M_NENTRIES - 1), REG2; \
+	sllx		REG2, 4, REG2; \
+	add		REG1, REG2, REG2; \
+	KTSB_LOAD_QUAD(REG2, REG3); \
+	cmp		REG3, TAG; \
+	be,a,pt		%xcc, OK_LABEL; \
+	 mov		REG4, REG1;
+#endif
+
+#endif /* !(_SPARC64_TSB_H) */
diff --git a/include/asm-sparc/ttable.h b/include/asm-sparc/ttable.h
new file mode 100644
index 0000000..5708ba2
--- /dev/null
+++ b/include/asm-sparc/ttable.h
@@ -0,0 +1,658 @@
+#ifndef _SPARC64_TTABLE_H
+#define _SPARC64_TTABLE_H
+
+#include <asm/utrap.h>
+
+#ifdef __ASSEMBLY__
+#include <asm/thread_info.h>
+#endif
+
+#define BOOT_KERNEL b sparc64_boot; nop; nop; nop; nop; nop; nop; nop;
+
+/* We need a "cleaned" instruction... */
+#define CLEAN_WINDOW							\
+	rdpr	%cleanwin, %l0;		add	%l0, 1, %l0;		\
+	wrpr	%l0, 0x0, %cleanwin;					\
+	clr	%o0;	clr	%o1;	clr	%o2;	clr	%o3;	\
+	clr	%o4;	clr	%o5;	clr	%o6;	clr	%o7;	\
+	clr	%l0;	clr	%l1;	clr	%l2;	clr	%l3;	\
+	clr	%l4;	clr	%l5;	clr	%l6;	clr	%l7;	\
+	retry;								\
+	nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;
+
+#define TRAP(routine)					\
+	sethi	%hi(109f), %g7;				\
+	ba,pt	%xcc, etrap;				\
+109:	 or	%g7, %lo(109b), %g7;			\
+	call	routine;				\
+	 add	%sp, PTREGS_OFF, %o0;			\
+	ba,pt	%xcc, rtrap;				\
+	 nop;						\
+	nop;
+
+#define TRAP_7INSNS(routine)				\
+	sethi	%hi(109f), %g7;				\
+	ba,pt	%xcc, etrap;				\
+109:	 or	%g7, %lo(109b), %g7;			\
+	call	routine;				\
+	 add	%sp, PTREGS_OFF, %o0;			\
+	ba,pt	%xcc, rtrap;				\
+	 nop;
+
+#define TRAP_SAVEFPU(routine)				\
+	sethi	%hi(109f), %g7;				\
+	ba,pt	%xcc, do_fptrap;			\
+109:	 or	%g7, %lo(109b), %g7;			\
+	call	routine;				\
+	 add	%sp, PTREGS_OFF, %o0;			\
+	ba,pt	%xcc, rtrap;				\
+	 nop;						\
+	nop;
+
+#define TRAP_NOSAVE(routine)				\
+	ba,pt	%xcc, routine;				\
+	 nop;						\
+	nop; nop; nop; nop; nop; nop;
+
+#define TRAP_NOSAVE_7INSNS(routine)			\
+	ba,pt	%xcc, routine;				\
+	 nop;						\
+	nop; nop; nop; nop; nop;
+
+#define TRAPTL1(routine)				\
+	sethi	%hi(109f), %g7;				\
+	ba,pt	%xcc, etraptl1;				\
+109:	 or	%g7, %lo(109b), %g7;			\
+	call	routine;				\
+	 add	%sp, PTREGS_OFF, %o0;			\
+	ba,pt	%xcc, rtrap;				\
+	 nop;						\
+	nop;
+
+#define TRAP_ARG(routine, arg)				\
+	sethi	%hi(109f), %g7;				\
+	ba,pt	%xcc, etrap;				\
+109:	 or	%g7, %lo(109b), %g7;			\
+	add	%sp, PTREGS_OFF, %o0;			\
+	call	routine;				\
+	 mov	arg, %o1;				\
+	ba,pt	%xcc, rtrap;				\
+	 nop;
+
+#define TRAPTL1_ARG(routine, arg)			\
+	sethi	%hi(109f), %g7;				\
+	ba,pt	%xcc, etraptl1;				\
+109:	 or	%g7, %lo(109b), %g7;			\
+	add	%sp, PTREGS_OFF, %o0;			\
+	call	routine;				\
+	 mov	arg, %o1;				\
+	ba,pt	%xcc, rtrap;				\
+	 nop;
+
+#define SYSCALL_TRAP(routine, systbl)			\
+	rdpr	%pil, %g2;				\
+	mov	TSTATE_SYSCALL, %g3;			\
+	sethi	%hi(109f), %g7;				\
+	ba,pt	%xcc, etrap_syscall;			\
+109:	 or	%g7, %lo(109b), %g7;			\
+	sethi	%hi(systbl), %l7;			\
+	ba,pt	%xcc, routine;				\
+	 or	%l7, %lo(systbl), %l7;
+
+#define TRAP_UTRAP(handler,lvl)				\
+	mov	handler, %g3;				\
+	ba,pt	%xcc, utrap_trap;			\
+	 mov	lvl, %g4;				\
+	nop;						\
+	nop;						\
+	nop;						\
+	nop;						\
+	nop;
+
+#ifdef CONFIG_COMPAT
+#define	LINUX_32BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall32, sys_call_table32)
+#else
+#define	LINUX_32BIT_SYSCALL_TRAP BTRAP(0x110)
+#endif
+#define LINUX_64BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall, sys_call_table64)
+#define GETCC_TRAP TRAP(getcc)
+#define SETCC_TRAP TRAP(setcc)
+#define BREAKPOINT_TRAP TRAP(breakpoint_trap)
+
+#ifdef CONFIG_TRACE_IRQFLAGS
+
+#define TRAP_IRQ(routine, level)			\
+	rdpr	%pil, %g2;				\
+	wrpr	%g0, 15, %pil;				\
+	sethi	%hi(1f-4), %g7;				\
+	ba,pt	%xcc, etrap_irq;			\
+	 or	%g7, %lo(1f-4), %g7;			\
+	nop;						\
+	nop;						\
+	nop;						\
+	.subsection	2;				\
+1:	call	trace_hardirqs_off;			\
+	 nop;						\
+	mov	level, %o0;				\
+	call	routine;				\
+	 add	%sp, PTREGS_OFF, %o1;			\
+	ba,a,pt	%xcc, rtrap_irq;			\
+	.previous;
+
+#else
+
+#define TRAP_IRQ(routine, level)			\
+	rdpr	%pil, %g2;				\
+	wrpr	%g0, 15, %pil;				\
+	ba,pt	%xcc, etrap_irq;			\
+	 rd	%pc, %g7;				\
+	mov	level, %o0;				\
+	call	routine;				\
+	 add	%sp, PTREGS_OFF, %o1;			\
+	ba,a,pt	%xcc, rtrap_irq;
+
+#endif
+
+#define TRAP_IVEC TRAP_NOSAVE(do_ivec)
+
+#define BTRAP(lvl) TRAP_ARG(bad_trap, lvl)
+
+#define BTRAPTL1(lvl) TRAPTL1_ARG(bad_trap_tl1, lvl)
+
+#define FLUSH_WINDOW_TRAP						\
+	ba,pt	%xcc, etrap;						\
+	 rd	%pc, %g7;						\
+	flushw;								\
+	ldx	[%sp + PTREGS_OFF + PT_V9_TNPC], %l1;			\
+	add	%l1, 4, %l2;						\
+	stx	%l1, [%sp + PTREGS_OFF + PT_V9_TPC];			\
+	ba,pt	%xcc, rtrap;						\
+	 stx	%l2, [%sp + PTREGS_OFF + PT_V9_TNPC];
+
+#ifdef CONFIG_KPROBES
+#define KPROBES_TRAP(lvl) TRAP_IRQ(kprobe_trap, lvl)
+#else
+#define KPROBES_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
+#endif
+
+#ifdef CONFIG_KGDB
+#define KGDB_TRAP(lvl) TRAP_IRQ(kgdb_trap, lvl)
+#else
+#define KGDB_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
+#endif
+
+#define SUN4V_ITSB_MISS					\
+	ldxa	[%g0] ASI_SCRATCHPAD, %g2;		\
+	ldx	[%g2 + HV_FAULT_I_ADDR_OFFSET], %g4;	\
+	ldx	[%g2 + HV_FAULT_I_CTX_OFFSET], %g5;	\
+	srlx	%g4, 22, %g6;				\
+	ba,pt	%xcc, sun4v_itsb_miss;			\
+	 nop;						\
+	nop;						\
+	nop;
+
+#define SUN4V_DTSB_MISS					\
+	ldxa	[%g0] ASI_SCRATCHPAD, %g2;		\
+	ldx	[%g2 + HV_FAULT_D_ADDR_OFFSET], %g4;	\
+	ldx	[%g2 + HV_FAULT_D_CTX_OFFSET], %g5;	\
+	srlx	%g4, 22, %g6;				\
+	ba,pt	%xcc, sun4v_dtsb_miss;			\
+	 nop;						\
+	nop;						\
+	nop;
+
+/* Before touching these macros, you owe it to yourself to go and
+ * see how arch/sparc64/kernel/winfixup.S works... -DaveM
+ *
+ * For the user cases we used to use the %asi register, but
+ * it turns out that the "wr xxx, %asi" costs ~5 cycles, so
+ * now we use immediate ASI loads and stores instead.  Kudos
+ * to Greg Onufer for pointing out this performance anomaly.
+ *
+ * Further note that we cannot use the g2, g4, g5, and g7 alternate
+ * globals in the spill routines, check out the save instruction in
+ * arch/sparc64/kernel/etrap.S to see what I mean about g2, and
+ * g4/g5 are the globals which are preserved by etrap processing
+ * for the caller of it.  The g7 register is the return pc for
+ * etrap.  Finally, g6 is the current thread register so we cannot
+ * us it in the spill handlers either.  Most of these rules do not
+ * apply to fill processing, only g6 is not usable.
+ */
+
+/* Normal kernel spill */
+#define SPILL_0_NORMAL					\
+	stx	%l0, [%sp + STACK_BIAS + 0x00];		\
+	stx	%l1, [%sp + STACK_BIAS + 0x08];		\
+	stx	%l2, [%sp + STACK_BIAS + 0x10];		\
+	stx	%l3, [%sp + STACK_BIAS + 0x18];		\
+	stx	%l4, [%sp + STACK_BIAS + 0x20];		\
+	stx	%l5, [%sp + STACK_BIAS + 0x28];		\
+	stx	%l6, [%sp + STACK_BIAS + 0x30];		\
+	stx	%l7, [%sp + STACK_BIAS + 0x38];		\
+	stx	%i0, [%sp + STACK_BIAS + 0x40];		\
+	stx	%i1, [%sp + STACK_BIAS + 0x48];		\
+	stx	%i2, [%sp + STACK_BIAS + 0x50];		\
+	stx	%i3, [%sp + STACK_BIAS + 0x58];		\
+	stx	%i4, [%sp + STACK_BIAS + 0x60];		\
+	stx	%i5, [%sp + STACK_BIAS + 0x68];		\
+	stx	%i6, [%sp + STACK_BIAS + 0x70];		\
+	stx	%i7, [%sp + STACK_BIAS + 0x78];		\
+	saved; retry; nop; nop; nop; nop; nop; nop;	\
+	nop; nop; nop; nop; nop; nop; nop; nop;
+
+#define SPILL_0_NORMAL_ETRAP				\
+etrap_kernel_spill:					\
+	stx	%l0, [%sp + STACK_BIAS + 0x00];		\
+	stx	%l1, [%sp + STACK_BIAS + 0x08];		\
+	stx	%l2, [%sp + STACK_BIAS + 0x10];		\
+	stx	%l3, [%sp + STACK_BIAS + 0x18];		\
+	stx	%l4, [%sp + STACK_BIAS + 0x20];		\
+	stx	%l5, [%sp + STACK_BIAS + 0x28];		\
+	stx	%l6, [%sp + STACK_BIAS + 0x30];		\
+	stx	%l7, [%sp + STACK_BIAS + 0x38];		\
+	stx	%i0, [%sp + STACK_BIAS + 0x40];		\
+	stx	%i1, [%sp + STACK_BIAS + 0x48];		\
+	stx	%i2, [%sp + STACK_BIAS + 0x50];		\
+	stx	%i3, [%sp + STACK_BIAS + 0x58];		\
+	stx	%i4, [%sp + STACK_BIAS + 0x60];		\
+	stx	%i5, [%sp + STACK_BIAS + 0x68];		\
+	stx	%i6, [%sp + STACK_BIAS + 0x70];		\
+	stx	%i7, [%sp + STACK_BIAS + 0x78];		\
+	saved;						\
+	sub	%g1, 2, %g1;				\
+	ba,pt	%xcc, etrap_save;			\
+	wrpr	%g1, %cwp;				\
+	nop; nop; nop; nop; nop; nop; nop; nop;		\
+	nop; nop; nop; nop;
+
+/* Normal 64bit spill */
+#define SPILL_1_GENERIC(ASI)				\
+	add	%sp, STACK_BIAS + 0x00, %g1;		\
+	stxa	%l0, [%g1 + %g0] ASI;			\
+	mov	0x08, %g3;				\
+	stxa	%l1, [%g1 + %g3] ASI;			\
+	add	%g1, 0x10, %g1;				\
+	stxa	%l2, [%g1 + %g0] ASI;			\
+	stxa	%l3, [%g1 + %g3] ASI;			\
+	add	%g1, 0x10, %g1;				\
+	stxa	%l4, [%g1 + %g0] ASI;			\
+	stxa	%l5, [%g1 + %g3] ASI;			\
+	add	%g1, 0x10, %g1;				\
+	stxa	%l6, [%g1 + %g0] ASI;			\
+	stxa	%l7, [%g1 + %g3] ASI;			\
+	add	%g1, 0x10, %g1;				\
+	stxa	%i0, [%g1 + %g0] ASI;			\
+	stxa	%i1, [%g1 + %g3] ASI;			\
+	add	%g1, 0x10, %g1;				\
+	stxa	%i2, [%g1 + %g0] ASI;			\
+	stxa	%i3, [%g1 + %g3] ASI;			\
+	add	%g1, 0x10, %g1;				\
+	stxa	%i4, [%g1 + %g0] ASI;			\
+	stxa	%i5, [%g1 + %g3] ASI;			\
+	add	%g1, 0x10, %g1;				\
+	stxa	%i6, [%g1 + %g0] ASI;			\
+	stxa	%i7, [%g1 + %g3] ASI;			\
+	saved;						\
+	retry; nop; nop;				\
+	b,a,pt	%xcc, spill_fixup_dax;			\
+	b,a,pt	%xcc, spill_fixup_mna;			\
+	b,a,pt	%xcc, spill_fixup;
+
+#define SPILL_1_GENERIC_ETRAP				\
+etrap_user_spill_64bit:					\
+	stxa	%l0, [%sp + STACK_BIAS + 0x00] %asi;	\
+	stxa	%l1, [%sp + STACK_BIAS + 0x08] %asi;	\
+	stxa	%l2, [%sp + STACK_BIAS + 0x10] %asi;	\
+	stxa	%l3, [%sp + STACK_BIAS + 0x18] %asi;	\
+	stxa	%l4, [%sp + STACK_BIAS + 0x20] %asi;	\
+	stxa	%l5, [%sp + STACK_BIAS + 0x28] %asi;	\
+	stxa	%l6, [%sp + STACK_BIAS + 0x30] %asi;	\
+	stxa	%l7, [%sp + STACK_BIAS + 0x38] %asi;	\
+	stxa	%i0, [%sp + STACK_BIAS + 0x40] %asi;	\
+	stxa	%i1, [%sp + STACK_BIAS + 0x48] %asi;	\
+	stxa	%i2, [%sp + STACK_BIAS + 0x50] %asi;	\
+	stxa	%i3, [%sp + STACK_BIAS + 0x58] %asi;	\
+	stxa	%i4, [%sp + STACK_BIAS + 0x60] %asi;	\
+	stxa	%i5, [%sp + STACK_BIAS + 0x68] %asi;	\
+	stxa	%i6, [%sp + STACK_BIAS + 0x70] %asi;	\
+	stxa	%i7, [%sp + STACK_BIAS + 0x78] %asi;	\
+	saved;						\
+	sub	%g1, 2, %g1;				\
+	ba,pt	%xcc, etrap_save;			\
+	 wrpr	%g1, %cwp;				\
+	nop; nop; nop; nop; nop;			\
+	nop; nop; nop; nop;				\
+	ba,a,pt	%xcc, etrap_spill_fixup_64bit;		\
+	ba,a,pt	%xcc, etrap_spill_fixup_64bit;		\
+	ba,a,pt	%xcc, etrap_spill_fixup_64bit;
+
+#define SPILL_1_GENERIC_ETRAP_FIXUP			\
+etrap_spill_fixup_64bit:				\
+	ldub	[%g6 + TI_WSAVED], %g1;			\
+	sll	%g1, 3, %g3;				\
+	add	%g6, %g3, %g3;				\
+	stx	%sp, [%g3 + TI_RWIN_SPTRS];		\
+	sll	%g1, 7, %g3;				\
+	add	%g6, %g3, %g3;				\
+	stx	%l0, [%g3 + TI_REG_WINDOW + 0x00];	\
+	stx	%l1, [%g3 + TI_REG_WINDOW + 0x08];	\
+	stx	%l2, [%g3 + TI_REG_WINDOW + 0x10];	\
+	stx	%l3, [%g3 + TI_REG_WINDOW + 0x18];	\
+	stx	%l4, [%g3 + TI_REG_WINDOW + 0x20];	\
+	stx	%l5, [%g3 + TI_REG_WINDOW + 0x28];	\
+	stx	%l6, [%g3 + TI_REG_WINDOW + 0x30];	\
+	stx	%l7, [%g3 + TI_REG_WINDOW + 0x38];	\
+	stx	%i0, [%g3 + TI_REG_WINDOW + 0x40];	\
+	stx	%i1, [%g3 + TI_REG_WINDOW + 0x48];	\
+	stx	%i2, [%g3 + TI_REG_WINDOW + 0x50];	\
+	stx	%i3, [%g3 + TI_REG_WINDOW + 0x58];	\
+	stx	%i4, [%g3 + TI_REG_WINDOW + 0x60];	\
+	stx	%i5, [%g3 + TI_REG_WINDOW + 0x68];	\
+	stx	%i6, [%g3 + TI_REG_WINDOW + 0x70];	\
+	stx	%i7, [%g3 + TI_REG_WINDOW + 0x78];	\
+	add	%g1, 1, %g1;				\
+	stb	%g1, [%g6 + TI_WSAVED];			\
+	saved;						\
+	rdpr	%cwp, %g1;				\
+	sub	%g1, 2, %g1;				\
+	ba,pt	%xcc, etrap_save;			\
+	 wrpr	%g1, %cwp;				\
+	nop; nop; nop
+
+/* Normal 32bit spill */
+#define SPILL_2_GENERIC(ASI)				\
+	srl	%sp, 0, %sp;				\
+	stwa	%l0, [%sp + %g0] ASI;			\
+	mov	0x04, %g3;				\
+	stwa	%l1, [%sp + %g3] ASI;			\
+	add	%sp, 0x08, %g1;				\
+	stwa	%l2, [%g1 + %g0] ASI;			\
+	stwa	%l3, [%g1 + %g3] ASI;			\
+	add	%g1, 0x08, %g1;				\
+	stwa	%l4, [%g1 + %g0] ASI;			\
+	stwa	%l5, [%g1 + %g3] ASI;			\
+	add	%g1, 0x08, %g1;				\
+	stwa	%l6, [%g1 + %g0] ASI;			\
+	stwa	%l7, [%g1 + %g3] ASI;			\
+	add	%g1, 0x08, %g1;				\
+	stwa	%i0, [%g1 + %g0] ASI;			\
+	stwa	%i1, [%g1 + %g3] ASI;			\
+	add	%g1, 0x08, %g1;				\
+	stwa	%i2, [%g1 + %g0] ASI;			\
+	stwa	%i3, [%g1 + %g3] ASI;			\
+	add	%g1, 0x08, %g1;				\
+	stwa	%i4, [%g1 + %g0] ASI;			\
+	stwa	%i5, [%g1 + %g3] ASI;			\
+	add	%g1, 0x08, %g1;				\
+	stwa	%i6, [%g1 + %g0] ASI;			\
+	stwa	%i7, [%g1 + %g3] ASI;			\
+	saved;						\
+        retry; nop; nop;				\
+	b,a,pt	%xcc, spill_fixup_dax;			\
+	b,a,pt	%xcc, spill_fixup_mna;			\
+	b,a,pt	%xcc, spill_fixup;
+
+#define SPILL_2_GENERIC_ETRAP		\
+etrap_user_spill_32bit:			\
+	srl	%sp, 0, %sp;		\
+	stwa	%l0, [%sp + 0x00] %asi;	\
+	stwa	%l1, [%sp + 0x04] %asi;	\
+	stwa	%l2, [%sp + 0x08] %asi;	\
+	stwa	%l3, [%sp + 0x0c] %asi;	\
+	stwa	%l4, [%sp + 0x10] %asi;	\
+	stwa	%l5, [%sp + 0x14] %asi;	\
+	stwa	%l6, [%sp + 0x18] %asi;	\
+	stwa	%l7, [%sp + 0x1c] %asi;	\
+	stwa	%i0, [%sp + 0x20] %asi;	\
+	stwa	%i1, [%sp + 0x24] %asi;	\
+	stwa	%i2, [%sp + 0x28] %asi;	\
+	stwa	%i3, [%sp + 0x2c] %asi;	\
+	stwa	%i4, [%sp + 0x30] %asi;	\
+	stwa	%i5, [%sp + 0x34] %asi;	\
+	stwa	%i6, [%sp + 0x38] %asi;	\
+	stwa	%i7, [%sp + 0x3c] %asi;	\
+	saved;				\
+	sub	%g1, 2, %g1;		\
+	ba,pt	%xcc, etrap_save;	\
+	 wrpr	%g1, %cwp;		\
+	nop; nop; nop; nop;		\
+	nop; nop; nop; nop;		\
+	ba,a,pt	%xcc, etrap_spill_fixup_32bit; \
+	ba,a,pt	%xcc, etrap_spill_fixup_32bit; \
+	ba,a,pt	%xcc, etrap_spill_fixup_32bit;
+
+#define SPILL_2_GENERIC_ETRAP_FIXUP			\
+etrap_spill_fixup_32bit:				\
+	ldub	[%g6 + TI_WSAVED], %g1;			\
+	sll	%g1, 3, %g3;				\
+	add	%g6, %g3, %g3;				\
+	stx	%sp, [%g3 + TI_RWIN_SPTRS];		\
+	sll	%g1, 7, %g3;				\
+	add	%g6, %g3, %g3;				\
+	stw	%l0, [%g3 + TI_REG_WINDOW + 0x00];	\
+	stw	%l1, [%g3 + TI_REG_WINDOW + 0x04];	\
+	stw	%l2, [%g3 + TI_REG_WINDOW + 0x08];	\
+	stw	%l3, [%g3 + TI_REG_WINDOW + 0x0c];	\
+	stw	%l4, [%g3 + TI_REG_WINDOW + 0x10];	\
+	stw	%l5, [%g3 + TI_REG_WINDOW + 0x14];	\
+	stw	%l6, [%g3 + TI_REG_WINDOW + 0x18];	\
+	stw	%l7, [%g3 + TI_REG_WINDOW + 0x1c];	\
+	stw	%i0, [%g3 + TI_REG_WINDOW + 0x20];	\
+	stw	%i1, [%g3 + TI_REG_WINDOW + 0x24];	\
+	stw	%i2, [%g3 + TI_REG_WINDOW + 0x28];	\
+	stw	%i3, [%g3 + TI_REG_WINDOW + 0x2c];	\
+	stw	%i4, [%g3 + TI_REG_WINDOW + 0x30];	\
+	stw	%i5, [%g3 + TI_REG_WINDOW + 0x34];	\
+	stw	%i6, [%g3 + TI_REG_WINDOW + 0x38];	\
+	stw	%i7, [%g3 + TI_REG_WINDOW + 0x3c];	\
+	add	%g1, 1, %g1;				\
+	stb	%g1, [%g6 + TI_WSAVED];			\
+	saved;						\
+	rdpr	%cwp, %g1;				\
+	sub	%g1, 2, %g1;				\
+	ba,pt	%xcc, etrap_save;			\
+	 wrpr	%g1, %cwp;				\
+	nop; nop; nop
+
+#define SPILL_1_NORMAL SPILL_1_GENERIC(ASI_AIUP)
+#define SPILL_2_NORMAL SPILL_2_GENERIC(ASI_AIUP)
+#define SPILL_3_NORMAL SPILL_0_NORMAL
+#define SPILL_4_NORMAL SPILL_0_NORMAL
+#define SPILL_5_NORMAL SPILL_0_NORMAL
+#define SPILL_6_NORMAL SPILL_0_NORMAL
+#define SPILL_7_NORMAL SPILL_0_NORMAL
+
+#define SPILL_0_OTHER SPILL_0_NORMAL
+#define SPILL_1_OTHER SPILL_1_GENERIC(ASI_AIUS)
+#define SPILL_2_OTHER SPILL_2_GENERIC(ASI_AIUS)
+#define SPILL_3_OTHER SPILL_3_NORMAL
+#define SPILL_4_OTHER SPILL_4_NORMAL
+#define SPILL_5_OTHER SPILL_5_NORMAL
+#define SPILL_6_OTHER SPILL_6_NORMAL
+#define SPILL_7_OTHER SPILL_7_NORMAL
+
+/* Normal kernel fill */
+#define FILL_0_NORMAL					\
+	ldx	[%sp + STACK_BIAS + 0x00], %l0;		\
+	ldx	[%sp + STACK_BIAS + 0x08], %l1;		\
+	ldx	[%sp + STACK_BIAS + 0x10], %l2;		\
+	ldx	[%sp + STACK_BIAS + 0x18], %l3;		\
+	ldx	[%sp + STACK_BIAS + 0x20], %l4;		\
+	ldx	[%sp + STACK_BIAS + 0x28], %l5;		\
+	ldx	[%sp + STACK_BIAS + 0x30], %l6;		\
+	ldx	[%sp + STACK_BIAS + 0x38], %l7;		\
+	ldx	[%sp + STACK_BIAS + 0x40], %i0;		\
+	ldx	[%sp + STACK_BIAS + 0x48], %i1;		\
+	ldx	[%sp + STACK_BIAS + 0x50], %i2;		\
+	ldx	[%sp + STACK_BIAS + 0x58], %i3;		\
+	ldx	[%sp + STACK_BIAS + 0x60], %i4;		\
+	ldx	[%sp + STACK_BIAS + 0x68], %i5;		\
+	ldx	[%sp + STACK_BIAS + 0x70], %i6;		\
+	ldx	[%sp + STACK_BIAS + 0x78], %i7;		\
+	restored; retry; nop; nop; nop; nop; nop; nop;	\
+	nop; nop; nop; nop; nop; nop; nop; nop;
+
+#define FILL_0_NORMAL_RTRAP				\
+kern_rtt_fill:						\
+	rdpr	%cwp, %g1;				\
+	sub	%g1, 1, %g1;				\
+	wrpr	%g1, %cwp;				\
+	ldx	[%sp + STACK_BIAS + 0x00], %l0;		\
+	ldx	[%sp + STACK_BIAS + 0x08], %l1;		\
+	ldx	[%sp + STACK_BIAS + 0x10], %l2;		\
+	ldx	[%sp + STACK_BIAS + 0x18], %l3;		\
+	ldx	[%sp + STACK_BIAS + 0x20], %l4;		\
+	ldx	[%sp + STACK_BIAS + 0x28], %l5;		\
+	ldx	[%sp + STACK_BIAS + 0x30], %l6;		\
+	ldx	[%sp + STACK_BIAS + 0x38], %l7;		\
+	ldx	[%sp + STACK_BIAS + 0x40], %i0;		\
+	ldx	[%sp + STACK_BIAS + 0x48], %i1;		\
+	ldx	[%sp + STACK_BIAS + 0x50], %i2;		\
+	ldx	[%sp + STACK_BIAS + 0x58], %i3;		\
+	ldx	[%sp + STACK_BIAS + 0x60], %i4;		\
+	ldx	[%sp + STACK_BIAS + 0x68], %i5;		\
+	ldx	[%sp + STACK_BIAS + 0x70], %i6;		\
+	ldx	[%sp + STACK_BIAS + 0x78], %i7;		\
+	restored;					\
+	add	%g1, 1, %g1;				\
+	ba,pt	%xcc, kern_rtt_restore;			\
+	 wrpr	%g1, %cwp;				\
+	nop; nop; nop; nop; nop;			\
+	nop; nop; nop; nop;
+
+
+/* Normal 64bit fill */
+#define FILL_1_GENERIC(ASI)				\
+	add	%sp, STACK_BIAS + 0x00, %g1;		\
+	ldxa	[%g1 + %g0] ASI, %l0;			\
+	mov	0x08, %g2;				\
+	mov	0x10, %g3;				\
+	ldxa	[%g1 + %g2] ASI, %l1;			\
+	mov	0x18, %g5;				\
+	ldxa	[%g1 + %g3] ASI, %l2;			\
+	ldxa	[%g1 + %g5] ASI, %l3;			\
+	add	%g1, 0x20, %g1;				\
+	ldxa	[%g1 + %g0] ASI, %l4;			\
+	ldxa	[%g1 + %g2] ASI, %l5;			\
+	ldxa	[%g1 + %g3] ASI, %l6;			\
+	ldxa	[%g1 + %g5] ASI, %l7;			\
+	add	%g1, 0x20, %g1;				\
+	ldxa	[%g1 + %g0] ASI, %i0;			\
+	ldxa	[%g1 + %g2] ASI, %i1;			\
+	ldxa	[%g1 + %g3] ASI, %i2;			\
+	ldxa	[%g1 + %g5] ASI, %i3;			\
+	add	%g1, 0x20, %g1;				\
+	ldxa	[%g1 + %g0] ASI, %i4;			\
+	ldxa	[%g1 + %g2] ASI, %i5;			\
+	ldxa	[%g1 + %g3] ASI, %i6;			\
+	ldxa	[%g1 + %g5] ASI, %i7;			\
+	restored;					\
+	retry; nop; nop; nop; nop;			\
+	b,a,pt	%xcc, fill_fixup_dax;			\
+	b,a,pt	%xcc, fill_fixup_mna;			\
+	b,a,pt	%xcc, fill_fixup;
+
+#define FILL_1_GENERIC_RTRAP				\
+user_rtt_fill_64bit:					\
+	ldxa	[%sp + STACK_BIAS + 0x00] %asi, %l0;	\
+	ldxa	[%sp + STACK_BIAS + 0x08] %asi, %l1;	\
+	ldxa	[%sp + STACK_BIAS + 0x10] %asi, %l2;	\
+	ldxa	[%sp + STACK_BIAS + 0x18] %asi, %l3;	\
+	ldxa	[%sp + STACK_BIAS + 0x20] %asi, %l4;	\
+	ldxa	[%sp + STACK_BIAS + 0x28] %asi, %l5;	\
+	ldxa	[%sp + STACK_BIAS + 0x30] %asi, %l6;	\
+	ldxa	[%sp + STACK_BIAS + 0x38] %asi, %l7;	\
+	ldxa	[%sp + STACK_BIAS + 0x40] %asi, %i0;	\
+	ldxa	[%sp + STACK_BIAS + 0x48] %asi, %i1;	\
+	ldxa	[%sp + STACK_BIAS + 0x50] %asi, %i2;	\
+	ldxa	[%sp + STACK_BIAS + 0x58] %asi, %i3;	\
+	ldxa	[%sp + STACK_BIAS + 0x60] %asi, %i4;	\
+	ldxa	[%sp + STACK_BIAS + 0x68] %asi, %i5;	\
+	ldxa	[%sp + STACK_BIAS + 0x70] %asi, %i6;	\
+	ldxa	[%sp + STACK_BIAS + 0x78] %asi, %i7;	\
+	ba,pt	%xcc, user_rtt_pre_restore;		\
+	 restored;					\
+	nop; nop; nop; nop; nop; nop;			\
+	nop; nop; nop; nop; nop;			\
+	ba,a,pt	%xcc, user_rtt_fill_fixup;		\
+	ba,a,pt	%xcc, user_rtt_fill_fixup;		\
+	ba,a,pt	%xcc, user_rtt_fill_fixup;
+
+
+/* Normal 32bit fill */
+#define FILL_2_GENERIC(ASI)				\
+	srl	%sp, 0, %sp;				\
+	lduwa	[%sp + %g0] ASI, %l0;			\
+	mov	0x04, %g2;				\
+	mov	0x08, %g3;				\
+	lduwa	[%sp + %g2] ASI, %l1;			\
+	mov	0x0c, %g5;				\
+	lduwa	[%sp + %g3] ASI, %l2;			\
+	lduwa	[%sp + %g5] ASI, %l3;			\
+	add	%sp, 0x10, %g1;				\
+	lduwa	[%g1 + %g0] ASI, %l4;			\
+	lduwa	[%g1 + %g2] ASI, %l5;			\
+	lduwa	[%g1 + %g3] ASI, %l6;			\
+	lduwa	[%g1 + %g5] ASI, %l7;			\
+	add	%g1, 0x10, %g1;				\
+	lduwa	[%g1 + %g0] ASI, %i0;			\
+	lduwa	[%g1 + %g2] ASI, %i1;			\
+	lduwa	[%g1 + %g3] ASI, %i2;			\
+	lduwa	[%g1 + %g5] ASI, %i3;			\
+	add	%g1, 0x10, %g1;				\
+	lduwa	[%g1 + %g0] ASI, %i4;			\
+	lduwa	[%g1 + %g2] ASI, %i5;			\
+	lduwa	[%g1 + %g3] ASI, %i6;			\
+	lduwa	[%g1 + %g5] ASI, %i7;			\
+	restored;					\
+	retry; nop; nop; nop; nop;			\
+	b,a,pt	%xcc, fill_fixup_dax;			\
+	b,a,pt	%xcc, fill_fixup_mna;			\
+	b,a,pt	%xcc, fill_fixup;
+
+#define FILL_2_GENERIC_RTRAP				\
+user_rtt_fill_32bit:					\
+	srl	%sp, 0, %sp;				\
+	lduwa	[%sp + 0x00] %asi, %l0;			\
+	lduwa	[%sp + 0x04] %asi, %l1;			\
+	lduwa	[%sp + 0x08] %asi, %l2;			\
+	lduwa	[%sp + 0x0c] %asi, %l3;			\
+	lduwa	[%sp + 0x10] %asi, %l4;			\
+	lduwa	[%sp + 0x14] %asi, %l5;			\
+	lduwa	[%sp + 0x18] %asi, %l6;			\
+	lduwa	[%sp + 0x1c] %asi, %l7;			\
+	lduwa	[%sp + 0x20] %asi, %i0;			\
+	lduwa	[%sp + 0x24] %asi, %i1;			\
+	lduwa	[%sp + 0x28] %asi, %i2;			\
+	lduwa	[%sp + 0x2c] %asi, %i3;			\
+	lduwa	[%sp + 0x30] %asi, %i4;			\
+	lduwa	[%sp + 0x34] %asi, %i5;			\
+	lduwa	[%sp + 0x38] %asi, %i6;			\
+	lduwa	[%sp + 0x3c] %asi, %i7;			\
+	ba,pt	%xcc, user_rtt_pre_restore;		\
+	 restored;					\
+	nop; nop; nop; nop; nop;			\
+	nop; nop; nop; nop; nop;			\
+	ba,a,pt	%xcc, user_rtt_fill_fixup;		\
+	ba,a,pt	%xcc, user_rtt_fill_fixup;		\
+	ba,a,pt	%xcc, user_rtt_fill_fixup;
+
+
+#define FILL_1_NORMAL FILL_1_GENERIC(ASI_AIUP)
+#define FILL_2_NORMAL FILL_2_GENERIC(ASI_AIUP)
+#define FILL_3_NORMAL FILL_0_NORMAL
+#define FILL_4_NORMAL FILL_0_NORMAL
+#define FILL_5_NORMAL FILL_0_NORMAL
+#define FILL_6_NORMAL FILL_0_NORMAL
+#define FILL_7_NORMAL FILL_0_NORMAL
+
+#define FILL_0_OTHER FILL_0_NORMAL
+#define FILL_1_OTHER FILL_1_GENERIC(ASI_AIUS)
+#define FILL_2_OTHER FILL_2_GENERIC(ASI_AIUS)
+#define FILL_3_OTHER FILL_3_NORMAL
+#define FILL_4_OTHER FILL_4_NORMAL
+#define FILL_5_OTHER FILL_5_NORMAL
+#define FILL_6_OTHER FILL_6_NORMAL
+#define FILL_7_OTHER FILL_7_NORMAL
+
+#endif /* !(_SPARC64_TTABLE_H) */
diff --git a/include/asm-sparc/types.h b/include/asm-sparc/types.h
index 07734f9..8c28fde 100644
--- a/include/asm-sparc/types.h
+++ b/include/asm-sparc/types.h
@@ -1,6 +1,5 @@
 #ifndef _SPARC_TYPES_H
 #define _SPARC_TYPES_H
-
 /*
  * This file is never included by application software unless
  * explicitly requested (e.g., via linux/types.h) in which case the
@@ -8,6 +7,35 @@
  * not a major issue.  However, for interoperability, libraries still
  * need to be careful to avoid a name clashes.
  */
+
+#if defined(__sparc__) && defined(__arch64__)
+
+/*** SPARC 64 bit ***/
+#include <asm-generic/int-l64.h>
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned short umode_t;
+
+#endif /* __ASSEMBLY__ */
+
+#ifdef __KERNEL__
+
+#define BITS_PER_LONG 64
+
+#ifndef __ASSEMBLY__
+
+/* Dma addresses come in generic and 64-bit flavours.  */
+
+typedef u32 dma_addr_t;
+typedef u64 dma64_addr_t;
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __KERNEL__ */
+#else
+
+/*** SPARC 32 bit ***/
 #include <asm-generic/int-ll64.h>
 
 #ifndef __ASSEMBLY__
@@ -29,4 +57,6 @@
 
 #endif /* __KERNEL__ */
 
+#endif /* defined(__sparc__) && defined(__arch64__) */
+
 #endif /* defined(_SPARC_TYPES_H) */
diff --git a/include/asm-sparc/uaccess.h b/include/asm-sparc/uaccess.h
index 47d5619..424facc 100644
--- a/include/asm-sparc/uaccess.h
+++ b/include/asm-sparc/uaccess.h
@@ -1,336 +1,8 @@
-/*
- * uaccess.h: User space memore access functions.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- */
-#ifndef _ASM_UACCESS_H
-#define _ASM_UACCESS_H
-
-#ifdef __KERNEL__
-#include <linux/compiler.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <asm/vac-ops.h>
+#ifndef ___ASM_SPARC_UACCESS_H
+#define ___ASM_SPARC_UACCESS_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/uaccess_64.h>
+#else
+#include <asm-sparc/uaccess_32.h>
 #endif
-
-#ifndef __ASSEMBLY__
-
-/* Sparc is not segmented, however we need to be able to fool access_ok()
- * when doing system calls from kernel mode legitimately.
- *
- * "For historical reasons, these macros are grossly misnamed." -Linus
- */
-
-#define KERNEL_DS   ((mm_segment_t) { 0 })
-#define USER_DS     ((mm_segment_t) { -1 })
-
-#define VERIFY_READ	0
-#define VERIFY_WRITE	1
-
-#define get_ds()	(KERNEL_DS)
-#define get_fs()	(current->thread.current_ds)
-#define set_fs(val)	((current->thread.current_ds) = (val))
-
-#define segment_eq(a,b)	((a).seg == (b).seg)
-
-/* We have there a nice not-mapped page at PAGE_OFFSET - PAGE_SIZE, so that this test
- * can be fairly lightweight.
- * No one can read/write anything from userland in the kernel space by setting
- * large size and address near to PAGE_OFFSET - a fault will break his intentions.
- */
-#define __user_ok(addr, size) ({ (void)(size); (addr) < STACK_TOP; })
-#define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
-#define __access_ok(addr,size) (__user_ok((addr) & get_fs().seg,(size)))
-#define access_ok(type, addr, size)					\
-	({ (void)(type); __access_ok((unsigned long)(addr), size); })
-
-/*
- * The exception table consists of pairs of addresses: the first is the
- * address of an instruction that is allowed to fault, and the second is
- * the address at which the program should continue.  No registers are
- * modified, so it is entirely up to the continuation code to figure out
- * what to do.
- *
- * All the routines below use bits of fixup code that are out of line
- * with the main instruction path.  This means when everything is well,
- * we don't even have to jump over them.  Further, they do not intrude
- * on our cache or tlb entries.
- *
- * There is a special way how to put a range of potentially faulting
- * insns (like twenty ldd/std's with now intervening other instructions)
- * You specify address of first in insn and 0 in fixup and in the next
- * exception_table_entry you specify last potentially faulting insn + 1
- * and in fixup the routine which should handle the fault.
- * That fixup code will get
- * (faulting_insn_address - first_insn_in_the_range_address)/4
- * in %g2 (ie. index of the faulting instruction in the range).
- */
-
-struct exception_table_entry
-{
-        unsigned long insn, fixup;
-};
-
-/* Returns 0 if exception not found and fixup otherwise.  */
-extern unsigned long search_extables_range(unsigned long addr, unsigned long *g2);
-
-extern void __ret_efault(void);
-
-/* Uh, these should become the main single-value transfer routines..
- * They automatically use the right size if we just have the right
- * pointer type..
- *
- * This gets kind of ugly. We want to return _two_ values in "get_user()"
- * and yet we don't want to do any pointers, because that is too much
- * of a performance impact. Thus we have a few rather ugly macros here,
- * and hide all the ugliness from the user.
- */
-#define put_user(x,ptr) ({ \
-unsigned long __pu_addr = (unsigned long)(ptr); \
-__chk_user_ptr(ptr); \
-__put_user_check((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr))); })
-
-#define get_user(x,ptr) ({ \
-unsigned long __gu_addr = (unsigned long)(ptr); \
-__chk_user_ptr(ptr); \
-__get_user_check((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr))); })
-
-/*
- * The "__xxx" versions do not do address space checking, useful when
- * doing multiple accesses to the same area (the user has to do the
- * checks by hand with "access_ok()")
- */
-#define __put_user(x,ptr) __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
-#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)),__typeof__(*(ptr)))
-
-struct __large_struct { unsigned long buf[100]; };
-#define __m(x) ((struct __large_struct __user *)(x))
-
-#define __put_user_check(x,addr,size) ({ \
-register int __pu_ret; \
-if (__access_ok(addr,size)) { \
-switch (size) { \
-case 1: __put_user_asm(x,b,addr,__pu_ret); break; \
-case 2: __put_user_asm(x,h,addr,__pu_ret); break; \
-case 4: __put_user_asm(x,,addr,__pu_ret); break; \
-case 8: __put_user_asm(x,d,addr,__pu_ret); break; \
-default: __pu_ret = __put_user_bad(); break; \
-} } else { __pu_ret = -EFAULT; } __pu_ret; })
-
-#define __put_user_nocheck(x,addr,size) ({ \
-register int __pu_ret; \
-switch (size) { \
-case 1: __put_user_asm(x,b,addr,__pu_ret); break; \
-case 2: __put_user_asm(x,h,addr,__pu_ret); break; \
-case 4: __put_user_asm(x,,addr,__pu_ret); break; \
-case 8: __put_user_asm(x,d,addr,__pu_ret); break; \
-default: __pu_ret = __put_user_bad(); break; \
-} __pu_ret; })
-
-#define __put_user_asm(x,size,addr,ret)					\
-__asm__ __volatile__(							\
-	"/* Put user asm, inline. */\n"					\
-"1:\t"	"st"#size " %1, %2\n\t"						\
-	"clr	%0\n"							\
-"2:\n\n\t"								\
-	".section .fixup,#alloc,#execinstr\n\t"				\
-	".align	4\n"							\
-"3:\n\t"								\
-	"b	2b\n\t"							\
-	" mov	%3, %0\n\t"						\
-        ".previous\n\n\t"						\
-	".section __ex_table,#alloc\n\t"				\
-	".align	4\n\t"							\
-	".word	1b, 3b\n\t"						\
-	".previous\n\n\t"						\
-       : "=&r" (ret) : "r" (x), "m" (*__m(addr)),			\
-	 "i" (-EFAULT))
-
-extern int __put_user_bad(void);
-
-#define __get_user_check(x,addr,size,type) ({ \
-register int __gu_ret; \
-register unsigned long __gu_val; \
-if (__access_ok(addr,size)) { \
-switch (size) { \
-case 1: __get_user_asm(__gu_val,ub,addr,__gu_ret); break; \
-case 2: __get_user_asm(__gu_val,uh,addr,__gu_ret); break; \
-case 4: __get_user_asm(__gu_val,,addr,__gu_ret); break; \
-case 8: __get_user_asm(__gu_val,d,addr,__gu_ret); break; \
-default: __gu_val = 0; __gu_ret = __get_user_bad(); break; \
-} } else { __gu_val = 0; __gu_ret = -EFAULT; } x = (type) __gu_val; __gu_ret; })
-
-#define __get_user_check_ret(x,addr,size,type,retval) ({ \
-register unsigned long __gu_val __asm__ ("l1"); \
-if (__access_ok(addr,size)) { \
-switch (size) { \
-case 1: __get_user_asm_ret(__gu_val,ub,addr,retval); break; \
-case 2: __get_user_asm_ret(__gu_val,uh,addr,retval); break; \
-case 4: __get_user_asm_ret(__gu_val,,addr,retval); break; \
-case 8: __get_user_asm_ret(__gu_val,d,addr,retval); break; \
-default: if (__get_user_bad()) return retval; \
-} x = (type) __gu_val; } else return retval; })
-
-#define __get_user_nocheck(x,addr,size,type) ({ \
-register int __gu_ret; \
-register unsigned long __gu_val; \
-switch (size) { \
-case 1: __get_user_asm(__gu_val,ub,addr,__gu_ret); break; \
-case 2: __get_user_asm(__gu_val,uh,addr,__gu_ret); break; \
-case 4: __get_user_asm(__gu_val,,addr,__gu_ret); break; \
-case 8: __get_user_asm(__gu_val,d,addr,__gu_ret); break; \
-default: __gu_val = 0; __gu_ret = __get_user_bad(); break; \
-} x = (type) __gu_val; __gu_ret; })
-
-#define __get_user_nocheck_ret(x,addr,size,type,retval) ({ \
-register unsigned long __gu_val __asm__ ("l1"); \
-switch (size) { \
-case 1: __get_user_asm_ret(__gu_val,ub,addr,retval); break; \
-case 2: __get_user_asm_ret(__gu_val,uh,addr,retval); break; \
-case 4: __get_user_asm_ret(__gu_val,,addr,retval); break; \
-case 8: __get_user_asm_ret(__gu_val,d,addr,retval); break; \
-default: if (__get_user_bad()) return retval; \
-} x = (type) __gu_val; })
-
-#define __get_user_asm(x,size,addr,ret)					\
-__asm__ __volatile__(							\
-	"/* Get user asm, inline. */\n"					\
-"1:\t"	"ld"#size " %2, %1\n\t"						\
-	"clr	%0\n"							\
-"2:\n\n\t"								\
-	".section .fixup,#alloc,#execinstr\n\t"				\
-	".align	4\n"							\
-"3:\n\t"								\
-	"clr	%1\n\t"							\
-	"b	2b\n\t"							\
-	" mov	%3, %0\n\n\t"						\
-	".previous\n\t"							\
-	".section __ex_table,#alloc\n\t"				\
-	".align	4\n\t"							\
-	".word	1b, 3b\n\n\t"						\
-	".previous\n\t"							\
-       : "=&r" (ret), "=&r" (x) : "m" (*__m(addr)),			\
-	 "i" (-EFAULT))
-
-#define __get_user_asm_ret(x,size,addr,retval)				\
-if (__builtin_constant_p(retval) && retval == -EFAULT)			\
-__asm__ __volatile__(							\
-	"/* Get user asm ret, inline. */\n"				\
-"1:\t"	"ld"#size " %1, %0\n\n\t"					\
-	".section __ex_table,#alloc\n\t"				\
-	".align	4\n\t"							\
-	".word	1b,__ret_efault\n\n\t"					\
-	".previous\n\t"							\
-       : "=&r" (x) : "m" (*__m(addr)));					\
-else									\
-__asm__ __volatile__(							\
-	"/* Get user asm ret, inline. */\n"				\
-"1:\t"	"ld"#size " %1, %0\n\n\t"					\
-	".section .fixup,#alloc,#execinstr\n\t"				\
-	".align	4\n"							\
-"3:\n\t"								\
-	"ret\n\t"							\
-	" restore %%g0, %2, %%o0\n\n\t"					\
-	".previous\n\t"							\
-	".section __ex_table,#alloc\n\t"				\
-	".align	4\n\t"							\
-	".word	1b, 3b\n\n\t"						\
-	".previous\n\t"							\
-       : "=&r" (x) : "m" (*__m(addr)), "i" (retval))
-
-extern int __get_user_bad(void);
-
-extern unsigned long __copy_user(void __user *to, const void __user *from, unsigned long size);
-
-static inline unsigned long copy_to_user(void __user *to, const void *from, unsigned long n)
-{
-	if (n && __access_ok((unsigned long) to, n))
-		return __copy_user(to, (__force void __user *) from, n);
-	else
-		return n;
-}
-
-static inline unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n)
-{
-	return __copy_user(to, (__force void __user *) from, n);
-}
-
-static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n)
-{
-	if (n && __access_ok((unsigned long) from, n))
-		return __copy_user((__force void __user *) to, from, n);
-	else
-		return n;
-}
-
-static inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n)
-{
-	return __copy_user((__force void __user *) to, from, n);
-}
-
-#define __copy_to_user_inatomic __copy_to_user
-#define __copy_from_user_inatomic __copy_from_user
-
-static inline unsigned long __clear_user(void __user *addr, unsigned long size)
-{
-	unsigned long ret;
-
-	__asm__ __volatile__ (
-		".section __ex_table,#alloc\n\t"
-		".align 4\n\t"
-		".word 1f,3\n\t"
-		".previous\n\t"
-		"mov %2, %%o1\n"
-		"1:\n\t"
-		"call __bzero\n\t"
-		" mov %1, %%o0\n\t"
-		"mov %%o0, %0\n"
-		: "=r" (ret) : "r" (addr), "r" (size) :
-		"o0", "o1", "o2", "o3", "o4", "o5", "o7",
-		"g1", "g2", "g3", "g4", "g5", "g7", "cc");
-
-	return ret;
-}
-
-static inline unsigned long clear_user(void __user *addr, unsigned long n)
-{
-	if (n && __access_ok((unsigned long) addr, n))
-		return __clear_user(addr, n);
-	else
-		return n;
-}
-
-extern long __strncpy_from_user(char *dest, const char __user *src, long count);
-
-static inline long strncpy_from_user(char *dest, const char __user *src, long count)
-{
-	if (__access_ok((unsigned long) src, count))
-		return __strncpy_from_user(dest, src, count);
-	else
-		return -EFAULT;
-}
-
-extern long __strlen_user(const char __user *);
-extern long __strnlen_user(const char __user *, long len);
-
-static inline long strlen_user(const char __user *str)
-{
-	if (!access_ok(VERIFY_READ, str, 0))
-		return 0;
-	else
-		return __strlen_user(str);
-}
-
-static inline long strnlen_user(const char __user *str, long len)
-{
-	if (!access_ok(VERIFY_READ, str, 0))
-		return 0;
-	else
-		return __strnlen_user(str, len);
-}
-
-#endif  /* __ASSEMBLY__ */
-
-#endif /* _ASM_UACCESS_H */
+#endif
diff --git a/include/asm-sparc/uaccess_32.h b/include/asm-sparc/uaccess_32.h
new file mode 100644
index 0000000..47d5619
--- /dev/null
+++ b/include/asm-sparc/uaccess_32.h
@@ -0,0 +1,336 @@
+/*
+ * uaccess.h: User space memore access functions.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+#ifndef _ASM_UACCESS_H
+#define _ASM_UACCESS_H
+
+#ifdef __KERNEL__
+#include <linux/compiler.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <asm/vac-ops.h>
+#endif
+
+#ifndef __ASSEMBLY__
+
+/* Sparc is not segmented, however we need to be able to fool access_ok()
+ * when doing system calls from kernel mode legitimately.
+ *
+ * "For historical reasons, these macros are grossly misnamed." -Linus
+ */
+
+#define KERNEL_DS   ((mm_segment_t) { 0 })
+#define USER_DS     ((mm_segment_t) { -1 })
+
+#define VERIFY_READ	0
+#define VERIFY_WRITE	1
+
+#define get_ds()	(KERNEL_DS)
+#define get_fs()	(current->thread.current_ds)
+#define set_fs(val)	((current->thread.current_ds) = (val))
+
+#define segment_eq(a,b)	((a).seg == (b).seg)
+
+/* We have there a nice not-mapped page at PAGE_OFFSET - PAGE_SIZE, so that this test
+ * can be fairly lightweight.
+ * No one can read/write anything from userland in the kernel space by setting
+ * large size and address near to PAGE_OFFSET - a fault will break his intentions.
+ */
+#define __user_ok(addr, size) ({ (void)(size); (addr) < STACK_TOP; })
+#define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
+#define __access_ok(addr,size) (__user_ok((addr) & get_fs().seg,(size)))
+#define access_ok(type, addr, size)					\
+	({ (void)(type); __access_ok((unsigned long)(addr), size); })
+
+/*
+ * The exception table consists of pairs of addresses: the first is the
+ * address of an instruction that is allowed to fault, and the second is
+ * the address at which the program should continue.  No registers are
+ * modified, so it is entirely up to the continuation code to figure out
+ * what to do.
+ *
+ * All the routines below use bits of fixup code that are out of line
+ * with the main instruction path.  This means when everything is well,
+ * we don't even have to jump over them.  Further, they do not intrude
+ * on our cache or tlb entries.
+ *
+ * There is a special way how to put a range of potentially faulting
+ * insns (like twenty ldd/std's with now intervening other instructions)
+ * You specify address of first in insn and 0 in fixup and in the next
+ * exception_table_entry you specify last potentially faulting insn + 1
+ * and in fixup the routine which should handle the fault.
+ * That fixup code will get
+ * (faulting_insn_address - first_insn_in_the_range_address)/4
+ * in %g2 (ie. index of the faulting instruction in the range).
+ */
+
+struct exception_table_entry
+{
+        unsigned long insn, fixup;
+};
+
+/* Returns 0 if exception not found and fixup otherwise.  */
+extern unsigned long search_extables_range(unsigned long addr, unsigned long *g2);
+
+extern void __ret_efault(void);
+
+/* Uh, these should become the main single-value transfer routines..
+ * They automatically use the right size if we just have the right
+ * pointer type..
+ *
+ * This gets kind of ugly. We want to return _two_ values in "get_user()"
+ * and yet we don't want to do any pointers, because that is too much
+ * of a performance impact. Thus we have a few rather ugly macros here,
+ * and hide all the ugliness from the user.
+ */
+#define put_user(x,ptr) ({ \
+unsigned long __pu_addr = (unsigned long)(ptr); \
+__chk_user_ptr(ptr); \
+__put_user_check((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr))); })
+
+#define get_user(x,ptr) ({ \
+unsigned long __gu_addr = (unsigned long)(ptr); \
+__chk_user_ptr(ptr); \
+__get_user_check((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr))); })
+
+/*
+ * The "__xxx" versions do not do address space checking, useful when
+ * doing multiple accesses to the same area (the user has to do the
+ * checks by hand with "access_ok()")
+ */
+#define __put_user(x,ptr) __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)),__typeof__(*(ptr)))
+
+struct __large_struct { unsigned long buf[100]; };
+#define __m(x) ((struct __large_struct __user *)(x))
+
+#define __put_user_check(x,addr,size) ({ \
+register int __pu_ret; \
+if (__access_ok(addr,size)) { \
+switch (size) { \
+case 1: __put_user_asm(x,b,addr,__pu_ret); break; \
+case 2: __put_user_asm(x,h,addr,__pu_ret); break; \
+case 4: __put_user_asm(x,,addr,__pu_ret); break; \
+case 8: __put_user_asm(x,d,addr,__pu_ret); break; \
+default: __pu_ret = __put_user_bad(); break; \
+} } else { __pu_ret = -EFAULT; } __pu_ret; })
+
+#define __put_user_nocheck(x,addr,size) ({ \
+register int __pu_ret; \
+switch (size) { \
+case 1: __put_user_asm(x,b,addr,__pu_ret); break; \
+case 2: __put_user_asm(x,h,addr,__pu_ret); break; \
+case 4: __put_user_asm(x,,addr,__pu_ret); break; \
+case 8: __put_user_asm(x,d,addr,__pu_ret); break; \
+default: __pu_ret = __put_user_bad(); break; \
+} __pu_ret; })
+
+#define __put_user_asm(x,size,addr,ret)					\
+__asm__ __volatile__(							\
+	"/* Put user asm, inline. */\n"					\
+"1:\t"	"st"#size " %1, %2\n\t"						\
+	"clr	%0\n"							\
+"2:\n\n\t"								\
+	".section .fixup,#alloc,#execinstr\n\t"				\
+	".align	4\n"							\
+"3:\n\t"								\
+	"b	2b\n\t"							\
+	" mov	%3, %0\n\t"						\
+        ".previous\n\n\t"						\
+	".section __ex_table,#alloc\n\t"				\
+	".align	4\n\t"							\
+	".word	1b, 3b\n\t"						\
+	".previous\n\n\t"						\
+       : "=&r" (ret) : "r" (x), "m" (*__m(addr)),			\
+	 "i" (-EFAULT))
+
+extern int __put_user_bad(void);
+
+#define __get_user_check(x,addr,size,type) ({ \
+register int __gu_ret; \
+register unsigned long __gu_val; \
+if (__access_ok(addr,size)) { \
+switch (size) { \
+case 1: __get_user_asm(__gu_val,ub,addr,__gu_ret); break; \
+case 2: __get_user_asm(__gu_val,uh,addr,__gu_ret); break; \
+case 4: __get_user_asm(__gu_val,,addr,__gu_ret); break; \
+case 8: __get_user_asm(__gu_val,d,addr,__gu_ret); break; \
+default: __gu_val = 0; __gu_ret = __get_user_bad(); break; \
+} } else { __gu_val = 0; __gu_ret = -EFAULT; } x = (type) __gu_val; __gu_ret; })
+
+#define __get_user_check_ret(x,addr,size,type,retval) ({ \
+register unsigned long __gu_val __asm__ ("l1"); \
+if (__access_ok(addr,size)) { \
+switch (size) { \
+case 1: __get_user_asm_ret(__gu_val,ub,addr,retval); break; \
+case 2: __get_user_asm_ret(__gu_val,uh,addr,retval); break; \
+case 4: __get_user_asm_ret(__gu_val,,addr,retval); break; \
+case 8: __get_user_asm_ret(__gu_val,d,addr,retval); break; \
+default: if (__get_user_bad()) return retval; \
+} x = (type) __gu_val; } else return retval; })
+
+#define __get_user_nocheck(x,addr,size,type) ({ \
+register int __gu_ret; \
+register unsigned long __gu_val; \
+switch (size) { \
+case 1: __get_user_asm(__gu_val,ub,addr,__gu_ret); break; \
+case 2: __get_user_asm(__gu_val,uh,addr,__gu_ret); break; \
+case 4: __get_user_asm(__gu_val,,addr,__gu_ret); break; \
+case 8: __get_user_asm(__gu_val,d,addr,__gu_ret); break; \
+default: __gu_val = 0; __gu_ret = __get_user_bad(); break; \
+} x = (type) __gu_val; __gu_ret; })
+
+#define __get_user_nocheck_ret(x,addr,size,type,retval) ({ \
+register unsigned long __gu_val __asm__ ("l1"); \
+switch (size) { \
+case 1: __get_user_asm_ret(__gu_val,ub,addr,retval); break; \
+case 2: __get_user_asm_ret(__gu_val,uh,addr,retval); break; \
+case 4: __get_user_asm_ret(__gu_val,,addr,retval); break; \
+case 8: __get_user_asm_ret(__gu_val,d,addr,retval); break; \
+default: if (__get_user_bad()) return retval; \
+} x = (type) __gu_val; })
+
+#define __get_user_asm(x,size,addr,ret)					\
+__asm__ __volatile__(							\
+	"/* Get user asm, inline. */\n"					\
+"1:\t"	"ld"#size " %2, %1\n\t"						\
+	"clr	%0\n"							\
+"2:\n\n\t"								\
+	".section .fixup,#alloc,#execinstr\n\t"				\
+	".align	4\n"							\
+"3:\n\t"								\
+	"clr	%1\n\t"							\
+	"b	2b\n\t"							\
+	" mov	%3, %0\n\n\t"						\
+	".previous\n\t"							\
+	".section __ex_table,#alloc\n\t"				\
+	".align	4\n\t"							\
+	".word	1b, 3b\n\n\t"						\
+	".previous\n\t"							\
+       : "=&r" (ret), "=&r" (x) : "m" (*__m(addr)),			\
+	 "i" (-EFAULT))
+
+#define __get_user_asm_ret(x,size,addr,retval)				\
+if (__builtin_constant_p(retval) && retval == -EFAULT)			\
+__asm__ __volatile__(							\
+	"/* Get user asm ret, inline. */\n"				\
+"1:\t"	"ld"#size " %1, %0\n\n\t"					\
+	".section __ex_table,#alloc\n\t"				\
+	".align	4\n\t"							\
+	".word	1b,__ret_efault\n\n\t"					\
+	".previous\n\t"							\
+       : "=&r" (x) : "m" (*__m(addr)));					\
+else									\
+__asm__ __volatile__(							\
+	"/* Get user asm ret, inline. */\n"				\
+"1:\t"	"ld"#size " %1, %0\n\n\t"					\
+	".section .fixup,#alloc,#execinstr\n\t"				\
+	".align	4\n"							\
+"3:\n\t"								\
+	"ret\n\t"							\
+	" restore %%g0, %2, %%o0\n\n\t"					\
+	".previous\n\t"							\
+	".section __ex_table,#alloc\n\t"				\
+	".align	4\n\t"							\
+	".word	1b, 3b\n\n\t"						\
+	".previous\n\t"							\
+       : "=&r" (x) : "m" (*__m(addr)), "i" (retval))
+
+extern int __get_user_bad(void);
+
+extern unsigned long __copy_user(void __user *to, const void __user *from, unsigned long size);
+
+static inline unsigned long copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+	if (n && __access_ok((unsigned long) to, n))
+		return __copy_user(to, (__force void __user *) from, n);
+	else
+		return n;
+}
+
+static inline unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+	return __copy_user(to, (__force void __user *) from, n);
+}
+
+static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+	if (n && __access_ok((unsigned long) from, n))
+		return __copy_user((__force void __user *) to, from, n);
+	else
+		return n;
+}
+
+static inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+	return __copy_user((__force void __user *) to, from, n);
+}
+
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
+static inline unsigned long __clear_user(void __user *addr, unsigned long size)
+{
+	unsigned long ret;
+
+	__asm__ __volatile__ (
+		".section __ex_table,#alloc\n\t"
+		".align 4\n\t"
+		".word 1f,3\n\t"
+		".previous\n\t"
+		"mov %2, %%o1\n"
+		"1:\n\t"
+		"call __bzero\n\t"
+		" mov %1, %%o0\n\t"
+		"mov %%o0, %0\n"
+		: "=r" (ret) : "r" (addr), "r" (size) :
+		"o0", "o1", "o2", "o3", "o4", "o5", "o7",
+		"g1", "g2", "g3", "g4", "g5", "g7", "cc");
+
+	return ret;
+}
+
+static inline unsigned long clear_user(void __user *addr, unsigned long n)
+{
+	if (n && __access_ok((unsigned long) addr, n))
+		return __clear_user(addr, n);
+	else
+		return n;
+}
+
+extern long __strncpy_from_user(char *dest, const char __user *src, long count);
+
+static inline long strncpy_from_user(char *dest, const char __user *src, long count)
+{
+	if (__access_ok((unsigned long) src, count))
+		return __strncpy_from_user(dest, src, count);
+	else
+		return -EFAULT;
+}
+
+extern long __strlen_user(const char __user *);
+extern long __strnlen_user(const char __user *, long len);
+
+static inline long strlen_user(const char __user *str)
+{
+	if (!access_ok(VERIFY_READ, str, 0))
+		return 0;
+	else
+		return __strlen_user(str);
+}
+
+static inline long strnlen_user(const char __user *str, long len)
+{
+	if (!access_ok(VERIFY_READ, str, 0))
+		return 0;
+	else
+		return __strnlen_user(str, len);
+}
+
+#endif  /* __ASSEMBLY__ */
+
+#endif /* _ASM_UACCESS_H */
diff --git a/include/asm-sparc/uaccess_64.h b/include/asm-sparc/uaccess_64.h
new file mode 100644
index 0000000..296ef30
--- /dev/null
+++ b/include/asm-sparc/uaccess_64.h
@@ -0,0 +1,273 @@
+#ifndef _ASM_UACCESS_H
+#define _ASM_UACCESS_H
+
+/*
+ * User space memory access functions
+ */
+
+#ifdef __KERNEL__
+#include <linux/compiler.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <asm/asi.h>
+#include <asm/system.h>
+#include <asm/spitfire.h>
+#include <asm-generic/uaccess.h>
+#endif
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Sparc64 is segmented, though more like the M68K than the I386.
+ * We use the secondary ASI to address user memory, which references a
+ * completely different VM map, thus there is zero chance of the user
+ * doing something queer and tricking us into poking kernel memory.
+ *
+ * What is left here is basically what is needed for the other parts of
+ * the kernel that expect to be able to manipulate, erum, "segments".
+ * Or perhaps more properly, permissions.
+ *
+ * "For historical reasons, these macros are grossly misnamed." -Linus
+ */
+
+#define KERNEL_DS   ((mm_segment_t) { ASI_P })
+#define USER_DS     ((mm_segment_t) { ASI_AIUS })	/* har har har */
+
+#define VERIFY_READ	0
+#define VERIFY_WRITE	1
+
+#define get_fs() ((mm_segment_t) { get_thread_current_ds() })
+#define get_ds() (KERNEL_DS)
+
+#define segment_eq(a,b)  ((a).seg == (b).seg)
+
+#define set_fs(val)								\
+do {										\
+	set_thread_current_ds((val).seg);					\
+	__asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "r" ((val).seg));	\
+} while(0)
+
+static inline int __access_ok(const void __user * addr, unsigned long size)
+{
+	return 1;
+}
+
+static inline int access_ok(int type, const void __user * addr, unsigned long size)
+{
+	return 1;
+}
+
+/*
+ * The exception table consists of pairs of addresses: the first is the
+ * address of an instruction that is allowed to fault, and the second is
+ * the address at which the program should continue.  No registers are
+ * modified, so it is entirely up to the continuation code to figure out
+ * what to do.
+ *
+ * All the routines below use bits of fixup code that are out of line
+ * with the main instruction path.  This means when everything is well,
+ * we don't even have to jump over them.  Further, they do not intrude
+ * on our cache or tlb entries.
+ */
+
+struct exception_table_entry {
+        unsigned int insn, fixup;
+};
+
+extern void __ret_efault(void);
+extern void __retl_efault(void);
+
+/* Uh, these should become the main single-value transfer routines..
+ * They automatically use the right size if we just have the right
+ * pointer type..
+ *
+ * This gets kind of ugly. We want to return _two_ values in "get_user()"
+ * and yet we don't want to do any pointers, because that is too much
+ * of a performance impact. Thus we have a few rather ugly macros here,
+ * and hide all the ugliness from the user.
+ */
+#define put_user(x,ptr) ({ \
+unsigned long __pu_addr = (unsigned long)(ptr); \
+__chk_user_ptr(ptr); \
+__put_user_nocheck((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr))); })
+
+#define get_user(x,ptr) ({ \
+unsigned long __gu_addr = (unsigned long)(ptr); \
+__chk_user_ptr(ptr); \
+__get_user_nocheck((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr))); })
+
+#define __put_user(x,ptr) put_user(x,ptr)
+#define __get_user(x,ptr) get_user(x,ptr)
+
+struct __large_struct { unsigned long buf[100]; };
+#define __m(x) ((struct __large_struct *)(x))
+
+#define __put_user_nocheck(data,addr,size) ({ \
+register int __pu_ret; \
+switch (size) { \
+case 1: __put_user_asm(data,b,addr,__pu_ret); break; \
+case 2: __put_user_asm(data,h,addr,__pu_ret); break; \
+case 4: __put_user_asm(data,w,addr,__pu_ret); break; \
+case 8: __put_user_asm(data,x,addr,__pu_ret); break; \
+default: __pu_ret = __put_user_bad(); break; \
+} __pu_ret; })
+
+#define __put_user_asm(x,size,addr,ret)					\
+__asm__ __volatile__(							\
+	"/* Put user asm, inline. */\n"					\
+"1:\t"	"st"#size "a %1, [%2] %%asi\n\t"				\
+	"clr	%0\n"							\
+"2:\n\n\t"								\
+	".section .fixup,#alloc,#execinstr\n\t"				\
+	".align	4\n"							\
+"3:\n\t"								\
+	"sethi	%%hi(2b), %0\n\t"					\
+	"jmpl	%0 + %%lo(2b), %%g0\n\t"				\
+	" mov	%3, %0\n\n\t"						\
+	".previous\n\t"							\
+	".section __ex_table,\"a\"\n\t"					\
+	".align	4\n\t"							\
+	".word	1b, 3b\n\t"						\
+	".previous\n\n\t"						\
+       : "=r" (ret) : "r" (x), "r" (__m(addr)),				\
+	 "i" (-EFAULT))
+
+extern int __put_user_bad(void);
+
+#define __get_user_nocheck(data,addr,size,type) ({ \
+register int __gu_ret; \
+register unsigned long __gu_val; \
+switch (size) { \
+case 1: __get_user_asm(__gu_val,ub,addr,__gu_ret); break; \
+case 2: __get_user_asm(__gu_val,uh,addr,__gu_ret); break; \
+case 4: __get_user_asm(__gu_val,uw,addr,__gu_ret); break; \
+case 8: __get_user_asm(__gu_val,x,addr,__gu_ret); break; \
+default: __gu_val = 0; __gu_ret = __get_user_bad(); break; \
+} data = (type) __gu_val; __gu_ret; })
+
+#define __get_user_nocheck_ret(data,addr,size,type,retval) ({ \
+register unsigned long __gu_val __asm__ ("l1"); \
+switch (size) { \
+case 1: __get_user_asm_ret(__gu_val,ub,addr,retval); break; \
+case 2: __get_user_asm_ret(__gu_val,uh,addr,retval); break; \
+case 4: __get_user_asm_ret(__gu_val,uw,addr,retval); break; \
+case 8: __get_user_asm_ret(__gu_val,x,addr,retval); break; \
+default: if (__get_user_bad()) return retval; \
+} data = (type) __gu_val; })
+
+#define __get_user_asm(x,size,addr,ret)					\
+__asm__ __volatile__(							\
+	"/* Get user asm, inline. */\n"					\
+"1:\t"	"ld"#size "a [%2] %%asi, %1\n\t"				\
+	"clr	%0\n"							\
+"2:\n\n\t"								\
+	".section .fixup,#alloc,#execinstr\n\t"				\
+	".align	4\n"							\
+"3:\n\t"								\
+	"sethi	%%hi(2b), %0\n\t"					\
+	"clr	%1\n\t"							\
+	"jmpl	%0 + %%lo(2b), %%g0\n\t"				\
+	" mov	%3, %0\n\n\t"						\
+	".previous\n\t"							\
+	".section __ex_table,\"a\"\n\t"					\
+	".align	4\n\t"							\
+	".word	1b, 3b\n\n\t"						\
+	".previous\n\t"							\
+       : "=r" (ret), "=r" (x) : "r" (__m(addr)),			\
+	 "i" (-EFAULT))
+
+#define __get_user_asm_ret(x,size,addr,retval)				\
+if (__builtin_constant_p(retval) && retval == -EFAULT)			\
+__asm__ __volatile__(							\
+	"/* Get user asm ret, inline. */\n"				\
+"1:\t"	"ld"#size "a [%1] %%asi, %0\n\n\t"				\
+	".section __ex_table,\"a\"\n\t"					\
+	".align	4\n\t"							\
+	".word	1b,__ret_efault\n\n\t"					\
+	".previous\n\t"							\
+       : "=r" (x) : "r" (__m(addr)));					\
+else									\
+__asm__ __volatile__(							\
+	"/* Get user asm ret, inline. */\n"				\
+"1:\t"	"ld"#size "a [%1] %%asi, %0\n\n\t"				\
+	".section .fixup,#alloc,#execinstr\n\t"				\
+	".align	4\n"							\
+"3:\n\t"								\
+	"ret\n\t"							\
+	" restore %%g0, %2, %%o0\n\n\t"					\
+	".previous\n\t"							\
+	".section __ex_table,\"a\"\n\t"					\
+	".align	4\n\t"							\
+	".word	1b, 3b\n\n\t"						\
+	".previous\n\t"							\
+       : "=r" (x) : "r" (__m(addr)), "i" (retval))
+
+extern int __get_user_bad(void);
+
+extern unsigned long __must_check ___copy_from_user(void *to,
+						    const void __user *from,
+						    unsigned long size);
+extern unsigned long copy_from_user_fixup(void *to, const void __user *from,
+					  unsigned long size);
+static inline unsigned long __must_check
+copy_from_user(void *to, const void __user *from, unsigned long size)
+{
+	unsigned long ret = ___copy_from_user(to, from, size);
+
+	if (unlikely(ret))
+		ret = copy_from_user_fixup(to, from, size);
+	return ret;
+}
+#define __copy_from_user copy_from_user
+
+extern unsigned long __must_check ___copy_to_user(void __user *to,
+						  const void *from,
+						  unsigned long size);
+extern unsigned long copy_to_user_fixup(void __user *to, const void *from,
+					unsigned long size);
+static inline unsigned long __must_check
+copy_to_user(void __user *to, const void *from, unsigned long size)
+{
+	unsigned long ret = ___copy_to_user(to, from, size);
+
+	if (unlikely(ret))
+		ret = copy_to_user_fixup(to, from, size);
+	return ret;
+}
+#define __copy_to_user copy_to_user
+
+extern unsigned long __must_check ___copy_in_user(void __user *to,
+						  const void __user *from,
+						  unsigned long size);
+extern unsigned long copy_in_user_fixup(void __user *to, void __user *from,
+					unsigned long size);
+static inline unsigned long __must_check
+copy_in_user(void __user *to, void __user *from, unsigned long size)
+{
+	unsigned long ret = ___copy_in_user(to, from, size);
+
+	if (unlikely(ret))
+		ret = copy_in_user_fixup(to, from, size);
+	return ret;
+}
+#define __copy_in_user copy_in_user
+
+extern unsigned long __must_check __clear_user(void __user *, unsigned long);
+
+#define clear_user __clear_user
+
+extern long __must_check __strncpy_from_user(char *dest, const char __user *src, long count);
+
+#define strncpy_from_user __strncpy_from_user
+
+extern long __strlen_user(const char __user *);
+extern long __strnlen_user(const char __user *, long len);
+
+#define strlen_user __strlen_user
+#define strnlen_user __strnlen_user
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
+#endif  /* __ASSEMBLY__ */
+
+#endif /* _ASM_UACCESS_H */
diff --git a/include/asm-sparc/uctx.h b/include/asm-sparc/uctx.h
new file mode 100644
index 0000000..dc937c7
--- /dev/null
+++ b/include/asm-sparc/uctx.h
@@ -0,0 +1,71 @@
+/*
+ * uctx.h: Sparc64 {set,get}context() register state layouts.
+ *
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef __SPARC64_UCTX_H
+#define __SPARC64_UCTX_H
+
+#define MC_TSTATE	0
+#define MC_PC		1
+#define MC_NPC		2
+#define MC_Y		3
+#define MC_G1		4
+#define MC_G2		5
+#define MC_G3		6
+#define MC_G4		7
+#define MC_G5		8
+#define MC_G6		9
+#define MC_G7		10
+#define MC_O0		11
+#define MC_O1		12
+#define MC_O2		13
+#define MC_O3		14
+#define MC_O4		15
+#define MC_O5		16
+#define MC_O6		17
+#define MC_O7		18
+#define MC_NGREG	19
+
+typedef unsigned long mc_greg_t;
+typedef mc_greg_t mc_gregset_t[MC_NGREG];
+
+#define MC_MAXFPQ	16
+struct mc_fq {
+	unsigned long	*mcfq_addr;
+	unsigned int	mcfq_insn;
+};
+
+struct mc_fpu {
+	union {
+		unsigned int	sregs[32];
+		unsigned long	dregs[32];
+		long double	qregs[16];
+	} mcfpu_fregs;
+	unsigned long	mcfpu_fsr;
+	unsigned long	mcfpu_fprs;
+	unsigned long	mcfpu_gsr;
+	struct mc_fq	*mcfpu_fq;
+	unsigned char	mcfpu_qcnt;
+	unsigned char	mcfpu_qentsz;
+	unsigned char	mcfpu_enab;
+};
+typedef struct mc_fpu mc_fpu_t;
+
+typedef struct {
+	mc_gregset_t	mc_gregs;
+	mc_greg_t	mc_fp;
+	mc_greg_t	mc_i7;
+	mc_fpu_t	mc_fpregs;
+} mcontext_t;
+
+struct ucontext {
+	struct ucontext		*uc_link;
+	unsigned long		uc_flags;
+	sigset_t		uc_sigmask;
+	mcontext_t		uc_mcontext;
+};
+typedef struct ucontext ucontext_t;
+
+#endif /* __SPARC64_UCTX_H */
diff --git a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h
index 2338a02..3c26096 100644
--- a/include/asm-sparc/unistd.h
+++ b/include/asm-sparc/unistd.h
@@ -1,378 +1,8 @@
-#ifndef _SPARC_UNISTD_H
-#define _SPARC_UNISTD_H
-
-/*
- * System calls under the Sparc.
- *
- * Don't be scared by the ugly clobbers, it is the only way I can
- * think of right now to force the arguments into fixed registers
- * before the trap into the system call with gcc 'asm' statements.
- *
- * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
- *
- * SunOS compatibility based upon preliminary work which is:
- *
- * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
- */
-
-#define __NR_restart_syscall      0 /* Linux Specific				   */
-#define __NR_exit                 1 /* Common                                      */
-#define __NR_fork                 2 /* Common                                      */
-#define __NR_read                 3 /* Common                                      */
-#define __NR_write                4 /* Common                                      */
-#define __NR_open                 5 /* Common                                      */
-#define __NR_close                6 /* Common                                      */
-#define __NR_wait4                7 /* Common                                      */
-#define __NR_creat                8 /* Common                                      */
-#define __NR_link                 9 /* Common                                      */
-#define __NR_unlink              10 /* Common                                      */
-#define __NR_execv               11 /* SunOS Specific                              */
-#define __NR_chdir               12 /* Common                                      */
-#define __NR_chown		 13 /* Common					   */
-#define __NR_mknod               14 /* Common                                      */
-#define __NR_chmod               15 /* Common                                      */
-#define __NR_lchown              16 /* Common                                      */
-#define __NR_brk                 17 /* Common                                      */
-#define __NR_perfctr             18 /* Performance counter operations              */
-#define __NR_lseek               19 /* Common                                      */
-#define __NR_getpid              20 /* Common                                      */
-#define __NR_capget		 21 /* Linux Specific				   */
-#define __NR_capset		 22 /* Linux Specific				   */
-#define __NR_setuid              23 /* Implemented via setreuid in SunOS           */
-#define __NR_getuid              24 /* Common                                      */
-#define __NR_vmsplice	         25 /* ENOSYS under SunOS			   */
-#define __NR_ptrace              26 /* Common                                      */
-#define __NR_alarm               27 /* Implemented via setitimer in SunOS          */
-#define __NR_sigaltstack	 28 /* Common					   */
-#define __NR_pause               29 /* Is sigblock(0)->sigpause() in SunOS         */
-#define __NR_utime               30 /* Implemented via utimes() under SunOS        */
-#define __NR_lchown32            31 /* Linux sparc32 specific                      */
-#define __NR_fchown32            32 /* Linux sparc32 specific                      */
-#define __NR_access              33 /* Common                                      */
-#define __NR_nice                34 /* Implemented via get/setpriority() in SunOS  */
-#define __NR_chown32             35 /* Linux sparc32 specific                      */
-#define __NR_sync                36 /* Common                                      */
-#define __NR_kill                37 /* Common                                      */
-#define __NR_stat                38 /* Common                                      */
-#define __NR_sendfile		 39 /* Linux Specific				   */
-#define __NR_lstat               40 /* Common                                      */
-#define __NR_dup                 41 /* Common                                      */
-#define __NR_pipe                42 /* Common                                      */
-#define __NR_times               43 /* Implemented via getrusage() in SunOS        */
-#define __NR_getuid32            44 /* Linux sparc32 specific                      */
-#define __NR_umount2             45 /* Linux Specific                              */
-#define __NR_setgid              46 /* Implemented via setregid() in SunOS         */
-#define __NR_getgid              47 /* Common                                      */
-#define __NR_signal              48 /* Implemented via sigvec() in SunOS           */
-#define __NR_geteuid             49 /* SunOS calls getuid()                        */
-#define __NR_getegid             50 /* SunOS calls getgid()                        */
-#define __NR_acct                51 /* Common                                      */
-/* #define __NR_memory_ordering  52    Linux sparc64 specific			   */
-#define __NR_getgid32            53 /* Linux sparc32 specific                      */
-#define __NR_ioctl               54 /* Common                                      */
-#define __NR_reboot              55 /* Common                                      */
-#define __NR_mmap2		 56 /* Linux sparc32 Specific			   */
-#define __NR_symlink             57 /* Common                                      */
-#define __NR_readlink            58 /* Common                                      */
-#define __NR_execve              59 /* Common                                      */
-#define __NR_umask               60 /* Common                                      */
-#define __NR_chroot              61 /* Common                                      */
-#define __NR_fstat               62 /* Common                                      */
-#define __NR_fstat64		 63 /* Linux Specific			           */
-#define __NR_getpagesize         64 /* Common                                      */
-#define __NR_msync               65 /* Common in newer 1.3.x revs...               */
-#define __NR_vfork               66 /* Common                                      */
-#define __NR_pread64             67 /* Linux Specific                              */
-#define __NR_pwrite64            68 /* Linux Specific                              */
-#define __NR_geteuid32           69 /* Linux sparc32, sbrk under SunOS             */
-#define __NR_getegid32           70 /* Linux sparc32, sstk under SunOS             */
-#define __NR_mmap                71 /* Common                                      */
-#define __NR_setreuid32          72 /* Linux sparc32, vadvise under SunOS          */
-#define __NR_munmap              73 /* Common                                      */
-#define __NR_mprotect            74 /* Common                                      */
-#define __NR_madvise             75 /* Common                                      */
-#define __NR_vhangup             76 /* Common                                      */
-#define __NR_truncate64		 77 /* Linux sparc32 Specific			   */
-#define __NR_mincore             78 /* Common                                      */
-#define __NR_getgroups           79 /* Common                                      */
-#define __NR_setgroups           80 /* Common                                      */
-#define __NR_getpgrp             81 /* Common                                      */
-#define __NR_setgroups32         82 /* Linux sparc32, setpgrp under SunOS          */
-#define __NR_setitimer           83 /* Common                                      */
-#define __NR_ftruncate64	 84 /* Linux sparc32 Specific			   */
-#define __NR_swapon              85 /* Common                                      */
-#define __NR_getitimer           86 /* Common                                      */
-#define __NR_setuid32            87 /* Linux sparc32, gethostname under SunOS      */
-#define __NR_sethostname         88 /* Common                                      */
-#define __NR_setgid32            89 /* Linux sparc32, getdtablesize under SunOS    */
-#define __NR_dup2                90 /* Common                                      */
-#define __NR_setfsuid32          91 /* Linux sparc32, getdopt under SunOS          */
-#define __NR_fcntl               92 /* Common                                      */
-#define __NR_select              93 /* Common                                      */
-#define __NR_setfsgid32          94 /* Linux sparc32, setdopt under SunOS          */
-#define __NR_fsync               95 /* Common                                      */
-#define __NR_setpriority         96 /* Common                                      */
-#define __NR_socket              97 /* Common                                      */
-#define __NR_connect             98 /* Common                                      */
-#define __NR_accept              99 /* Common                                      */
-#define __NR_getpriority        100 /* Common                                      */
-#define __NR_rt_sigreturn       101 /* Linux Specific                              */
-#define __NR_rt_sigaction       102 /* Linux Specific                              */
-#define __NR_rt_sigprocmask     103 /* Linux Specific                              */
-#define __NR_rt_sigpending      104 /* Linux Specific                              */
-#define __NR_rt_sigtimedwait    105 /* Linux Specific                              */
-#define __NR_rt_sigqueueinfo    106 /* Linux Specific                              */
-#define __NR_rt_sigsuspend      107 /* Linux Specific                              */
-#define __NR_setresuid32        108 /* Linux Specific, sigvec under SunOS	   */
-#define __NR_getresuid32        109 /* Linux Specific, sigblock under SunOS	   */
-#define __NR_setresgid32        110 /* Linux Specific, sigsetmask under SunOS	   */
-#define __NR_getresgid32        111 /* Linux Specific, sigpause under SunOS	   */
-#define __NR_setregid32         112 /* Linux sparc32, sigstack under SunOS         */
-#define __NR_recvmsg            113 /* Common                                      */
-#define __NR_sendmsg            114 /* Common                                      */
-#define __NR_getgroups32        115 /* Linux sparc32, vtrace under SunOS           */
-#define __NR_gettimeofday       116 /* Common                                      */
-#define __NR_getrusage          117 /* Common                                      */
-#define __NR_getsockopt         118 /* Common                                      */
-#define __NR_getcwd		119 /* Linux Specific				   */
-#define __NR_readv              120 /* Common                                      */
-#define __NR_writev             121 /* Common                                      */
-#define __NR_settimeofday       122 /* Common                                      */
-#define __NR_fchown             123 /* Common                                      */
-#define __NR_fchmod             124 /* Common                                      */
-#define __NR_recvfrom           125 /* Common                                      */
-#define __NR_setreuid           126 /* Common                                      */
-#define __NR_setregid           127 /* Common                                      */
-#define __NR_rename             128 /* Common                                      */
-#define __NR_truncate           129 /* Common                                      */
-#define __NR_ftruncate          130 /* Common                                      */
-#define __NR_flock              131 /* Common                                      */
-#define __NR_lstat64		132 /* Linux Specific			           */
-#define __NR_sendto             133 /* Common                                      */
-#define __NR_shutdown           134 /* Common                                      */
-#define __NR_socketpair         135 /* Common                                      */
-#define __NR_mkdir              136 /* Common                                      */
-#define __NR_rmdir              137 /* Common                                      */
-#define __NR_utimes             138 /* SunOS Specific                              */
-#define __NR_stat64		139 /* Linux Specific			           */
-#define __NR_sendfile64         140 /* adjtime under SunOS                         */
-#define __NR_getpeername        141 /* Common                                      */
-#define __NR_futex              142 /* gethostid under SunOS                       */
-#define __NR_gettid             143 /* ENOSYS under SunOS                          */
-#define __NR_getrlimit          144 /* Common                                      */
-#define __NR_setrlimit          145 /* Common                                      */
-#define __NR_pivot_root		146 /* Linux Specific, killpg under SunOS          */
-#define __NR_prctl		147 /* ENOSYS under SunOS                          */
-#define __NR_pciconfig_read	148 /* ENOSYS under SunOS                          */
-#define __NR_pciconfig_write	149 /* ENOSYS under SunOS                          */
-#define __NR_getsockname        150 /* Common                                      */
-#define __NR_inotify_init       151 /* Linux specific                              */
-#define __NR_inotify_add_watch  152 /* Linux specific                              */
-#define __NR_poll               153 /* Common                                      */
-#define __NR_getdents64		154 /* Linux specific				   */
-#define __NR_fcntl64		155 /* Linux sparc32 Specific                      */
-#define __NR_inotify_rm_watch   156 /* Linux specific				   */
-#define __NR_statfs             157 /* Common                                      */
-#define __NR_fstatfs            158 /* Common                                      */
-#define __NR_umount             159 /* Common                                      */
-#define __NR_sched_set_affinity 160 /* Linux specific, async_daemon under SunOS    */
-#define __NR_sched_get_affinity 161 /* Linux specific, getfh under SunOS           */
-#define __NR_getdomainname      162 /* SunOS Specific                              */
-#define __NR_setdomainname      163 /* Common                                      */
-/* #define __NR_utrap_install   164    Linux sparc64 specific			   */
-#define __NR_quotactl           165 /* Common                                      */
-#define __NR_set_tid_address    166 /* Linux specific, exportfs under SunOS        */
-#define __NR_mount              167 /* Common                                      */
-#define __NR_ustat              168 /* Common                                      */
-#define __NR_setxattr           169 /* SunOS: semsys                               */
-#define __NR_lsetxattr          170 /* SunOS: msgsys                               */
-#define __NR_fsetxattr          171 /* SunOS: shmsys                               */
-#define __NR_getxattr           172 /* SunOS: auditsys                             */
-#define __NR_lgetxattr          173 /* SunOS: rfssys                               */
-#define __NR_getdents           174 /* Common                                      */
-#define __NR_setsid             175 /* Common                                      */
-#define __NR_fchdir             176 /* Common                                      */
-#define __NR_fgetxattr          177 /* SunOS: fchroot                              */
-#define __NR_listxattr          178 /* SunOS: vpixsys                              */
-#define __NR_llistxattr         179 /* SunOS: aioread                              */
-#define __NR_flistxattr         180 /* SunOS: aiowrite                             */
-#define __NR_removexattr        181 /* SunOS: aiowait                              */
-#define __NR_lremovexattr       182 /* SunOS: aiocancel                            */
-#define __NR_sigpending         183 /* Common                                      */
-#define __NR_query_module	184 /* Linux Specific				   */
-#define __NR_setpgid            185 /* Common                                      */
-#define __NR_fremovexattr       186 /* SunOS: pathconf                             */
-#define __NR_tkill              187 /* SunOS: fpathconf                            */
-#define __NR_exit_group		188 /* Linux specific, sysconf undef SunOS         */
-#define __NR_uname              189 /* Linux Specific                              */
-#define __NR_init_module        190 /* Linux Specific                              */
-#define __NR_personality        191 /* Linux Specific                              */
-#define __NR_remap_file_pages   192 /* Linux Specific                              */
-#define __NR_epoll_create       193 /* Linux Specific                              */
-#define __NR_epoll_ctl          194 /* Linux Specific                              */
-#define __NR_epoll_wait         195 /* Linux Specific                              */
-#define __NR_ioprio_set         196 /* Linux Specific                              */
-#define __NR_getppid            197 /* Linux Specific                              */
-#define __NR_sigaction          198 /* Linux Specific                              */
-#define __NR_sgetmask           199 /* Linux Specific                              */
-#define __NR_ssetmask           200 /* Linux Specific                              */
-#define __NR_sigsuspend         201 /* Linux Specific                              */
-#define __NR_oldlstat           202 /* Linux Specific                              */
-#define __NR_uselib             203 /* Linux Specific                              */
-#define __NR_readdir            204 /* Linux Specific                              */
-#define __NR_readahead          205 /* Linux Specific                              */
-#define __NR_socketcall         206 /* Linux Specific                              */
-#define __NR_syslog             207 /* Linux Specific                              */
-#define __NR_lookup_dcookie     208 /* Linux Specific                              */
-#define __NR_fadvise64          209 /* Linux Specific                              */
-#define __NR_fadvise64_64       210 /* Linux Specific                              */
-#define __NR_tgkill             211 /* Linux Specific                              */
-#define __NR_waitpid            212 /* Linux Specific                              */
-#define __NR_swapoff            213 /* Linux Specific                              */
-#define __NR_sysinfo            214 /* Linux Specific                              */
-#define __NR_ipc                215 /* Linux Specific                              */
-#define __NR_sigreturn          216 /* Linux Specific                              */
-#define __NR_clone              217 /* Linux Specific                              */
-#define __NR_ioprio_get         218 /* Linux Specific                              */
-#define __NR_adjtimex           219 /* Linux Specific                              */
-#define __NR_sigprocmask        220 /* Linux Specific                              */
-#define __NR_create_module      221 /* Linux Specific                              */
-#define __NR_delete_module      222 /* Linux Specific                              */
-#define __NR_get_kernel_syms    223 /* Linux Specific                              */
-#define __NR_getpgid            224 /* Linux Specific                              */
-#define __NR_bdflush            225 /* Linux Specific                              */
-#define __NR_sysfs              226 /* Linux Specific                              */
-#define __NR_afs_syscall        227 /* Linux Specific                              */
-#define __NR_setfsuid           228 /* Linux Specific                              */
-#define __NR_setfsgid           229 /* Linux Specific                              */
-#define __NR__newselect         230 /* Linux Specific                              */
-#define __NR_time               231 /* Linux Specific                              */
-#define __NR_splice             232 /* Linux Specific                              */
-#define __NR_stime              233 /* Linux Specific                              */
-#define __NR_statfs64           234 /* Linux Specific                              */
-#define __NR_fstatfs64          235 /* Linux Specific                              */
-#define __NR__llseek            236 /* Linux Specific                              */
-#define __NR_mlock              237
-#define __NR_munlock            238
-#define __NR_mlockall           239
-#define __NR_munlockall         240
-#define __NR_sched_setparam     241
-#define __NR_sched_getparam     242
-#define __NR_sched_setscheduler 243
-#define __NR_sched_getscheduler 244
-#define __NR_sched_yield        245
-#define __NR_sched_get_priority_max 246
-#define __NR_sched_get_priority_min 247
-#define __NR_sched_rr_get_interval  248
-#define __NR_nanosleep          249
-#define __NR_mremap             250
-#define __NR__sysctl            251
-#define __NR_getsid             252
-#define __NR_fdatasync          253
-#define __NR_nfsservctl         254
-#define __NR_sync_file_range	255
-#define __NR_clock_settime	256
-#define __NR_clock_gettime	257
-#define __NR_clock_getres	258
-#define __NR_clock_nanosleep	259
-#define __NR_sched_getaffinity	260
-#define __NR_sched_setaffinity	261
-#define __NR_timer_settime	262
-#define __NR_timer_gettime	263
-#define __NR_timer_getoverrun	264
-#define __NR_timer_delete	265
-#define __NR_timer_create	266
-/* #define __NR_vserver		267 Reserved for VSERVER */
-#define __NR_io_setup		268
-#define __NR_io_destroy		269
-#define __NR_io_submit		270
-#define __NR_io_cancel		271
-#define __NR_io_getevents	272
-#define __NR_mq_open		273
-#define __NR_mq_unlink		274
-#define __NR_mq_timedsend	275
-#define __NR_mq_timedreceive	276
-#define __NR_mq_notify		277
-#define __NR_mq_getsetattr	278
-#define __NR_waitid		279
-#define __NR_tee		280
-#define __NR_add_key		281
-#define __NR_request_key	282
-#define __NR_keyctl		283
-#define __NR_openat		284
-#define __NR_mkdirat		285
-#define __NR_mknodat		286
-#define __NR_fchownat		287
-#define __NR_futimesat		288
-#define __NR_fstatat64		289
-#define __NR_unlinkat		290
-#define __NR_renameat		291
-#define __NR_linkat		292
-#define __NR_symlinkat		293
-#define __NR_readlinkat		294
-#define __NR_fchmodat		295
-#define __NR_faccessat		296
-#define __NR_pselect6		297
-#define __NR_ppoll		298
-#define __NR_unshare		299
-#define __NR_set_robust_list	300
-#define __NR_get_robust_list	301
-#define __NR_migrate_pages	302
-#define __NR_mbind		303
-#define __NR_get_mempolicy	304
-#define __NR_set_mempolicy	305
-#define __NR_kexec_load		306
-#define __NR_move_pages		307
-#define __NR_getcpu		308
-#define __NR_epoll_pwait	309
-#define __NR_utimensat		310
-#define __NR_signalfd		311
-#define __NR_timerfd_create	312
-#define __NR_eventfd		313
-#define __NR_fallocate		314
-#define __NR_timerfd_settime	315
-#define __NR_timerfd_gettime	316
-
-#define NR_SYSCALLS		317
-
-/* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
- * it never had the plain ones and there is no value to adding those
- * old versions into the syscall table.
- */
-#define __IGNORE_setresuid
-#define __IGNORE_getresuid
-#define __IGNORE_setresgid
-#define __IGNORE_getresgid
-
-#ifdef __KERNEL__
-#define __ARCH_WANT_IPC_PARSE_VERSION
-#define __ARCH_WANT_OLD_READDIR
-#define __ARCH_WANT_STAT64
-#define __ARCH_WANT_SYS_ALARM
-#define __ARCH_WANT_SYS_GETHOSTNAME
-#define __ARCH_WANT_SYS_PAUSE
-#define __ARCH_WANT_SYS_SGETMASK
-#define __ARCH_WANT_SYS_SIGNAL
-#define __ARCH_WANT_SYS_TIME
-#define __ARCH_WANT_SYS_UTIME
-#define __ARCH_WANT_SYS_WAITPID
-#define __ARCH_WANT_SYS_SOCKETCALL
-#define __ARCH_WANT_SYS_FADVISE64
-#define __ARCH_WANT_SYS_GETPGRP
-#define __ARCH_WANT_SYS_LLSEEK
-#define __ARCH_WANT_SYS_NICE
-#define __ARCH_WANT_SYS_OLDUMOUNT
-#define __ARCH_WANT_SYS_SIGPENDING
-#define __ARCH_WANT_SYS_SIGPROCMASK
-#define __ARCH_WANT_SYS_RT_SIGSUSPEND
-
-/*
- * "Conditional" syscalls
- *
- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
- * but it doesn't work on all toolchains, so we just do it by hand
- */
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
-
-#endif /* __KERNEL__ */
-#endif /* _SPARC_UNISTD_H */
+#ifndef ___ASM_SPARC_UNISTD_H
+#define ___ASM_SPARC_UNISTD_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/unistd_64.h>
+#else
+#include <asm-sparc/unistd_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/unistd_32.h b/include/asm-sparc/unistd_32.h
new file mode 100644
index 0000000..2338a02
--- /dev/null
+++ b/include/asm-sparc/unistd_32.h
@@ -0,0 +1,378 @@
+#ifndef _SPARC_UNISTD_H
+#define _SPARC_UNISTD_H
+
+/*
+ * System calls under the Sparc.
+ *
+ * Don't be scared by the ugly clobbers, it is the only way I can
+ * think of right now to force the arguments into fixed registers
+ * before the trap into the system call with gcc 'asm' statements.
+ *
+ * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
+ *
+ * SunOS compatibility based upon preliminary work which is:
+ *
+ * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
+ */
+
+#define __NR_restart_syscall      0 /* Linux Specific				   */
+#define __NR_exit                 1 /* Common                                      */
+#define __NR_fork                 2 /* Common                                      */
+#define __NR_read                 3 /* Common                                      */
+#define __NR_write                4 /* Common                                      */
+#define __NR_open                 5 /* Common                                      */
+#define __NR_close                6 /* Common                                      */
+#define __NR_wait4                7 /* Common                                      */
+#define __NR_creat                8 /* Common                                      */
+#define __NR_link                 9 /* Common                                      */
+#define __NR_unlink              10 /* Common                                      */
+#define __NR_execv               11 /* SunOS Specific                              */
+#define __NR_chdir               12 /* Common                                      */
+#define __NR_chown		 13 /* Common					   */
+#define __NR_mknod               14 /* Common                                      */
+#define __NR_chmod               15 /* Common                                      */
+#define __NR_lchown              16 /* Common                                      */
+#define __NR_brk                 17 /* Common                                      */
+#define __NR_perfctr             18 /* Performance counter operations              */
+#define __NR_lseek               19 /* Common                                      */
+#define __NR_getpid              20 /* Common                                      */
+#define __NR_capget		 21 /* Linux Specific				   */
+#define __NR_capset		 22 /* Linux Specific				   */
+#define __NR_setuid              23 /* Implemented via setreuid in SunOS           */
+#define __NR_getuid              24 /* Common                                      */
+#define __NR_vmsplice	         25 /* ENOSYS under SunOS			   */
+#define __NR_ptrace              26 /* Common                                      */
+#define __NR_alarm               27 /* Implemented via setitimer in SunOS          */
+#define __NR_sigaltstack	 28 /* Common					   */
+#define __NR_pause               29 /* Is sigblock(0)->sigpause() in SunOS         */
+#define __NR_utime               30 /* Implemented via utimes() under SunOS        */
+#define __NR_lchown32            31 /* Linux sparc32 specific                      */
+#define __NR_fchown32            32 /* Linux sparc32 specific                      */
+#define __NR_access              33 /* Common                                      */
+#define __NR_nice                34 /* Implemented via get/setpriority() in SunOS  */
+#define __NR_chown32             35 /* Linux sparc32 specific                      */
+#define __NR_sync                36 /* Common                                      */
+#define __NR_kill                37 /* Common                                      */
+#define __NR_stat                38 /* Common                                      */
+#define __NR_sendfile		 39 /* Linux Specific				   */
+#define __NR_lstat               40 /* Common                                      */
+#define __NR_dup                 41 /* Common                                      */
+#define __NR_pipe                42 /* Common                                      */
+#define __NR_times               43 /* Implemented via getrusage() in SunOS        */
+#define __NR_getuid32            44 /* Linux sparc32 specific                      */
+#define __NR_umount2             45 /* Linux Specific                              */
+#define __NR_setgid              46 /* Implemented via setregid() in SunOS         */
+#define __NR_getgid              47 /* Common                                      */
+#define __NR_signal              48 /* Implemented via sigvec() in SunOS           */
+#define __NR_geteuid             49 /* SunOS calls getuid()                        */
+#define __NR_getegid             50 /* SunOS calls getgid()                        */
+#define __NR_acct                51 /* Common                                      */
+/* #define __NR_memory_ordering  52    Linux sparc64 specific			   */
+#define __NR_getgid32            53 /* Linux sparc32 specific                      */
+#define __NR_ioctl               54 /* Common                                      */
+#define __NR_reboot              55 /* Common                                      */
+#define __NR_mmap2		 56 /* Linux sparc32 Specific			   */
+#define __NR_symlink             57 /* Common                                      */
+#define __NR_readlink            58 /* Common                                      */
+#define __NR_execve              59 /* Common                                      */
+#define __NR_umask               60 /* Common                                      */
+#define __NR_chroot              61 /* Common                                      */
+#define __NR_fstat               62 /* Common                                      */
+#define __NR_fstat64		 63 /* Linux Specific			           */
+#define __NR_getpagesize         64 /* Common                                      */
+#define __NR_msync               65 /* Common in newer 1.3.x revs...               */
+#define __NR_vfork               66 /* Common                                      */
+#define __NR_pread64             67 /* Linux Specific                              */
+#define __NR_pwrite64            68 /* Linux Specific                              */
+#define __NR_geteuid32           69 /* Linux sparc32, sbrk under SunOS             */
+#define __NR_getegid32           70 /* Linux sparc32, sstk under SunOS             */
+#define __NR_mmap                71 /* Common                                      */
+#define __NR_setreuid32          72 /* Linux sparc32, vadvise under SunOS          */
+#define __NR_munmap              73 /* Common                                      */
+#define __NR_mprotect            74 /* Common                                      */
+#define __NR_madvise             75 /* Common                                      */
+#define __NR_vhangup             76 /* Common                                      */
+#define __NR_truncate64		 77 /* Linux sparc32 Specific			   */
+#define __NR_mincore             78 /* Common                                      */
+#define __NR_getgroups           79 /* Common                                      */
+#define __NR_setgroups           80 /* Common                                      */
+#define __NR_getpgrp             81 /* Common                                      */
+#define __NR_setgroups32         82 /* Linux sparc32, setpgrp under SunOS          */
+#define __NR_setitimer           83 /* Common                                      */
+#define __NR_ftruncate64	 84 /* Linux sparc32 Specific			   */
+#define __NR_swapon              85 /* Common                                      */
+#define __NR_getitimer           86 /* Common                                      */
+#define __NR_setuid32            87 /* Linux sparc32, gethostname under SunOS      */
+#define __NR_sethostname         88 /* Common                                      */
+#define __NR_setgid32            89 /* Linux sparc32, getdtablesize under SunOS    */
+#define __NR_dup2                90 /* Common                                      */
+#define __NR_setfsuid32          91 /* Linux sparc32, getdopt under SunOS          */
+#define __NR_fcntl               92 /* Common                                      */
+#define __NR_select              93 /* Common                                      */
+#define __NR_setfsgid32          94 /* Linux sparc32, setdopt under SunOS          */
+#define __NR_fsync               95 /* Common                                      */
+#define __NR_setpriority         96 /* Common                                      */
+#define __NR_socket              97 /* Common                                      */
+#define __NR_connect             98 /* Common                                      */
+#define __NR_accept              99 /* Common                                      */
+#define __NR_getpriority        100 /* Common                                      */
+#define __NR_rt_sigreturn       101 /* Linux Specific                              */
+#define __NR_rt_sigaction       102 /* Linux Specific                              */
+#define __NR_rt_sigprocmask     103 /* Linux Specific                              */
+#define __NR_rt_sigpending      104 /* Linux Specific                              */
+#define __NR_rt_sigtimedwait    105 /* Linux Specific                              */
+#define __NR_rt_sigqueueinfo    106 /* Linux Specific                              */
+#define __NR_rt_sigsuspend      107 /* Linux Specific                              */
+#define __NR_setresuid32        108 /* Linux Specific, sigvec under SunOS	   */
+#define __NR_getresuid32        109 /* Linux Specific, sigblock under SunOS	   */
+#define __NR_setresgid32        110 /* Linux Specific, sigsetmask under SunOS	   */
+#define __NR_getresgid32        111 /* Linux Specific, sigpause under SunOS	   */
+#define __NR_setregid32         112 /* Linux sparc32, sigstack under SunOS         */
+#define __NR_recvmsg            113 /* Common                                      */
+#define __NR_sendmsg            114 /* Common                                      */
+#define __NR_getgroups32        115 /* Linux sparc32, vtrace under SunOS           */
+#define __NR_gettimeofday       116 /* Common                                      */
+#define __NR_getrusage          117 /* Common                                      */
+#define __NR_getsockopt         118 /* Common                                      */
+#define __NR_getcwd		119 /* Linux Specific				   */
+#define __NR_readv              120 /* Common                                      */
+#define __NR_writev             121 /* Common                                      */
+#define __NR_settimeofday       122 /* Common                                      */
+#define __NR_fchown             123 /* Common                                      */
+#define __NR_fchmod             124 /* Common                                      */
+#define __NR_recvfrom           125 /* Common                                      */
+#define __NR_setreuid           126 /* Common                                      */
+#define __NR_setregid           127 /* Common                                      */
+#define __NR_rename             128 /* Common                                      */
+#define __NR_truncate           129 /* Common                                      */
+#define __NR_ftruncate          130 /* Common                                      */
+#define __NR_flock              131 /* Common                                      */
+#define __NR_lstat64		132 /* Linux Specific			           */
+#define __NR_sendto             133 /* Common                                      */
+#define __NR_shutdown           134 /* Common                                      */
+#define __NR_socketpair         135 /* Common                                      */
+#define __NR_mkdir              136 /* Common                                      */
+#define __NR_rmdir              137 /* Common                                      */
+#define __NR_utimes             138 /* SunOS Specific                              */
+#define __NR_stat64		139 /* Linux Specific			           */
+#define __NR_sendfile64         140 /* adjtime under SunOS                         */
+#define __NR_getpeername        141 /* Common                                      */
+#define __NR_futex              142 /* gethostid under SunOS                       */
+#define __NR_gettid             143 /* ENOSYS under SunOS                          */
+#define __NR_getrlimit          144 /* Common                                      */
+#define __NR_setrlimit          145 /* Common                                      */
+#define __NR_pivot_root		146 /* Linux Specific, killpg under SunOS          */
+#define __NR_prctl		147 /* ENOSYS under SunOS                          */
+#define __NR_pciconfig_read	148 /* ENOSYS under SunOS                          */
+#define __NR_pciconfig_write	149 /* ENOSYS under SunOS                          */
+#define __NR_getsockname        150 /* Common                                      */
+#define __NR_inotify_init       151 /* Linux specific                              */
+#define __NR_inotify_add_watch  152 /* Linux specific                              */
+#define __NR_poll               153 /* Common                                      */
+#define __NR_getdents64		154 /* Linux specific				   */
+#define __NR_fcntl64		155 /* Linux sparc32 Specific                      */
+#define __NR_inotify_rm_watch   156 /* Linux specific				   */
+#define __NR_statfs             157 /* Common                                      */
+#define __NR_fstatfs            158 /* Common                                      */
+#define __NR_umount             159 /* Common                                      */
+#define __NR_sched_set_affinity 160 /* Linux specific, async_daemon under SunOS    */
+#define __NR_sched_get_affinity 161 /* Linux specific, getfh under SunOS           */
+#define __NR_getdomainname      162 /* SunOS Specific                              */
+#define __NR_setdomainname      163 /* Common                                      */
+/* #define __NR_utrap_install   164    Linux sparc64 specific			   */
+#define __NR_quotactl           165 /* Common                                      */
+#define __NR_set_tid_address    166 /* Linux specific, exportfs under SunOS        */
+#define __NR_mount              167 /* Common                                      */
+#define __NR_ustat              168 /* Common                                      */
+#define __NR_setxattr           169 /* SunOS: semsys                               */
+#define __NR_lsetxattr          170 /* SunOS: msgsys                               */
+#define __NR_fsetxattr          171 /* SunOS: shmsys                               */
+#define __NR_getxattr           172 /* SunOS: auditsys                             */
+#define __NR_lgetxattr          173 /* SunOS: rfssys                               */
+#define __NR_getdents           174 /* Common                                      */
+#define __NR_setsid             175 /* Common                                      */
+#define __NR_fchdir             176 /* Common                                      */
+#define __NR_fgetxattr          177 /* SunOS: fchroot                              */
+#define __NR_listxattr          178 /* SunOS: vpixsys                              */
+#define __NR_llistxattr         179 /* SunOS: aioread                              */
+#define __NR_flistxattr         180 /* SunOS: aiowrite                             */
+#define __NR_removexattr        181 /* SunOS: aiowait                              */
+#define __NR_lremovexattr       182 /* SunOS: aiocancel                            */
+#define __NR_sigpending         183 /* Common                                      */
+#define __NR_query_module	184 /* Linux Specific				   */
+#define __NR_setpgid            185 /* Common                                      */
+#define __NR_fremovexattr       186 /* SunOS: pathconf                             */
+#define __NR_tkill              187 /* SunOS: fpathconf                            */
+#define __NR_exit_group		188 /* Linux specific, sysconf undef SunOS         */
+#define __NR_uname              189 /* Linux Specific                              */
+#define __NR_init_module        190 /* Linux Specific                              */
+#define __NR_personality        191 /* Linux Specific                              */
+#define __NR_remap_file_pages   192 /* Linux Specific                              */
+#define __NR_epoll_create       193 /* Linux Specific                              */
+#define __NR_epoll_ctl          194 /* Linux Specific                              */
+#define __NR_epoll_wait         195 /* Linux Specific                              */
+#define __NR_ioprio_set         196 /* Linux Specific                              */
+#define __NR_getppid            197 /* Linux Specific                              */
+#define __NR_sigaction          198 /* Linux Specific                              */
+#define __NR_sgetmask           199 /* Linux Specific                              */
+#define __NR_ssetmask           200 /* Linux Specific                              */
+#define __NR_sigsuspend         201 /* Linux Specific                              */
+#define __NR_oldlstat           202 /* Linux Specific                              */
+#define __NR_uselib             203 /* Linux Specific                              */
+#define __NR_readdir            204 /* Linux Specific                              */
+#define __NR_readahead          205 /* Linux Specific                              */
+#define __NR_socketcall         206 /* Linux Specific                              */
+#define __NR_syslog             207 /* Linux Specific                              */
+#define __NR_lookup_dcookie     208 /* Linux Specific                              */
+#define __NR_fadvise64          209 /* Linux Specific                              */
+#define __NR_fadvise64_64       210 /* Linux Specific                              */
+#define __NR_tgkill             211 /* Linux Specific                              */
+#define __NR_waitpid            212 /* Linux Specific                              */
+#define __NR_swapoff            213 /* Linux Specific                              */
+#define __NR_sysinfo            214 /* Linux Specific                              */
+#define __NR_ipc                215 /* Linux Specific                              */
+#define __NR_sigreturn          216 /* Linux Specific                              */
+#define __NR_clone              217 /* Linux Specific                              */
+#define __NR_ioprio_get         218 /* Linux Specific                              */
+#define __NR_adjtimex           219 /* Linux Specific                              */
+#define __NR_sigprocmask        220 /* Linux Specific                              */
+#define __NR_create_module      221 /* Linux Specific                              */
+#define __NR_delete_module      222 /* Linux Specific                              */
+#define __NR_get_kernel_syms    223 /* Linux Specific                              */
+#define __NR_getpgid            224 /* Linux Specific                              */
+#define __NR_bdflush            225 /* Linux Specific                              */
+#define __NR_sysfs              226 /* Linux Specific                              */
+#define __NR_afs_syscall        227 /* Linux Specific                              */
+#define __NR_setfsuid           228 /* Linux Specific                              */
+#define __NR_setfsgid           229 /* Linux Specific                              */
+#define __NR__newselect         230 /* Linux Specific                              */
+#define __NR_time               231 /* Linux Specific                              */
+#define __NR_splice             232 /* Linux Specific                              */
+#define __NR_stime              233 /* Linux Specific                              */
+#define __NR_statfs64           234 /* Linux Specific                              */
+#define __NR_fstatfs64          235 /* Linux Specific                              */
+#define __NR__llseek            236 /* Linux Specific                              */
+#define __NR_mlock              237
+#define __NR_munlock            238
+#define __NR_mlockall           239
+#define __NR_munlockall         240
+#define __NR_sched_setparam     241
+#define __NR_sched_getparam     242
+#define __NR_sched_setscheduler 243
+#define __NR_sched_getscheduler 244
+#define __NR_sched_yield        245
+#define __NR_sched_get_priority_max 246
+#define __NR_sched_get_priority_min 247
+#define __NR_sched_rr_get_interval  248
+#define __NR_nanosleep          249
+#define __NR_mremap             250
+#define __NR__sysctl            251
+#define __NR_getsid             252
+#define __NR_fdatasync          253
+#define __NR_nfsservctl         254
+#define __NR_sync_file_range	255
+#define __NR_clock_settime	256
+#define __NR_clock_gettime	257
+#define __NR_clock_getres	258
+#define __NR_clock_nanosleep	259
+#define __NR_sched_getaffinity	260
+#define __NR_sched_setaffinity	261
+#define __NR_timer_settime	262
+#define __NR_timer_gettime	263
+#define __NR_timer_getoverrun	264
+#define __NR_timer_delete	265
+#define __NR_timer_create	266
+/* #define __NR_vserver		267 Reserved for VSERVER */
+#define __NR_io_setup		268
+#define __NR_io_destroy		269
+#define __NR_io_submit		270
+#define __NR_io_cancel		271
+#define __NR_io_getevents	272
+#define __NR_mq_open		273
+#define __NR_mq_unlink		274
+#define __NR_mq_timedsend	275
+#define __NR_mq_timedreceive	276
+#define __NR_mq_notify		277
+#define __NR_mq_getsetattr	278
+#define __NR_waitid		279
+#define __NR_tee		280
+#define __NR_add_key		281
+#define __NR_request_key	282
+#define __NR_keyctl		283
+#define __NR_openat		284
+#define __NR_mkdirat		285
+#define __NR_mknodat		286
+#define __NR_fchownat		287
+#define __NR_futimesat		288
+#define __NR_fstatat64		289
+#define __NR_unlinkat		290
+#define __NR_renameat		291
+#define __NR_linkat		292
+#define __NR_symlinkat		293
+#define __NR_readlinkat		294
+#define __NR_fchmodat		295
+#define __NR_faccessat		296
+#define __NR_pselect6		297
+#define __NR_ppoll		298
+#define __NR_unshare		299
+#define __NR_set_robust_list	300
+#define __NR_get_robust_list	301
+#define __NR_migrate_pages	302
+#define __NR_mbind		303
+#define __NR_get_mempolicy	304
+#define __NR_set_mempolicy	305
+#define __NR_kexec_load		306
+#define __NR_move_pages		307
+#define __NR_getcpu		308
+#define __NR_epoll_pwait	309
+#define __NR_utimensat		310
+#define __NR_signalfd		311
+#define __NR_timerfd_create	312
+#define __NR_eventfd		313
+#define __NR_fallocate		314
+#define __NR_timerfd_settime	315
+#define __NR_timerfd_gettime	316
+
+#define NR_SYSCALLS		317
+
+/* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
+ * it never had the plain ones and there is no value to adding those
+ * old versions into the syscall table.
+ */
+#define __IGNORE_setresuid
+#define __IGNORE_getresuid
+#define __IGNORE_setresgid
+#define __IGNORE_getresgid
+
+#ifdef __KERNEL__
+#define __ARCH_WANT_IPC_PARSE_VERSION
+#define __ARCH_WANT_OLD_READDIR
+#define __ARCH_WANT_STAT64
+#define __ARCH_WANT_SYS_ALARM
+#define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_SYS_PAUSE
+#define __ARCH_WANT_SYS_SGETMASK
+#define __ARCH_WANT_SYS_SIGNAL
+#define __ARCH_WANT_SYS_TIME
+#define __ARCH_WANT_SYS_UTIME
+#define __ARCH_WANT_SYS_WAITPID
+#define __ARCH_WANT_SYS_SOCKETCALL
+#define __ARCH_WANT_SYS_FADVISE64
+#define __ARCH_WANT_SYS_GETPGRP
+#define __ARCH_WANT_SYS_LLSEEK
+#define __ARCH_WANT_SYS_NICE
+#define __ARCH_WANT_SYS_OLDUMOUNT
+#define __ARCH_WANT_SYS_SIGPENDING
+#define __ARCH_WANT_SYS_SIGPROCMASK
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
+
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
+
+#endif /* __KERNEL__ */
+#endif /* _SPARC_UNISTD_H */
diff --git a/include/asm-sparc/unistd_64.h b/include/asm-sparc/unistd_64.h
new file mode 100644
index 0000000..13be445
--- /dev/null
+++ b/include/asm-sparc/unistd_64.h
@@ -0,0 +1,373 @@
+#ifndef _SPARC64_UNISTD_H
+#define _SPARC64_UNISTD_H
+
+/*
+ * System calls under the Sparc.
+ *
+ * Don't be scared by the ugly clobbers, it is the only way I can
+ * think of right now to force the arguments into fixed registers
+ * before the trap into the system call with gcc 'asm' statements.
+ *
+ * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
+ *
+ * SunOS compatibility based upon preliminary work which is:
+ *
+ * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
+ */
+
+#define __NR_restart_syscall      0 /* Linux Specific				   */
+#define __NR_exit                 1 /* Common                                      */
+#define __NR_fork                 2 /* Common                                      */
+#define __NR_read                 3 /* Common                                      */
+#define __NR_write                4 /* Common                                      */
+#define __NR_open                 5 /* Common                                      */
+#define __NR_close                6 /* Common                                      */
+#define __NR_wait4                7 /* Common                                      */
+#define __NR_creat                8 /* Common                                      */
+#define __NR_link                 9 /* Common                                      */
+#define __NR_unlink              10 /* Common                                      */
+#define __NR_execv               11 /* SunOS Specific                              */
+#define __NR_chdir               12 /* Common                                      */
+#define __NR_chown		 13 /* Common					   */
+#define __NR_mknod               14 /* Common                                      */
+#define __NR_chmod               15 /* Common                                      */
+#define __NR_lchown              16 /* Common                                      */
+#define __NR_brk                 17 /* Common                                      */
+#define __NR_perfctr             18 /* Performance counter operations              */
+#define __NR_lseek               19 /* Common                                      */
+#define __NR_getpid              20 /* Common                                      */
+#define __NR_capget		 21 /* Linux Specific				   */
+#define __NR_capset		 22 /* Linux Specific				   */
+#define __NR_setuid              23 /* Implemented via setreuid in SunOS           */
+#define __NR_getuid              24 /* Common                                      */
+#define __NR_vmsplice	         25 /* ENOSYS under SunOS			   */
+#define __NR_ptrace              26 /* Common                                      */
+#define __NR_alarm               27 /* Implemented via setitimer in SunOS          */
+#define __NR_sigaltstack	 28 /* Common					   */
+#define __NR_pause               29 /* Is sigblock(0)->sigpause() in SunOS         */
+#define __NR_utime               30 /* Implemented via utimes() under SunOS        */
+/* #define __NR_lchown32         31    Linux sparc32 specific                      */
+/* #define __NR_fchown32         32    Linux sparc32 specific                      */
+#define __NR_access              33 /* Common                                      */
+#define __NR_nice                34 /* Implemented via get/setpriority() in SunOS  */
+/* #define __NR_chown32          35    Linux sparc32 specific                      */
+#define __NR_sync                36 /* Common                                      */
+#define __NR_kill                37 /* Common                                      */
+#define __NR_stat                38 /* Common                                      */
+#define __NR_sendfile		 39 /* Linux Specific				   */
+#define __NR_lstat               40 /* Common                                      */
+#define __NR_dup                 41 /* Common                                      */
+#define __NR_pipe                42 /* Common                                      */
+#define __NR_times               43 /* Implemented via getrusage() in SunOS        */
+/* #define __NR_getuid32         44    Linux sparc32 specific                      */
+#define __NR_umount2             45 /* Linux Specific                              */
+#define __NR_setgid              46 /* Implemented via setregid() in SunOS         */
+#define __NR_getgid              47 /* Common                                      */
+#define __NR_signal              48 /* Implemented via sigvec() in SunOS           */
+#define __NR_geteuid             49 /* SunOS calls getuid()                        */
+#define __NR_getegid             50 /* SunOS calls getgid()                        */
+#define __NR_acct                51 /* Common                                      */
+#define __NR_memory_ordering	 52 /* Linux Specific				   */
+/* #define __NR_getgid32         53    Linux sparc32 specific                      */
+#define __NR_ioctl               54 /* Common                                      */
+#define __NR_reboot              55 /* Common                                      */
+/* #define __NR_mmap2		 56    Linux sparc32 Specific                      */
+#define __NR_symlink             57 /* Common                                      */
+#define __NR_readlink            58 /* Common                                      */
+#define __NR_execve              59 /* Common                                      */
+#define __NR_umask               60 /* Common                                      */
+#define __NR_chroot              61 /* Common                                      */
+#define __NR_fstat               62 /* Common                                      */
+#define __NR_fstat64             63 /* Linux Specific                              */
+#define __NR_getpagesize         64 /* Common                                      */
+#define __NR_msync               65 /* Common in newer 1.3.x revs...               */
+#define __NR_vfork               66 /* Common                                      */
+#define __NR_pread64             67 /* Linux Specific                              */
+#define __NR_pwrite64            68 /* Linux Specific                              */
+/* #define __NR_geteuid32        69    Linux sparc32, sbrk under SunOS             */
+/* #define __NR_getegid32        70    Linux sparc32, sstk under SunOS             */
+#define __NR_mmap                71 /* Common                                      */
+/* #define __NR_setreuid32       72    Linux sparc32, vadvise under SunOS          */
+#define __NR_munmap              73 /* Common                                      */
+#define __NR_mprotect            74 /* Common                                      */
+#define __NR_madvise             75 /* Common                                      */
+#define __NR_vhangup             76 /* Common                                      */
+/* #define __NR_truncate64       77    Linux sparc32 Specific			   */
+#define __NR_mincore             78 /* Common                                      */
+#define __NR_getgroups           79 /* Common                                      */
+#define __NR_setgroups           80 /* Common                                      */
+#define __NR_getpgrp             81 /* Common                                      */
+/* #define __NR_setgroups32      82    Linux sparc32, setpgrp under SunOS          */
+#define __NR_setitimer           83 /* Common                                      */
+/* #define __NR_ftruncate64      84    Linux sparc32 Specific			   */
+#define __NR_swapon              85 /* Common                                      */
+#define __NR_getitimer           86 /* Common                                      */
+/* #define __NR_setuid32         87    Linux sparc32, gethostname under SunOS      */
+#define __NR_sethostname         88 /* Common                                      */
+/* #define __NR_setgid32         89    Linux sparc32, getdtablesize under SunOS    */
+#define __NR_dup2                90 /* Common                                      */
+/* #define __NR_setfsuid32       91    Linux sparc32, getdopt under SunOS          */
+#define __NR_fcntl               92 /* Common                                      */
+#define __NR_select              93 /* Common                                      */
+/* #define __NR_setfsgid32       94    Linux sparc32, setdopt under SunOS          */
+#define __NR_fsync               95 /* Common                                      */
+#define __NR_setpriority         96 /* Common                                      */
+#define __NR_socket              97 /* Common                                      */
+#define __NR_connect             98 /* Common                                      */
+#define __NR_accept              99 /* Common                                      */
+#define __NR_getpriority        100 /* Common                                      */
+#define __NR_rt_sigreturn       101 /* Linux Specific                              */
+#define __NR_rt_sigaction       102 /* Linux Specific                              */
+#define __NR_rt_sigprocmask     103 /* Linux Specific                              */
+#define __NR_rt_sigpending      104 /* Linux Specific                              */
+#define __NR_rt_sigtimedwait    105 /* Linux Specific                              */
+#define __NR_rt_sigqueueinfo    106 /* Linux Specific                              */
+#define __NR_rt_sigsuspend      107 /* Linux Specific                              */
+#define __NR_setresuid          108 /* Linux Specific, sigvec under SunOS	   */
+#define __NR_getresuid          109 /* Linux Specific, sigblock under SunOS	   */
+#define __NR_setresgid          110 /* Linux Specific, sigsetmask under SunOS	   */
+#define __NR_getresgid          111 /* Linux Specific, sigpause under SunOS	   */
+/* #define __NR_setregid32       75    Linux sparc32, sigstack under SunOS         */
+#define __NR_recvmsg            113 /* Common                                      */
+#define __NR_sendmsg            114 /* Common                                      */
+/* #define __NR_getgroups32     115    Linux sparc32, vtrace under SunOS           */
+#define __NR_gettimeofday       116 /* Common                                      */
+#define __NR_getrusage          117 /* Common                                      */
+#define __NR_getsockopt         118 /* Common                                      */
+#define __NR_getcwd		119 /* Linux Specific				   */
+#define __NR_readv              120 /* Common                                      */
+#define __NR_writev             121 /* Common                                      */
+#define __NR_settimeofday       122 /* Common                                      */
+#define __NR_fchown             123 /* Common                                      */
+#define __NR_fchmod             124 /* Common                                      */
+#define __NR_recvfrom           125 /* Common                                      */
+#define __NR_setreuid           126 /* Common                                      */
+#define __NR_setregid           127 /* Common                                      */
+#define __NR_rename             128 /* Common                                      */
+#define __NR_truncate           129 /* Common                                      */
+#define __NR_ftruncate          130 /* Common                                      */
+#define __NR_flock              131 /* Common                                      */
+#define __NR_lstat64		132 /* Linux Specific                              */
+#define __NR_sendto             133 /* Common                                      */
+#define __NR_shutdown           134 /* Common                                      */
+#define __NR_socketpair         135 /* Common                                      */
+#define __NR_mkdir              136 /* Common                                      */
+#define __NR_rmdir              137 /* Common                                      */
+#define __NR_utimes             138 /* SunOS Specific                              */
+#define __NR_stat64		139 /* Linux Specific			           */
+#define __NR_sendfile64         140 /* adjtime under SunOS                         */
+#define __NR_getpeername        141 /* Common                                      */
+#define __NR_futex              142 /* gethostid under SunOS                       */
+#define __NR_gettid             143 /* ENOSYS under SunOS                          */
+#define __NR_getrlimit		144 /* Common                                      */
+#define __NR_setrlimit          145 /* Common                                      */
+#define __NR_pivot_root		146 /* Linux Specific, killpg under SunOS          */
+#define __NR_prctl		147 /* ENOSYS under SunOS                          */
+#define __NR_pciconfig_read	148 /* ENOSYS under SunOS                          */
+#define __NR_pciconfig_write	149 /* ENOSYS under SunOS                          */
+#define __NR_getsockname        150 /* Common                                      */
+#define __NR_inotify_init       151 /* Linux specific                              */
+#define __NR_inotify_add_watch  152 /* Linux specific                              */
+#define __NR_poll               153 /* Common                                      */
+#define __NR_getdents64		154 /* Linux specific				   */
+/* #define __NR_fcntl64         155    Linux sparc32 Specific                      */
+#define __NR_inotify_rm_watch   156 /* Linux specific				   */
+#define __NR_statfs             157 /* Common                                      */
+#define __NR_fstatfs            158 /* Common                                      */
+#define __NR_umount             159 /* Common                                      */
+#define __NR_sched_set_affinity 160 /* Linux specific, async_daemon under SunOS    */
+#define __NR_sched_get_affinity 161 /* Linux specific, getfh under SunOS           */
+#define __NR_getdomainname      162 /* SunOS Specific                              */
+#define __NR_setdomainname      163 /* Common                                      */
+#define __NR_utrap_install	164 /* SYSV ABI/v9 required			   */
+#define __NR_quotactl           165 /* Common                                      */
+#define __NR_set_tid_address    166 /* Linux specific, exportfs under SunOS        */
+#define __NR_mount              167 /* Common                                      */
+#define __NR_ustat              168 /* Common                                      */
+#define __NR_setxattr           169 /* SunOS: semsys                               */
+#define __NR_lsetxattr          170 /* SunOS: msgsys                               */
+#define __NR_fsetxattr          171 /* SunOS: shmsys                               */
+#define __NR_getxattr           172 /* SunOS: auditsys                             */
+#define __NR_lgetxattr          173 /* SunOS: rfssys                               */
+#define __NR_getdents           174 /* Common                                      */
+#define __NR_setsid             175 /* Common                                      */
+#define __NR_fchdir             176 /* Common                                      */
+#define __NR_fgetxattr          177 /* SunOS: fchroot                              */
+#define __NR_listxattr          178 /* SunOS: vpixsys                              */
+#define __NR_llistxattr         179 /* SunOS: aioread                              */
+#define __NR_flistxattr         180 /* SunOS: aiowrite                             */
+#define __NR_removexattr        181 /* SunOS: aiowait                              */
+#define __NR_lremovexattr       182 /* SunOS: aiocancel                            */
+#define __NR_sigpending         183 /* Common                                      */
+#define __NR_query_module	184 /* Linux Specific				   */
+#define __NR_setpgid            185 /* Common                                      */
+#define __NR_fremovexattr       186 /* SunOS: pathconf                             */
+#define __NR_tkill              187 /* SunOS: fpathconf                            */
+#define __NR_exit_group		188 /* Linux specific, sysconf undef SunOS         */
+#define __NR_uname              189 /* Linux Specific                              */
+#define __NR_init_module        190 /* Linux Specific                              */
+#define __NR_personality        191 /* Linux Specific                              */
+#define __NR_remap_file_pages   192 /* Linux Specific                              */
+#define __NR_epoll_create       193 /* Linux Specific                              */
+#define __NR_epoll_ctl          194 /* Linux Specific                              */
+#define __NR_epoll_wait         195 /* Linux Specific                              */
+#define __NR_ioprio_set         196 /* Linux Specific                              */
+#define __NR_getppid            197 /* Linux Specific                              */
+#define __NR_sigaction          198 /* Linux Specific                              */
+#define __NR_sgetmask           199 /* Linux Specific                              */
+#define __NR_ssetmask           200 /* Linux Specific                              */
+#define __NR_sigsuspend         201 /* Linux Specific                              */
+#define __NR_oldlstat           202 /* Linux Specific                              */
+#define __NR_uselib             203 /* Linux Specific                              */
+#define __NR_readdir            204 /* Linux Specific                              */
+#define __NR_readahead          205 /* Linux Specific                              */
+#define __NR_socketcall         206 /* Linux Specific                              */
+#define __NR_syslog             207 /* Linux Specific                              */
+#define __NR_lookup_dcookie     208 /* Linux Specific                              */
+#define __NR_fadvise64          209 /* Linux Specific                              */
+#define __NR_fadvise64_64       210 /* Linux Specific                              */
+#define __NR_tgkill             211 /* Linux Specific                              */
+#define __NR_waitpid            212 /* Linux Specific                              */
+#define __NR_swapoff            213 /* Linux Specific                              */
+#define __NR_sysinfo            214 /* Linux Specific                              */
+#define __NR_ipc                215 /* Linux Specific                              */
+#define __NR_sigreturn          216 /* Linux Specific                              */
+#define __NR_clone              217 /* Linux Specific                              */
+#define __NR_ioprio_get         218 /* Linux Specific                              */
+#define __NR_adjtimex           219 /* Linux Specific                              */
+#define __NR_sigprocmask        220 /* Linux Specific                              */
+#define __NR_create_module      221 /* Linux Specific                              */
+#define __NR_delete_module      222 /* Linux Specific                              */
+#define __NR_get_kernel_syms    223 /* Linux Specific                              */
+#define __NR_getpgid            224 /* Linux Specific                              */
+#define __NR_bdflush            225 /* Linux Specific                              */
+#define __NR_sysfs              226 /* Linux Specific                              */
+#define __NR_afs_syscall        227 /* Linux Specific                              */
+#define __NR_setfsuid           228 /* Linux Specific                              */
+#define __NR_setfsgid           229 /* Linux Specific                              */
+#define __NR__newselect         230 /* Linux Specific                              */
+#ifdef __KERNEL__
+#define __NR_time		231 /* Linux sparc32                               */
+#endif
+#define __NR_splice             232 /* Linux Specific                              */
+#define __NR_stime              233 /* Linux Specific                              */
+#define __NR_statfs64           234 /* Linux Specific                              */
+#define __NR_fstatfs64          235 /* Linux Specific                              */
+#define __NR__llseek            236 /* Linux Specific                              */
+#define __NR_mlock              237
+#define __NR_munlock            238
+#define __NR_mlockall           239
+#define __NR_munlockall         240
+#define __NR_sched_setparam     241
+#define __NR_sched_getparam     242
+#define __NR_sched_setscheduler 243
+#define __NR_sched_getscheduler 244
+#define __NR_sched_yield        245
+#define __NR_sched_get_priority_max 246
+#define __NR_sched_get_priority_min 247
+#define __NR_sched_rr_get_interval  248
+#define __NR_nanosleep          249
+#define __NR_mremap             250
+#define __NR__sysctl            251
+#define __NR_getsid             252
+#define __NR_fdatasync          253
+#define __NR_nfsservctl         254
+#define __NR_sync_file_range	255
+#define __NR_clock_settime	256
+#define __NR_clock_gettime	257
+#define __NR_clock_getres	258
+#define __NR_clock_nanosleep	259
+#define __NR_sched_getaffinity	260
+#define __NR_sched_setaffinity	261
+#define __NR_timer_settime	262
+#define __NR_timer_gettime	263
+#define __NR_timer_getoverrun	264
+#define __NR_timer_delete	265
+#define __NR_timer_create	266
+/* #define __NR_vserver		267 Reserved for VSERVER */
+#define __NR_io_setup		268
+#define __NR_io_destroy		269
+#define __NR_io_submit		270
+#define __NR_io_cancel		271
+#define __NR_io_getevents	272
+#define __NR_mq_open		273
+#define __NR_mq_unlink		274
+#define __NR_mq_timedsend	275
+#define __NR_mq_timedreceive	276
+#define __NR_mq_notify		277
+#define __NR_mq_getsetattr	278
+#define __NR_waitid		279
+#define __NR_tee		280
+#define __NR_add_key		281
+#define __NR_request_key	282
+#define __NR_keyctl		283
+#define __NR_openat		284
+#define __NR_mkdirat		285
+#define __NR_mknodat		286
+#define __NR_fchownat		287
+#define __NR_futimesat		288
+#define __NR_fstatat64		289
+#define __NR_unlinkat		290
+#define __NR_renameat		291
+#define __NR_linkat		292
+#define __NR_symlinkat		293
+#define __NR_readlinkat		294
+#define __NR_fchmodat		295
+#define __NR_faccessat		296
+#define __NR_pselect6		297
+#define __NR_ppoll		298
+#define __NR_unshare		299
+#define __NR_set_robust_list	300
+#define __NR_get_robust_list	301
+#define __NR_migrate_pages	302
+#define __NR_mbind		303
+#define __NR_get_mempolicy	304
+#define __NR_set_mempolicy	305
+#define __NR_kexec_load		306
+#define __NR_move_pages		307
+#define __NR_getcpu		308
+#define __NR_epoll_pwait	309
+#define __NR_utimensat		310
+#define __NR_signalfd		311
+#define __NR_timerfd_create	312
+#define __NR_eventfd		313
+#define __NR_fallocate		314
+#define __NR_timerfd_settime	315
+#define __NR_timerfd_gettime	316
+
+#define NR_SYSCALLS		317
+
+#ifdef __KERNEL__
+#define __ARCH_WANT_IPC_PARSE_VERSION
+#define __ARCH_WANT_OLD_READDIR
+#define __ARCH_WANT_STAT64
+#define __ARCH_WANT_SYS_ALARM
+#define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_SYS_PAUSE
+#define __ARCH_WANT_SYS_SGETMASK
+#define __ARCH_WANT_SYS_SIGNAL
+#define __ARCH_WANT_SYS_TIME
+#define __ARCH_WANT_COMPAT_SYS_TIME
+#define __ARCH_WANT_SYS_UTIME
+#define __ARCH_WANT_SYS_WAITPID
+#define __ARCH_WANT_SYS_SOCKETCALL
+#define __ARCH_WANT_SYS_FADVISE64
+#define __ARCH_WANT_SYS_GETPGRP
+#define __ARCH_WANT_SYS_LLSEEK
+#define __ARCH_WANT_SYS_NICE
+#define __ARCH_WANT_SYS_OLDUMOUNT
+#define __ARCH_WANT_SYS_SIGPENDING
+#define __ARCH_WANT_SYS_SIGPROCMASK
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
+
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
+
+#endif /* __KERNEL__ */
+#endif /* _SPARC64_UNISTD_H */
diff --git a/include/asm-sparc/upa.h b/include/asm-sparc/upa.h
new file mode 100644
index 0000000..5b16332
--- /dev/null
+++ b/include/asm-sparc/upa.h
@@ -0,0 +1,109 @@
+#ifndef _SPARC64_UPA_H
+#define _SPARC64_UPA_H
+
+#include <asm/asi.h>
+
+/* UPA level registers and defines. */
+
+/* UPA Config Register */
+#define UPA_CONFIG_RESV		0xffffffffc0000000 /* Reserved.                    */
+#define UPA_CONFIG_PCON		0x000000003fc00000 /* Depth of various sys queues. */
+#define UPA_CONFIG_MID		0x00000000003e0000 /* Module ID.                   */
+#define UPA_CONFIG_PCAP		0x000000000001ffff /* Port Capabilities.           */
+
+/* UPA Port ID Register */
+#define UPA_PORTID_FNP		0xff00000000000000 /* Hardcoded to 0xfc on ultra.  */
+#define UPA_PORTID_RESV		0x00fffff800000000 /* Reserved.                    */
+#define UPA_PORTID_ECCVALID     0x0000000400000000 /* Zero if mod can generate ECC */
+#define UPA_PORTID_ONEREAD      0x0000000200000000 /* Set if mod generates P_RASB  */
+#define UPA_PORTID_PINTRDQ      0x0000000180000000 /* # outstanding P_INT_REQ's    */
+#define UPA_PORTID_PREQDQ       0x000000007e000000 /* slave-wr's to mod supported  */
+#define UPA_PORTID_PREQRD       0x0000000001e00000 /* # incoming P_REQ's supported */
+#define UPA_PORTID_UPACAP       0x00000000001f0000 /* UPA capabilities of mod      */
+#define UPA_PORTID_ID           0x000000000000ffff /* Module Identification bits  */
+
+/* UPA I/O space accessors */
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+static inline unsigned char _upa_readb(unsigned long addr)
+{
+	unsigned char ret;
+
+	__asm__ __volatile__("lduba\t[%1] %2, %0\t/* upa_readb */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+	return ret;
+}
+
+static inline unsigned short _upa_readw(unsigned long addr)
+{
+	unsigned short ret;
+
+	__asm__ __volatile__("lduha\t[%1] %2, %0\t/* upa_readw */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+	return ret;
+}
+
+static inline unsigned int _upa_readl(unsigned long addr)
+{
+	unsigned int ret;
+
+	__asm__ __volatile__("lduwa\t[%1] %2, %0\t/* upa_readl */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+	return ret;
+}
+
+static inline unsigned long _upa_readq(unsigned long addr)
+{
+	unsigned long ret;
+
+	__asm__ __volatile__("ldxa\t[%1] %2, %0\t/* upa_readq */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+	return ret;
+}
+
+static inline void _upa_writeb(unsigned char b, unsigned long addr)
+{
+	__asm__ __volatile__("stba\t%0, [%1] %2\t/* upa_writeb */"
+			     : /* no outputs */
+			     : "r" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+static inline void _upa_writew(unsigned short w, unsigned long addr)
+{
+	__asm__ __volatile__("stha\t%0, [%1] %2\t/* upa_writew */"
+			     : /* no outputs */
+			     : "r" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+static inline void _upa_writel(unsigned int l, unsigned long addr)
+{
+	__asm__ __volatile__("stwa\t%0, [%1] %2\t/* upa_writel */"
+			     : /* no outputs */
+			     : "r" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+static inline void _upa_writeq(unsigned long q, unsigned long addr)
+{
+	__asm__ __volatile__("stxa\t%0, [%1] %2\t/* upa_writeq */"
+			     : /* no outputs */
+			     : "r" (q), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+#define upa_readb(__addr)		(_upa_readb((unsigned long)(__addr)))
+#define upa_readw(__addr)		(_upa_readw((unsigned long)(__addr)))
+#define upa_readl(__addr)		(_upa_readl((unsigned long)(__addr)))
+#define upa_readq(__addr)		(_upa_readq((unsigned long)(__addr)))
+#define upa_writeb(__b, __addr)		(_upa_writeb((__b), (unsigned long)(__addr)))
+#define upa_writew(__w, __addr)		(_upa_writew((__w), (unsigned long)(__addr)))
+#define upa_writel(__l, __addr)		(_upa_writel((__l), (unsigned long)(__addr)))
+#define upa_writeq(__q, __addr)		(_upa_writeq((__q), (unsigned long)(__addr)))
+#endif /* __KERNEL__ && !__ASSEMBLY__ */
+
+#endif /* !(_SPARC64_UPA_H) */
diff --git a/include/asm-sparc/utrap.h b/include/asm-sparc/utrap.h
new file mode 100644
index 0000000..9da37ba
--- /dev/null
+++ b/include/asm-sparc/utrap.h
@@ -0,0 +1,51 @@
+/*
+ * include/asm-sparc64/utrap.h
+ *
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#ifndef __ASM_SPARC64_UTRAP_H
+#define __ASM_SPARC64_UTRAP_H
+
+#define UT_INSTRUCTION_EXCEPTION		1
+#define UT_INSTRUCTION_ERROR			2
+#define UT_INSTRUCTION_PROTECTION		3
+#define UT_ILLTRAP_INSTRUCTION			4
+#define UT_ILLEGAL_INSTRUCTION			5
+#define UT_PRIVILEGED_OPCODE			6
+#define UT_FP_DISABLED				7
+#define UT_FP_EXCEPTION_IEEE_754		8
+#define UT_FP_EXCEPTION_OTHER			9
+#define UT_TAG_OVERVIEW				10
+#define UT_DIVISION_BY_ZERO			11
+#define UT_DATA_EXCEPTION			12
+#define UT_DATA_ERROR				13
+#define UT_DATA_PROTECTION			14
+#define UT_MEM_ADDRESS_NOT_ALIGNED		15
+#define UT_PRIVILEGED_ACTION			16
+#define UT_ASYNC_DATA_ERROR			17
+#define UT_TRAP_INSTRUCTION_16			18
+#define UT_TRAP_INSTRUCTION_17			19
+#define UT_TRAP_INSTRUCTION_18			20
+#define UT_TRAP_INSTRUCTION_19			21
+#define UT_TRAP_INSTRUCTION_20			22
+#define UT_TRAP_INSTRUCTION_21			23
+#define UT_TRAP_INSTRUCTION_22			24
+#define UT_TRAP_INSTRUCTION_23			25
+#define UT_TRAP_INSTRUCTION_24			26
+#define UT_TRAP_INSTRUCTION_25			27
+#define UT_TRAP_INSTRUCTION_26			28
+#define UT_TRAP_INSTRUCTION_27			29
+#define UT_TRAP_INSTRUCTION_28			30
+#define UT_TRAP_INSTRUCTION_29			31
+#define UT_TRAP_INSTRUCTION_30			32
+#define UT_TRAP_INSTRUCTION_31			33
+
+#define	UTH_NOCHANGE				(-1)
+
+#ifndef __ASSEMBLY__
+typedef int utrap_entry_t;
+typedef void *utrap_handler_t;
+#endif /* __ASSEMBLY__ */
+
+#endif /* !(__ASM_SPARC64_PROCESSOR_H) */
diff --git a/include/asm-sparc/vaddrs.h b/include/asm-sparc/vaddrs.h
index f6ca477..a22fed5 100644
--- a/include/asm-sparc/vaddrs.h
+++ b/include/asm-sparc/vaddrs.h
@@ -34,11 +34,6 @@
 #define IOBASE_VADDR		0xfe000000
 #define IOBASE_END		0xfe600000
 
-#define VMALLOC_START		0xfe600000
-
-/* XXX Alter this when I get around to fixing sun4c - Anton */
-#define VMALLOC_END		0xffc00000
-
 /*
  * On the sun4/4c we need a place
  * to reliably map locked down kernel data.  This includes the
diff --git a/include/asm-sparc/vio.h b/include/asm-sparc/vio.h
new file mode 100644
index 0000000..d4de32f
--- /dev/null
+++ b/include/asm-sparc/vio.h
@@ -0,0 +1,406 @@
+#ifndef _SPARC64_VIO_H
+#define _SPARC64_VIO_H
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/timer.h>
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/list.h>
+#include <linux/log2.h>
+
+#include <asm/ldc.h>
+#include <asm/mdesc.h>
+
+struct vio_msg_tag {
+	u8			type;
+#define VIO_TYPE_CTRL		0x01
+#define VIO_TYPE_DATA		0x02
+#define VIO_TYPE_ERR		0x04
+
+	u8			stype;
+#define VIO_SUBTYPE_INFO	0x01
+#define VIO_SUBTYPE_ACK		0x02
+#define VIO_SUBTYPE_NACK	0x04
+
+	u16			stype_env;
+#define VIO_VER_INFO		0x0001
+#define VIO_ATTR_INFO		0x0002
+#define VIO_DRING_REG		0x0003
+#define VIO_DRING_UNREG		0x0004
+#define VIO_RDX			0x0005
+#define VIO_PKT_DATA		0x0040
+#define VIO_DESC_DATA		0x0041
+#define VIO_DRING_DATA		0x0042
+#define VNET_MCAST_INFO		0x0101
+
+	u32		sid;
+};
+
+struct vio_rdx {
+	struct vio_msg_tag	tag;
+	u64			resv[6];
+};
+
+struct vio_ver_info {
+	struct vio_msg_tag	tag;
+	u16			major;
+	u16			minor;
+	u8			dev_class;
+#define VDEV_NETWORK		0x01
+#define VDEV_NETWORK_SWITCH	0x02
+#define VDEV_DISK		0x03
+#define VDEV_DISK_SERVER	0x04
+
+	u8			resv1[3];
+	u64			resv2[5];
+};
+
+struct vio_dring_register {
+	struct vio_msg_tag	tag;
+	u64			dring_ident;
+	u32			num_descr;
+	u32			descr_size;
+	u16			options;
+#define VIO_TX_DRING		0x0001
+#define VIO_RX_DRING		0x0002
+	u16			resv;
+	u32			num_cookies;
+	struct ldc_trans_cookie	cookies[0];
+};
+
+struct vio_dring_unregister {
+	struct vio_msg_tag	tag;
+	u64			dring_ident;
+	u64			resv[5];
+};
+
+/* Data transfer modes */
+#define VIO_PKT_MODE		0x01 /* Packet based transfer	*/
+#define VIO_DESC_MODE		0x02 /* In-band descriptors	*/
+#define VIO_DRING_MODE		0x03 /* Descriptor rings	*/
+
+struct vio_dring_data {
+	struct vio_msg_tag	tag;
+	u64			seq;
+	u64			dring_ident;
+	u32			start_idx;
+	u32			end_idx;
+	u8			state;
+#define VIO_DRING_ACTIVE	0x01
+#define VIO_DRING_STOPPED	0x02
+
+	u8			__pad1;
+	u16			__pad2;
+	u32			__pad3;
+	u64			__par4[2];
+};
+
+struct vio_dring_hdr {
+	u8			state;
+#define VIO_DESC_FREE		0x01
+#define VIO_DESC_READY		0x02
+#define VIO_DESC_ACCEPTED	0x03
+#define VIO_DESC_DONE		0x04
+	u8			ack;
+#define VIO_ACK_ENABLE		0x01
+#define VIO_ACK_DISABLE		0x00
+
+	u16			__pad1;
+	u32			__pad2;
+};
+
+/* VIO disk specific structures and defines */
+struct vio_disk_attr_info {
+	struct vio_msg_tag	tag;
+	u8			xfer_mode;
+	u8			vdisk_type;
+#define VD_DISK_TYPE_SLICE	0x01 /* Slice in block device	*/
+#define VD_DISK_TYPE_DISK	0x02 /* Entire block device	*/
+	u16			resv1;
+	u32			vdisk_block_size;
+	u64			operations;
+	u64			vdisk_size;
+	u64			max_xfer_size;
+	u64			resv2[2];
+};
+
+struct vio_disk_desc {
+	struct vio_dring_hdr	hdr;
+	u64			req_id;
+	u8			operation;
+#define VD_OP_BREAD		0x01 /* Block read			*/
+#define VD_OP_BWRITE		0x02 /* Block write			*/
+#define VD_OP_FLUSH		0x03 /* Flush disk contents		*/
+#define VD_OP_GET_WCE		0x04 /* Get write-cache status		*/
+#define VD_OP_SET_WCE		0x05 /* Enable/disable write-cache	*/
+#define VD_OP_GET_VTOC		0x06 /* Get VTOC			*/
+#define VD_OP_SET_VTOC		0x07 /* Set VTOC			*/
+#define VD_OP_GET_DISKGEOM	0x08 /* Get disk geometry		*/
+#define VD_OP_SET_DISKGEOM	0x09 /* Set disk geometry		*/
+#define VD_OP_SCSICMD		0x0a /* SCSI control command		*/
+#define VD_OP_GET_DEVID		0x0b /* Get device ID			*/
+#define VD_OP_GET_EFI		0x0c /* Get EFI				*/
+#define VD_OP_SET_EFI		0x0d /* Set EFI				*/
+	u8			slice;
+	u16			resv1;
+	u32			status;
+	u64			offset;
+	u64			size;
+	u32			ncookies;
+	u32			resv2;
+	struct ldc_trans_cookie	cookies[0];
+};
+
+#define VIO_DISK_VNAME_LEN	8
+#define VIO_DISK_ALABEL_LEN	128
+#define VIO_DISK_NUM_PART	8
+
+struct vio_disk_vtoc {
+	u8			volume_name[VIO_DISK_VNAME_LEN];
+	u16			sector_size;
+	u16			num_partitions;
+	u8			ascii_label[VIO_DISK_ALABEL_LEN];
+	struct {
+		u16		id;
+		u16		perm_flags;
+		u32		resv;
+		u64		start_block;
+		u64		num_blocks;
+	} partitions[VIO_DISK_NUM_PART];
+};
+
+struct vio_disk_geom {
+	u16			num_cyl; /* Num data cylinders		*/
+	u16			alt_cyl; /* Num alternate cylinders	*/
+	u16			beg_cyl; /* Cyl off of fixed head area	*/
+	u16			num_hd;  /* Num heads			*/
+	u16			num_sec; /* Num sectors			*/
+	u16			ifact;   /* Interleave factor		*/
+	u16			apc;     /* Alts per cylinder (SCSI)	*/
+	u16			rpm;	 /* Revolutions per minute	*/
+	u16			phy_cyl; /* Num physical cylinders	*/
+	u16			wr_skip; /* Num sects to skip, writes	*/
+	u16			rd_skip; /* Num sects to skip, writes	*/
+};
+
+struct vio_disk_devid {
+	u16			resv;
+	u16			type;
+	u32			len;
+	char			id[0];
+};
+
+struct vio_disk_efi {
+	u64			lba;
+	u64			len;
+	char			data[0];
+};
+
+/* VIO net specific structures and defines */
+struct vio_net_attr_info {
+	struct vio_msg_tag	tag;
+	u8			xfer_mode;
+	u8			addr_type;
+#define VNET_ADDR_ETHERMAC	0x01
+	u16			ack_freq;
+	u32			resv1;
+	u64			addr;
+	u64			mtu;
+	u64			resv2[3];
+};
+
+#define VNET_NUM_MCAST		7
+
+struct vio_net_mcast_info {
+	struct vio_msg_tag	tag;
+	u8			set;
+	u8			count;
+	u8			mcast_addr[VNET_NUM_MCAST * 6];
+	u32			resv;
+};
+
+struct vio_net_desc {
+	struct vio_dring_hdr	hdr;
+	u32			size;
+	u32			ncookies;
+	struct ldc_trans_cookie	cookies[0];
+};
+
+#define VIO_MAX_RING_COOKIES	24
+
+struct vio_dring_state {
+	u64			ident;
+	void			*base;
+	u64			snd_nxt;
+	u64			rcv_nxt;
+	u32			entry_size;
+	u32			num_entries;
+	u32			prod;
+	u32			cons;
+	u32			pending;
+	int			ncookies;
+	struct ldc_trans_cookie	cookies[VIO_MAX_RING_COOKIES];
+};
+
+static inline void *vio_dring_cur(struct vio_dring_state *dr)
+{
+	return dr->base + (dr->entry_size * dr->prod);
+}
+
+static inline void *vio_dring_entry(struct vio_dring_state *dr,
+				    unsigned int index)
+{
+	return dr->base + (dr->entry_size * index);
+}
+
+static inline u32 vio_dring_avail(struct vio_dring_state *dr,
+				  unsigned int ring_size)
+{
+	BUILD_BUG_ON(!is_power_of_2(ring_size));
+
+	return (dr->pending -
+		((dr->prod - dr->cons) & (ring_size - 1)));
+}
+
+#define VIO_MAX_TYPE_LEN	32
+#define VIO_MAX_COMPAT_LEN	64
+
+struct vio_dev {
+	u64			mp;
+	struct device_node	*dp;
+
+	char			type[VIO_MAX_TYPE_LEN];
+	char			compat[VIO_MAX_COMPAT_LEN];
+	int			compat_len;
+
+	u64			dev_no;
+
+	unsigned long		channel_id;
+
+	unsigned int		tx_irq;
+	unsigned int		rx_irq;
+
+	struct device		dev;
+};
+
+struct vio_driver {
+	struct list_head		node;
+	const struct vio_device_id	*id_table;
+	int (*probe)(struct vio_dev *dev, const struct vio_device_id *id);
+	int (*remove)(struct vio_dev *dev);
+	void (*shutdown)(struct vio_dev *dev);
+	unsigned long			driver_data;
+	struct device_driver		driver;
+};
+
+struct vio_version {
+	u16		major;
+	u16		minor;
+};
+
+struct vio_driver_state;
+struct vio_driver_ops {
+	int	(*send_attr)(struct vio_driver_state *vio);
+	int	(*handle_attr)(struct vio_driver_state *vio, void *pkt);
+	void	(*handshake_complete)(struct vio_driver_state *vio);
+};
+
+struct vio_completion {
+	struct completion	com;
+	int			err;
+	int			waiting_for;
+};
+
+struct vio_driver_state {
+	/* Protects VIO handshake and, optionally, driver private state.  */
+	spinlock_t		lock;
+
+	struct ldc_channel	*lp;
+
+	u32			_peer_sid;
+	u32			_local_sid;
+	struct vio_dring_state	drings[2];
+#define VIO_DRIVER_TX_RING	0
+#define VIO_DRIVER_RX_RING	1
+
+	u8			hs_state;
+#define VIO_HS_INVALID		0x00
+#define VIO_HS_GOTVERS		0x01
+#define VIO_HS_GOT_ATTR		0x04
+#define VIO_HS_SENT_DREG	0x08
+#define VIO_HS_SENT_RDX		0x10
+#define VIO_HS_GOT_RDX_ACK	0x20
+#define VIO_HS_GOT_RDX		0x40
+#define VIO_HS_SENT_RDX_ACK	0x80
+#define VIO_HS_COMPLETE		(VIO_HS_GOT_RDX_ACK | VIO_HS_SENT_RDX_ACK)
+
+	u8			dev_class;
+
+	u8			dr_state;
+#define VIO_DR_STATE_TXREG	0x01
+#define VIO_DR_STATE_RXREG	0x02
+#define VIO_DR_STATE_TXREQ	0x10
+#define VIO_DR_STATE_RXREQ	0x20
+
+	u8			debug;
+#define VIO_DEBUG_HS		0x01
+#define VIO_DEBUG_DATA		0x02
+
+	void			*desc_buf;
+	unsigned int		desc_buf_len;
+
+	struct vio_completion	*cmp;
+
+	struct vio_dev		*vdev;
+
+	struct timer_list	timer;
+
+	struct vio_version	ver;
+
+	struct vio_version	*ver_table;
+	int			ver_table_entries;
+
+	char			*name;
+
+	struct vio_driver_ops	*ops;
+};
+
+#define viodbg(TYPE, f, a...) \
+do {	if (vio->debug & VIO_DEBUG_##TYPE) \
+		printk(KERN_INFO "vio: ID[%lu] " f, \
+		       vio->vdev->channel_id, ## a); \
+} while (0)
+
+extern int vio_register_driver(struct vio_driver *drv);
+extern void vio_unregister_driver(struct vio_driver *drv);
+
+static inline struct vio_driver *to_vio_driver(struct device_driver *drv)
+{
+	return container_of(drv, struct vio_driver, driver);
+}
+
+static inline struct vio_dev *to_vio_dev(struct device *dev)
+{
+	return container_of(dev, struct vio_dev, dev);
+}
+
+extern int vio_ldc_send(struct vio_driver_state *vio, void *data, int len);
+extern void vio_link_state_change(struct vio_driver_state *vio, int event);
+extern void vio_conn_reset(struct vio_driver_state *vio);
+extern int vio_control_pkt_engine(struct vio_driver_state *vio, void *pkt);
+extern int vio_validate_sid(struct vio_driver_state *vio,
+			    struct vio_msg_tag *tp);
+extern u32 vio_send_sid(struct vio_driver_state *vio);
+extern int vio_ldc_alloc(struct vio_driver_state *vio,
+			 struct ldc_channel_config *base_cfg, void *event_arg);
+extern void vio_ldc_free(struct vio_driver_state *vio);
+extern int vio_driver_init(struct vio_driver_state *vio, struct vio_dev *vdev,
+			   u8 dev_class, struct vio_version *ver_table,
+			   int ver_table_size, struct vio_driver_ops *ops,
+			   char *name);
+
+extern void vio_port_up(struct vio_driver_state *vio);
+
+#endif /* _SPARC64_VIO_H */
diff --git a/include/asm-sparc/visasm.h b/include/asm-sparc/visasm.h
new file mode 100644
index 0000000..de797b9
--- /dev/null
+++ b/include/asm-sparc/visasm.h
@@ -0,0 +1,62 @@
+#ifndef _SPARC64_VISASM_H
+#define _SPARC64_VISASM_H
+
+/* visasm.h:  FPU saving macros for VIS routines
+ *
+ * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
+ */
+
+#include <asm/pstate.h>
+#include <asm/ptrace.h>
+
+/* Clobbers %o5, %g1, %g2, %g3, %g7, %icc, %xcc */
+
+#define VISEntry					\
+	rd		%fprs, %o5;			\
+	andcc		%o5, (FPRS_FEF|FPRS_DU), %g0;	\
+	be,pt		%icc, 297f;			\
+	 sethi		%hi(297f), %g7;			\
+	sethi		%hi(VISenter), %g1;		\
+	jmpl		%g1 + %lo(VISenter), %g0;	\
+	 or		%g7, %lo(297f), %g7;		\
+297:	wr		%g0, FPRS_FEF, %fprs;		\
+
+#define VISExit						\
+	wr		%g0, 0, %fprs;
+
+/* Clobbers %o5, %g1, %g2, %g3, %g7, %icc, %xcc.
+ * Must preserve %o5 between VISEntryHalf and VISExitHalf */
+
+#define VISEntryHalf					\
+	rd		%fprs, %o5;			\
+	andcc		%o5, FPRS_FEF, %g0;		\
+	be,pt		%icc, 297f;			\
+	 sethi		%hi(298f), %g7;			\
+	sethi		%hi(VISenterhalf), %g1;		\
+	jmpl		%g1 + %lo(VISenterhalf), %g0;	\
+	 or		%g7, %lo(298f), %g7;		\
+	clr		%o5;				\
+297:	wr		%o5, FPRS_FEF, %fprs;		\
+298:
+
+#define VISExitHalf					\
+	wr		%o5, 0, %fprs;
+
+#ifndef __ASSEMBLY__
+static inline void save_and_clear_fpu(void) {
+	__asm__ __volatile__ (
+"		rd %%fprs, %%o5\n"
+"		andcc %%o5, %0, %%g0\n"
+"		be,pt %%icc, 299f\n"
+"		 sethi %%hi(298f), %%g7\n"
+"		sethi %%hi(VISenter), %%g1\n"
+"		jmpl %%g1 + %%lo(VISenter), %%g0\n"
+"		 or %%g7, %%lo(298f), %%g7\n"
+"	298:	wr %%g0, 0, %%fprs\n"
+"	299:\n"
+"		" : : "i" (FPRS_FEF|FPRS_DU) :
+		"o5", "g1", "g2", "g3", "g7", "cc");
+}
+#endif
+
+#endif /* _SPARC64_ASI_H */
diff --git a/include/asm-sparc/watchdog.h b/include/asm-sparc/watchdog.h
new file mode 100644
index 0000000..5baf2d3
--- /dev/null
+++ b/include/asm-sparc/watchdog.h
@@ -0,0 +1,31 @@
+/*
+ *
+ * watchdog - Driver interface for the hardware watchdog timers
+ * present on Sun Microsystems boardsets
+ *
+ * Copyright (c) 2000 Eric Brower <ebrower@usa.net>
+ *
+ */
+
+#ifndef _SPARC64_WATCHDOG_H
+#define _SPARC64_WATCHDOG_H
+
+#include <linux/watchdog.h>
+
+/* Solaris compatibility ioctls--
+ * Ref. <linux/watchdog.h> for standard linux watchdog ioctls
+ */
+#define WIOCSTART _IO (WATCHDOG_IOCTL_BASE, 10)		/* Start Timer		*/
+#define WIOCSTOP  _IO (WATCHDOG_IOCTL_BASE, 11)		/* Stop Timer		*/
+#define WIOCGSTAT _IOR(WATCHDOG_IOCTL_BASE, 12, int)/* Get Timer Status	*/
+
+/* Status flags from WIOCGSTAT ioctl
+ */
+#define WD_FREERUN	0x01	/* timer is running, interrupts disabled	*/
+#define WD_EXPIRED	0x02	/* timer has expired						*/
+#define WD_RUNNING	0x04	/* timer is running, interrupts enabled		*/
+#define WD_STOPPED	0x08	/* timer has not been started				*/
+#define WD_SERVICED 0x10	/* timer interrupt was serviced				*/
+
+#endif /* ifndef _SPARC64_WATCHDOG_H */
+
diff --git a/include/asm-sparc/xor.h b/include/asm-sparc/xor.h
index f34b2cfa..35089a8 100644
--- a/include/asm-sparc/xor.h
+++ b/include/asm-sparc/xor.h
@@ -1,269 +1,8 @@
-/*
- * include/asm-sparc/xor.h
- *
- * Optimized RAID-5 checksumming functions for 32-bit Sparc.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * (for example /usr/src/linux/COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*
- * High speed xor_block operation for RAID4/5 utilizing the
- * ldd/std SPARC instructions.
- *
- * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz)
- */
-
-static void
-sparc_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
-{
-	int lines = bytes / (sizeof (long)) / 8;
-
-	do {
-		__asm__ __volatile__(
-		  "ldd [%0 + 0x00], %%g2\n\t"
-		  "ldd [%0 + 0x08], %%g4\n\t"
-		  "ldd [%0 + 0x10], %%o0\n\t"
-		  "ldd [%0 + 0x18], %%o2\n\t"
-		  "ldd [%1 + 0x00], %%o4\n\t"
-		  "ldd [%1 + 0x08], %%l0\n\t"
-		  "ldd [%1 + 0x10], %%l2\n\t"
-		  "ldd [%1 + 0x18], %%l4\n\t"
-		  "xor %%g2, %%o4, %%g2\n\t"
-		  "xor %%g3, %%o5, %%g3\n\t"
-		  "xor %%g4, %%l0, %%g4\n\t"
-		  "xor %%g5, %%l1, %%g5\n\t"
-		  "xor %%o0, %%l2, %%o0\n\t"
-		  "xor %%o1, %%l3, %%o1\n\t"
-		  "xor %%o2, %%l4, %%o2\n\t"
-		  "xor %%o3, %%l5, %%o3\n\t"
-		  "std %%g2, [%0 + 0x00]\n\t"
-		  "std %%g4, [%0 + 0x08]\n\t"
-		  "std %%o0, [%0 + 0x10]\n\t"
-		  "std %%o2, [%0 + 0x18]\n"
-		:
-		: "r" (p1), "r" (p2)
-		: "g2", "g3", "g4", "g5",
-		  "o0", "o1", "o2", "o3", "o4", "o5",
-		  "l0", "l1", "l2", "l3", "l4", "l5");
-		p1 += 8;
-		p2 += 8;
-	} while (--lines > 0);
-}
-
-static void
-sparc_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
-	unsigned long *p3)
-{
-	int lines = bytes / (sizeof (long)) / 8;
-
-	do {
-		__asm__ __volatile__(
-		  "ldd [%0 + 0x00], %%g2\n\t"
-		  "ldd [%0 + 0x08], %%g4\n\t"
-		  "ldd [%0 + 0x10], %%o0\n\t"
-		  "ldd [%0 + 0x18], %%o2\n\t"
-		  "ldd [%1 + 0x00], %%o4\n\t"
-		  "ldd [%1 + 0x08], %%l0\n\t"
-		  "ldd [%1 + 0x10], %%l2\n\t"
-		  "ldd [%1 + 0x18], %%l4\n\t"
-		  "xor %%g2, %%o4, %%g2\n\t"
-		  "xor %%g3, %%o5, %%g3\n\t"
-		  "ldd [%2 + 0x00], %%o4\n\t"
-		  "xor %%g4, %%l0, %%g4\n\t"
-		  "xor %%g5, %%l1, %%g5\n\t"
-		  "ldd [%2 + 0x08], %%l0\n\t"
-		  "xor %%o0, %%l2, %%o0\n\t"
-		  "xor %%o1, %%l3, %%o1\n\t"
-		  "ldd [%2 + 0x10], %%l2\n\t"
-		  "xor %%o2, %%l4, %%o2\n\t"
-		  "xor %%o3, %%l5, %%o3\n\t"
-		  "ldd [%2 + 0x18], %%l4\n\t"
-		  "xor %%g2, %%o4, %%g2\n\t"
-		  "xor %%g3, %%o5, %%g3\n\t"
-		  "xor %%g4, %%l0, %%g4\n\t"
-		  "xor %%g5, %%l1, %%g5\n\t"
-		  "xor %%o0, %%l2, %%o0\n\t"
-		  "xor %%o1, %%l3, %%o1\n\t"
-		  "xor %%o2, %%l4, %%o2\n\t"
-		  "xor %%o3, %%l5, %%o3\n\t"
-		  "std %%g2, [%0 + 0x00]\n\t"
-		  "std %%g4, [%0 + 0x08]\n\t"
-		  "std %%o0, [%0 + 0x10]\n\t"
-		  "std %%o2, [%0 + 0x18]\n"
-		:
-		: "r" (p1), "r" (p2), "r" (p3)
-		: "g2", "g3", "g4", "g5",
-		  "o0", "o1", "o2", "o3", "o4", "o5",
-		  "l0", "l1", "l2", "l3", "l4", "l5");
-		p1 += 8;
-		p2 += 8;
-		p3 += 8;
-	} while (--lines > 0);
-}
-
-static void
-sparc_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
-	unsigned long *p3, unsigned long *p4)
-{
-	int lines = bytes / (sizeof (long)) / 8;
-
-	do {
-		__asm__ __volatile__(
-		  "ldd [%0 + 0x00], %%g2\n\t"
-		  "ldd [%0 + 0x08], %%g4\n\t"
-		  "ldd [%0 + 0x10], %%o0\n\t"
-		  "ldd [%0 + 0x18], %%o2\n\t"
-		  "ldd [%1 + 0x00], %%o4\n\t"
-		  "ldd [%1 + 0x08], %%l0\n\t"
-		  "ldd [%1 + 0x10], %%l2\n\t"
-		  "ldd [%1 + 0x18], %%l4\n\t"
-		  "xor %%g2, %%o4, %%g2\n\t"
-		  "xor %%g3, %%o5, %%g3\n\t"
-		  "ldd [%2 + 0x00], %%o4\n\t"
-		  "xor %%g4, %%l0, %%g4\n\t"
-		  "xor %%g5, %%l1, %%g5\n\t"
-		  "ldd [%2 + 0x08], %%l0\n\t"
-		  "xor %%o0, %%l2, %%o0\n\t"
-		  "xor %%o1, %%l3, %%o1\n\t"
-		  "ldd [%2 + 0x10], %%l2\n\t"
-		  "xor %%o2, %%l4, %%o2\n\t"
-		  "xor %%o3, %%l5, %%o3\n\t"
-		  "ldd [%2 + 0x18], %%l4\n\t"
-		  "xor %%g2, %%o4, %%g2\n\t"
-		  "xor %%g3, %%o5, %%g3\n\t"
-		  "ldd [%3 + 0x00], %%o4\n\t"
-		  "xor %%g4, %%l0, %%g4\n\t"
-		  "xor %%g5, %%l1, %%g5\n\t"
-		  "ldd [%3 + 0x08], %%l0\n\t"
-		  "xor %%o0, %%l2, %%o0\n\t"
-		  "xor %%o1, %%l3, %%o1\n\t"
-		  "ldd [%3 + 0x10], %%l2\n\t"
-		  "xor %%o2, %%l4, %%o2\n\t"
-		  "xor %%o3, %%l5, %%o3\n\t"
-		  "ldd [%3 + 0x18], %%l4\n\t"
-		  "xor %%g2, %%o4, %%g2\n\t"
-		  "xor %%g3, %%o5, %%g3\n\t"
-		  "xor %%g4, %%l0, %%g4\n\t"
-		  "xor %%g5, %%l1, %%g5\n\t"
-		  "xor %%o0, %%l2, %%o0\n\t"
-		  "xor %%o1, %%l3, %%o1\n\t"
-		  "xor %%o2, %%l4, %%o2\n\t"
-		  "xor %%o3, %%l5, %%o3\n\t"
-		  "std %%g2, [%0 + 0x00]\n\t"
-		  "std %%g4, [%0 + 0x08]\n\t"
-		  "std %%o0, [%0 + 0x10]\n\t"
-		  "std %%o2, [%0 + 0x18]\n"
-		:
-		: "r" (p1), "r" (p2), "r" (p3), "r" (p4)
-		: "g2", "g3", "g4", "g5",
-		  "o0", "o1", "o2", "o3", "o4", "o5",
-		  "l0", "l1", "l2", "l3", "l4", "l5");
-		p1 += 8;
-		p2 += 8;
-		p3 += 8;
-		p4 += 8;
-	} while (--lines > 0);
-}
-
-static void
-sparc_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
-	unsigned long *p3, unsigned long *p4, unsigned long *p5)
-{
-	int lines = bytes / (sizeof (long)) / 8;
-
-	do {
-		__asm__ __volatile__(
-		  "ldd [%0 + 0x00], %%g2\n\t"
-		  "ldd [%0 + 0x08], %%g4\n\t"
-		  "ldd [%0 + 0x10], %%o0\n\t"
-		  "ldd [%0 + 0x18], %%o2\n\t"
-		  "ldd [%1 + 0x00], %%o4\n\t"
-		  "ldd [%1 + 0x08], %%l0\n\t"
-		  "ldd [%1 + 0x10], %%l2\n\t"
-		  "ldd [%1 + 0x18], %%l4\n\t"
-		  "xor %%g2, %%o4, %%g2\n\t"
-		  "xor %%g3, %%o5, %%g3\n\t"
-		  "ldd [%2 + 0x00], %%o4\n\t"
-		  "xor %%g4, %%l0, %%g4\n\t"
-		  "xor %%g5, %%l1, %%g5\n\t"
-		  "ldd [%2 + 0x08], %%l0\n\t"
-		  "xor %%o0, %%l2, %%o0\n\t"
-		  "xor %%o1, %%l3, %%o1\n\t"
-		  "ldd [%2 + 0x10], %%l2\n\t"
-		  "xor %%o2, %%l4, %%o2\n\t"
-		  "xor %%o3, %%l5, %%o3\n\t"
-		  "ldd [%2 + 0x18], %%l4\n\t"
-		  "xor %%g2, %%o4, %%g2\n\t"
-		  "xor %%g3, %%o5, %%g3\n\t"
-		  "ldd [%3 + 0x00], %%o4\n\t"
-		  "xor %%g4, %%l0, %%g4\n\t"
-		  "xor %%g5, %%l1, %%g5\n\t"
-		  "ldd [%3 + 0x08], %%l0\n\t"
-		  "xor %%o0, %%l2, %%o0\n\t"
-		  "xor %%o1, %%l3, %%o1\n\t"
-		  "ldd [%3 + 0x10], %%l2\n\t"
-		  "xor %%o2, %%l4, %%o2\n\t"
-		  "xor %%o3, %%l5, %%o3\n\t"
-		  "ldd [%3 + 0x18], %%l4\n\t"
-		  "xor %%g2, %%o4, %%g2\n\t"
-		  "xor %%g3, %%o5, %%g3\n\t"
-		  "ldd [%4 + 0x00], %%o4\n\t"
-		  "xor %%g4, %%l0, %%g4\n\t"
-		  "xor %%g5, %%l1, %%g5\n\t"
-		  "ldd [%4 + 0x08], %%l0\n\t"
-		  "xor %%o0, %%l2, %%o0\n\t"
-		  "xor %%o1, %%l3, %%o1\n\t"
-		  "ldd [%4 + 0x10], %%l2\n\t"
-		  "xor %%o2, %%l4, %%o2\n\t"
-		  "xor %%o3, %%l5, %%o3\n\t"
-		  "ldd [%4 + 0x18], %%l4\n\t"
-		  "xor %%g2, %%o4, %%g2\n\t"
-		  "xor %%g3, %%o5, %%g3\n\t"
-		  "xor %%g4, %%l0, %%g4\n\t"
-		  "xor %%g5, %%l1, %%g5\n\t"
-		  "xor %%o0, %%l2, %%o0\n\t"
-		  "xor %%o1, %%l3, %%o1\n\t"
-		  "xor %%o2, %%l4, %%o2\n\t"
-		  "xor %%o3, %%l5, %%o3\n\t"
-		  "std %%g2, [%0 + 0x00]\n\t"
-		  "std %%g4, [%0 + 0x08]\n\t"
-		  "std %%o0, [%0 + 0x10]\n\t"
-		  "std %%o2, [%0 + 0x18]\n"
-		:
-		: "r" (p1), "r" (p2), "r" (p3), "r" (p4), "r" (p5)
-		: "g2", "g3", "g4", "g5",
-		  "o0", "o1", "o2", "o3", "o4", "o5",
-		  "l0", "l1", "l2", "l3", "l4", "l5");
-		p1 += 8;
-		p2 += 8;
-		p3 += 8;
-		p4 += 8;
-		p5 += 8;
-	} while (--lines > 0);
-}
-
-static struct xor_block_template xor_block_SPARC = {
-	.name	= "SPARC",
-	.do_2	= sparc_2,
-	.do_3	= sparc_3,
-	.do_4	= sparc_4,
-	.do_5	= sparc_5,
-};
-
-/* For grins, also test the generic routines.  */
-#include <asm-generic/xor.h>
-
-#undef XOR_TRY_TEMPLATES
-#define XOR_TRY_TEMPLATES				\
-	do {						\
-		xor_speed(&xor_block_8regs);		\
-		xor_speed(&xor_block_32regs);		\
-		xor_speed(&xor_block_SPARC);		\
-	} while (0)
+#ifndef ___ASM_SPARC_XOR_H
+#define ___ASM_SPARC_XOR_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm-sparc/xor_64.h>
+#else
+#include <asm-sparc/xor_32.h>
+#endif
+#endif
diff --git a/include/asm-sparc/xor_32.h b/include/asm-sparc/xor_32.h
new file mode 100644
index 0000000..f34b2cfa
--- /dev/null
+++ b/include/asm-sparc/xor_32.h
@@ -0,0 +1,269 @@
+/*
+ * include/asm-sparc/xor.h
+ *
+ * Optimized RAID-5 checksumming functions for 32-bit Sparc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * (for example /usr/src/linux/COPYING); if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * High speed xor_block operation for RAID4/5 utilizing the
+ * ldd/std SPARC instructions.
+ *
+ * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz)
+ */
+
+static void
+sparc_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
+{
+	int lines = bytes / (sizeof (long)) / 8;
+
+	do {
+		__asm__ __volatile__(
+		  "ldd [%0 + 0x00], %%g2\n\t"
+		  "ldd [%0 + 0x08], %%g4\n\t"
+		  "ldd [%0 + 0x10], %%o0\n\t"
+		  "ldd [%0 + 0x18], %%o2\n\t"
+		  "ldd [%1 + 0x00], %%o4\n\t"
+		  "ldd [%1 + 0x08], %%l0\n\t"
+		  "ldd [%1 + 0x10], %%l2\n\t"
+		  "ldd [%1 + 0x18], %%l4\n\t"
+		  "xor %%g2, %%o4, %%g2\n\t"
+		  "xor %%g3, %%o5, %%g3\n\t"
+		  "xor %%g4, %%l0, %%g4\n\t"
+		  "xor %%g5, %%l1, %%g5\n\t"
+		  "xor %%o0, %%l2, %%o0\n\t"
+		  "xor %%o1, %%l3, %%o1\n\t"
+		  "xor %%o2, %%l4, %%o2\n\t"
+		  "xor %%o3, %%l5, %%o3\n\t"
+		  "std %%g2, [%0 + 0x00]\n\t"
+		  "std %%g4, [%0 + 0x08]\n\t"
+		  "std %%o0, [%0 + 0x10]\n\t"
+		  "std %%o2, [%0 + 0x18]\n"
+		:
+		: "r" (p1), "r" (p2)
+		: "g2", "g3", "g4", "g5",
+		  "o0", "o1", "o2", "o3", "o4", "o5",
+		  "l0", "l1", "l2", "l3", "l4", "l5");
+		p1 += 8;
+		p2 += 8;
+	} while (--lines > 0);
+}
+
+static void
+sparc_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+	unsigned long *p3)
+{
+	int lines = bytes / (sizeof (long)) / 8;
+
+	do {
+		__asm__ __volatile__(
+		  "ldd [%0 + 0x00], %%g2\n\t"
+		  "ldd [%0 + 0x08], %%g4\n\t"
+		  "ldd [%0 + 0x10], %%o0\n\t"
+		  "ldd [%0 + 0x18], %%o2\n\t"
+		  "ldd [%1 + 0x00], %%o4\n\t"
+		  "ldd [%1 + 0x08], %%l0\n\t"
+		  "ldd [%1 + 0x10], %%l2\n\t"
+		  "ldd [%1 + 0x18], %%l4\n\t"
+		  "xor %%g2, %%o4, %%g2\n\t"
+		  "xor %%g3, %%o5, %%g3\n\t"
+		  "ldd [%2 + 0x00], %%o4\n\t"
+		  "xor %%g4, %%l0, %%g4\n\t"
+		  "xor %%g5, %%l1, %%g5\n\t"
+		  "ldd [%2 + 0x08], %%l0\n\t"
+		  "xor %%o0, %%l2, %%o0\n\t"
+		  "xor %%o1, %%l3, %%o1\n\t"
+		  "ldd [%2 + 0x10], %%l2\n\t"
+		  "xor %%o2, %%l4, %%o2\n\t"
+		  "xor %%o3, %%l5, %%o3\n\t"
+		  "ldd [%2 + 0x18], %%l4\n\t"
+		  "xor %%g2, %%o4, %%g2\n\t"
+		  "xor %%g3, %%o5, %%g3\n\t"
+		  "xor %%g4, %%l0, %%g4\n\t"
+		  "xor %%g5, %%l1, %%g5\n\t"
+		  "xor %%o0, %%l2, %%o0\n\t"
+		  "xor %%o1, %%l3, %%o1\n\t"
+		  "xor %%o2, %%l4, %%o2\n\t"
+		  "xor %%o3, %%l5, %%o3\n\t"
+		  "std %%g2, [%0 + 0x00]\n\t"
+		  "std %%g4, [%0 + 0x08]\n\t"
+		  "std %%o0, [%0 + 0x10]\n\t"
+		  "std %%o2, [%0 + 0x18]\n"
+		:
+		: "r" (p1), "r" (p2), "r" (p3)
+		: "g2", "g3", "g4", "g5",
+		  "o0", "o1", "o2", "o3", "o4", "o5",
+		  "l0", "l1", "l2", "l3", "l4", "l5");
+		p1 += 8;
+		p2 += 8;
+		p3 += 8;
+	} while (--lines > 0);
+}
+
+static void
+sparc_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+	unsigned long *p3, unsigned long *p4)
+{
+	int lines = bytes / (sizeof (long)) / 8;
+
+	do {
+		__asm__ __volatile__(
+		  "ldd [%0 + 0x00], %%g2\n\t"
+		  "ldd [%0 + 0x08], %%g4\n\t"
+		  "ldd [%0 + 0x10], %%o0\n\t"
+		  "ldd [%0 + 0x18], %%o2\n\t"
+		  "ldd [%1 + 0x00], %%o4\n\t"
+		  "ldd [%1 + 0x08], %%l0\n\t"
+		  "ldd [%1 + 0x10], %%l2\n\t"
+		  "ldd [%1 + 0x18], %%l4\n\t"
+		  "xor %%g2, %%o4, %%g2\n\t"
+		  "xor %%g3, %%o5, %%g3\n\t"
+		  "ldd [%2 + 0x00], %%o4\n\t"
+		  "xor %%g4, %%l0, %%g4\n\t"
+		  "xor %%g5, %%l1, %%g5\n\t"
+		  "ldd [%2 + 0x08], %%l0\n\t"
+		  "xor %%o0, %%l2, %%o0\n\t"
+		  "xor %%o1, %%l3, %%o1\n\t"
+		  "ldd [%2 + 0x10], %%l2\n\t"
+		  "xor %%o2, %%l4, %%o2\n\t"
+		  "xor %%o3, %%l5, %%o3\n\t"
+		  "ldd [%2 + 0x18], %%l4\n\t"
+		  "xor %%g2, %%o4, %%g2\n\t"
+		  "xor %%g3, %%o5, %%g3\n\t"
+		  "ldd [%3 + 0x00], %%o4\n\t"
+		  "xor %%g4, %%l0, %%g4\n\t"
+		  "xor %%g5, %%l1, %%g5\n\t"
+		  "ldd [%3 + 0x08], %%l0\n\t"
+		  "xor %%o0, %%l2, %%o0\n\t"
+		  "xor %%o1, %%l3, %%o1\n\t"
+		  "ldd [%3 + 0x10], %%l2\n\t"
+		  "xor %%o2, %%l4, %%o2\n\t"
+		  "xor %%o3, %%l5, %%o3\n\t"
+		  "ldd [%3 + 0x18], %%l4\n\t"
+		  "xor %%g2, %%o4, %%g2\n\t"
+		  "xor %%g3, %%o5, %%g3\n\t"
+		  "xor %%g4, %%l0, %%g4\n\t"
+		  "xor %%g5, %%l1, %%g5\n\t"
+		  "xor %%o0, %%l2, %%o0\n\t"
+		  "xor %%o1, %%l3, %%o1\n\t"
+		  "xor %%o2, %%l4, %%o2\n\t"
+		  "xor %%o3, %%l5, %%o3\n\t"
+		  "std %%g2, [%0 + 0x00]\n\t"
+		  "std %%g4, [%0 + 0x08]\n\t"
+		  "std %%o0, [%0 + 0x10]\n\t"
+		  "std %%o2, [%0 + 0x18]\n"
+		:
+		: "r" (p1), "r" (p2), "r" (p3), "r" (p4)
+		: "g2", "g3", "g4", "g5",
+		  "o0", "o1", "o2", "o3", "o4", "o5",
+		  "l0", "l1", "l2", "l3", "l4", "l5");
+		p1 += 8;
+		p2 += 8;
+		p3 += 8;
+		p4 += 8;
+	} while (--lines > 0);
+}
+
+static void
+sparc_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+	unsigned long *p3, unsigned long *p4, unsigned long *p5)
+{
+	int lines = bytes / (sizeof (long)) / 8;
+
+	do {
+		__asm__ __volatile__(
+		  "ldd [%0 + 0x00], %%g2\n\t"
+		  "ldd [%0 + 0x08], %%g4\n\t"
+		  "ldd [%0 + 0x10], %%o0\n\t"
+		  "ldd [%0 + 0x18], %%o2\n\t"
+		  "ldd [%1 + 0x00], %%o4\n\t"
+		  "ldd [%1 + 0x08], %%l0\n\t"
+		  "ldd [%1 + 0x10], %%l2\n\t"
+		  "ldd [%1 + 0x18], %%l4\n\t"
+		  "xor %%g2, %%o4, %%g2\n\t"
+		  "xor %%g3, %%o5, %%g3\n\t"
+		  "ldd [%2 + 0x00], %%o4\n\t"
+		  "xor %%g4, %%l0, %%g4\n\t"
+		  "xor %%g5, %%l1, %%g5\n\t"
+		  "ldd [%2 + 0x08], %%l0\n\t"
+		  "xor %%o0, %%l2, %%o0\n\t"
+		  "xor %%o1, %%l3, %%o1\n\t"
+		  "ldd [%2 + 0x10], %%l2\n\t"
+		  "xor %%o2, %%l4, %%o2\n\t"
+		  "xor %%o3, %%l5, %%o3\n\t"
+		  "ldd [%2 + 0x18], %%l4\n\t"
+		  "xor %%g2, %%o4, %%g2\n\t"
+		  "xor %%g3, %%o5, %%g3\n\t"
+		  "ldd [%3 + 0x00], %%o4\n\t"
+		  "xor %%g4, %%l0, %%g4\n\t"
+		  "xor %%g5, %%l1, %%g5\n\t"
+		  "ldd [%3 + 0x08], %%l0\n\t"
+		  "xor %%o0, %%l2, %%o0\n\t"
+		  "xor %%o1, %%l3, %%o1\n\t"
+		  "ldd [%3 + 0x10], %%l2\n\t"
+		  "xor %%o2, %%l4, %%o2\n\t"
+		  "xor %%o3, %%l5, %%o3\n\t"
+		  "ldd [%3 + 0x18], %%l4\n\t"
+		  "xor %%g2, %%o4, %%g2\n\t"
+		  "xor %%g3, %%o5, %%g3\n\t"
+		  "ldd [%4 + 0x00], %%o4\n\t"
+		  "xor %%g4, %%l0, %%g4\n\t"
+		  "xor %%g5, %%l1, %%g5\n\t"
+		  "ldd [%4 + 0x08], %%l0\n\t"
+		  "xor %%o0, %%l2, %%o0\n\t"
+		  "xor %%o1, %%l3, %%o1\n\t"
+		  "ldd [%4 + 0x10], %%l2\n\t"
+		  "xor %%o2, %%l4, %%o2\n\t"
+		  "xor %%o3, %%l5, %%o3\n\t"
+		  "ldd [%4 + 0x18], %%l4\n\t"
+		  "xor %%g2, %%o4, %%g2\n\t"
+		  "xor %%g3, %%o5, %%g3\n\t"
+		  "xor %%g4, %%l0, %%g4\n\t"
+		  "xor %%g5, %%l1, %%g5\n\t"
+		  "xor %%o0, %%l2, %%o0\n\t"
+		  "xor %%o1, %%l3, %%o1\n\t"
+		  "xor %%o2, %%l4, %%o2\n\t"
+		  "xor %%o3, %%l5, %%o3\n\t"
+		  "std %%g2, [%0 + 0x00]\n\t"
+		  "std %%g4, [%0 + 0x08]\n\t"
+		  "std %%o0, [%0 + 0x10]\n\t"
+		  "std %%o2, [%0 + 0x18]\n"
+		:
+		: "r" (p1), "r" (p2), "r" (p3), "r" (p4), "r" (p5)
+		: "g2", "g3", "g4", "g5",
+		  "o0", "o1", "o2", "o3", "o4", "o5",
+		  "l0", "l1", "l2", "l3", "l4", "l5");
+		p1 += 8;
+		p2 += 8;
+		p3 += 8;
+		p4 += 8;
+		p5 += 8;
+	} while (--lines > 0);
+}
+
+static struct xor_block_template xor_block_SPARC = {
+	.name	= "SPARC",
+	.do_2	= sparc_2,
+	.do_3	= sparc_3,
+	.do_4	= sparc_4,
+	.do_5	= sparc_5,
+};
+
+/* For grins, also test the generic routines.  */
+#include <asm-generic/xor.h>
+
+#undef XOR_TRY_TEMPLATES
+#define XOR_TRY_TEMPLATES				\
+	do {						\
+		xor_speed(&xor_block_8regs);		\
+		xor_speed(&xor_block_32regs);		\
+		xor_speed(&xor_block_SPARC);		\
+	} while (0)
diff --git a/include/asm-sparc/xor_64.h b/include/asm-sparc/xor_64.h
new file mode 100644
index 0000000..a023388
--- /dev/null
+++ b/include/asm-sparc/xor_64.h
@@ -0,0 +1,70 @@
+/*
+ * include/asm-sparc64/xor.h
+ *
+ * High speed xor_block operation for RAID4/5 utilizing the
+ * UltraSparc Visual Instruction Set and Niagara block-init
+ * twin-load instructions.
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
+ * Copyright (C) 2006 David S. Miller <davem@davemloft.net>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * (for example /usr/src/linux/COPYING); if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <asm/spitfire.h>
+
+extern void xor_vis_2(unsigned long, unsigned long *, unsigned long *);
+extern void xor_vis_3(unsigned long, unsigned long *, unsigned long *,
+		      unsigned long *);
+extern void xor_vis_4(unsigned long, unsigned long *, unsigned long *,
+		      unsigned long *, unsigned long *);
+extern void xor_vis_5(unsigned long, unsigned long *, unsigned long *,
+		      unsigned long *, unsigned long *, unsigned long *);
+
+/* XXX Ugh, write cheetah versions... -DaveM */
+
+static struct xor_block_template xor_block_VIS = {
+        .name	= "VIS",
+        .do_2	= xor_vis_2,
+        .do_3	= xor_vis_3,
+        .do_4	= xor_vis_4,
+        .do_5	= xor_vis_5,
+};
+
+extern void xor_niagara_2(unsigned long, unsigned long *, unsigned long *);
+extern void xor_niagara_3(unsigned long, unsigned long *, unsigned long *,
+			  unsigned long *);
+extern void xor_niagara_4(unsigned long, unsigned long *, unsigned long *,
+			  unsigned long *, unsigned long *);
+extern void xor_niagara_5(unsigned long, unsigned long *, unsigned long *,
+			  unsigned long *, unsigned long *, unsigned long *);
+
+static struct xor_block_template xor_block_niagara = {
+        .name	= "Niagara",
+        .do_2	= xor_niagara_2,
+        .do_3	= xor_niagara_3,
+        .do_4	= xor_niagara_4,
+        .do_5	= xor_niagara_5,
+};
+
+#undef XOR_TRY_TEMPLATES
+#define XOR_TRY_TEMPLATES				\
+	do {						\
+		xor_speed(&xor_block_VIS);		\
+		xor_speed(&xor_block_niagara);		\
+	} while (0)
+
+/* For VIS for everything except Niagara.  */
+#define XOR_SELECT_TEMPLATE(FASTEST) \
+	((tlb_type == hypervisor && \
+	  (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 || \
+	   sun4v_chip_type == SUN4V_CHIP_NIAGARA2)) ? \
+	 &xor_block_niagara : \
+	 &xor_block_VIS)
diff --git a/include/asm-sparc64/Kbuild b/include/asm-sparc64/Kbuild
index dce1cf9..6cdaf9d 100644
--- a/include/asm-sparc64/Kbuild
+++ b/include/asm-sparc64/Kbuild
@@ -1,23 +1 @@
-include include/asm-generic/Kbuild.asm
-
-ALTARCH := sparc
-ARCHDEF := defined __sparc__ && defined __arch64__
-ALTARCHDEF := defined __sparc__ && !defined __arch64__
-
-header-y += apb.h
-header-y += asi.h
-header-y += bbc.h
-header-y += bpp.h
-header-y += display7seg.h
-header-y += envctrl.h
-header-y += openprom.h
-header-y += openpromio.h
-header-y += psrcompat.h
-header-y += pstate.h
-header-y += reg.h
-header-y += uctx.h
-header-y += utrap.h
-header-y += watchdog.h
-
-unifdef-y += fbio.h
-unifdef-y += perfctr.h
+# dummy file to avoid breaking make headers_install
diff --git a/include/asm-sparc64/agp.h b/include/asm-sparc64/agp.h
index e9fcf0e..eb8d4b3 100644
--- a/include/asm-sparc64/agp.h
+++ b/include/asm-sparc64/agp.h
@@ -1,20 +1 @@
-#ifndef AGP_H
-#define AGP_H 1
-
-/* dummy for now */
-
-#define map_page_into_agp(page) 
-#define unmap_page_from_agp(page) 
-#define flush_agp_cache() mb()
-
-/* Convert a physical address to an address suitable for the GART. */
-#define phys_to_gart(x) (x)
-#define gart_to_phys(x) (x)
-
-/* GATT allocation. Returns/accepts GATT kernel virtual address. */
-#define alloc_gatt_pages(order)		\
-	((char *)__get_free_pages(GFP_KERNEL, (order)))
-#define free_gatt_pages(table, order)	\
-	free_pages((unsigned long)(table), (order))
-
-#endif
+#include <asm-sparc/agp.h>
diff --git a/include/asm-sparc64/apb.h b/include/asm-sparc64/apb.h
index 8f3b57d..5e236ca 100644
--- a/include/asm-sparc64/apb.h
+++ b/include/asm-sparc64/apb.h
@@ -1,36 +1 @@
-/*
- * apb.h: Advanced PCI Bridge Configuration Registers and Bits
- *
- * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
- */
-
-#ifndef _SPARC64_APB_H
-#define _SPARC64_APB_H
-
-#define APB_TICK_REGISTER			0xb0
-#define APB_INT_ACK				0xb8
-#define APB_PRIMARY_MASTER_RETRY_LIMIT		0xc0
-#define APB_DMA_ASFR				0xc8
-#define APB_DMA_AFAR				0xd0
-#define APB_PIO_TARGET_RETRY_LIMIT		0xd8
-#define APB_PIO_TARGET_LATENCY_TIMER		0xd9
-#define APB_DMA_TARGET_RETRY_LIMIT		0xda
-#define APB_DMA_TARGET_LATENCY_TIMER		0xdb
-#define APB_SECONDARY_MASTER_RETRY_LIMIT	0xdc
-#define APB_SECONDARY_CONTROL			0xdd
-#define APB_IO_ADDRESS_MAP			0xde
-#define APB_MEM_ADDRESS_MAP			0xdf
-
-#define APB_PCI_CONTROL_LOW			0xe0
-#  define APB_PCI_CTL_LOW_ARB_PARK			(1 << 21)
-#  define APB_PCI_CTL_LOW_ERRINT_EN			(1 << 8)
-
-#define APB_PCI_CONTROL_HIGH			0xe4
-#  define APB_PCI_CTL_HIGH_SERR				(1 << 2)
-#  define APB_PCI_CTL_HIGH_ARBITER_EN			(1 << 0)
-
-#define APB_PIO_ASFR				0xe8
-#define APB_PIO_AFAR				0xf0
-#define APB_DIAG_REGISTER			0xf8
-
-#endif /* !(_SPARC64_APB_H) */
+#include <asm-sparc/apb.h>
diff --git a/include/asm-sparc64/asi.h b/include/asm-sparc64/asi.h
index bc57c40..9b7110c 100644
--- a/include/asm-sparc64/asi.h
+++ b/include/asm-sparc64/asi.h
@@ -1,160 +1 @@
-#ifndef _SPARC64_ASI_H
-#define _SPARC64_ASI_H
-
-/* asi.h:  Address Space Identifier values for the V9.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-/* V9 Architecture mandary ASIs. */
-#define ASI_N			0x04 /* Nucleus				*/
-#define ASI_NL			0x0c /* Nucleus, little endian		*/
-#define ASI_AIUP		0x10 /* Primary, user			*/
-#define ASI_AIUS		0x11 /* Secondary, user			*/
-#define ASI_AIUPL		0x18 /* Primary, user, little endian	*/
-#define ASI_AIUSL		0x19 /* Secondary, user, little endian	*/
-#define ASI_P			0x80 /* Primary, implicit		*/
-#define ASI_S			0x81 /* Secondary, implicit		*/
-#define ASI_PNF			0x82 /* Primary, no fault		*/
-#define ASI_SNF			0x83 /* Secondary, no fault		*/
-#define ASI_PL			0x88 /* Primary, implicit, l-endian	*/
-#define ASI_SL			0x89 /* Secondary, implicit, l-endian	*/
-#define ASI_PNFL		0x8a /* Primary, no fault, l-endian	*/
-#define ASI_SNFL		0x8b /* Secondary, no fault, l-endian	*/
-
-/* SpitFire and later extended ASIs.  The "(III)" marker designates
- * UltraSparc-III and later specific ASIs.  The "(CMT)" marker designates
- * Chip Multi Threading specific ASIs.  "(NG)" designates Niagara specific
- * ASIs, "(4V)" designates SUN4V specific ASIs.
- */
-#define ASI_PHYS_USE_EC		0x14 /* PADDR, E-cachable		*/
-#define ASI_PHYS_BYPASS_EC_E	0x15 /* PADDR, E-bit			*/
-#define ASI_BLK_AIUP_4V		0x16 /* (4V) Prim, user, block ld/st	*/
-#define ASI_BLK_AIUS_4V		0x17 /* (4V) Sec, user, block ld/st	*/
-#define ASI_PHYS_USE_EC_L	0x1c /* PADDR, E-cachable, little endian*/
-#define ASI_PHYS_BYPASS_EC_E_L	0x1d /* PADDR, E-bit, little endian	*/
-#define ASI_BLK_AIUP_L_4V	0x1e /* (4V) Prim, user, block, l-endian*/
-#define ASI_BLK_AIUS_L_4V	0x1f /* (4V) Sec, user, block, l-endian	*/
-#define ASI_SCRATCHPAD		0x20 /* (4V) Scratch Pad Registers	*/
-#define ASI_MMU			0x21 /* (4V) MMU Context Registers	*/
-#define ASI_BLK_INIT_QUAD_LDD_AIUS 0x23 /* (NG) init-store, twin load,
-					 * secondary, user
-					 */
-#define ASI_NUCLEUS_QUAD_LDD	0x24 /* Cachable, qword load		*/
-#define ASI_QUEUE		0x25 /* (4V) Interrupt Queue Registers	*/
-#define ASI_QUAD_LDD_PHYS_4V	0x26 /* (4V) Physical, qword load	*/
-#define ASI_NUCLEUS_QUAD_LDD_L	0x2c /* Cachable, qword load, l-endian 	*/
-#define ASI_QUAD_LDD_PHYS_L_4V	0x2e /* (4V) Phys, qword load, l-endian	*/
-#define ASI_PCACHE_DATA_STATUS	0x30 /* (III) PCache data stat RAM diag	*/
-#define ASI_PCACHE_DATA		0x31 /* (III) PCache data RAM diag	*/
-#define ASI_PCACHE_TAG		0x32 /* (III) PCache tag RAM diag	*/
-#define ASI_PCACHE_SNOOP_TAG	0x33 /* (III) PCache snoop tag RAM diag	*/
-#define ASI_QUAD_LDD_PHYS	0x34 /* (III+) PADDR, qword load	*/
-#define ASI_WCACHE_VALID_BITS	0x38 /* (III) WCache Valid Bits diag	*/
-#define ASI_WCACHE_DATA		0x39 /* (III) WCache data RAM diag	*/
-#define ASI_WCACHE_TAG		0x3a /* (III) WCache tag RAM diag	*/
-#define ASI_WCACHE_SNOOP_TAG	0x3b /* (III) WCache snoop tag RAM diag	*/
-#define ASI_QUAD_LDD_PHYS_L	0x3c /* (III+) PADDR, qw-load, l-endian	*/
-#define ASI_SRAM_FAST_INIT	0x40 /* (III+) Fast SRAM init		*/
-#define ASI_CORE_AVAILABLE	0x41 /* (CMT) LP Available		*/
-#define ASI_CORE_ENABLE_STAT	0x41 /* (CMT) LP Enable Status		*/
-#define ASI_CORE_ENABLE		0x41 /* (CMT) LP Enable RW		*/
-#define ASI_XIR_STEERING	0x41 /* (CMT) XIR Steering RW		*/
-#define ASI_CORE_RUNNING_RW	0x41 /* (CMT) LP Running RW		*/
-#define ASI_CORE_RUNNING_W1S	0x41 /* (CMT) LP Running Write-One Set	*/
-#define ASI_CORE_RUNNING_W1C	0x41 /* (CMT) LP Running Write-One Clr	*/
-#define ASI_CORE_RUNNING_STAT	0x41 /* (CMT) LP Running Status		*/
-#define ASI_CMT_ERROR_STEERING	0x41 /* (CMT) Error Steering RW		*/
-#define ASI_DCACHE_INVALIDATE	0x42 /* (III) DCache Invalidate diag	*/
-#define ASI_DCACHE_UTAG		0x43 /* (III) DCache uTag diag		*/
-#define ASI_DCACHE_SNOOP_TAG	0x44 /* (III) DCache snoop tag RAM diag	*/
-#define ASI_LSU_CONTROL		0x45 /* Load-store control unit		*/
-#define ASI_DCU_CONTROL_REG	0x45 /* (III) DCache Unit Control reg	*/
-#define ASI_DCACHE_DATA		0x46 /* DCache data-ram diag access	*/
-#define ASI_DCACHE_TAG		0x47 /* Dcache tag/valid ram diag access*/
-#define ASI_INTR_DISPATCH_STAT	0x48 /* IRQ vector dispatch status	*/
-#define ASI_INTR_RECEIVE	0x49 /* IRQ vector receive status	*/
-#define ASI_UPA_CONFIG		0x4a /* UPA config space		*/
-#define ASI_JBUS_CONFIG		0x4a /* (IIIi) JBUS Config Register	*/
-#define ASI_SAFARI_CONFIG	0x4a /* (III) Safari Config Register	*/
-#define ASI_SAFARI_ADDRESS	0x4a /* (III) Safari Address Register	*/
-#define ASI_ESTATE_ERROR_EN	0x4b /* E-cache error enable space	*/
-#define ASI_AFSR		0x4c /* Async fault status register	*/
-#define ASI_AFAR		0x4d /* Async fault address register	*/
-#define ASI_EC_TAG_DATA		0x4e /* E-cache tag/valid ram diag acc	*/
-#define ASI_IMMU		0x50 /* Insn-MMU main register space	*/
-#define ASI_IMMU_TSB_8KB_PTR	0x51 /* Insn-MMU 8KB TSB pointer reg	*/
-#define ASI_IMMU_TSB_64KB_PTR	0x52 /* Insn-MMU 64KB TSB pointer reg	*/
-#define ASI_ITLB_DATA_IN	0x54 /* Insn-MMU TLB data in reg	*/
-#define ASI_ITLB_DATA_ACCESS	0x55 /* Insn-MMU TLB data access reg	*/
-#define ASI_ITLB_TAG_READ	0x56 /* Insn-MMU TLB tag read reg	*/
-#define ASI_IMMU_DEMAP		0x57 /* Insn-MMU TLB demap		*/
-#define ASI_DMMU		0x58 /* Data-MMU main register space	*/
-#define ASI_DMMU_TSB_8KB_PTR	0x59 /* Data-MMU 8KB TSB pointer reg	*/
-#define ASI_DMMU_TSB_64KB_PTR	0x5a /* Data-MMU 16KB TSB pointer reg	*/
-#define ASI_DMMU_TSB_DIRECT_PTR	0x5b /* Data-MMU TSB direct pointer reg	*/
-#define ASI_DTLB_DATA_IN	0x5c /* Data-MMU TLB data in reg	*/
-#define ASI_DTLB_DATA_ACCESS	0x5d /* Data-MMU TLB data access reg	*/
-#define ASI_DTLB_TAG_READ	0x5e /* Data-MMU TLB tag read reg	*/
-#define ASI_DMMU_DEMAP		0x5f /* Data-MMU TLB demap		*/
-#define ASI_IIU_INST_TRAP	0x60 /* (III) Instruction Breakpoint	*/
-#define ASI_INTR_ID		0x63 /* (CMT) Interrupt ID register	*/
-#define ASI_CORE_ID		0x63 /* (CMT) LP ID register		*/
-#define ASI_CESR_ID		0x63 /* (CMT) CESR ID register		*/
-#define ASI_IC_INSTR		0x66 /* Insn cache instrucion ram diag	*/
-#define ASI_IC_TAG		0x67 /* Insn cache tag/valid ram diag 	*/
-#define ASI_IC_STAG		0x68 /* (III) Insn cache snoop tag ram	*/
-#define ASI_IC_PRE_DECODE	0x6e /* Insn cache pre-decode ram diag	*/
-#define ASI_IC_NEXT_FIELD	0x6f /* Insn cache next-field ram diag	*/
-#define ASI_BRPRED_ARRAY	0x6f /* (III) Branch Prediction RAM diag*/
-#define ASI_BLK_AIUP		0x70 /* Primary, user, block load/store	*/
-#define ASI_BLK_AIUS		0x71 /* Secondary, user, block ld/st	*/
-#define ASI_MCU_CTRL_REG	0x72 /* (III) Memory controller regs	*/
-#define ASI_EC_DATA		0x74 /* (III) E-cache data staging reg	*/
-#define ASI_EC_CTRL		0x75 /* (III) E-cache control reg	*/
-#define ASI_EC_W		0x76 /* E-cache diag write access	*/
-#define ASI_UDB_ERROR_W		0x77 /* External UDB error regs W	*/
-#define ASI_UDB_CONTROL_W	0x77 /* External UDB control regs W	*/
-#define ASI_INTR_W		0x77 /* IRQ vector dispatch write	*/
-#define ASI_INTR_DATAN_W	0x77 /* (III) Out irq vector data reg N	*/
-#define ASI_INTR_DISPATCH_W	0x77 /* (III) Interrupt vector dispatch	*/
-#define ASI_BLK_AIUPL		0x78 /* Primary, user, little, blk ld/st*/
-#define ASI_BLK_AIUSL		0x79 /* Secondary, user, little, blk ld/st*/
-#define ASI_EC_R		0x7e /* E-cache diag read access	*/
-#define ASI_UDBH_ERROR_R	0x7f /* External UDB error regs rd hi	*/
-#define ASI_UDBL_ERROR_R	0x7f /* External UDB error regs rd low	*/
-#define ASI_UDBH_CONTROL_R	0x7f /* External UDB control regs rd hi	*/
-#define ASI_UDBL_CONTROL_R	0x7f /* External UDB control regs rd low*/
-#define ASI_INTR_R		0x7f /* IRQ vector dispatch read	*/
-#define ASI_INTR_DATAN_R	0x7f /* (III) In irq vector data reg N	*/
-#define ASI_PST8_P		0xc0 /* Primary, 8 8-bit, partial	*/
-#define ASI_PST8_S		0xc1 /* Secondary, 8 8-bit, partial	*/
-#define ASI_PST16_P		0xc2 /* Primary, 4 16-bit, partial	*/
-#define ASI_PST16_S		0xc3 /* Secondary, 4 16-bit, partial	*/
-#define ASI_PST32_P		0xc4 /* Primary, 2 32-bit, partial	*/
-#define ASI_PST32_S		0xc5 /* Secondary, 2 32-bit, partial	*/
-#define ASI_PST8_PL		0xc8 /* Primary, 8 8-bit, partial, L	*/
-#define ASI_PST8_SL		0xc9 /* Secondary, 8 8-bit, partial, L	*/
-#define ASI_PST16_PL		0xca /* Primary, 4 16-bit, partial, L	*/
-#define ASI_PST16_SL		0xcb /* Secondary, 4 16-bit, partial, L	*/
-#define ASI_PST32_PL		0xcc /* Primary, 2 32-bit, partial, L	*/
-#define ASI_PST32_SL		0xcd /* Secondary, 2 32-bit, partial, L	*/
-#define ASI_FL8_P		0xd0 /* Primary, 1 8-bit, fpu ld/st	*/
-#define ASI_FL8_S		0xd1 /* Secondary, 1 8-bit, fpu ld/st	*/
-#define ASI_FL16_P		0xd2 /* Primary, 1 16-bit, fpu ld/st	*/
-#define ASI_FL16_S		0xd3 /* Secondary, 1 16-bit, fpu ld/st	*/
-#define ASI_FL8_PL		0xd8 /* Primary, 1 8-bit, fpu ld/st, L	*/
-#define ASI_FL8_SL		0xd9 /* Secondary, 1 8-bit, fpu ld/st, L*/
-#define ASI_FL16_PL		0xda /* Primary, 1 16-bit, fpu ld/st, L	*/
-#define ASI_FL16_SL		0xdb /* Secondary, 1 16-bit, fpu ld/st,L*/
-#define ASI_BLK_COMMIT_P	0xe0 /* Primary, blk store commit	*/
-#define ASI_BLK_COMMIT_S	0xe1 /* Secondary, blk store commit	*/
-#define ASI_BLK_INIT_QUAD_LDD_P	0xe2 /* (NG) init-store, twin load,
-				      * primary, implicit
-				      */
-#define ASI_BLK_P		0xf0 /* Primary, blk ld/st		*/
-#define ASI_BLK_S		0xf1 /* Secondary, blk ld/st		*/
-#define ASI_BLK_PL		0xf8 /* Primary, blk ld/st, little	*/
-#define ASI_BLK_SL		0xf9 /* Secondary, blk ld/st, little	*/
-
-#endif /* _SPARC64_ASI_H */
+#include <asm-sparc/asi.h>
diff --git a/include/asm-sparc64/atomic.h b/include/asm-sparc64/atomic.h
index 2c71ec4a..f512682 100644
--- a/include/asm-sparc64/atomic.h
+++ b/include/asm-sparc64/atomic.h
@@ -1,128 +1 @@
-/* atomic.h: Thankfully the V9 is at least reasonable for this
- *           stuff.
- *
- * Copyright (C) 1996, 1997, 2000 David S. Miller (davem@redhat.com)
- */
-
-#ifndef __ARCH_SPARC64_ATOMIC__
-#define __ARCH_SPARC64_ATOMIC__
-
-#include <linux/types.h>
-#include <asm/system.h>
-
-typedef struct { volatile int counter; } atomic_t;
-typedef struct { volatile __s64 counter; } atomic64_t;
-
-#define ATOMIC_INIT(i)		{ (i) }
-#define ATOMIC64_INIT(i)	{ (i) }
-
-#define atomic_read(v)		((v)->counter)
-#define atomic64_read(v)	((v)->counter)
-
-#define atomic_set(v, i)	(((v)->counter) = i)
-#define atomic64_set(v, i)	(((v)->counter) = i)
-
-extern void atomic_add(int, atomic_t *);
-extern void atomic64_add(int, atomic64_t *);
-extern void atomic_sub(int, atomic_t *);
-extern void atomic64_sub(int, atomic64_t *);
-
-extern int atomic_add_ret(int, atomic_t *);
-extern int atomic64_add_ret(int, atomic64_t *);
-extern int atomic_sub_ret(int, atomic_t *);
-extern int atomic64_sub_ret(int, atomic64_t *);
-
-#define atomic_dec_return(v) atomic_sub_ret(1, v)
-#define atomic64_dec_return(v) atomic64_sub_ret(1, v)
-
-#define atomic_inc_return(v) atomic_add_ret(1, v)
-#define atomic64_inc_return(v) atomic64_add_ret(1, v)
-
-#define atomic_sub_return(i, v) atomic_sub_ret(i, v)
-#define atomic64_sub_return(i, v) atomic64_sub_ret(i, v)
-
-#define atomic_add_return(i, v) atomic_add_ret(i, v)
-#define atomic64_add_return(i, v) atomic64_add_ret(i, v)
-
-/*
- * atomic_inc_and_test - increment and test
- * @v: pointer of type atomic_t
- *
- * Atomically increments @v by 1
- * and returns true if the result is zero, or false for all
- * other cases.
- */
-#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
-#define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0)
-
-#define atomic_sub_and_test(i, v) (atomic_sub_ret(i, v) == 0)
-#define atomic64_sub_and_test(i, v) (atomic64_sub_ret(i, v) == 0)
-
-#define atomic_dec_and_test(v) (atomic_sub_ret(1, v) == 0)
-#define atomic64_dec_and_test(v) (atomic64_sub_ret(1, v) == 0)
-
-#define atomic_inc(v) atomic_add(1, v)
-#define atomic64_inc(v) atomic64_add(1, v)
-
-#define atomic_dec(v) atomic_sub(1, v)
-#define atomic64_dec(v) atomic64_sub(1, v)
-
-#define atomic_add_negative(i, v) (atomic_add_ret(i, v) < 0)
-#define atomic64_add_negative(i, v) (atomic64_add_ret(i, v) < 0)
-
-#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
-{
-	int c, old;
-	c = atomic_read(v);
-	for (;;) {
-		if (unlikely(c == (u)))
-			break;
-		old = atomic_cmpxchg((v), c, c + (a));
-		if (likely(old == c))
-			break;
-		c = old;
-	}
-	return c != (u);
-}
-
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
-
-#define atomic64_cmpxchg(v, o, n) \
-	((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
-#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
-
-static inline int atomic64_add_unless(atomic64_t *v, long a, long u)
-{
-	long c, old;
-	c = atomic64_read(v);
-	for (;;) {
-		if (unlikely(c == (u)))
-			break;
-		old = atomic64_cmpxchg((v), c, c + (a));
-		if (likely(old == c))
-			break;
-		c = old;
-	}
-	return c != (u);
-}
-
-#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
-
-/* Atomic operations are already serializing */
-#ifdef CONFIG_SMP
-#define smp_mb__before_atomic_dec()	membar_storeload_loadload();
-#define smp_mb__after_atomic_dec()	membar_storeload_storestore();
-#define smp_mb__before_atomic_inc()	membar_storeload_loadload();
-#define smp_mb__after_atomic_inc()	membar_storeload_storestore();
-#else
-#define smp_mb__before_atomic_dec()	barrier()
-#define smp_mb__after_atomic_dec()	barrier()
-#define smp_mb__before_atomic_inc()	barrier()
-#define smp_mb__after_atomic_inc()	barrier()
-#endif
-
-#include <asm-generic/atomic.h>
-#endif /* !(__ARCH_SPARC64_ATOMIC__) */
+#include <asm-sparc/atomic.h>
diff --git a/include/asm-sparc64/auxio.h b/include/asm-sparc64/auxio.h
index c410049..46c9042 100644
--- a/include/asm-sparc64/auxio.h
+++ b/include/asm-sparc64/auxio.h
@@ -1,100 +1 @@
-/*
- * auxio.h:  Definitions and code for the Auxiliary I/O registers.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- *
- * Refactoring for unified NCR/PCIO support 2002 Eric Brower (ebrower@usa.net)
- */
-#ifndef _SPARC64_AUXIO_H
-#define _SPARC64_AUXIO_H
-
-/* AUXIO implementations:
- * sbus-based NCR89C105 "Slavio"
- *	LED/Floppy (AUX1) register
- *	Power (AUX2) register
- *
- * ebus-based auxio on PCIO 
- *	LED Auxio Register
- *	Power Auxio Register
- *
- * Register definitions from NCR _NCR89C105 Chip Specification_
- * 
- * SLAVIO AUX1 @ 0x1900000
- * -------------------------------------------------
- * | (R) | (R) |  D  | (R) |  E  |  M  |  T  |  L  |
- * -------------------------------------------------
- * (R) - bit 7:6,4 are reserved and should be masked in s/w
- *  D  - Floppy Density Sense (1=high density) R/O
- *  E  - Link Test Enable, directly reflected on AT&T 7213 LTE pin
- *  M  - Monitor/Mouse Mux, directly reflected on MON_MSE_MUX pin
- *  T  - Terminal Count: sends TC pulse to 82077 floppy controller
- *  L  - System LED on front panel (0=off, 1=on) 
- */
-#define AUXIO_AUX1_MASK		0xc0 /* Mask bits 		*/
-#define AUXIO_AUX1_FDENS	0x20 /* Floppy Density Sense	*/
-#define AUXIO_AUX1_LTE 		0x08 /* Link Test Enable 	*/
-#define AUXIO_AUX1_MMUX		0x04 /* Monitor/Mouse Mux	*/
-#define AUXIO_AUX1_FTCNT	0x02 /* Terminal Count, 	*/
-#define AUXIO_AUX1_LED		0x01 /* System LED		*/
-
-/* SLAVIO AUX2 @ 0x1910000
- * -------------------------------------------------
- * | (R) | (R) |  D  | (R) | (R) | (R) |  C  |  F  |
- * -------------------------------------------------
- * (R) - bits 7:6,4:2 are reserved and should be masked in s/w
- *  D  - Power Failure Detect (1=power fail)
- *  C  - Clear Power Failure Detect Int (1=clear)
- *  F  - Power Off (1=power off)
- */
-#define AUXIO_AUX2_MASK		0xdc /* Mask Bits		*/
-#define AUXIO_AUX2_PFAILDET	0x20 /* Power Fail Detect	*/
-#define AUXIO_AUX2_PFAILCLR 	0x02 /* Clear Pwr Fail Det Intr	*/
-#define AUXIO_AUX2_PWR_OFF	0x01 /* Power Off		*/
-
-/* Register definitions from Sun Microsystems _PCIO_ p/n 802-7837
- *
- * PCIO LED Auxio @ 0x726000
- * -------------------------------------------------
- * |             31:1 Unused                 | LED |
- * -------------------------------------------------
- * Bits 31:1 unused
- * LED - System LED on front panel (0=off, 1=on)
- */
-#define AUXIO_PCIO_LED		0x01 /* System LED 		*/ 
-
-/* PCIO Power Auxio @ 0x724000
- * -------------------------------------------------
- * |             31:2 Unused           | CPO | SPO |
- * -------------------------------------------------
- * Bits 31:2 unused
- * CPO - Courtesy Power Off (1=off)
- * SPO - System Power Off   (1=off)
- */
-#define AUXIO_PCIO_CPWR_OFF	0x02 /* Courtesy Power Off	*/
-#define AUXIO_PCIO_SPWR_OFF	0x01 /* System Power Off	*/
-
-#ifndef __ASSEMBLY__
-
-extern void __iomem *auxio_register;
-
-#define AUXIO_LTE_ON	1
-#define AUXIO_LTE_OFF	0
-
-/* auxio_set_lte - Set Link Test Enable (TPE Link Detect)
- *
- * on - AUXIO_LTE_ON or AUXIO_LTE_OFF
- */
-extern void auxio_set_lte(int on);
-
-#define AUXIO_LED_ON	1
-#define AUXIO_LED_OFF	0
-
-/* auxio_set_led - Set system front panel LED 
- *
- * on - AUXIO_LED_ON or AUXIO_LED_OFF
- */
-extern void auxio_set_led(int on);
-
-#endif /* ifndef __ASSEMBLY__ */ 
-
-#endif /* !(_SPARC64_AUXIO_H) */
+#include <asm-sparc/auxio.h>
diff --git a/include/asm-sparc64/backoff.h b/include/asm-sparc64/backoff.h
index fa1fdf6..8ee26d9 100644
--- a/include/asm-sparc64/backoff.h
+++ b/include/asm-sparc64/backoff.h
@@ -1,31 +1 @@
-#ifndef _SPARC64_BACKOFF_H
-#define _SPARC64_BACKOFF_H
-
-#define BACKOFF_LIMIT	(4 * 1024)
-
-#ifdef CONFIG_SMP
-
-#define BACKOFF_SETUP(reg)	\
-	mov	1, reg
-
-#define BACKOFF_SPIN(reg, tmp, label)	\
-	mov	reg, tmp; \
-88:	brnz,pt	tmp, 88b; \
-	 sub	tmp, 1, tmp; \
-	set	BACKOFF_LIMIT, tmp; \
-	cmp	reg, tmp; \
-	bg,pn	%xcc, label; \
-	 nop; \
-	ba,pt	%xcc, label; \
-	 sllx	reg, 1, reg;
-
-#else
-
-#define BACKOFF_SETUP(reg)
-#define BACKOFF_SPIN(reg, tmp, label) \
-	ba,pt	%xcc, label; \
-	 nop;
-
-#endif
-
-#endif /* _SPARC64_BACKOFF_H */
+#include <asm-sparc/backoff.h>
diff --git a/include/asm-sparc64/bbc.h b/include/asm-sparc64/bbc.h
index 423a858..06e8b63 100644
--- a/include/asm-sparc64/bbc.h
+++ b/include/asm-sparc64/bbc.h
@@ -1,225 +1 @@
-/*
- * bbc.h: Defines for BootBus Controller found on UltraSPARC-III
- *        systems.
- *
- * Copyright (C) 2000 David S. Miller (davem@redhat.com)
- */
-
-#ifndef _SPARC64_BBC_H
-#define _SPARC64_BBC_H
-
-/* Register sizes are indicated by "B" (Byte, 1-byte),
- * "H" (Half-word, 2 bytes), "W" (Word, 4 bytes) or
- * "Q" (Quad, 8 bytes) inside brackets.
- */
-
-#define BBC_AID		0x00	/* [B] Agent ID			*/
-#define BBC_DEVP	0x01	/* [B] Device Present		*/
-#define BBC_ARB		0x02	/* [B] Arbitration		*/
-#define BBC_QUIESCE	0x03	/* [B] Quiesce			*/
-#define BBC_WDACTION	0x04	/* [B] Watchdog Action		*/
-#define BBC_SPG		0x06	/* [B] Soft POR Gen		*/
-#define BBC_SXG		0x07	/* [B] Soft XIR Gen		*/
-#define BBC_PSRC	0x08	/* [W] POR Source		*/
-#define BBC_XSRC	0x0c	/* [B] XIR Source		*/
-#define BBC_CSC		0x0d	/* [B] Clock Synthesizers Control*/
-#define BBC_ES_CTRL	0x0e	/* [H] Energy Star Control	*/
-#define BBC_ES_ACT	0x10	/* [W] E* Assert Change Time	*/
-#define BBC_ES_DACT	0x14	/* [B] E* De-Assert Change Time	*/
-#define BBC_ES_DABT	0x15	/* [B] E* De-Assert Bypass Time	*/
-#define BBC_ES_ABT	0x16	/* [H] E* Assert Bypass Time	*/
-#define BBC_ES_PST	0x18	/* [W] E* PLL Settle Time	*/
-#define BBC_ES_FSL	0x1c	/* [W] E* Frequency Switch Latency*/
-#define BBC_EBUST	0x20	/* [Q] EBUS Timing		*/
-#define BBC_JTAG_CMD	0x28	/* [W] JTAG+ Command		*/
-#define BBC_JTAG_CTRL	0x2c	/* [B] JTAG+ Control		*/
-#define BBC_I2C_SEL	0x2d	/* [B] I2C Selection		*/
-#define BBC_I2C_0_S1	0x2e	/* [B] I2C ctrlr-0 reg S1	*/
-#define BBC_I2C_0_S0	0x2f	/* [B] I2C ctrlr-0 regs S0,S0',S2,S3*/
-#define BBC_I2C_1_S1	0x30	/* [B] I2C ctrlr-1 reg S1	*/
-#define BBC_I2C_1_S0	0x31	/* [B] I2C ctrlr-1 regs S0,S0',S2,S3*/
-#define BBC_KBD_BEEP	0x32	/* [B] Keyboard Beep		*/
-#define BBC_KBD_BCNT	0x34	/* [W] Keyboard Beep Counter	*/
-
-#define BBC_REGS_SIZE	0x40
-
-/* There is a 2K scratch ram area at offset 0x80000 but I doubt
- * we will use it for anything.
- */
-
-/* Agent ID register.  This register shows the Safari Agent ID
- * for the processors.  The value returned depends upon which
- * cpu is reading the register.
- */
-#define BBC_AID_ID	0x07	/* Safari ID		*/
-#define BBC_AID_RESV	0xf8	/* Reserved		*/
-
-/* Device Present register.  One can determine which cpus are actually
- * present in the machine by interrogating this register.
- */
-#define BBC_DEVP_CPU0	0x01	/* Processor 0 present	*/
-#define BBC_DEVP_CPU1	0x02	/* Processor 1 present	*/
-#define BBC_DEVP_CPU2	0x04	/* Processor 2 present	*/
-#define BBC_DEVP_CPU3	0x08	/* Processor 3 present	*/
-#define BBC_DEVP_RESV	0xf0	/* Reserved		*/
-
-/* Arbitration register.  This register is used to block access to
- * the BBC from a particular cpu.
- */
-#define BBC_ARB_CPU0	0x01	/* Enable cpu 0 BBC arbitratrion */
-#define BBC_ARB_CPU1	0x02	/* Enable cpu 1 BBC arbitratrion */
-#define BBC_ARB_CPU2	0x04	/* Enable cpu 2 BBC arbitratrion */
-#define BBC_ARB_CPU3	0x08	/* Enable cpu 3 BBC arbitratrion */
-#define BBC_ARB_RESV	0xf0	/* Reserved			 */
-
-/* Quiesce register.  Bus and BBC segments for cpus can be disabled
- * with this register, ie. for hot plugging.
- */
-#define BBC_QUIESCE_S02	0x01	/* Quiesce Safari segment for cpu 0 and 2 */
-#define BBC_QUIESCE_S13	0x02	/* Quiesce Safari segment for cpu 1 and 3 */
-#define BBC_QUIESCE_B02	0x04	/* Quiesce BBC segment for cpu 0 and 2    */
-#define BBC_QUIESCE_B13	0x08	/* Quiesce BBC segment for cpu 1 and 3    */
-#define BBC_QUIESCE_FD0 0x10	/* Disable Fatal_Error[0] reporting	  */
-#define BBC_QUIESCE_FD1 0x20	/* Disable Fatal_Error[1] reporting	  */
-#define BBC_QUIESCE_FD2 0x40	/* Disable Fatal_Error[2] reporting	  */
-#define BBC_QUIESCE_FD3 0x80	/* Disable Fatal_Error[3] reporting	  */
-
-/* Watchdog Action register.  When the watchdog device timer expires
- * a line is enabled to the BBC.  The action BBC takes when this line
- * is asserted can be controlled by this regiser.
- */
-#define BBC_WDACTION_RST  0x01	/* When set, watchdog causes system reset.
-				 * When clear, BBC ignores watchdog signal.
-				 */
-#define BBC_WDACTION_RESV 0xfe	/* Reserved */
-
-/* Soft_POR_GEN register.  The POR (Power On Reset) signal may be asserted
- * for specific processors or all processors via this register.
- */
-#define BBC_SPG_CPU0	0x01 /* Assert POR for processor 0	*/
-#define BBC_SPG_CPU1	0x02 /* Assert POR for processor 1	*/
-#define BBC_SPG_CPU2	0x04 /* Assert POR for processor 2	*/
-#define BBC_SPG_CPU3	0x08 /* Assert POR for processor 3	*/
-#define BBC_SPG_CPUALL	0x10 /* Reset all processors and reset
-			      * the entire system.
-			      */
-#define BBC_SPG_RESV	0xe0 /* Reserved			*/
-
-/* Soft_XIR_GEN register.  The XIR (eXternally Initiated Reset) signal
- * may be asserted to specific processors via this register.
- */
-#define BBC_SXG_CPU0	0x01 /* Assert XIR for processor 0	*/
-#define BBC_SXG_CPU1	0x02 /* Assert XIR for processor 1	*/
-#define BBC_SXG_CPU2	0x04 /* Assert XIR for processor 2	*/
-#define BBC_SXG_CPU3	0x08 /* Assert XIR for processor 3	*/
-#define BBC_SXG_RESV	0xf0 /* Reserved			*/
-
-/* POR Source register.  One may identify the cause of the most recent
- * reset by reading this register.
- */
-#define BBC_PSRC_SPG0	0x0001 /* CPU 0 reset via BBC_SPG register	*/
-#define BBC_PSRC_SPG1	0x0002 /* CPU 1 reset via BBC_SPG register	*/
-#define BBC_PSRC_SPG2	0x0004 /* CPU 2 reset via BBC_SPG register	*/
-#define BBC_PSRC_SPG3	0x0008 /* CPU 3 reset via BBC_SPG register	*/
-#define BBC_PSRC_SPGSYS	0x0010 /* System reset via BBC_SPG register	*/
-#define BBC_PSRC_JTAG	0x0020 /* System reset via JTAG+		*/
-#define BBC_PSRC_BUTTON	0x0040 /* System reset via push-button dongle	*/
-#define BBC_PSRC_PWRUP	0x0080 /* System reset via power-up		*/
-#define BBC_PSRC_FE0	0x0100 /* CPU 0 reported Fatal_Error		*/
-#define BBC_PSRC_FE1	0x0200 /* CPU 1 reported Fatal_Error		*/
-#define BBC_PSRC_FE2	0x0400 /* CPU 2 reported Fatal_Error		*/
-#define BBC_PSRC_FE3	0x0800 /* CPU 3 reported Fatal_Error		*/
-#define BBC_PSRC_FE4	0x1000 /* Schizo reported Fatal_Error		*/
-#define BBC_PSRC_FE5	0x2000 /* Safari device 5 reported Fatal_Error	*/
-#define BBC_PSRC_FE6	0x4000 /* CPMS reported Fatal_Error		*/
-#define BBC_PSRC_SYNTH	0x8000 /* System reset when on-board clock synthesizers
-				* were updated.
-				*/
-#define BBC_PSRC_WDT   0x10000 /* System reset via Super I/O watchdog	*/
-#define BBC_PSRC_RSC   0x20000 /* System reset via RSC remote monitoring
-				* device
-				*/
-
-/* XIR Source register.  The source of an XIR event sent to a processor may
- * be determined via this register.
- */
-#define BBC_XSRC_SXG0	0x01	/* CPU 0 received XIR via Soft_XIR_GEN reg */
-#define BBC_XSRC_SXG1	0x02	/* CPU 1 received XIR via Soft_XIR_GEN reg */
-#define BBC_XSRC_SXG2	0x04	/* CPU 2 received XIR via Soft_XIR_GEN reg */
-#define BBC_XSRC_SXG3	0x08	/* CPU 3 received XIR via Soft_XIR_GEN reg */
-#define BBC_XSRC_JTAG	0x10	/* All CPUs received XIR via JTAG+         */
-#define BBC_XSRC_W_OR_B	0x20	/* All CPUs received XIR either because:
-				 * a) Super I/O watchdog fired, or
-				 * b) XIR push button was activated
-				 */
-#define BBC_XSRC_RESV	0xc0	/* Reserved				   */
-
-/* Clock Synthesizers Control register.  This register provides the big-bang
- * programming interface to the two clock synthesizers of the machine.
- */
-#define BBC_CSC_SLOAD	0x01	/* Directly connected to S_LOAD pins	*/
-#define BBC_CSC_SDATA	0x02	/* Directly connected to S_DATA pins	*/
-#define BBC_CSC_SCLOCK	0x04	/* Directly connected to S_CLOCK pins	*/
-#define BBC_CSC_RESV	0x78	/* Reserved				*/
-#define BBC_CSC_RST	0x80	/* Generate system reset when S_LOAD==1	*/
-
-/* Energy Star Control register.  This register is used to generate the
- * clock frequency change trigger to the main system devices (Schizo and
- * the processors).  The transition occurs when bits in this register
- * go from 0 to 1, only one bit must be set at once else no action
- * occurs.  Basically the sequence of events is:
- * a) Choose new frequency: full, 1/2 or 1/32
- * b) Program this desired frequency into the cpus and Schizo.
- * c) Set the same value in this register.
- * d) 16 system clocks later, clear this register.
- */
-#define BBC_ES_CTRL_1_1		0x01	/* Full frequency	*/
-#define BBC_ES_CTRL_1_2		0x02	/* 1/2 frequency	*/
-#define BBC_ES_CTRL_1_32	0x20	/* 1/32 frequency	*/
-#define BBC_ES_RESV		0xdc	/* Reserved		*/
-
-/* Energy Star Assert Change Time register.  This determines the number
- * of BBC clock cycles (which is half the system frequency) between
- * the detection of FREEZE_ACK being asserted and the assertion of
- * the CLK_CHANGE_L[2:0] signals.
- */
-#define BBC_ES_ACT_VAL	0xff
-
-/* Energy Star Assert Bypass Time register.  This determines the number
- * of BBC clock cycles (which is half the system frequency) between
- * the assertion of the CLK_CHANGE_L[2:0] signals and the assertion of
- * the ESTAR_PLL_BYPASS signal.
- */
-#define BBC_ES_ABT_VAL	0xffff
-
-/* Energy Star PLL Settle Time register.  This determines the number of
- * BBC clock cycles (which is half the system frequency) between the
- * de-assertion of CLK_CHANGE_L[2:0] and the de-assertion of the FREEZE_L
- * signal.
- */
-#define BBC_ES_PST_VAL	0xffffffff
-
-/* Energy Star Frequency Switch Latency register.  This is the number of
- * BBC clocks between the de-assertion of CLK_CHANGE_L[2:0] and the first
- * edge of the Safari clock at the new frequency.
- */
-#define BBC_ES_FSL_VAL	0xffffffff
-
-/* Keyboard Beep control register.  This is a simple enabler for the audio
- * beep sound.
- */
-#define BBC_KBD_BEEP_ENABLE	0x01 /* Enable beep	*/
-#define BBC_KBD_BEEP_RESV	0xfe /* Reserved	*/
-
-/* Keyboard Beep Counter register.  There is a free-running counter inside
- * the BBC which runs at half the system clock.  The bit set in this register
- * determines when the audio sound is generated.  So for example if bit
- * 10 is set, the audio beep will oscillate at 1/(2**12).  The keyboard beep
- * generator automatically selects a different bit to use if the system clock
- * is changed via Energy Star.
- */
-#define BBC_KBD_BCNT_BITS	0x0007fc00
-#define BBC_KBC_BCNT_RESV	0xfff803ff
-
-#endif /* _SPARC64_BBC_H */
-
+#include <asm-sparc/bbc.h>
diff --git a/include/asm-sparc64/bitops.h b/include/asm-sparc64/bitops.h
index bb87b80..2044043 100644
--- a/include/asm-sparc64/bitops.h
+++ b/include/asm-sparc64/bitops.h
@@ -1,107 +1 @@
-/*
- * bitops.h: Bit string operations on the V9.
- *
- * Copyright 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef _SPARC64_BITOPS_H
-#define _SPARC64_BITOPS_H
-
-#ifndef _LINUX_BITOPS_H
-#error only <linux/bitops.h> can be included directly
-#endif
-
-#include <linux/compiler.h>
-#include <asm/byteorder.h>
-
-extern int test_and_set_bit(unsigned long nr, volatile unsigned long *addr);
-extern int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr);
-extern int test_and_change_bit(unsigned long nr, volatile unsigned long *addr);
-extern void set_bit(unsigned long nr, volatile unsigned long *addr);
-extern void clear_bit(unsigned long nr, volatile unsigned long *addr);
-extern void change_bit(unsigned long nr, volatile unsigned long *addr);
-
-#include <asm-generic/bitops/non-atomic.h>
-
-#ifdef CONFIG_SMP
-#define smp_mb__before_clear_bit()	membar_storeload_loadload()
-#define smp_mb__after_clear_bit()	membar_storeload_storestore()
-#else
-#define smp_mb__before_clear_bit()	barrier()
-#define smp_mb__after_clear_bit()	barrier()
-#endif
-
-#include <asm-generic/bitops/ffz.h>
-#include <asm-generic/bitops/__ffs.h>
-#include <asm-generic/bitops/fls.h>
-#include <asm-generic/bitops/__fls.h>
-#include <asm-generic/bitops/fls64.h>
-
-#ifdef __KERNEL__
-
-#include <asm-generic/bitops/sched.h>
-#include <asm-generic/bitops/ffs.h>
-
-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
- */
-
-#ifdef ULTRA_HAS_POPULATION_COUNT
-
-static inline unsigned int hweight64(unsigned long w)
-{
-	unsigned int res;
-
-	__asm__ ("popc %1,%0" : "=r" (res) : "r" (w));
-	return res;
-}
-
-static inline unsigned int hweight32(unsigned int w)
-{
-	unsigned int res;
-
-	__asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffffffff));
-	return res;
-}
-
-static inline unsigned int hweight16(unsigned int w)
-{
-	unsigned int res;
-
-	__asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffff));
-	return res;
-}
-
-static inline unsigned int hweight8(unsigned int w)
-{
-	unsigned int res;
-
-	__asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xff));
-	return res;
-}
-
-#else
-
-#include <asm-generic/bitops/hweight.h>
-
-#endif
-#include <asm-generic/bitops/lock.h>
-#endif /* __KERNEL__ */
-
-#include <asm-generic/bitops/find.h>
-
-#ifdef __KERNEL__
-
-#include <asm-generic/bitops/ext2-non-atomic.h>
-
-#define ext2_set_bit_atomic(lock,nr,addr) \
-	test_and_set_bit((nr) ^ 0x38,(unsigned long *)(addr))
-#define ext2_clear_bit_atomic(lock,nr,addr) \
-	test_and_clear_bit((nr) ^ 0x38,(unsigned long *)(addr))
-
-#include <asm-generic/bitops/minix.h>
-
-#endif /* __KERNEL__ */
-
-#endif /* defined(_SPARC64_BITOPS_H) */
+#include <asm-sparc/bitops.h>
diff --git a/include/asm-sparc64/cacheflush.h b/include/asm-sparc64/cacheflush.h
index 122e405..cf5b6b3 100644
--- a/include/asm-sparc64/cacheflush.h
+++ b/include/asm-sparc64/cacheflush.h
@@ -1,76 +1 @@
-#ifndef _SPARC64_CACHEFLUSH_H
-#define _SPARC64_CACHEFLUSH_H
-
-#include <asm/page.h>
-
-#ifndef __ASSEMBLY__
-
-#include <linux/mm.h>
-
-/* Cache flush operations. */
-
-/* These are the same regardless of whether this is an SMP kernel or not. */
-#define flush_cache_mm(__mm) \
-	do { if ((__mm) == current->mm) flushw_user(); } while(0)
-#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
-#define flush_cache_range(vma, start, end) \
-	flush_cache_mm((vma)->vm_mm)
-#define flush_cache_page(vma, page, pfn) \
-	flush_cache_mm((vma)->vm_mm)
-
-/* 
- * On spitfire, the icache doesn't snoop local stores and we don't
- * use block commit stores (which invalidate icache lines) during
- * module load, so we need this.
- */
-extern void flush_icache_range(unsigned long start, unsigned long end);
-extern void __flush_icache_page(unsigned long);
-
-extern void __flush_dcache_page(void *addr, int flush_icache);
-extern void flush_dcache_page_impl(struct page *page);
-#ifdef CONFIG_SMP
-extern void smp_flush_dcache_page_impl(struct page *page, int cpu);
-extern void flush_dcache_page_all(struct mm_struct *mm, struct page *page);
-#else
-#define smp_flush_dcache_page_impl(page,cpu) flush_dcache_page_impl(page)
-#define flush_dcache_page_all(mm,page) flush_dcache_page_impl(page)
-#endif
-
-extern void __flush_dcache_range(unsigned long start, unsigned long end);
-extern void flush_dcache_page(struct page *page);
-
-#define flush_icache_page(vma, pg)	do { } while(0)
-#define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
-
-extern void flush_ptrace_access(struct vm_area_struct *, struct page *,
-				unsigned long uaddr, void *kaddr,
-				unsigned long len, int write);
-
-#define copy_to_user_page(vma, page, vaddr, dst, src, len)		\
-	do {								\
-		flush_cache_page(vma, vaddr, page_to_pfn(page));	\
-		memcpy(dst, src, len);					\
-		flush_ptrace_access(vma, page, vaddr, src, len, 0);	\
-	} while (0)
-
-#define copy_from_user_page(vma, page, vaddr, dst, src, len) 		\
-	do {								\
-		flush_cache_page(vma, vaddr, page_to_pfn(page));	\
-		memcpy(dst, src, len);					\
-		flush_ptrace_access(vma, page, vaddr, dst, len, 1);	\
-	} while (0)
-
-#define flush_dcache_mmap_lock(mapping)		do { } while (0)
-#define flush_dcache_mmap_unlock(mapping)	do { } while (0)
-
-#define flush_cache_vmap(start, end)		do { } while (0)
-#define flush_cache_vunmap(start, end)		do { } while (0)
-
-#ifdef CONFIG_DEBUG_PAGEALLOC
-/* internal debugging function */
-void kernel_map_pages(struct page *page, int numpages, int enable);
-#endif
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* _SPARC64_CACHEFLUSH_H */
+#include <asm-sparc/cacheflush.h>
diff --git a/include/asm-sparc64/chafsr.h b/include/asm-sparc64/chafsr.h
index 85c69b3..aaab975 100644
--- a/include/asm-sparc64/chafsr.h
+++ b/include/asm-sparc64/chafsr.h
@@ -1,241 +1 @@
-#ifndef _SPARC64_CHAFSR_H
-#define _SPARC64_CHAFSR_H
-
-/* Cheetah Asynchronous Fault Status register, ASI=0x4C VA<63:0>=0x0 */
-
-/* Comments indicate which processor variants on which the bit definition
- * is valid.  Codes are:
- * ch	-->	cheetah
- * ch+	-->	cheetah plus
- * jp	-->	jalapeno
- */
-
-/* All bits of this register except M_SYNDROME and E_SYNDROME are
- * read, write 1 to clear.  M_SYNDROME and E_SYNDROME are read-only.
- */
-
-/* Software bit set by linux trap handlers to indicate that the trap was
- * signalled at %tl >= 1.
- */
-#define CHAFSR_TL1		(1UL << 63UL) /* n/a */
-
-/* Unmapped error from system bus for prefetch queue or
- * store queue read operation
- */
-#define CHPAFSR_DTO		(1UL << 59UL) /* ch+ */
-
-/* Bus error from system bus for prefetch queue or store queue
- * read operation
- */
-#define CHPAFSR_DBERR		(1UL << 58UL) /* ch+ */
-
-/* Hardware corrected E-cache Tag ECC error */
-#define CHPAFSR_THCE		(1UL << 57UL) /* ch+ */
-/* System interface protocol error, hw timeout caused */
-#define JPAFSR_JETO		(1UL << 57UL) /* jp */
-
-/* SW handled correctable E-cache Tag ECC error */
-#define CHPAFSR_TSCE		(1UL << 56UL) /* ch+ */
-/* Parity error on system snoop results */
-#define JPAFSR_SCE		(1UL << 56UL) /* jp */
-
-/* Uncorrectable E-cache Tag ECC error */
-#define CHPAFSR_TUE		(1UL << 55UL) /* ch+ */
-/* System interface protocol error, illegal command detected */
-#define JPAFSR_JEIC		(1UL << 55UL) /* jp */
-
-/* Uncorrectable system bus data ECC error due to prefetch
- * or store fill request
- */
-#define CHPAFSR_DUE		(1UL << 54UL) /* ch+ */
-/* System interface protocol error, illegal ADTYPE detected */
-#define JPAFSR_JEIT		(1UL << 54UL) /* jp */
-
-/* Multiple errors of the same type have occurred.  This bit is set when
- * an uncorrectable error or a SW correctable error occurs and the status
- * bit to report that error is already set.  When multiple errors of
- * different types are indicated by setting multiple status bits.
- *
- * This bit is not set if multiple HW corrected errors with the same
- * status bit occur, only uncorrectable and SW correctable ones have
- * this behavior.
- *
- * This bit is not set when multiple ECC errors happen within a single
- * 64-byte system bus transaction.  Only the first ECC error in a 16-byte
- * subunit will be logged.  All errors in subsequent 16-byte subunits
- * from the same 64-byte transaction are ignored.
- */
-#define CHAFSR_ME		(1UL << 53UL) /* ch,ch+,jp */
-
-/* Privileged state error has occurred.  This is a capture of PSTATE.PRIV
- * at the time the error is detected.
- */
-#define CHAFSR_PRIV		(1UL << 52UL) /* ch,ch+,jp */
-
-/* The following bits 51 (CHAFSR_PERR) to 33 (CHAFSR_CE) are sticky error
- * bits and record the most recently detected errors.  Bits accumulate
- * errors that have been detected since the last write to clear the bit.
- */
-
-/* System interface protocol error.  The processor asserts its' ERROR
- * pin when this event occurs and it also logs a specific cause code
- * into a JTAG scannable flop.
- */
-#define CHAFSR_PERR		(1UL << 51UL) /* ch,ch+,jp */
-
-/* Internal processor error.  The processor asserts its' ERROR
- * pin when this event occurs and it also logs a specific cause code
- * into a JTAG scannable flop.
- */
-#define CHAFSR_IERR		(1UL << 50UL) /* ch,ch+,jp */
-
-/* System request parity error on incoming address */
-#define CHAFSR_ISAP		(1UL << 49UL) /* ch,ch+,jp */
-
-/* HW Corrected system bus MTAG ECC error */
-#define CHAFSR_EMC		(1UL << 48UL) /* ch,ch+ */
-/* Parity error on L2 cache tag SRAM */
-#define JPAFSR_ETP		(1UL << 48UL) /* jp */
-
-/* Uncorrectable system bus MTAG ECC error */
-#define CHAFSR_EMU		(1UL << 47UL) /* ch,ch+ */
-/* Out of range memory error has occurred */
-#define JPAFSR_OM		(1UL << 47UL) /* jp */
-
-/* HW Corrected system bus data ECC error for read of interrupt vector */
-#define CHAFSR_IVC		(1UL << 46UL) /* ch,ch+ */
-/* Error due to unsupported store */
-#define JPAFSR_UMS		(1UL << 46UL) /* jp */
-
-/* Uncorrectable system bus data ECC error for read of interrupt vector */
-#define CHAFSR_IVU		(1UL << 45UL) /* ch,ch+,jp */
-
-/* Unmapped error from system bus */
-#define CHAFSR_TO		(1UL << 44UL) /* ch,ch+,jp */
-
-/* Bus error response from system bus */
-#define CHAFSR_BERR		(1UL << 43UL) /* ch,ch+,jp */
-
-/* SW Correctable E-cache ECC error for instruction fetch or data access
- * other than block load.
- */
-#define CHAFSR_UCC		(1UL << 42UL) /* ch,ch+,jp */
-
-/* Uncorrectable E-cache ECC error for instruction fetch or data access
- * other than block load.
- */
-#define CHAFSR_UCU		(1UL << 41UL) /* ch,ch+,jp */
-
-/* Copyout HW Corrected ECC error */
-#define CHAFSR_CPC		(1UL << 40UL) /* ch,ch+,jp */
-
-/* Copyout Uncorrectable ECC error */
-#define CHAFSR_CPU		(1UL << 39UL) /* ch,ch+,jp */
-
-/* HW Corrected ECC error from E-cache for writeback */
-#define CHAFSR_WDC		(1UL << 38UL) /* ch,ch+,jp */
-
-/* Uncorrectable ECC error from E-cache for writeback */
-#define CHAFSR_WDU		(1UL << 37UL) /* ch,ch+,jp */
-
-/* HW Corrected ECC error from E-cache for store merge or block load */
-#define CHAFSR_EDC		(1UL << 36UL) /* ch,ch+,jp */
-
-/* Uncorrectable ECC error from E-cache for store merge or block load */
-#define CHAFSR_EDU		(1UL << 35UL) /* ch,ch+,jp */
-
-/* Uncorrectable system bus data ECC error for read of memory or I/O */
-#define CHAFSR_UE		(1UL << 34UL) /* ch,ch+,jp */
-
-/* HW Corrected system bus data ECC error for read of memory or I/O */
-#define CHAFSR_CE		(1UL << 33UL) /* ch,ch+,jp */
-
-/* Uncorrectable ECC error from remote cache/memory */
-#define JPAFSR_RUE		(1UL << 32UL) /* jp */
-
-/* Correctable ECC error from remote cache/memory */
-#define JPAFSR_RCE		(1UL << 31UL) /* jp */
-
-/* JBUS parity error on returned read data */
-#define JPAFSR_BP		(1UL << 30UL) /* jp */
-
-/* JBUS parity error on data for writeback or block store */
-#define JPAFSR_WBP		(1UL << 29UL) /* jp */
-
-/* Foreign read to DRAM incurring correctable ECC error */
-#define JPAFSR_FRC		(1UL << 28UL) /* jp */
-
-/* Foreign read to DRAM incurring uncorrectable ECC error */
-#define JPAFSR_FRU		(1UL << 27UL) /* jp */
-
-#define CHAFSR_ERRORS		(CHAFSR_PERR | CHAFSR_IERR | CHAFSR_ISAP | CHAFSR_EMC | \
-				 CHAFSR_EMU | CHAFSR_IVC | CHAFSR_IVU | CHAFSR_TO | \
-				 CHAFSR_BERR | CHAFSR_UCC | CHAFSR_UCU | CHAFSR_CPC | \
-				 CHAFSR_CPU | CHAFSR_WDC | CHAFSR_WDU | CHAFSR_EDC | \
-				 CHAFSR_EDU | CHAFSR_UE | CHAFSR_CE)
-#define CHPAFSR_ERRORS		(CHPAFSR_DTO | CHPAFSR_DBERR | CHPAFSR_THCE | \
-				 CHPAFSR_TSCE | CHPAFSR_TUE | CHPAFSR_DUE | \
-				 CHAFSR_PERR | CHAFSR_IERR | CHAFSR_ISAP | CHAFSR_EMC | \
-				 CHAFSR_EMU | CHAFSR_IVC | CHAFSR_IVU | CHAFSR_TO | \
-				 CHAFSR_BERR | CHAFSR_UCC | CHAFSR_UCU | CHAFSR_CPC | \
-				 CHAFSR_CPU | CHAFSR_WDC | CHAFSR_WDU | CHAFSR_EDC | \
-				 CHAFSR_EDU | CHAFSR_UE | CHAFSR_CE)
-#define JPAFSR_ERRORS		(JPAFSR_JETO | JPAFSR_SCE | JPAFSR_JEIC | \
-				 JPAFSR_JEIT | CHAFSR_PERR | CHAFSR_IERR | \
-				 CHAFSR_ISAP | JPAFSR_ETP | JPAFSR_OM | \
-				 JPAFSR_UMS | CHAFSR_IVU | CHAFSR_TO | \
-				 CHAFSR_BERR | CHAFSR_UCC | CHAFSR_UCU | \
-				 CHAFSR_CPC | CHAFSR_CPU | CHAFSR_WDC | \
-				 CHAFSR_WDU | CHAFSR_EDC | CHAFSR_EDU | \
-				 CHAFSR_UE | CHAFSR_CE | JPAFSR_RUE | \
-				 JPAFSR_RCE | JPAFSR_BP | JPAFSR_WBP | \
-				 JPAFSR_FRC | JPAFSR_FRU)
-
-/* Active JBUS request signal when error occurred */
-#define JPAFSR_JBREQ		(0x7UL << 24UL) /* jp */
-#define JPAFSR_JBREQ_SHIFT	24UL
-
-/* L2 cache way information */
-#define JPAFSR_ETW		(0x3UL << 22UL) /* jp */
-#define JPAFSR_ETW_SHIFT	22UL
-
-/* System bus MTAG ECC syndrome.  This field captures the status of the
- * first occurrence of the highest-priority error according to the M_SYND
- * overwrite policy.  After the AFSR sticky bit, corresponding to the error
- * for which the M_SYND is reported, is cleared, the contents of the M_SYND
- * field will be unchanged by will be unfrozen for further error capture.
- */
-#define CHAFSR_M_SYNDROME	(0xfUL << 16UL) /* ch,ch+,jp */
-#define CHAFSR_M_SYNDROME_SHIFT	16UL
-
-/* Agenid Id of the foreign device causing the UE/CE errors */
-#define JPAFSR_AID		(0x1fUL << 9UL) /* jp */
-#define JPAFSR_AID_SHIFT	9UL
-
-/* System bus or E-cache data ECC syndrome.  This field captures the status
- * of the first occurrence of the highest-priority error according to the
- * E_SYND overwrite policy.  After the AFSR sticky bit, corresponding to the
- * error for which the E_SYND is reported, is cleare, the contents of the E_SYND
- * field will be unchanged but will be unfrozen for further error capture.
- */
-#define CHAFSR_E_SYNDROME	(0x1ffUL << 0UL) /* ch,ch+,jp */
-#define CHAFSR_E_SYNDROME_SHIFT	0UL
-
-/* The AFSR must be explicitly cleared by software, it is not cleared automatically
- * by a read.  Writes to bits <51:33> with bits set will clear the corresponding
- * bits in the AFSR.  Bits associated with disrupting traps must be cleared before
- * interrupts are re-enabled to prevent multiple traps for the same error.  I.e.
- * PSTATE.IE and AFSR bits control delivery of disrupting traps.
- *
- * Since there is only one AFAR, when multiple events have been logged by the
- * bits in the AFSR, at most one of these events will have its status captured
- * in the AFAR.  The highest priority of those event bits will get AFAR logging.
- * The AFAR will be unlocked and available to capture the address of another event
- * as soon as the one bit in AFSR that corresponds to the event logged in AFAR is
- * cleared.  For example, if AFSR.CE is detected, then AFSR.UE (which overwrites
- * the AFAR), and AFSR.UE is cleared by not AFSR.CE, then the AFAR will be unlocked
- * and ready for another event, even though AFSR.CE is still set.  The same rules
- * also apply to the M_SYNDROME and E_SYNDROME fields of the AFSR.
- */
-
-#endif /* _SPARC64_CHAFSR_H */
+#include <asm-sparc/chafsr.h>
diff --git a/include/asm-sparc64/checksum.h b/include/asm-sparc64/checksum.h
index b290564..c3966c5 100644
--- a/include/asm-sparc64/checksum.h
+++ b/include/asm-sparc64/checksum.h
@@ -1,167 +1 @@
-#ifndef __SPARC64_CHECKSUM_H
-#define __SPARC64_CHECKSUM_H
-
-/*  checksum.h:  IP/UDP/TCP checksum routines on the V9.
- *
- *  Copyright(C) 1995 Linus Torvalds
- *  Copyright(C) 1995 Miguel de Icaza
- *  Copyright(C) 1996 David S. Miller
- *  Copyright(C) 1996 Eddie C. Dost
- *  Copyright(C) 1997 Jakub Jelinek
- *
- * derived from:
- *	Alpha checksum c-code
- *      ix86 inline assembly
- *      RFC1071 Computing the Internet Checksum
- */
-
-#include <linux/in6.h>
-#include <asm/uaccess.h>
-
-/* computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-extern __wsum csum_partial(const void * buff, int len, __wsum sum);
-
-/* the same as csum_partial, but copies from user space while it
- * checksums
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-extern __wsum csum_partial_copy_nocheck(const void *src, void *dst,
-					      int len, __wsum sum);
-
-extern long __csum_partial_copy_from_user(const void __user *src,
-					  void *dst, int len,
-					  __wsum sum);
-
-static inline __wsum
-csum_partial_copy_from_user(const void __user *src,
-			    void *dst, int len,
-			    __wsum sum, int *err)
-{
-	long ret = __csum_partial_copy_from_user(src, dst, len, sum);
-	if (ret < 0)
-		*err = -EFAULT;
-	return (__force __wsum) ret;
-}
-
-/* 
- *	Copy and checksum to user
- */
-#define HAVE_CSUM_COPY_USER
-extern long __csum_partial_copy_to_user(const void *src,
-					void __user *dst, int len,
-					  __wsum sum);
-
-static inline __wsum
-csum_and_copy_to_user(const void *src,
-		      void __user *dst, int len,
-		      __wsum sum, int *err)
-{
-	long ret = __csum_partial_copy_to_user(src, dst, len, sum);
-	if (ret < 0)
-		*err = -EFAULT;
-	return (__force __wsum) ret;
-}
-
-/* ihl is always 5 or greater, almost always is 5, and iph is word aligned
- * the majority of the time.
- */
-extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl);
-
-/* Fold a partial checksum without adding pseudo headers. */
-static inline __sum16 csum_fold(__wsum sum)
-{
-	unsigned int tmp;
-
-	__asm__ __volatile__(
-"	addcc		%0, %1, %1\n"
-"	srl		%1, 16, %1\n"
-"	addc		%1, %%g0, %1\n"
-"	xnor		%%g0, %1, %0\n"
-	: "=&r" (sum), "=r" (tmp)
-	: "0" (sum), "1" ((__force u32)sum<<16)
-	: "cc");
-	return (__force __sum16)sum;
-}
-
-static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
-					       unsigned int len,
-					       unsigned short proto,
-					       __wsum sum)
-{
-	__asm__ __volatile__(
-"	addcc		%1, %0, %0\n"
-"	addccc		%2, %0, %0\n"
-"	addccc		%3, %0, %0\n"
-"	addc		%0, %%g0, %0\n"
-	: "=r" (sum), "=r" (saddr)
-	: "r" (daddr), "r" (proto + len), "0" (sum), "1" (saddr)
-	: "cc");
-	return sum;
-}
-
-/*
- * computes the checksum of the TCP/UDP pseudo-header
- * returns a 16-bit checksum, already complemented
- */
-static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
-						   unsigned short len,
-						   unsigned short proto,
-						   __wsum sum)
-{
-	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
-}
-
-#define _HAVE_ARCH_IPV6_CSUM
-
-static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
-				      const struct in6_addr *daddr,
-				      __u32 len, unsigned short proto,
-				      __wsum sum)
-{
-	__asm__ __volatile__ (
-"	addcc		%3, %4, %%g7\n"
-"	addccc		%5, %%g7, %%g7\n"
-"	lduw		[%2 + 0x0c], %%g2\n"
-"	lduw		[%2 + 0x08], %%g3\n"
-"	addccc		%%g2, %%g7, %%g7\n"
-"	lduw		[%2 + 0x04], %%g2\n"
-"	addccc		%%g3, %%g7, %%g7\n"
-"	lduw		[%2 + 0x00], %%g3\n"
-"	addccc		%%g2, %%g7, %%g7\n"
-"	lduw		[%1 + 0x0c], %%g2\n"
-"	addccc		%%g3, %%g7, %%g7\n"
-"	lduw		[%1 + 0x08], %%g3\n"
-"	addccc		%%g2, %%g7, %%g7\n"
-"	lduw		[%1 + 0x04], %%g2\n"
-"	addccc		%%g3, %%g7, %%g7\n"
-"	lduw		[%1 + 0x00], %%g3\n"
-"	addccc		%%g2, %%g7, %%g7\n"
-"	addccc		%%g3, %%g7, %0\n"
-"	addc		0, %0, %0\n"
-	: "=&r" (sum)
-	: "r" (saddr), "r" (daddr), "r"(htonl(len)),
-	  "r"(htonl(proto)), "r"(sum)
-	: "g2", "g3", "g7", "cc");
-
-	return csum_fold(sum);
-}
-
-/* this routine is used for miscellaneous IP-like checksums, mainly in icmp.c */
-static inline __sum16 ip_compute_csum(const void *buff, int len)
-{
-	return csum_fold(csum_partial(buff, len, 0));
-}
-
-#endif /* !(__SPARC64_CHECKSUM_H) */
+#include <asm-sparc/checksum.h>
diff --git a/include/asm-sparc64/chmctrl.h b/include/asm-sparc64/chmctrl.h
index 859b4a4..eb757b4 100644
--- a/include/asm-sparc64/chmctrl.h
+++ b/include/asm-sparc64/chmctrl.h
@@ -1,183 +1 @@
-#ifndef _SPARC64_CHMCTRL_H
-#define _SPARC64_CHMCTRL_H
-
-/* Cheetah memory controller programmable registers. */
-#define CHMCTRL_TCTRL1		0x00 /* Memory Timing Control I		*/
-#define CHMCTRL_TCTRL2		0x08 /* Memory Timing Control II	*/
-#define CHMCTRL_TCTRL3		0x38 /* Memory Timing Control III	*/
-#define CHMCTRL_TCTRL4		0x40 /* Memory Timing Control IV	*/
-#define CHMCTRL_DECODE1		0x10 /* Memory Address Decode I		*/
-#define CHMCTRL_DECODE2		0x18 /* Memory Address Decode II	*/
-#define CHMCTRL_DECODE3		0x20 /* Memory Address Decode III	*/
-#define CHMCTRL_DECODE4		0x28 /* Memory Address Decode IV	*/
-#define CHMCTRL_MACTRL		0x30 /* Memory Address Control		*/
-
-/* Memory Timing Control I */
-#define TCTRL1_SDRAMCTL_DLY	0xf000000000000000UL
-#define TCTRL1_SDRAMCTL_DLY_SHIFT     60
-#define TCTRL1_SDRAMCLK_DLY	0x0e00000000000000UL
-#define TCTRL1_SDRAMCLK_DLY_SHIFT     57
-#define TCTRL1_R		0x0100000000000000UL
-#define TCTRL1_R_SHIFT 		      56
-#define TCTRL1_AUTORFR_CYCLE	0x00fe000000000000UL
-#define TCTRL1_AUTORFR_CYCLE_SHIFT    49
-#define TCTRL1_RD_WAIT		0x0001f00000000000UL
-#define TCTRL1_RD_WAIT_SHIFT	      44
-#define TCTRL1_PC_CYCLE		0x00000fc000000000UL
-#define TCTRL1_PC_CYCLE_SHIFT	      38
-#define TCTRL1_WR_MORE_RAS_PW	0x0000003f00000000UL
-#define TCTRL1_WR_MORE_RAS_PW_SHIFT   32
-#define TCTRL1_RD_MORE_RAW_PW	0x00000000fc000000UL
-#define TCTRL1_RD_MORE_RAS_PW_SHIFT   26
-#define TCTRL1_ACT_WR_DLY	0x0000000003f00000UL
-#define TCTRL1_ACT_WR_DLY_SHIFT	      20
-#define TCTRL1_ACT_RD_DLY	0x00000000000fc000UL
-#define TCTRL1_ACT_RD_DLY_SHIFT	      14
-#define TCTRL1_BANK_PRESENT	0x0000000000003000UL
-#define TCTRL1_BANK_PRESENT_SHIFT     12
-#define TCTRL1_RFR_INT		0x0000000000000ff8UL
-#define TCTRL1_RFR_INT_SHIFT	      3
-#define TCTRL1_SET_MODE_REG	0x0000000000000004UL
-#define TCTRL1_SET_MODE_REG_SHIFT     2
-#define TCTRL1_RFR_ENABLE	0x0000000000000002UL
-#define TCTRL1_RFR_ENABLE_SHIFT	      1
-#define TCTRL1_PRECHG_ALL	0x0000000000000001UL
-#define TCTRL1_PRECHG_ALL_SHIFT	      0
-
-/* Memory Timing Control II */
-#define TCTRL2_WR_MSEL_DLY	0xfc00000000000000UL
-#define TCTRL2_WR_MSEL_DLY_SHIFT      58
-#define TCTRL2_RD_MSEL_DLY	0x03f0000000000000UL
-#define TCTRL2_RD_MSEL_DLY_SHIFT      52
-#define TCTRL2_WRDATA_THLD	0x000c000000000000UL
-#define TCTRL2_WRDATA_THLD_SHIFT      50
-#define TCTRL2_RDWR_RD_TI_DLY	0x0003f00000000000UL
-#define TCTRL2_RDWR_RD_TI_DLY_SHIFT   44
-#define TCTRL2_AUTOPRECHG_ENBL	0x0000080000000000UL
-#define TCTRL2_AUTOPRECHG_ENBL_SHIFT  43
-#define TCTRL2_RDWR_PI_MORE_DLY	0x000007c000000000UL
-#define TCTRL2_RDWR_PI_MORE_DLY_SHIFT 38
-#define TCTRL2_RDWR_1_DLY	0x0000003f00000000UL
-#define TCTRL2_RDWR_1_DLY_SHIFT       32
-#define TCTRL2_WRWR_PI_MORE_DLY	0x00000000f8000000UL
-#define TCTRL2_WRWR_PI_MORE_DLY_SHIFT 27
-#define TCTRL2_WRWR_1_DLY	0x0000000007e00000UL
-#define TCTRL2_WRWR_1_DLY_SHIFT       21
-#define TCTRL2_RDWR_RD_PI_MORE_DLY 0x00000000001f0000UL
-#define TCTRL2_RDWR_RD_PI_MORE_DLY_SHIFT 16
-#define TCTRL2_R		0x0000000000008000UL
-#define TCTRL2_R_SHIFT		      15
-#define TCTRL2_SDRAM_MODE_REG_DATA 0x0000000000007fffUL
-#define TCTRL2_SDRAM_MODE_REG_DATA_SHIFT 0
-
-/* Memory Timing Control III */
-#define TCTRL3_SDRAM_CTL_DLY	0xf000000000000000UL
-#define TCTRL3_SDRAM_CTL_DLY_SHIFT    60
-#define TCTRL3_SDRAM_CLK_DLY	0x0e00000000000000UL
-#define TCTRL3_SDRAM_CLK_DLY_SHIFT    57
-#define TCTRL3_R		0x0100000000000000UL
-#define TCTRL3_R_SHIFT		      56
-#define TCTRL3_AUTO_RFR_CYCLE	0x00fe000000000000UL
-#define TCTRL3_AUTO_RFR_CYCLE_SHIFT   49
-#define TCTRL3_RD_WAIT		0x0001f00000000000UL
-#define TCTRL3_RD_WAIT_SHIFT	      44
-#define TCTRL3_PC_CYCLE		0x00000fc000000000UL
-#define TCTRL3_PC_CYCLE_SHIFT	      38
-#define TCTRL3_WR_MORE_RAW_PW	0x0000003f00000000UL
-#define TCTRL3_WR_MORE_RAW_PW_SHIFT   32
-#define TCTRL3_RD_MORE_RAW_PW	0x00000000fc000000UL
-#define TCTRL3_RD_MORE_RAW_PW_SHIFT   26
-#define TCTRL3_ACT_WR_DLY	0x0000000003f00000UL
-#define TCTRL3_ACT_WR_DLY_SHIFT       20
-#define TCTRL3_ACT_RD_DLY	0x00000000000fc000UL
-#define TCTRL3_ACT_RD_DLY_SHIFT       14
-#define TCTRL3_BANK_PRESENT	0x0000000000003000UL
-#define TCTRL3_BANK_PRESENT_SHIFT     12
-#define TCTRL3_RFR_INT		0x0000000000000ff8UL
-#define TCTRL3_RFR_INT_SHIFT	      3
-#define TCTRL3_SET_MODE_REG	0x0000000000000004UL
-#define TCTRL3_SET_MODE_REG_SHIFT     2
-#define TCTRL3_RFR_ENABLE	0x0000000000000002UL
-#define TCTRL3_RFR_ENABLE_SHIFT       1
-#define TCTRL3_PRECHG_ALL	0x0000000000000001UL
-#define TCTRL3_PRECHG_ALL_SHIFT	      0
-
-/* Memory Timing Control IV */
-#define TCTRL4_WR_MSEL_DLY	0xfc00000000000000UL
-#define TCTRL4_WR_MSEL_DLY_SHIFT      58
-#define TCTRL4_RD_MSEL_DLY	0x03f0000000000000UL
-#define TCTRL4_RD_MSEL_DLY_SHIFT      52
-#define TCTRL4_WRDATA_THLD	0x000c000000000000UL
-#define TCTRL4_WRDATA_THLD_SHIFT      50
-#define TCTRL4_RDWR_RD_RI_DLY	0x0003f00000000000UL
-#define TCTRL4_RDWR_RD_RI_DLY_SHIFT   44
-#define TCTRL4_AUTO_PRECHG_ENBL	0x0000080000000000UL
-#define TCTRL4_AUTO_PRECHG_ENBL_SHIFT 43
-#define TCTRL4_RD_WR_PI_MORE_DLY 0x000007c000000000UL
-#define TCTRL4_RD_WR_PI_MORE_DLY_SHIFT 38
-#define TCTRL4_RD_WR_TI_DLY	0x0000003f00000000UL
-#define TCTRL4_RD_WR_TI_DLY_SHIFT     32
-#define TCTRL4_WR_WR_PI_MORE_DLY 0x00000000f8000000UL
-#define TCTRL4_WR_WR_PI_MORE_DLY_SHIFT 27
-#define TCTRL4_WR_WR_TI_DLY	0x0000000007e00000UL
-#define TCTRL4_WR_WR_TI_DLY_SHIFT     21
-#define TCTRL4_RDWR_RD_PI_MORE_DLY 0x00000000001f000UL0
-#define TCTRL4_RDWR_RD_PI_MORE_DLY_SHIFT 16
-#define TCTRL4_R		0x0000000000008000UL
-#define TCTRL4_R_SHIFT		      15
-#define TCTRL4_SDRAM_MODE_REG_DATA 0x0000000000007fffUL
-#define TCTRL4_SDRAM_MODE_REG_DATA_SHIFT 0
-
-/* All 4 memory address decoding registers have the
- * same layout.
- */
-#define MEM_DECODE_VALID	0x8000000000000000UL /* Valid */
-#define MEM_DECODE_VALID_SHIFT	      63
-#define MEM_DECODE_UK		0x001ffe0000000000UL /* Upper mask */
-#define MEM_DECODE_UK_SHIFT	      41
-#define MEM_DECODE_UM		0x0000001ffff00000UL /* Upper match */
-#define MEM_DECODE_UM_SHIFT	      20
-#define MEM_DECODE_LK		0x000000000003c000UL /* Lower mask */
-#define MEM_DECODE_LK_SHIFT	      14
-#define MEM_DECODE_LM		0x0000000000000f00UL /* Lower match */
-#define MEM_DECODE_LM_SHIFT           8
-
-#define PA_UPPER_BITS		0x000007fffc000000UL
-#define PA_UPPER_BITS_SHIFT	26
-#define PA_LOWER_BITS		0x00000000000003c0UL
-#define PA_LOWER_BITS_SHIFT	6
-
-#define MACTRL_R0		         0x8000000000000000UL
-#define MACTRL_R0_SHIFT		         63
-#define MACTRL_ADDR_LE_PW                0x7000000000000000UL
-#define MACTRL_ADDR_LE_PW_SHIFT		 60
-#define MACTRL_CMD_PW                    0x0f00000000000000UL
-#define MACTRL_CMD_PW_SHIFT		 56
-#define MACTRL_HALF_MODE_WR_MSEL_DLY     0x00fc000000000000UL
-#define MACTRL_HALF_MODE_WR_MSEL_DLY_SHIFT 50
-#define MACTRL_HALF_MODE_RD_MSEL_DLY     0x0003f00000000000UL
-#define MACTRL_HALF_MODE_RD_MSEL_DLY_SHIFT 44
-#define MACTRL_HALF_MODE_SDRAM_CTL_DLY   0x00000f0000000000UL
-#define MACTRL_HALF_MODE_SDRAM_CTL_DLY_SHIFT 40
-#define MACTRL_HALF_MODE_SDRAM_CLK_DLY   0x000000e000000000UL
-#define MACTRL_HALF_MODE_SDRAM_CLK_DLY_SHIFT 37
-#define MACTRL_R1                        0x0000001000000000UL
-#define MACTRL_R1_SHIFT                      36
-#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B3 0x0000000f00000000UL
-#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B3_SHIFT 32
-#define MACTRL_ENC_INTLV_B3              0x00000000f8000000UL
-#define MACTRL_ENC_INTLV_B3_SHIFT              27
-#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B2 0x0000000007800000UL
-#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B2_SHIFT 23
-#define MACTRL_ENC_INTLV_B2              0x00000000007c0000UL
-#define MACTRL_ENC_INTLV_B2_SHIFT              18
-#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B1 0x000000000003c000UL
-#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B1_SHIFT 14
-#define MACTRL_ENC_INTLV_B1              0x0000000000003e00UL
-#define MACTRL_ENC_INTLV_B1_SHIFT               9
-#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B0 0x00000000000001e0UL
-#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B0_SHIFT  5
-#define MACTRL_ENC_INTLV_B0              0x000000000000001fUL
-#define MACTRL_ENC_INTLV_B0_SHIFT               0
-
-#endif /* _SPARC64_CHMCTRL_H */
+#include <asm-sparc/chmctrl.h>
diff --git a/include/asm-sparc64/cmt.h b/include/asm-sparc64/cmt.h
index 870db59..b19b445 100644
--- a/include/asm-sparc64/cmt.h
+++ b/include/asm-sparc64/cmt.h
@@ -1,59 +1 @@
-#ifndef _SPARC64_CMT_H
-#define _SPARC64_CMT_H
-
-/* cmt.h: Chip Multi-Threading register definitions
- *
- * Copyright (C) 2004 David S. Miller (davem@redhat.com)
- */
-
-/* ASI_CORE_ID - private */
-#define LP_ID		0x0000000000000010UL
-#define  LP_ID_MAX	0x00000000003f0000UL
-#define  LP_ID_ID	0x000000000000003fUL
-
-/* ASI_INTR_ID - private */
-#define LP_INTR_ID	0x0000000000000000UL
-#define  LP_INTR_ID_ID	0x00000000000003ffUL
-
-/* ASI_CESR_ID - private */
-#define CESR_ID		0x0000000000000040UL
-#define  CESR_ID_ID	0x00000000000000ffUL
-
-/* ASI_CORE_AVAILABLE - shared */
-#define LP_AVAIL	0x0000000000000000UL
-#define  LP_AVAIL_1	0x0000000000000002UL
-#define  LP_AVAIL_0	0x0000000000000001UL
-
-/* ASI_CORE_ENABLE_STATUS - shared */
-#define LP_ENAB_STAT	0x0000000000000010UL
-#define  LP_ENAB_STAT_1	0x0000000000000002UL
-#define  LP_ENAB_STAT_0	0x0000000000000001UL
-
-/* ASI_CORE_ENABLE - shared */
-#define LP_ENAB		0x0000000000000020UL
-#define  LP_ENAB_1	0x0000000000000002UL
-#define  LP_ENAB_0	0x0000000000000001UL
-
-/* ASI_CORE_RUNNING - shared */
-#define LP_RUNNING_RW	0x0000000000000050UL
-#define LP_RUNNING_W1S	0x0000000000000060UL
-#define LP_RUNNING_W1C	0x0000000000000068UL
-#define  LP_RUNNING_1	0x0000000000000002UL
-#define  LP_RUNNING_0	0x0000000000000001UL
-
-/* ASI_CORE_RUNNING_STAT - shared */
-#define LP_RUN_STAT	0x0000000000000058UL
-#define  LP_RUN_STAT_1	0x0000000000000002UL
-#define  LP_RUN_STAT_0	0x0000000000000001UL
-
-/* ASI_XIR_STEERING - shared */
-#define LP_XIR_STEER	0x0000000000000030UL
-#define  LP_XIR_STEER_1	0x0000000000000002UL
-#define  LP_XIR_STEER_0	0x0000000000000001UL
-
-/* ASI_CMT_ERROR_STEERING - shared */
-#define CMT_ER_STEER	0x0000000000000040UL
-#define  CMT_ER_STEER_1	0x0000000000000002UL
-#define  CMT_ER_STEER_0	0x0000000000000001UL
-
-#endif /* _SPARC64_CMT_H */
+#include <asm-sparc/cmt.h>
diff --git a/include/asm-sparc64/compat.h b/include/asm-sparc64/compat.h
index f260b58..8c155d2 100644
--- a/include/asm-sparc64/compat.h
+++ b/include/asm-sparc64/compat.h
@@ -1,243 +1 @@
-#ifndef _ASM_SPARC64_COMPAT_H
-#define _ASM_SPARC64_COMPAT_H
-/*
- * Architecture specific compatibility types
- */
-#include <linux/types.h>
-
-#define COMPAT_USER_HZ	100
-
-typedef u32		compat_size_t;
-typedef s32		compat_ssize_t;
-typedef s32		compat_time_t;
-typedef s32		compat_clock_t;
-typedef s32		compat_pid_t;
-typedef u16		__compat_uid_t;
-typedef u16		__compat_gid_t;
-typedef u32		__compat_uid32_t;
-typedef u32		__compat_gid32_t;
-typedef u16		compat_mode_t;
-typedef u32		compat_ino_t;
-typedef u16		compat_dev_t;
-typedef s32		compat_off_t;
-typedef s64		compat_loff_t;
-typedef s16		compat_nlink_t;
-typedef u16		compat_ipc_pid_t;
-typedef s32		compat_daddr_t;
-typedef u32		compat_caddr_t;
-typedef __kernel_fsid_t	compat_fsid_t;
-typedef s32		compat_key_t;
-typedef s32		compat_timer_t;
-
-typedef s32		compat_int_t;
-typedef s32		compat_long_t;
-typedef s64		compat_s64;
-typedef u32		compat_uint_t;
-typedef u32		compat_ulong_t;
-typedef u64		compat_u64;
-
-struct compat_timespec {
-	compat_time_t	tv_sec;
-	s32		tv_nsec;
-};
-
-struct compat_timeval {
-	compat_time_t	tv_sec;
-	s32		tv_usec;
-};
-
-struct compat_stat {
-	compat_dev_t	st_dev;
-	compat_ino_t	st_ino;
-	compat_mode_t	st_mode;
-	compat_nlink_t	st_nlink;
-	__compat_uid_t	st_uid;
-	__compat_gid_t	st_gid;
-	compat_dev_t	st_rdev;
-	compat_off_t	st_size;
-	compat_time_t	st_atime;
-	compat_ulong_t	st_atime_nsec;
-	compat_time_t	st_mtime;
-	compat_ulong_t	st_mtime_nsec;
-	compat_time_t	st_ctime;
-	compat_ulong_t	st_ctime_nsec;
-	compat_off_t	st_blksize;
-	compat_off_t	st_blocks;
-	u32		__unused4[2];
-};
-
-struct compat_stat64 {
-	unsigned long long	st_dev;
-
-	unsigned long long	st_ino;
-
-	unsigned int	st_mode;
-	unsigned int	st_nlink;
-
-	unsigned int	st_uid;
-	unsigned int	st_gid;
-
-	unsigned long long	st_rdev;
-
-	unsigned char	__pad3[8];
-
-	long long	st_size;
-	unsigned int	st_blksize;
-
-	unsigned char	__pad4[8];
-	unsigned int	st_blocks;
-
-	unsigned int	st_atime;
-	unsigned int	st_atime_nsec;
-
-	unsigned int	st_mtime;
-	unsigned int	st_mtime_nsec;
-
-	unsigned int	st_ctime;
-	unsigned int	st_ctime_nsec;
-
-	unsigned int	__unused4;
-	unsigned int	__unused5;
-};
-
-struct compat_flock {
-	short		l_type;
-	short		l_whence;
-	compat_off_t	l_start;
-	compat_off_t	l_len;
-	compat_pid_t	l_pid;
-	short		__unused;
-};
-
-#define F_GETLK64	12
-#define F_SETLK64	13
-#define F_SETLKW64	14
-
-struct compat_flock64 {
-	short		l_type;
-	short		l_whence;
-	compat_loff_t	l_start;
-	compat_loff_t	l_len;
-	compat_pid_t	l_pid;
-	short		__unused;
-};
-
-struct compat_statfs {
-	int		f_type;
-	int		f_bsize;
-	int		f_blocks;
-	int		f_bfree;
-	int		f_bavail;
-	int		f_files;
-	int		f_ffree;
-	compat_fsid_t	f_fsid;
-	int		f_namelen;	/* SunOS ignores this field. */
-	int		f_frsize;
-	int		f_spare[5];
-};
-
-#define COMPAT_RLIM_INFINITY 0x7fffffff
-
-typedef u32		compat_old_sigset_t;
-
-#define _COMPAT_NSIG		64
-#define _COMPAT_NSIG_BPW	32
-
-typedef u32		compat_sigset_word;
-
-#define COMPAT_OFF_T_MAX	0x7fffffff
-#define COMPAT_LOFF_T_MAX	0x7fffffffffffffffL
-
-/*
- * A pointer passed in from user mode. This should not
- * be used for syscall parameters, just declare them
- * as pointers because the syscall entry code will have
- * appropriately converted them already.
- */
-typedef	u32		compat_uptr_t;
-
-static inline void __user *compat_ptr(compat_uptr_t uptr)
-{
-	return (void __user *)(unsigned long)uptr;
-}
-
-static inline compat_uptr_t ptr_to_compat(void __user *uptr)
-{
-	return (u32)(unsigned long)uptr;
-}
-
-static inline void __user *compat_alloc_user_space(long len)
-{
-	struct pt_regs *regs = current_thread_info()->kregs;
-	unsigned long usp = regs->u_regs[UREG_I6];
-
-	if (!(test_thread_flag(TIF_32BIT)))
-		usp += STACK_BIAS;
-	else
-		usp &= 0xffffffffUL;
-
-	usp -= len;
-	usp &= ~0x7UL;
-
-	return (void __user *) usp;
-}
-
-struct compat_ipc64_perm {
-	compat_key_t key;
-	__compat_uid32_t uid;
-	__compat_gid32_t gid;
-	__compat_uid32_t cuid;
-	__compat_gid32_t cgid;
-	unsigned short __pad1;
-	compat_mode_t mode;
-	unsigned short __pad2;
-	unsigned short seq;
-	unsigned long __unused1;	/* yes they really are 64bit pads */
-	unsigned long __unused2;
-};
-
-struct compat_semid64_ds {
-	struct compat_ipc64_perm sem_perm;
-	unsigned int	__pad1;
-	compat_time_t	sem_otime;
-	unsigned int	__pad2;
-	compat_time_t	sem_ctime;
-	u32		sem_nsems;
-	u32		__unused1;
-	u32		__unused2;
-};
-
-struct compat_msqid64_ds {
-	struct compat_ipc64_perm msg_perm;
-	unsigned int	__pad1;
-	compat_time_t	msg_stime;
-	unsigned int	__pad2;
-	compat_time_t	msg_rtime;
-	unsigned int	__pad3;
-	compat_time_t	msg_ctime;
-	unsigned int	msg_cbytes;
-	unsigned int	msg_qnum;
-	unsigned int	msg_qbytes;
-	compat_pid_t	msg_lspid;
-	compat_pid_t	msg_lrpid;
-	unsigned int	__unused1;
-	unsigned int	__unused2;
-};
-
-struct compat_shmid64_ds {
-	struct compat_ipc64_perm shm_perm;
-	unsigned int	__pad1;
-	compat_time_t	shm_atime;
-	unsigned int	__pad2;
-	compat_time_t	shm_dtime;
-	unsigned int	__pad3;
-	compat_time_t	shm_ctime;
-	compat_size_t	shm_segsz;
-	compat_pid_t	shm_cpid;
-	compat_pid_t	shm_lpid;
-	unsigned int	shm_nattch;
-	unsigned int	__unused1;
-	unsigned int	__unused2;
-};
-
-#endif /* _ASM_SPARC64_COMPAT_H */
+#include <asm-sparc/compat.h>
diff --git a/include/asm-sparc64/compat_signal.h b/include/asm-sparc64/compat_signal.h
index b759eab..7187dcc 100644
--- a/include/asm-sparc64/compat_signal.h
+++ b/include/asm-sparc64/compat_signal.h
@@ -1,29 +1 @@
-#ifndef _COMPAT_SIGNAL_H
-#define _COMPAT_SIGNAL_H
-
-#include <linux/compat.h>
-#include <asm/signal.h>
-
-#ifdef CONFIG_COMPAT
-struct __new_sigaction32 {
-	unsigned		sa_handler;
-	unsigned int    	sa_flags;
-	unsigned		sa_restorer;     /* not used by Linux/SPARC yet */
-	compat_sigset_t 	sa_mask;
-};
-
-struct __old_sigaction32 {
-	unsigned		sa_handler;
-	compat_old_sigset_t  	sa_mask;
-	unsigned int    	sa_flags;
-	unsigned		sa_restorer;     /* not used by Linux/SPARC yet */
-};
-
-typedef struct sigaltstack32 {
-	u32			ss_sp;
-	int			ss_flags;
-	compat_size_t		ss_size;
-} stack_t32;
-#endif
-
-#endif /* !(_COMPAT_SIGNAL_H) */
+#include <asm-sparc/compat_signal.h>
diff --git a/include/asm-sparc64/cpudata.h b/include/asm-sparc64/cpudata.h
index 532975e..3220e13 100644
--- a/include/asm-sparc64/cpudata.h
+++ b/include/asm-sparc64/cpudata.h
@@ -1,240 +1 @@
-/* cpudata.h: Per-cpu parameters.
- *
- * Copyright (C) 2003, 2005, 2006 David S. Miller (davem@davemloft.net)
- */
-
-#ifndef _SPARC64_CPUDATA_H
-#define _SPARC64_CPUDATA_H
-
-#include <asm/hypervisor.h>
-#include <asm/asi.h>
-
-#ifndef __ASSEMBLY__
-
-#include <linux/percpu.h>
-#include <linux/threads.h>
-
-typedef struct {
-	/* Dcache line 1 */
-	unsigned int	__softirq_pending; /* must be 1st, see rtrap.S */
-	unsigned int	__pad0;
-	unsigned long	clock_tick;	/* %tick's per second */
-	unsigned long	__pad;
-	unsigned int	__pad1;
-	unsigned int	__pad2;
-
-	/* Dcache line 2, rarely used */
-	unsigned int	dcache_size;
-	unsigned int	dcache_line_size;
-	unsigned int	icache_size;
-	unsigned int	icache_line_size;
-	unsigned int	ecache_size;
-	unsigned int	ecache_line_size;
-	int		core_id;
-	int		proc_id;
-} cpuinfo_sparc;
-
-DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data);
-#define cpu_data(__cpu)		per_cpu(__cpu_data, (__cpu))
-#define local_cpu_data()	__get_cpu_var(__cpu_data)
-
-/* Trap handling code needs to get at a few critical values upon
- * trap entry and to process TSB misses.  These cannot be in the
- * per_cpu() area as we really need to lock them into the TLB and
- * thus make them part of the main kernel image.  As a result we
- * try to make this as small as possible.
- *
- * This is padded out and aligned to 64-bytes to avoid false sharing
- * on SMP.
- */
-
-/* If you modify the size of this structure, please update
- * TRAP_BLOCK_SZ_SHIFT below.
- */
-struct thread_info;
-struct trap_per_cpu {
-/* D-cache line 1: Basic thread information, cpu and device mondo queues */
-	struct thread_info	*thread;
-	unsigned long		pgd_paddr;
-	unsigned long		cpu_mondo_pa;
-	unsigned long		dev_mondo_pa;
-
-/* D-cache line 2: Error Mondo Queue and kernel buffer pointers */
-	unsigned long		resum_mondo_pa;
-	unsigned long		resum_kernel_buf_pa;
-	unsigned long		nonresum_mondo_pa;
-	unsigned long		nonresum_kernel_buf_pa;
-
-/* Dcache lines 3, 4, 5, and 6: Hypervisor Fault Status */
-	struct hv_fault_status	fault_info;
-
-/* Dcache line 7: Physical addresses of CPU send mondo block and CPU list.  */
-	unsigned long		cpu_mondo_block_pa;
-	unsigned long		cpu_list_pa;
-	unsigned long		tsb_huge;
-	unsigned long		tsb_huge_temp;
-
-/* Dcache line 8: IRQ work list, and keep trap_block a power-of-2 in size.  */
-	unsigned long		irq_worklist_pa;
-	unsigned int		cpu_mondo_qmask;
-	unsigned int		dev_mondo_qmask;
-	unsigned int		resum_qmask;
-	unsigned int		nonresum_qmask;
-	void			*hdesc;
-} __attribute__((aligned(64)));
-extern struct trap_per_cpu trap_block[NR_CPUS];
-extern void init_cur_cpu_trap(struct thread_info *);
-extern void setup_tba(void);
-extern int ncpus_probed;
-extern void __init cpu_probe(void);
-extern const struct seq_operations cpuinfo_op;
-
-extern unsigned long real_hard_smp_processor_id(void);
-
-struct cpuid_patch_entry {
-	unsigned int	addr;
-	unsigned int	cheetah_safari[4];
-	unsigned int	cheetah_jbus[4];
-	unsigned int	starfire[4];
-	unsigned int	sun4v[4];
-};
-extern struct cpuid_patch_entry __cpuid_patch, __cpuid_patch_end;
-
-struct sun4v_1insn_patch_entry {
-	unsigned int	addr;
-	unsigned int	insn;
-};
-extern struct sun4v_1insn_patch_entry __sun4v_1insn_patch,
-	__sun4v_1insn_patch_end;
-
-struct sun4v_2insn_patch_entry {
-	unsigned int	addr;
-	unsigned int	insns[2];
-};
-extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch,
-	__sun4v_2insn_patch_end;
-
-#endif /* !(__ASSEMBLY__) */
-
-#define TRAP_PER_CPU_THREAD		0x00
-#define TRAP_PER_CPU_PGD_PADDR		0x08
-#define TRAP_PER_CPU_CPU_MONDO_PA	0x10
-#define TRAP_PER_CPU_DEV_MONDO_PA	0x18
-#define TRAP_PER_CPU_RESUM_MONDO_PA	0x20
-#define TRAP_PER_CPU_RESUM_KBUF_PA	0x28
-#define TRAP_PER_CPU_NONRESUM_MONDO_PA	0x30
-#define TRAP_PER_CPU_NONRESUM_KBUF_PA	0x38
-#define TRAP_PER_CPU_FAULT_INFO		0x40
-#define TRAP_PER_CPU_CPU_MONDO_BLOCK_PA	0xc0
-#define TRAP_PER_CPU_CPU_LIST_PA	0xc8
-#define TRAP_PER_CPU_TSB_HUGE		0xd0
-#define TRAP_PER_CPU_TSB_HUGE_TEMP	0xd8
-#define TRAP_PER_CPU_IRQ_WORKLIST_PA	0xe0
-#define TRAP_PER_CPU_CPU_MONDO_QMASK	0xe8
-#define TRAP_PER_CPU_DEV_MONDO_QMASK	0xec
-#define TRAP_PER_CPU_RESUM_QMASK	0xf0
-#define TRAP_PER_CPU_NONRESUM_QMASK	0xf4
-
-#define TRAP_BLOCK_SZ_SHIFT		8
-
-#include <asm/scratchpad.h>
-
-#define __GET_CPUID(REG)				\
-	/* Spitfire implementation (default). */	\
-661:	ldxa		[%g0] ASI_UPA_CONFIG, REG;	\
-	srlx		REG, 17, REG;			\
-	 and		REG, 0x1f, REG;			\
-	nop;						\
-	.section	.cpuid_patch, "ax";		\
-	/* Instruction location. */			\
-	.word		661b;				\
-	/* Cheetah Safari implementation. */		\
-	ldxa		[%g0] ASI_SAFARI_CONFIG, REG;	\
-	srlx		REG, 17, REG;			\
-	and		REG, 0x3ff, REG;		\
-	nop;						\
-	/* Cheetah JBUS implementation. */		\
-	ldxa		[%g0] ASI_JBUS_CONFIG, REG;	\
-	srlx		REG, 17, REG;			\
-	and		REG, 0x1f, REG;			\
-	nop;						\
-	/* Starfire implementation. */			\
-	sethi		%hi(0x1fff40000d0 >> 9), REG;	\
-	sllx		REG, 9, REG;			\
-	or		REG, 0xd0, REG;			\
-	lduwa		[REG] ASI_PHYS_BYPASS_EC_E, REG;\
-	/* sun4v implementation. */			\
-	mov		SCRATCHPAD_CPUID, REG;		\
-	ldxa		[REG] ASI_SCRATCHPAD, REG;	\
-	nop;						\
-	nop;						\
-	.previous;
-
-#ifdef CONFIG_SMP
-
-#define TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
-	__GET_CPUID(TMP)			\
-	sethi	%hi(trap_block), DEST;		\
-	sllx	TMP, TRAP_BLOCK_SZ_SHIFT, TMP;	\
-	or	DEST, %lo(trap_block), DEST;	\
-	add	DEST, TMP, DEST;		\
-
-/* Clobbers TMP, current address space PGD phys address into DEST.  */
-#define TRAP_LOAD_PGD_PHYS(DEST, TMP)		\
-	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
-	ldx	[DEST + TRAP_PER_CPU_PGD_PADDR], DEST;
-
-/* Clobbers TMP, loads local processor's IRQ work area into DEST.  */
-#define TRAP_LOAD_IRQ_WORK_PA(DEST, TMP)	\
-	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
-	add	DEST, TRAP_PER_CPU_IRQ_WORKLIST_PA, DEST;
-
-/* Clobbers TMP, loads DEST with current thread info pointer.  */
-#define TRAP_LOAD_THREAD_REG(DEST, TMP)		\
-	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
-	ldx	[DEST + TRAP_PER_CPU_THREAD], DEST;
-
-/* Given the current thread info pointer in THR, load the per-cpu
- * area base of the current processor into DEST.  REG1, REG2, and REG3 are
- * clobbered.
- *
- * You absolutely cannot use DEST as a temporary in this code.  The
- * reason is that traps can happen during execution, and return from
- * trap will load the fully resolved DEST per-cpu base.  This can corrupt
- * the calculations done by the macro mid-stream.
- */
-#define LOAD_PER_CPU_BASE(DEST, THR, REG1, REG2, REG3)	\
-	lduh	[THR + TI_CPU], REG1;			\
-	sethi	%hi(__per_cpu_shift), REG3;		\
-	sethi	%hi(__per_cpu_base), REG2;		\
-	ldx	[REG3 + %lo(__per_cpu_shift)], REG3;	\
-	ldx	[REG2 + %lo(__per_cpu_base)], REG2;	\
-	sllx	REG1, REG3, REG3;			\
-	add	REG3, REG2, DEST;
-
-#else
-
-#define TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
-	sethi	%hi(trap_block), DEST;		\
-	or	DEST, %lo(trap_block), DEST;	\
-
-/* Uniprocessor versions, we know the cpuid is zero.  */
-#define TRAP_LOAD_PGD_PHYS(DEST, TMP)		\
-	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
-	ldx	[DEST + TRAP_PER_CPU_PGD_PADDR], DEST;
-
-/* Clobbers TMP, loads local processor's IRQ work area into DEST.  */
-#define TRAP_LOAD_IRQ_WORK_PA(DEST, TMP)	\
-	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
-	add	DEST, TRAP_PER_CPU_IRQ_WORKLIST_PA, DEST;
-
-#define TRAP_LOAD_THREAD_REG(DEST, TMP)		\
-	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
-	ldx	[DEST + TRAP_PER_CPU_THREAD], DEST;
-
-/* No per-cpu areas on uniprocessor, so no need to load DEST.  */
-#define LOAD_PER_CPU_BASE(DEST, THR, REG1, REG2, REG3)
-
-#endif /* !(CONFIG_SMP) */
-
-#endif /* _SPARC64_CPUDATA_H */
+#include <asm-sparc/cpudata.h>
diff --git a/include/asm-sparc64/dcr.h b/include/asm-sparc64/dcr.h
index 620c9ba6..d67613b 100644
--- a/include/asm-sparc64/dcr.h
+++ b/include/asm-sparc64/dcr.h
@@ -1,14 +1 @@
-#ifndef _SPARC64_DCR_H
-#define _SPARC64_DCR_H
-
-/* UltraSparc-III/III+ Dispatch Control Register, ASR 0x12 */
-#define DCR_DPE		0x0000000000001000 /* III+: D$ Parity Error Enable	*/
-#define DCR_OBS		0x0000000000000fc0 /* Observability Bus Controls	*/
-#define DCR_BPE		0x0000000000000020 /* Branch Predict Enable		*/
-#define DCR_RPE		0x0000000000000010 /* Return Address Prediction Enable	*/
-#define DCR_SI		0x0000000000000008 /* Single Instruction Disable	*/
-#define DCR_IPE		0x0000000000000004 /* III+: I$ Parity Error Enable	*/
-#define DCR_IFPOE	0x0000000000000002 /* IRQ FP Operation Enable		*/
-#define DCR_MS		0x0000000000000001 /* Multi-Scalar dispatch		*/
-
-#endif /* _SPARC64_DCR_H */
+#include <asm-sparc/dcr.h>
diff --git a/include/asm-sparc64/dcu.h b/include/asm-sparc64/dcu.h
index 0f704e10..28853f4 100644
--- a/include/asm-sparc64/dcu.h
+++ b/include/asm-sparc64/dcu.h
@@ -1,27 +1 @@
-#ifndef _SPARC64_DCU_H
-#define _SPARC64_DCU_H
-
-#include <linux/const.h>
-
-/* UltraSparc-III Data Cache Unit Control Register */
-#define DCU_CP	_AC(0x0002000000000000,UL) /* Phys Cache Enable w/o mmu	*/
-#define DCU_CV	_AC(0x0001000000000000,UL) /* Virt Cache Enable w/o mmu	*/
-#define DCU_ME	_AC(0x0000800000000000,UL) /* NC-store Merging Enable	*/
-#define DCU_RE	_AC(0x0000400000000000,UL) /* RAW bypass Enable		*/
-#define DCU_PE	_AC(0x0000200000000000,UL) /* PCache Enable		*/
-#define DCU_HPE	_AC(0x0000100000000000,UL) /* HW prefetch Enable	*/
-#define DCU_SPE	_AC(0x0000080000000000,UL) /* SW prefetch Enable	*/
-#define DCU_SL	_AC(0x0000040000000000,UL) /* Secondary ld-steering Enab*/
-#define DCU_WE	_AC(0x0000020000000000,UL) /* WCache enable		*/
-#define DCU_PM	_AC(0x000001fe00000000,UL) /* PA Watchpoint Byte Mask	*/
-#define DCU_VM	_AC(0x00000001fe000000,UL) /* VA Watchpoint Byte Mask	*/
-#define DCU_PR	_AC(0x0000000001000000,UL) /* PA Watchpoint Read Enable	*/
-#define DCU_PW	_AC(0x0000000000800000,UL) /* PA Watchpoint Write Enable*/
-#define DCU_VR	_AC(0x0000000000400000,UL) /* VA Watchpoint Read Enable	*/
-#define DCU_VW	_AC(0x0000000000200000,UL) /* VA Watchpoint Write Enable*/
-#define DCU_DM	_AC(0x0000000000000008,UL) /* DMMU Enable		*/
-#define DCU_IM	_AC(0x0000000000000004,UL) /* IMMU Enable		*/
-#define DCU_DC	_AC(0x0000000000000002,UL) /* Data Cache Enable		*/
-#define DCU_IC	_AC(0x0000000000000001,UL) /* Instruction Cache Enable	*/
-
-#endif /* _SPARC64_DCU_H */
+#include <asm-sparc/dcu.h>
diff --git a/include/asm-sparc64/delay.h b/include/asm-sparc64/delay.h
index a77aa62..33dc558 100644
--- a/include/asm-sparc64/delay.h
+++ b/include/asm-sparc64/delay.h
@@ -1,17 +1 @@
-/* delay.h: Linux delay routines on sparc64.
- *
- * Copyright (C) 1996, 2004, 2007 David S. Miller (davem@davemloft.net).
- */
-
-#ifndef _SPARC64_DELAY_H
-#define _SPARC64_DELAY_H
-
-#ifndef __ASSEMBLY__
-
-extern void __delay(unsigned long loops);
-extern void udelay(unsigned long usecs);
-#define mdelay(n)	udelay((n) * 1000)
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* _SPARC64_DELAY_H */
+#include <asm-sparc/delay.h>
diff --git a/include/asm-sparc64/display7seg.h b/include/asm-sparc64/display7seg.h
index c066a89..e74f046 100644
--- a/include/asm-sparc64/display7seg.h
+++ b/include/asm-sparc64/display7seg.h
@@ -1,79 +1 @@
-/*
- *
- * display7seg - Driver interface for the 7-segment display
- * present on Sun Microsystems CP1400 and CP1500
- *
- * Copyright (c) 2000 Eric Brower <ebrower@usa.net>
- *
- */
-
-#ifndef __display7seg_h__
-#define __display7seg_h__
-
-#define D7S_IOC	'p'
-
-#define D7SIOCRD _IOR(D7S_IOC, 0x45, int)	/* Read device state	*/
-#define D7SIOCWR _IOW(D7S_IOC, 0x46, int)	/* Write device state	*/
-#define D7SIOCTM _IO (D7S_IOC, 0x47)		/* Translate mode (FLIP)*/
-
-/*
- * ioctl flag definitions
- *
- * POINT	- Toggle decimal point	(0=absent 1=present)
- * ALARM	- Toggle alarm LED 		(0=green  1=red)
- * FLIP		- Toggle inverted mode 	(0=normal 1=flipped) 
- * bits 0-4	- Character displayed	(see definitions below)
- *
- * Display segments are defined as follows, 
- * subject to D7S_FLIP register state:
- *
- *    a
- *   ---
- * f|   |b
- *   -g-
- * e|   |c
- *   ---
- *    d
- */
-
-#define D7S_POINT	(1 << 7)	/* Decimal point*/
-#define D7S_ALARM	(1 << 6)	/* Alarm LED 	*/
-#define D7S_FLIP	(1 << 5)	/* Flip display */
-
-#define D7S_0		0x00		/* Numerals 0-9 */
-#define D7S_1		0x01
-#define D7S_2		0x02
-#define D7S_3		0x03
-#define D7S_4		0x04
-#define D7S_5		0x05
-#define D7S_6		0x06
-#define D7S_7		0x07
-#define D7S_8		0x08
-#define D7S_9		0x09
-#define D7S_A		0x0A		/* Letters A-F, H, L, P */
-#define D7S_B		0x0B
-#define D7S_C		0x0C
-#define D7S_D		0x0D
-#define D7S_E		0x0E
-#define D7S_F		0x0F
-#define D7S_H		0x10
-#define D7S_E2		0x11
-#define D7S_L		0x12
-#define D7S_P		0x13
-#define D7S_SEGA	0x14		/* Individual segments */
-#define D7S_SEGB	0x15
-#define D7S_SEGC	0x16
-#define D7S_SEGD	0x17
-#define D7S_SEGE	0x18
-#define D7S_SEGF	0x19
-#define D7S_SEGG	0x1A
-#define D7S_SEGABFG 0x1B		/* Segment groupings */
-#define D7S_SEGCDEG	0x1C
-#define D7S_SEGBCEF 0x1D
-#define D7S_SEGADG	0x1E
-#define D7S_BLANK	0x1F		/* Clear all segments */
-
-#define D7S_MIN_VAL	0x0
-#define D7S_MAX_VAL	0x1F
-
-#endif /* ifndef __display7seg_h__ */
+#include <asm-sparc/display7seg.h>
diff --git a/include/asm-sparc64/dma-mapping.h b/include/asm-sparc64/dma-mapping.h
index 38cbec7..380b7b6 100644
--- a/include/asm-sparc64/dma-mapping.h
+++ b/include/asm-sparc64/dma-mapping.h
@@ -1,154 +1 @@
-#ifndef _ASM_SPARC64_DMA_MAPPING_H
-#define _ASM_SPARC64_DMA_MAPPING_H
-
-#include <linux/scatterlist.h>
-#include <linux/mm.h>
-
-#define DMA_ERROR_CODE	(~(dma_addr_t)0x0)
-
-struct dma_ops {
-	void *(*alloc_coherent)(struct device *dev, size_t size,
-				dma_addr_t *dma_handle, gfp_t flag);
-	void (*free_coherent)(struct device *dev, size_t size,
-			      void *cpu_addr, dma_addr_t dma_handle);
-	dma_addr_t (*map_single)(struct device *dev, void *cpu_addr,
-				 size_t size,
-				 enum dma_data_direction direction);
-	void (*unmap_single)(struct device *dev, dma_addr_t dma_addr,
-			     size_t size,
-			     enum dma_data_direction direction);
-	int (*map_sg)(struct device *dev, struct scatterlist *sg, int nents,
-		      enum dma_data_direction direction);
-	void (*unmap_sg)(struct device *dev, struct scatterlist *sg,
-			 int nhwentries,
-			 enum dma_data_direction direction);
-	void (*sync_single_for_cpu)(struct device *dev,
-				    dma_addr_t dma_handle, size_t size,
-				    enum dma_data_direction direction);
-	void (*sync_sg_for_cpu)(struct device *dev, struct scatterlist *sg,
-				int nelems,
-				enum dma_data_direction direction);
-};
-extern const struct dma_ops *dma_ops;
-
-extern int dma_supported(struct device *dev, u64 mask);
-extern int dma_set_mask(struct device *dev, u64 dma_mask);
-
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-				       dma_addr_t *dma_handle, gfp_t flag)
-{
-	return dma_ops->alloc_coherent(dev, size, dma_handle, flag);
-}
-
-static inline void dma_free_coherent(struct device *dev, size_t size,
-				     void *cpu_addr, dma_addr_t dma_handle)
-{
-	dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
-}
-
-static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
-					size_t size,
-					enum dma_data_direction direction)
-{
-	return dma_ops->map_single(dev, cpu_addr, size, direction);
-}
-
-static inline void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
-				    size_t size,
-				    enum dma_data_direction direction)
-{
-	dma_ops->unmap_single(dev, dma_addr, size, direction);
-}
-
-static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
-				      unsigned long offset, size_t size,
-				      enum dma_data_direction direction)
-{
-	return dma_ops->map_single(dev, page_address(page) + offset,
-				   size, direction);
-}
-
-static inline void dma_unmap_page(struct device *dev, dma_addr_t dma_address,
-				  size_t size,
-				  enum dma_data_direction direction)
-{
-	dma_ops->unmap_single(dev, dma_address, size, direction);
-}
-
-static inline int dma_map_sg(struct device *dev, struct scatterlist *sg,
-			     int nents, enum dma_data_direction direction)
-{
-	return dma_ops->map_sg(dev, sg, nents, direction);
-}
-
-static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
-				int nents, enum dma_data_direction direction)
-{
-	dma_ops->unmap_sg(dev, sg, nents, direction);
-}
-
-static inline void dma_sync_single_for_cpu(struct device *dev,
-					   dma_addr_t dma_handle, size_t size,
-					   enum dma_data_direction direction)
-{
-	dma_ops->sync_single_for_cpu(dev, dma_handle, size, direction);
-}
-
-static inline void dma_sync_single_for_device(struct device *dev,
-					      dma_addr_t dma_handle,
-					      size_t size,
-					      enum dma_data_direction direction)
-{
-	/* No flushing needed to sync cpu writes to the device.  */
-}
-
-static inline void dma_sync_single_range_for_cpu(struct device *dev,
-						 dma_addr_t dma_handle,
-						 unsigned long offset,
-						 size_t size,
-						 enum dma_data_direction direction)
-{
-	dma_sync_single_for_cpu(dev, dma_handle+offset, size, direction);
-}
-
-static inline void dma_sync_single_range_for_device(struct device *dev,
-						    dma_addr_t dma_handle,
-						    unsigned long offset,
-						    size_t size,
-						    enum dma_data_direction direction)
-{
-	/* No flushing needed to sync cpu writes to the device.  */
-}
-
-
-static inline void dma_sync_sg_for_cpu(struct device *dev,
-				       struct scatterlist *sg, int nelems,
-				       enum dma_data_direction direction)
-{
-	dma_ops->sync_sg_for_cpu(dev, sg, nelems, direction);
-}
-
-static inline void dma_sync_sg_for_device(struct device *dev,
-					  struct scatterlist *sg, int nelems,
-					  enum dma_data_direction direction)
-{
-	/* No flushing needed to sync cpu writes to the device.  */
-}
-
-static inline int dma_mapping_error(dma_addr_t dma_addr)
-{
-	return (dma_addr == DMA_ERROR_CODE);
-}
-
-static inline int dma_get_cache_alignment(void)
-{
-	/* no easy way to get cache size on all processors, so return
-	 * the maximum possible, to be safe */
-	return (1 << INTERNODE_CACHE_SHIFT);
-}
-
-#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
-#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
-#define dma_is_consistent(d, h)	(1)
-
-#endif /* _ASM_SPARC64_DMA_MAPPING_H */
+#include <asm-sparc/dma-mapping.h>
diff --git a/include/asm-sparc64/dma.h b/include/asm-sparc64/dma.h
index 9d4c024..2e36248 100644
--- a/include/asm-sparc64/dma.h
+++ b/include/asm-sparc64/dma.h
@@ -1,205 +1 @@
-/*
- * include/asm-sparc64/dma.h
- *
- * Copyright 1996 (C) David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef _ASM_SPARC64_DMA_H
-#define _ASM_SPARC64_DMA_H
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/spinlock.h>
-
-#include <asm/sbus.h>
-#include <asm/delay.h>
-#include <asm/oplib.h>
-
-/* These are irrelevant for Sparc DMA, but we leave it in so that
- * things can compile.
- */
-#define MAX_DMA_CHANNELS 8
-#define DMA_MODE_READ    1
-#define DMA_MODE_WRITE   2
-#define MAX_DMA_ADDRESS  (~0UL)
-
-/* Useful constants */
-#define SIZE_16MB      (16*1024*1024)
-#define SIZE_64K       (64*1024)
-
-/* SBUS DMA controller reg offsets */
-#define DMA_CSR		0x00UL		/* rw  DMA control/status register    0x00   */
-#define DMA_ADDR	0x04UL		/* rw  DMA transfer address register  0x04   */
-#define DMA_COUNT	0x08UL		/* rw  DMA transfer count register    0x08   */
-#define DMA_TEST	0x0cUL		/* rw  DMA test/debug register        0x0c   */
-
-/* DVMA chip revisions */
-enum dvma_rev {
-	dvmarev0,
-	dvmaesc1,
-	dvmarev1,
-	dvmarev2,
-	dvmarev3,
-	dvmarevplus,
-	dvmahme
-};
-
-#define DMA_HASCOUNT(rev)  ((rev)==dvmaesc1)
-
-/* Linux DMA information structure, filled during probe. */
-struct sbus_dma {
-	struct sbus_dma *next;
-	struct sbus_dev *sdev;
-	void __iomem *regs;
-
-	/* Status, misc info */
-	int node;                /* Prom node for this DMA device */
-	int running;             /* Are we doing DMA now? */
-	int allocated;           /* Are we "owned" by anyone yet? */
-
-	/* Transfer information. */
-	u32 addr;                /* Start address of current transfer */
-	int nbytes;              /* Size of current transfer */
-	int realbytes;           /* For splitting up large transfers, etc. */
-
-	/* DMA revision */
-	enum dvma_rev revision;
-};
-
-extern struct sbus_dma *dma_chain;
-
-/* Broken hardware... */
-#define DMA_ISBROKEN(dma)    ((dma)->revision == dvmarev1)
-#define DMA_ISESC1(dma)      ((dma)->revision == dvmaesc1)
-
-/* Main routines in dma.c */
-extern void dvma_init(struct sbus_bus *);
-
-/* Fields in the cond_reg register */
-/* First, the version identification bits */
-#define DMA_DEVICE_ID    0xf0000000        /* Device identification bits */
-#define DMA_VERS0        0x00000000        /* Sunray DMA version */
-#define DMA_ESCV1        0x40000000        /* DMA ESC Version 1 */
-#define DMA_VERS1        0x80000000        /* DMA rev 1 */
-#define DMA_VERS2        0xa0000000        /* DMA rev 2 */
-#define DMA_VERHME       0xb0000000        /* DMA hme gate array */
-#define DMA_VERSPLUS     0x90000000        /* DMA rev 1 PLUS */
-
-#define DMA_HNDL_INTR    0x00000001        /* An IRQ needs to be handled */
-#define DMA_HNDL_ERROR   0x00000002        /* We need to take an error */
-#define DMA_FIFO_ISDRAIN 0x0000000c        /* The DMA FIFO is draining */
-#define DMA_INT_ENAB     0x00000010        /* Turn on interrupts */
-#define DMA_FIFO_INV     0x00000020        /* Invalidate the FIFO */
-#define DMA_ACC_SZ_ERR   0x00000040        /* The access size was bad */
-#define DMA_FIFO_STDRAIN 0x00000040        /* DMA_VERS1 Drain the FIFO */
-#define DMA_RST_SCSI     0x00000080        /* Reset the SCSI controller */
-#define DMA_RST_ENET     DMA_RST_SCSI      /* Reset the ENET controller */
-#define DMA_ST_WRITE     0x00000100        /* write from device to memory */
-#define DMA_ENABLE       0x00000200        /* Fire up DMA, handle requests */
-#define DMA_PEND_READ    0x00000400        /* DMA_VERS1/0/PLUS Pending Read */
-#define DMA_ESC_BURST    0x00000800        /* 1=16byte 0=32byte */
-#define DMA_READ_AHEAD   0x00001800        /* DMA read ahead partial longword */
-#define DMA_DSBL_RD_DRN  0x00001000        /* No EC drain on slave reads */
-#define DMA_BCNT_ENAB    0x00002000        /* If on, use the byte counter */
-#define DMA_TERM_CNTR    0x00004000        /* Terminal counter */
-#define DMA_SCSI_SBUS64  0x00008000        /* HME: Enable 64-bit SBUS mode. */
-#define DMA_CSR_DISAB    0x00010000        /* No FIFO drains during csr */
-#define DMA_SCSI_DISAB   0x00020000        /* No FIFO drains during reg */
-#define DMA_DSBL_WR_INV  0x00020000        /* No EC inval. on slave writes */
-#define DMA_ADD_ENABLE   0x00040000        /* Special ESC DVMA optimization */
-#define DMA_E_BURSTS	 0x000c0000	   /* ENET: SBUS r/w burst mask */
-#define DMA_E_BURST32	 0x00040000	   /* ENET: SBUS 32 byte r/w burst */
-#define DMA_E_BURST16	 0x00000000	   /* ENET: SBUS 16 byte r/w burst */
-#define DMA_BRST_SZ      0x000c0000        /* SCSI: SBUS r/w burst size */
-#define DMA_BRST64       0x000c0000        /* SCSI: 64byte bursts (HME on UltraSparc only) */
-#define DMA_BRST32       0x00040000        /* SCSI: 32byte bursts */
-#define DMA_BRST16       0x00000000        /* SCSI: 16byte bursts */
-#define DMA_BRST0        0x00080000        /* SCSI: no bursts (non-HME gate arrays) */
-#define DMA_ADDR_DISAB   0x00100000        /* No FIFO drains during addr */
-#define DMA_2CLKS        0x00200000        /* Each transfer = 2 clock ticks */
-#define DMA_3CLKS        0x00400000        /* Each transfer = 3 clock ticks */
-#define DMA_EN_ENETAUI   DMA_3CLKS         /* Put lance into AUI-cable mode */
-#define DMA_CNTR_DISAB   0x00800000        /* No IRQ when DMA_TERM_CNTR set */
-#define DMA_AUTO_NADDR   0x01000000        /* Use "auto nxt addr" feature */
-#define DMA_SCSI_ON      0x02000000        /* Enable SCSI dma */
-#define DMA_PARITY_OFF   0x02000000        /* HME: disable parity checking */
-#define DMA_LOADED_ADDR  0x04000000        /* Address has been loaded */
-#define DMA_LOADED_NADDR 0x08000000        /* Next address has been loaded */
-#define DMA_RESET_FAS366 0x08000000        /* HME: Assert RESET to FAS366 */
-
-/* Values describing the burst-size property from the PROM */
-#define DMA_BURST1       0x01
-#define DMA_BURST2       0x02
-#define DMA_BURST4       0x04
-#define DMA_BURST8       0x08
-#define DMA_BURST16      0x10
-#define DMA_BURST32      0x20
-#define DMA_BURST64      0x40
-#define DMA_BURSTBITS    0x7f
-
-/* Determine highest possible final transfer address given a base */
-#define DMA_MAXEND(addr) (0x01000000UL-(((unsigned long)(addr))&0x00ffffffUL))
-
-/* Yes, I hack a lot of elisp in my spare time... */
-#define DMA_ERROR_P(regs)  ((sbus_readl((regs) + DMA_CSR) & DMA_HNDL_ERROR))
-#define DMA_IRQ_P(regs)    ((sbus_readl((regs) + DMA_CSR)) & (DMA_HNDL_INTR | DMA_HNDL_ERROR))
-#define DMA_WRITE_P(regs)  ((sbus_readl((regs) + DMA_CSR) & DMA_ST_WRITE))
-#define DMA_OFF(__regs)		\
-do {	u32 tmp = sbus_readl((__regs) + DMA_CSR); \
-	tmp &= ~DMA_ENABLE; \
-	sbus_writel(tmp, (__regs) + DMA_CSR); \
-} while(0)
-#define DMA_INTSOFF(__regs)	\
-do {	u32 tmp = sbus_readl((__regs) + DMA_CSR); \
-	tmp &= ~DMA_INT_ENAB; \
-	sbus_writel(tmp, (__regs) + DMA_CSR); \
-} while(0)
-#define DMA_INTSON(__regs)	\
-do {	u32 tmp = sbus_readl((__regs) + DMA_CSR); \
-	tmp |= DMA_INT_ENAB; \
-	sbus_writel(tmp, (__regs) + DMA_CSR); \
-} while(0)
-#define DMA_PUNTFIFO(__regs)	\
-do {	u32 tmp = sbus_readl((__regs) + DMA_CSR); \
-	tmp |= DMA_FIFO_INV; \
-	sbus_writel(tmp, (__regs) + DMA_CSR); \
-} while(0)
-#define DMA_SETSTART(__regs, __addr)	\
-	sbus_writel((u32)(__addr), (__regs) + DMA_ADDR);
-#define DMA_BEGINDMA_W(__regs)	\
-do {	u32 tmp = sbus_readl((__regs) + DMA_CSR); \
-	tmp |= (DMA_ST_WRITE|DMA_ENABLE|DMA_INT_ENAB); \
-	sbus_writel(tmp, (__regs) + DMA_CSR); \
-} while(0)
-#define DMA_BEGINDMA_R(__regs)	\
-do {	u32 tmp = sbus_readl((__regs) + DMA_CSR); \
-	tmp |= (DMA_ENABLE|DMA_INT_ENAB); \
-	tmp &= ~DMA_ST_WRITE; \
-	sbus_writel(tmp, (__regs) + DMA_CSR); \
-} while(0)
-
-/* For certain DMA chips, we need to disable ints upon irq entry
- * and turn them back on when we are done.  So in any ESP interrupt
- * handler you *must* call DMA_IRQ_ENTRY upon entry and DMA_IRQ_EXIT
- * when leaving the handler.  You have been warned...
- */
-#define DMA_IRQ_ENTRY(dma, dregs) do { \
-        if(DMA_ISBROKEN(dma)) DMA_INTSOFF(dregs); \
-   } while (0)
-
-#define DMA_IRQ_EXIT(dma, dregs) do { \
-	if(DMA_ISBROKEN(dma)) DMA_INTSON(dregs); \
-   } while(0)
-
-#define for_each_dvma(dma) \
-        for((dma) = dma_chain; (dma); (dma) = (dma)->next)
-
-/* From PCI */
-
-#ifdef CONFIG_PCI
-extern int isa_dma_bridge_buggy;
-#else
-#define isa_dma_bridge_buggy 	(0)
-#endif
-
-#endif /* !(_ASM_SPARC64_DMA_H) */
+#include <asm-sparc/dma.h>
diff --git a/include/asm-sparc64/ebus.h b/include/asm-sparc64/ebus.h
index fcc62b9..d7d4761 100644
--- a/include/asm-sparc64/ebus.h
+++ b/include/asm-sparc64/ebus.h
@@ -1,94 +1 @@
-/*
- * ebus.h: PCI to Ebus pseudo driver software state.
- *
- * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- */
-
-#ifndef __SPARC64_EBUS_H
-#define __SPARC64_EBUS_H
-
-#include <asm/oplib.h>
-#include <asm/prom.h>
-#include <asm/of_device.h>
-
-struct linux_ebus_child {
-	struct linux_ebus_child		*next;
-	struct linux_ebus_device	*parent;
-	struct linux_ebus		*bus;
-	struct device_node		*prom_node;
-	struct resource			 resource[PROMREG_MAX];
-	int				 num_addrs;
-	unsigned int			 irqs[PROMINTR_MAX];
-	int				 num_irqs;
-};
-
-struct linux_ebus_device {
-	struct of_device		ofdev;
-	struct linux_ebus_device	*next;
-	struct linux_ebus_child		*children;
-	struct linux_ebus		*bus;
-	struct device_node		*prom_node;
-	struct resource			 resource[PROMREG_MAX];
-	int				 num_addrs;
-	unsigned int			 irqs[PROMINTR_MAX];
-	int				 num_irqs;
-};
-#define to_ebus_device(d) container_of(d, struct linux_ebus_device, ofdev.dev)
-
-struct linux_ebus {
-	struct of_device		ofdev;
-	struct linux_ebus		*next;
-	struct linux_ebus_device	*devices;
-	struct pci_dev			*self;
-	int				 index;
-	int				 is_rio;
-	struct device_node		*prom_node;
-};
-#define to_ebus(d) container_of(d, struct linux_ebus, ofdev.dev)
-
-struct ebus_dma_info {
-	spinlock_t	lock;
-	void __iomem	*regs;
-
-	unsigned int	flags;
-#define EBUS_DMA_FLAG_USE_EBDMA_HANDLER		0x00000001
-#define EBUS_DMA_FLAG_TCI_DISABLE		0x00000002
-
-	/* These are only valid is EBUS_DMA_FLAG_USE_EBDMA_HANDLER is
-	 * set.
-	 */
-	void (*callback)(struct ebus_dma_info *p, int event, void *cookie);
-	void *client_cookie;
-	unsigned int	irq;
-#define EBUS_DMA_EVENT_ERROR	1
-#define EBUS_DMA_EVENT_DMA	2
-#define EBUS_DMA_EVENT_DEVICE	4
-
-	unsigned char	name[64];
-};
-
-extern int ebus_dma_register(struct ebus_dma_info *p);
-extern int ebus_dma_irq_enable(struct ebus_dma_info *p, int on);
-extern void ebus_dma_unregister(struct ebus_dma_info *p);
-extern int ebus_dma_request(struct ebus_dma_info *p, dma_addr_t bus_addr,
-			    size_t len);
-extern void ebus_dma_prepare(struct ebus_dma_info *p, int write);
-extern unsigned int ebus_dma_residue(struct ebus_dma_info *p);
-extern unsigned int ebus_dma_addr(struct ebus_dma_info *p);
-extern void ebus_dma_enable(struct ebus_dma_info *p, int on);
-
-extern struct linux_ebus		*ebus_chain;
-
-extern void ebus_init(void);
-
-#define for_each_ebus(bus)						\
-        for((bus) = ebus_chain; (bus); (bus) = (bus)->next)
-
-#define for_each_ebusdev(dev, bus)					\
-        for((dev) = (bus)->devices; (dev); (dev) = (dev)->next)
-
-#define for_each_edevchild(dev, child)					\
-        for((child) = (dev)->children; (child); (child) = (child)->next)
-
-#endif /* !(__SPARC64_EBUS_H) */
+#include <asm-sparc/ebus.h>
diff --git a/include/asm-sparc64/elf.h b/include/asm-sparc64/elf.h
index 0818a13..f256d94 100644
--- a/include/asm-sparc64/elf.h
+++ b/include/asm-sparc64/elf.h
@@ -1,217 +1 @@
-#ifndef __ASM_SPARC64_ELF_H
-#define __ASM_SPARC64_ELF_H
-
-/*
- * ELF register definitions..
- */
-
-#include <asm/ptrace.h>
-#include <asm/processor.h>
-#include <asm/uaccess.h>
-#include <asm/spitfire.h>
-
-/*
- * Sparc section types
- */
-#define STT_REGISTER		13
-
-/*
- * Sparc ELF relocation types
- */
-#define	R_SPARC_NONE		0
-#define	R_SPARC_8		1
-#define	R_SPARC_16		2
-#define	R_SPARC_32		3
-#define	R_SPARC_DISP8		4
-#define	R_SPARC_DISP16		5
-#define	R_SPARC_DISP32		6
-#define	R_SPARC_WDISP30		7
-#define	R_SPARC_WDISP22		8
-#define	R_SPARC_HI22		9
-#define	R_SPARC_22		10
-#define	R_SPARC_13		11
-#define	R_SPARC_LO10		12
-#define	R_SPARC_GOT10		13
-#define	R_SPARC_GOT13		14
-#define	R_SPARC_GOT22		15
-#define	R_SPARC_PC10		16
-#define	R_SPARC_PC22		17
-#define	R_SPARC_WPLT30		18
-#define	R_SPARC_COPY		19
-#define	R_SPARC_GLOB_DAT	20
-#define	R_SPARC_JMP_SLOT	21
-#define	R_SPARC_RELATIVE	22
-#define	R_SPARC_UA32		23
-#define R_SPARC_PLT32		24
-#define R_SPARC_HIPLT22		25
-#define R_SPARC_LOPLT10		26
-#define R_SPARC_PCPLT32		27
-#define R_SPARC_PCPLT22		28
-#define R_SPARC_PCPLT10		29
-#define R_SPARC_10		30
-#define R_SPARC_11		31
-#define R_SPARC_64		32
-#define R_SPARC_OLO10		33
-#define R_SPARC_WDISP16		40
-#define R_SPARC_WDISP19		41
-#define R_SPARC_7		43
-#define R_SPARC_5		44
-#define R_SPARC_6		45
-
-/* Bits present in AT_HWCAP, primarily for Sparc32.  */
-
-#define HWCAP_SPARC_FLUSH       1    /* CPU supports flush instruction. */
-#define HWCAP_SPARC_STBAR       2
-#define HWCAP_SPARC_SWAP        4
-#define HWCAP_SPARC_MULDIV      8
-#define HWCAP_SPARC_V9		16
-#define HWCAP_SPARC_ULTRA3	32
-#define HWCAP_SPARC_BLKINIT	64
-#define HWCAP_SPARC_N2		128
-
-#define CORE_DUMP_USE_REGSET
-
-/*
- * These are used to set parameters in the core dumps.
- */
-#define ELF_ARCH		EM_SPARCV9
-#define ELF_CLASS		ELFCLASS64
-#define ELF_DATA		ELFDATA2MSB
-
-/* Format of 64-bit elf_gregset_t is:
- * 	G0 --> G7
- * 	O0 --> O7
- * 	L0 --> L7
- * 	I0 --> I7
- *	TSTATE
- *	TPC
- *	TNPC
- *	Y
- */
-typedef unsigned long elf_greg_t;
-#define ELF_NGREG 36
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-typedef struct {
-	unsigned long	pr_regs[32];
-	unsigned long	pr_fsr;
-	unsigned long	pr_gsr;
-	unsigned long	pr_fprs;
-} elf_fpregset_t;
-
-/* Format of 32-bit elf_gregset_t is:
- * 	G0 --> G7
- *	O0 --> O7
- *	L0 --> L7
- *	I0 --> I7
- *	PSR, PC, nPC, Y, WIM, TBR
- */
-typedef unsigned int compat_elf_greg_t;
-#define COMPAT_ELF_NGREG 38
-typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG];
-
-typedef struct {
-	union {
-		unsigned int	pr_regs[32];
-		unsigned long	pr_dregs[16];
-	} pr_fr;
-	unsigned int __unused;
-	unsigned int	pr_fsr;
-	unsigned char	pr_qcnt;
-	unsigned char	pr_q_entrysize;
-	unsigned char	pr_en;
-	unsigned int	pr_q[64];
-} compat_elf_fpregset_t;
-
-/* UltraSparc extensions.  Still unused, but will be eventually.  */
-typedef struct {
-	unsigned int pr_type;
-	unsigned int pr_align;
-	union {
-		struct {
-			union {
-				unsigned int	pr_regs[32];
-				unsigned long	pr_dregs[16];
-				long double	pr_qregs[8];
-			} pr_xfr;
-		} pr_v8p;
-		unsigned int	pr_xfsr;
-		unsigned int	pr_fprs;
-		unsigned int	pr_xg[8];
-		unsigned int	pr_xo[8];
-		unsigned long	pr_tstate;
-		unsigned int	pr_filler[8];
-	} pr_un;
-} elf_xregset_t;
-
-/*
- * This is used to ensure we don't load something for the wrong architecture.
- */
-#define elf_check_arch(x)		((x)->e_machine == ELF_ARCH)
-#define compat_elf_check_arch(x)	((x)->e_machine == EM_SPARC || \
-					 (x)->e_machine == EM_SPARC32PLUS)
-#define compat_start_thread		start_thread32
-
-#define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE	PAGE_SIZE
-
-/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
-   use of this is to invoke "./ld.so someprog" to test out a new version of
-   the loader.  We need to make sure that it is out of the way of the program
-   that it will "exec", and that there is sufficient room for the brk.  */
-
-#define ELF_ET_DYN_BASE		0x0000010000000000UL
-#define COMPAT_ELF_ET_DYN_BASE	0x0000000070000000UL
-
-
-/* This yields a mask that user programs can use to figure out what
-   instruction set this cpu supports.  */
-
-/* On Ultra, we support all of the v8 capabilities. */
-static inline unsigned int sparc64_elf_hwcap(void)
-{
-	unsigned int cap = (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR |
-			    HWCAP_SPARC_SWAP | HWCAP_SPARC_MULDIV |
-			    HWCAP_SPARC_V9);
-
-	if (tlb_type == cheetah || tlb_type == cheetah_plus)
-		cap |= HWCAP_SPARC_ULTRA3;
-	else if (tlb_type == hypervisor) {
-		if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 ||
-		    sun4v_chip_type == SUN4V_CHIP_NIAGARA2)
-			cap |= HWCAP_SPARC_BLKINIT;
-		if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2)
-			cap |= HWCAP_SPARC_N2;
-	}
-
-	return cap;
-}
-
-#define ELF_HWCAP	sparc64_elf_hwcap();
-
-/* This yields a string that ld.so will use to load implementation
-   specific libraries for optimization.  This is more specific in
-   intent than poking at uname or /proc/cpuinfo.  */
-
-#define ELF_PLATFORM	(NULL)
-
-#define SET_PERSONALITY(ex, ibcs2)			\
-do {	unsigned long new_flags = current_thread_info()->flags; \
-	new_flags &= _TIF_32BIT;			\
-	if ((ex).e_ident[EI_CLASS] == ELFCLASS32)	\
-		new_flags |= _TIF_32BIT;		\
-	else						\
-		new_flags &= ~_TIF_32BIT;		\
-	if ((current_thread_info()->flags & _TIF_32BIT) \
-	    != new_flags)				\
-		set_thread_flag(TIF_ABI_PENDING);	\
-	else						\
-		clear_thread_flag(TIF_ABI_PENDING);	\
-	/* flush_thread will update pgd cache */	\
-	if (ibcs2)					\
-		set_personality(PER_SVR4);		\
-	else if (current->personality != PER_LINUX32)	\
-		set_personality(PER_LINUX);		\
-} while (0)
-
-#endif /* !(__ASM_SPARC64_ELF_H) */
+#include <asm-sparc/elf.h>
diff --git a/include/asm-sparc64/envctrl.h b/include/asm-sparc64/envctrl.h
index a5668a0..a2cc0ca 100644
--- a/include/asm-sparc64/envctrl.h
+++ b/include/asm-sparc64/envctrl.h
@@ -1,103 +1 @@
-/*
- *
- * envctrl.h: Definitions for access to the i2c environment
- *            monitoring on Ultrasparc systems.
- *
- * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
- * Copyright (C) 2000  Vinh Truong  (vinh.truong@eng.sun.com)
- * VT - Add all ioctl commands and environment status definitions 
- * VT - Add application note 
- */
-#ifndef _SPARC64_ENVCTRL_H
-#define _SPARC64_ENVCTRL_H 1
-
-#include <linux/ioctl.h>
-
-/* Application note:
- *
- * The driver supports 4 operations: open(), close(), ioctl(), read()
- * The device name is /dev/envctrl.
- * Below is sample usage:
- *
- *	fd = open("/dev/envtrl", O_RDONLY);
- *	if (ioctl(fd, ENVCTRL_READ_SHUTDOWN_TEMPERATURE, 0) < 0)
- *		printf("error\n");
- *	ret = read(fd, buf, 10);
- *	close(fd);
- *
- * Notice in the case of cpu voltage and temperature, the default is
- * cpu0.  If we need to know the info of cpu1, cpu2, cpu3, we need to
- * pass in cpu number in ioctl() last parameter.  For example, to
- * get the voltage of cpu2:
- *
- *	ioctlbuf[0] = 2;
- *	if (ioctl(fd, ENVCTRL_READ_CPU_VOLTAGE, ioctlbuf) < 0)
- *		printf("error\n");
- *	ret = read(fd, buf, 10);
- *
- * All the return values are in ascii.  So check read return value
- * and do appropriate conversions in your application.
- */
-
-/* IOCTL commands */
-
-/* Note: these commands reflect possible monitor features.
- * Some boards choose to support some of the features only.
- */
-#define ENVCTRL_RD_CPU_TEMPERATURE	_IOR('p', 0x40, int)
-#define ENVCTRL_RD_CPU_VOLTAGE		_IOR('p', 0x41, int)
-#define ENVCTRL_RD_FAN_STATUS		_IOR('p', 0x42, int)
-#define ENVCTRL_RD_WARNING_TEMPERATURE	_IOR('p', 0x43, int)
-#define ENVCTRL_RD_SHUTDOWN_TEMPERATURE	_IOR('p', 0x44, int)
-#define ENVCTRL_RD_VOLTAGE_STATUS	_IOR('p', 0x45, int)
-#define ENVCTRL_RD_SCSI_TEMPERATURE	_IOR('p', 0x46, int)
-#define ENVCTRL_RD_ETHERNET_TEMPERATURE	_IOR('p', 0x47, int)
-#define ENVCTRL_RD_MTHRBD_TEMPERATURE	_IOR('p', 0x48, int)
-
-#define ENVCTRL_RD_GLOBALADDRESS	_IOR('p', 0x49, int)
-
-/* Read return values for a voltage status request. */
-#define ENVCTRL_VOLTAGE_POWERSUPPLY_GOOD	0x01
-#define ENVCTRL_VOLTAGE_BAD			0x02
-#define ENVCTRL_POWERSUPPLY_BAD			0x03
-#define ENVCTRL_VOLTAGE_POWERSUPPLY_BAD		0x04
-
-/* Read return values for a fan status request.
- * A failure match means either the fan fails or
- * the fan is not connected.  Some boards have optional
- * connectors to connect extra fans.
- *
- * There are maximum 8 monitor fans.  Some are cpu fans
- * some are system fans.  The mask below only indicates
- * fan by order number.
- * Below is a sample application:
- *
- *	if (ioctl(fd, ENVCTRL_READ_FAN_STATUS, 0) < 0) {
- *		printf("ioctl fan failed\n");
- *	}
- *	if (read(fd, rslt, 1) <= 0) {
- *		printf("error or fan not monitored\n");
- *	} else {
- *		if (rslt[0] == ENVCTRL_ALL_FANS_GOOD) {
- *			printf("all fans good\n");
- *	} else if (rslt[0] == ENVCTRL_ALL_FANS_BAD) {
- *		printf("all fans bad\n");
- *	} else {
- *		if (rslt[0] & ENVCTRL_FAN0_FAILURE_MASK) {
- *			printf("fan 0 failed or not connected\n");
- *	}
- *	......
- */  
-
-#define ENVCTRL_ALL_FANS_GOOD			0x00
-#define ENVCTRL_FAN0_FAILURE_MASK		0x01
-#define ENVCTRL_FAN1_FAILURE_MASK		0x02
-#define ENVCTRL_FAN2_FAILURE_MASK		0x04
-#define ENVCTRL_FAN3_FAILURE_MASK		0x08
-#define ENVCTRL_FAN4_FAILURE_MASK		0x10
-#define ENVCTRL_FAN5_FAILURE_MASK		0x20
-#define ENVCTRL_FAN6_FAILURE_MASK		0x40
-#define ENVCTRL_FAN7_FAILURE_MASK		0x80
-#define ENVCTRL_ALL_FANS_BAD 			0xFF
-
-#endif /* !(_SPARC64_ENVCTRL_H) */
+#include <asm-sparc/envctrl.h>
diff --git a/include/asm-sparc64/estate.h b/include/asm-sparc64/estate.h
index 520c085..bedd0ef 100644
--- a/include/asm-sparc64/estate.h
+++ b/include/asm-sparc64/estate.h
@@ -1,49 +1 @@
-#ifndef _SPARC64_ESTATE_H
-#define _SPARC64_ESTATE_H
-
-/* UltraSPARC-III E-cache Error Enable */
-#define ESTATE_ERROR_FMT	0x0000000000040000 /* Force MTAG ECC		*/
-#define ESTATE_ERROR_FMESS	0x000000000003c000 /* Forced MTAG ECC val	*/
-#define ESTATE_ERROR_FMD	0x0000000000002000 /* Force DATA ECC		*/
-#define ESTATE_ERROR_FDECC	0x0000000000001ff0 /* Forced DATA ECC val	*/
-#define ESTATE_ERROR_UCEEN	0x0000000000000008 /* See below			*/
-#define ESTATE_ERROR_NCEEN	0x0000000000000002 /* See below			*/
-#define ESTATE_ERROR_CEEN	0x0000000000000001 /* See below			*/
-
-/* UCEEN enables the fast_ECC_error trap for: 1) software correctable E-cache
- * errors 2) uncorrectable E-cache errors.  Such events only occur on reads
- * of the E-cache by the local processor for: 1) data loads 2) instruction
- * fetches 3) atomic operations.  Such events _cannot_ occur for: 1) merge
- * 2) writeback 2) copyout.  The AFSR bits associated with these traps are
- * UCC and UCU.
- */
-
-/* NCEEN enables instruction_access_error, data_access_error, and ECC_error traps
- * for uncorrectable ECC errors and system errors.
- *
- * Uncorrectable system bus data error or MTAG ECC error, system bus TimeOUT,
- * or system bus BusERR:
- * 1) As the result of an instruction fetch, will generate instruction_access_error
- * 2) As the result of a load etc. will generate data_access_error.
- * 3) As the result of store merge completion, writeback, or copyout will
- *    generate a disrupting ECC_error trap.
- * 4) As the result of such errors on instruction vector fetch can generate any
- *    of the 3 trap types.
- *
- * The AFSR bits associated with these traps are EMU, EDU, WDU, CPU, IVU, UE,
- * BERR, and TO.
- */
-
-/* CEEN enables the ECC_error trap for hardware corrected ECC errors.  System bus
- * reads resulting in a hardware corrected data or MTAG ECC error will generate an
- * ECC_error disrupting trap with this bit enabled.
- *
- * This same trap will also be generated when a hardware corrected ECC error results
- * during store merge, writeback, and copyout operations.
- */
-
-/* In general, if the trap enable bits above are disabled the AFSR bits will still
- * log the events even though the trap will not be generated by the processor.
- */
-
-#endif /* _SPARC64_ESTATE_H */
+#include <asm-sparc/estate.h>
diff --git a/include/asm-sparc64/fbio.h b/include/asm-sparc64/fbio.h
index b9215a0..c17edf8 100644
--- a/include/asm-sparc64/fbio.h
+++ b/include/asm-sparc64/fbio.h
@@ -1,330 +1 @@
-#ifndef __LINUX_FBIO_H
-#define __LINUX_FBIO_H
-
-#include <linux/compiler.h>
-#include <linux/types.h>
-
-/* Constants used for fbio SunOS compatibility */
-/* (C) 1996 Miguel de Icaza */
-
-/* Frame buffer types */
-#define FBTYPE_NOTYPE           -1
-#define FBTYPE_SUN1BW           0   /* mono */
-#define FBTYPE_SUN1COLOR        1 
-#define FBTYPE_SUN2BW           2 
-#define FBTYPE_SUN2COLOR        3 
-#define FBTYPE_SUN2GP           4 
-#define FBTYPE_SUN5COLOR        5 
-#define FBTYPE_SUN3COLOR        6 
-#define FBTYPE_MEMCOLOR         7 
-#define FBTYPE_SUN4COLOR        8 
- 
-#define FBTYPE_NOTSUN1          9 
-#define FBTYPE_NOTSUN2          10
-#define FBTYPE_NOTSUN3          11
- 
-#define FBTYPE_SUNFAST_COLOR    12  /* cg6 */
-#define FBTYPE_SUNROP_COLOR     13
-#define FBTYPE_SUNFB_VIDEO      14
-#define FBTYPE_SUNGIFB          15
-#define FBTYPE_SUNGPLAS         16
-#define FBTYPE_SUNGP3           17
-#define FBTYPE_SUNGT            18
-#define FBTYPE_SUNLEO           19      /* zx Leo card */
-#define FBTYPE_MDICOLOR         20      /* cg14 */
-#define FBTYPE_TCXCOLOR		21	/* SUNW,tcx card */
-
-#define FBTYPE_LASTPLUSONE      21	/* This is not last + 1 in fact... */
-
-/* Does not seem to be listed in the Sun file either */
-#define FBTYPE_CREATOR          22
-#define FBTYPE_PCI_IGA1682	23
-#define FBTYPE_P9100COLOR	24
-
-#define FBTYPE_PCI_GENERIC	1000
-#define FBTYPE_PCI_MACH64	1001
-
-/* fbio ioctls */
-/* Returned by FBIOGTYPE */
-struct  fbtype {
-        int     fb_type;        /* fb type, see above */
-        int     fb_height;      /* pixels */
-        int     fb_width;       /* pixels */
-        int     fb_depth;
-        int     fb_cmsize;      /* color map entries */
-        int     fb_size;        /* fb size in bytes */
-};
-#define FBIOGTYPE _IOR('F', 0, struct fbtype)
-
-struct  fbcmap {
-        int             index;          /* first element (0 origin) */
-        int             count;
-        unsigned char   __user *red;
-        unsigned char   __user *green;
-        unsigned char   __user *blue;
-};
-
-#ifdef __KERNEL__
-#define FBIOPUTCMAP_SPARC _IOW('F', 3, struct fbcmap)
-#define FBIOGETCMAP_SPARC _IOW('F', 4, struct fbcmap)
-#else
-#define FBIOPUTCMAP _IOW('F', 3, struct fbcmap)
-#define FBIOGETCMAP _IOW('F', 4, struct fbcmap)
-#endif
-
-/* # of device specific values */
-#define FB_ATTR_NDEVSPECIFIC    8
-/* # of possible emulations */
-#define FB_ATTR_NEMUTYPES       4
- 
-struct fbsattr {
-        int     flags;
-        int     emu_type;	/* -1 if none */
-        int     dev_specific[FB_ATTR_NDEVSPECIFIC];
-};
- 
-struct fbgattr {
-        int     real_type;	/* real frame buffer type */
-        int     owner;		/* unknown */
-        struct fbtype fbtype;	/* real frame buffer fbtype */
-        struct fbsattr sattr;   
-        int     emu_types[FB_ATTR_NEMUTYPES]; /* supported emulations */
-};
-#define FBIOSATTR  _IOW('F', 5, struct fbgattr) /* Unsupported: */
-#define FBIOGATTR  _IOR('F', 6, struct fbgattr)	/* supported */
-
-#define FBIOSVIDEO _IOW('F', 7, int)
-#define FBIOGVIDEO _IOR('F', 8, int)
-
-struct fbcursor {
-        short set;              /* what to set, choose from the list above */
-        short enable;           /* cursor on/off */
-        struct fbcurpos pos;    /* cursor position */
-        struct fbcurpos hot;    /* cursor hot spot */
-        struct fbcmap cmap;     /* color map info */
-        struct fbcurpos size;   /* cursor bit map size */
-        char __user *image;     /* cursor image bits */
-        char __user *mask;      /* cursor mask bits */
-};
-
-/* set/get cursor attributes/shape */
-#define FBIOSCURSOR     _IOW('F', 24, struct fbcursor)
-#define FBIOGCURSOR     _IOWR('F', 25, struct fbcursor)
- 
-/* set/get cursor position */
-#define FBIOSCURPOS     _IOW('F', 26, struct fbcurpos)
-#define FBIOGCURPOS     _IOW('F', 27, struct fbcurpos)
- 
-/* get max cursor size */
-#define FBIOGCURMAX     _IOR('F', 28, struct fbcurpos)
-
-/* wid manipulation */
-struct fb_wid_alloc {
-#define FB_WID_SHARED_8		0
-#define FB_WID_SHARED_24	1
-#define FB_WID_DBL_8		2
-#define FB_WID_DBL_24		3
-	__u32	wa_type;
-	__s32	wa_index;	/* Set on return */
-	__u32	wa_count;	
-};
-struct fb_wid_item {
-	__u32	wi_type;
-	__s32	wi_index;
-	__u32	wi_attrs;
-	__u32	wi_values[32];
-};
-struct fb_wid_list {
-	__u32	wl_flags;
-	__u32	wl_count;
-	struct fb_wid_item	*wl_list;
-};
-
-#define FBIO_WID_ALLOC	_IOWR('F', 30, struct fb_wid_alloc)
-#define FBIO_WID_FREE	_IOW('F', 31, struct fb_wid_alloc)
-#define FBIO_WID_PUT	_IOW('F', 32, struct fb_wid_list)
-#define FBIO_WID_GET	_IOWR('F', 33, struct fb_wid_list)
-
-/* Creator ioctls */
-#define FFB_IOCTL	('F'<<8)
-#define FFB_SYS_INFO		(FFB_IOCTL|80)
-#define FFB_CLUTREAD		(FFB_IOCTL|81)
-#define FFB_CLUTPOST		(FFB_IOCTL|82)
-#define FFB_SETDIAGMODE		(FFB_IOCTL|83)
-#define FFB_GETMONITORID	(FFB_IOCTL|84)
-#define FFB_GETVIDEOMODE	(FFB_IOCTL|85)
-#define FFB_SETVIDEOMODE	(FFB_IOCTL|86)
-#define FFB_SETSERVER		(FFB_IOCTL|87)
-#define FFB_SETOVCTL		(FFB_IOCTL|88)
-#define FFB_GETOVCTL		(FFB_IOCTL|89)
-#define FFB_GETSAXNUM		(FFB_IOCTL|90)
-#define FFB_FBDEBUG		(FFB_IOCTL|91)
-
-/* Cg14 ioctls */
-#define MDI_IOCTL          ('M'<<8)
-#define MDI_RESET          (MDI_IOCTL|1)
-#define MDI_GET_CFGINFO    (MDI_IOCTL|2)
-#define MDI_SET_PIXELMODE  (MDI_IOCTL|3)
-#    define MDI_32_PIX     32
-#    define MDI_16_PIX     16
-#    define MDI_8_PIX      8
-
-struct mdi_cfginfo {
-	int     mdi_ncluts;     /* Number of implemented CLUTs in this MDI */
-        int     mdi_type;       /* FBTYPE name */
-        int     mdi_height;     /* height */
-        int     mdi_width;      /* widht */
-        int     mdi_size;       /* available ram */
-        int     mdi_mode;       /* 8bpp, 16bpp or 32bpp */
-        int     mdi_pixfreq;    /* pixel clock (from PROM) */
-};
-
-/* SparcLinux specific ioctl for the MDI, should be replaced for
- * the SET_XLUT/SET_CLUTn ioctls instead
- */
-#define MDI_CLEAR_XLUT       (MDI_IOCTL|9)
-
-/* leo & ffb ioctls */
-struct fb_clut_alloc {
-	__u32	clutid;	/* Set on return */
- 	__u32	flag;
- 	__u32	index;
-};
-
-struct fb_clut {
-#define FB_CLUT_WAIT	0x00000001	/* Not yet implemented */
- 	__u32	flag;
- 	__u32	clutid;
- 	__u32	offset;
- 	__u32	count;
- 	char *	red;
- 	char *	green;
- 	char *	blue;
-};
-
-struct fb_clut32 {
- 	__u32	flag;
- 	__u32	clutid;
- 	__u32	offset;
- 	__u32	count;
- 	__u32	red;
- 	__u32	green;
- 	__u32	blue;
-};
-
-#define LEO_CLUTALLOC	_IOWR('L', 53, struct fb_clut_alloc)
-#define LEO_CLUTFREE	_IOW('L', 54, struct fb_clut_alloc)
-#define LEO_CLUTREAD	_IOW('L', 55, struct fb_clut)
-#define LEO_CLUTPOST	_IOW('L', 56, struct fb_clut)
-#define LEO_SETGAMMA	_IOW('L', 68, int) /* Not yet implemented */
-#define LEO_GETGAMMA	_IOR('L', 69, int) /* Not yet implemented */
-
-#ifdef __KERNEL__
-/* Addresses on the fd of a cgsix that are mappable */
-#define CG6_FBC    0x70000000
-#define CG6_TEC    0x70001000
-#define CG6_BTREGS 0x70002000
-#define CG6_FHC    0x70004000
-#define CG6_THC    0x70005000
-#define CG6_ROM    0x70006000
-#define CG6_RAM    0x70016000
-#define CG6_DHC    0x80000000
-
-#define CG3_MMAP_OFFSET 0x4000000
-
-/* Addresses on the fd of a tcx that are mappable */
-#define TCX_RAM8BIT   		0x00000000
-#define TCX_RAM24BIT   		0x01000000
-#define TCX_UNK3   		0x10000000
-#define TCX_UNK4   		0x20000000
-#define TCX_CONTROLPLANE   	0x28000000
-#define TCX_UNK6   		0x30000000
-#define TCX_UNK7   		0x38000000
-#define TCX_TEC    		0x70000000
-#define TCX_BTREGS 		0x70002000
-#define TCX_THC    		0x70004000
-#define TCX_DHC    		0x70008000
-#define TCX_ALT	   		0x7000a000
-#define TCX_SYNC   		0x7000e000
-#define TCX_UNK2    		0x70010000
-
-/* CG14 definitions */
-
-/* Offsets into the OBIO space: */
-#define CG14_REGS        0       /* registers */
-#define CG14_CURSORREGS  0x1000  /* cursor registers */
-#define CG14_DACREGS     0x2000  /* DAC registers */
-#define CG14_XLUT        0x3000  /* X Look Up Table -- ??? */
-#define CG14_CLUT1       0x4000  /* Color Look Up Table */
-#define CG14_CLUT2       0x5000  /* Color Look Up Table */
-#define CG14_CLUT3       0x6000  /* Color Look Up Table */
-#define CG14_AUTO	 0xf000
-
-#endif /* KERNEL */
-
-/* These are exported to userland for applications to use */
-/* Mappable offsets for the cg14: control registers */
-#define MDI_DIRECT_MAP 0x10000000
-#define MDI_CTLREG_MAP 0x20000000
-#define MDI_CURSOR_MAP 0x30000000
-#define MDI_SHDW_VRT_MAP 0x40000000
-
-/* Mappable offsets for the cg14: frame buffer resolutions */
-/* 32 bits */
-#define MDI_CHUNKY_XBGR_MAP 0x50000000
-#define MDI_CHUNKY_BGR_MAP 0x60000000
-
-/* 16 bits */
-#define MDI_PLANAR_X16_MAP 0x70000000
-#define MDI_PLANAR_C16_MAP 0x80000000
-
-/* 8 bit is done as CG3 MMAP offset */
-/* 32 bits, planar */
-#define MDI_PLANAR_X32_MAP 0x90000000
-#define MDI_PLANAR_B32_MAP 0xa0000000
-#define MDI_PLANAR_G32_MAP 0xb0000000
-#define MDI_PLANAR_R32_MAP 0xc0000000
-
-/* Mappable offsets on leo */
-#define LEO_SS0_MAP            0x00000000
-#define LEO_LC_SS0_USR_MAP     0x00800000
-#define LEO_LD_SS0_MAP         0x00801000
-#define LEO_LX_CURSOR_MAP      0x00802000
-#define LEO_SS1_MAP            0x00803000
-#define LEO_LC_SS1_USR_MAP     0x01003000
-#define LEO_LD_SS1_MAP         0x01004000
-#define LEO_UNK_MAP            0x01005000
-#define LEO_LX_KRN_MAP         0x01006000
-#define LEO_LC_SS0_KRN_MAP     0x01007000
-#define LEO_LC_SS1_KRN_MAP     0x01008000
-#define LEO_LD_GBL_MAP         0x01009000
-#define LEO_UNK2_MAP           0x0100a000
-
-#ifdef __KERNEL__
-struct  fbcmap32 {
-	int             index;          /* first element (0 origin) */
-	int             count;
-	u32		red;
-	u32		green;
-	u32		blue;
-};
-
-#define FBIOPUTCMAP32	_IOW('F', 3, struct fbcmap32)
-#define FBIOGETCMAP32	_IOW('F', 4, struct fbcmap32)
-
-struct fbcursor32 {
-	short set;		/* what to set, choose from the list above */
-	short enable;		/* cursor on/off */
-	struct fbcurpos pos;	/* cursor position */
-	struct fbcurpos hot;	/* cursor hot spot */
-	struct fbcmap32 cmap;	/* color map info */
-	struct fbcurpos size;	/* cursor bit map size */
-	u32	image;		/* cursor image bits */
-	u32	mask;		/* cursor mask bits */
-};
-
-#define FBIOSCURSOR32	_IOW('F', 24, struct fbcursor32)
-#define FBIOGCURSOR32	_IOW('F', 25, struct fbcursor32)
-#endif
-
-#endif /* __LINUX_FBIO_H */
+#include <asm-sparc/fbio.h>
diff --git a/include/asm-sparc64/fcntl.h b/include/asm-sparc64/fcntl.h
index 8a09ca7..8b1beae 100644
--- a/include/asm-sparc64/fcntl.h
+++ b/include/asm-sparc64/fcntl.h
@@ -1,35 +1 @@
-#ifndef _SPARC64_FCNTL_H
-#define _SPARC64_FCNTL_H
-
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
-   located on an ext2 file system */
-#define O_NDELAY	0x0004
-#define O_APPEND	0x0008
-#define FASYNC		0x0040	/* fcntl, for BSD compatibility */
-#define O_CREAT		0x0200	/* not fcntl */
-#define O_TRUNC		0x0400	/* not fcntl */
-#define O_EXCL		0x0800	/* not fcntl */
-#define O_SYNC		0x2000
-#define O_NONBLOCK	0x4000
-#define O_NOCTTY	0x8000	/* not fcntl */
-#define O_LARGEFILE	0x40000
-#define O_DIRECT        0x100000 /* direct disk access hint */
-#define O_NOATIME	0x200000
-#define O_CLOEXEC	0x400000
-
-#define F_GETOWN	5	/*  for sockets. */
-#define F_SETOWN	6	/*  for sockets. */
-#define F_GETLK		7
-#define F_SETLK		8
-#define F_SETLKW	9
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK		1
-#define F_WRLCK		2
-#define F_UNLCK		3
-
-#define __ARCH_FLOCK_PAD	short __unused;
-
-#include <asm-generic/fcntl.h>
-
-#endif /* !(_SPARC64_FCNTL_H) */
+#include <asm-sparc/fcntl.h>
diff --git a/include/asm-sparc64/fhc.h b/include/asm-sparc64/fhc.h
index ddffcdf..73eb04c 100644
--- a/include/asm-sparc64/fhc.h
+++ b/include/asm-sparc64/fhc.h
@@ -1,131 +1 @@
-/*
- * fhc.h: Structures for central/fhc pseudo driver on Sunfire/Starfire/Wildfire.
- *
- * Copyright (C) 1997, 1999 David S. Miller (davem@redhat.com)
- */
-
-#ifndef _SPARC64_FHC_H
-#define _SPARC64_FHC_H
-
-#include <linux/timer.h>
-
-#include <asm/oplib.h>
-#include <asm/prom.h>
-#include <asm/upa.h>
-
-struct linux_fhc;
-
-/* Clock board register offsets. */
-#define CLOCK_CTRL	0x00UL	/* Main control */
-#define CLOCK_STAT1	0x10UL	/* Status one */
-#define CLOCK_STAT2	0x20UL	/* Status two */
-#define CLOCK_PWRSTAT	0x30UL	/* Power status */
-#define CLOCK_PWRPRES	0x40UL	/* Power presence */
-#define CLOCK_TEMP	0x50UL	/* Temperature */
-#define CLOCK_IRQDIAG	0x60UL	/* IRQ diagnostics */
-#define CLOCK_PWRSTAT2	0x70UL	/* Power status two */
-
-#define CLOCK_CTRL_LLED		0x04	/* Left LED, 0 == on */
-#define CLOCK_CTRL_MLED		0x02	/* Mid LED, 1 == on */
-#define CLOCK_CTRL_RLED		0x01	/* RIght LED, 1 == on */
-
-struct linux_central {
-	struct linux_fhc		*child;
-	unsigned long			cfreg;
-	unsigned long			clkregs;
-	unsigned long			clkver;
-	int				slots;
-	struct device_node		*prom_node;
-
-	struct linux_prom_ranges	central_ranges[PROMREG_MAX];
-	int				num_central_ranges;
-};
-
-/* Firehose controller register offsets */
-struct fhc_regs {
-	unsigned long			pregs;	/* FHC internal regs */
-#define FHC_PREGS_ID	0x00UL	/* FHC ID */
-#define  FHC_ID_VERS		0xf0000000 /* Version of this FHC		*/
-#define  FHC_ID_PARTID		0x0ffff000 /* Part ID code (0x0f9f == FHC)	*/
-#define  FHC_ID_MANUF		0x0000007e /* Manufacturer (0x3e == SUN's JEDEC)*/
-#define  FHC_ID_RESV		0x00000001 /* Read as one			*/
-#define FHC_PREGS_RCS	0x10UL	/* FHC Reset Control/Status Register */
-#define  FHC_RCS_POR		0x80000000 /* Last reset was a power cycle	*/
-#define  FHC_RCS_SPOR		0x40000000 /* Last reset was sw power on reset	*/
-#define  FHC_RCS_SXIR		0x20000000 /* Last reset was sw XIR reset	*/
-#define  FHC_RCS_BPOR		0x10000000 /* Last reset was due to POR button	*/
-#define  FHC_RCS_BXIR		0x08000000 /* Last reset was due to XIR button	*/
-#define  FHC_RCS_WEVENT		0x04000000 /* CPU reset was due to wakeup event	*/
-#define  FHC_RCS_CFATAL		0x02000000 /* Centerplane Fatal Error signalled	*/
-#define  FHC_RCS_FENAB		0x01000000 /* Fatal errors elicit system reset	*/
-#define FHC_PREGS_CTRL	0x20UL	/* FHC Control Register */
-#define  FHC_CONTROL_ICS	0x00100000 /* Ignore Centerplane Signals	*/
-#define  FHC_CONTROL_FRST	0x00080000 /* Fatal Error Reset Enable		*/
-#define  FHC_CONTROL_LFAT	0x00040000 /* AC/DC signalled a local error	*/
-#define  FHC_CONTROL_SLINE	0x00010000 /* Firmware Synchronization Line	*/
-#define  FHC_CONTROL_DCD	0x00008000 /* DC-->DC Converter Disable		*/
-#define  FHC_CONTROL_POFF	0x00004000 /* AC/DC Controller PLL Disable	*/
-#define  FHC_CONTROL_FOFF	0x00002000 /* FHC Controller PLL Disable	*/
-#define  FHC_CONTROL_AOFF	0x00001000 /* CPU A SRAM/SBD Low Power Mode	*/
-#define  FHC_CONTROL_BOFF	0x00000800 /* CPU B SRAM/SBD Low Power Mode	*/
-#define  FHC_CONTROL_PSOFF	0x00000400 /* Turns off this FHC's power supply	*/
-#define  FHC_CONTROL_IXIST	0x00000200 /* 0=FHC tells clock board it exists	*/
-#define  FHC_CONTROL_XMSTR	0x00000100 /* 1=Causes this FHC to be XIR master*/
-#define  FHC_CONTROL_LLED	0x00000040 /* 0=Left LED ON			*/
-#define  FHC_CONTROL_MLED	0x00000020 /* 1=Middle LED ON			*/
-#define  FHC_CONTROL_RLED	0x00000010 /* 1=Right LED			*/
-#define  FHC_CONTROL_BPINS	0x00000003 /* Spare Bidirectional Pins		*/
-#define FHC_PREGS_BSR	0x30UL	/* FHC Board Status Register */
-#define  FHC_BSR_DA64		0x00040000 /* Port A: 0=128bit 1=64bit data path */
-#define  FHC_BSR_DB64		0x00020000 /* Port B: 0=128bit 1=64bit data path */
-#define  FHC_BSR_BID		0x0001e000 /* Board ID                           */
-#define  FHC_BSR_SA		0x00001c00 /* Port A UPA Speed (from the pins)   */
-#define  FHC_BSR_SB		0x00000380 /* Port B UPA Speed (from the pins)   */
-#define  FHC_BSR_NDIAG		0x00000040 /* Not in Diag Mode                   */
-#define  FHC_BSR_NTBED		0x00000020 /* Not in TestBED Mode                */
-#define  FHC_BSR_NIA		0x0000001c /* Jumper, bit 18 in PROM space       */
-#define  FHC_BSR_SI		0x00000001 /* Spare input pin value              */
-#define FHC_PREGS_ECC	0x40UL	/* FHC ECC Control Register (16 bits) */
-#define FHC_PREGS_JCTRL	0xf0UL	/* FHC JTAG Control Register */
-#define  FHC_JTAG_CTRL_MENAB	0x80000000 /* Indicates this is JTAG Master	 */
-#define  FHC_JTAG_CTRL_MNONE	0x40000000 /* Indicates no JTAG Master present	 */
-#define FHC_PREGS_JCMD	0x100UL	/* FHC JTAG Command Register */
-	unsigned long			ireg;	/* FHC IGN reg */
-#define FHC_IREG_IGN	0x00UL	/* This FHC's IGN */
-	unsigned long			ffregs;	/* FHC fanfail regs */
-#define FHC_FFREGS_IMAP	0x00UL	/* FHC Fanfail IMAP */
-#define FHC_FFREGS_ICLR	0x10UL	/* FHC Fanfail ICLR */
-	unsigned long			sregs;	/* FHC system regs */
-#define FHC_SREGS_IMAP	0x00UL	/* FHC System IMAP */
-#define FHC_SREGS_ICLR	0x10UL	/* FHC System ICLR */
-	unsigned long			uregs;	/* FHC uart regs */
-#define FHC_UREGS_IMAP	0x00UL	/* FHC Uart IMAP */
-#define FHC_UREGS_ICLR	0x10UL	/* FHC Uart ICLR */
-	unsigned long			tregs;	/* FHC TOD regs */
-#define FHC_TREGS_IMAP	0x00UL	/* FHC TOD IMAP */
-#define FHC_TREGS_ICLR	0x10UL	/* FHC TOD ICLR */
-};
-
-struct linux_fhc {
-	struct linux_fhc		*next;
-	struct linux_central		*parent;	/* NULL if not central FHC */
-	struct fhc_regs			fhc_regs;
-	int				board;
-	int				jtag_master;
-	struct device_node		*prom_node;
-
-	struct linux_prom_ranges	fhc_ranges[PROMREG_MAX];
-	int				num_fhc_ranges;
-};
-
-extern struct linux_central *central_bus;
-
-extern void apply_central_ranges(struct linux_central *central, 
-				 struct linux_prom_registers *regs,
-				 int nregs);
-
-extern void apply_fhc_ranges(struct linux_fhc *fhc, 
-			     struct linux_prom_registers *regs,
-			     int nregs);
-
-#endif /* !(_SPARC64_FHC_H) */
+#include <asm-sparc/fhc.h>
diff --git a/include/asm-sparc64/floppy.h b/include/asm-sparc64/floppy.h
index ca19f80..2148781 100644
--- a/include/asm-sparc64/floppy.h
+++ b/include/asm-sparc64/floppy.h
@@ -1,782 +1 @@
-/* floppy.h: Sparc specific parts of the Floppy driver.
- *
- * Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net)
- * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- *
- * Ultra/PCI support added: Sep 1997  Eddie C. Dost  (ecd@skynet.be)
- */
-
-#ifndef __ASM_SPARC64_FLOPPY_H
-#define __ASM_SPARC64_FLOPPY_H
-
-#include <linux/init.h>
-#include <linux/pci.h>
-
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/idprom.h>
-#include <asm/oplib.h>
-#include <asm/auxio.h>
-#include <asm/sbus.h>
-#include <asm/irq.h>
-
-
-/*
- * Define this to enable exchanging drive 0 and 1 if only drive 1 is
- * probed on PCI machines.
- */
-#undef PCI_FDC_SWAP_DRIVES
-
-
-/* References:
- * 1) Netbsd Sun floppy driver.
- * 2) NCR 82077 controller manual
- * 3) Intel 82077 controller manual
- */
-struct sun_flpy_controller {
-	volatile unsigned char status1_82077; /* Auxiliary Status reg. 1 */
-	volatile unsigned char status2_82077; /* Auxiliary Status reg. 2 */
-	volatile unsigned char dor_82077;     /* Digital Output reg. */
-	volatile unsigned char tapectl_82077; /* Tape Control reg */
-	volatile unsigned char status_82077;  /* Main Status Register. */
-#define drs_82077              status_82077   /* Digital Rate Select reg. */
-	volatile unsigned char data_82077;    /* Data fifo. */
-	volatile unsigned char ___unused;
-	volatile unsigned char dir_82077;     /* Digital Input reg. */
-#define dcr_82077              dir_82077      /* Config Control reg. */
-};
-
-/* You'll only ever find one controller on an Ultra anyways. */
-static struct sun_flpy_controller *sun_fdc = (struct sun_flpy_controller *)-1;
-unsigned long fdc_status;
-static struct sbus_dev *floppy_sdev = NULL;
-
-struct sun_floppy_ops {
-	unsigned char	(*fd_inb) (unsigned long port);
-	void		(*fd_outb) (unsigned char value, unsigned long port);
-	void		(*fd_enable_dma) (void);
-	void		(*fd_disable_dma) (void);
-	void		(*fd_set_dma_mode) (int);
-	void		(*fd_set_dma_addr) (char *);
-	void		(*fd_set_dma_count) (int);
-	unsigned int	(*get_dma_residue) (void);
-	int		(*fd_request_irq) (void);
-	void		(*fd_free_irq) (void);
-	int		(*fd_eject) (int);
-};
-
-static struct sun_floppy_ops sun_fdops;
-
-#define fd_inb(port)              sun_fdops.fd_inb(port)
-#define fd_outb(value,port)       sun_fdops.fd_outb(value,port)
-#define fd_enable_dma()           sun_fdops.fd_enable_dma()
-#define fd_disable_dma()          sun_fdops.fd_disable_dma()
-#define fd_request_dma()          (0) /* nothing... */
-#define fd_free_dma()             /* nothing... */
-#define fd_clear_dma_ff()         /* nothing... */
-#define fd_set_dma_mode(mode)     sun_fdops.fd_set_dma_mode(mode)
-#define fd_set_dma_addr(addr)     sun_fdops.fd_set_dma_addr(addr)
-#define fd_set_dma_count(count)   sun_fdops.fd_set_dma_count(count)
-#define get_dma_residue(x)        sun_fdops.get_dma_residue()
-#define fd_cacheflush(addr, size) /* nothing... */
-#define fd_request_irq()          sun_fdops.fd_request_irq()
-#define fd_free_irq()             sun_fdops.fd_free_irq()
-#define fd_eject(drive)           sun_fdops.fd_eject(drive)
-
-/* Super paranoid... */
-#undef HAVE_DISABLE_HLT
-
-static int sun_floppy_types[2] = { 0, 0 };
-
-/* Here is where we catch the floppy driver trying to initialize,
- * therefore this is where we call the PROM device tree probing
- * routine etc. on the Sparc.
- */
-#define FLOPPY0_TYPE		sun_floppy_init()
-#define FLOPPY1_TYPE		sun_floppy_types[1]
-
-#define FDC1			((unsigned long)sun_fdc)
-
-#define N_FDC    1
-#define N_DRIVE  8
-
-/* No 64k boundary crossing problems on the Sparc. */
-#define CROSS_64KB(a,s) (0)
-
-static unsigned char sun_82077_fd_inb(unsigned long port)
-{
-	udelay(5);
-	switch(port & 7) {
-	default:
-		printk("floppy: Asked to read unknown port %lx\n", port);
-		panic("floppy: Port bolixed.");
-	case 4: /* FD_STATUS */
-		return sbus_readb(&sun_fdc->status_82077) & ~STATUS_DMA;
-	case 5: /* FD_DATA */
-		return sbus_readb(&sun_fdc->data_82077);
-	case 7: /* FD_DIR */
-		/* XXX: Is DCL on 0x80 in sun4m? */
-		return sbus_readb(&sun_fdc->dir_82077);
-	};
-	panic("sun_82072_fd_inb: How did I get here?");
-}
-
-static void sun_82077_fd_outb(unsigned char value, unsigned long port)
-{
-	udelay(5);
-	switch(port & 7) {
-	default:
-		printk("floppy: Asked to write to unknown port %lx\n", port);
-		panic("floppy: Port bolixed.");
-	case 2: /* FD_DOR */
-		/* Happily, the 82077 has a real DOR register. */
-		sbus_writeb(value, &sun_fdc->dor_82077);
-		break;
-	case 5: /* FD_DATA */
-		sbus_writeb(value, &sun_fdc->data_82077);
-		break;
-	case 7: /* FD_DCR */
-		sbus_writeb(value, &sun_fdc->dcr_82077);
-		break;
-	case 4: /* FD_STATUS */
-		sbus_writeb(value, &sun_fdc->status_82077);
-		break;
-	};
-	return;
-}
-
-/* For pseudo-dma (Sun floppy drives have no real DMA available to
- * them so we must eat the data fifo bytes directly ourselves) we have
- * three state variables.  doing_pdma tells our inline low-level
- * assembly floppy interrupt entry point whether it should sit and eat
- * bytes from the fifo or just transfer control up to the higher level
- * floppy interrupt c-code.  I tried very hard but I could not get the
- * pseudo-dma to work in c-code without getting many overruns and
- * underruns.  If non-zero, doing_pdma encodes the direction of
- * the transfer for debugging.  1=read 2=write
- */
-unsigned char *pdma_vaddr;
-unsigned long pdma_size;
-volatile int doing_pdma = 0;
-
-/* This is software state */
-char *pdma_base = NULL;
-unsigned long pdma_areasize;
-
-/* Common routines to all controller types on the Sparc. */
-static void sun_fd_disable_dma(void)
-{
-	doing_pdma = 0;
-	if (pdma_base) {
-		mmu_unlockarea(pdma_base, pdma_areasize);
-		pdma_base = NULL;
-	}
-}
-
-static void sun_fd_set_dma_mode(int mode)
-{
-	switch(mode) {
-	case DMA_MODE_READ:
-		doing_pdma = 1;
-		break;
-	case DMA_MODE_WRITE:
-		doing_pdma = 2;
-		break;
-	default:
-		printk("Unknown dma mode %d\n", mode);
-		panic("floppy: Giving up...");
-	}
-}
-
-static void sun_fd_set_dma_addr(char *buffer)
-{
-	pdma_vaddr = buffer;
-}
-
-static void sun_fd_set_dma_count(int length)
-{
-	pdma_size = length;
-}
-
-static void sun_fd_enable_dma(void)
-{
-	pdma_vaddr = mmu_lockarea(pdma_vaddr, pdma_size);
-	pdma_base = pdma_vaddr;
-	pdma_areasize = pdma_size;
-}
-
-irqreturn_t sparc_floppy_irq(int irq, void *dev_cookie)
-{
-	if (likely(doing_pdma)) {
-		void __iomem *stat = (void __iomem *) fdc_status;
-		unsigned char *vaddr = pdma_vaddr;
-		unsigned long size = pdma_size;
-		u8 val;
-
-		while (size) {
-			val = readb(stat);
-			if (unlikely(!(val & 0x80))) {
-				pdma_vaddr = vaddr;
-				pdma_size = size;
-				return IRQ_HANDLED;
-			}
-			if (unlikely(!(val & 0x20))) {
-				pdma_vaddr = vaddr;
-				pdma_size = size;
-				doing_pdma = 0;
-				goto main_interrupt;
-			}
-			if (val & 0x40) {
-				/* read */
-				*vaddr++ = readb(stat + 1);
-			} else {
-				unsigned char data = *vaddr++;
-
-				/* write */
-				writeb(data, stat + 1);
-			}
-			size--;
-		}
-
-		pdma_vaddr = vaddr;
-		pdma_size = size;
-
-		/* Send Terminal Count pulse to floppy controller. */
-		val = readb(auxio_register);
-		val |= AUXIO_AUX1_FTCNT;
-		writeb(val, auxio_register);
-		val &= ~AUXIO_AUX1_FTCNT;
-		writeb(val, auxio_register);
-
-		doing_pdma = 0;
-	}
-
-main_interrupt:
-	return floppy_interrupt(irq, dev_cookie);
-}
-
-static int sun_fd_request_irq(void)
-{
-	static int once = 0;
-	int error;
-
-	if(!once) {
-		once = 1;
-
-		error = request_irq(FLOPPY_IRQ, sparc_floppy_irq, 
-				    IRQF_DISABLED, "floppy", NULL);
-
-		return ((error == 0) ? 0 : -1);
-	}
-	return 0;
-}
-
-static void sun_fd_free_irq(void)
-{
-}
-
-static unsigned int sun_get_dma_residue(void)
-{
-	/* XXX This isn't really correct. XXX */
-	return 0;
-}
-
-static int sun_fd_eject(int drive)
-{
-	set_dor(0x00, 0xff, 0x90);
-	udelay(500);
-	set_dor(0x00, 0x6f, 0x00);
-	udelay(500);
-	return 0;
-}
-
-#ifdef CONFIG_PCI
-#include <asm/ebus.h>
-#include <asm/ns87303.h>
-
-static struct ebus_dma_info sun_pci_fd_ebus_dma;
-static struct pci_dev *sun_pci_ebus_dev;
-static int sun_pci_broken_drive = -1;
-
-struct sun_pci_dma_op {
-	unsigned int 	addr;
-	int		len;
-	int		direction;
-	char		*buf;
-};
-static struct sun_pci_dma_op sun_pci_dma_current = { -1U, 0, 0, NULL};
-static struct sun_pci_dma_op sun_pci_dma_pending = { -1U, 0, 0, NULL};
-
-extern irqreturn_t floppy_interrupt(int irq, void *dev_id);
-
-static unsigned char sun_pci_fd_inb(unsigned long port)
-{
-	udelay(5);
-	return inb(port);
-}
-
-static void sun_pci_fd_outb(unsigned char val, unsigned long port)
-{
-	udelay(5);
-	outb(val, port);
-}
-
-static void sun_pci_fd_broken_outb(unsigned char val, unsigned long port)
-{
-	udelay(5);
-	/*
-	 * XXX: Due to SUN's broken floppy connector on AX and AXi
-	 *      we need to turn on MOTOR_0 also, if the floppy is
-	 *      jumpered to DS1 (like most PC floppies are). I hope
-	 *      this does not hurt correct hardware like the AXmp.
-	 *      (Eddie, Sep 12 1998).
-	 */
-	if (port == ((unsigned long)sun_fdc) + 2) {
-		if (((val & 0x03) == sun_pci_broken_drive) && (val & 0x20)) {
-			val |= 0x10;
-		}
-	}
-	outb(val, port);
-}
-
-#ifdef PCI_FDC_SWAP_DRIVES
-static void sun_pci_fd_lde_broken_outb(unsigned char val, unsigned long port)
-{
-	udelay(5);
-	/*
-	 * XXX: Due to SUN's broken floppy connector on AX and AXi
-	 *      we need to turn on MOTOR_0 also, if the floppy is
-	 *      jumpered to DS1 (like most PC floppies are). I hope
-	 *      this does not hurt correct hardware like the AXmp.
-	 *      (Eddie, Sep 12 1998).
-	 */
-	if (port == ((unsigned long)sun_fdc) + 2) {
-		if (((val & 0x03) == sun_pci_broken_drive) && (val & 0x10)) {
-			val &= ~(0x03);
-			val |= 0x21;
-		}
-	}
-	outb(val, port);
-}
-#endif /* PCI_FDC_SWAP_DRIVES */
-
-static void sun_pci_fd_enable_dma(void)
-{
-	BUG_ON((NULL == sun_pci_dma_pending.buf) 	||
-	    (0	  == sun_pci_dma_pending.len) 	||
-	    (0	  == sun_pci_dma_pending.direction));
-
-	sun_pci_dma_current.buf = sun_pci_dma_pending.buf;
-	sun_pci_dma_current.len = sun_pci_dma_pending.len;
-	sun_pci_dma_current.direction = sun_pci_dma_pending.direction;
-
-	sun_pci_dma_pending.buf  = NULL;
-	sun_pci_dma_pending.len  = 0;
-	sun_pci_dma_pending.direction = 0;
-	sun_pci_dma_pending.addr = -1U;
-
-	sun_pci_dma_current.addr = 
-		pci_map_single(sun_pci_ebus_dev,
-			       sun_pci_dma_current.buf,
-			       sun_pci_dma_current.len,
-			       sun_pci_dma_current.direction);
-
-	ebus_dma_enable(&sun_pci_fd_ebus_dma, 1);
-
-	if (ebus_dma_request(&sun_pci_fd_ebus_dma,
-			     sun_pci_dma_current.addr,
-			     sun_pci_dma_current.len))
-		BUG();
-}
-
-static void sun_pci_fd_disable_dma(void)
-{
-	ebus_dma_enable(&sun_pci_fd_ebus_dma, 0);
-	if (sun_pci_dma_current.addr != -1U)
-		pci_unmap_single(sun_pci_ebus_dev,
-				 sun_pci_dma_current.addr,
-				 sun_pci_dma_current.len,
-				 sun_pci_dma_current.direction);
-	sun_pci_dma_current.addr = -1U;
-}
-
-static void sun_pci_fd_set_dma_mode(int mode)
-{
-	if (mode == DMA_MODE_WRITE)
-		sun_pci_dma_pending.direction = PCI_DMA_TODEVICE;
-	else
-		sun_pci_dma_pending.direction = PCI_DMA_FROMDEVICE;
-
-	ebus_dma_prepare(&sun_pci_fd_ebus_dma, mode != DMA_MODE_WRITE);
-}
-
-static void sun_pci_fd_set_dma_count(int length)
-{
-	sun_pci_dma_pending.len = length;
-}
-
-static void sun_pci_fd_set_dma_addr(char *buffer)
-{
-	sun_pci_dma_pending.buf = buffer;
-}
-
-static unsigned int sun_pci_get_dma_residue(void)
-{
-	return ebus_dma_residue(&sun_pci_fd_ebus_dma);
-}
-
-static int sun_pci_fd_request_irq(void)
-{
-	return ebus_dma_irq_enable(&sun_pci_fd_ebus_dma, 1);
-}
-
-static void sun_pci_fd_free_irq(void)
-{
-	ebus_dma_irq_enable(&sun_pci_fd_ebus_dma, 0);
-}
-
-static int sun_pci_fd_eject(int drive)
-{
-	return -EINVAL;
-}
-
-void sun_pci_fd_dma_callback(struct ebus_dma_info *p, int event, void *cookie)
-{
-	floppy_interrupt(0, NULL);
-}
-
-/*
- * Floppy probing, we'd like to use /dev/fd0 for a single Floppy on PCI,
- * even if this is configured using DS1, thus looks like /dev/fd1 with
- * the cabling used in Ultras.
- */
-#define DOR	(port + 2)
-#define MSR	(port + 4)
-#define FIFO	(port + 5)
-
-static void sun_pci_fd_out_byte(unsigned long port, unsigned char val,
-			        unsigned long reg)
-{
-	unsigned char status;
-	int timeout = 1000;
-
-	while (!((status = inb(MSR)) & 0x80) && --timeout)
-		udelay(100);
-	outb(val, reg);
-}
-
-static unsigned char sun_pci_fd_sensei(unsigned long port)
-{
-	unsigned char result[2] = { 0x70, 0x00 };
-	unsigned char status;
-	int i = 0;
-
-	sun_pci_fd_out_byte(port, 0x08, FIFO);
-	do {
-		int timeout = 1000;
-
-		while (!((status = inb(MSR)) & 0x80) && --timeout)
-			udelay(100);
-
-		if (!timeout)
-			break;
-
-		if ((status & 0xf0) == 0xd0)
-			result[i++] = inb(FIFO);
-		else
-			break;
-	} while (i < 2);
-
-	return result[0];
-}
-
-static void sun_pci_fd_reset(unsigned long port)
-{
-	unsigned char mask = 0x00;
-	unsigned char status;
-	int timeout = 10000;
-
-	outb(0x80, MSR);
-	do {
-		status = sun_pci_fd_sensei(port);
-		if ((status & 0xc0) == 0xc0)
-			mask |= 1 << (status & 0x03);
-		else
-			udelay(100);
-	} while ((mask != 0x0f) && --timeout);
-}
-
-static int sun_pci_fd_test_drive(unsigned long port, int drive)
-{
-	unsigned char status, data;
-	int timeout = 1000;
-	int ready;
-
-	sun_pci_fd_reset(port);
-
-	data = (0x10 << drive) | 0x0c | drive;
-	sun_pci_fd_out_byte(port, data, DOR);
-
-	sun_pci_fd_out_byte(port, 0x07, FIFO);
-	sun_pci_fd_out_byte(port, drive & 0x03, FIFO);
-
-	do {
-		udelay(100);
-		status = sun_pci_fd_sensei(port);
-	} while (((status & 0xc0) == 0x80) && --timeout);
-
-	if (!timeout)
-		ready = 0;
-	else
-		ready = (status & 0x10) ? 0 : 1;
-
-	sun_pci_fd_reset(port);
-	return ready;
-}
-#undef FIFO
-#undef MSR
-#undef DOR
-
-#endif /* CONFIG_PCI */
-
-#ifdef CONFIG_PCI
-static int __init ebus_fdthree_p(struct linux_ebus_device *edev)
-{
-	if (!strcmp(edev->prom_node->name, "fdthree"))
-		return 1;
-	if (!strcmp(edev->prom_node->name, "floppy")) {
-		const char *compat;
-
-		compat = of_get_property(edev->prom_node,
-					 "compatible", NULL);
-		if (compat && !strcmp(compat, "fdthree"))
-			return 1;
-	}
-	return 0;
-}
-#endif
-
-static unsigned long __init sun_floppy_init(void)
-{
-	char state[128];
-	struct sbus_bus *bus;
-	struct sbus_dev *sdev = NULL;
-	static int initialized = 0;
-
-	if (initialized)
-		return sun_floppy_types[0];
-	initialized = 1;
-
-	for_all_sbusdev (sdev, bus) {
-		if (!strcmp(sdev->prom_name, "SUNW,fdtwo")) 
-			break;
-	}
-	if(sdev) {
-		floppy_sdev = sdev;
-		FLOPPY_IRQ = sdev->irqs[0];
-	} else {
-#ifdef CONFIG_PCI
-		struct linux_ebus *ebus;
-		struct linux_ebus_device *edev = NULL;
-		unsigned long config = 0;
-		void __iomem *auxio_reg;
-		const char *state_prop;
-
-		for_each_ebus(ebus) {
-			for_each_ebusdev(edev, ebus) {
-				if (ebus_fdthree_p(edev))
-					goto ebus_done;
-			}
-		}
-	ebus_done:
-		if (!edev)
-			return 0;
-
-		state_prop = of_get_property(edev->prom_node, "status", NULL);
-		if (state_prop && !strncmp(state_prop, "disabled", 8))
-			return 0;
-			
-		FLOPPY_IRQ = edev->irqs[0];
-
-		/* Make sure the high density bit is set, some systems
-		 * (most notably Ultra5/Ultra10) come up with it clear.
-		 */
-		auxio_reg = (void __iomem *) edev->resource[2].start;
-		writel(readl(auxio_reg)|0x2, auxio_reg);
-
-		sun_pci_ebus_dev = ebus->self;
-
-		spin_lock_init(&sun_pci_fd_ebus_dma.lock);
-
-		/* XXX ioremap */
-		sun_pci_fd_ebus_dma.regs = (void __iomem *)
-			edev->resource[1].start;
-		if (!sun_pci_fd_ebus_dma.regs)
-			return 0;
-
-		sun_pci_fd_ebus_dma.flags = (EBUS_DMA_FLAG_USE_EBDMA_HANDLER |
-					     EBUS_DMA_FLAG_TCI_DISABLE);
-		sun_pci_fd_ebus_dma.callback = sun_pci_fd_dma_callback;
-		sun_pci_fd_ebus_dma.client_cookie = NULL;
-		sun_pci_fd_ebus_dma.irq = FLOPPY_IRQ;
-		strcpy(sun_pci_fd_ebus_dma.name, "floppy");
-		if (ebus_dma_register(&sun_pci_fd_ebus_dma))
-			return 0;
-
-		/* XXX ioremap */
-		sun_fdc = (struct sun_flpy_controller *)edev->resource[0].start;
-
-		sun_fdops.fd_inb = sun_pci_fd_inb;
-		sun_fdops.fd_outb = sun_pci_fd_outb;
-
-		can_use_virtual_dma = use_virtual_dma = 0;
-		sun_fdops.fd_enable_dma = sun_pci_fd_enable_dma;
-		sun_fdops.fd_disable_dma = sun_pci_fd_disable_dma;
-		sun_fdops.fd_set_dma_mode = sun_pci_fd_set_dma_mode;
-		sun_fdops.fd_set_dma_addr = sun_pci_fd_set_dma_addr;
-		sun_fdops.fd_set_dma_count = sun_pci_fd_set_dma_count;
-		sun_fdops.get_dma_residue = sun_pci_get_dma_residue;
-
-		sun_fdops.fd_request_irq = sun_pci_fd_request_irq;
-		sun_fdops.fd_free_irq = sun_pci_fd_free_irq;
-
-		sun_fdops.fd_eject = sun_pci_fd_eject;
-
-        	fdc_status = (unsigned long) &sun_fdc->status_82077;
-
-		/*
-		 * XXX: Find out on which machines this is really needed.
-		 */
-		if (1) {
-			sun_pci_broken_drive = 1;
-			sun_fdops.fd_outb = sun_pci_fd_broken_outb;
-		}
-
-		allowed_drive_mask = 0;
-		if (sun_pci_fd_test_drive((unsigned long)sun_fdc, 0))
-			sun_floppy_types[0] = 4;
-		if (sun_pci_fd_test_drive((unsigned long)sun_fdc, 1))
-			sun_floppy_types[1] = 4;
-
-		/*
-		 * Find NS87303 SuperIO config registers (through ecpp).
-		 */
-		for_each_ebus(ebus) {
-			for_each_ebusdev(edev, ebus) {
-				if (!strcmp(edev->prom_node->name, "ecpp")) {
-					config = edev->resource[1].start;
-					goto config_done;
-				}
-			}
-		}
-	config_done:
-
-		/*
-		 * Sanity check, is this really the NS87303?
-		 */
-		switch (config & 0x3ff) {
-		case 0x02e:
-		case 0x15c:
-		case 0x26e:
-		case 0x398:
-			break;
-		default:
-			config = 0;
-		}
-
-		if (!config)
-			return sun_floppy_types[0];
-
-		/* Enable PC-AT mode. */
-		ns87303_modify(config, ASC, 0, 0xc0);
-
-#ifdef PCI_FDC_SWAP_DRIVES
-		/*
-		 * If only Floppy 1 is present, swap drives.
-		 */
-		if (!sun_floppy_types[0] && sun_floppy_types[1]) {
-			/*
-			 * Set the drive exchange bit in FCR on NS87303,
-			 * make sure other bits are sane before doing so.
-			 */
-			ns87303_modify(config, FER, FER_EDM, 0);
-			ns87303_modify(config, ASC, ASC_DRV2_SEL, 0);
-			ns87303_modify(config, FCR, 0, FCR_LDE);
-
-			config = sun_floppy_types[0];
-			sun_floppy_types[0] = sun_floppy_types[1];
-			sun_floppy_types[1] = config;
-
-			if (sun_pci_broken_drive != -1) {
-				sun_pci_broken_drive = 1 - sun_pci_broken_drive;
-				sun_fdops.fd_outb = sun_pci_fd_lde_broken_outb;
-			}
-		}
-#endif /* PCI_FDC_SWAP_DRIVES */
-
-		return sun_floppy_types[0];
-#else
-		return 0;
-#endif
-	}
-	prom_getproperty(sdev->prom_node, "status", state, sizeof(state));
-	if(!strncmp(state, "disabled", 8))
-		return 0;
-
-	/*
-	 * We cannot do sbus_ioremap here: it does request_region,
-	 * which the generic floppy driver tries to do once again.
-	 * But we must use the sdev resource values as they have
-	 * had parent ranges applied.
-	 */
-	sun_fdc = (struct sun_flpy_controller *)
-		(sdev->resource[0].start +
-		 ((sdev->resource[0].flags & 0x1ffUL) << 32UL));
-
-	/* Last minute sanity check... */
-	if(sbus_readb(&sun_fdc->status1_82077) == 0xff) {
-		sun_fdc = (struct sun_flpy_controller *)-1;
-		return 0;
-	}
-
-        sun_fdops.fd_inb = sun_82077_fd_inb;
-        sun_fdops.fd_outb = sun_82077_fd_outb;
-
-	can_use_virtual_dma = use_virtual_dma = 1;
-	sun_fdops.fd_enable_dma = sun_fd_enable_dma;
-	sun_fdops.fd_disable_dma = sun_fd_disable_dma;
-	sun_fdops.fd_set_dma_mode = sun_fd_set_dma_mode;
-	sun_fdops.fd_set_dma_addr = sun_fd_set_dma_addr;
-	sun_fdops.fd_set_dma_count = sun_fd_set_dma_count;
-	sun_fdops.get_dma_residue = sun_get_dma_residue;
-
-	sun_fdops.fd_request_irq = sun_fd_request_irq;
-	sun_fdops.fd_free_irq = sun_fd_free_irq;
-
-	sun_fdops.fd_eject = sun_fd_eject;
-
-        fdc_status = (unsigned long) &sun_fdc->status_82077;
-
-	/* Success... */
-	allowed_drive_mask = 0x01;
-	sun_floppy_types[0] = 4;
-	sun_floppy_types[1] = 0;
-
-	return sun_floppy_types[0];
-}
-
-#define EXTRA_FLOPPY_PARAMS
-
-static DEFINE_SPINLOCK(dma_spin_lock);
-
-#define claim_dma_lock() \
-({	unsigned long flags; \
-	spin_lock_irqsave(&dma_spin_lock, flags); \
-	flags; \
-})
-
-#define release_dma_lock(__flags) \
-	spin_unlock_irqrestore(&dma_spin_lock, __flags);
-
-#endif /* !(__ASM_SPARC64_FLOPPY_H) */
+#include <asm-sparc/floppy.h>
diff --git a/include/asm-sparc64/fpumacro.h b/include/asm-sparc64/fpumacro.h
index cc463fe..30d6d0f 100644
--- a/include/asm-sparc64/fpumacro.h
+++ b/include/asm-sparc64/fpumacro.h
@@ -1,33 +1 @@
-/* fpumacro.h: FPU related macros.
- *
- * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef _SPARC64_FPUMACRO_H
-#define _SPARC64_FPUMACRO_H
-
-#include <asm/asi.h>
-#include <asm/visasm.h>
-
-struct fpustate {
-	u32	regs[64];
-};
-
-#define FPUSTATE (struct fpustate *)(current_thread_info()->fpregs)
-
-static inline unsigned long fprs_read(void)
-{
-	unsigned long retval;
-
-	__asm__ __volatile__("rd %%fprs, %0" : "=r" (retval));
-
-	return retval;
-}
-
-static inline void fprs_write(unsigned long val)
-{
-	__asm__ __volatile__("wr %0, 0x0, %%fprs" : : "r" (val));
-}
-
-#endif /* !(_SPARC64_FPUMACRO_H) */
+#include <asm-sparc/fpumacro.h>
diff --git a/include/asm-sparc64/futex.h b/include/asm-sparc64/futex.h
index d837893..1ceb0bb 100644
--- a/include/asm-sparc64/futex.h
+++ b/include/asm-sparc64/futex.h
@@ -1,110 +1 @@
-#ifndef _SPARC64_FUTEX_H
-#define _SPARC64_FUTEX_H
-
-#include <linux/futex.h>
-#include <linux/uaccess.h>
-#include <asm/errno.h>
-#include <asm/system.h>
-
-#define __futex_cas_op(insn, ret, oldval, uaddr, oparg)	\
-	__asm__ __volatile__(				\
-	"\n1:	lduwa	[%3] %%asi, %2\n"		\
-	"	" insn "\n"				\
-	"2:	casa	[%3] %%asi, %2, %1\n"		\
-	"	cmp	%2, %1\n"			\
-	"	bne,pn	%%icc, 1b\n"			\
-	"	 mov	0, %0\n"			\
-	"3:\n"						\
-	"	.section .fixup,#alloc,#execinstr\n"	\
-	"	.align	4\n"				\
-	"4:	sethi	%%hi(3b), %0\n"			\
-	"	jmpl	%0 + %%lo(3b), %%g0\n"		\
-	"	 mov	%5, %0\n"			\
-	"	.previous\n"				\
-	"	.section __ex_table,\"a\"\n"		\
-	"	.align	4\n"				\
-	"	.word	1b, 4b\n"			\
-	"	.word	2b, 4b\n"			\
-	"	.previous\n"				\
-	: "=&r" (ret), "=&r" (oldval), "=&r" (tem)	\
-	: "r" (uaddr), "r" (oparg), "i" (-EFAULT)	\
-	: "memory")
-
-static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
-{
-	int op = (encoded_op >> 28) & 7;
-	int cmp = (encoded_op >> 24) & 15;
-	int oparg = (encoded_op << 8) >> 20;
-	int cmparg = (encoded_op << 20) >> 20;
-	int oldval = 0, ret, tem;
-
-	if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(int))))
-		return -EFAULT;
-	if (unlikely((((unsigned long) uaddr) & 0x3UL)))
-		return -EINVAL;
-
-	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
-		oparg = 1 << oparg;
-
-	pagefault_disable();
-
-	switch (op) {
-	case FUTEX_OP_SET:
-		__futex_cas_op("mov\t%4, %1", ret, oldval, uaddr, oparg);
-		break;
-	case FUTEX_OP_ADD:
-		__futex_cas_op("add\t%2, %4, %1", ret, oldval, uaddr, oparg);
-		break;
-	case FUTEX_OP_OR:
-		__futex_cas_op("or\t%2, %4, %1", ret, oldval, uaddr, oparg);
-		break;
-	case FUTEX_OP_ANDN:
-		__futex_cas_op("and\t%2, %4, %1", ret, oldval, uaddr, oparg);
-		break;
-	case FUTEX_OP_XOR:
-		__futex_cas_op("xor\t%2, %4, %1", ret, oldval, uaddr, oparg);
-		break;
-	default:
-		ret = -ENOSYS;
-	}
-
-	pagefault_enable();
-
-	if (!ret) {
-		switch (cmp) {
-		case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
-		case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
-		case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
-		case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
-		case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
-		case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
-		default: ret = -ENOSYS;
-		}
-	}
-	return ret;
-}
-
-static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
-{
-	__asm__ __volatile__(
-	"\n1:	casa	[%3] %%asi, %2, %0\n"
-	"2:\n"
-	"	.section .fixup,#alloc,#execinstr\n"
-	"	.align	4\n"
-	"3:	sethi	%%hi(2b), %0\n"
-	"	jmpl	%0 + %%lo(2b), %%g0\n"
-	"	 mov	%4, %0\n"
-	"	.previous\n"
-	"	.section __ex_table,\"a\"\n"
-	"	.align	4\n"
-	"	.word	1b, 3b\n"
-	"	.previous\n"
-	: "=r" (newval)
-	: "0" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT)
-	: "memory");
-
-	return newval;
-}
-
-#endif /* !(_SPARC64_FUTEX_H) */
+#include <asm-sparc/futex.h>
diff --git a/include/asm-sparc64/hardirq.h b/include/asm-sparc64/hardirq.h
index 7c29fd1..63dca3d 100644
--- a/include/asm-sparc64/hardirq.h
+++ b/include/asm-sparc64/hardirq.h
@@ -1,19 +1 @@
-/* hardirq.h: 64-bit Sparc hard IRQ support.
- *
- * Copyright (C) 1997, 1998, 2005 David S. Miller (davem@davemloft.net)
- */
-
-#ifndef __SPARC64_HARDIRQ_H
-#define __SPARC64_HARDIRQ_H
-
-#include <asm/cpudata.h>
-
-#define __ARCH_IRQ_STAT
-#define local_softirq_pending() \
-	(local_cpu_data().__softirq_pending)
-
-void ack_bad_irq(unsigned int irq);
-
-#define HARDIRQ_BITS	8
-
-#endif /* !(__SPARC64_HARDIRQ_H) */
+#include <asm-sparc/hardirq.h>
diff --git a/include/asm-sparc64/head.h b/include/asm-sparc64/head.h
index 10e9dab..2254c09 100644
--- a/include/asm-sparc64/head.h
+++ b/include/asm-sparc64/head.h
@@ -1,76 +1 @@
-#ifndef _SPARC64_HEAD_H
-#define _SPARC64_HEAD_H
-
-#include <asm/pstate.h>
-
-	/* wrpr	%g0, val, %gl */
-#define SET_GL(val)	\
-	.word	0xa1902000 | val
-
-	/* rdpr %gl, %gN */
-#define GET_GL_GLOBAL(N)	\
-	.word	0x81540000 | (N << 25)
-
-#define KERNBASE	0x400000
-
-#define	PTREGS_OFF	(STACK_BIAS + STACKFRAME_SZ)
-
-#define __CHEETAH_ID	0x003e0014
-#define __JALAPENO_ID	0x003e0016
-#define __SERRANO_ID	0x003e0022
-
-#define CHEETAH_MANUF		0x003e
-#define CHEETAH_IMPL		0x0014 /* Ultra-III   */
-#define CHEETAH_PLUS_IMPL	0x0015 /* Ultra-III+  */
-#define JALAPENO_IMPL		0x0016 /* Ultra-IIIi  */
-#define JAGUAR_IMPL		0x0018 /* Ultra-IV    */
-#define PANTHER_IMPL		0x0019 /* Ultra-IV+   */
-#define SERRANO_IMPL		0x0022 /* Ultra-IIIi+ */
-
-#define BRANCH_IF_SUN4V(tmp1,label)		\
-	sethi	%hi(is_sun4v), %tmp1;		\
-	lduw	[%tmp1 + %lo(is_sun4v)], %tmp1; \
-	brnz,pn	%tmp1, label;			\
-	 nop
-
-#define BRANCH_IF_CHEETAH_BASE(tmp1,tmp2,label)	\
-	rdpr	%ver, %tmp1;			\
-	sethi	%hi(__CHEETAH_ID), %tmp2;	\
-	srlx	%tmp1, 32, %tmp1;		\
-	or	%tmp2, %lo(__CHEETAH_ID), %tmp2;\
-	cmp	%tmp1, %tmp2;			\
-	be,pn	%icc, label;			\
-	 nop;
-
-#define BRANCH_IF_JALAPENO(tmp1,tmp2,label)	\
-	rdpr	%ver, %tmp1;			\
-	sethi	%hi(__JALAPENO_ID), %tmp2;	\
-	srlx	%tmp1, 32, %tmp1;		\
-	or	%tmp2, %lo(__JALAPENO_ID), %tmp2;\
-	cmp	%tmp1, %tmp2;			\
-	be,pn	%icc, label;			\
-	 nop;
-
-#define BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(tmp1,tmp2,label)	\
-	rdpr	%ver, %tmp1;			\
-	srlx	%tmp1, (32 + 16), %tmp2;	\
-	cmp	%tmp2, CHEETAH_MANUF;		\
-	bne,pt	%xcc, 99f;			\
-	 sllx	%tmp1, 16, %tmp1;		\
-	srlx	%tmp1, (32 + 16), %tmp2;	\
-	cmp	%tmp2, CHEETAH_PLUS_IMPL;	\
-	bgeu,pt	%xcc, label;			\
-99:	 nop;
-
-#define BRANCH_IF_ANY_CHEETAH(tmp1,tmp2,label)	\
-	rdpr	%ver, %tmp1;			\
-	srlx	%tmp1, (32 + 16), %tmp2;	\
-	cmp	%tmp2, CHEETAH_MANUF;		\
-	bne,pt	%xcc, 99f;			\
-	 sllx	%tmp1, 16, %tmp1;		\
-	srlx	%tmp1, (32 + 16), %tmp2;	\
-	cmp	%tmp2, CHEETAH_IMPL;		\
-	bgeu,pt	%xcc, label;			\
-99:	 nop;
-
-#endif /* !(_SPARC64_HEAD_H) */
+#include <asm-sparc/head.h>
diff --git a/include/asm-sparc64/hugetlb.h b/include/asm-sparc64/hugetlb.h
index 412af58..21d8f0a 100644
--- a/include/asm-sparc64/hugetlb.h
+++ b/include/asm-sparc64/hugetlb.h
@@ -1,84 +1 @@
-#ifndef _ASM_SPARC64_HUGETLB_H
-#define _ASM_SPARC64_HUGETLB_H
-
-#include <asm/page.h>
-
-
-void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
-		     pte_t *ptep, pte_t pte);
-
-pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
-			      pte_t *ptep);
-
-void hugetlb_prefault_arch_hook(struct mm_struct *mm);
-
-static inline int is_hugepage_only_range(struct mm_struct *mm,
-					 unsigned long addr,
-					 unsigned long len) {
-	return 0;
-}
-
-/*
- * If the arch doesn't supply something else, assume that hugepage
- * size aligned regions are ok without further preparation.
- */
-static inline int prepare_hugepage_range(unsigned long addr, unsigned long len)
-{
-	if (len & ~HPAGE_MASK)
-		return -EINVAL;
-	if (addr & ~HPAGE_MASK)
-		return -EINVAL;
-	return 0;
-}
-
-static inline void hugetlb_free_pgd_range(struct mmu_gather **tlb,
-					  unsigned long addr, unsigned long end,
-					  unsigned long floor,
-					  unsigned long ceiling)
-{
-	free_pgd_range(tlb, addr, end, floor, ceiling);
-}
-
-static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
-					 unsigned long addr, pte_t *ptep)
-{
-}
-
-static inline int huge_pte_none(pte_t pte)
-{
-	return pte_none(pte);
-}
-
-static inline pte_t huge_pte_wrprotect(pte_t pte)
-{
-	return pte_wrprotect(pte);
-}
-
-static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
-					   unsigned long addr, pte_t *ptep)
-{
-	ptep_set_wrprotect(mm, addr, ptep);
-}
-
-static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
-					     unsigned long addr, pte_t *ptep,
-					     pte_t pte, int dirty)
-{
-	return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
-}
-
-static inline pte_t huge_ptep_get(pte_t *ptep)
-{
-	return *ptep;
-}
-
-static inline int arch_prepare_hugepage(struct page *page)
-{
-	return 0;
-}
-
-static inline void arch_release_hugepage(struct page *page)
-{
-}
-
-#endif /* _ASM_SPARC64_HUGETLB_H */
+#include <asm-sparc/hugetlb.h>
diff --git a/include/asm-sparc64/hvtramp.h b/include/asm-sparc64/hvtramp.h
index b2b9b94..fb46bfe 100644
--- a/include/asm-sparc64/hvtramp.h
+++ b/include/asm-sparc64/hvtramp.h
@@ -1,37 +1 @@
-#ifndef _SPARC64_HVTRAP_H
-#define _SPARC64_HVTRAP_H
-
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-
-struct hvtramp_mapping {
-	__u64		vaddr;
-	__u64		tte;
-};
-
-struct hvtramp_descr {
-	__u32			cpu;
-	__u32			num_mappings;
-	__u64			fault_info_va;
-	__u64			fault_info_pa;
-	__u64			thread_reg;
-	struct hvtramp_mapping	maps[1];
-};
-
-extern void hv_cpu_startup(unsigned long hvdescr_pa);
-
-#endif
-
-#define HVTRAMP_DESCR_CPU		0x00
-#define HVTRAMP_DESCR_NUM_MAPPINGS	0x04
-#define HVTRAMP_DESCR_FAULT_INFO_VA	0x08
-#define HVTRAMP_DESCR_FAULT_INFO_PA	0x10
-#define HVTRAMP_DESCR_THREAD_REG	0x18
-#define HVTRAMP_DESCR_MAPS		0x20
-
-#define HVTRAMP_MAPPING_VADDR		0x00
-#define HVTRAMP_MAPPING_TTE		0x08
-#define HVTRAMP_MAPPING_SIZE		0x10
-
-#endif /* _SPARC64_HVTRAP_H */
+#include <asm-sparc/hvtramp.h>
diff --git a/include/asm-sparc64/hw_irq.h b/include/asm-sparc64/hw_irq.h
index 8e44a83..16920a2 100644
--- a/include/asm-sparc64/hw_irq.h
+++ b/include/asm-sparc64/hw_irq.h
@@ -1,4 +1 @@
-#ifndef __ASM_SPARC64_HW_IRQ_H
-#define __ASM_SPARC64_HW_IRQ_H
-
-#endif
+#include <asm-sparc/hw_irq.h>
diff --git a/include/asm-sparc64/hypervisor.h b/include/asm-sparc64/hypervisor.h
index 3ad45df..fe7e51a 100644
--- a/include/asm-sparc64/hypervisor.h
+++ b/include/asm-sparc64/hypervisor.h
@@ -1,2945 +1 @@
-#ifndef _SPARC64_HYPERVISOR_H
-#define _SPARC64_HYPERVISOR_H
-
-/* Sun4v hypervisor interfaces and defines.
- *
- * Hypervisor calls are made via traps to software traps number 0x80
- * and above.  Registers %o0 to %o5 serve as argument, status, and
- * return value registers.
- *
- * There are two kinds of these traps.  First there are the normal
- * "fast traps" which use software trap 0x80 and encode the function
- * to invoke by number in register %o5.  Argument and return value
- * handling is as follows:
- *
- * -----------------------------------------------
- * |  %o5  | function number |     undefined     |
- * |  %o0  |   argument 0    |   return status   |
- * |  %o1  |   argument 1    |   return value 1  |
- * |  %o2  |   argument 2    |   return value 2  |
- * |  %o3  |   argument 3    |   return value 3  |
- * |  %o4  |   argument 4    |   return value 4  |
- * -----------------------------------------------
- *
- * The second type are "hyper-fast traps" which encode the function
- * number in the software trap number itself.  So these use trap
- * numbers > 0x80.  The register usage for hyper-fast traps is as
- * follows:
- *
- * -----------------------------------------------
- * |  %o0  |   argument 0    |   return status   |
- * |  %o1  |   argument 1    |   return value 1  |
- * |  %o2  |   argument 2    |   return value 2  |
- * |  %o3  |   argument 3    |   return value 3  |
- * |  %o4  |   argument 4    |   return value 4  |
- * -----------------------------------------------
- *
- * Registers providing explicit arguments to the hypervisor calls
- * are volatile across the call.  Upon return their values are
- * undefined unless explicitly specified as containing a particular
- * return value by the specific call.  The return status is always
- * returned in register %o0, zero indicates a successful execution of
- * the hypervisor call and other values indicate an error status as
- * defined below.  So, for example, if a hyper-fast trap takes
- * arguments 0, 1, and 2, then %o0, %o1, and %o2 are volatile across
- * the call and %o3, %o4, and %o5 would be preserved.
- *
- * If the hypervisor trap is invalid, or the fast trap function number
- * is invalid, HV_EBADTRAP will be returned in %o0.  Also, all 64-bits
- * of the argument and return values are significant.
- */
-
-/* Trap numbers.  */
-#define HV_FAST_TRAP		0x80
-#define HV_MMU_MAP_ADDR_TRAP	0x83
-#define HV_MMU_UNMAP_ADDR_TRAP	0x84
-#define HV_TTRACE_ADDENTRY_TRAP	0x85
-#define HV_CORE_TRAP		0xff
-
-/* Error codes.  */
-#define HV_EOK				0  /* Successful return            */
-#define HV_ENOCPU			1  /* Invalid CPU id               */
-#define HV_ENORADDR			2  /* Invalid real address         */
-#define HV_ENOINTR			3  /* Invalid interrupt id         */
-#define HV_EBADPGSZ			4  /* Invalid pagesize encoding    */
-#define HV_EBADTSB			5  /* Invalid TSB description      */
-#define HV_EINVAL			6  /* Invalid argument             */
-#define HV_EBADTRAP			7  /* Invalid function number      */
-#define HV_EBADALIGN			8  /* Invalid address alignment    */
-#define HV_EWOULDBLOCK			9  /* Cannot complete w/o blocking */
-#define HV_ENOACCESS			10 /* No access to resource        */
-#define HV_EIO				11 /* I/O error                    */
-#define HV_ECPUERROR			12 /* CPU in error state           */
-#define HV_ENOTSUPPORTED		13 /* Function not supported       */
-#define HV_ENOMAP			14 /* No mapping found             */
-#define HV_ETOOMANY			15 /* Too many items specified     */
-#define HV_ECHANNEL			16 /* Invalid LDC channel          */
-#define HV_EBUSY			17 /* Resource busy                */
-
-/* mach_exit()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_MACH_EXIT
- * ARG0:	exit code
- * ERRORS:	This service does not return.
- *
- * Stop all CPUs in the virtual domain and place them into the stopped
- * state.  The 64-bit exit code may be passed to a service entity as
- * the domain's exit status.  On systems without a service entity, the
- * domain will undergo a reset, and the boot firmware will be
- * reloaded.
- *
- * This function will never return to the guest that invokes it.
- *
- * Note: By convention an exit code of zero denotes a successful exit by
- *       the guest code.  A non-zero exit code denotes a guest specific
- *       error indication.
- *
- */
-#define HV_FAST_MACH_EXIT		0x00
-
-#ifndef __ASSEMBLY__
-extern void sun4v_mach_exit(unsigned long exit_code);
-#endif
-
-/* Domain services.  */
-
-/* mach_desc()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_MACH_DESC
- * ARG0:	buffer
- * ARG1:	length
- * RET0:	status
- * RET1:	length
- * ERRORS:	HV_EBADALIGN	Buffer is badly aligned
- *		HV_ENORADDR	Buffer is to an illegal real address.
- *		HV_EINVAL	Buffer length is too small for complete
- *				machine description.
- *
- * Copy the most current machine description into the buffer indicated
- * by the real address in ARG0.  The buffer provided must be 16 byte
- * aligned.  Upon success or HV_EINVAL, this service returns the
- * actual size of the machine description in the RET1 return value.
- *
- * Note: A method of determining the appropriate buffer size for the
- *       machine description is to first call this service with a buffer
- *       length of 0 bytes.
- */
-#define HV_FAST_MACH_DESC		0x01
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_mach_desc(unsigned long buffer_pa,
-				     unsigned long buf_len,
-				     unsigned long *real_buf_len);
-#endif
-
-/* mach_sir()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_MACH_SIR
- * ERRORS:	This service does not return.
- *
- * Perform a software initiated reset of the virtual machine domain.
- * All CPUs are captured as soon as possible, all hardware devices are
- * returned to the entry default state, and the domain is restarted at
- * the SIR (trap type 0x04) real trap table (RTBA) entry point on one
- * of the CPUs.  The single CPU restarted is selected as determined by
- * platform specific policy.  Memory is preserved across this
- * operation.
- */
-#define HV_FAST_MACH_SIR		0x02
-
-#ifndef __ASSEMBLY__
-extern void sun4v_mach_sir(void);
-#endif
-
-/* mach_set_watchdog()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_MACH_SET_WATCHDOG
- * ARG0:	timeout in milliseconds
- * RET0:	status
- * RET1:	time remaining in milliseconds
- *
- * A guest uses this API to set a watchdog timer.  Once the gues has set
- * the timer, it must call the timer service again either to disable or
- * postpone the expiration.  If the timer expires before being reset or
- * disabled, then the hypervisor take a platform specific action leading
- * to guest termination within a bounded time period.  The platform action
- * may include recovery actions such as reporting the expiration to a
- * Service Processor, and/or automatically restarting the gues.
- *
- * The 'timeout' parameter is specified in milliseconds, however the
- * implementated granularity is given by the 'watchdog-resolution'
- * property in the 'platform' node of the guest's machine description.
- * The largest allowed timeout value is specified by the
- * 'watchdog-max-timeout' property of the 'platform' node.
- *
- * If the 'timeout' argument is not zero, the watchdog timer is set to
- * expire after a minimum of 'timeout' milliseconds.
- *
- * If the 'timeout' argument is zero, the watchdog timer is disabled.
- *
- * If the 'timeout' value exceeds the value of the 'max-watchdog-timeout'
- * property, the hypervisor leaves the watchdog timer state unchanged,
- * and returns a status of EINVAL.
- *
- * The 'time remaining' return value is valid regardless of whether the
- * return status is EOK or EINVAL.  A non-zero return value indicates the
- * number of milliseconds that were remaining until the timer was to expire.
- * If less than one millisecond remains, the return value is '1'.  If the
- * watchdog timer was disabled at the time of the call, the return value is
- * zero.
- *
- * If the hypervisor cannot support the exact timeout value requested, but
- * can support a larger timeout value, the hypervisor may round the actual
- * timeout to a value larger than the requested timeout, consequently the
- * 'time remaining' return value may be larger than the previously requested
- * timeout value.
- *
- * Any guest OS debugger should be aware that the watchdog service may be in
- * use.  Consequently, it is recommended that the watchdog service is
- * disabled upon debugger entry (e.g. reaching a breakpoint), and then
- * re-enabled upon returning to normal execution.  The API has been designed
- * with this in mind, and the 'time remaining' result of the disable call may
- * be used directly as the timeout argument of the re-enable call.
- */
-#define HV_FAST_MACH_SET_WATCHDOG	0x05
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_mach_set_watchdog(unsigned long timeout,
-					     unsigned long *orig_timeout);
-#endif
-
-/* CPU services.
- *
- * CPUs represent devices that can execute software threads.  A single
- * chip that contains multiple cores or strands is represented as
- * multiple CPUs with unique CPU identifiers.  CPUs are exported to
- * OBP via the machine description (and to the OS via the OBP device
- * tree).  CPUs are always in one of three states: stopped, running,
- * or error.
- *
- * A CPU ID is a pre-assigned 16-bit value that uniquely identifies a
- * CPU within a logical domain.  Operations that are to be performed
- * on multiple CPUs specify them via a CPU list.  A CPU list is an
- * array in real memory, of which each 16-bit word is a CPU ID.  CPU
- * lists are passed through the API as two arguments.  The first is
- * the number of entries (16-bit words) in the CPU list, and the
- * second is the (real address) pointer to the CPU ID list.
- */
-
-/* cpu_start()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_CPU_START
- * ARG0:	CPU ID
- * ARG1:	PC
- * ARG2:	RTBA
- * ARG3:	target ARG0
- * RET0:	status
- * ERRORS:	ENOCPU		Invalid CPU ID
- *		EINVAL		Target CPU ID is not in the stopped state
- *		ENORADDR	Invalid PC or RTBA real address
- *		EBADALIGN	Unaligned PC or unaligned RTBA
- *		EWOULDBLOCK	Starting resources are not available
- *
- * Start CPU with given CPU ID with PC in %pc and with a real trap
- * base address value of RTBA.  The indicated CPU must be in the
- * stopped state.  The supplied RTBA must be aligned on a 256 byte
- * boundary.  On successful completion, the specified CPU will be in
- * the running state and will be supplied with "target ARG0" in %o0
- * and RTBA in %tba.
- */
-#define HV_FAST_CPU_START		0x10
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_cpu_start(unsigned long cpuid,
-				     unsigned long pc,
-				     unsigned long rtba,
-				     unsigned long arg0);
-#endif
-
-/* cpu_stop()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_CPU_STOP
- * ARG0:	CPU ID
- * RET0:	status
- * ERRORS:	ENOCPU		Invalid CPU ID
- *		EINVAL		Target CPU ID is the current cpu
- *		EINVAL		Target CPU ID is not in the running state
- *		EWOULDBLOCK	Stopping resources are not available
- *		ENOTSUPPORTED	Not supported on this platform
- *
- * The specified CPU is stopped.  The indicated CPU must be in the
- * running state.  On completion, it will be in the stopped state.  It
- * is not legal to stop the current CPU.
- *
- * Note: As this service cannot be used to stop the current cpu, this service
- *       may not be used to stop the last running CPU in a domain.  To stop
- *       and exit a running domain, a guest must use the mach_exit() service.
- */
-#define HV_FAST_CPU_STOP		0x11
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_cpu_stop(unsigned long cpuid);
-#endif
-
-/* cpu_yield()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_CPU_YIELD
- * RET0:	status
- * ERRORS:	No possible error.
- *
- * Suspend execution on the current CPU.  Execution will resume when
- * an interrupt (device, %stick_compare, or cross-call) is targeted to
- * the CPU.  On some CPUs, this API may be used by the hypervisor to
- * save power by disabling hardware strands.
- */
-#define HV_FAST_CPU_YIELD		0x12
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_cpu_yield(void);
-#endif
-
-/* cpu_qconf()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_CPU_QCONF
- * ARG0:	queue
- * ARG1:	base real address
- * ARG2:	number of entries
- * RET0:	status
- * ERRORS:	ENORADDR	Invalid base real address
- *		EINVAL		Invalid queue or number of entries is less
- *				than 2 or too large.
- *		EBADALIGN	Base real address is not correctly aligned
- *				for size.
- *
- * Configure the given queue to be placed at the given base real
- * address, with the given number of entries.  The number of entries
- * must be a power of 2.  The base real address must be aligned
- * exactly to match the queue size.  Each queue entry is 64 bytes
- * long, so for example a 32 entry queue must be aligned on a 2048
- * byte real address boundary.
- *
- * The specified queue is unconfigured if the number of entries is given
- * as zero.
- *
- * For the current version of this API service, the argument queue is defined
- * as follows:
- *
- *	queue		description
- *	-----		-------------------------
- *	0x3c		cpu mondo queue
- *	0x3d		device mondo queue
- *	0x3e		resumable error queue
- *	0x3f		non-resumable error queue
- *
- * Note: The maximum number of entries for each queue for a specific cpu may
- *       be determined from the machine description.
- */
-#define HV_FAST_CPU_QCONF		0x14
-#define  HV_CPU_QUEUE_CPU_MONDO		 0x3c
-#define  HV_CPU_QUEUE_DEVICE_MONDO	 0x3d
-#define  HV_CPU_QUEUE_RES_ERROR		 0x3e
-#define  HV_CPU_QUEUE_NONRES_ERROR	 0x3f
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_cpu_qconf(unsigned long type,
-				     unsigned long queue_paddr,
-				     unsigned long num_queue_entries);
-#endif
-
-/* cpu_qinfo()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_CPU_QINFO
- * ARG0:	queue
- * RET0:	status
- * RET1:	base real address
- * RET1:	number of entries
- * ERRORS:	EINVAL		Invalid queue
- *
- * Return the configuration info for the given queue.  The base real
- * address and number of entries of the defined queue are returned.
- * The queue argument values are the same as for cpu_qconf() above.
- *
- * If the specified queue is a valid queue number, but no queue has
- * been defined, the number of entries will be set to zero and the
- * base real address returned is undefined.
- */
-#define HV_FAST_CPU_QINFO		0x15
-
-/* cpu_mondo_send()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_CPU_MONDO_SEND
- * ARG0-1:	CPU list
- * ARG2:	data real address
- * RET0:	status
- * ERRORS:	EBADALIGN	Mondo data is not 64-byte aligned or CPU list
- *				is not 2-byte aligned.
- *		ENORADDR	Invalid data mondo address, or invalid cpu list
- *				address.
- *		ENOCPU		Invalid cpu in CPU list
- *		EWOULDBLOCK	Some or all of the listed CPUs did not receive
- *				the mondo
- *		ECPUERROR	One or more of the listed CPUs are in error
- *				state, use HV_FAST_CPU_STATE to see which ones
- *		EINVAL		CPU list includes caller's CPU ID
- *
- * Send a mondo interrupt to the CPUs in the given CPU list with the
- * 64-bytes at the given data real address.  The data must be 64-byte
- * aligned.  The mondo data will be delivered to the cpu_mondo queues
- * of the recipient CPUs.
- *
- * In all cases, error or not, the CPUs in the CPU list to which the
- * mondo has been successfully delivered will be indicated by having
- * their entry in CPU list updated with the value 0xffff.
- */
-#define HV_FAST_CPU_MONDO_SEND		0x42
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_cpu_mondo_send(unsigned long cpu_count, unsigned long cpu_list_pa, unsigned long mondo_block_pa);
-#endif
-
-/* cpu_myid()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_CPU_MYID
- * RET0:	status
- * RET1:	CPU ID
- * ERRORS:	No errors defined.
- *
- * Return the hypervisor ID handle for the current CPU.  Use by a
- * virtual CPU to discover it's own identity.
- */
-#define HV_FAST_CPU_MYID		0x16
-
-/* cpu_state()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_CPU_STATE
- * ARG0:	CPU ID
- * RET0:	status
- * RET1:	state
- * ERRORS:	ENOCPU		Invalid CPU ID
- *
- * Retrieve the current state of the CPU with the given CPU ID.
- */
-#define HV_FAST_CPU_STATE		0x17
-#define  HV_CPU_STATE_STOPPED		 0x01
-#define  HV_CPU_STATE_RUNNING		 0x02
-#define  HV_CPU_STATE_ERROR		 0x03
-
-#ifndef __ASSEMBLY__
-extern long sun4v_cpu_state(unsigned long cpuid);
-#endif
-
-/* cpu_set_rtba()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_CPU_SET_RTBA
- * ARG0:	RTBA
- * RET0:	status
- * RET1:	previous RTBA
- * ERRORS:	ENORADDR	Invalid RTBA real address
- *		EBADALIGN	RTBA is incorrectly aligned for a trap table
- *
- * Set the real trap base address of the local cpu to the given RTBA.
- * The supplied RTBA must be aligned on a 256 byte boundary.  Upon
- * success the previous value of the RTBA is returned in RET1.
- *
- * Note: This service does not affect %tba
- */
-#define HV_FAST_CPU_SET_RTBA		0x18
-
-/* cpu_set_rtba()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_CPU_GET_RTBA
- * RET0:	status
- * RET1:	previous RTBA
- * ERRORS:	No possible error.
- *
- * Returns the current value of RTBA in RET1.
- */
-#define HV_FAST_CPU_GET_RTBA		0x19
-
-/* MMU services.
- *
- * Layout of a TSB description for mmu_tsb_ctx{,non}0() calls.
- */
-#ifndef __ASSEMBLY__
-struct hv_tsb_descr {
-	unsigned short		pgsz_idx;
-	unsigned short		assoc;
-	unsigned int		num_ttes;	/* in TTEs */
-	unsigned int		ctx_idx;
-	unsigned int		pgsz_mask;
-	unsigned long		tsb_base;
-	unsigned long		resv;
-};
-#endif
-#define HV_TSB_DESCR_PGSZ_IDX_OFFSET	0x00
-#define HV_TSB_DESCR_ASSOC_OFFSET	0x02
-#define HV_TSB_DESCR_NUM_TTES_OFFSET	0x04
-#define HV_TSB_DESCR_CTX_IDX_OFFSET	0x08
-#define HV_TSB_DESCR_PGSZ_MASK_OFFSET	0x0c
-#define HV_TSB_DESCR_TSB_BASE_OFFSET	0x10
-#define HV_TSB_DESCR_RESV_OFFSET	0x18
-
-/* Page size bitmask.  */
-#define HV_PGSZ_MASK_8K			(1 << 0)
-#define HV_PGSZ_MASK_64K		(1 << 1)
-#define HV_PGSZ_MASK_512K		(1 << 2)
-#define HV_PGSZ_MASK_4MB		(1 << 3)
-#define HV_PGSZ_MASK_32MB		(1 << 4)
-#define HV_PGSZ_MASK_256MB		(1 << 5)
-#define HV_PGSZ_MASK_2GB		(1 << 6)
-#define HV_PGSZ_MASK_16GB		(1 << 7)
-
-/* Page size index.  The value given in the TSB descriptor must correspond
- * to the smallest page size specified in the pgsz_mask page size bitmask.
- */
-#define HV_PGSZ_IDX_8K			0
-#define HV_PGSZ_IDX_64K			1
-#define HV_PGSZ_IDX_512K		2
-#define HV_PGSZ_IDX_4MB			3
-#define HV_PGSZ_IDX_32MB		4
-#define HV_PGSZ_IDX_256MB		5
-#define HV_PGSZ_IDX_2GB			6
-#define HV_PGSZ_IDX_16GB		7
-
-/* MMU fault status area.
- *
- * MMU related faults have their status and fault address information
- * placed into a memory region made available by privileged code.  Each
- * virtual processor must make a mmu_fault_area_conf() call to tell the
- * hypervisor where that processor's fault status should be stored.
- *
- * The fault status block is a multiple of 64-bytes and must be aligned
- * on a 64-byte boundary.
- */
-#ifndef __ASSEMBLY__
-struct hv_fault_status {
-	unsigned long		i_fault_type;
-	unsigned long		i_fault_addr;
-	unsigned long		i_fault_ctx;
-	unsigned long		i_reserved[5];
-	unsigned long		d_fault_type;
-	unsigned long		d_fault_addr;
-	unsigned long		d_fault_ctx;
-	unsigned long		d_reserved[5];
-};
-#endif
-#define HV_FAULT_I_TYPE_OFFSET	0x00
-#define HV_FAULT_I_ADDR_OFFSET	0x08
-#define HV_FAULT_I_CTX_OFFSET	0x10
-#define HV_FAULT_D_TYPE_OFFSET	0x40
-#define HV_FAULT_D_ADDR_OFFSET	0x48
-#define HV_FAULT_D_CTX_OFFSET	0x50
-
-#define HV_FAULT_TYPE_FAST_MISS	1
-#define HV_FAULT_TYPE_FAST_PROT	2
-#define HV_FAULT_TYPE_MMU_MISS	3
-#define HV_FAULT_TYPE_INV_RA	4
-#define HV_FAULT_TYPE_PRIV_VIOL	5
-#define HV_FAULT_TYPE_PROT_VIOL	6
-#define HV_FAULT_TYPE_NFO	7
-#define HV_FAULT_TYPE_NFO_SEFF	8
-#define HV_FAULT_TYPE_INV_VA	9
-#define HV_FAULT_TYPE_INV_ASI	10
-#define HV_FAULT_TYPE_NC_ATOMIC	11
-#define HV_FAULT_TYPE_PRIV_ACT	12
-#define HV_FAULT_TYPE_RESV1	13
-#define HV_FAULT_TYPE_UNALIGNED	14
-#define HV_FAULT_TYPE_INV_PGSZ	15
-/* Values 16 --> -2 are reserved.  */
-#define HV_FAULT_TYPE_MULTIPLE	-1
-
-/* Flags argument for mmu_{map,unmap}_addr(), mmu_demap_{page,context,all}(),
- * and mmu_{map,unmap}_perm_addr().
- */
-#define HV_MMU_DMMU			0x01
-#define HV_MMU_IMMU			0x02
-#define HV_MMU_ALL			(HV_MMU_DMMU | HV_MMU_IMMU)
-
-/* mmu_map_addr()
- * TRAP:	HV_MMU_MAP_ADDR_TRAP
- * ARG0:	virtual address
- * ARG1:	mmu context
- * ARG2:	TTE
- * ARG3:	flags (HV_MMU_{IMMU,DMMU})
- * ERRORS:	EINVAL		Invalid virtual address, mmu context, or flags
- *		EBADPGSZ	Invalid page size value
- *		ENORADDR	Invalid real address in TTE
- *
- * Create a non-permanent mapping using the given TTE, virtual
- * address, and mmu context.  The flags argument determines which
- * (data, or instruction, or both) TLB the mapping gets loaded into.
- *
- * The behavior is undefined if the valid bit is clear in the TTE.
- *
- * Note: This API call is for privileged code to specify temporary translation
- *       mappings without the need to create and manage a TSB.
- */
-
-/* mmu_unmap_addr()
- * TRAP:	HV_MMU_UNMAP_ADDR_TRAP
- * ARG0:	virtual address
- * ARG1:	mmu context
- * ARG2:	flags (HV_MMU_{IMMU,DMMU})
- * ERRORS:	EINVAL		Invalid virtual address, mmu context, or flags
- *
- * Demaps the given virtual address in the given mmu context on this
- * CPU.  This function is intended to be used to demap pages mapped
- * with mmu_map_addr.  This service is equivalent to invoking
- * mmu_demap_page() with only the current CPU in the CPU list. The
- * flags argument determines which (data, or instruction, or both) TLB
- * the mapping gets unmapped from.
- *
- * Attempting to perform an unmap operation for a previously defined
- * permanent mapping will have undefined results.
- */
-
-/* mmu_tsb_ctx0()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_MMU_TSB_CTX0
- * ARG0:	number of TSB descriptions
- * ARG1:	TSB descriptions pointer
- * RET0:	status
- * ERRORS:	ENORADDR		Invalid TSB descriptions pointer or
- *					TSB base within a descriptor
- *		EBADALIGN		TSB descriptions pointer is not aligned
- *					to an 8-byte boundary, or TSB base
- *					within a descriptor is not aligned for
- *					the given TSB size
- *		EBADPGSZ		Invalid page size in a TSB descriptor
- *		EBADTSB			Invalid associativity or size in a TSB
- *					descriptor
- *		EINVAL			Invalid number of TSB descriptions, or
- *					invalid context index in a TSB
- *					descriptor, or index page size not
- *					equal to smallest page size in page
- *					size bitmask field.
- *
- * Configures the TSBs for the current CPU for virtual addresses with
- * context zero.  The TSB descriptions pointer is a pointer to an
- * array of the given number of TSB descriptions.
- *
- * Note: The maximum number of TSBs available to a virtual CPU is given by the
- *       mmu-max-#tsbs property of the cpu's corresponding "cpu" node in the
- *       machine description.
- */
-#define HV_FAST_MMU_TSB_CTX0		0x20
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_mmu_tsb_ctx0(unsigned long num_descriptions,
-					unsigned long tsb_desc_ra);
-#endif
-
-/* mmu_tsb_ctxnon0()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_MMU_TSB_CTXNON0
- * ARG0:	number of TSB descriptions
- * ARG1:	TSB descriptions pointer
- * RET0:	status
- * ERRORS:	Same as for mmu_tsb_ctx0() above.
- *
- * Configures the TSBs for the current CPU for virtual addresses with
- * non-zero contexts.  The TSB descriptions pointer is a pointer to an
- * array of the given number of TSB descriptions.
- *
- * Note: A maximum of 16 TSBs may be specified in the TSB description list.
- */
-#define HV_FAST_MMU_TSB_CTXNON0		0x21
-
-/* mmu_demap_page()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_MMU_DEMAP_PAGE
- * ARG0:	reserved, must be zero
- * ARG1:	reserved, must be zero
- * ARG2:	virtual address
- * ARG3:	mmu context
- * ARG4:	flags (HV_MMU_{IMMU,DMMU})
- * RET0:	status
- * ERRORS:	EINVAL			Invalid virutal address, context, or
- *					flags value
- *		ENOTSUPPORTED		ARG0 or ARG1 is non-zero
- *
- * Demaps any page mapping of the given virtual address in the given
- * mmu context for the current virtual CPU.  Any virtually tagged
- * caches are guaranteed to be kept consistent.  The flags argument
- * determines which TLB (instruction, or data, or both) participate in
- * the operation.
- *
- * ARG0 and ARG1 are both reserved and must be set to zero.
- */
-#define HV_FAST_MMU_DEMAP_PAGE		0x22
-
-/* mmu_demap_ctx()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_MMU_DEMAP_CTX
- * ARG0:	reserved, must be zero
- * ARG1:	reserved, must be zero
- * ARG2:	mmu context
- * ARG3:	flags (HV_MMU_{IMMU,DMMU})
- * RET0:	status
- * ERRORS:	EINVAL			Invalid context or flags value
- *		ENOTSUPPORTED		ARG0 or ARG1 is non-zero
- *
- * Demaps all non-permanent virtual page mappings previously specified
- * for the given context for the current virtual CPU.  Any virtual
- * tagged caches are guaranteed to be kept consistent.  The flags
- * argument determines which TLB (instruction, or data, or both)
- * participate in the operation.
- *
- * ARG0 and ARG1 are both reserved and must be set to zero.
- */
-#define HV_FAST_MMU_DEMAP_CTX		0x23
-
-/* mmu_demap_all()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_MMU_DEMAP_ALL
- * ARG0:	reserved, must be zero
- * ARG1:	reserved, must be zero
- * ARG2:	flags (HV_MMU_{IMMU,DMMU})
- * RET0:	status
- * ERRORS:	EINVAL			Invalid flags value
- *		ENOTSUPPORTED		ARG0 or ARG1 is non-zero
- *
- * Demaps all non-permanent virtual page mappings previously specified
- * for the current virtual CPU.  Any virtual tagged caches are
- * guaranteed to be kept consistent.  The flags argument determines
- * which TLB (instruction, or data, or both) participate in the
- * operation.
- *
- * ARG0 and ARG1 are both reserved and must be set to zero.
- */
-#define HV_FAST_MMU_DEMAP_ALL		0x24
-
-#ifndef __ASSEMBLY__
-extern void sun4v_mmu_demap_all(void);
-#endif
-
-/* mmu_map_perm_addr()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_MMU_MAP_PERM_ADDR
- * ARG0:	virtual address
- * ARG1:	reserved, must be zero
- * ARG2:	TTE
- * ARG3:	flags (HV_MMU_{IMMU,DMMU})
- * RET0:	status
- * ERRORS:	EINVAL			Invalid virutal address or flags value
- *		EBADPGSZ		Invalid page size value
- *		ENORADDR		Invalid real address in TTE
- *		ETOOMANY		Too many mappings (max of 8 reached)
- *
- * Create a permanent mapping using the given TTE and virtual address
- * for context 0 on the calling virtual CPU.  A maximum of 8 such
- * permanent mappings may be specified by privileged code.  Mappings
- * may be removed with mmu_unmap_perm_addr().
- *
- * The behavior is undefined if a TTE with the valid bit clear is given.
- *
- * Note: This call is used to specify address space mappings for which
- *       privileged code does not expect to receive misses.  For example,
- *       this mechanism can be used to map kernel nucleus code and data.
- */
-#define HV_FAST_MMU_MAP_PERM_ADDR	0x25
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_mmu_map_perm_addr(unsigned long vaddr,
-					     unsigned long set_to_zero,
-					     unsigned long tte,
-					     unsigned long flags);
-#endif
-
-/* mmu_fault_area_conf()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_MMU_FAULT_AREA_CONF
- * ARG0:	real address
- * RET0:	status
- * RET1:	previous mmu fault area real address
- * ERRORS:	ENORADDR		Invalid real address
- *		EBADALIGN		Invalid alignment for fault area
- *
- * Configure the MMU fault status area for the calling CPU.  A 64-byte
- * aligned real address specifies where MMU fault status information
- * is placed.  The return value is the previously specified area, or 0
- * for the first invocation.  Specifying a fault area at real address
- * 0 is not allowed.
- */
-#define HV_FAST_MMU_FAULT_AREA_CONF	0x26
-
-/* mmu_enable()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_MMU_ENABLE
- * ARG0:	enable flag
- * ARG1:	return target address
- * RET0:	status
- * ERRORS:	ENORADDR		Invalid real address when disabling
- *					translation.
- *		EBADALIGN		The return target address is not
- *					aligned to an instruction.
- *		EINVAL			The enable flag request the current
- *					operating mode (e.g. disable if already
- *					disabled)
- *
- * Enable or disable virtual address translation for the calling CPU
- * within the virtual machine domain.  If the enable flag is zero,
- * translation is disabled, any non-zero value will enable
- * translation.
- *
- * When this function returns, the newly selected translation mode
- * will be active.  If the mmu is being enabled, then the return
- * target address is a virtual address else it is a real address.
- *
- * Upon successful completion, control will be returned to the given
- * return target address (ie. the cpu will jump to that address).  On
- * failure, the previous mmu mode remains and the trap simply returns
- * as normal with the appropriate error code in RET0.
- */
-#define HV_FAST_MMU_ENABLE		0x27
-
-/* mmu_unmap_perm_addr()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_MMU_UNMAP_PERM_ADDR
- * ARG0:	virtual address
- * ARG1:	reserved, must be zero
- * ARG2:	flags (HV_MMU_{IMMU,DMMU})
- * RET0:	status
- * ERRORS:	EINVAL			Invalid virutal address or flags value
- *		ENOMAP			Specified mapping was not found
- *
- * Demaps any permanent page mapping (established via
- * mmu_map_perm_addr()) at the given virtual address for context 0 on
- * the current virtual CPU.  Any virtual tagged caches are guaranteed
- * to be kept consistent.
- */
-#define HV_FAST_MMU_UNMAP_PERM_ADDR	0x28
-
-/* mmu_tsb_ctx0_info()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_MMU_TSB_CTX0_INFO
- * ARG0:	max TSBs
- * ARG1:	buffer pointer
- * RET0:	status
- * RET1:	number of TSBs
- * ERRORS:	EINVAL			Supplied buffer is too small
- *		EBADALIGN		The buffer pointer is badly aligned
- *		ENORADDR		Invalid real address for buffer pointer
- *
- * Return the TSB configuration as previous defined by mmu_tsb_ctx0()
- * into the provided buffer.  The size of the buffer is given in ARG1
- * in terms of the number of TSB description entries.
- *
- * Upon return, RET1 always contains the number of TSB descriptions
- * previously configured.  If zero TSBs were configured, EOK is
- * returned with RET1 containing 0.
- */
-#define HV_FAST_MMU_TSB_CTX0_INFO	0x29
-
-/* mmu_tsb_ctxnon0_info()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_MMU_TSB_CTXNON0_INFO
- * ARG0:	max TSBs
- * ARG1:	buffer pointer
- * RET0:	status
- * RET1:	number of TSBs
- * ERRORS:	EINVAL			Supplied buffer is too small
- *		EBADALIGN		The buffer pointer is badly aligned
- *		ENORADDR		Invalid real address for buffer pointer
- *
- * Return the TSB configuration as previous defined by
- * mmu_tsb_ctxnon0() into the provided buffer.  The size of the buffer
- * is given in ARG1 in terms of the number of TSB description entries.
- *
- * Upon return, RET1 always contains the number of TSB descriptions
- * previously configured.  If zero TSBs were configured, EOK is
- * returned with RET1 containing 0.
- */
-#define HV_FAST_MMU_TSB_CTXNON0_INFO	0x2a
-
-/* mmu_fault_area_info()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_MMU_FAULT_AREA_INFO
- * RET0:	status
- * RET1:	fault area real address
- * ERRORS:	No errors defined.
- *
- * Return the currently defined MMU fault status area for the current
- * CPU.  The real address of the fault status area is returned in
- * RET1, or 0 is returned in RET1 if no fault status area is defined.
- *
- * Note: mmu_fault_area_conf() may be called with the return value (RET1)
- *       from this service if there is a need to save and restore the fault
- *	 area for a cpu.
- */
-#define HV_FAST_MMU_FAULT_AREA_INFO	0x2b
-
-/* Cache and Memory services. */
-
-/* mem_scrub()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_MEM_SCRUB
- * ARG0:	real address
- * ARG1:	length
- * RET0:	status
- * RET1:	length scrubbed
- * ERRORS:	ENORADDR	Invalid real address
- *		EBADALIGN	Start address or length are not correctly
- *				aligned
- *		EINVAL		Length is zero
- *
- * Zero the memory contents in the range real address to real address
- * plus length minus 1.  Also, valid ECC will be generated for that
- * memory address range.  Scrubbing is started at the given real
- * address, but may not scrub the entire given length.  The actual
- * length scrubbed will be returned in RET1.
- *
- * The real address and length must be aligned on an 8K boundary, or
- * contain the start address and length from a sun4v error report.
- *
- * Note: There are two uses for this function.  The first use is to block clear
- *       and initialize memory and the second is to scrub an u ncorrectable
- *       error reported via a resumable or non-resumable trap.  The second
- *       use requires the arguments to be equal to the real address and length
- *       provided in a sun4v memory error report.
- */
-#define HV_FAST_MEM_SCRUB		0x31
-
-/* mem_sync()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_MEM_SYNC
- * ARG0:	real address
- * ARG1:	length
- * RET0:	status
- * RET1:	length synced
- * ERRORS:	ENORADDR	Invalid real address
- *		EBADALIGN	Start address or length are not correctly
- *				aligned
- *		EINVAL		Length is zero
- *
- * Force the next access within the real address to real address plus
- * length minus 1 to be fetches from main system memory.  Less than
- * the given length may be synced, the actual amount synced is
- * returned in RET1.  The real address and length must be aligned on
- * an 8K boundary.
- */
-#define HV_FAST_MEM_SYNC		0x32
-
-/* Time of day services.
- *
- * The hypervisor maintains the time of day on a per-domain basis.
- * Changing the time of day in one domain does not affect the time of
- * day on any other domain.
- *
- * Time is described by a single unsigned 64-bit word which is the
- * number of seconds since the UNIX Epoch (00:00:00 UTC, January 1,
- * 1970).
- */
-
-/* tod_get()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_TOD_GET
- * RET0:	status
- * RET1:	TOD
- * ERRORS:	EWOULDBLOCK	TOD resource is temporarily unavailable
- *		ENOTSUPPORTED	If TOD not supported on this platform
- *
- * Return the current time of day.  May block if TOD access is
- * temporarily not possible.
- */
-#define HV_FAST_TOD_GET			0x50
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_tod_get(unsigned long *time);
-#endif
-
-/* tod_set()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_TOD_SET
- * ARG0:	TOD
- * RET0:	status
- * ERRORS:	EWOULDBLOCK	TOD resource is temporarily unavailable
- *		ENOTSUPPORTED	If TOD not supported on this platform
- *
- * The current time of day is set to the value specified in ARG0.  May
- * block if TOD access is temporarily not possible.
- */
-#define HV_FAST_TOD_SET			0x51
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_tod_set(unsigned long time);
-#endif
-
-/* Console services */
-
-/* con_getchar()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_CONS_GETCHAR
- * RET0:	status
- * RET1:	character
- * ERRORS:	EWOULDBLOCK	No character available.
- *
- * Returns a character from the console device.  If no character is
- * available then an EWOULDBLOCK error is returned.  If a character is
- * available, then the returned status is EOK and the character value
- * is in RET1.
- *
- * A virtual BREAK is represented by the 64-bit value -1.
- *
- * A virtual HUP signal is represented by the 64-bit value -2.
- */
-#define HV_FAST_CONS_GETCHAR		0x60
-
-/* con_putchar()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_CONS_PUTCHAR
- * ARG0:	character
- * RET0:	status
- * ERRORS:	EINVAL		Illegal character
- *		EWOULDBLOCK	Output buffer currently full, would block
- *
- * Send a character to the console device.  Only character values
- * between 0 and 255 may be used.  Values outside this range are
- * invalid except for the 64-bit value -1 which is used to send a
- * virtual BREAK.
- */
-#define HV_FAST_CONS_PUTCHAR		0x61
-
-/* con_read()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_CONS_READ
- * ARG0:	buffer real address
- * ARG1:	buffer size in bytes
- * RET0:	status
- * RET1:	bytes read or BREAK or HUP
- * ERRORS:	EWOULDBLOCK	No character available.
- *
- * Reads characters into a buffer from the console device.  If no
- * character is available then an EWOULDBLOCK error is returned.
- * If a character is available, then the returned status is EOK
- * and the number of bytes read into the given buffer is provided
- * in RET1.
- *
- * A virtual BREAK is represented by the 64-bit RET1 value -1.
- *
- * A virtual HUP signal is represented by the 64-bit RET1 value -2.
- *
- * If BREAK or HUP are indicated, no bytes were read into buffer.
- */
-#define HV_FAST_CONS_READ		0x62
-
-/* con_write()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_CONS_WRITE
- * ARG0:	buffer real address
- * ARG1:	buffer size in bytes
- * RET0:	status
- * RET1:	bytes written
- * ERRORS:	EWOULDBLOCK	Output buffer currently full, would block
- *
- * Send a characters in buffer to the console device.  Breaks must be
- * sent using con_putchar().
- */
-#define HV_FAST_CONS_WRITE		0x63
-
-#ifndef __ASSEMBLY__
-extern long sun4v_con_getchar(long *status);
-extern long sun4v_con_putchar(long c);
-extern long sun4v_con_read(unsigned long buffer,
-			   unsigned long size,
-			   unsigned long *bytes_read);
-extern unsigned long sun4v_con_write(unsigned long buffer,
-				     unsigned long size,
-				     unsigned long *bytes_written);
-#endif
-
-/* mach_set_soft_state()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_MACH_SET_SOFT_STATE
- * ARG0:	software state
- * ARG1:	software state description pointer
- * RET0:	status
- * ERRORS:	EINVAL		software state not valid or software state
- *				description is not NULL terminated
- *		ENORADDR	software state description pointer is not a
- *				valid real address
- *		EBADALIGNED	software state description is not correctly
- *				aligned
- *
- * This allows the guest to report it's soft state to the hypervisor.  There
- * are two primary components to this state.  The first part states whether
- * the guest software is running or not.  The second containts optional
- * details specific to the software.
- *
- * The software state argument is defined below in HV_SOFT_STATE_*, and
- * indicates whether the guest is operating normally or in a transitional
- * state.
- *
- * The software state description argument is a real address of a data buffer
- * of size 32-bytes aligned on a 32-byte boundary.  It is treated as a NULL
- * terminated 7-bit ASCII string of up to 31 characters not including the
- * NULL termination.
- */
-#define HV_FAST_MACH_SET_SOFT_STATE	0x70
-#define  HV_SOFT_STATE_NORMAL		 0x01
-#define  HV_SOFT_STATE_TRANSITION	 0x02
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_mach_set_soft_state(unsigned long soft_state,
-					       unsigned long msg_string_ra);
-#endif
-
-/* mach_get_soft_state()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_MACH_GET_SOFT_STATE
- * ARG0:	software state description pointer
- * RET0:	status
- * RET1:	software state
- * ERRORS:	ENORADDR	software state description pointer is not a
- *				valid real address
- *		EBADALIGNED	software state description is not correctly
- *				aligned
- *
- * Retrieve the current value of the guest's software state.  The rules
- * for the software state pointer are the same as for mach_set_soft_state()
- * above.
- */
-#define HV_FAST_MACH_GET_SOFT_STATE	0x71
-
-/* svc_send()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_SVC_SEND
- * ARG0:	service ID
- * ARG1:	buffer real address
- * ARG2:	buffer size
- * RET0:	STATUS
- * RET1:	sent_bytes
- *
- * Be careful, all output registers are clobbered by this operation,
- * so for example it is not possible to save away a value in %o4
- * across the trap.
- */
-#define HV_FAST_SVC_SEND		0x80
-
-/* svc_recv()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_SVC_RECV
- * ARG0:	service ID
- * ARG1:	buffer real address
- * ARG2:	buffer size
- * RET0:	STATUS
- * RET1:	recv_bytes
- *
- * Be careful, all output registers are clobbered by this operation,
- * so for example it is not possible to save away a value in %o4
- * across the trap.
- */
-#define HV_FAST_SVC_RECV		0x81
-
-/* svc_getstatus()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_SVC_GETSTATUS
- * ARG0:	service ID
- * RET0:	STATUS
- * RET1:	status bits
- */
-#define HV_FAST_SVC_GETSTATUS		0x82
-
-/* svc_setstatus()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_SVC_SETSTATUS
- * ARG0:	service ID
- * ARG1:	bits to set
- * RET0:	STATUS
- */
-#define HV_FAST_SVC_SETSTATUS		0x83
-
-/* svc_clrstatus()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_SVC_CLRSTATUS
- * ARG0:	service ID
- * ARG1:	bits to clear
- * RET0:	STATUS
- */
-#define HV_FAST_SVC_CLRSTATUS		0x84
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_svc_send(unsigned long svc_id,
-				    unsigned long buffer,
-				    unsigned long buffer_size,
-				    unsigned long *sent_bytes);
-extern unsigned long sun4v_svc_recv(unsigned long svc_id,
-				    unsigned long buffer,
-				    unsigned long buffer_size,
-				    unsigned long *recv_bytes);
-extern unsigned long sun4v_svc_getstatus(unsigned long svc_id,
-					 unsigned long *status_bits);
-extern unsigned long sun4v_svc_setstatus(unsigned long svc_id,
-					 unsigned long status_bits);
-extern unsigned long sun4v_svc_clrstatus(unsigned long svc_id,
-					 unsigned long status_bits);
-#endif
-
-/* Trap trace services.
- *
- * The hypervisor provides a trap tracing capability for privileged
- * code running on each virtual CPU.  Privileged code provides a
- * round-robin trap trace queue within which the hypervisor writes
- * 64-byte entries detailing hyperprivileged traps taken n behalf of
- * privileged code.  This is provided as a debugging capability for
- * privileged code.
- *
- * The trap trace control structure is 64-bytes long and placed at the
- * start (offset 0) of the trap trace buffer, and is described as
- * follows:
- */
-#ifndef __ASSEMBLY__
-struct hv_trap_trace_control {
-	unsigned long		head_offset;
-	unsigned long		tail_offset;
-	unsigned long		__reserved[0x30 / sizeof(unsigned long)];
-};
-#endif
-#define HV_TRAP_TRACE_CTRL_HEAD_OFFSET	0x00
-#define HV_TRAP_TRACE_CTRL_TAIL_OFFSET	0x08
-
-/* The head offset is the offset of the most recently completed entry
- * in the trap-trace buffer.  The tail offset is the offset of the
- * next entry to be written.  The control structure is owned and
- * modified by the hypervisor.  A guest may not modify the control
- * structure contents.  Attempts to do so will result in undefined
- * behavior for the guest.
- *
- * Each trap trace buffer entry is layed out as follows:
- */
-#ifndef __ASSEMBLY__
-struct hv_trap_trace_entry {
-	unsigned char	type;		/* Hypervisor or guest entry?	*/
-	unsigned char	hpstate;	/* Hyper-privileged state	*/
-	unsigned char	tl;		/* Trap level			*/
-	unsigned char	gl;		/* Global register level	*/
-	unsigned short	tt;		/* Trap type			*/
-	unsigned short	tag;		/* Extended trap identifier	*/
-	unsigned long	tstate;		/* Trap state			*/
-	unsigned long	tick;		/* Tick				*/
-	unsigned long	tpc;		/* Trap PC			*/
-	unsigned long	f1;		/* Entry specific		*/
-	unsigned long	f2;		/* Entry specific		*/
-	unsigned long	f3;		/* Entry specific		*/
-	unsigned long	f4;		/* Entry specific		*/
-};
-#endif
-#define HV_TRAP_TRACE_ENTRY_TYPE	0x00
-#define HV_TRAP_TRACE_ENTRY_HPSTATE	0x01
-#define HV_TRAP_TRACE_ENTRY_TL		0x02
-#define HV_TRAP_TRACE_ENTRY_GL		0x03
-#define HV_TRAP_TRACE_ENTRY_TT		0x04
-#define HV_TRAP_TRACE_ENTRY_TAG		0x06
-#define HV_TRAP_TRACE_ENTRY_TSTATE	0x08
-#define HV_TRAP_TRACE_ENTRY_TICK	0x10
-#define HV_TRAP_TRACE_ENTRY_TPC		0x18
-#define HV_TRAP_TRACE_ENTRY_F1		0x20
-#define HV_TRAP_TRACE_ENTRY_F2		0x28
-#define HV_TRAP_TRACE_ENTRY_F3		0x30
-#define HV_TRAP_TRACE_ENTRY_F4		0x38
-
-/* The type field is encoded as follows.  */
-#define HV_TRAP_TYPE_UNDEF		0x00 /* Entry content undefined     */
-#define HV_TRAP_TYPE_HV			0x01 /* Hypervisor trap entry       */
-#define HV_TRAP_TYPE_GUEST		0xff /* Added via ttrace_addentry() */
-
-/* ttrace_buf_conf()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_TTRACE_BUF_CONF
- * ARG0:	real address
- * ARG1:	number of entries
- * RET0:	status
- * RET1:	number of entries
- * ERRORS:	ENORADDR	Invalid real address
- *		EINVAL		Size is too small
- *		EBADALIGN	Real address not aligned on 64-byte boundary
- *
- * Requests hypervisor trap tracing and declares a virtual CPU's trap
- * trace buffer to the hypervisor.  The real address supplies the real
- * base address of the trap trace queue and must be 64-byte aligned.
- * Specifying a value of 0 for the number of entries disables trap
- * tracing for the calling virtual CPU.  The buffer allocated must be
- * sized for a power of two number of 64-byte trap trace entries plus
- * an initial 64-byte control structure.
- * 
- * This may be invoked any number of times so that a virtual CPU may
- * relocate a trap trace buffer or create "snapshots" of information.
- *
- * If the real address is illegal or badly aligned, then trap tracing
- * is disabled and an error is returned.
- *
- * Upon failure with EINVAL, this service call returns in RET1 the
- * minimum number of buffer entries required.  Upon other failures
- * RET1 is undefined.
- */
-#define HV_FAST_TTRACE_BUF_CONF		0x90
-
-/* ttrace_buf_info()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_TTRACE_BUF_INFO
- * RET0:	status
- * RET1:	real address
- * RET2:	size
- * ERRORS:	None defined.
- *
- * Returns the size and location of the previously declared trap-trace
- * buffer.  In the event that no buffer was previously defined, or the
- * buffer is disabled, this call will return a size of zero bytes.
- */
-#define HV_FAST_TTRACE_BUF_INFO		0x91
-
-/* ttrace_enable()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_TTRACE_ENABLE
- * ARG0:	enable
- * RET0:	status
- * RET1:	previous enable state
- * ERRORS:	EINVAL		No trap trace buffer currently defined
- *
- * Enable or disable trap tracing, and return the previous enabled
- * state in RET1.  Future systems may define various flags for the
- * enable argument (ARG0), for the moment a guest should pass
- * "(uint64_t) -1" to enable, and "(uint64_t) 0" to disable all
- * tracing - which will ensure future compatability.
- */
-#define HV_FAST_TTRACE_ENABLE		0x92
-
-/* ttrace_freeze()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_TTRACE_FREEZE
- * ARG0:	freeze
- * RET0:	status
- * RET1:	previous freeze state
- * ERRORS:	EINVAL		No trap trace buffer currently defined
- *
- * Freeze or unfreeze trap tracing, returning the previous freeze
- * state in RET1.  A guest should pass a non-zero value to freeze and
- * a zero value to unfreeze all tracing.  The returned previous state
- * is 0 for not frozen and 1 for frozen.
- */
-#define HV_FAST_TTRACE_FREEZE		0x93
-
-/* ttrace_addentry()
- * TRAP:	HV_TTRACE_ADDENTRY_TRAP
- * ARG0:	tag (16-bits)
- * ARG1:	data word 0
- * ARG2:	data word 1
- * ARG3:	data word 2
- * ARG4:	data word 3
- * RET0:	status
- * ERRORS:	EINVAL		No trap trace buffer currently defined
- *
- * Add an entry to the trap trace buffer.  Upon return only ARG0/RET0
- * is modified - none of the other registers holding arguments are
- * volatile across this hypervisor service.
- */
-
-/* Core dump services.
- *
- * Since the hypervisor viraulizes and thus obscures a lot of the
- * physical machine layout and state, traditional OS crash dumps can
- * be difficult to diagnose especially when the problem is a
- * configuration error of some sort.
- *
- * The dump services provide an opaque buffer into which the
- * hypervisor can place it's internal state in order to assist in
- * debugging such situations.  The contents are opaque and extremely
- * platform and hypervisor implementation specific.  The guest, during
- * a core dump, requests that the hypervisor update any information in
- * the dump buffer in preparation to being dumped as part of the
- * domain's memory image.
- */
-
-/* dump_buf_update()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_DUMP_BUF_UPDATE
- * ARG0:	real address
- * ARG1:	size
- * RET0:	status
- * RET1:	required size of dump buffer
- * ERRORS:	ENORADDR	Invalid real address
- *		EBADALIGN	Real address is not aligned on a 64-byte
- *				boundary
- *		EINVAL		Size is non-zero but less than minimum size
- *				required
- *		ENOTSUPPORTED	Operation not supported on current logical
- *				domain
- *
- * Declare a domain dump buffer to the hypervisor.  The real address
- * provided for the domain dump buffer must be 64-byte aligned.  The
- * size specifies the size of the dump buffer and may be larger than
- * the minimum size specified in the machine description.  The
- * hypervisor will fill the dump buffer with opaque data.
- *
- * Note: A guest may elect to include dump buffer contents as part of a crash
- *       dump to assist with debugging.  This function may be called any number
- *       of times so that a guest may relocate a dump buffer, or create
- *       "snapshots" of any dump-buffer information.  Each call to
- *       dump_buf_update() atomically declares the new dump buffer to the
- *       hypervisor.
- *
- * A specified size of 0 unconfigures the dump buffer.  If the real
- * address is illegal or badly aligned, then any currently active dump
- * buffer is disabled and an error is returned.
- *
- * In the event that the call fails with EINVAL, RET1 contains the
- * minimum size requires by the hypervisor for a valid dump buffer.
- */
-#define HV_FAST_DUMP_BUF_UPDATE		0x94
-
-/* dump_buf_info()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_DUMP_BUF_INFO
- * RET0:	status
- * RET1:	real address of current dump buffer
- * RET2:	size of current dump buffer
- * ERRORS:	No errors defined.
- *
- * Return the currently configures dump buffer description.  A
- * returned size of 0 bytes indicates an undefined dump buffer.  In
- * this case the return address in RET1 is undefined.
- */
-#define HV_FAST_DUMP_BUF_INFO		0x95
-
-/* Device interrupt services.
- *
- * Device interrupts are allocated to system bus bridges by the hypervisor,
- * and described to OBP in the machine description.  OBP then describes
- * these interrupts to the OS via properties in the device tree.
- *
- * Terminology:
- *
- *	cpuid		Unique opaque value which represents a target cpu.
- *
- *	devhandle	Device handle.  It uniquely identifies a device, and
- *			consistes of the lower 28-bits of the hi-cell of the
- *			first entry of the device's "reg" property in the
- *			OBP device tree.
- *
- *	devino		Device interrupt number.  Specifies the relative
- *			interrupt number within the device.  The unique
- *			combination of devhandle and devino are used to
- *			identify a specific device interrupt.
- *
- *			Note: The devino value is the same as the values in the
- *			      "interrupts" property or "interrupt-map" property
- *			      in the OBP device tree for that device.
- *
- *	sysino		System interrupt number.  A 64-bit unsigned interger
- *			representing a unique interrupt within a virtual
- *			machine.
- *
- *	intr_state	A flag representing the interrupt state for a given
- *			sysino.  The state values are defined below.
- *
- *	intr_enabled	A flag representing the 'enabled' state for a given
- *			sysino.  The enable values are defined below.
- */
-
-#define HV_INTR_STATE_IDLE		0 /* Nothing pending */
-#define HV_INTR_STATE_RECEIVED		1 /* Interrupt received by hardware */
-#define HV_INTR_STATE_DELIVERED		2 /* Interrupt delivered to queue */
-
-#define HV_INTR_DISABLED		0 /* sysino not enabled */
-#define HV_INTR_ENABLED			1 /* sysino enabled */
-
-/* intr_devino_to_sysino()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_INTR_DEVINO2SYSINO
- * ARG0:	devhandle
- * ARG1:	devino
- * RET0:	status
- * RET1:	sysino
- * ERRORS:	EINVAL		Invalid devhandle/devino
- *
- * Converts a device specific interrupt number of the given
- * devhandle/devino into a system specific ino (sysino).
- */
-#define HV_FAST_INTR_DEVINO2SYSINO	0xa0
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_devino_to_sysino(unsigned long devhandle,
-					    unsigned long devino);
-#endif
-
-/* intr_getenabled()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_INTR_GETENABLED
- * ARG0:	sysino
- * RET0:	status
- * RET1:	intr_enabled (HV_INTR_{DISABLED,ENABLED})
- * ERRORS:	EINVAL		Invalid sysino
- *
- * Returns interrupt enabled state in RET1 for the interrupt defined
- * by the given sysino.
- */
-#define HV_FAST_INTR_GETENABLED		0xa1
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_intr_getenabled(unsigned long sysino);
-#endif
-
-/* intr_setenabled()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_INTR_SETENABLED
- * ARG0:	sysino
- * ARG1:	intr_enabled (HV_INTR_{DISABLED,ENABLED})
- * RET0:	status
- * ERRORS:	EINVAL		Invalid sysino or intr_enabled value
- *
- * Set the 'enabled' state of the interrupt sysino.
- */
-#define HV_FAST_INTR_SETENABLED		0xa2
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_intr_setenabled(unsigned long sysino, unsigned long intr_enabled);
-#endif
-
-/* intr_getstate()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_INTR_GETSTATE
- * ARG0:	sysino
- * RET0:	status
- * RET1:	intr_state (HV_INTR_STATE_*)
- * ERRORS:	EINVAL		Invalid sysino
- *
- * Returns current state of the interrupt defined by the given sysino.
- */
-#define HV_FAST_INTR_GETSTATE		0xa3
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_intr_getstate(unsigned long sysino);
-#endif
-
-/* intr_setstate()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_INTR_SETSTATE
- * ARG0:	sysino
- * ARG1:	intr_state (HV_INTR_STATE_*)
- * RET0:	status
- * ERRORS:	EINVAL		Invalid sysino or intr_state value
- *
- * Sets the current state of the interrupt described by the given sysino
- * value.
- *
- * Note: Setting the state to HV_INTR_STATE_IDLE clears any pending
- *       interrupt for sysino.
- */
-#define HV_FAST_INTR_SETSTATE		0xa4
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_intr_setstate(unsigned long sysino, unsigned long intr_state);
-#endif
-
-/* intr_gettarget()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_INTR_GETTARGET
- * ARG0:	sysino
- * RET0:	status
- * RET1:	cpuid
- * ERRORS:	EINVAL		Invalid sysino
- *
- * Returns CPU that is the current target of the interrupt defined by
- * the given sysino.  The CPU value returned is undefined if the target
- * has not been set via intr_settarget().
- */
-#define HV_FAST_INTR_GETTARGET		0xa5
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_intr_gettarget(unsigned long sysino);
-#endif
-
-/* intr_settarget()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_INTR_SETTARGET
- * ARG0:	sysino
- * ARG1:	cpuid
- * RET0:	status
- * ERRORS:	EINVAL		Invalid sysino
- *		ENOCPU		Invalid cpuid
- *
- * Set the target CPU for the interrupt defined by the given sysino.
- */
-#define HV_FAST_INTR_SETTARGET		0xa6
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_intr_settarget(unsigned long sysino, unsigned long cpuid);
-#endif
-
-/* vintr_get_cookie()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_VINTR_GET_COOKIE
- * ARG0:	device handle
- * ARG1:	device ino
- * RET0:	status
- * RET1:	cookie
- */
-#define HV_FAST_VINTR_GET_COOKIE	0xa7
-
-/* vintr_set_cookie()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_VINTR_SET_COOKIE
- * ARG0:	device handle
- * ARG1:	device ino
- * ARG2:	cookie
- * RET0:	status
- */
-#define HV_FAST_VINTR_SET_COOKIE	0xa8
-
-/* vintr_get_valid()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_VINTR_GET_VALID
- * ARG0:	device handle
- * ARG1:	device ino
- * RET0:	status
- * RET1:	valid state
- */
-#define HV_FAST_VINTR_GET_VALID		0xa9
-
-/* vintr_set_valid()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_VINTR_SET_VALID
- * ARG0:	device handle
- * ARG1:	device ino
- * ARG2:	valid state
- * RET0:	status
- */
-#define HV_FAST_VINTR_SET_VALID		0xaa
-
-/* vintr_get_state()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_VINTR_GET_STATE
- * ARG0:	device handle
- * ARG1:	device ino
- * RET0:	status
- * RET1:	state
- */
-#define HV_FAST_VINTR_GET_STATE		0xab
-
-/* vintr_set_state()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_VINTR_SET_STATE
- * ARG0:	device handle
- * ARG1:	device ino
- * ARG2:	state
- * RET0:	status
- */
-#define HV_FAST_VINTR_SET_STATE		0xac
-
-/* vintr_get_target()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_VINTR_GET_TARGET
- * ARG0:	device handle
- * ARG1:	device ino
- * RET0:	status
- * RET1:	cpuid
- */
-#define HV_FAST_VINTR_GET_TARGET	0xad
-
-/* vintr_set_target()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_VINTR_SET_TARGET
- * ARG0:	device handle
- * ARG1:	device ino
- * ARG2:	cpuid
- * RET0:	status
- */
-#define HV_FAST_VINTR_SET_TARGET	0xae
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_vintr_get_cookie(unsigned long dev_handle,
-					    unsigned long dev_ino,
-					    unsigned long *cookie);
-extern unsigned long sun4v_vintr_set_cookie(unsigned long dev_handle,
-					    unsigned long dev_ino,
-					    unsigned long cookie);
-extern unsigned long sun4v_vintr_get_valid(unsigned long dev_handle,
-					   unsigned long dev_ino,
-					   unsigned long *valid);
-extern unsigned long sun4v_vintr_set_valid(unsigned long dev_handle,
-					   unsigned long dev_ino,
-					   unsigned long valid);
-extern unsigned long sun4v_vintr_get_state(unsigned long dev_handle,
-					   unsigned long dev_ino,
-					   unsigned long *state);
-extern unsigned long sun4v_vintr_set_state(unsigned long dev_handle,
-					   unsigned long dev_ino,
-					   unsigned long state);
-extern unsigned long sun4v_vintr_get_target(unsigned long dev_handle,
-					    unsigned long dev_ino,
-					    unsigned long *cpuid);
-extern unsigned long sun4v_vintr_set_target(unsigned long dev_handle,
-					    unsigned long dev_ino,
-					    unsigned long cpuid);
-#endif
-
-/* PCI IO services.
- *
- * See the terminology descriptions in the device interrupt services
- * section above as those apply here too.  Here are terminology
- * definitions specific to these PCI IO services:
- *
- *	tsbnum		TSB number.  Indentifies which io-tsb is used.
- *			For this version of the specification, tsbnum
- *			must be zero.
- *
- *	tsbindex	TSB index.  Identifies which entry in the TSB
- *			is used.  The first entry is zero.
- *
- *	tsbid		A 64-bit aligned data structure which contains
- *			a tsbnum and a tsbindex.  Bits 63:32 contain the
- *			tsbnum and bits 31:00 contain the tsbindex.
- *
- *			Use the HV_PCI_TSBID() macro to construct such
- * 			values.
- *
- *	io_attributes	IO attributes for IOMMU mappings.  One of more
- *			of the attritbute bits are stores in a 64-bit
- *			value.  The values are defined below.
- *
- *	r_addr		64-bit real address
- *
- *	pci_device	PCI device address.  A PCI device address identifies
- *			a specific device on a specific PCI bus segment.
- *			A PCI device address ia a 32-bit unsigned integer
- *			with the following format:
- *
- *				00000000.bbbbbbbb.dddddfff.00000000
- *
- *			Use the HV_PCI_DEVICE_BUILD() macro to construct
- *			such values.
- *
- *	pci_config_offset
- *			PCI configureation space offset.  For conventional
- *			PCI a value between 0 and 255.  For extended
- *			configuration space, a value between 0 and 4095.
- *
- *			Note: For PCI configuration space accesses, the offset
- *			      must be aligned to the access size.
- *
- *	error_flag	A return value which specifies if the action succeeded
- *			or failed.  0 means no error, non-0 means some error
- *			occurred while performing the service.
- *
- *	io_sync_direction
- *			Direction definition for pci_dma_sync(), defined
- *			below in HV_PCI_SYNC_*.
- *
- *	io_page_list	A list of io_page_addresses, an io_page_address is
- *			a real address.
- *
- *	io_page_list_p	A pointer to an io_page_list.
- *
- *	"size based byte swap" - Some functions do size based byte swapping
- *				 which allows sw to access pointers and
- *				 counters in native form when the processor
- *				 operates in a different endianness than the
- *				 IO bus.  Size-based byte swapping converts a
- *				 multi-byte field between big-endian and
- *				 little-endian format.
- */
-
-#define HV_PCI_MAP_ATTR_READ		0x01
-#define HV_PCI_MAP_ATTR_WRITE		0x02
-
-#define HV_PCI_DEVICE_BUILD(b,d,f)	\
-	((((b) & 0xff) << 16) | \
-	 (((d) & 0x1f) << 11) | \
-	 (((f) & 0x07) <<  8))
-
-#define HV_PCI_TSBID(__tsb_num, __tsb_index) \
-	((((u64)(__tsb_num)) << 32UL) | ((u64)(__tsb_index)))
-
-#define HV_PCI_SYNC_FOR_DEVICE		0x01
-#define HV_PCI_SYNC_FOR_CPU		0x02
-
-/* pci_iommu_map()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_IOMMU_MAP
- * ARG0:	devhandle
- * ARG1:	tsbid
- * ARG2:	#ttes
- * ARG3:	io_attributes
- * ARG4:	io_page_list_p
- * RET0:	status
- * RET1:	#ttes mapped
- * ERRORS:	EINVAL		Invalid devhandle/tsbnum/tsbindex/io_attributes
- *		EBADALIGN	Improperly aligned real address
- *		ENORADDR	Invalid real address
- *
- * Create IOMMU mappings in the sun4v device defined by the given
- * devhandle.  The mappings are created in the TSB defined by the
- * tsbnum component of the given tsbid.  The first mapping is created
- * in the TSB i ndex defined by the tsbindex component of the given tsbid.
- * The call creates up to #ttes mappings, the first one at tsbnum, tsbindex,
- * the second at tsbnum, tsbindex + 1, etc.
- *
- * All mappings are created with the attributes defined by the io_attributes
- * argument.  The page mapping addresses are described in the io_page_list
- * defined by the given io_page_list_p, which is a pointer to the io_page_list.
- * The first entry in the io_page_list is the address for the first iotte, the
- * 2nd for the 2nd iotte, and so on.
- *
- * Each io_page_address in the io_page_list must be appropriately aligned.
- * #ttes must be greater than zero.  For this version of the spec, the tsbnum
- * component of the given tsbid must be zero.
- *
- * Returns the actual number of mappings creates, which may be less than
- * or equal to the argument #ttes.  If the function returns a value which
- * is less than the #ttes, the caller may continus to call the function with
- * an updated tsbid, #ttes, io_page_list_p arguments until all pages are
- * mapped.
- *
- * Note: This function does not imply an iotte cache flush.  The guest must
- *       demap an entry before re-mapping it.
- */
-#define HV_FAST_PCI_IOMMU_MAP		0xb0
-
-/* pci_iommu_demap()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_IOMMU_DEMAP
- * ARG0:	devhandle
- * ARG1:	tsbid
- * ARG2:	#ttes
- * RET0:	status
- * RET1:	#ttes demapped
- * ERRORS:	EINVAL		Invalid devhandle/tsbnum/tsbindex
- *
- * Demap and flush IOMMU mappings in the device defined by the given
- * devhandle.  Demaps up to #ttes entries in the TSB defined by the tsbnum
- * component of the given tsbid, starting at the TSB index defined by the
- * tsbindex component of the given tsbid.
- *
- * For this version of the spec, the tsbnum of the given tsbid must be zero.
- * #ttes must be greater than zero.
- *
- * Returns the actual number of ttes demapped, which may be less than or equal
- * to the argument #ttes.  If #ttes demapped is less than #ttes, the caller
- * may continue to call this function with updated tsbid and #ttes arguments
- * until all pages are demapped.
- *
- * Note: Entries do not have to be mapped to be demapped.  A demap of an
- *       unmapped page will flush the entry from the tte cache.
- */
-#define HV_FAST_PCI_IOMMU_DEMAP		0xb1
-
-/* pci_iommu_getmap()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_IOMMU_GETMAP
- * ARG0:	devhandle
- * ARG1:	tsbid
- * RET0:	status
- * RET1:	io_attributes
- * RET2:	real address
- * ERRORS:	EINVAL		Invalid devhandle/tsbnum/tsbindex
- *		ENOMAP		Mapping is not valid, no translation exists
- *
- * Read and return the mapping in the device described by the given devhandle
- * and tsbid.  If successful, the io_attributes shall be returned in RET1
- * and the page address of the mapping shall be returned in RET2.
- *
- * For this version of the spec, the tsbnum component of the given tsbid
- * must be zero.
- */
-#define HV_FAST_PCI_IOMMU_GETMAP	0xb2
-
-/* pci_iommu_getbypass()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_IOMMU_GETBYPASS
- * ARG0:	devhandle
- * ARG1:	real address
- * ARG2:	io_attributes
- * RET0:	status
- * RET1:	io_addr
- * ERRORS:	EINVAL		Invalid devhandle/io_attributes
- *		ENORADDR	Invalid real address
- *		ENOTSUPPORTED	Function not supported in this implementation.
- *
- * Create a "special" mapping in the device described by the given devhandle,
- * for the given real address and attributes.  Return the IO address in RET1
- * if successful.
- */
-#define HV_FAST_PCI_IOMMU_GETBYPASS	0xb3
-
-/* pci_config_get()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_CONFIG_GET
- * ARG0:	devhandle
- * ARG1:	pci_device
- * ARG2:	pci_config_offset
- * ARG3:	size
- * RET0:	status
- * RET1:	error_flag
- * RET2:	data
- * ERRORS:	EINVAL		Invalid devhandle/pci_device/offset/size
- *		EBADALIGN	pci_config_offset not size aligned
- *		ENOACCESS	Access to this offset is not permitted
- *
- * Read PCI configuration space for the adapter described by the given
- * devhandle.  Read size (1, 2, or 4) bytes of data from the given
- * pci_device, at pci_config_offset from the beginning of the device's
- * configuration space.  If there was no error, RET1 is set to zero and
- * RET2 is set to the data read.  Insignificant bits in RET2 are not
- * guarenteed to have any specific value and therefore must be ignored.
- *
- * The data returned in RET2 is size based byte swapped.
- *
- * If an error occurs during the read, set RET1 to a non-zero value.  The
- * given pci_config_offset must be 'size' aligned.
- */
-#define HV_FAST_PCI_CONFIG_GET		0xb4
-
-/* pci_config_put()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_CONFIG_PUT
- * ARG0:	devhandle
- * ARG1:	pci_device
- * ARG2:	pci_config_offset
- * ARG3:	size
- * ARG4:	data
- * RET0:	status
- * RET1:	error_flag
- * ERRORS:	EINVAL		Invalid devhandle/pci_device/offset/size
- *		EBADALIGN	pci_config_offset not size aligned
- *		ENOACCESS	Access to this offset is not permitted
- *
- * Write PCI configuration space for the adapter described by the given
- * devhandle.  Write size (1, 2, or 4) bytes of data in a single operation,
- * at pci_config_offset from the beginning of the device's configuration
- * space.  The data argument contains the data to be written to configuration
- * space.  Prior to writing, the data is size based byte swapped.
- *
- * If an error occurs during the write access, do not generate an error
- * report, do set RET1 to a non-zero value.  Otherwise RET1 is zero.
- * The given pci_config_offset must be 'size' aligned.
- *
- * This function is permitted to read from offset zero in the configuration
- * space described by the given pci_device if necessary to ensure that the
- * write access to config space completes.
- */
-#define HV_FAST_PCI_CONFIG_PUT		0xb5
-
-/* pci_peek()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_PEEK
- * ARG0:	devhandle
- * ARG1:	real address
- * ARG2:	size
- * RET0:	status
- * RET1:	error_flag
- * RET2:	data
- * ERRORS:	EINVAL		Invalid devhandle or size
- *		EBADALIGN	Improperly aligned real address
- *		ENORADDR	Bad real address
- *		ENOACCESS	Guest access prohibited
- *
- * Attempt to read the IO address given by the given devhandle, real address,
- * and size.  Size must be 1, 2, 4, or 8.  The read is performed as a single
- * access operation using the given size.  If an error occurs when reading
- * from the given location, do not generate an error report, but return a
- * non-zero value in RET1.  If the read was successful, return zero in RET1
- * and return the actual data read in RET2.  The data returned is size based
- * byte swapped.
- *
- * Non-significant bits in RET2 are not guarenteed to have any specific value
- * and therefore must be ignored.  If RET1 is returned as non-zero, the data 
- * value is not guarenteed to have any specific value and should be ignored.
- *
- * The caller must have permission to read from the given devhandle, real
- * address, which must be an IO address.  The argument real address must be a
- * size aligned address.
- *
- * The hypervisor implementation of this function must block access to any
- * IO address that the guest does not have explicit permission to access.
- */
-#define HV_FAST_PCI_PEEK		0xb6
-
-/* pci_poke()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_POKE
- * ARG0:	devhandle
- * ARG1:	real address
- * ARG2:	size
- * ARG3:	data
- * ARG4:	pci_device
- * RET0:	status
- * RET1:	error_flag
- * ERRORS:	EINVAL		Invalid devhandle, size, or pci_device
- *		EBADALIGN	Improperly aligned real address
- *		ENORADDR	Bad real address
- *		ENOACCESS	Guest access prohibited
- *		ENOTSUPPORTED	Function is not supported by implementation
- *
- * Attempt to write data to the IO address given by the given devhandle,
- * real address, and size.  Size must be 1, 2, 4, or 8.  The write is
- * performed as a single access operation using the given size. Prior to
- * writing the data is size based swapped.
- *
- * If an error occurs when writing to the given location, do not generate an
- * error report, but return a non-zero value in RET1.  If the write was
- * successful, return zero in RET1.
- *
- * pci_device describes the configuration address of the device being
- * written to.  The implementation may safely read from offset 0 with
- * the configuration space of the device described by devhandle and
- * pci_device in order to guarantee that the write portion of the operation
- * completes
- *
- * Any error that occurs due to the read shall be reported using the normal
- * error reporting mechanisms .. the read error is not suppressed.
- *
- * The caller must have permission to write to the given devhandle, real
- * address, which must be an IO address.  The argument real address must be a
- * size aligned address.  The caller must have permission to read from
- * the given devhandle, pci_device cofiguration space offset 0.
- *
- * The hypervisor implementation of this function must block access to any
- * IO address that the guest does not have explicit permission to access.
- */
-#define HV_FAST_PCI_POKE		0xb7
-
-/* pci_dma_sync()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_DMA_SYNC
- * ARG0:	devhandle
- * ARG1:	real address
- * ARG2:	size
- * ARG3:	io_sync_direction
- * RET0:	status
- * RET1:	#synced
- * ERRORS:	EINVAL		Invalid devhandle or io_sync_direction
- *		ENORADDR	Bad real address
- *
- * Synchronize a memory region described by the given real address and size,
- * for the device defined by the given devhandle using the direction(s)
- * defined by the given io_sync_direction.  The argument size is the size of
- * the memory region in bytes.
- *
- * Return the actual number of bytes synchronized in the return value #synced,
- * which may be less than or equal to the argument size.  If the return
- * value #synced is less than size, the caller must continue to call this
- * function with updated real address and size arguments until the entire
- * memory region is synchronized.
- */
-#define HV_FAST_PCI_DMA_SYNC		0xb8
-
-/* PCI MSI services.  */
-
-#define HV_MSITYPE_MSI32		0x00
-#define HV_MSITYPE_MSI64		0x01
-
-#define HV_MSIQSTATE_IDLE		0x00
-#define HV_MSIQSTATE_ERROR		0x01
-
-#define HV_MSIQ_INVALID			0x00
-#define HV_MSIQ_VALID			0x01
-
-#define HV_MSISTATE_IDLE		0x00
-#define HV_MSISTATE_DELIVERED		0x01
-
-#define HV_MSIVALID_INVALID		0x00
-#define HV_MSIVALID_VALID		0x01
-
-#define HV_PCIE_MSGTYPE_PME_MSG		0x18
-#define HV_PCIE_MSGTYPE_PME_ACK_MSG	0x1b
-#define HV_PCIE_MSGTYPE_CORR_MSG	0x30
-#define HV_PCIE_MSGTYPE_NONFATAL_MSG	0x31
-#define HV_PCIE_MSGTYPE_FATAL_MSG	0x33
-
-#define HV_MSG_INVALID			0x00
-#define HV_MSG_VALID			0x01
-
-/* pci_msiq_conf()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_MSIQ_CONF
- * ARG0:	devhandle
- * ARG1:	msiqid
- * ARG2:	real address
- * ARG3:	number of entries
- * RET0:	status
- * ERRORS:	EINVAL		Invalid devhandle, msiqid or nentries
- *		EBADALIGN	Improperly aligned real address
- *		ENORADDR	Bad real address
- *
- * Configure the MSI queue given by the devhandle and msiqid arguments,
- * and to be placed at the given real address and be of the given
- * number of entries.  The real address must be aligned exactly to match
- * the queue size.  Each queue entry is 64-bytes long, so f.e. a 32 entry
- * queue must be aligned on a 2048 byte real address boundary.  The MSI-EQ
- * Head and Tail are initialized so that the MSI-EQ is 'empty'.
- *
- * Implementation Note: Certain implementations have fixed sized queues.  In
- *                      that case, number of entries must contain the correct
- *                      value.
- */
-#define HV_FAST_PCI_MSIQ_CONF		0xc0
-
-/* pci_msiq_info()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_MSIQ_INFO
- * ARG0:	devhandle
- * ARG1:	msiqid
- * RET0:	status
- * RET1:	real address
- * RET2:	number of entries
- * ERRORS:	EINVAL		Invalid devhandle or msiqid
- *
- * Return the configuration information for the MSI queue described
- * by the given devhandle and msiqid.  The base address of the queue
- * is returned in ARG1 and the number of entries is returned in ARG2.
- * If the queue is unconfigured, the real address is undefined and the
- * number of entries will be returned as zero.
- */
-#define HV_FAST_PCI_MSIQ_INFO		0xc1
-
-/* pci_msiq_getvalid()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_MSIQ_GETVALID
- * ARG0:	devhandle
- * ARG1:	msiqid
- * RET0:	status
- * RET1:	msiqvalid	(HV_MSIQ_VALID or HV_MSIQ_INVALID)
- * ERRORS:	EINVAL		Invalid devhandle or msiqid
- *
- * Get the valid state of the MSI-EQ described by the given devhandle and
- * msiqid.
- */
-#define HV_FAST_PCI_MSIQ_GETVALID	0xc2
-
-/* pci_msiq_setvalid()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_MSIQ_SETVALID
- * ARG0:	devhandle
- * ARG1:	msiqid
- * ARG2:	msiqvalid	(HV_MSIQ_VALID or HV_MSIQ_INVALID)
- * RET0:	status
- * ERRORS:	EINVAL		Invalid devhandle or msiqid or msiqvalid
- *				value or MSI EQ is uninitialized
- *
- * Set the valid state of the MSI-EQ described by the given devhandle and
- * msiqid to the given msiqvalid.
- */
-#define HV_FAST_PCI_MSIQ_SETVALID	0xc3
-
-/* pci_msiq_getstate()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_MSIQ_GETSTATE
- * ARG0:	devhandle
- * ARG1:	msiqid
- * RET0:	status
- * RET1:	msiqstate	(HV_MSIQSTATE_IDLE or HV_MSIQSTATE_ERROR)
- * ERRORS:	EINVAL		Invalid devhandle or msiqid
- *
- * Get the state of the MSI-EQ described by the given devhandle and
- * msiqid.
- */
-#define HV_FAST_PCI_MSIQ_GETSTATE	0xc4
-
-/* pci_msiq_getvalid()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_MSIQ_GETVALID
- * ARG0:	devhandle
- * ARG1:	msiqid
- * ARG2:	msiqstate	(HV_MSIQSTATE_IDLE or HV_MSIQSTATE_ERROR)
- * RET0:	status
- * ERRORS:	EINVAL		Invalid devhandle or msiqid or msiqstate
- *				value or MSI EQ is uninitialized
- *
- * Set the state of the MSI-EQ described by the given devhandle and
- * msiqid to the given msiqvalid.
- */
-#define HV_FAST_PCI_MSIQ_SETSTATE	0xc5
-
-/* pci_msiq_gethead()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_MSIQ_GETHEAD
- * ARG0:	devhandle
- * ARG1:	msiqid
- * RET0:	status
- * RET1:	msiqhead
- * ERRORS:	EINVAL		Invalid devhandle or msiqid
- *
- * Get the current MSI EQ queue head for the MSI-EQ described by the
- * given devhandle and msiqid.
- */
-#define HV_FAST_PCI_MSIQ_GETHEAD	0xc6
-
-/* pci_msiq_sethead()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_MSIQ_SETHEAD
- * ARG0:	devhandle
- * ARG1:	msiqid
- * ARG2:	msiqhead
- * RET0:	status
- * ERRORS:	EINVAL		Invalid devhandle or msiqid or msiqhead,
- *				or MSI EQ is uninitialized
- *
- * Set the current MSI EQ queue head for the MSI-EQ described by the
- * given devhandle and msiqid.
- */
-#define HV_FAST_PCI_MSIQ_SETHEAD	0xc7
-
-/* pci_msiq_gettail()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_MSIQ_GETTAIL
- * ARG0:	devhandle
- * ARG1:	msiqid
- * RET0:	status
- * RET1:	msiqtail
- * ERRORS:	EINVAL		Invalid devhandle or msiqid
- *
- * Get the current MSI EQ queue tail for the MSI-EQ described by the
- * given devhandle and msiqid.
- */
-#define HV_FAST_PCI_MSIQ_GETTAIL	0xc8
-
-/* pci_msi_getvalid()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_MSI_GETVALID
- * ARG0:	devhandle
- * ARG1:	msinum
- * RET0:	status
- * RET1:	msivalidstate
- * ERRORS:	EINVAL		Invalid devhandle or msinum
- *
- * Get the current valid/enabled state for the MSI defined by the
- * given devhandle and msinum.
- */
-#define HV_FAST_PCI_MSI_GETVALID	0xc9
-
-/* pci_msi_setvalid()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_MSI_SETVALID
- * ARG0:	devhandle
- * ARG1:	msinum
- * ARG2:	msivalidstate
- * RET0:	status
- * ERRORS:	EINVAL		Invalid devhandle or msinum or msivalidstate
- *
- * Set the current valid/enabled state for the MSI defined by the
- * given devhandle and msinum.
- */
-#define HV_FAST_PCI_MSI_SETVALID	0xca
-
-/* pci_msi_getmsiq()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_MSI_GETMSIQ
- * ARG0:	devhandle
- * ARG1:	msinum
- * RET0:	status
- * RET1:	msiqid
- * ERRORS:	EINVAL		Invalid devhandle or msinum or MSI is unbound
- *
- * Get the MSI EQ that the MSI defined by the given devhandle and
- * msinum is bound to.
- */
-#define HV_FAST_PCI_MSI_GETMSIQ		0xcb
-
-/* pci_msi_setmsiq()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_MSI_SETMSIQ
- * ARG0:	devhandle
- * ARG1:	msinum
- * ARG2:	msitype
- * ARG3:	msiqid
- * RET0:	status
- * ERRORS:	EINVAL		Invalid devhandle or msinum or msiqid
- *
- * Set the MSI EQ that the MSI defined by the given devhandle and
- * msinum is bound to.
- */
-#define HV_FAST_PCI_MSI_SETMSIQ		0xcc
-
-/* pci_msi_getstate()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_MSI_GETSTATE
- * ARG0:	devhandle
- * ARG1:	msinum
- * RET0:	status
- * RET1:	msistate
- * ERRORS:	EINVAL		Invalid devhandle or msinum
- *
- * Get the state of the MSI defined by the given devhandle and msinum.
- * If not initialized, return HV_MSISTATE_IDLE.
- */
-#define HV_FAST_PCI_MSI_GETSTATE	0xcd
-
-/* pci_msi_setstate()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_MSI_SETSTATE
- * ARG0:	devhandle
- * ARG1:	msinum
- * ARG2:	msistate
- * RET0:	status
- * ERRORS:	EINVAL		Invalid devhandle or msinum or msistate
- *
- * Set the state of the MSI defined by the given devhandle and msinum.
- */
-#define HV_FAST_PCI_MSI_SETSTATE	0xce
-
-/* pci_msg_getmsiq()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_MSG_GETMSIQ
- * ARG0:	devhandle
- * ARG1:	msgtype
- * RET0:	status
- * RET1:	msiqid
- * ERRORS:	EINVAL		Invalid devhandle or msgtype
- *
- * Get the MSI EQ of the MSG defined by the given devhandle and msgtype.
- */
-#define HV_FAST_PCI_MSG_GETMSIQ		0xd0
-
-/* pci_msg_setmsiq()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_MSG_SETMSIQ
- * ARG0:	devhandle
- * ARG1:	msgtype
- * ARG2:	msiqid
- * RET0:	status
- * ERRORS:	EINVAL		Invalid devhandle, msgtype, or msiqid
- *
- * Set the MSI EQ of the MSG defined by the given devhandle and msgtype.
- */
-#define HV_FAST_PCI_MSG_SETMSIQ		0xd1
-
-/* pci_msg_getvalid()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_MSG_GETVALID
- * ARG0:	devhandle
- * ARG1:	msgtype
- * RET0:	status
- * RET1:	msgvalidstate
- * ERRORS:	EINVAL		Invalid devhandle or msgtype
- *
- * Get the valid/enabled state of the MSG defined by the given
- * devhandle and msgtype.
- */
-#define HV_FAST_PCI_MSG_GETVALID	0xd2
-
-/* pci_msg_setvalid()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_PCI_MSG_SETVALID
- * ARG0:	devhandle
- * ARG1:	msgtype
- * ARG2:	msgvalidstate
- * RET0:	status
- * ERRORS:	EINVAL		Invalid devhandle or msgtype or msgvalidstate
- *
- * Set the valid/enabled state of the MSG defined by the given
- * devhandle and msgtype.
- */
-#define HV_FAST_PCI_MSG_SETVALID	0xd3
-
-/* Logical Domain Channel services.  */
-
-#define LDC_CHANNEL_DOWN		0
-#define LDC_CHANNEL_UP			1
-#define LDC_CHANNEL_RESETTING		2
-
-/* ldc_tx_qconf()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_LDC_TX_QCONF
- * ARG0:	channel ID
- * ARG1:	real address base of queue
- * ARG2:	num entries in queue
- * RET0:	status
- *
- * Configure transmit queue for the LDC endpoint specified by the
- * given channel ID, to be placed at the given real address, and
- * be of the given num entries.  Num entries must be a power of two.
- * The real address base of the queue must be aligned on the queue
- * size.  Each queue entry is 64-bytes, so for example, a 32 entry
- * queue must be aligned on a 2048 byte real address boundary.
- *
- * Upon configuration of a valid transmit queue the head and tail
- * pointers are set to a hypervisor specific identical value indicating
- * that the queue initially is empty.
- *
- * The endpoint's transmit queue is un-configured if num entries is zero.
- *
- * The maximum number of entries for each queue for a specific cpu may be
- * determined from the machine description.  A transmit queue may be
- * specified even in the event that the LDC is down (peer endpoint has no
- * receive queue specified).  Transmission will begin as soon as the peer
- * endpoint defines a receive queue.
- *
- * It is recommended that a guest wait for a transmit queue to empty prior
- * to reconfiguring it, or un-configuring it.  Re or un-configuring of a
- * non-empty transmit queue behaves exactly as defined above, however it
- * is undefined as to how many of the pending entries in the original queue
- * will be delivered prior to the re-configuration taking effect.
- * Furthermore, as the queue configuration causes a reset of the head and
- * tail pointers there is no way for a guest to determine how many entries
- * have been sent after the configuration operation.
- */
-#define HV_FAST_LDC_TX_QCONF		0xe0
-
-/* ldc_tx_qinfo()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_LDC_TX_QINFO
- * ARG0:	channel ID
- * RET0:	status
- * RET1:	real address base of queue
- * RET2:	num entries in queue
- *
- * Return the configuration info for the transmit queue of LDC endpoint
- * defined by the given channel ID.  The real address is the currently
- * defined real address base of the defined queue, and num entries is the
- * size of the queue in terms of number of entries.
- *
- * If the specified channel ID is a valid endpoint number, but no transmit
- * queue has been defined this service will return success, but with num
- * entries set to zero and the real address will have an undefined value.
- */
-#define HV_FAST_LDC_TX_QINFO		0xe1
-
-/* ldc_tx_get_state()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_LDC_TX_GET_STATE
- * ARG0:	channel ID
- * RET0:	status
- * RET1:	head offset
- * RET2:	tail offset
- * RET3:	channel state
- *
- * Return the transmit state, and the head and tail queue pointers, for
- * the transmit queue of the LDC endpoint defined by the given channel ID.
- * The head and tail values are the byte offset of the head and tail
- * positions of the transmit queue for the specified endpoint.
- */
-#define HV_FAST_LDC_TX_GET_STATE	0xe2
-
-/* ldc_tx_set_qtail()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_LDC_TX_SET_QTAIL
- * ARG0:	channel ID
- * ARG1:	tail offset
- * RET0:	status
- *
- * Update the tail pointer for the transmit queue associated with the LDC
- * endpoint defined by the given channel ID.  The tail offset specified
- * must be aligned on a 64 byte boundary, and calculated so as to increase
- * the number of pending entries on the transmit queue.  Any attempt to
- * decrease the number of pending transmit queue entires is considered
- * an invalid tail offset and will result in an EINVAL error.
- *
- * Since the tail of the transmit queue may not be moved backwards, the
- * transmit queue may be flushed by configuring a new transmit queue,
- * whereupon the hypervisor will configure the initial transmit head and
- * tail pointers to be equal.
- */
-#define HV_FAST_LDC_TX_SET_QTAIL	0xe3
-
-/* ldc_rx_qconf()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_LDC_RX_QCONF
- * ARG0:	channel ID
- * ARG1:	real address base of queue
- * ARG2:	num entries in queue
- * RET0:	status
- *
- * Configure receive queue for the LDC endpoint specified by the
- * given channel ID, to be placed at the given real address, and
- * be of the given num entries.  Num entries must be a power of two.
- * The real address base of the queue must be aligned on the queue
- * size.  Each queue entry is 64-bytes, so for example, a 32 entry
- * queue must be aligned on a 2048 byte real address boundary.
- *
- * The endpoint's transmit queue is un-configured if num entries is zero.
- *
- * If a valid receive queue is specified for a local endpoint the LDC is
- * in the up state for the purpose of transmission to this endpoint.
- *
- * The maximum number of entries for each queue for a specific cpu may be
- * determined from the machine description.
- *
- * As receive queue configuration causes a reset of the queue's head and
- * tail pointers there is no way for a gues to determine how many entries
- * have been received between a preceeding ldc_get_rx_state() API call
- * and the completion of the configuration operation.  It should be noted
- * that datagram delivery is not guarenteed via domain channels anyway,
- * and therefore any higher protocol should be resilient to datagram
- * loss if necessary.  However, to overcome this specific race potential
- * it is recommended, for example, that a higher level protocol be employed
- * to ensure either retransmission, or ensure that no datagrams are pending
- * on the peer endpoint's transmit queue prior to the configuration process.
- */
-#define HV_FAST_LDC_RX_QCONF		0xe4
-
-/* ldc_rx_qinfo()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_LDC_RX_QINFO
- * ARG0:	channel ID
- * RET0:	status
- * RET1:	real address base of queue
- * RET2:	num entries in queue
- *
- * Return the configuration info for the receive queue of LDC endpoint
- * defined by the given channel ID.  The real address is the currently
- * defined real address base of the defined queue, and num entries is the
- * size of the queue in terms of number of entries.
- *
- * If the specified channel ID is a valid endpoint number, but no receive
- * queue has been defined this service will return success, but with num
- * entries set to zero and the real address will have an undefined value.
- */
-#define HV_FAST_LDC_RX_QINFO		0xe5
-
-/* ldc_rx_get_state()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_LDC_RX_GET_STATE
- * ARG0:	channel ID
- * RET0:	status
- * RET1:	head offset
- * RET2:	tail offset
- * RET3:	channel state
- *
- * Return the receive state, and the head and tail queue pointers, for
- * the receive queue of the LDC endpoint defined by the given channel ID.
- * The head and tail values are the byte offset of the head and tail
- * positions of the receive queue for the specified endpoint.
- */
-#define HV_FAST_LDC_RX_GET_STATE	0xe6
-
-/* ldc_rx_set_qhead()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_LDC_RX_SET_QHEAD
- * ARG0:	channel ID
- * ARG1:	head offset
- * RET0:	status
- *
- * Update the head pointer for the receive queue associated with the LDC
- * endpoint defined by the given channel ID.  The head offset specified
- * must be aligned on a 64 byte boundary, and calculated so as to decrease
- * the number of pending entries on the receive queue.  Any attempt to
- * increase the number of pending receive queue entires is considered
- * an invalid head offset and will result in an EINVAL error.
- *
- * The receive queue may be flushed by setting the head offset equal
- * to the current tail offset.
- */
-#define HV_FAST_LDC_RX_SET_QHEAD	0xe7
-
-/* LDC Map Table Entry.  Each slot is defined by a translation table
- * entry, as specified by the LDC_MTE_* bits below, and a 64-bit
- * hypervisor invalidation cookie.
- */
-#define LDC_MTE_PADDR	0x0fffffffffffe000 /* pa[55:13]          */
-#define LDC_MTE_COPY_W	0x0000000000000400 /* copy write access  */
-#define LDC_MTE_COPY_R	0x0000000000000200 /* copy read access   */
-#define LDC_MTE_IOMMU_W	0x0000000000000100 /* IOMMU write access */
-#define LDC_MTE_IOMMU_R	0x0000000000000080 /* IOMMU read access  */
-#define LDC_MTE_EXEC	0x0000000000000040 /* execute            */
-#define LDC_MTE_WRITE	0x0000000000000020 /* read               */
-#define LDC_MTE_READ	0x0000000000000010 /* write              */
-#define LDC_MTE_SZALL	0x000000000000000f /* page size bits     */
-#define LDC_MTE_SZ16GB	0x0000000000000007 /* 16GB page          */
-#define LDC_MTE_SZ2GB	0x0000000000000006 /* 2GB page           */
-#define LDC_MTE_SZ256MB	0x0000000000000005 /* 256MB page         */
-#define LDC_MTE_SZ32MB	0x0000000000000004 /* 32MB page          */
-#define LDC_MTE_SZ4MB	0x0000000000000003 /* 4MB page           */
-#define LDC_MTE_SZ512K	0x0000000000000002 /* 512K page          */
-#define LDC_MTE_SZ64K	0x0000000000000001 /* 64K page           */
-#define LDC_MTE_SZ8K	0x0000000000000000 /* 8K page            */
-
-#ifndef __ASSEMBLY__
-struct ldc_mtable_entry {
-	unsigned long	mte;
-	unsigned long	cookie;
-};
-#endif
-
-/* ldc_set_map_table()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_LDC_SET_MAP_TABLE
- * ARG0:	channel ID
- * ARG1:	table real address
- * ARG2:	num entries
- * RET0:	status
- *
- * Register the MTE table at the given table real address, with the
- * specified num entries, for the LDC indicated by the given channel
- * ID.
- */
-#define HV_FAST_LDC_SET_MAP_TABLE	0xea
-
-/* ldc_get_map_table()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_LDC_GET_MAP_TABLE
- * ARG0:	channel ID
- * RET0:	status
- * RET1:	table real address
- * RET2:	num entries
- *
- * Return the configuration of the current mapping table registered
- * for the given channel ID.
- */
-#define HV_FAST_LDC_GET_MAP_TABLE	0xeb
-
-#define LDC_COPY_IN	0
-#define LDC_COPY_OUT	1
-
-/* ldc_copy()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_LDC_COPY
- * ARG0:	channel ID
- * ARG1:	LDC_COPY_* direction code
- * ARG2:	target real address
- * ARG3:	local real address
- * ARG4:	length in bytes
- * RET0:	status
- * RET1:	actual length in bytes
- */
-#define HV_FAST_LDC_COPY		0xec
-
-#define LDC_MEM_READ	1
-#define LDC_MEM_WRITE	2
-#define LDC_MEM_EXEC	4
-
-/* ldc_mapin()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_LDC_MAPIN
- * ARG0:	channel ID
- * ARG1:	cookie
- * RET0:	status
- * RET1:	real address
- * RET2:	LDC_MEM_* permissions
- */
-#define HV_FAST_LDC_MAPIN		0xed
-
-/* ldc_unmap()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_LDC_UNMAP
- * ARG0:	real address
- * RET0:	status
- */
-#define HV_FAST_LDC_UNMAP		0xee
-
-/* ldc_revoke()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_LDC_REVOKE
- * ARG0:	channel ID
- * ARG1:	cookie
- * ARG2:	ldc_mtable_entry cookie
- * RET0:	status
- */
-#define HV_FAST_LDC_REVOKE		0xef
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_ldc_tx_qconf(unsigned long channel,
-					unsigned long ra,
-					unsigned long num_entries);
-extern unsigned long sun4v_ldc_tx_qinfo(unsigned long channel,
-					unsigned long *ra,
-					unsigned long *num_entries);
-extern unsigned long sun4v_ldc_tx_get_state(unsigned long channel,
-					    unsigned long *head_off,
-					    unsigned long *tail_off,
-					    unsigned long *chan_state);
-extern unsigned long sun4v_ldc_tx_set_qtail(unsigned long channel,
-					    unsigned long tail_off);
-extern unsigned long sun4v_ldc_rx_qconf(unsigned long channel,
-					unsigned long ra,
-					unsigned long num_entries);
-extern unsigned long sun4v_ldc_rx_qinfo(unsigned long channel,
-					unsigned long *ra,
-					unsigned long *num_entries);
-extern unsigned long sun4v_ldc_rx_get_state(unsigned long channel,
-					    unsigned long *head_off,
-					    unsigned long *tail_off,
-					    unsigned long *chan_state);
-extern unsigned long sun4v_ldc_rx_set_qhead(unsigned long channel,
-					    unsigned long head_off);
-extern unsigned long sun4v_ldc_set_map_table(unsigned long channel,
-					     unsigned long ra,
-					     unsigned long num_entries);
-extern unsigned long sun4v_ldc_get_map_table(unsigned long channel,
-					     unsigned long *ra,
-					     unsigned long *num_entries);
-extern unsigned long sun4v_ldc_copy(unsigned long channel,
-				    unsigned long dir_code,
-				    unsigned long tgt_raddr,
-				    unsigned long lcl_raddr,
-				    unsigned long len,
-				    unsigned long *actual_len);
-extern unsigned long sun4v_ldc_mapin(unsigned long channel,
-				     unsigned long cookie,
-				     unsigned long *ra,
-				     unsigned long *perm);
-extern unsigned long sun4v_ldc_unmap(unsigned long ra);
-extern unsigned long sun4v_ldc_revoke(unsigned long channel,
-				      unsigned long cookie,
-				      unsigned long mte_cookie);
-#endif
-
-/* Performance counter services.  */
-
-#define HV_PERF_JBUS_PERF_CTRL_REG	0x00
-#define HV_PERF_JBUS_PERF_CNT_REG	0x01
-#define HV_PERF_DRAM_PERF_CTRL_REG_0	0x02
-#define HV_PERF_DRAM_PERF_CNT_REG_0	0x03
-#define HV_PERF_DRAM_PERF_CTRL_REG_1	0x04
-#define HV_PERF_DRAM_PERF_CNT_REG_1	0x05
-#define HV_PERF_DRAM_PERF_CTRL_REG_2	0x06
-#define HV_PERF_DRAM_PERF_CNT_REG_2	0x07
-#define HV_PERF_DRAM_PERF_CTRL_REG_3	0x08
-#define HV_PERF_DRAM_PERF_CNT_REG_3	0x09
-
-/* get_perfreg()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_GET_PERFREG
- * ARG0:	performance reg number
- * RET0:	status
- * RET1:	performance reg value
- * ERRORS:	EINVAL		Invalid performance register number
- *		ENOACCESS	No access allowed to performance counters
- *
- * Read the value of the given DRAM/JBUS performance counter/control register.
- */
-#define HV_FAST_GET_PERFREG		0x100
-
-/* set_perfreg()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_SET_PERFREG
- * ARG0:	performance reg number
- * ARG1:	performance reg value
- * RET0:	status
- * ERRORS:	EINVAL		Invalid performance register number
- *		ENOACCESS	No access allowed to performance counters
- *
- * Write the given performance reg value to the given DRAM/JBUS
- * performance counter/control register.
- */
-#define HV_FAST_SET_PERFREG		0x101
-
-/* MMU statistics services.
- *
- * The hypervisor maintains MMU statistics and privileged code provides
- * a buffer where these statistics can be collected.  It is continually
- * updated once configured.  The layout is as follows:
- */
-#ifndef __ASSEMBLY__
-struct hv_mmu_statistics {
-	unsigned long immu_tsb_hits_ctx0_8k_tte;
-	unsigned long immu_tsb_ticks_ctx0_8k_tte;
-	unsigned long immu_tsb_hits_ctx0_64k_tte;
-	unsigned long immu_tsb_ticks_ctx0_64k_tte;
-	unsigned long __reserved1[2];
-	unsigned long immu_tsb_hits_ctx0_4mb_tte;
-	unsigned long immu_tsb_ticks_ctx0_4mb_tte;
-	unsigned long __reserved2[2];
-	unsigned long immu_tsb_hits_ctx0_256mb_tte;
-	unsigned long immu_tsb_ticks_ctx0_256mb_tte;
-	unsigned long __reserved3[4];
-	unsigned long immu_tsb_hits_ctxnon0_8k_tte;
-	unsigned long immu_tsb_ticks_ctxnon0_8k_tte;
-	unsigned long immu_tsb_hits_ctxnon0_64k_tte;
-	unsigned long immu_tsb_ticks_ctxnon0_64k_tte;
-	unsigned long __reserved4[2];
-	unsigned long immu_tsb_hits_ctxnon0_4mb_tte;
-	unsigned long immu_tsb_ticks_ctxnon0_4mb_tte;
-	unsigned long __reserved5[2];
-	unsigned long immu_tsb_hits_ctxnon0_256mb_tte;
-	unsigned long immu_tsb_ticks_ctxnon0_256mb_tte;
-	unsigned long __reserved6[4];
-	unsigned long dmmu_tsb_hits_ctx0_8k_tte;
-	unsigned long dmmu_tsb_ticks_ctx0_8k_tte;
-	unsigned long dmmu_tsb_hits_ctx0_64k_tte;
-	unsigned long dmmu_tsb_ticks_ctx0_64k_tte;
-	unsigned long __reserved7[2];
-	unsigned long dmmu_tsb_hits_ctx0_4mb_tte;
-	unsigned long dmmu_tsb_ticks_ctx0_4mb_tte;
-	unsigned long __reserved8[2];
-	unsigned long dmmu_tsb_hits_ctx0_256mb_tte;
-	unsigned long dmmu_tsb_ticks_ctx0_256mb_tte;
-	unsigned long __reserved9[4];
-	unsigned long dmmu_tsb_hits_ctxnon0_8k_tte;
-	unsigned long dmmu_tsb_ticks_ctxnon0_8k_tte;
-	unsigned long dmmu_tsb_hits_ctxnon0_64k_tte;
-	unsigned long dmmu_tsb_ticks_ctxnon0_64k_tte;
-	unsigned long __reserved10[2];
-	unsigned long dmmu_tsb_hits_ctxnon0_4mb_tte;
-	unsigned long dmmu_tsb_ticks_ctxnon0_4mb_tte;
-	unsigned long __reserved11[2];
-	unsigned long dmmu_tsb_hits_ctxnon0_256mb_tte;
-	unsigned long dmmu_tsb_ticks_ctxnon0_256mb_tte;
-	unsigned long __reserved12[4];
-};
-#endif
-
-/* mmustat_conf()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_MMUSTAT_CONF
- * ARG0:	real address
- * RET0:	status
- * RET1:	real address
- * ERRORS:	ENORADDR	Invalid real address
- *		EBADALIGN	Real address not aligned on 64-byte boundary
- *		EBADTRAP	API not supported on this processor
- *
- * Enable MMU statistic gathering using the buffer at the given real
- * address on the current virtual CPU.  The new buffer real address
- * is given in ARG1, and the previously specified buffer real address
- * is returned in RET1, or is returned as zero for the first invocation.
- *
- * If the passed in real address argument is zero, this will disable
- * MMU statistic collection on the current virtual CPU.  If an error is
- * returned then no statistics are collected.
- *
- * The buffer contents should be initialized to all zeros before being
- * given to the hypervisor or else the statistics will be meaningless.
- */
-#define HV_FAST_MMUSTAT_CONF		0x102
-
-/* mmustat_info()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_MMUSTAT_INFO
- * RET0:	status
- * RET1:	real address
- * ERRORS:	EBADTRAP	API not supported on this processor
- *
- * Return the current state and real address of the currently configured
- * MMU statistics buffer on the current virtual CPU.
- */
-#define HV_FAST_MMUSTAT_INFO		0x103
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_mmustat_conf(unsigned long ra, unsigned long *orig_ra);
-extern unsigned long sun4v_mmustat_info(unsigned long *ra);
-#endif
-
-/* NCS crypto services  */
-
-/* ncs_request() sub-function numbers */
-#define HV_NCS_QCONF			0x01
-#define HV_NCS_QTAIL_UPDATE		0x02
-
-#ifndef __ASSEMBLY__
-struct hv_ncs_queue_entry {
-	/* MAU Control Register */
-	unsigned long	mau_control;
-#define MAU_CONTROL_INV_PARITY	0x0000000000002000
-#define MAU_CONTROL_STRAND	0x0000000000001800
-#define MAU_CONTROL_BUSY	0x0000000000000400
-#define MAU_CONTROL_INT		0x0000000000000200
-#define MAU_CONTROL_OP		0x00000000000001c0
-#define MAU_CONTROL_OP_SHIFT	6
-#define MAU_OP_LOAD_MA_MEMORY	0x0
-#define MAU_OP_STORE_MA_MEMORY	0x1
-#define MAU_OP_MODULAR_MULT	0x2
-#define MAU_OP_MODULAR_REDUCE	0x3
-#define MAU_OP_MODULAR_EXP_LOOP	0x4
-#define MAU_CONTROL_LEN		0x000000000000003f
-#define MAU_CONTROL_LEN_SHIFT	0
-
-	/* Real address of bytes to load or store bytes
-	 * into/out-of the MAU.
-	 */
-	unsigned long	mau_mpa;
-
-	/* Modular Arithmetic MA Offset Register.  */
-	unsigned long	mau_ma;
-
-	/* Modular Arithmetic N Prime Register.  */
-	unsigned long	mau_np;
-};
-
-struct hv_ncs_qconf_arg {
-	unsigned long	mid;      /* MAU ID, 1 per core on Niagara */
-	unsigned long	base;     /* Real address base of queue */
-	unsigned long	end;	  /* Real address end of queue */
-	unsigned long	num_ents; /* Number of entries in queue */
-};
-
-struct hv_ncs_qtail_update_arg {
-	unsigned long	mid;      /* MAU ID, 1 per core on Niagara */
-	unsigned long	tail;     /* New tail index to use */
-	unsigned long	syncflag; /* only SYNCFLAG_SYNC is implemented */
-#define HV_NCS_SYNCFLAG_SYNC	0x00
-#define HV_NCS_SYNCFLAG_ASYNC	0x01
-};
-#endif
-
-/* ncs_request()
- * TRAP:	HV_FAST_TRAP
- * FUNCTION:	HV_FAST_NCS_REQUEST
- * ARG0:	NCS sub-function
- * ARG1:	sub-function argument real address
- * ARG2:	size in bytes of sub-function argument
- * RET0:	status
- *
- * The MAU chip of the Niagara processor is not directly accessible
- * to privileged code, instead it is programmed indirectly via this
- * hypervisor API.
- *
- * The interfaces defines a queue of MAU operations to perform.
- * Privileged code registers a queue with the hypervisor by invoking
- * this HVAPI with the HV_NCS_QCONF sub-function, which defines the
- * base, end, and number of entries of the queue.  Each queue entry
- * contains a MAU register struct block.
- *
- * The privileged code then proceeds to add entries to the queue and
- * then invoke the HV_NCS_QTAIL_UPDATE sub-function.  Since only
- * synchronous operations are supported by the current hypervisor,
- * HV_NCS_QTAIL_UPDATE will run all the pending queue entries to
- * completion and return HV_EOK, or return an error code.
- *
- * The real address of the sub-function argument must be aligned on at
- * least an 8-byte boundary.
- *
- * The tail argument of HV_NCS_QTAIL_UPDATE is an index, not a byte
- * offset, into the queue and must be less than or equal the 'num_ents'
- * argument given in the HV_NCS_QCONF call.
- */
-#define HV_FAST_NCS_REQUEST		0x110
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_ncs_request(unsigned long request,
-				       unsigned long arg_ra,
-				       unsigned long arg_size);
-#endif
-
-#define HV_FAST_FIRE_GET_PERFREG	0x120
-#define HV_FAST_FIRE_SET_PERFREG	0x121
-
-/* Function numbers for HV_CORE_TRAP.  */
-#define HV_CORE_SET_VER			0x00
-#define HV_CORE_PUTCHAR			0x01
-#define HV_CORE_EXIT			0x02
-#define HV_CORE_GET_VER			0x03
-
-/* Hypervisor API groups for use with HV_CORE_SET_VER and
- * HV_CORE_GET_VER.
- */
-#define HV_GRP_SUN4V			0x0000
-#define HV_GRP_CORE			0x0001
-#define HV_GRP_INTR			0x0002
-#define HV_GRP_SOFT_STATE		0x0003
-#define HV_GRP_PCI			0x0100
-#define HV_GRP_LDOM			0x0101
-#define HV_GRP_SVC_CHAN			0x0102
-#define HV_GRP_NCS			0x0103
-#define HV_GRP_NIAG_PERF		0x0200
-#define HV_GRP_FIRE_PERF		0x0201
-#define HV_GRP_DIAG			0x0300
-
-#ifndef __ASSEMBLY__
-extern unsigned long sun4v_get_version(unsigned long group,
-				       unsigned long *major,
-				       unsigned long *minor);
-extern unsigned long sun4v_set_version(unsigned long group,
-				       unsigned long major,
-				       unsigned long minor,
-				       unsigned long *actual_minor);
-
-extern int sun4v_hvapi_register(unsigned long group, unsigned long major,
-				unsigned long *minor);
-extern void sun4v_hvapi_unregister(unsigned long group);
-extern int sun4v_hvapi_get(unsigned long group,
-			   unsigned long *major,
-			   unsigned long *minor);
-extern void sun4v_hvapi_init(void);
-#endif
-
-#endif /* !(_SPARC64_HYPERVISOR_H) */
+#include <asm-sparc/hypervisor.h>
diff --git a/include/asm-sparc64/ide.h b/include/asm-sparc64/ide.h
index 1282676..7125317 100644
--- a/include/asm-sparc64/ide.h
+++ b/include/asm-sparc64/ide.h
@@ -1,118 +1 @@
-/*
- * ide.h: Ultra/PCI specific IDE glue.
- *
- * Copyright (C) 1997  David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1998  Eddie C. Dost   (ecd@skynet.be)
- */
-
-#ifndef _SPARC64_IDE_H
-#define _SPARC64_IDE_H
-
-#ifdef __KERNEL__
-
-#include <asm/pgalloc.h>
-#include <asm/io.h>
-#include <asm/spitfire.h>
-#include <asm/cacheflush.h>
-#include <asm/page.h>
-
-#ifndef MAX_HWIFS
-# ifdef CONFIG_BLK_DEV_IDEPCI
-#define MAX_HWIFS	10
-# else
-#define MAX_HWIFS	2
-# endif
-#endif
-
-#define __ide_insl(data_reg, buffer, wcount) \
-	__ide_insw(data_reg, buffer, (wcount)<<1)
-#define __ide_outsl(data_reg, buffer, wcount) \
-	__ide_outsw(data_reg, buffer, (wcount)<<1)
-
-/* On sparc64, I/O ports and MMIO registers are accessed identically.  */
-#define __ide_mm_insw	__ide_insw
-#define __ide_mm_insl	__ide_insl
-#define __ide_mm_outsw	__ide_outsw
-#define __ide_mm_outsl	__ide_outsl
-
-static inline unsigned int inw_be(void __iomem *addr)
-{
-	unsigned int ret;
-
-	__asm__ __volatile__("lduha [%1] %2, %0"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-
-	return ret;
-}
-
-static inline void __ide_insw(void __iomem *port, void *dst, u32 count)
-{
-#ifdef DCACHE_ALIASING_POSSIBLE
-	unsigned long end = (unsigned long)dst + (count << 1);
-#endif
-	u16 *ps = dst;
-	u32 *pi;
-
-	if(((u64)ps) & 0x2) {
-		*ps++ = inw_be(port);
-		count--;
-	}
-	pi = (u32 *)ps;
-	while(count >= 2) {
-		u32 w;
-
-		w  = inw_be(port) << 16;
-		w |= inw_be(port);
-		*pi++ = w;
-		count -= 2;
-	}
-	ps = (u16 *)pi;
-	if(count)
-		*ps++ = inw_be(port);
-
-#ifdef DCACHE_ALIASING_POSSIBLE
-	__flush_dcache_range((unsigned long)dst, end);
-#endif
-}
-
-static inline void outw_be(unsigned short w, void __iomem *addr)
-{
-	__asm__ __volatile__("stha %0, [%1] %2"
-			     : /* no outputs */
-			     : "r" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-}
-
-static inline void __ide_outsw(void __iomem *port, void *src, u32 count)
-{
-#ifdef DCACHE_ALIASING_POSSIBLE
-	unsigned long end = (unsigned long)src + (count << 1);
-#endif
-	const u16 *ps = src;
-	const u32 *pi;
-
-	if(((u64)src) & 0x2) {
-		outw_be(*ps++, port);
-		count--;
-	}
-	pi = (const u32 *)ps;
-	while(count >= 2) {
-		u32 w;
-
-		w = *pi++;
-		outw_be((w >> 16), port);
-		outw_be(w, port);
-		count -= 2;
-	}
-	ps = (const u16 *)pi;
-	if(count)
-		outw_be(*ps, port);
-
-#ifdef DCACHE_ALIASING_POSSIBLE
-	__flush_dcache_range((unsigned long)src, end);
-#endif
-}
-
-#endif /* __KERNEL__ */
-
-#endif /* _SPARC64_IDE_H */
+#include <asm-sparc/ide.h>
diff --git a/include/asm-sparc64/idprom.h b/include/asm-sparc64/idprom.h
index a363fa0..c22f9c3 100644
--- a/include/asm-sparc64/idprom.h
+++ b/include/asm-sparc64/idprom.h
@@ -1,25 +1 @@
-/*
- * idprom.h: Macros and defines for idprom routines
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef _SPARC64_IDPROM_H
-#define _SPARC64_IDPROM_H
-
-#include <linux/types.h>
-
-struct idprom {
-	u8		id_format;	/* Format identifier (always 0x01) */
-	u8		id_machtype;	/* Machine type */
-	u8		id_ethaddr[6];	/* Hardware ethernet address */
-	s32		id_date;	/* Date of manufacture */
-	u32		id_sernum:24;	/* Unique serial number */
-	u8		id_cksum;	/* Checksum - xor of the data bytes */
-	u8		reserved[16];
-};
-
-extern struct idprom *idprom;
-extern void idprom_init(void);
-
-#endif /* !(_SPARC_IDPROM_H) */
+#include <asm-sparc/idprom.h>
diff --git a/include/asm-sparc64/intr_queue.h b/include/asm-sparc64/intr_queue.h
index 206077d..f722501 100644
--- a/include/asm-sparc64/intr_queue.h
+++ b/include/asm-sparc64/intr_queue.h
@@ -1,15 +1 @@
-#ifndef _SPARC64_INTR_QUEUE_H
-#define _SPARC64_INTR_QUEUE_H
-
-/* Sun4v interrupt queue registers, accessed via ASI_QUEUE.  */
-
-#define INTRQ_CPU_MONDO_HEAD	  0x3c0 /* CPU mondo head	          */
-#define INTRQ_CPU_MONDO_TAIL	  0x3c8 /* CPU mondo tail	          */
-#define INTRQ_DEVICE_MONDO_HEAD	  0x3d0 /* Device mondo head	          */
-#define INTRQ_DEVICE_MONDO_TAIL	  0x3d8 /* Device mondo tail	          */
-#define INTRQ_RESUM_MONDO_HEAD	  0x3e0 /* Resumable error mondo head     */
-#define INTRQ_RESUM_MONDO_TAIL	  0x3e8 /* Resumable error mondo tail     */
-#define INTRQ_NONRESUM_MONDO_HEAD 0x3f0 /* Non-resumable error mondo head */
-#define INTRQ_NONRESUM_MONDO_TAIL 0x3f8 /* Non-resumable error mondo head */
-
-#endif /* !(_SPARC64_INTR_QUEUE_H) */
+#include <asm-sparc/intr_queue.h>
diff --git a/include/asm-sparc64/io.h b/include/asm-sparc64/io.h
index 3158960..25ff258 100644
--- a/include/asm-sparc64/io.h
+++ b/include/asm-sparc64/io.h
@@ -1,511 +1 @@
-#ifndef __SPARC64_IO_H
-#define __SPARC64_IO_H
-
-#include <linux/kernel.h>
-#include <linux/compiler.h>
-#include <linux/types.h>
-
-#include <asm/page.h>      /* IO address mapping routines need this */
-#include <asm/system.h>
-#include <asm/asi.h>
-
-/* PC crapola... */
-#define __SLOW_DOWN_IO	do { } while (0)
-#define SLOW_DOWN_IO	do { } while (0)
-
-/* BIO layer definitions. */
-extern unsigned long kern_base, kern_size;
-#define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
-#define BIO_VMERGE_BOUNDARY	8192
-
-static inline u8 _inb(unsigned long addr)
-{
-	u8 ret;
-
-	__asm__ __volatile__("lduba\t[%1] %2, %0\t/* pci_inb */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
-			     : "memory");
-
-	return ret;
-}
-
-static inline u16 _inw(unsigned long addr)
-{
-	u16 ret;
-
-	__asm__ __volatile__("lduha\t[%1] %2, %0\t/* pci_inw */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
-			     : "memory");
-
-	return ret;
-}
-
-static inline u32 _inl(unsigned long addr)
-{
-	u32 ret;
-
-	__asm__ __volatile__("lduwa\t[%1] %2, %0\t/* pci_inl */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
-			     : "memory");
-
-	return ret;
-}
-
-static inline void _outb(u8 b, unsigned long addr)
-{
-	__asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_outb */"
-			     : /* no outputs */
-			     : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
-			     : "memory");
-}
-
-static inline void _outw(u16 w, unsigned long addr)
-{
-	__asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_outw */"
-			     : /* no outputs */
-			     : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
-			     : "memory");
-}
-
-static inline void _outl(u32 l, unsigned long addr)
-{
-	__asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_outl */"
-			     : /* no outputs */
-			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
-			     : "memory");
-}
-
-#define inb(__addr)		(_inb((unsigned long)(__addr)))
-#define inw(__addr)		(_inw((unsigned long)(__addr)))
-#define inl(__addr)		(_inl((unsigned long)(__addr)))
-#define outb(__b, __addr)	(_outb((u8)(__b), (unsigned long)(__addr)))
-#define outw(__w, __addr)	(_outw((u16)(__w), (unsigned long)(__addr)))
-#define outl(__l, __addr)	(_outl((u32)(__l), (unsigned long)(__addr)))
-
-#define inb_p(__addr) 		inb(__addr)
-#define outb_p(__b, __addr)	outb(__b, __addr)
-#define inw_p(__addr)		inw(__addr)
-#define outw_p(__w, __addr)	outw(__w, __addr)
-#define inl_p(__addr)		inl(__addr)
-#define outl_p(__l, __addr)	outl(__l, __addr)
-
-extern void outsb(unsigned long, const void *, unsigned long);
-extern void outsw(unsigned long, const void *, unsigned long);
-extern void outsl(unsigned long, const void *, unsigned long);
-extern void insb(unsigned long, void *, unsigned long);
-extern void insw(unsigned long, void *, unsigned long);
-extern void insl(unsigned long, void *, unsigned long);
-
-static inline void ioread8_rep(void __iomem *port, void *buf, unsigned long count)
-{
-	insb((unsigned long __force)port, buf, count);
-}
-static inline void ioread16_rep(void __iomem *port, void *buf, unsigned long count)
-{
-	insw((unsigned long __force)port, buf, count);
-}
-
-static inline void ioread32_rep(void __iomem *port, void *buf, unsigned long count)
-{
-	insl((unsigned long __force)port, buf, count);
-}
-
-static inline void iowrite8_rep(void __iomem *port, const void *buf, unsigned long count)
-{
-	outsb((unsigned long __force)port, buf, count);
-}
-
-static inline void iowrite16_rep(void __iomem *port, const void *buf, unsigned long count)
-{
-	outsw((unsigned long __force)port, buf, count);
-}
-
-static inline void iowrite32_rep(void __iomem *port, const void *buf, unsigned long count)
-{
-	outsl((unsigned long __force)port, buf, count);
-}
-
-/* Memory functions, same as I/O accesses on Ultra. */
-static inline u8 _readb(const volatile void __iomem *addr)
-{	u8 ret;
-
-	__asm__ __volatile__("lduba\t[%1] %2, %0\t/* pci_readb */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
-			     : "memory");
-	return ret;
-}
-
-static inline u16 _readw(const volatile void __iomem *addr)
-{	u16 ret;
-
-	__asm__ __volatile__("lduha\t[%1] %2, %0\t/* pci_readw */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
-			     : "memory");
-
-	return ret;
-}
-
-static inline u32 _readl(const volatile void __iomem *addr)
-{	u32 ret;
-
-	__asm__ __volatile__("lduwa\t[%1] %2, %0\t/* pci_readl */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
-			     : "memory");
-
-	return ret;
-}
-
-static inline u64 _readq(const volatile void __iomem *addr)
-{	u64 ret;
-
-	__asm__ __volatile__("ldxa\t[%1] %2, %0\t/* pci_readq */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
-			     : "memory");
-
-	return ret;
-}
-
-static inline void _writeb(u8 b, volatile void __iomem *addr)
-{
-	__asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_writeb */"
-			     : /* no outputs */
-			     : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
-			     : "memory");
-}
-
-static inline void _writew(u16 w, volatile void __iomem *addr)
-{
-	__asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_writew */"
-			     : /* no outputs */
-			     : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
-			     : "memory");
-}
-
-static inline void _writel(u32 l, volatile void __iomem *addr)
-{
-	__asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_writel */"
-			     : /* no outputs */
-			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
-			     : "memory");
-}
-
-static inline void _writeq(u64 q, volatile void __iomem *addr)
-{
-	__asm__ __volatile__("stxa\t%r0, [%1] %2\t/* pci_writeq */"
-			     : /* no outputs */
-			     : "Jr" (q), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
-			     : "memory");
-}
-
-#define readb(__addr)		_readb(__addr)
-#define readw(__addr)		_readw(__addr)
-#define readl(__addr)		_readl(__addr)
-#define readq(__addr)		_readq(__addr)
-#define readb_relaxed(__addr)	_readb(__addr)
-#define readw_relaxed(__addr)	_readw(__addr)
-#define readl_relaxed(__addr)	_readl(__addr)
-#define readq_relaxed(__addr)	_readq(__addr)
-#define writeb(__b, __addr)	_writeb(__b, __addr)
-#define writew(__w, __addr)	_writew(__w, __addr)
-#define writel(__l, __addr)	_writel(__l, __addr)
-#define writeq(__q, __addr)	_writeq(__q, __addr)
-
-/* Now versions without byte-swapping. */
-static inline u8 _raw_readb(unsigned long addr)
-{
-	u8 ret;
-
-	__asm__ __volatile__("lduba\t[%1] %2, %0\t/* pci_raw_readb */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-
-	return ret;
-}
-
-static inline u16 _raw_readw(unsigned long addr)
-{
-	u16 ret;
-
-	__asm__ __volatile__("lduha\t[%1] %2, %0\t/* pci_raw_readw */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-
-	return ret;
-}
-
-static inline u32 _raw_readl(unsigned long addr)
-{
-	u32 ret;
-
-	__asm__ __volatile__("lduwa\t[%1] %2, %0\t/* pci_raw_readl */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-
-	return ret;
-}
-
-static inline u64 _raw_readq(unsigned long addr)
-{
-	u64 ret;
-
-	__asm__ __volatile__("ldxa\t[%1] %2, %0\t/* pci_raw_readq */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-
-	return ret;
-}
-
-static inline void _raw_writeb(u8 b, unsigned long addr)
-{
-	__asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_raw_writeb */"
-			     : /* no outputs */
-			     : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-}
-
-static inline void _raw_writew(u16 w, unsigned long addr)
-{
-	__asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_raw_writew */"
-			     : /* no outputs */
-			     : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-}
-
-static inline void _raw_writel(u32 l, unsigned long addr)
-{
-	__asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_raw_writel */"
-			     : /* no outputs */
-			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-}
-
-static inline void _raw_writeq(u64 q, unsigned long addr)
-{
-	__asm__ __volatile__("stxa\t%r0, [%1] %2\t/* pci_raw_writeq */"
-			     : /* no outputs */
-			     : "Jr" (q), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-}
-
-#define __raw_readb(__addr)		(_raw_readb((unsigned long)(__addr)))
-#define __raw_readw(__addr)		(_raw_readw((unsigned long)(__addr)))
-#define __raw_readl(__addr)		(_raw_readl((unsigned long)(__addr)))
-#define __raw_readq(__addr)		(_raw_readq((unsigned long)(__addr)))
-#define __raw_writeb(__b, __addr)	(_raw_writeb((u8)(__b), (unsigned long)(__addr)))
-#define __raw_writew(__w, __addr)	(_raw_writew((u16)(__w), (unsigned long)(__addr)))
-#define __raw_writel(__l, __addr)	(_raw_writel((u32)(__l), (unsigned long)(__addr)))
-#define __raw_writeq(__q, __addr)	(_raw_writeq((u64)(__q), (unsigned long)(__addr)))
-
-/* Valid I/O Space regions are anywhere, because each PCI bus supported
- * can live in an arbitrary area of the physical address range.
- */
-#define IO_SPACE_LIMIT 0xffffffffffffffffUL
-
-/* Now, SBUS variants, only difference from PCI is that we do
- * not use little-endian ASIs.
- */
-static inline u8 _sbus_readb(const volatile void __iomem *addr)
-{
-	u8 ret;
-
-	__asm__ __volatile__("lduba\t[%1] %2, %0\t/* sbus_readb */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
-			     : "memory");
-
-	return ret;
-}
-
-static inline u16 _sbus_readw(const volatile void __iomem *addr)
-{
-	u16 ret;
-
-	__asm__ __volatile__("lduha\t[%1] %2, %0\t/* sbus_readw */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
-			     : "memory");
-
-	return ret;
-}
-
-static inline u32 _sbus_readl(const volatile void __iomem *addr)
-{
-	u32 ret;
-
-	__asm__ __volatile__("lduwa\t[%1] %2, %0\t/* sbus_readl */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
-			     : "memory");
-
-	return ret;
-}
-
-static inline u64 _sbus_readq(const volatile void __iomem *addr)
-{
-	u64 ret;
-
-	__asm__ __volatile__("ldxa\t[%1] %2, %0\t/* sbus_readq */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
-			     : "memory");
-
-	return ret;
-}
-
-static inline void _sbus_writeb(u8 b, volatile void __iomem *addr)
-{
-	__asm__ __volatile__("stba\t%r0, [%1] %2\t/* sbus_writeb */"
-			     : /* no outputs */
-			     : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
-			     : "memory");
-}
-
-static inline void _sbus_writew(u16 w, volatile void __iomem *addr)
-{
-	__asm__ __volatile__("stha\t%r0, [%1] %2\t/* sbus_writew */"
-			     : /* no outputs */
-			     : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
-			     : "memory");
-}
-
-static inline void _sbus_writel(u32 l, volatile void __iomem *addr)
-{
-	__asm__ __volatile__("stwa\t%r0, [%1] %2\t/* sbus_writel */"
-			     : /* no outputs */
-			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
-			     : "memory");
-}
-
-static inline void _sbus_writeq(u64 l, volatile void __iomem *addr)
-{
-	__asm__ __volatile__("stxa\t%r0, [%1] %2\t/* sbus_writeq */"
-			     : /* no outputs */
-			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)
-			     : "memory");
-}
-
-#define sbus_readb(__addr)		_sbus_readb(__addr)
-#define sbus_readw(__addr)		_sbus_readw(__addr)
-#define sbus_readl(__addr)		_sbus_readl(__addr)
-#define sbus_readq(__addr)		_sbus_readq(__addr)
-#define sbus_writeb(__b, __addr)	_sbus_writeb(__b, __addr)
-#define sbus_writew(__w, __addr)	_sbus_writew(__w, __addr)
-#define sbus_writel(__l, __addr)	_sbus_writel(__l, __addr)
-#define sbus_writeq(__l, __addr)	_sbus_writeq(__l, __addr)
-
-static inline void _sbus_memset_io(volatile void __iomem *dst, int c, __kernel_size_t n)
-{
-	while(n--) {
-		sbus_writeb(c, dst);
-		dst++;
-	}
-}
-
-#define sbus_memset_io(d,c,sz)	_sbus_memset_io(d,c,sz)
-
-static inline void
-_memset_io(volatile void __iomem *dst, int c, __kernel_size_t n)
-{
-	volatile void __iomem *d = dst;
-
-	while (n--) {
-		writeb(c, d);
-		d++;
-	}
-}
-
-#define memset_io(d,c,sz)	_memset_io(d,c,sz)
-
-static inline void
-_memcpy_fromio(void *dst, const volatile void __iomem *src, __kernel_size_t n)
-{
-	char *d = dst;
-
-	while (n--) {
-		char tmp = readb(src);
-		*d++ = tmp;
-		src++;
-	}
-}
-
-#define memcpy_fromio(d,s,sz)	_memcpy_fromio(d,s,sz)
-
-static inline void 
-_memcpy_toio(volatile void __iomem *dst, const void *src, __kernel_size_t n)
-{
-	const char *s = src;
-	volatile void __iomem *d = dst;
-
-	while (n--) {
-		char tmp = *s++;
-		writeb(tmp, d);
-		d++;
-	}
-}
-
-#define memcpy_toio(d,s,sz)	_memcpy_toio(d,s,sz)
-
-#define mmiowb()
-
-#ifdef __KERNEL__
-
-/* On sparc64 we have the whole physical IO address space accessible
- * using physically addressed loads and stores, so this does nothing.
- */
-static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
-{
-	return (void __iomem *)offset;
-}
-
-#define ioremap_nocache(X,Y)		ioremap((X),(Y))
-
-static inline void iounmap(volatile void __iomem *addr)
-{
-}
-
-#define ioread8(X)			readb(X)
-#define ioread16(X)			readw(X)
-#define ioread32(X)			readl(X)
-#define iowrite8(val,X)			writeb(val,X)
-#define iowrite16(val,X)		writew(val,X)
-#define iowrite32(val,X)		writel(val,X)
-
-/* Create a virtual mapping cookie for an IO port range */
-extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
-extern void ioport_unmap(void __iomem *);
-
-/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
-struct pci_dev;
-extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
-extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
-
-/* Similarly for SBUS. */
-#define sbus_ioremap(__res, __offset, __size, __name) \
-({	unsigned long __ret; \
-	__ret  = (__res)->start + (((__res)->flags & 0x1ffUL) << 32UL); \
-	__ret += (unsigned long) (__offset); \
-	if (! request_region((__ret), (__size), (__name))) \
-		__ret = 0UL; \
-	(void __iomem *) __ret; \
-})
-
-#define sbus_iounmap(__addr, __size)	\
-	release_region((unsigned long)(__addr), (__size))
-
-/*
- * Convert a physical pointer to a virtual kernel pointer for /dev/mem
- * access
- */
-#define xlate_dev_mem_ptr(p)	__va(p)
-
-/*
- * Convert a virtual cached pointer to an uncached pointer
- */
-#define xlate_dev_kmem_ptr(p)	p
-
-#endif
-
-#endif /* !(__SPARC64_IO_H) */
+#include <asm-sparc/io.h>
diff --git a/include/asm-sparc64/ioctl.h b/include/asm-sparc64/ioctl.h
index d634c21..18fc562 100644
--- a/include/asm-sparc64/ioctl.h
+++ b/include/asm-sparc64/ioctl.h
@@ -1,67 +1 @@
-#ifndef _SPARC64_IOCTL_H
-#define _SPARC64_IOCTL_H
-
-/*
- * Our DIR and SIZE overlap in order to simulteneously provide
- * a non-zero _IOC_NONE (for binary compatibility) and
- * 14 bits of size as on i386. Here's the layout:
- *
- *   0xE0000000   DIR
- *   0x80000000     DIR = WRITE
- *   0x40000000     DIR = READ
- *   0x20000000     DIR = NONE
- *   0x3FFF0000   SIZE (overlaps NONE bit)
- *   0x0000FF00   TYPE
- *   0x000000FF   NR (CMD)
- */
-
-#define _IOC_NRBITS      8
-#define _IOC_TYPEBITS    8
-#define _IOC_SIZEBITS   13	/* Actually 14, see below. */
-#define _IOC_DIRBITS     3
-
-#define _IOC_NRMASK      ((1 << _IOC_NRBITS)-1)
-#define _IOC_TYPEMASK    ((1 << _IOC_TYPEBITS)-1)
-#define _IOC_SIZEMASK    ((1 << _IOC_SIZEBITS)-1)
-#define _IOC_XSIZEMASK   ((1 << (_IOC_SIZEBITS+1))-1)
-#define _IOC_DIRMASK     ((1 << _IOC_DIRBITS)-1)
-
-#define _IOC_NRSHIFT     0
-#define _IOC_TYPESHIFT   (_IOC_NRSHIFT + _IOC_NRBITS)
-#define _IOC_SIZESHIFT   (_IOC_TYPESHIFT + _IOC_TYPEBITS)
-#define _IOC_DIRSHIFT    (_IOC_SIZESHIFT + _IOC_SIZEBITS)
-
-#define _IOC_NONE        1U
-#define _IOC_READ        2U
-#define _IOC_WRITE       4U
-
-#define _IOC(dir,type,nr,size) \
-        (((dir)  << _IOC_DIRSHIFT) | \
-         ((type) << _IOC_TYPESHIFT) | \
-         ((nr)   << _IOC_NRSHIFT) | \
-         ((size) << _IOC_SIZESHIFT))
-
-#define _IO(type,nr)        _IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)  _IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)  _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* Used to decode ioctl numbers in drivers despite the leading underscore... */
-#define _IOC_DIR(nr)    \
- ( (((((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) & (_IOC_WRITE|_IOC_READ)) != 0)?   \
-                            (((nr) >> _IOC_DIRSHIFT) & (_IOC_WRITE|_IOC_READ)):  \
-                            (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) )
-#define _IOC_TYPE(nr)       (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
-#define _IOC_NR(nr)         (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
-#define _IOC_SIZE(nr)   \
- ((((((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) & (_IOC_WRITE|_IOC_READ)) == 0)?    \
-                         0: (((nr) >> _IOC_SIZESHIFT) & _IOC_XSIZEMASK))
-
-/* ...and for the PCMCIA and sound. */
-#define IOC_IN          (_IOC_WRITE << _IOC_DIRSHIFT)
-#define IOC_OUT         (_IOC_READ << _IOC_DIRSHIFT)
-#define IOC_INOUT       ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
-#define IOCSIZE_MASK    (_IOC_XSIZEMASK << _IOC_SIZESHIFT)
-#define IOCSIZE_SHIFT   (_IOC_SIZESHIFT)
-
-#endif /* !(_SPARC64_IOCTL_H) */
+#include <asm-sparc/ioctl.h>
diff --git a/include/asm-sparc64/ioctls.h b/include/asm-sparc64/ioctls.h
index 94d1b75..dcd5540 100644
--- a/include/asm-sparc64/ioctls.h
+++ b/include/asm-sparc64/ioctls.h
@@ -1,136 +1 @@
-#ifndef _ASM_SPARC64_IOCTLS_H
-#define _ASM_SPARC64_IOCTLS_H
-
-#include <asm/ioctl.h>
-
-/* Big T */
-#define TCGETA		_IOR('T', 1, struct termio)
-#define TCSETA		_IOW('T', 2, struct termio)
-#define TCSETAW		_IOW('T', 3, struct termio)
-#define TCSETAF		_IOW('T', 4, struct termio)
-#define TCSBRK		_IO('T', 5)
-#define TCXONC		_IO('T', 6)
-#define TCFLSH		_IO('T', 7)
-#define TCGETS		_IOR('T', 8, struct termios)
-#define TCSETS		_IOW('T', 9, struct termios)
-#define TCSETSW		_IOW('T', 10, struct termios)
-#define TCSETSF		_IOW('T', 11, struct termios)
-#define TCGETS2		_IOR('T', 12, struct termios2)
-#define TCSETS2		_IOW('T', 13, struct termios2)
-#define TCSETSW2	_IOW('T', 14, struct termios2)
-#define TCSETSF2	_IOW('T', 15, struct termios2)
-
-/* Note that all the ioctls that are not available in Linux have a 
- * double underscore on the front to: a) avoid some programs to
- * think we support some ioctls under Linux (autoconfiguration stuff)
- */
-/* Little t */
-#define TIOCGETD	_IOR('t', 0, int)
-#define TIOCSETD	_IOW('t', 1, int)
-#define __TIOCHPCL        _IO('t', 2) /* SunOS Specific */
-#define __TIOCMODG        _IOR('t', 3, int) /* SunOS Specific */
-#define __TIOCMODS        _IOW('t', 4, int) /* SunOS Specific */
-#define __TIOCGETP        _IOR('t', 8, struct sgttyb) /* SunOS Specific */
-#define __TIOCSETP        _IOW('t', 9, struct sgttyb) /* SunOS Specific */
-#define __TIOCSETN        _IOW('t', 10, struct sgttyb) /* SunOS Specific */
-#define TIOCEXCL	_IO('t', 13)
-#define TIOCNXCL	_IO('t', 14)
-#define __TIOCFLUSH       _IOW('t', 16, int) /* SunOS Specific */
-#define __TIOCSETC        _IOW('t', 17, struct tchars) /* SunOS Specific */
-#define __TIOCGETC        _IOR('t', 18, struct tchars) /* SunOS Specific */
-#define __TIOCTCNTL       _IOW('t', 32, int) /* SunOS Specific */
-#define __TIOCSIGNAL      _IOW('t', 33, int) /* SunOS Specific */
-#define __TIOCSETX        _IOW('t', 34, int) /* SunOS Specific */
-#define __TIOCGETX        _IOR('t', 35, int) /* SunOS Specific */
-#define TIOCCONS	_IO('t', 36)
-#define TIOCGSOFTCAR	_IOR('t', 100, int)
-#define TIOCSSOFTCAR	_IOW('t', 101, int)
-#define __TIOCUCNTL       _IOW('t', 102, int) /* SunOS Specific */
-#define TIOCSWINSZ	_IOW('t', 103, struct winsize)
-#define TIOCGWINSZ	_IOR('t', 104, struct winsize)
-#define __TIOCREMOTE      _IOW('t', 105, int) /* SunOS Specific */
-#define TIOCMGET	_IOR('t', 106, int)
-#define TIOCMBIC	_IOW('t', 107, int)
-#define TIOCMBIS	_IOW('t', 108, int)
-#define TIOCMSET	_IOW('t', 109, int)
-#define TIOCSTART       _IO('t', 110)
-#define TIOCSTOP        _IO('t', 111)
-#define TIOCPKT		_IOW('t', 112, int)
-#define TIOCNOTTY	_IO('t', 113)
-#define TIOCSTI		_IOW('t', 114, char)
-#define TIOCOUTQ	_IOR('t', 115, int)
-#define __TIOCGLTC        _IOR('t', 116, struct ltchars) /* SunOS Specific */
-#define __TIOCSLTC        _IOW('t', 117, struct ltchars) /* SunOS Specific */
-/* 118 is the non-posix setpgrp tty ioctl */
-/* 119 is the non-posix getpgrp tty ioctl */
-#define __TIOCCDTR        _IO('t', 120) /* SunOS Specific */
-#define __TIOCSDTR        _IO('t', 121) /* SunOS Specific */
-#define TIOCCBRK        _IO('t', 122)
-#define TIOCSBRK        _IO('t', 123)
-#define __TIOCLGET        _IOW('t', 124, int) /* SunOS Specific */
-#define __TIOCLSET        _IOW('t', 125, int) /* SunOS Specific */
-#define __TIOCLBIC        _IOW('t', 126, int) /* SunOS Specific */
-#define __TIOCLBIS        _IOW('t', 127, int) /* SunOS Specific */
-#define __TIOCISPACE      _IOR('t', 128, int) /* SunOS Specific */
-#define __TIOCISIZE       _IOR('t', 129, int) /* SunOS Specific */
-#define TIOCSPGRP	_IOW('t', 130, int)
-#define TIOCGPGRP	_IOR('t', 131, int)
-#define TIOCSCTTY	_IO('t', 132)
-#define TIOCGSID	_IOR('t', 133, int)
-/* Get minor device of a pty master's FD -- Solaris equiv is ISPTM */
-#define TIOCGPTN	_IOR('t', 134, unsigned int) /* Get Pty Number */
-#define TIOCSPTLCK	_IOW('t', 135, int) /* Lock/unlock PTY */
-
-/* Little f */
-#define FIOCLEX		_IO('f', 1)
-#define FIONCLEX	_IO('f', 2)
-#define FIOASYNC	_IOW('f', 125, int)
-#define FIONBIO		_IOW('f', 126, int)
-#define FIONREAD	_IOR('f', 127, int)
-#define TIOCINQ		FIONREAD
-#define FIOQSIZE	_IOR('f', 128, loff_t)
-
-/* SCARY Rutgers local SunOS kernel hackery, perhaps I will support it
- * someday.  This is completely bogus, I know...
- */
-#define __TCGETSTAT       _IO('T', 200) /* Rutgers specific */
-#define __TCSETSTAT       _IO('T', 201) /* Rutgers specific */
-
-/* Linux specific, no SunOS equivalent. */
-#define TIOCLINUX	0x541C
-#define TIOCGSERIAL	0x541E
-#define TIOCSSERIAL	0x541F
-#define TCSBRKP		0x5425
-#define TIOCSERCONFIG	0x5453
-#define TIOCSERGWILD	0x5454
-#define TIOCSERSWILD	0x5455
-#define TIOCGLCKTRMIOS	0x5456
-#define TIOCSLCKTRMIOS	0x5457
-#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-#define TIOCMIWAIT	0x545C /* Wait for change on serial input line(s) */
-#define TIOCGICOUNT	0x545D /* Read serial port inline interrupt counts */
-
-/* Kernel definitions */
-#ifdef __KERNEL__
-#define TIOCGETC __TIOCGETC
-#define TIOCGETP __TIOCGETP
-#define TIOCGLTC __TIOCGLTC
-#define TIOCSLTC __TIOCSLTC
-#define TIOCSETP __TIOCSETP
-#define TIOCSETN __TIOCSETN
-#define TIOCSETC __TIOCSETC
-#endif
-
-/* Used for packet mode */
-#define TIOCPKT_DATA		 0
-#define TIOCPKT_FLUSHREAD	 1
-#define TIOCPKT_FLUSHWRITE	 2
-#define TIOCPKT_STOP		 4
-#define TIOCPKT_START		 8
-#define TIOCPKT_NOSTOP		16
-#define TIOCPKT_DOSTOP		32
-
-#endif /* !(_ASM_SPARC64_IOCTLS_H) */
+#include <asm-sparc/ioctls.h>
diff --git a/include/asm-sparc64/iommu.h b/include/asm-sparc64/iommu.h
index d7b9afc..76252bb 100644
--- a/include/asm-sparc64/iommu.h
+++ b/include/asm-sparc64/iommu.h
@@ -1,62 +1 @@
-/* iommu.h: Definitions for the sun5 IOMMU.
- *
- * Copyright (C) 1996, 1999, 2007 David S. Miller (davem@davemloft.net)
- */
-#ifndef _SPARC64_IOMMU_H
-#define _SPARC64_IOMMU_H
-
-/* The format of an iopte in the page tables. */
-#define IOPTE_VALID   0x8000000000000000UL
-#define IOPTE_64K     0x2000000000000000UL
-#define IOPTE_STBUF   0x1000000000000000UL
-#define IOPTE_INTRA   0x0800000000000000UL
-#define IOPTE_CONTEXT 0x07ff800000000000UL
-#define IOPTE_PAGE    0x00007fffffffe000UL
-#define IOPTE_CACHE   0x0000000000000010UL
-#define IOPTE_WRITE   0x0000000000000002UL
-
-#define IOMMU_NUM_CTXS	4096
-
-struct iommu_arena {
-	unsigned long	*map;
-	unsigned int	hint;
-	unsigned int	limit;
-};
-
-struct iommu {
-	spinlock_t		lock;
-	struct iommu_arena	arena;
-	void			(*flush_all)(struct iommu *);
-	iopte_t			*page_table;
-	u32			page_table_map_base;
-	unsigned long		iommu_control;
-	unsigned long		iommu_tsbbase;
-	unsigned long		iommu_flush;
-	unsigned long		iommu_flushinv;
-	unsigned long		iommu_tags;
-	unsigned long		iommu_ctxflush;
-	unsigned long		write_complete_reg;
-	unsigned long		dummy_page;
-	unsigned long		dummy_page_pa;
-	unsigned long		ctx_lowest_free;
-	DECLARE_BITMAP(ctx_bitmap, IOMMU_NUM_CTXS);
-	u32			dma_addr_mask;
-};
-
-struct strbuf {
-	int			strbuf_enabled;
-	unsigned long		strbuf_control;
-	unsigned long		strbuf_pflush;
-	unsigned long		strbuf_fsync;
-	unsigned long		strbuf_ctxflush;
-	unsigned long		strbuf_ctxmatch_base;
-	unsigned long		strbuf_flushflag_pa;
-	volatile unsigned long *strbuf_flushflag;
-	volatile unsigned long	__flushflag_buf[(64+(64-1)) / sizeof(long)];
-};
-
-extern int iommu_table_init(struct iommu *iommu, int tsbsize,
-			    u32 dma_offset, u32 dma_addr_mask,
-			    int numa_node);
-
-#endif /* !(_SPARC64_IOMMU_H) */
+#include <asm-sparc/iommu.h>
diff --git a/include/asm-sparc64/ipcbuf.h b/include/asm-sparc64/ipcbuf.h
index 9c5bf1b..41dfaf1 100644
--- a/include/asm-sparc64/ipcbuf.h
+++ b/include/asm-sparc64/ipcbuf.h
@@ -1,28 +1 @@
-#ifndef _SPARC64_IPCBUF_H
-#define _SPARC64_IPCBUF_H
-
-/* 
- * The ipc64_perm structure for sparc64 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 32-bit seq
- * - 2 miscellaneous 64-bit values
- */
-
-struct ipc64_perm
-{
-	__kernel_key_t	key;
-	__kernel_uid_t	uid;
-	__kernel_gid_t	gid;
-	__kernel_uid_t	cuid;
-	__kernel_gid_t	cgid;
-	__kernel_mode_t	mode; 
-	unsigned short	__pad1;
-	unsigned short	seq;
-	unsigned long	__unused1;
-	unsigned long	__unused2;
-};
-
-#endif /* _SPARC64_IPCBUF_H */
+#include <asm-sparc/ipcbuf.h>
diff --git a/include/asm-sparc64/irq.h b/include/asm-sparc64/irq.h
index 0bb9bf5..b2102e6 100644
--- a/include/asm-sparc64/irq.h
+++ b/include/asm-sparc64/irq.h
@@ -1,93 +1 @@
-/* irq.h: IRQ registers on the 64-bit Sparc.
- *
- * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
- * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
- */
-
-#ifndef _SPARC64_IRQ_H
-#define _SPARC64_IRQ_H
-
-#include <linux/linkage.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <asm/pil.h>
-#include <asm/ptrace.h>
-
-/* IMAP/ICLR register defines */
-#define IMAP_VALID		0x80000000UL	/* IRQ Enabled		*/
-#define IMAP_TID_UPA		0x7c000000UL	/* UPA TargetID		*/
-#define IMAP_TID_JBUS		0x7c000000UL	/* JBUS TargetID	*/
-#define IMAP_TID_SHIFT		26
-#define IMAP_AID_SAFARI		0x7c000000UL	/* Safari AgentID	*/
-#define IMAP_AID_SHIFT		26
-#define IMAP_NID_SAFARI		0x03e00000UL	/* Safari NodeID	*/
-#define IMAP_NID_SHIFT		21
-#define IMAP_IGN		0x000007c0UL	/* IRQ Group Number	*/
-#define IMAP_INO		0x0000003fUL	/* IRQ Number		*/
-#define IMAP_INR		0x000007ffUL	/* Full interrupt number*/
-
-#define ICLR_IDLE		0x00000000UL	/* Idle state		*/
-#define ICLR_TRANSMIT		0x00000001UL	/* Transmit state	*/
-#define ICLR_PENDING		0x00000003UL	/* Pending state	*/
-
-/* The largest number of unique interrupt sources we support.
- * If this needs to ever be larger than 255, you need to change
- * the type of ino_bucket->virt_irq as appropriate.
- *
- * ino_bucket->virt_irq allocation is made during {sun4v_,}build_irq().
- */
-#define NR_IRQS    255
-
-extern void irq_install_pre_handler(int virt_irq,
-				    void (*func)(unsigned int, void *, void *),
-				    void *arg1, void *arg2);
-#define irq_canonicalize(irq)	(irq)
-extern unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap);
-extern unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino);
-extern unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino);
-extern unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p,
-				    unsigned int msi_devino_start,
-				    unsigned int msi_devino_end);
-extern void sun4v_destroy_msi(unsigned int virt_irq);
-extern unsigned int sun4u_build_msi(u32 portid, unsigned int *virt_irq_p,
-				    unsigned int msi_devino_start,
-				    unsigned int msi_devino_end,
-				    unsigned long imap_base,
-				    unsigned long iclr_base);
-extern void sun4u_destroy_msi(unsigned int virt_irq);
-extern unsigned int sbus_build_irq(void *sbus, unsigned int ino);
-
-extern unsigned char virt_irq_alloc(unsigned int dev_handle,
-				    unsigned int dev_ino);
-#ifdef CONFIG_PCI_MSI
-extern void virt_irq_free(unsigned int virt_irq);
-#endif
-
-extern void __init init_IRQ(void);
-extern void fixup_irqs(void);
-
-static inline void set_softint(unsigned long bits)
-{
-	__asm__ __volatile__("wr	%0, 0x0, %%set_softint"
-			     : /* No outputs */
-			     : "r" (bits));
-}
-
-static inline void clear_softint(unsigned long bits)
-{
-	__asm__ __volatile__("wr	%0, 0x0, %%clear_softint"
-			     : /* No outputs */
-			     : "r" (bits));
-}
-
-static inline unsigned long get_softint(void)
-{
-	unsigned long retval;
-
-	__asm__ __volatile__("rd	%%softint, %0"
-			     : "=r" (retval));
-	return retval;
-}
-
-#endif
+#include <asm-sparc/irq.h>
diff --git a/include/asm-sparc64/irq_regs.h b/include/asm-sparc64/irq_regs.h
index 3dd9c0b..1e2b8a1 100644
--- a/include/asm-sparc64/irq_regs.h
+++ b/include/asm-sparc64/irq_regs.h
@@ -1 +1 @@
-#include <asm-generic/irq_regs.h>
+#include <asm-sparc/irq_regs.h>
diff --git a/include/asm-sparc64/irqflags.h b/include/asm-sparc64/irqflags.h
index 024fc54..27b091fc 100644
--- a/include/asm-sparc64/irqflags.h
+++ b/include/asm-sparc64/irqflags.h
@@ -1,89 +1 @@
-/*
- * include/asm-sparc64/irqflags.h
- *
- * IRQ flags handling
- *
- * This file gets included from lowlevel asm headers too, to provide
- * wrapped versions of the local_irq_*() APIs, based on the
- * raw_local_irq_*() functions from the lowlevel headers.
- */
-#ifndef _ASM_IRQFLAGS_H
-#define _ASM_IRQFLAGS_H
-
-#ifndef __ASSEMBLY__
-
-static inline unsigned long __raw_local_save_flags(void)
-{
-	unsigned long flags;
-
-	__asm__ __volatile__(
-		"rdpr	%%pil, %0"
-		: "=r" (flags)
-	);
-
-	return flags;
-}
-
-#define raw_local_save_flags(flags) \
-		do { (flags) = __raw_local_save_flags(); } while (0)
-
-static inline void raw_local_irq_restore(unsigned long flags)
-{
-	__asm__ __volatile__(
-		"wrpr	%0, %%pil"
-		: /* no output */
-		: "r" (flags)
-		: "memory"
-	);
-}
-
-static inline void raw_local_irq_disable(void)
-{
-	__asm__ __volatile__(
-		"wrpr	15, %%pil"
-		: /* no outputs */
-		: /* no inputs */
-		: "memory"
-	);
-}
-
-static inline void raw_local_irq_enable(void)
-{
-	__asm__ __volatile__(
-		"wrpr	0, %%pil"
-		: /* no outputs */
-		: /* no inputs */
-		: "memory"
-	);
-}
-
-static inline int raw_irqs_disabled_flags(unsigned long flags)
-{
-	return (flags > 0);
-}
-
-static inline int raw_irqs_disabled(void)
-{
-	unsigned long flags = __raw_local_save_flags();
-
-	return raw_irqs_disabled_flags(flags);
-}
-
-/*
- * For spinlocks, etc:
- */
-static inline unsigned long __raw_local_irq_save(void)
-{
-	unsigned long flags = __raw_local_save_flags();
-
-	raw_local_irq_disable();
-
-	return flags;
-}
-
-#define raw_local_irq_save(flags) \
-		do { (flags) = __raw_local_irq_save(); } while (0)
-
-#endif /* (__ASSEMBLY__) */
-
-#endif /* !(_ASM_IRQFLAGS_H) */
+#include <asm-sparc/irqflags.h>
diff --git a/include/asm-sparc64/kdebug.h b/include/asm-sparc64/kdebug.h
index f905b77..78cfd5d 100644
--- a/include/asm-sparc64/kdebug.h
+++ b/include/asm-sparc64/kdebug.h
@@ -1,19 +1 @@
-#ifndef _SPARC64_KDEBUG_H
-#define _SPARC64_KDEBUG_H
-
-struct pt_regs;
-
-extern void bad_trap(struct pt_regs *, long);
-
-/* Grossly misnamed. */
-enum die_val {
-	DIE_OOPS = 1,
-	DIE_DEBUG,	/* ta 0x70 */
-	DIE_DEBUG_2,	/* ta 0x71 */
-	DIE_DIE,
-	DIE_TRAP,
-	DIE_TRAP_TL1,
-	DIE_CALL,
-};
-
-#endif
+#include <asm-sparc/kdebug.h>
diff --git a/include/asm-sparc64/kmap_types.h b/include/asm-sparc64/kmap_types.h
index 34c1d3d..276530c 100644
--- a/include/asm-sparc64/kmap_types.h
+++ b/include/asm-sparc64/kmap_types.h
@@ -1,25 +1 @@
-#ifndef _ASM_KMAP_TYPES_H
-#define _ASM_KMAP_TYPES_H
-
-/* Dummy header just to define km_type.  None of this
- * is actually used on sparc64.  -DaveM
- */
-
-enum km_type {
-	KM_BOUNCE_READ,
-	KM_SKB_SUNRPC_DATA,
-	KM_SKB_DATA_SOFTIRQ,
-	KM_USER0,
-	KM_USER1,
-	KM_BIO_SRC_IRQ,
-	KM_BIO_DST_IRQ,
-	KM_PTE0,
-	KM_PTE1,
-	KM_IRQ0,
-	KM_IRQ1,
-	KM_SOFTIRQ0,
-	KM_SOFTIRQ1,
-	KM_TYPE_NR
-};
-
-#endif
+#include <asm-sparc/kmap_types.h>
diff --git a/include/asm-sparc64/kprobes.h b/include/asm-sparc64/kprobes.h
index 5879d71..c55e43e 100644
--- a/include/asm-sparc64/kprobes.h
+++ b/include/asm-sparc64/kprobes.h
@@ -1,49 +1 @@
-#ifndef _SPARC64_KPROBES_H
-#define _SPARC64_KPROBES_H
-
-#include <linux/types.h>
-#include <linux/percpu.h>
-
-typedef u32 kprobe_opcode_t;
-
-#define BREAKPOINT_INSTRUCTION   0x91d02070 /* ta 0x70 */
-#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
-#define MAX_INSN_SIZE 2
-
-#define kretprobe_blacklist_size 0
-
-#define arch_remove_kprobe(p)	do {} while (0)
-
-#define flush_insn_slot(p)		\
-do { 	flushi(&(p)->ainsn.insn[0]);	\
-	flushi(&(p)->ainsn.insn[1]);	\
-} while (0)
-
-void kretprobe_trampoline(void);
-
-/* Architecture specific copy of original instruction*/
-struct arch_specific_insn {
-	/* copy of the original instruction */
-	kprobe_opcode_t insn[MAX_INSN_SIZE];
-};
-
-struct prev_kprobe {
-	struct kprobe *kp;
-	unsigned long status;
-	unsigned long orig_tnpc;
-	unsigned long orig_tstate_pil;
-};
-
-/* per-cpu kprobe control block */
-struct kprobe_ctlblk {
-	unsigned long kprobe_status;
-	unsigned long kprobe_orig_tnpc;
-	unsigned long kprobe_orig_tstate_pil;
-	struct pt_regs jprobe_saved_regs;
-	struct prev_kprobe prev_kprobe;
-};
-
-extern int kprobe_exceptions_notify(struct notifier_block *self,
-				    unsigned long val, void *data);
-extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
-#endif /* _SPARC64_KPROBES_H */
+#include <asm-sparc/kprobes.h>
diff --git a/include/asm-sparc64/kvm.h b/include/asm-sparc64/kvm.h
index 380537a..53564ad 100644
--- a/include/asm-sparc64/kvm.h
+++ b/include/asm-sparc64/kvm.h
@@ -1,6 +1 @@
-#ifndef __LINUX_KVM_SPARC64_H
-#define __LINUX_KVM_SPARC64_H
-
-/* sparc64 does not support KVM */
-
-#endif
+#include <asm-sparc/kvm.h>
diff --git a/include/asm-sparc64/ldc.h b/include/asm-sparc64/ldc.h
index bdb524a..40f3f23 100644
--- a/include/asm-sparc64/ldc.h
+++ b/include/asm-sparc64/ldc.h
@@ -1,138 +1 @@
-#ifndef _SPARC64_LDC_H
-#define _SPARC64_LDC_H
-
-#include <asm/hypervisor.h>
-
-extern int ldom_domaining_enabled;
-extern void ldom_set_var(const char *var, const char *value);
-extern void ldom_reboot(const char *boot_command);
-extern void ldom_power_off(void);
-
-/* The event handler will be evoked when link state changes
- * or data becomes available on the receive side.
- *
- * For non-RAW links, if the LDC_EVENT_RESET event arrives the
- * driver should reset all of it's internal state and reinvoke
- * ldc_connect() to try and bring the link up again.
- *
- * For RAW links, ldc_connect() is not used.  Instead the driver
- * just waits for the LDC_EVENT_UP event.
- */
-struct ldc_channel_config {
-	void (*event)(void *arg, int event);
-
-	u32			mtu;
-	unsigned int		rx_irq;
-	unsigned int		tx_irq;
-	u8			mode;
-#define LDC_MODE_RAW		0x00
-#define LDC_MODE_UNRELIABLE	0x01
-#define LDC_MODE_RESERVED	0x02
-#define LDC_MODE_STREAM		0x03
-
-	u8			debug;
-#define LDC_DEBUG_HS		0x01
-#define LDC_DEBUG_STATE		0x02
-#define LDC_DEBUG_RX		0x04
-#define LDC_DEBUG_TX		0x08
-#define LDC_DEBUG_DATA		0x10
-};
-
-#define LDC_EVENT_RESET		0x01
-#define LDC_EVENT_UP		0x02
-#define LDC_EVENT_DATA_READY	0x04
-
-#define LDC_STATE_INVALID	0x00
-#define LDC_STATE_INIT		0x01
-#define LDC_STATE_BOUND		0x02
-#define LDC_STATE_READY		0x03
-#define LDC_STATE_CONNECTED	0x04
-
-struct ldc_channel;
-
-/* Allocate state for a channel.  */
-extern struct ldc_channel *ldc_alloc(unsigned long id,
-				     const struct ldc_channel_config *cfgp,
-				     void *event_arg);
-
-/* Shut down and free state for a channel.  */
-extern void ldc_free(struct ldc_channel *lp);
-
-/* Register TX and RX queues of the link with the hypervisor.  */
-extern int ldc_bind(struct ldc_channel *lp, const char *name);
-
-/* For non-RAW protocols we need to complete a handshake before
- * communication can proceed.  ldc_connect() does that, if the
- * handshake completes successfully, an LDC_EVENT_UP event will
- * be sent up to the driver.
- */
-extern int ldc_connect(struct ldc_channel *lp);
-extern int ldc_disconnect(struct ldc_channel *lp);
-
-extern int ldc_state(struct ldc_channel *lp);
-
-/* Read and write operations.  Only valid when the link is up.  */
-extern int ldc_write(struct ldc_channel *lp, const void *buf,
-		     unsigned int size);
-extern int ldc_read(struct ldc_channel *lp, void *buf, unsigned int size);
-
-#define LDC_MAP_SHADOW	0x01
-#define LDC_MAP_DIRECT	0x02
-#define LDC_MAP_IO	0x04
-#define LDC_MAP_R	0x08
-#define LDC_MAP_W	0x10
-#define LDC_MAP_X	0x20
-#define LDC_MAP_RW	(LDC_MAP_R | LDC_MAP_W)
-#define LDC_MAP_RWX	(LDC_MAP_R | LDC_MAP_W | LDC_MAP_X)
-#define LDC_MAP_ALL	0x03f
-
-struct ldc_trans_cookie {
-	u64			cookie_addr;
-	u64			cookie_size;
-};
-
-struct scatterlist;
-extern int ldc_map_sg(struct ldc_channel *lp,
-		      struct scatterlist *sg, int num_sg,
-		      struct ldc_trans_cookie *cookies, int ncookies,
-		      unsigned int map_perm);
-
-extern int ldc_map_single(struct ldc_channel *lp,
-			  void *buf, unsigned int len,
-			  struct ldc_trans_cookie *cookies, int ncookies,
-			  unsigned int map_perm);
-
-extern void ldc_unmap(struct ldc_channel *lp, struct ldc_trans_cookie *cookies,
-		      int ncookies);
-
-extern int ldc_copy(struct ldc_channel *lp, int copy_dir,
-		    void *buf, unsigned int len, unsigned long offset,
-		    struct ldc_trans_cookie *cookies, int ncookies);
-
-static inline int ldc_get_dring_entry(struct ldc_channel *lp,
-				      void *buf, unsigned int len,
-				      unsigned long offset,
-				      struct ldc_trans_cookie *cookies,
-				      int ncookies)
-{
-	return ldc_copy(lp, LDC_COPY_IN, buf, len, offset, cookies, ncookies);
-}
-
-static inline int ldc_put_dring_entry(struct ldc_channel *lp,
-				      void *buf, unsigned int len,
-				      unsigned long offset,
-				      struct ldc_trans_cookie *cookies,
-				      int ncookies)
-{
-	return ldc_copy(lp, LDC_COPY_OUT, buf, len, offset, cookies, ncookies);
-}
-
-extern void *ldc_alloc_exp_dring(struct ldc_channel *lp, unsigned int len,
-				 struct ldc_trans_cookie *cookies,
-				 int *ncookies, unsigned int map_perm);
-
-extern void ldc_free_exp_dring(struct ldc_channel *lp, void *buf,
-			       unsigned int len,
-			       struct ldc_trans_cookie *cookies, int ncookies);
-
-#endif /* _SPARC64_LDC_H */
+#include <asm-sparc/ldc.h>
diff --git a/include/asm-sparc64/linkage.h b/include/asm-sparc64/linkage.h
index 291c2d0..3ea4fd1 100644
--- a/include/asm-sparc64/linkage.h
+++ b/include/asm-sparc64/linkage.h
@@ -1,6 +1 @@
-#ifndef __ASM_LINKAGE_H
-#define __ASM_LINKAGE_H
-
-/* Nothing to see here... */
-
-#endif
+#include <asm-sparc/linkage.h>
diff --git a/include/asm-sparc64/lmb.h b/include/asm-sparc64/lmb.h
index 6a352cb..3d04981 100644
--- a/include/asm-sparc64/lmb.h
+++ b/include/asm-sparc64/lmb.h
@@ -1,10 +1 @@
-#ifndef _SPARC64_LMB_H
-#define _SPARC64_LMB_H
-
-#include <asm/oplib.h>
-
-#define LMB_DBG(fmt...) prom_printf(fmt)
-
-#define LMB_REAL_LIMIT	0
-
-#endif /* !(_SPARC64_LMB_H) */
+#include <asm-sparc/lmb.h>
diff --git a/include/asm-sparc64/lsu.h b/include/asm-sparc64/lsu.h
index 7190f8d..4e3d8b1 100644
--- a/include/asm-sparc64/lsu.h
+++ b/include/asm-sparc64/lsu.h
@@ -1,19 +1 @@
-#ifndef _SPARC64_LSU_H
-#define _SPARC64_LSU_H
-
-#include <linux/const.h>
-
-/* LSU Control Register */
-#define LSU_CONTROL_PM _AC(0x000001fe00000000,UL) /* Phys-watchpoint byte mask*/
-#define LSU_CONTROL_VM _AC(0x00000001fe000000,UL) /* Virt-watchpoint byte mask*/
-#define LSU_CONTROL_PR _AC(0x0000000001000000,UL) /* Phys-rd watchpoint enable*/
-#define LSU_CONTROL_PW _AC(0x0000000000800000,UL) /* Phys-wr watchpoint enable*/
-#define LSU_CONTROL_VR _AC(0x0000000000400000,UL) /* Virt-rd watchpoint enable*/
-#define LSU_CONTROL_VW _AC(0x0000000000200000,UL) /* Virt-wr watchpoint enable*/
-#define LSU_CONTROL_FM _AC(0x00000000000ffff0,UL) /* Parity mask enables.     */
-#define LSU_CONTROL_DM _AC(0x0000000000000008,UL) /* Data MMU enable.         */
-#define LSU_CONTROL_IM _AC(0x0000000000000004,UL) /* Instruction MMU enable.  */
-#define LSU_CONTROL_DC _AC(0x0000000000000002,UL) /* Data cache enable.       */
-#define LSU_CONTROL_IC _AC(0x0000000000000001,UL) /* Instruction cache enable.*/
-
-#endif /* !(_SPARC64_LSU_H) */
+#include <asm-sparc/lsu.h>
diff --git a/include/asm-sparc64/mc146818rtc.h b/include/asm-sparc64/mc146818rtc.h
index e9c0fcc..97842e6 100644
--- a/include/asm-sparc64/mc146818rtc.h
+++ b/include/asm-sparc64/mc146818rtc.h
@@ -1,34 +1 @@
-/*
- * Machine dependent access functions for RTC registers.
- */
-#ifndef __ASM_SPARC64_MC146818RTC_H
-#define __ASM_SPARC64_MC146818RTC_H
-
-#include <asm/io.h>
-
-#ifndef RTC_PORT
-#ifdef CONFIG_PCI
-extern unsigned long ds1287_regs;
-#else
-#define ds1287_regs (0UL)
-#endif
-#define RTC_PORT(x)	(ds1287_regs + (x))
-#define RTC_ALWAYS_BCD	0
-#endif
-
-/*
- * The yet supported machines all access the RTC index register via
- * an ISA port access but the way to access the date register differs ...
- */
-#define CMOS_READ(addr) ({ \
-outb_p((addr),RTC_PORT(0)); \
-inb_p(RTC_PORT(1)); \
-})
-#define CMOS_WRITE(val, addr) ({ \
-outb_p((addr),RTC_PORT(0)); \
-outb_p((val),RTC_PORT(1)); \
-})
-
-#define RTC_IRQ 8
-
-#endif /* __ASM_SPARC64_MC146818RTC_H */
+#include <asm-sparc/mc146818rtc.h>
diff --git a/include/asm-sparc64/mdesc.h b/include/asm-sparc64/mdesc.h
index 1acc727..165a193 100644
--- a/include/asm-sparc64/mdesc.h
+++ b/include/asm-sparc64/mdesc.h
@@ -1,78 +1 @@
-#ifndef _SPARC64_MDESC_H
-#define _SPARC64_MDESC_H
-
-#include <linux/types.h>
-#include <linux/cpumask.h>
-#include <asm/prom.h>
-
-struct mdesc_handle;
-
-/* Machine description operations are to be surrounded by grab and
- * release calls.  The mdesc_handle returned from the grab is
- * the first argument to all of the operational calls that work
- * on mdescs.
- */
-extern struct mdesc_handle *mdesc_grab(void);
-extern void mdesc_release(struct mdesc_handle *);
-
-#define MDESC_NODE_NULL		(~(u64)0)
-
-extern u64 mdesc_node_by_name(struct mdesc_handle *handle,
-			      u64 from_node, const char *name);
-#define mdesc_for_each_node_by_name(__hdl, __node, __name) \
-	for (__node = mdesc_node_by_name(__hdl, MDESC_NODE_NULL, __name); \
-	     (__node) != MDESC_NODE_NULL; \
-	     __node = mdesc_node_by_name(__hdl, __node, __name))
-
-/* Access to property values returned from mdesc_get_property() are
- * only valid inside of a mdesc_grab()/mdesc_release() sequence.
- * Once mdesc_release() is called, the memory backed up by these
- * pointers may reference freed up memory.
- *
- * Therefore callers must make copies of any property values
- * they need.
- *
- * These same rules apply to mdesc_node_name().
- */
-extern const void *mdesc_get_property(struct mdesc_handle *handle,
-				      u64 node, const char *name, int *lenp);
-extern const char *mdesc_node_name(struct mdesc_handle *hp, u64 node);
-
-/* MD arc iteration, the standard sequence is:
- *
- *	unsigned long arc;
- *	mdesc_for_each_arc(arc, handle, node, MDESC_ARC_TYPE_{FWD,BACK}) {
- *		unsigned long target = mdesc_arc_target(handle, arc);
- *		...
- *	}
- */
-
-#define MDESC_ARC_TYPE_FWD	"fwd"
-#define MDESC_ARC_TYPE_BACK	"back"
-
-extern u64 mdesc_next_arc(struct mdesc_handle *handle, u64 from,
-			  const char *arc_type);
-#define mdesc_for_each_arc(__arc, __hdl, __node, __type) \
-	for (__arc = mdesc_next_arc(__hdl, __node, __type); \
-	     (__arc) != MDESC_NODE_NULL; \
-	     __arc = mdesc_next_arc(__hdl, __arc, __type))
-
-extern u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc);
-
-extern void mdesc_update(void);
-
-struct mdesc_notifier_client {
-	void (*add)(struct mdesc_handle *handle, u64 node);
-	void (*remove)(struct mdesc_handle *handle, u64 node);
-
-	const char			*node_name;
-	struct mdesc_notifier_client	*next;
-};
-
-extern void mdesc_register_notifier(struct mdesc_notifier_client *client);
-
-extern void mdesc_fill_in_cpu_data(cpumask_t mask);
-
-extern void sun4v_mdesc_init(void);
-
-#endif
+#include <asm-sparc/mdesc.h>
diff --git a/include/asm-sparc64/mman.h b/include/asm-sparc64/mman.h
index d2ae67c..17ddb17 100644
--- a/include/asm-sparc64/mman.h
+++ b/include/asm-sparc64/mman.h
@@ -1,31 +1 @@
-#ifndef __SPARC64_MMAN_H__
-#define __SPARC64_MMAN_H__
-
-#include <asm-generic/mman.h>
-
-/* SunOS'ified... */
-
-#define MAP_RENAME      MAP_ANONYMOUS   /* In SunOS terminology */
-#define MAP_NORESERVE   0x40            /* don't reserve swap pages */
-#define MAP_INHERIT     0x80            /* SunOS doesn't do this, but... */
-#define MAP_LOCKED      0x100           /* lock the mapping */
-#define _MAP_NEW        0x80000000      /* Binary compatibility is fun... */
-
-#define MAP_GROWSDOWN	0x0200		/* stack-like segment */
-#define MAP_DENYWRITE	0x0800		/* ETXTBSY */
-#define MAP_EXECUTABLE	0x1000		/* mark it as an executable */
-
-#define MCL_CURRENT     0x2000          /* lock all currently mapped pages */
-#define MCL_FUTURE      0x4000          /* lock all additions to address space */
-
-#define MAP_POPULATE	0x8000		/* populate (prefault) pagetables */
-#define MAP_NONBLOCK	0x10000		/* do not block on IO */
-
-#ifdef __KERNEL__
-#ifndef __ASSEMBLY__
-#define arch_mmap_check(addr,len,flags)	sparc64_mmap_check(addr,len)
-int sparc64_mmap_check(unsigned long addr, unsigned long len);
-#endif
-#endif
-
-#endif /* __SPARC64_MMAN_H__ */
+#include <asm-sparc/mman.h>
diff --git a/include/asm-sparc64/mmu.h b/include/asm-sparc64/mmu.h
index 8abc58f..e677a64 100644
--- a/include/asm-sparc64/mmu.h
+++ b/include/asm-sparc64/mmu.h
@@ -1,127 +1 @@
-#ifndef __MMU_H
-#define __MMU_H
-
-#include <linux/const.h>
-#include <asm/page.h>
-#include <asm/hypervisor.h>
-
-#define CTX_NR_BITS		13
-
-#define TAG_CONTEXT_BITS	((_AC(1,UL) << CTX_NR_BITS) - _AC(1,UL))
-
-/* UltraSPARC-III+ and later have a feature whereby you can
- * select what page size the various Data-TLB instances in the
- * chip.  In order to gracefully support this, we put the version
- * field in a spot outside of the areas of the context register
- * where this parameter is specified.
- */
-#define CTX_VERSION_SHIFT	22
-#define CTX_VERSION_MASK	((~0UL) << CTX_VERSION_SHIFT)
-
-#define CTX_PGSZ_8KB		_AC(0x0,UL)
-#define CTX_PGSZ_64KB		_AC(0x1,UL)
-#define CTX_PGSZ_512KB		_AC(0x2,UL)
-#define CTX_PGSZ_4MB		_AC(0x3,UL)
-#define CTX_PGSZ_BITS		_AC(0x7,UL)
-#define CTX_PGSZ0_NUC_SHIFT	61
-#define CTX_PGSZ1_NUC_SHIFT	58
-#define CTX_PGSZ0_SHIFT		16
-#define CTX_PGSZ1_SHIFT		19
-#define CTX_PGSZ_MASK		((CTX_PGSZ_BITS << CTX_PGSZ0_SHIFT) | \
-				 (CTX_PGSZ_BITS << CTX_PGSZ1_SHIFT))
-
-#if defined(CONFIG_SPARC64_PAGE_SIZE_8KB)
-#define CTX_PGSZ_BASE	CTX_PGSZ_8KB
-#elif defined(CONFIG_SPARC64_PAGE_SIZE_64KB)
-#define CTX_PGSZ_BASE	CTX_PGSZ_64KB
-#elif defined(CONFIG_SPARC64_PAGE_SIZE_512KB)
-#define CTX_PGSZ_BASE	CTX_PGSZ_512KB
-#elif defined(CONFIG_SPARC64_PAGE_SIZE_4MB)
-#define CTX_PGSZ_BASE	CTX_PGSZ_4MB
-#else
-#error No page size specified in kernel configuration
-#endif
-
-#if defined(CONFIG_HUGETLB_PAGE_SIZE_4MB)
-#define CTX_PGSZ_HUGE		CTX_PGSZ_4MB
-#elif defined(CONFIG_HUGETLB_PAGE_SIZE_512K)
-#define CTX_PGSZ_HUGE		CTX_PGSZ_512KB
-#elif defined(CONFIG_HUGETLB_PAGE_SIZE_64K)
-#define CTX_PGSZ_HUGE		CTX_PGSZ_64KB
-#endif
-
-#define CTX_PGSZ_KERN	CTX_PGSZ_4MB
-
-/* Thus, when running on UltraSPARC-III+ and later, we use the following
- * PRIMARY_CONTEXT register values for the kernel context.
- */
-#define CTX_CHEETAH_PLUS_NUC \
-	((CTX_PGSZ_KERN << CTX_PGSZ0_NUC_SHIFT) | \
-	 (CTX_PGSZ_BASE << CTX_PGSZ1_NUC_SHIFT))
-
-#define CTX_CHEETAH_PLUS_CTX0 \
-	((CTX_PGSZ_KERN << CTX_PGSZ0_SHIFT) | \
-	 (CTX_PGSZ_BASE << CTX_PGSZ1_SHIFT))
-
-/* If you want "the TLB context number" use CTX_NR_MASK.  If you
- * want "the bits I program into the context registers" use
- * CTX_HW_MASK.
- */
-#define CTX_NR_MASK		TAG_CONTEXT_BITS
-#define CTX_HW_MASK		(CTX_NR_MASK | CTX_PGSZ_MASK)
-
-#define CTX_FIRST_VERSION	((_AC(1,UL) << CTX_VERSION_SHIFT) + _AC(1,UL))
-#define CTX_VALID(__ctx)	\
-	 (!(((__ctx.sparc64_ctx_val) ^ tlb_context_cache) & CTX_VERSION_MASK))
-#define CTX_HWBITS(__ctx)	((__ctx.sparc64_ctx_val) & CTX_HW_MASK)
-#define CTX_NRBITS(__ctx)	((__ctx.sparc64_ctx_val) & CTX_NR_MASK)
-
-#ifndef __ASSEMBLY__
-
-#define TSB_ENTRY_ALIGNMENT	16
-
-struct tsb {
-	unsigned long tag;
-	unsigned long pte;
-} __attribute__((aligned(TSB_ENTRY_ALIGNMENT)));
-
-extern void __tsb_insert(unsigned long ent, unsigned long tag, unsigned long pte);
-extern void tsb_flush(unsigned long ent, unsigned long tag);
-extern void tsb_init(struct tsb *tsb, unsigned long size);
-
-struct tsb_config {
-	struct tsb		*tsb;
-	unsigned long		tsb_rss_limit;
-	unsigned long		tsb_nentries;
-	unsigned long		tsb_reg_val;
-	unsigned long		tsb_map_vaddr;
-	unsigned long		tsb_map_pte;
-};
-
-#define MM_TSB_BASE	0
-
-#ifdef CONFIG_HUGETLB_PAGE
-#define MM_TSB_HUGE	1
-#define MM_NUM_TSBS	2
-#else
-#define MM_NUM_TSBS	1
-#endif
-
-typedef struct {
-	spinlock_t		lock;
-	unsigned long		sparc64_ctx_val;
-	unsigned long		huge_pte_count;
-	struct tsb_config	tsb_block[MM_NUM_TSBS];
-	struct hv_tsb_descr	tsb_descr[MM_NUM_TSBS];
-} mm_context_t;
-
-#endif /* !__ASSEMBLY__ */
-
-#define TSB_CONFIG_TSB		0x00
-#define TSB_CONFIG_RSS_LIMIT	0x08
-#define TSB_CONFIG_NENTRIES	0x10
-#define TSB_CONFIG_REG_VAL	0x18
-#define TSB_CONFIG_MAP_VADDR	0x20
-#define TSB_CONFIG_MAP_PTE	0x28
-
-#endif /* __MMU_H */
+#include <asm-sparc/mmu.h>
diff --git a/include/asm-sparc64/mmu_context.h b/include/asm-sparc64/mmu_context.h
index 5693ab4..877fee9 100644
--- a/include/asm-sparc64/mmu_context.h
+++ b/include/asm-sparc64/mmu_context.h
@@ -1,155 +1 @@
-#ifndef __SPARC64_MMU_CONTEXT_H
-#define __SPARC64_MMU_CONTEXT_H
-
-/* Derived heavily from Linus's Alpha/AXP ASN code... */
-
-#ifndef __ASSEMBLY__
-
-#include <linux/spinlock.h>
-#include <asm/system.h>
-#include <asm/spitfire.h>
-#include <asm-generic/mm_hooks.h>
-
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
-{
-}
-
-extern spinlock_t ctx_alloc_lock;
-extern unsigned long tlb_context_cache;
-extern unsigned long mmu_context_bmap[];
-
-extern void get_new_mmu_context(struct mm_struct *mm);
-#ifdef CONFIG_SMP
-extern void smp_new_mmu_context_version(void);
-#else
-#define smp_new_mmu_context_version() do { } while (0)
-#endif
-
-extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
-extern void destroy_context(struct mm_struct *mm);
-
-extern void __tsb_context_switch(unsigned long pgd_pa,
-				 struct tsb_config *tsb_base,
-				 struct tsb_config *tsb_huge,
-				 unsigned long tsb_descr_pa);
-
-static inline void tsb_context_switch(struct mm_struct *mm)
-{
-	__tsb_context_switch(__pa(mm->pgd),
-			     &mm->context.tsb_block[0],
-#ifdef CONFIG_HUGETLB_PAGE
-			     (mm->context.tsb_block[1].tsb ?
-			      &mm->context.tsb_block[1] :
-			      NULL)
-#else
-			     NULL
-#endif
-			     , __pa(&mm->context.tsb_descr[0]));
-}
-
-extern void tsb_grow(struct mm_struct *mm, unsigned long tsb_index, unsigned long mm_rss);
-#ifdef CONFIG_SMP
-extern void smp_tsb_sync(struct mm_struct *mm);
-#else
-#define smp_tsb_sync(__mm) do { } while (0)
-#endif
-
-/* Set MMU context in the actual hardware. */
-#define load_secondary_context(__mm) \
-	__asm__ __volatile__( \
-	"\n661:	stxa		%0, [%1] %2\n" \
-	"	.section	.sun4v_1insn_patch, \"ax\"\n" \
-	"	.word		661b\n" \
-	"	stxa		%0, [%1] %3\n" \
-	"	.previous\n" \
-	"	flush		%%g6\n" \
-	: /* No outputs */ \
-	: "r" (CTX_HWBITS((__mm)->context)), \
-	  "r" (SECONDARY_CONTEXT), "i" (ASI_DMMU), "i" (ASI_MMU))
-
-extern void __flush_tlb_mm(unsigned long, unsigned long);
-
-/* Switch the current MM context.  Interrupts are disabled.  */
-static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, struct task_struct *tsk)
-{
-	unsigned long ctx_valid, flags;
-	int cpu;
-
-	if (unlikely(mm == &init_mm))
-		return;
-
-	spin_lock_irqsave(&mm->context.lock, flags);
-	ctx_valid = CTX_VALID(mm->context);
-	if (!ctx_valid)
-		get_new_mmu_context(mm);
-
-	/* We have to be extremely careful here or else we will miss
-	 * a TSB grow if we switch back and forth between a kernel
-	 * thread and an address space which has it's TSB size increased
-	 * on another processor.
-	 *
-	 * It is possible to play some games in order to optimize the
-	 * switch, but the safest thing to do is to unconditionally
-	 * perform the secondary context load and the TSB context switch.
-	 *
-	 * For reference the bad case is, for address space "A":
-	 *
-	 *		CPU 0			CPU 1
-	 *	run address space A
-	 *	set cpu0's bits in cpu_vm_mask
-	 *	switch to kernel thread, borrow
-	 *	address space A via entry_lazy_tlb
-	 *					run address space A
-	 *					set cpu1's bit in cpu_vm_mask
-	 *					flush_tlb_pending()
-	 *					reset cpu_vm_mask to just cpu1
-	 *					TSB grow
-	 *	run address space A
-	 *	context was valid, so skip
-	 *	TSB context switch
-	 *
-	 * At that point cpu0 continues to use a stale TSB, the one from
-	 * before the TSB grow performed on cpu1.  cpu1 did not cross-call
-	 * cpu0 to update it's TSB because at that point the cpu_vm_mask
-	 * only had cpu1 set in it.
-	 */
-	load_secondary_context(mm);
-	tsb_context_switch(mm);
-
-	/* Any time a processor runs a context on an address space
-	 * for the first time, we must flush that context out of the
-	 * local TLB.
-	 */
-	cpu = smp_processor_id();
-	if (!ctx_valid || !cpu_isset(cpu, mm->cpu_vm_mask)) {
-		cpu_set(cpu, mm->cpu_vm_mask);
-		__flush_tlb_mm(CTX_HWBITS(mm->context),
-			       SECONDARY_CONTEXT);
-	}
-	spin_unlock_irqrestore(&mm->context.lock, flags);
-}
-
-#define deactivate_mm(tsk,mm)	do { } while (0)
-
-/* Activate a new MM instance for the current task. */
-static inline void activate_mm(struct mm_struct *active_mm, struct mm_struct *mm)
-{
-	unsigned long flags;
-	int cpu;
-
-	spin_lock_irqsave(&mm->context.lock, flags);
-	if (!CTX_VALID(mm->context))
-		get_new_mmu_context(mm);
-	cpu = smp_processor_id();
-	if (!cpu_isset(cpu, mm->cpu_vm_mask))
-		cpu_set(cpu, mm->cpu_vm_mask);
-
-	load_secondary_context(mm);
-	__flush_tlb_mm(CTX_HWBITS(mm->context), SECONDARY_CONTEXT);
-	tsb_context_switch(mm);
-	spin_unlock_irqrestore(&mm->context.lock, flags);
-}
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(__SPARC64_MMU_CONTEXT_H) */
+#include <asm-sparc/mmu_context.h>
diff --git a/include/asm-sparc64/mmzone.h b/include/asm-sparc64/mmzone.h
index ebf5986..43a710f 100644
--- a/include/asm-sparc64/mmzone.h
+++ b/include/asm-sparc64/mmzone.h
@@ -1,17 +1 @@
-#ifndef _SPARC64_MMZONE_H
-#define _SPARC64_MMZONE_H
-
-#ifdef CONFIG_NEED_MULTIPLE_NODES
-
-extern struct pglist_data *node_data[];
-
-#define NODE_DATA(nid)		(node_data[nid])
-#define node_start_pfn(nid)	(NODE_DATA(nid)->node_start_pfn)
-#define node_end_pfn(nid)	(NODE_DATA(nid)->node_end_pfn)
-
-extern int numa_cpu_lookup_table[];
-extern cpumask_t numa_cpumask_lookup_table[];
-
-#endif /* CONFIG_NEED_MULTIPLE_NODES */
-
-#endif /* _SPARC64_MMZONE_H */
+#include <asm-sparc/mmzone.h>
diff --git a/include/asm-sparc64/module.h b/include/asm-sparc64/module.h
index 3d77ba4..a9606db 100644
--- a/include/asm-sparc64/module.h
+++ b/include/asm-sparc64/module.h
@@ -1,7 +1 @@
-#ifndef _ASM_SPARC64_MODULE_H
-#define _ASM_SPARC64_MODULE_H
-struct mod_arch_specific { };
-#define Elf_Shdr Elf64_Shdr
-#define Elf_Sym Elf64_Sym
-#define Elf_Ehdr Elf64_Ehdr
-#endif /* _ASM_SPARC64_MODULE_H */
+#include <asm-sparc/module.h>
diff --git a/include/asm-sparc64/mostek.h b/include/asm-sparc64/mostek.h
index c5652de..95a752f 100644
--- a/include/asm-sparc64/mostek.h
+++ b/include/asm-sparc64/mostek.h
@@ -1,143 +1 @@
-/* mostek.h:  Describes the various Mostek time of day clock registers.
- *
- * Copyright (C) 1995 David S. Miller (davem@davemloft.net)
- * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu)
- */
-
-#ifndef _SPARC64_MOSTEK_H
-#define _SPARC64_MOSTEK_H
-
-#include <asm/idprom.h>
-
-/*       M48T02 Register Map (adapted from Sun NVRAM/Hostid FAQ)
- *
- *                             Data
- * Address                                                 Function
- *        Bit 7 Bit 6 Bit 5 Bit 4Bit 3 Bit 2 Bit 1 Bit 0
- *   7ff  -     -     -     -    -     -     -     -       Year 00-99
- *   7fe  0     0     0     -    -     -     -     -      Month 01-12
- *   7fd  0     0     -     -    -     -     -     -       Date 01-31
- *   7fc  0     FT    0     0    0     -     -     -        Day 01-07
- *   7fb  KS    0     -     -    -     -     -     -      Hours 00-23
- *   7fa  0     -     -     -    -     -     -     -    Minutes 00-59
- *   7f9  ST    -     -     -    -     -     -     -    Seconds 00-59
- *   7f8  W     R     S     -    -     -     -     -    Control
- *
- *   * ST is STOP BIT
- *   * W is WRITE BIT
- *   * R is READ BIT
- *   * S is SIGN BIT
- *   * FT is FREQ TEST BIT
- *   * KS is KICK START BIT
- */
-
-/* The Mostek 48t02 real time clock and NVRAM chip. The registers
- * other than the control register are in binary coded decimal. Some
- * control bits also live outside the control register.
- *
- * We now deal with physical addresses for I/O to the chip. -DaveM
- */
-static inline u8 mostek_read(void __iomem *addr)
-{
-	u8 ret;
-
-	__asm__ __volatile__("lduba	[%1] %2, %0"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-	return ret;
-}
-
-static inline void mostek_write(void __iomem *addr, u8 val)
-{
-	__asm__ __volatile__("stba	%0, [%1] %2"
-			     : /* no outputs */
-			     : "r" (val), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-}
-
-#define MOSTEK_EEPROM		0x0000UL
-#define MOSTEK_IDPROM		0x07d8UL
-#define MOSTEK_CREG		0x07f8UL
-#define MOSTEK_SEC		0x07f9UL
-#define MOSTEK_MIN		0x07faUL
-#define MOSTEK_HOUR		0x07fbUL
-#define MOSTEK_DOW		0x07fcUL
-#define MOSTEK_DOM		0x07fdUL
-#define MOSTEK_MONTH		0x07feUL
-#define MOSTEK_YEAR		0x07ffUL
-
-extern spinlock_t mostek_lock;
-extern void __iomem *mstk48t02_regs;
-
-/* Control register values. */
-#define	MSTK_CREG_WRITE	0x80	/* Must set this before placing values. */
-#define	MSTK_CREG_READ	0x40	/* Stop updates to allow a clean read. */
-#define	MSTK_CREG_SIGN	0x20	/* Slow/speed clock in calibration mode. */
-
-/* Control bits that live in the other registers. */
-#define	MSTK_STOP	0x80	/* Stop the clock oscillator. (sec) */
-#define	MSTK_KICK_START	0x80	/* Kick start the clock chip. (hour) */
-#define MSTK_FREQ_TEST	0x40	/* Frequency test mode. (day) */
-
-#define MSTK_YEAR_ZERO       1968   /* If year reg has zero, it is 1968. */
-#define MSTK_CVT_YEAR(yr)  ((yr) + MSTK_YEAR_ZERO)
-
-/* Masks that define how much space each value takes up. */
-#define	MSTK_SEC_MASK	0x7f
-#define	MSTK_MIN_MASK	0x7f
-#define	MSTK_HOUR_MASK	0x3f
-#define	MSTK_DOW_MASK	0x07
-#define	MSTK_DOM_MASK	0x3f
-#define	MSTK_MONTH_MASK	0x1f
-#define	MSTK_YEAR_MASK	0xffU
-
-/* Binary coded decimal conversion macros. */
-#define MSTK_REGVAL_TO_DECIMAL(x)  (((x) & 0x0F) + 0x0A * ((x) >> 0x04))
-#define MSTK_DECIMAL_TO_REGVAL(x)  ((((x) / 0x0A) << 0x04) + ((x) % 0x0A))
-
-/* Generic register set and get macros for internal use. */
-#define MSTK_GET(regs,name)	\
-	(MSTK_REGVAL_TO_DECIMAL(mostek_read(regs + MOSTEK_ ## name) & MSTK_ ## name ## _MASK))
-#define MSTK_SET(regs,name,value) \
-do {	u8 __val = mostek_read(regs + MOSTEK_ ## name); \
-	__val &= ~(MSTK_ ## name ## _MASK); \
-	__val |= (MSTK_DECIMAL_TO_REGVAL(value) & \
-		  (MSTK_ ## name ## _MASK)); \
-	mostek_write(regs + MOSTEK_ ## name, __val); \
-} while(0)
-
-/* Macros to make register access easier on our fingers. These give you
- * the decimal value of the register requested if applicable. You pass
- * the a pointer to a 'struct mostek48t02'.
- */
-#define	MSTK_REG_CREG(regs)	(mostek_read((regs) + MOSTEK_CREG))
-#define	MSTK_REG_SEC(regs)	MSTK_GET(regs,SEC)
-#define	MSTK_REG_MIN(regs)	MSTK_GET(regs,MIN)
-#define	MSTK_REG_HOUR(regs)	MSTK_GET(regs,HOUR)
-#define	MSTK_REG_DOW(regs)	MSTK_GET(regs,DOW)
-#define	MSTK_REG_DOM(regs)	MSTK_GET(regs,DOM)
-#define	MSTK_REG_MONTH(regs)	MSTK_GET(regs,MONTH)
-#define	MSTK_REG_YEAR(regs)	MSTK_GET(regs,YEAR)
-
-#define	MSTK_SET_REG_SEC(regs,value)	MSTK_SET(regs,SEC,value)
-#define	MSTK_SET_REG_MIN(regs,value)	MSTK_SET(regs,MIN,value)
-#define	MSTK_SET_REG_HOUR(regs,value)	MSTK_SET(regs,HOUR,value)
-#define	MSTK_SET_REG_DOW(regs,value)	MSTK_SET(regs,DOW,value)
-#define	MSTK_SET_REG_DOM(regs,value)	MSTK_SET(regs,DOM,value)
-#define	MSTK_SET_REG_MONTH(regs,value)	MSTK_SET(regs,MONTH,value)
-#define	MSTK_SET_REG_YEAR(regs,value)	MSTK_SET(regs,YEAR,value)
-
-
-/* The Mostek 48t08 clock chip. Found on Sun4m's I think. It has the
- * same (basically) layout of the 48t02 chip except for the extra
- * NVRAM on board (8 KB against the 48t02's 2 KB).
- */
-#define MOSTEK_48T08_OFFSET	0x0000UL	/* Lower NVRAM portions */
-#define MOSTEK_48T08_48T02	0x1800UL	/* Offset to 48T02 chip */
-
-/* SUN5 systems usually have 48t59 model clock chipsets.  But we keep the older
- * clock chip definitions around just in case.
- */
-#define MOSTEK_48T59_OFFSET	0x0000UL	/* Lower NVRAM portions */
-#define MOSTEK_48T59_48T02	0x1800UL	/* Offset to 48T02 chip */
-
-#endif /* !(_SPARC64_MOSTEK_H) */
+#include <asm-sparc/mostek.h>
diff --git a/include/asm-sparc64/msgbuf.h b/include/asm-sparc64/msgbuf.h
index 55c101b..5b33cc9 100644
--- a/include/asm-sparc64/msgbuf.h
+++ b/include/asm-sparc64/msgbuf.h
@@ -1,27 +1 @@
-#ifndef _SPARC64_MSGBUF_H
-#define _SPARC64_MSGBUF_H
-
-/* 
- * The msqid64_ds structure for sparc64 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 2 miscellaneous 64-bit values
- */
-
-struct msqid64_ds {
-	struct ipc64_perm msg_perm;
-	__kernel_time_t msg_stime;	/* last msgsnd time */
-	__kernel_time_t msg_rtime;	/* last msgrcv time */
-	__kernel_time_t msg_ctime;	/* last change time */
-	unsigned long  msg_cbytes;	/* current number of bytes on queue */
-	unsigned long  msg_qnum;	/* number of messages in queue */
-	unsigned long  msg_qbytes;	/* max number of bytes on queue */
-	__kernel_pid_t msg_lspid;	/* pid of last msgsnd */
-	__kernel_pid_t msg_lrpid;	/* last receive pid */
-	unsigned long  __unused1;
-	unsigned long  __unused2;
-};
-
-#endif /* _SPARC64_MSGBUF_H */
+#include <asm-sparc/msgbuf.h>
diff --git a/include/asm-sparc64/mutex.h b/include/asm-sparc64/mutex.h
index 458c1f7..c0c0f8f 100644
--- a/include/asm-sparc64/mutex.h
+++ b/include/asm-sparc64/mutex.h
@@ -1,9 +1 @@
-/*
- * Pull in the generic implementation for the mutex fastpath.
- *
- * TODO: implement optimized primitives instead, or leave the generic
- * implementation in place, or pick the atomic_xchg() based generic
- * implementation. (see asm-generic/mutex-xchg.h for details)
- */
-
-#include <asm-generic/mutex-dec.h>
+#include <asm-sparc/mutex.h>
diff --git a/include/asm-sparc64/namei.h b/include/asm-sparc64/namei.h
index cbc1b4c..1344a91 100644
--- a/include/asm-sparc64/namei.h
+++ b/include/asm-sparc64/namei.h
@@ -1,13 +1 @@
-/*
- * linux/include/asm-sparc64/namei.h
- *
- * Routines to handle famous /usr/gnemul/s*.
- * Included from linux/fs/namei.c
- */
-
-#ifndef __SPARC64_NAMEI_H
-#define __SPARC64_NAMEI_H
-
-#define __emul_prefix() NULL
-
-#endif /* __SPARC64_NAMEI_H */
+#include <asm-sparc/namei.h>
diff --git a/include/asm-sparc64/ns87303.h b/include/asm-sparc64/ns87303.h
index 686defe..5f369d4 100644
--- a/include/asm-sparc64/ns87303.h
+++ b/include/asm-sparc64/ns87303.h
@@ -1,118 +1 @@
-/* ns87303.h: Configuration Register Description for the
- *            National Semiconductor PC87303 (SuperIO).
- *
- * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
- */
-
-#ifndef _SPARC_NS87303_H
-#define _SPARC_NS87303_H 1
-
-/*
- * Control Register Index Values
- */
-#define FER	0x00
-#define FAR	0x01
-#define PTR	0x02
-#define FCR	0x03
-#define PCR	0x04
-#define KRR	0x05
-#define PMC	0x06
-#define TUP	0x07
-#define SID	0x08
-#define ASC	0x09
-#define CS0CF0	0x0a
-#define CS0CF1	0x0b
-#define CS1CF0	0x0c
-#define CS1CF1	0x0d
-
-/* Function Enable Register (FER) bits */
-#define FER_EDM		0x10	/* Encoded Drive and Motor pin information   */
-
-/* Function Address Register (FAR) bits */
-#define FAR_LPT_MASK	0x03
-#define FAR_LPTB	0x00
-#define FAR_LPTA	0x01
-#define FAR_LPTC	0x02
-
-/* Power and Test Register (PTR) bits */
-#define PTR_LPTB_IRQ7	0x08
-#define PTR_LEVEL_IRQ	0x80	/* When not ECP/EPP: Use level IRQ           */
-#define PTR_LPT_REG_DIR	0x80	/* When ECP/EPP: LPT CTR controlls direction */
-				/*               of the parallel port	     */
-
-/* Function Control Register (FCR) bits */
-#define FCR_LDE		0x10	/* Logical Drive Exchange                    */
-#define FCR_ZWS_ENA	0x20	/* Enable short host read/write in ECP/EPP   */
-
-/* Printer Control Register (PCR) bits */
-#define PCR_EPP_ENABLE	0x01
-#define PCR_EPP_IEEE	0x02	/* Enable EPP Version 1.9 (IEEE 1284)        */
-#define PCR_ECP_ENABLE	0x04
-#define PCR_ECP_CLK_ENA	0x08	/* If 0 ECP Clock is stopped on Power down   */
-#define PCR_IRQ_POLAR	0x20	/* If 0 IRQ is level high or negative pulse, */
-				/* if 1 polarity is inverted                 */
-#define PCR_IRQ_ODRAIN	0x40	/* If 1, IRQ is open drain                   */
-
-/* Tape UARTs and Parallel Port Config Register (TUP) bits */
-#define TUP_EPP_TIMO	0x02	/* Enable EPP timeout IRQ                    */
-
-/* Advanced SuperIO Config Register (ASC) bits */
-#define ASC_LPT_IRQ7	0x01	/* Always use IRQ7 for LPT                  */
-#define ASC_DRV2_SEL	0x02	/* Logical Drive Exchange controlled by TDR  */
-
-#define FER_RESERVED	0x00
-#define FAR_RESERVED	0x00
-#define PTR_RESERVED	0x73
-#define FCR_RESERVED	0xc4
-#define PCR_RESERVED	0x10
-#define KRR_RESERVED	0x00
-#define PMC_RESERVED	0x98
-#define TUP_RESERVED	0xfb
-#define SIP_RESERVED	0x00
-#define ASC_RESERVED	0x18
-#define CS0CF0_RESERVED	0x00
-#define CS0CF1_RESERVED	0x08
-#define CS1CF0_RESERVED	0x00
-#define CS1CF1_RESERVED	0x08
-
-#ifdef __KERNEL__
-
-#include <linux/spinlock.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-
-extern spinlock_t ns87303_lock;
-
-static inline int ns87303_modify(unsigned long port, unsigned int index,
-				     unsigned char clr, unsigned char set)
-{
-	static unsigned char reserved[] = {
-		FER_RESERVED, FAR_RESERVED, PTR_RESERVED, FCR_RESERVED,
-		PCR_RESERVED, KRR_RESERVED, PMC_RESERVED, TUP_RESERVED,
-		SIP_RESERVED, ASC_RESERVED, CS0CF0_RESERVED, CS0CF1_RESERVED,
-		CS1CF0_RESERVED, CS1CF1_RESERVED
-	};
-	unsigned long flags;
-	unsigned char value;
-
-	if (index > 0x0d)
-		return -EINVAL;
-
-	spin_lock_irqsave(&ns87303_lock, flags);
-
-	outb(index, port);
-	value = inb(port + 1);
-	value &= ~(reserved[index] | clr);
-	value |= set;
-	outb(value, port + 1);
-	outb(value, port + 1);
-
-	spin_unlock_irqrestore(&ns87303_lock, flags);
-
-	return 0;
-}
-
-#endif /* __KERNEL__ */
-
-#endif /* !(_SPARC_NS87303_H) */
+#include <asm-sparc/ns87303.h>
diff --git a/include/asm-sparc64/of_platform.h b/include/asm-sparc64/of_platform.h
index 78aa032..f7c427b 100644
--- a/include/asm-sparc64/of_platform.h
+++ b/include/asm-sparc64/of_platform.h
@@ -1,25 +1 @@
-#ifndef _ASM_SPARC64_OF_PLATFORM_H
-#define _ASM_SPARC64_OF_PLATFORM_H
-/*
- *    Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
- *			 <benh@kernel.crashing.org>
- *    Modified for Sparc by merging parts of asm-sparc/of_device.h
- *		by Stephen Rothwell
- *
- *  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 is just here during the transition */
-#include <linux/of_platform.h>
-
-extern struct bus_type isa_bus_type;
-extern struct bus_type ebus_bus_type;
-extern struct bus_type sbus_bus_type;
-
-#define of_bus_type	of_platform_bus_type	/* for compatibility */
-
-#endif	/* _ASM_SPARC64_OF_PLATFORM_H */
+#include <asm-sparc/of_platform.h>
diff --git a/include/asm-sparc64/openprom.h b/include/asm-sparc64/openprom.h
index b69e4a8..acf4b23 100644
--- a/include/asm-sparc64/openprom.h
+++ b/include/asm-sparc64/openprom.h
@@ -1,280 +1 @@
-#ifndef __SPARC64_OPENPROM_H
-#define __SPARC64_OPENPROM_H
-
-/* openprom.h:  Prom structures and defines for access to the OPENBOOT
- *              prom routines and data areas.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef __ASSEMBLY__
-/* V0 prom device operations. */
-struct linux_dev_v0_funcs {
-	int (*v0_devopen)(char *device_str);
-	int (*v0_devclose)(int dev_desc);
-	int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
-	int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
-	int (*v0_wrnetdev)(int dev_desc, int num_bytes, char *buf);
-	int (*v0_rdnetdev)(int dev_desc, int num_bytes, char *buf);
-	int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
-	int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
-	int (*v0_seekdev)(int dev_desc, long logical_offst, int from);
-};
-
-/* V2 and later prom device operations. */
-struct linux_dev_v2_funcs {
-	int (*v2_inst2pkg)(int d);	/* Convert ihandle to phandle */
-	char * (*v2_dumb_mem_alloc)(char *va, unsigned sz);
-	void (*v2_dumb_mem_free)(char *va, unsigned sz);
-
-	/* To map devices into virtual I/O space. */
-	char * (*v2_dumb_mmap)(char *virta, int which_io, unsigned paddr, unsigned sz);
-	void (*v2_dumb_munmap)(char *virta, unsigned size);
-
-	int (*v2_dev_open)(char *devpath);
-	void (*v2_dev_close)(int d);
-	int (*v2_dev_read)(int d, char *buf, int nbytes);
-	int (*v2_dev_write)(int d, char *buf, int nbytes);
-	int (*v2_dev_seek)(int d, int hi, int lo);
-
-	/* Never issued (multistage load support) */
-	void (*v2_wheee2)(void);
-	void (*v2_wheee3)(void);
-};
-
-struct linux_mlist_v0 {
-	struct linux_mlist_v0 *theres_more;
-	unsigned start_adr;
-	unsigned num_bytes;
-};
-
-struct linux_mem_v0 {
-	struct linux_mlist_v0 **v0_totphys;
-	struct linux_mlist_v0 **v0_prommap;
-	struct linux_mlist_v0 **v0_available; /* What we can use */
-};
-
-/* Arguments sent to the kernel from the boot prompt. */
-struct linux_arguments_v0 {
-	char *argv[8];
-	char args[100];
-	char boot_dev[2];
-	int boot_dev_ctrl;
-	int boot_dev_unit;
-	int dev_partition;
-	char *kernel_file_name;
-	void *aieee1;           /* XXX */
-};
-
-/* V2 and up boot things. */
-struct linux_bootargs_v2 {
-	char **bootpath;
-	char **bootargs;
-	int *fd_stdin;
-	int *fd_stdout;
-};
-
-/* The top level PROM vector. */
-struct linux_romvec {
-	/* Version numbers. */
-	unsigned int pv_magic_cookie;
-	unsigned int pv_romvers;
-	unsigned int pv_plugin_revision;
-	unsigned int pv_printrev;
-
-	/* Version 0 memory descriptors. */
-	struct linux_mem_v0 pv_v0mem;
-
-	/* Node operations. */
-	struct linux_nodeops *pv_nodeops;
-
-	char **pv_bootstr;
-	struct linux_dev_v0_funcs pv_v0devops;
-
-	char *pv_stdin;
-	char *pv_stdout;
-#define	PROMDEV_KBD	0		/* input from keyboard */
-#define	PROMDEV_SCREEN	0		/* output to screen */
-#define	PROMDEV_TTYA	1		/* in/out to ttya */
-#define	PROMDEV_TTYB	2		/* in/out to ttyb */
-
-	/* Blocking getchar/putchar.  NOT REENTRANT! (grr) */
-	int (*pv_getchar)(void);
-	void (*pv_putchar)(int ch);
-
-	/* Non-blocking variants. */
-	int (*pv_nbgetchar)(void);
-	int (*pv_nbputchar)(int ch);
-
-	void (*pv_putstr)(char *str, int len);
-
-	/* Miscellany. */
-	void (*pv_reboot)(char *bootstr);
-	void (*pv_printf)(__const__ char *fmt, ...);
-	void (*pv_abort)(void);
-	__volatile__ int *pv_ticks;
-	void (*pv_halt)(void);
-	void (**pv_synchook)(void);
-
-	/* Evaluate a forth string, not different proto for V0 and V2->up. */
-	union {
-		void (*v0_eval)(int len, char *str);
-		void (*v2_eval)(char *str);
-	} pv_fortheval;
-
-	struct linux_arguments_v0 **pv_v0bootargs;
-
-	/* Get ether address. */
-	unsigned int (*pv_enaddr)(int d, char *enaddr);
-
-	struct linux_bootargs_v2 pv_v2bootargs;
-	struct linux_dev_v2_funcs pv_v2devops;
-
-	int filler[15];
-
-	/* This one is sun4c/sun4 only. */
-	void (*pv_setctxt)(int ctxt, char *va, int pmeg);
-
-	/* Prom version 3 Multiprocessor routines. This stuff is crazy.
-	 * No joke. Calling these when there is only one cpu probably
-	 * crashes the machine, have to test this. :-)
-	 */
-
-	/* v3_cpustart() will start the cpu 'whichcpu' in mmu-context
-	 * 'thiscontext' executing at address 'prog_counter'
-	 */
-	int (*v3_cpustart)(unsigned int whichcpu, int ctxtbl_ptr,
-			   int thiscontext, char *prog_counter);
-
-	/* v3_cpustop() will cause cpu 'whichcpu' to stop executing
-	 * until a resume cpu call is made.
-	 */
-	int (*v3_cpustop)(unsigned int whichcpu);
-
-	/* v3_cpuidle() will idle cpu 'whichcpu' until a stop or
-	 * resume cpu call is made.
-	 */
-	int (*v3_cpuidle)(unsigned int whichcpu);
-
-	/* v3_cpuresume() will resume processor 'whichcpu' executing
-	 * starting with whatever 'pc' and 'npc' were left at the
-	 * last 'idle' or 'stop' call.
-	 */
-	int (*v3_cpuresume)(unsigned int whichcpu);
-};
-
-/* Routines for traversing the prom device tree. */
-struct linux_nodeops {
-	int (*no_nextnode)(int node);
-	int (*no_child)(int node);
-	int (*no_proplen)(int node, char *name);
-	int (*no_getprop)(int node, char *name, char *val);
-	int (*no_setprop)(int node, char *name, char *val, int len);
-	char * (*no_nextprop)(int node, char *name);
-};
-
-/* More fun PROM structures for device probing. */
-#define PROMREG_MAX     24
-#define PROMVADDR_MAX   16
-#define PROMINTR_MAX    32
-
-struct linux_prom_registers {
-	unsigned which_io;	/* hi part of physical address			*/
-	unsigned phys_addr;	/* The physical address of this register	*/
-	int reg_size;		/* How many bytes does this register take up?	*/
-};
-
-struct linux_prom64_registers {
-	unsigned long phys_addr;
-	unsigned long reg_size;
-};
-
-struct linux_prom_irqs {
-	int pri;    /* IRQ priority */
-	int vector; /* This is foobar, what does it do? */
-};
-
-/* Element of the "ranges" vector */
-struct linux_prom_ranges {
-	unsigned int ot_child_space;
-	unsigned int ot_child_base;		/* Bus feels this */
-	unsigned int ot_parent_space;
-	unsigned int ot_parent_base;		/* CPU looks from here */
-	unsigned int or_size;
-};
-
-struct linux_prom64_ranges {
-	unsigned long ot_child_base;		/* Bus feels this */
-	unsigned long ot_parent_base;		/* CPU looks from here */
-	unsigned long or_size;
-};
-
-/* Ranges and reg properties are a bit different for PCI. */
-struct linux_prom_pci_registers {
-	unsigned int phys_hi;
-	unsigned int phys_mid;
-	unsigned int phys_lo;
-
-	unsigned int size_hi;
-	unsigned int size_lo;
-};
-
-struct linux_prom_pci_ranges {
-	unsigned int child_phys_hi;	/* Only certain bits are encoded here. */
-	unsigned int child_phys_mid;
-	unsigned int child_phys_lo;
-
-	unsigned int parent_phys_hi;
-	unsigned int parent_phys_lo;
-
-	unsigned int size_hi;
-	unsigned int size_lo;
-};
-
-struct linux_prom_pci_intmap {
-	unsigned int phys_hi;
-	unsigned int phys_mid;
-	unsigned int phys_lo;
-
-	unsigned int interrupt;
-
-	int          cnode;
-	unsigned int cinterrupt;
-};
-
-struct linux_prom_pci_intmask {
-	unsigned int phys_hi;
-	unsigned int phys_mid;
-	unsigned int phys_lo;
-	unsigned int interrupt;
-};
-
-struct linux_prom_ebus_ranges {
-	unsigned int child_phys_hi;
-	unsigned int child_phys_lo;
-
-	unsigned int parent_phys_hi;
-	unsigned int parent_phys_mid;
-	unsigned int parent_phys_lo;
-
-	unsigned int size;
-};
-
-struct linux_prom_ebus_intmap {
-	unsigned int phys_hi;
-	unsigned int phys_lo;
-
-	unsigned int interrupt;
-
-	int          cnode;
-	unsigned int cinterrupt;
-};
-
-struct linux_prom_ebus_intmask {
-	unsigned int phys_hi;
-	unsigned int phys_lo;
-	unsigned int interrupt;
-};
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(__SPARC64_OPENPROM_H) */
+#include <asm-sparc/openprom.h>
diff --git a/include/asm-sparc64/openpromio.h b/include/asm-sparc64/openpromio.h
index 847ce23..122fabd 100644
--- a/include/asm-sparc64/openpromio.h
+++ b/include/asm-sparc64/openpromio.h
@@ -1,69 +1 @@
-#ifndef	_SPARC64_OPENPROMIO_H
-#define	_SPARC64_OPENPROMIO_H
-
-#include <linux/compiler.h>
-#include <linux/ioctl.h>
-#include <linux/types.h>
-
-/*
- * SunOS and Solaris /dev/openprom definitions. The ioctl values
- * were chosen to be exactly equal to the SunOS equivalents.
- */
-
-struct openpromio
-{
-	u_int	oprom_size;		/* Actual size of the oprom_array. */
-	char	oprom_array[1];		/* Holds property names and values. */
-};
-
-#define	OPROMMAXPARAM	4096		/* Maximum size of oprom_array. */
-
-#define	OPROMGETOPT		0x20004F01
-#define	OPROMSETOPT		0x20004F02
-#define	OPROMNXTOPT		0x20004F03
-#define	OPROMSETOPT2		0x20004F04
-#define	OPROMNEXT		0x20004F05
-#define	OPROMCHILD		0x20004F06
-#define	OPROMGETPROP		0x20004F07
-#define	OPROMNXTPROP		0x20004F08
-#define	OPROMU2P		0x20004F09
-#define	OPROMGETCONS		0x20004F0A
-#define	OPROMGETFBNAME		0x20004F0B
-#define	OPROMGETBOOTARGS	0x20004F0C
-/* Linux extensions */				/* Arguments in oprom_array: */
-#define OPROMSETCUR		0x20004FF0	/* int node - Sets current node */
-#define OPROMPCI2NODE		0x20004FF1	/* int pci_bus, pci_devfn - Sets current node to PCI device's node */
-#define OPROMPATH2NODE		0x20004FF2	/* char path[] - Set current node from fully qualified PROM path */
-
-/*
- * Return values from OPROMGETCONS:
- */
-
-#define OPROMCONS_NOT_WSCONS    0
-#define OPROMCONS_STDIN_IS_KBD  0x1     /* stdin device is kbd */
-#define OPROMCONS_STDOUT_IS_FB  0x2     /* stdout is a framebuffer */
-#define OPROMCONS_OPENPROM      0x4     /* supports openboot */
-
-
-/*
- *  NetBSD/OpenBSD /dev/openprom definitions.
- */
-
-struct opiocdesc
-{
-	int	op_nodeid;		/* PROM Node ID (value-result) */
-	int	op_namelen;		/* Length of op_name. */
-	char	__user *op_name;	/* Pointer to the property name. */
-	int	op_buflen;		/* Length of op_buf (value-result) */
-	char	__user *op_buf;		/* Pointer to buffer. */
-};
-
-#define	OPIOCGET	_IOWR('O', 1, struct opiocdesc)
-#define	OPIOCSET	_IOW('O', 2, struct opiocdesc)
-#define	OPIOCNEXTPROP	_IOWR('O', 3, struct opiocdesc)
-#define	OPIOCGETOPTNODE	_IOR('O', 4, int)
-#define	OPIOCGETNEXT	_IOWR('O', 5, int)
-#define	OPIOCGETCHILD	_IOWR('O', 6, int)
-
-#endif /* _SPARC64_OPENPROMIO_H */
-
+#include <asm-sparc/openpromio.h>
diff --git a/include/asm-sparc64/oplib.h b/include/asm-sparc64/oplib.h
index 55c5bb2..d93e44e 100644
--- a/include/asm-sparc64/oplib.h
+++ b/include/asm-sparc64/oplib.h
@@ -1,322 +1 @@
-/* oplib.h:  Describes the interface and available routines in the
- *           Linux Prom library.
- *
- * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
- * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- */
-
-#ifndef __SPARC64_OPLIB_H
-#define __SPARC64_OPLIB_H
-
-#include <asm/openprom.h>
-
-/* OBP version string. */
-extern char prom_version[];
-
-/* Root node of the prom device tree, this stays constant after
- * initialization is complete.
- */
-extern int prom_root_node;
-
-/* PROM stdin and stdout */
-extern int prom_stdin, prom_stdout;
-
-/* /chosen node of the prom device tree, this stays constant after
- * initialization is complete.
- */
-extern int prom_chosen_node;
-
-/* Helper values and strings in arch/sparc64/kernel/head.S */
-extern const char prom_peer_name[];
-extern const char prom_compatible_name[];
-extern const char prom_root_compatible[];
-extern const char prom_cpu_compatible[];
-extern const char prom_finddev_name[];
-extern const char prom_chosen_path[];
-extern const char prom_cpu_path[];
-extern const char prom_getprop_name[];
-extern const char prom_mmu_name[];
-extern const char prom_callmethod_name[];
-extern const char prom_translate_name[];
-extern const char prom_map_name[];
-extern const char prom_unmap_name[];
-extern int prom_mmu_ihandle_cache;
-extern unsigned int prom_boot_mapped_pc;
-extern unsigned int prom_boot_mapping_mode;
-extern unsigned long prom_boot_mapping_phys_high, prom_boot_mapping_phys_low;
-
-struct linux_mlist_p1275 {
-	struct linux_mlist_p1275 *theres_more;
-	unsigned long start_adr;
-	unsigned long num_bytes;
-};
-
-struct linux_mem_p1275 {
-	struct linux_mlist_p1275 **p1275_totphys;
-	struct linux_mlist_p1275 **p1275_prommap;
-	struct linux_mlist_p1275 **p1275_available; /* What we can use */
-};
-
-/* The functions... */
-
-/* You must call prom_init() before using any of the library services,
- * preferably as early as possible.  Pass it the romvec pointer.
- */
-extern void prom_init(void *cif_handler, void *cif_stack);
-
-/* Boot argument acquisition, returns the boot command line string. */
-extern char *prom_getbootargs(void);
-
-/* Device utilities. */
-
-/* Device operations. */
-
-/* Open the device described by the passed string.  Note, that the format
- * of the string is different on V0 vs. V2->higher proms.  The caller must
- * know what he/she is doing!  Returns the device descriptor, an int.
- */
-extern int prom_devopen(const char *device_string);
-
-/* Close a previously opened device described by the passed integer
- * descriptor.
- */
-extern int prom_devclose(int device_handle);
-
-/* Do a seek operation on the device described by the passed integer
- * descriptor.
- */
-extern void prom_seek(int device_handle, unsigned int seek_hival,
-		      unsigned int seek_lowval);
-
-/* Miscellaneous routines, don't really fit in any category per se. */
-
-/* Reboot the machine with the command line passed. */
-extern void prom_reboot(const char *boot_command);
-
-/* Evaluate the forth string passed. */
-extern void prom_feval(const char *forth_string);
-
-/* Enter the prom, with possibility of continuation with the 'go'
- * command in newer proms.
- */
-extern void prom_cmdline(void);
-
-/* Enter the prom, with no chance of continuation for the stand-alone
- * which calls this.
- */
-extern void prom_halt(void) __attribute__ ((noreturn));
-
-/* Halt and power-off the machine. */
-extern void prom_halt_power_off(void) __attribute__ ((noreturn));
-
-/* Set the PROM 'sync' callback function to the passed function pointer.
- * When the user gives the 'sync' command at the prom prompt while the
- * kernel is still active, the prom will call this routine.
- *
- */
-typedef int (*callback_func_t)(long *cmd);
-extern void prom_setcallback(callback_func_t func_ptr);
-
-/* Acquire the IDPROM of the root node in the prom device tree.  This
- * gets passed a buffer where you would like it stuffed.  The return value
- * is the format type of this idprom or 0xff on error.
- */
-extern unsigned char prom_get_idprom(char *idp_buffer, int idpbuf_size);
-
-/* Character operations to/from the console.... */
-
-/* Non-blocking get character from console. */
-extern int prom_nbgetchar(void);
-
-/* Non-blocking put character to console. */
-extern int prom_nbputchar(char character);
-
-/* Blocking get character from console. */
-extern char prom_getchar(void);
-
-/* Blocking put character to console. */
-extern void prom_putchar(char character);
-
-/* Prom's internal routines, don't use in kernel/boot code. */
-extern void prom_printf(const char *fmt, ...);
-extern void prom_write(const char *buf, unsigned int len);
-
-/* Multiprocessor operations... */
-#ifdef CONFIG_SMP
-/* Start the CPU with the given device tree node at the passed program
- * counter with the given arg passed in via register %o0.
- */
-extern void prom_startcpu(int cpunode, unsigned long pc, unsigned long arg);
-
-/* Start the CPU with the given cpu ID at the passed program
- * counter with the given arg passed in via register %o0.
- */
-extern void prom_startcpu_cpuid(int cpuid, unsigned long pc, unsigned long arg);
-
-/* Stop the CPU with the given cpu ID.  */
-extern void prom_stopcpu_cpuid(int cpuid);
-
-/* Stop the current CPU. */
-extern void prom_stopself(void);
-
-/* Idle the current CPU. */
-extern void prom_idleself(void);
-
-/* Resume the CPU with the passed device tree node. */
-extern void prom_resumecpu(int cpunode);
-#endif
-
-/* Power management interfaces. */
-
-/* Put the current CPU to sleep. */
-extern void prom_sleepself(void);
-
-/* Put the entire system to sleep. */
-extern int prom_sleepsystem(void);
-
-/* Initiate a wakeup event. */
-extern int prom_wakeupsystem(void);
-
-/* MMU and memory related OBP interfaces. */
-
-/* Get unique string identifying SIMM at given physical address. */
-extern int prom_getunumber(int syndrome_code,
-			   unsigned long phys_addr,
-			   char *buf, int buflen);
-
-/* Retain physical memory to the caller across soft resets. */
-extern unsigned long prom_retain(const char *name,
-				 unsigned long pa_low, unsigned long pa_high,
-				 long size, long align);
-
-/* Load explicit I/D TLB entries into the calling processor. */
-extern long prom_itlb_load(unsigned long index,
-			   unsigned long tte_data,
-			   unsigned long vaddr);
-
-extern long prom_dtlb_load(unsigned long index,
-			   unsigned long tte_data,
-			   unsigned long vaddr);
-
-/* Map/Unmap client program address ranges.  First the format of
- * the mapping mode argument.
- */
-#define PROM_MAP_WRITE	0x0001 /* Writable */
-#define PROM_MAP_READ	0x0002 /* Readable - sw */
-#define PROM_MAP_EXEC	0x0004 /* Executable - sw */
-#define PROM_MAP_LOCKED	0x0010 /* Locked, use i/dtlb load calls for this instead */
-#define PROM_MAP_CACHED	0x0020 /* Cacheable in both L1 and L2 caches */
-#define PROM_MAP_SE	0x0040 /* Side-Effects */
-#define PROM_MAP_GLOB	0x0080 /* Global */
-#define PROM_MAP_IE	0x0100 /* Invert-Endianness */
-#define PROM_MAP_DEFAULT (PROM_MAP_WRITE | PROM_MAP_READ | PROM_MAP_EXEC | PROM_MAP_CACHED)
-
-extern int prom_map(int mode, unsigned long size,
-		    unsigned long vaddr, unsigned long paddr);
-extern void prom_unmap(unsigned long size, unsigned long vaddr);
-
-
-/* PROM device tree traversal functions... */
-
-#ifdef PROMLIB_INTERNAL
-
-/* Internal version of prom_getchild. */
-extern int __prom_getchild(int parent_node);
-
-/* Internal version of prom_getsibling. */
-extern int __prom_getsibling(int node);
-
-#endif
-
-/* Get the child node of the given node, or zero if no child exists. */
-extern int prom_getchild(int parent_node);
-
-/* Get the next sibling node of the given node, or zero if no further
- * siblings exist.
- */
-extern int prom_getsibling(int node);
-
-/* Get the length, at the passed node, of the given property type.
- * Returns -1 on error (ie. no such property at this node).
- */
-extern int prom_getproplen(int thisnode, const char *property);
-
-/* Fetch the requested property using the given buffer.  Returns
- * the number of bytes the prom put into your buffer or -1 on error.
- */
-extern int prom_getproperty(int thisnode, const char *property,
-			    char *prop_buffer, int propbuf_size);
-
-/* Acquire an integer property. */
-extern int prom_getint(int node, const char *property);
-
-/* Acquire an integer property, with a default value. */
-extern int prom_getintdefault(int node, const char *property, int defval);
-
-/* Acquire a boolean property, 0=FALSE 1=TRUE. */
-extern int prom_getbool(int node, const char *prop);
-
-/* Acquire a string property, null string on error. */
-extern void prom_getstring(int node, const char *prop, char *buf, int bufsize);
-
-/* Does the passed node have the given "name"? YES=1 NO=0 */
-extern int prom_nodematch(int thisnode, const char *name);
-
-/* Search all siblings starting at the passed node for "name" matching
- * the given string.  Returns the node on success, zero on failure.
- */
-extern int prom_searchsiblings(int node_start, const char *name);
-
-/* Return the first property type, as a string, for the given node.
- * Returns a null string on error. Buffer should be at least 32B long.
- */
-extern char *prom_firstprop(int node, char *buffer);
-
-/* Returns the next property after the passed property for the given
- * node.  Returns null string on failure. Buffer should be at least 32B long.
- */
-extern char *prom_nextprop(int node, const char *prev_property, char *buffer);
-
-/* Returns 1 if the specified node has given property. */
-extern int prom_node_has_property(int node, const char *property);
-
-/* Returns phandle of the path specified */
-extern int prom_finddevice(const char *name);
-
-/* Set the indicated property at the given node with the passed value.
- * Returns the number of bytes of your value that the prom took.
- */
-extern int prom_setprop(int node, const char *prop_name, char *prop_value,
-			int value_size);
-			
-extern int prom_pathtoinode(const char *path);
-extern int prom_inst2pkg(int);
-extern int prom_service_exists(const char *service_name);
-extern void prom_sun4v_guest_soft_state(void);
-
-extern int prom_ihandle2path(int handle, char *buffer, int bufsize);
-
-/* Client interface level routines. */
-extern long p1275_cmd(const char *, long, ...);
-
-#if 0
-#define P1275_SIZE(x) ((((long)((x) / 32)) << 32) | (x))
-#else
-#define P1275_SIZE(x) x
-#endif
-
-/* We support at most 16 input and 1 output argument */
-#define P1275_ARG_NUMBER		0
-#define P1275_ARG_IN_STRING		1
-#define P1275_ARG_OUT_BUF		2
-#define P1275_ARG_OUT_32B		3
-#define P1275_ARG_IN_FUNCTION		4
-#define P1275_ARG_IN_BUF		5
-#define P1275_ARG_IN_64B		6
-
-#define P1275_IN(x) ((x) & 0xf)
-#define P1275_OUT(x) (((x) << 4) & 0xf0)
-#define P1275_INOUT(i,o) (P1275_IN(i)|P1275_OUT(o))
-#define P1275_ARG(n,x) ((x) << ((n)*3 + 8))
-
-#endif /* !(__SPARC64_OPLIB_H) */
+#include <asm-sparc/oplib.h>
diff --git a/include/asm-sparc64/page.h b/include/asm-sparc64/page.h
index 93f0881..f46c1fb 100644
--- a/include/asm-sparc64/page.h
+++ b/include/asm-sparc64/page.h
@@ -1,142 +1 @@
-#ifndef _SPARC64_PAGE_H
-#define _SPARC64_PAGE_H
-
-#include <linux/const.h>
-
-#if defined(CONFIG_SPARC64_PAGE_SIZE_8KB)
-#define PAGE_SHIFT   13
-#elif defined(CONFIG_SPARC64_PAGE_SIZE_64KB)
-#define PAGE_SHIFT   16
-#elif defined(CONFIG_SPARC64_PAGE_SIZE_512KB)
-#define PAGE_SHIFT   19
-#elif defined(CONFIG_SPARC64_PAGE_SIZE_4MB)
-#define PAGE_SHIFT   22
-#else
-#error No page size specified in kernel configuration
-#endif
-
-#define PAGE_SIZE    (_AC(1,UL) << PAGE_SHIFT)
-#define PAGE_MASK    (~(PAGE_SIZE-1))
-
-/* Flushing for D-cache alias handling is only needed if
- * the page size is smaller than 16K.
- */
-#if PAGE_SHIFT < 14
-#define DCACHE_ALIASING_POSSIBLE
-#endif
-
-#if defined(CONFIG_HUGETLB_PAGE_SIZE_4MB)
-#define HPAGE_SHIFT		22
-#elif defined(CONFIG_HUGETLB_PAGE_SIZE_512K)
-#define HPAGE_SHIFT		19
-#elif defined(CONFIG_HUGETLB_PAGE_SIZE_64K)
-#define HPAGE_SHIFT		16
-#endif
-
-#ifdef CONFIG_HUGETLB_PAGE
-#define HPAGE_SIZE		(_AC(1,UL) << HPAGE_SHIFT)
-#define HPAGE_MASK		(~(HPAGE_SIZE - 1UL))
-#define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
-#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
-#endif
-
-#ifndef __ASSEMBLY__
-
-extern void _clear_page(void *page);
-#define clear_page(X)	_clear_page((void *)(X))
-struct page;
-extern void clear_user_page(void *addr, unsigned long vaddr, struct page *page);
-#define copy_page(X,Y)	memcpy((void *)(X), (void *)(Y), PAGE_SIZE)
-extern void copy_user_page(void *to, void *from, unsigned long vaddr, struct page *topage);
-
-/* Unlike sparc32, sparc64's parameter passing API is more
- * sane in that structures which as small enough are passed
- * in registers instead of on the stack.  Thus, setting
- * STRICT_MM_TYPECHECKS does not generate worse code so
- * let's enable it to get the type checking.
- */
-
-#define STRICT_MM_TYPECHECKS
-
-#ifdef STRICT_MM_TYPECHECKS
-/* These are used to make use of C type-checking.. */
-typedef struct { unsigned long pte; } pte_t;
-typedef struct { unsigned long iopte; } iopte_t;
-typedef struct { unsigned int pmd; } pmd_t;
-typedef struct { unsigned int pgd; } pgd_t;
-typedef struct { unsigned long pgprot; } pgprot_t;
-
-#define pte_val(x)	((x).pte)
-#define iopte_val(x)	((x).iopte)
-#define pmd_val(x)      ((x).pmd)
-#define pgd_val(x)	((x).pgd)
-#define pgprot_val(x)	((x).pgprot)
-
-#define __pte(x)	((pte_t) { (x) } )
-#define __iopte(x)	((iopte_t) { (x) } )
-#define __pmd(x)        ((pmd_t) { (x) } )
-#define __pgd(x)	((pgd_t) { (x) } )
-#define __pgprot(x)	((pgprot_t) { (x) } )
-
-#else
-/* .. while these make it easier on the compiler */
-typedef unsigned long pte_t;
-typedef unsigned long iopte_t;
-typedef unsigned int pmd_t;
-typedef unsigned int pgd_t;
-typedef unsigned long pgprot_t;
-
-#define pte_val(x)	(x)
-#define iopte_val(x)	(x)
-#define pmd_val(x)      (x)
-#define pgd_val(x)	(x)
-#define pgprot_val(x)	(x)
-
-#define __pte(x)	(x)
-#define __iopte(x)	(x)
-#define __pmd(x)        (x)
-#define __pgd(x)	(x)
-#define __pgprot(x)	(x)
-
-#endif /* (STRICT_MM_TYPECHECKS) */
-
-typedef struct page *pgtable_t;
-
-#define TASK_UNMAPPED_BASE	(test_thread_flag(TIF_32BIT) ? \
-				 (_AC(0x0000000070000000,UL)) : \
-				 (_AC(0xfffff80000000000,UL) + (1UL << 32UL)))
-
-#include <asm-generic/memory_model.h>
-
-#endif /* !(__ASSEMBLY__) */
-
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)	(((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
-/* We used to stick this into a hard-coded global register (%g4)
- * but that does not make sense anymore.
- */
-#define PAGE_OFFSET		_AC(0xFFFFF80000000000,UL)
-
-#ifndef __ASSEMBLY__
-
-#define __pa(x)			((unsigned long)(x) - PAGE_OFFSET)
-#define __va(x)			((void *)((unsigned long) (x) + PAGE_OFFSET))
-
-#define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
-
-#define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr)>>PAGE_SHIFT)
-
-#define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
-
-#define virt_to_phys __pa
-#define phys_to_virt __va
-
-#endif /* !(__ASSEMBLY__) */
-
-#define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
-				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-
-#include <asm-generic/page.h>
-
-#endif /* _SPARC64_PAGE_H */
+#include <asm-sparc/page.h>
diff --git a/include/asm-sparc64/param.h b/include/asm-sparc64/param.h
index f0125cf..40c6dc1 100644
--- a/include/asm-sparc64/param.h
+++ b/include/asm-sparc64/param.h
@@ -1,23 +1 @@
-#ifndef _ASMSPARC64_PARAM_H
-#define _ASMSPARC64_PARAM_H
-
-
-#ifdef __KERNEL__
-# define HZ		CONFIG_HZ	/* Internal kernel timer frequency */
-# define USER_HZ	100	/* .. some user interfaces are in "ticks" */
-# define CLOCKS_PER_SEC (USER_HZ)
-#endif
-
-#ifndef HZ
-#define HZ 100
-#endif
-
-#define EXEC_PAGESIZE	8192    /* Thanks for sun4's we carry baggage... */
-
-#ifndef NOGROUP
-#define NOGROUP		(-1)
-#endif
-
-#define MAXHOSTNAMELEN	64	/* max length of hostname */
-
-#endif /* _ASMSPARC64_PARAM_H */
+#include <asm-sparc/param.h>
diff --git a/include/asm-sparc64/parport.h b/include/asm-sparc64/parport.h
index e9555b2..b4e4ca8 100644
--- a/include/asm-sparc64/parport.h
+++ b/include/asm-sparc64/parport.h
@@ -1,246 +1 @@
-/* parport.h: sparc64 specific parport initialization and dma.
- *
- * Copyright (C) 1999  Eddie C. Dost  (ecd@skynet.be)
- */
-
-#ifndef _ASM_SPARC64_PARPORT_H
-#define _ASM_SPARC64_PARPORT_H 1
-
-#include <asm/ebus.h>
-#include <asm/ns87303.h>
-#include <asm/of_device.h>
-#include <asm/prom.h>
-
-#define PARPORT_PC_MAX_PORTS	PARPORT_MAX
-
-/*
- * While sparc64 doesn't have an ISA DMA API, we provide something that looks
- * close enough to make parport_pc happy
- */
-#define HAS_DMA
-
-static DEFINE_SPINLOCK(dma_spin_lock);
-
-#define claim_dma_lock() \
-({	unsigned long flags; \
-	spin_lock_irqsave(&dma_spin_lock, flags); \
-	flags; \
-})
-
-#define release_dma_lock(__flags) \
-	spin_unlock_irqrestore(&dma_spin_lock, __flags);
-
-static struct sparc_ebus_info {
-	struct ebus_dma_info info;
-	unsigned int addr;
-	unsigned int count;
-	int lock;
-
-	struct parport *port;
-} sparc_ebus_dmas[PARPORT_PC_MAX_PORTS];
-
-static DECLARE_BITMAP(dma_slot_map, PARPORT_PC_MAX_PORTS);
-
-static inline int request_dma(unsigned int dmanr, const char *device_id)
-{
-	if (dmanr >= PARPORT_PC_MAX_PORTS)
-		return -EINVAL;
-	if (xchg(&sparc_ebus_dmas[dmanr].lock, 1) != 0)
-		return -EBUSY;
-	return 0;
-}
-
-static inline void free_dma(unsigned int dmanr)
-{
-	if (dmanr >= PARPORT_PC_MAX_PORTS) {
-		printk(KERN_WARNING "Trying to free DMA%d\n", dmanr);
-		return;
-	}
-	if (xchg(&sparc_ebus_dmas[dmanr].lock, 0) == 0) {
-		printk(KERN_WARNING "Trying to free free DMA%d\n", dmanr);
-		return;
-	}	
-}
-
-static inline void enable_dma(unsigned int dmanr)
-{
-	ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 1);
-
-	if (ebus_dma_request(&sparc_ebus_dmas[dmanr].info,
-			     sparc_ebus_dmas[dmanr].addr,
-			     sparc_ebus_dmas[dmanr].count))
-		BUG();
-}
-
-static inline void disable_dma(unsigned int dmanr)
-{
-	ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 0);
-}
-
-static inline void clear_dma_ff(unsigned int dmanr)
-{
-	/* nothing */
-}
-
-static inline void set_dma_mode(unsigned int dmanr, char mode)
-{
-	ebus_dma_prepare(&sparc_ebus_dmas[dmanr].info, (mode != DMA_MODE_WRITE));
-}
-
-static inline void set_dma_addr(unsigned int dmanr, unsigned int addr)
-{
-	sparc_ebus_dmas[dmanr].addr = addr;
-}
-
-static inline void set_dma_count(unsigned int dmanr, unsigned int count)
-{
-	sparc_ebus_dmas[dmanr].count = count;
-}
-
-static inline unsigned int get_dma_residue(unsigned int dmanr)
-{
-	return ebus_dma_residue(&sparc_ebus_dmas[dmanr].info);
-}
-
-static int __devinit ecpp_probe(struct of_device *op, const struct of_device_id *match)
-{
-	unsigned long base = op->resource[0].start;
-	unsigned long config = op->resource[1].start;
-	unsigned long d_base = op->resource[2].start;
-	unsigned long d_len;
-	struct device_node *parent;
-	struct parport *p;
-	int slot, err;
-
-	parent = op->node->parent;
-	if (!strcmp(parent->name, "dma")) {
-		p = parport_pc_probe_port(base, base + 0x400,
-					  op->irqs[0], PARPORT_DMA_NOFIFO,
-					  op->dev.parent->parent);
-		if (!p)
-			return -ENOMEM;
-		dev_set_drvdata(&op->dev, p);
-		return 0;
-	}
-
-	for (slot = 0; slot < PARPORT_PC_MAX_PORTS; slot++) {
-		if (!test_and_set_bit(slot, dma_slot_map))
-			break;
-	}
-	err = -ENODEV;
-	if (slot >= PARPORT_PC_MAX_PORTS)
-		goto out_err;
-
-	spin_lock_init(&sparc_ebus_dmas[slot].info.lock);
-
-	d_len = (op->resource[2].end - d_base) + 1UL;
-	sparc_ebus_dmas[slot].info.regs =
-		of_ioremap(&op->resource[2], 0, d_len, "ECPP DMA");
-
-	if (!sparc_ebus_dmas[slot].info.regs)
-		goto out_clear_map;
-
-	sparc_ebus_dmas[slot].info.flags = 0;
-	sparc_ebus_dmas[slot].info.callback = NULL;
-	sparc_ebus_dmas[slot].info.client_cookie = NULL;
-	sparc_ebus_dmas[slot].info.irq = 0xdeadbeef;
-	strcpy(sparc_ebus_dmas[slot].info.name, "parport");
-	if (ebus_dma_register(&sparc_ebus_dmas[slot].info))
-		goto out_unmap_regs;
-
-	ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 1);
-
-	/* Configure IRQ to Push Pull, Level Low */
-	/* Enable ECP, set bit 2 of the CTR first */
-	outb(0x04, base + 0x02);
-	ns87303_modify(config, PCR,
-		       PCR_EPP_ENABLE |
-		       PCR_IRQ_ODRAIN,
-		       PCR_ECP_ENABLE |
-		       PCR_ECP_CLK_ENA |
-		       PCR_IRQ_POLAR);
-
-	/* CTR bit 5 controls direction of port */
-	ns87303_modify(config, PTR,
-		       0, PTR_LPT_REG_DIR);
-
-	p = parport_pc_probe_port(base, base + 0x400,
-				  op->irqs[0],
-				  slot,
-				  op->dev.parent);
-	err = -ENOMEM;
-	if (!p)
-		goto out_disable_irq;
-
-	dev_set_drvdata(&op->dev, p);
-
-	return 0;
-
-out_disable_irq:
-	ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0);
-	ebus_dma_unregister(&sparc_ebus_dmas[slot].info);
-
-out_unmap_regs:
-	of_iounmap(&op->resource[2], sparc_ebus_dmas[slot].info.regs, d_len);
-
-out_clear_map:
-	clear_bit(slot, dma_slot_map);
-
-out_err:
-	return err;
-}
-
-static int __devexit ecpp_remove(struct of_device *op)
-{
-	struct parport *p = dev_get_drvdata(&op->dev);
-	int slot = p->dma;
-
-	parport_pc_unregister_port(p);
-
-	if (slot != PARPORT_DMA_NOFIFO) {
-		unsigned long d_base = op->resource[2].start;
-		unsigned long d_len;
-
-		d_len = (op->resource[2].end - d_base) + 1UL;
-
-		ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0);
-		ebus_dma_unregister(&sparc_ebus_dmas[slot].info);
-		of_iounmap(&op->resource[2],
-			   sparc_ebus_dmas[slot].info.regs,
-			   d_len);
-		clear_bit(slot, dma_slot_map);
-	}
-
-	return 0;
-}
-
-static struct of_device_id ecpp_match[] = {
-	{
-		.name = "ecpp",
-	},
-	{
-		.name = "parallel",
-		.compatible = "ecpp",
-	},
-	{
-		.name = "parallel",
-		.compatible = "ns87317-ecpp",
-	},
-	{},
-};
-
-static struct of_platform_driver ecpp_driver = {
-	.name			= "ecpp",
-	.match_table		= ecpp_match,
-	.probe			= ecpp_probe,
-	.remove			= __devexit_p(ecpp_remove),
-};
-
-static int parport_pc_find_nonpci_ports(int autoirq, int autodma)
-{
-	of_register_driver(&ecpp_driver, &of_bus_type);
-
-	return 0;
-}
-
-#endif /* !(_ASM_SPARC64_PARPORT_H */
+#include <asm-sparc/parport.h>
diff --git a/include/asm-sparc64/pci.h b/include/asm-sparc64/pci.h
index f59f257..da54c4d 100644
--- a/include/asm-sparc64/pci.h
+++ b/include/asm-sparc64/pci.h
@@ -1,209 +1 @@
-#ifndef __SPARC64_PCI_H
-#define __SPARC64_PCI_H
-
-#ifdef __KERNEL__
-
-#include <linux/dma-mapping.h>
-
-/* Can be used to override the logic in pci_scan_bus for skipping
- * already-configured bus numbers - to be used for buggy BIOSes
- * or architectures with incomplete PCI setup by the loader.
- */
-#define pcibios_assign_all_busses()	0
-#define pcibios_scan_all_fns(a, b)	0
-
-#define PCIBIOS_MIN_IO		0UL
-#define PCIBIOS_MIN_MEM		0UL
-
-#define PCI_IRQ_NONE		0xffffffff
-
-#define PCI_CACHE_LINE_BYTES	64
-
-static inline void pcibios_set_master(struct pci_dev *dev)
-{
-	/* No special bus mastering setup handling */
-}
-
-static inline void pcibios_penalize_isa_irq(int irq, int active)
-{
-	/* We don't do dynamic PCI IRQ allocation */
-}
-
-/* The PCI address space does not equal the physical memory
- * address space.  The networking and block device layers use
- * this boolean for bounce buffer decisions.
- */
-#define PCI_DMA_BUS_IS_PHYS	(0)
-
-static inline void *pci_alloc_consistent(struct pci_dev *pdev, size_t size,
-					 dma_addr_t *dma_handle)
-{
-	return dma_alloc_coherent(&pdev->dev, size, dma_handle, GFP_ATOMIC);
-}
-
-static inline void pci_free_consistent(struct pci_dev *pdev, size_t size,
-				       void *vaddr, dma_addr_t dma_handle)
-{
-	return dma_free_coherent(&pdev->dev, size, vaddr, dma_handle);
-}
-
-static inline dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr,
-					size_t size, int direction)
-{
-	return dma_map_single(&pdev->dev, ptr, size,
-			      (enum dma_data_direction) direction);
-}
-
-static inline void pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr,
-				    size_t size, int direction)
-{
-	dma_unmap_single(&pdev->dev, dma_addr, size,
-			 (enum dma_data_direction) direction);
-}
-
-#define pci_map_page(dev, page, off, size, dir) \
-	pci_map_single(dev, (page_address(page) + (off)), size, dir)
-#define pci_unmap_page(dev,addr,sz,dir) \
-	pci_unmap_single(dev,addr,sz,dir)
-
-/* pci_unmap_{single,page} is not a nop, thus... */
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)	\
-	dma_addr_t ADDR_NAME;
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		\
-	__u32 LEN_NAME;
-#define pci_unmap_addr(PTR, ADDR_NAME)			\
-	((PTR)->ADDR_NAME)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)		\
-	(((PTR)->ADDR_NAME) = (VAL))
-#define pci_unmap_len(PTR, LEN_NAME)			\
-	((PTR)->LEN_NAME)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
-	(((PTR)->LEN_NAME) = (VAL))
-
-static inline int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg,
-			     int nents, int direction)
-{
-	return dma_map_sg(&pdev->dev, sg, nents,
-			  (enum dma_data_direction) direction);
-}
-
-static inline void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg,
-				int nents, int direction)
-{
-	dma_unmap_sg(&pdev->dev, sg, nents,
-		     (enum dma_data_direction) direction);
-}
-
-static inline void pci_dma_sync_single_for_cpu(struct pci_dev *pdev,
-					       dma_addr_t dma_handle,
-					       size_t size, int direction)
-{
-	dma_sync_single_for_cpu(&pdev->dev, dma_handle, size,
-				(enum dma_data_direction) direction);
-}
-
-static inline void pci_dma_sync_single_for_device(struct pci_dev *pdev,
-						  dma_addr_t dma_handle,
-						  size_t size, int direction)
-{
-	/* No flushing needed to sync cpu writes to the device.  */
-}
-
-static inline void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev,
-					   struct scatterlist *sg,
-					   int nents, int direction)
-{
-	dma_sync_sg_for_cpu(&pdev->dev, sg, nents,
-			    (enum dma_data_direction) direction);
-}
-
-static inline void pci_dma_sync_sg_for_device(struct pci_dev *pdev,
-					      struct scatterlist *sg,
-					      int nelems, int direction)
-{
-	/* No flushing needed to sync cpu writes to the device.  */
-}
-
-/* Return whether the given PCI device DMA address mask can
- * be supported properly.  For example, if your device can
- * only drive the low 24-bits during PCI bus mastering, then
- * you would pass 0x00ffffff as the mask to this function.
- */
-extern int pci_dma_supported(struct pci_dev *hwdev, u64 mask);
-
-/* PCI IOMMU mapping bypass support. */
-
-/* PCI 64-bit addressing works for all slots on all controller
- * types on sparc64.  However, it requires that the device
- * can drive enough of the 64 bits.
- */
-#define PCI64_REQUIRED_MASK	(~(dma64_addr_t)0)
-#define PCI64_ADDR_BASE		0xfffc000000000000UL
-
-static inline int pci_dma_mapping_error(dma_addr_t dma_addr)
-{
-	return dma_mapping_error(dma_addr);
-}
-
-#ifdef CONFIG_PCI
-static inline void pci_dma_burst_advice(struct pci_dev *pdev,
-					enum pci_dma_burst_strategy *strat,
-					unsigned long *strategy_parameter)
-{
-	unsigned long cacheline_size;
-	u8 byte;
-
-	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &byte);
-	if (byte == 0)
-		cacheline_size = 1024;
-	else
-		cacheline_size = (int) byte * 4;
-
-	*strat = PCI_DMA_BURST_BOUNDARY;
-	*strategy_parameter = cacheline_size;
-}
-#endif
-
-/* Return the index of the PCI controller for device PDEV. */
-
-extern int pci_domain_nr(struct pci_bus *bus);
-static inline int pci_proc_domain(struct pci_bus *bus)
-{
-	return 1;
-}
-
-/* Platform support for /proc/bus/pci/X/Y mmap()s. */
-
-#define HAVE_PCI_MMAP
-#define HAVE_ARCH_PCI_GET_UNMAPPED_AREA
-#define get_pci_unmapped_area get_fb_unmapped_area
-
-extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-			       enum pci_mmap_state mmap_state,
-			       int write_combine);
-
-extern void
-pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
-			struct resource *res);
-
-extern void
-pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
-			struct pci_bus_region *region);
-
-extern struct resource *pcibios_select_root(struct pci_dev *, struct resource *);
-
-static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
-{
-	return PCI_IRQ_NONE;
-}
-
-struct device_node;
-extern struct device_node *pci_device_to_OF_node(struct pci_dev *pdev);
-
-#define HAVE_ARCH_PCI_RESOURCE_TO_USER
-extern void pci_resource_to_user(const struct pci_dev *dev, int bar,
-				 const struct resource *rsrc,
-				 resource_size_t *start, resource_size_t *end);
-#endif /* __KERNEL__ */
-
-#endif /* __SPARC64_PCI_H */
+#include <asm-sparc/pci.h>
diff --git a/include/asm-sparc64/percpu.h b/include/asm-sparc64/percpu.h
index bee6459..292729b 100644
--- a/include/asm-sparc64/percpu.h
+++ b/include/asm-sparc64/percpu.h
@@ -1,28 +1 @@
-#ifndef __ARCH_SPARC64_PERCPU__
-#define __ARCH_SPARC64_PERCPU__
-
-#include <linux/compiler.h>
-
-register unsigned long __local_per_cpu_offset asm("g5");
-
-#ifdef CONFIG_SMP
-
-extern void real_setup_per_cpu_areas(void);
-
-extern unsigned long __per_cpu_base;
-extern unsigned long __per_cpu_shift;
-#define __per_cpu_offset(__cpu) \
-	(__per_cpu_base + ((unsigned long)(__cpu) << __per_cpu_shift))
-#define per_cpu_offset(x) (__per_cpu_offset(x))
-
-#define __my_cpu_offset __local_per_cpu_offset
-
-#else /* ! SMP */
-
-#define real_setup_per_cpu_areas()		do { } while (0)
-
-#endif	/* SMP */
-
-#include <asm-generic/percpu.h>
-
-#endif /* __ARCH_SPARC64_PERCPU__ */
+#include <asm-sparc/percpu.h>
diff --git a/include/asm-sparc64/perfctr.h b/include/asm-sparc64/perfctr.h
index 8368730..52073a9 100644
--- a/include/asm-sparc64/perfctr.h
+++ b/include/asm-sparc64/perfctr.h
@@ -1,173 +1 @@
-/*----------------------------------------
-  PERFORMANCE INSTRUMENTATION  
-  Guillaume Thouvenin           08/10/98
-  David S. Miller               10/06/98
-  ---------------------------------------*/
-#ifndef PERF_COUNTER_API
-#define PERF_COUNTER_API
-
-/* sys_perfctr() interface.  First arg is operation code
- * from enumeration below.  The meaning of further arguments
- * are determined by the operation code.
- *
- * int sys_perfctr(int opcode, unsigned long arg0,
- *                 unsigned long arg1, unsigned long arg2)
- *
- * Pointers which are passed by the user are pointers to 64-bit
- * integers.
- *
- * Once enabled, performance counter state is retained until the
- * process either exits or performs an exec.  That is, performance
- * counters remain enabled for fork/clone children.
- */
-enum perfctr_opcode {
-	/* Enable UltraSparc performance counters, ARG0 is pointer
-	 * to 64-bit accumulator for D0 counter in PIC, ARG1 is pointer
-	 * to 64-bit accumulator for D1 counter.  ARG2 is a pointer to
-	 * the initial PCR register value to use.
-	 */
-	PERFCTR_ON,
-
-	/* Disable UltraSparc performance counters.  The PCR is written
-	 * with zero and the user counter accumulator pointers and
-	 * working PCR register value are forgotten.
-	 */
-	PERFCTR_OFF,
-
-	/* Add current D0 and D1 PIC values into user pointers given
-	 * in PERFCTR_ON operation.  The PIC is cleared before returning.
-	 */
-	PERFCTR_READ,
-
-	/* Clear the PIC register. */
-	PERFCTR_CLRPIC,
-
-	/* Begin using a new PCR value, the pointer to which is passed
-	 * in ARG0.  The PIC is also cleared after the new PCR value is
-	 * written.
-	 */
-	PERFCTR_SETPCR,
-
-	/* Store in pointer given in ARG0 the current PCR register value
-	 * being used.
-	 */
-	PERFCTR_GETPCR
-};
-
-/* I don't want the kernel's namespace to be polluted with this
- * stuff when this file is included.  --DaveM
- */
-#ifndef __KERNEL__
-
-#define  PRIV 0x00000001
-#define  SYS  0x00000002
-#define  USR  0x00000004
-
-/* Pic.S0 Selection Bit Field Encoding, Ultra-I/II  */
-#define  CYCLE_CNT            0x00000000
-#define  INSTR_CNT            0x00000010
-#define  DISPATCH0_IC_MISS    0x00000020
-#define  DISPATCH0_STOREBUF   0x00000030
-#define  IC_REF               0x00000080
-#define  DC_RD                0x00000090
-#define  DC_WR                0x000000A0
-#define  LOAD_USE             0x000000B0
-#define  EC_REF               0x000000C0
-#define  EC_WRITE_HIT_RDO     0x000000D0
-#define  EC_SNOOP_INV         0x000000E0
-#define  EC_RD_HIT            0x000000F0
-
-/* Pic.S0 Selection Bit Field Encoding, Ultra-III  */
-#define  US3_CYCLE_CNT	      	0x00000000
-#define  US3_INSTR_CNT	      	0x00000010
-#define  US3_DISPATCH0_IC_MISS	0x00000020
-#define  US3_DISPATCH0_BR_TGT	0x00000030
-#define  US3_DISPATCH0_2ND_BR	0x00000040
-#define  US3_RSTALL_STOREQ	0x00000050
-#define  US3_RSTALL_IU_USE	0x00000060
-#define  US3_IC_REF		0x00000080
-#define  US3_DC_RD		0x00000090
-#define  US3_DC_WR		0x000000a0
-#define  US3_EC_REF		0x000000c0
-#define  US3_EC_WR_HIT_RTO	0x000000d0
-#define  US3_EC_SNOOP_INV	0x000000e0
-#define  US3_EC_RD_MISS		0x000000f0
-#define  US3_PC_PORT0_RD	0x00000100
-#define  US3_SI_SNOOP		0x00000110
-#define  US3_SI_CIQ_FLOW	0x00000120
-#define  US3_SI_OWNED		0x00000130
-#define  US3_SW_COUNT_0		0x00000140
-#define  US3_IU_BR_MISS_TAKEN	0x00000150
-#define  US3_IU_BR_COUNT_TAKEN	0x00000160
-#define  US3_DISP_RS_MISPRED	0x00000170
-#define  US3_FA_PIPE_COMPL	0x00000180
-#define  US3_MC_READS_0		0x00000200
-#define  US3_MC_READS_1		0x00000210
-#define  US3_MC_READS_2		0x00000220
-#define  US3_MC_READS_3		0x00000230
-#define  US3_MC_STALLS_0	0x00000240
-#define  US3_MC_STALLS_2	0x00000250
-
-/* Pic.S1 Selection Bit Field Encoding, Ultra-I/II  */
-#define  CYCLE_CNT_D1         0x00000000
-#define  INSTR_CNT_D1         0x00000800
-#define  DISPATCH0_IC_MISPRED 0x00001000
-#define  DISPATCH0_FP_USE     0x00001800
-#define  IC_HIT               0x00004000
-#define  DC_RD_HIT            0x00004800
-#define  DC_WR_HIT            0x00005000
-#define  LOAD_USE_RAW         0x00005800
-#define  EC_HIT               0x00006000
-#define  EC_WB                0x00006800
-#define  EC_SNOOP_CB          0x00007000
-#define  EC_IT_HIT            0x00007800
-
-/* Pic.S1 Selection Bit Field Encoding, Ultra-III  */
-#define  US3_CYCLE_CNT_D1	0x00000000
-#define  US3_INSTR_CNT_D1	0x00000800
-#define  US3_DISPATCH0_MISPRED	0x00001000
-#define  US3_IC_MISS_CANCELLED	0x00001800
-#define  US3_RE_ENDIAN_MISS	0x00002000
-#define  US3_RE_FPU_BYPASS	0x00002800
-#define  US3_RE_DC_MISS		0x00003000
-#define  US3_RE_EC_MISS		0x00003800
-#define  US3_IC_MISS		0x00004000
-#define  US3_DC_RD_MISS		0x00004800
-#define  US3_DC_WR_MISS		0x00005000
-#define  US3_RSTALL_FP_USE	0x00005800
-#define  US3_EC_MISSES		0x00006000
-#define  US3_EC_WB		0x00006800
-#define  US3_EC_SNOOP_CB	0x00007000
-#define  US3_EC_IC_MISS		0x00007800
-#define  US3_RE_PC_MISS		0x00008000
-#define  US3_ITLB_MISS		0x00008800
-#define  US3_DTLB_MISS		0x00009000
-#define  US3_WC_MISS		0x00009800
-#define  US3_WC_SNOOP_CB	0x0000a000
-#define  US3_WC_SCRUBBED	0x0000a800
-#define  US3_WC_WB_WO_READ	0x0000b000
-#define  US3_PC_SOFT_HIT	0x0000c000
-#define  US3_PC_SNOOP_INV	0x0000c800
-#define  US3_PC_HARD_HIT	0x0000d000
-#define  US3_PC_PORT1_RD	0x0000d800
-#define  US3_SW_COUNT_1		0x0000e000
-#define  US3_IU_STAT_BR_MIS_UNTAKEN	0x0000e800
-#define  US3_IU_STAT_BR_COUNT_UNTAKEN	0x0000f000
-#define  US3_PC_MS_MISSES	0x0000f800
-#define  US3_MC_WRITES_0	0x00010800
-#define  US3_MC_WRITES_1	0x00011000
-#define  US3_MC_WRITES_2	0x00011800
-#define  US3_MC_WRITES_3	0x00012000
-#define  US3_MC_STALLS_1	0x00012800
-#define  US3_MC_STALLS_3	0x00013000
-#define  US3_RE_RAW_MISS	0x00013800
-#define  US3_FM_PIPE_COMPLETION	0x00014000
-
-struct vcounter_struct {
-  unsigned long long vcnt0;
-  unsigned long long vcnt1;
-};
-
-#endif /* !(__KERNEL__) */
-
-#endif /* !(PERF_COUNTER_API) */
+#include <asm-sparc/perfctr.h>
diff --git a/include/asm-sparc64/pgalloc.h b/include/asm-sparc64/pgalloc.h
index 326de10..bec3164 100644
--- a/include/asm-sparc64/pgalloc.h
+++ b/include/asm-sparc64/pgalloc.h
@@ -1,81 +1 @@
-#ifndef _SPARC64_PGALLOC_H
-#define _SPARC64_PGALLOC_H
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/quicklist.h>
-
-#include <asm/spitfire.h>
-#include <asm/cpudata.h>
-#include <asm/cacheflush.h>
-#include <asm/page.h>
-
-/* Page table allocation/freeing. */
-
-static inline pgd_t *pgd_alloc(struct mm_struct *mm)
-{
-	return quicklist_alloc(0, GFP_KERNEL, NULL);
-}
-
-static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
-{
-	quicklist_free(0, NULL, pgd);
-}
-
-#define pud_populate(MM, PUD, PMD)	pud_set(PUD, PMD)
-
-static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
-{
-	return quicklist_alloc(0, GFP_KERNEL, NULL);
-}
-
-static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
-{
-	quicklist_free(0, NULL, pmd);
-}
-
-static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
-					  unsigned long address)
-{
-	return quicklist_alloc(0, GFP_KERNEL, NULL);
-}
-
-static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
-					unsigned long address)
-{
-	struct page *page;
-	void *pg;
-
-	pg = quicklist_alloc(0, GFP_KERNEL, NULL);
-	if (!pg)
-		return NULL;
-	page = virt_to_page(pg);
-	pgtable_page_ctor(page);
-	return page;
-}
-		
-static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
-{
-	quicklist_free(0, NULL, pte);
-}
-
-static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
-{
-	pgtable_page_dtor(ptepage);
-	quicklist_free_page(0, NULL, ptepage);
-}
-
-
-#define pmd_populate_kernel(MM, PMD, PTE)	pmd_set(PMD, PTE)
-#define pmd_populate(MM,PMD,PTE_PAGE)		\
-	pmd_populate_kernel(MM,PMD,page_address(PTE_PAGE))
-#define pmd_pgtable(pmd) pmd_page(pmd)
-
-static inline void check_pgt_cache(void)
-{
-	quicklist_trim(0, NULL, 25, 16);
-}
-
-#endif /* _SPARC64_PGALLOC_H */
+#include <asm-sparc/pgalloc.h>
diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
index b870177..9decbd9 100644
--- a/include/asm-sparc64/pgtable.h
+++ b/include/asm-sparc64/pgtable.h
@@ -1,781 +1 @@
-/*
- * pgtable.h: SpitFire page table operations.
- *
- * Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu)
- * Copyright 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- */
-
-#ifndef _SPARC64_PGTABLE_H
-#define _SPARC64_PGTABLE_H
-
-/* This file contains the functions and defines necessary to modify and use
- * the SpitFire page tables.
- */
-
-#include <asm-generic/pgtable-nopud.h>
-
-#include <linux/compiler.h>
-#include <linux/const.h>
-#include <asm/types.h>
-#include <asm/spitfire.h>
-#include <asm/asi.h>
-#include <asm/system.h>
-#include <asm/page.h>
-#include <asm/processor.h>
-
-/* The kernel image occupies 0x4000000 to 0x6000000 (4MB --> 96MB).
- * The page copy blockops can use 0x6000000 to 0x8000000.
- * The TSB is mapped in the 0x8000000 to 0xa000000 range.
- * The PROM resides in an area spanning 0xf0000000 to 0x100000000.
- * The vmalloc area spans 0x100000000 to 0x200000000.
- * Since modules need to be in the lowest 32-bits of the address space,
- * we place them right before the OBP area from 0x10000000 to 0xf0000000.
- * There is a single static kernel PMD which maps from 0x0 to address
- * 0x400000000.
- */
-#define	TLBTEMP_BASE		_AC(0x0000000006000000,UL)
-#define	TSBMAP_BASE		_AC(0x0000000008000000,UL)
-#define MODULES_VADDR		_AC(0x0000000010000000,UL)
-#define MODULES_LEN		_AC(0x00000000e0000000,UL)
-#define MODULES_END		_AC(0x00000000f0000000,UL)
-#define LOW_OBP_ADDRESS		_AC(0x00000000f0000000,UL)
-#define HI_OBP_ADDRESS		_AC(0x0000000100000000,UL)
-#define VMALLOC_START		_AC(0x0000000100000000,UL)
-#define VMALLOC_END		_AC(0x0000000200000000,UL)
-#define VMEMMAP_BASE		_AC(0x0000000200000000,UL)
-
-#define vmemmap			((struct page *)VMEMMAP_BASE)
-
-/* XXX All of this needs to be rethought so we can take advantage
- * XXX cheetah's full 64-bit virtual address space, ie. no more hole
- * XXX in the middle like on spitfire. -DaveM
- */
-/*
- * Given a virtual address, the lowest PAGE_SHIFT bits determine offset
- * into the page; the next higher PAGE_SHIFT-3 bits determine the pte#
- * in the proper pagetable (the -3 is from the 8 byte ptes, and each page
- * table is a single page long). The next higher PMD_BITS determine pmd# 
- * in the proper pmdtable (where we must have PMD_BITS <= (PAGE_SHIFT-2) 
- * since the pmd entries are 4 bytes, and each pmd page is a single page 
- * long). Finally, the higher few bits determine pgde#.
- */
-
-/* PMD_SHIFT determines the size of the area a second-level page
- * table can map
- */
-#define PMD_SHIFT	(PAGE_SHIFT + (PAGE_SHIFT-3))
-#define PMD_SIZE	(_AC(1,UL) << PMD_SHIFT)
-#define PMD_MASK	(~(PMD_SIZE-1))
-#define PMD_BITS	(PAGE_SHIFT - 2)
-
-/* PGDIR_SHIFT determines what a third-level page table entry can map */
-#define PGDIR_SHIFT	(PAGE_SHIFT + (PAGE_SHIFT-3) + PMD_BITS)
-#define PGDIR_SIZE	(_AC(1,UL) << PGDIR_SHIFT)
-#define PGDIR_MASK	(~(PGDIR_SIZE-1))
-#define PGDIR_BITS	(PAGE_SHIFT - 2)
-
-#ifndef __ASSEMBLY__
-
-#include <linux/sched.h>
-
-/* Entries per page directory level. */
-#define PTRS_PER_PTE	(1UL << (PAGE_SHIFT-3))
-#define PTRS_PER_PMD	(1UL << PMD_BITS)
-#define PTRS_PER_PGD	(1UL << PGDIR_BITS)
-
-/* Kernel has a separate 44bit address space. */
-#define FIRST_USER_ADDRESS	0
-
-#define pte_ERROR(e)	__builtin_trap()
-#define pmd_ERROR(e)	__builtin_trap()
-#define pgd_ERROR(e)	__builtin_trap()
-
-#endif /* !(__ASSEMBLY__) */
-
-/* PTE bits which are the same in SUN4U and SUN4V format.  */
-#define _PAGE_VALID	  _AC(0x8000000000000000,UL) /* Valid TTE            */
-#define _PAGE_R	  	  _AC(0x8000000000000000,UL) /* Keep ref bit uptodate*/
-
-/* SUN4U pte bits... */
-#define _PAGE_SZ4MB_4U	  _AC(0x6000000000000000,UL) /* 4MB Page             */
-#define _PAGE_SZ512K_4U	  _AC(0x4000000000000000,UL) /* 512K Page            */
-#define _PAGE_SZ64K_4U	  _AC(0x2000000000000000,UL) /* 64K Page             */
-#define _PAGE_SZ8K_4U	  _AC(0x0000000000000000,UL) /* 8K Page              */
-#define _PAGE_NFO_4U	  _AC(0x1000000000000000,UL) /* No Fault Only        */
-#define _PAGE_IE_4U	  _AC(0x0800000000000000,UL) /* Invert Endianness    */
-#define _PAGE_SOFT2_4U	  _AC(0x07FC000000000000,UL) /* Software bits, set 2 */
-#define _PAGE_RES1_4U	  _AC(0x0002000000000000,UL) /* Reserved             */
-#define _PAGE_SZ32MB_4U	  _AC(0x0001000000000000,UL) /* (Panther) 32MB page  */
-#define _PAGE_SZ256MB_4U  _AC(0x2001000000000000,UL) /* (Panther) 256MB page */
-#define _PAGE_SZALL_4U	  _AC(0x6001000000000000,UL) /* All pgsz bits        */
-#define _PAGE_SN_4U	  _AC(0x0000800000000000,UL) /* (Cheetah) Snoop      */
-#define _PAGE_RES2_4U	  _AC(0x0000780000000000,UL) /* Reserved             */
-#define _PAGE_PADDR_4U	  _AC(0x000007FFFFFFE000,UL) /* (Cheetah) pa[42:13]  */
-#define _PAGE_SOFT_4U	  _AC(0x0000000000001F80,UL) /* Software bits:       */
-#define _PAGE_EXEC_4U	  _AC(0x0000000000001000,UL) /* Executable SW bit    */
-#define _PAGE_MODIFIED_4U _AC(0x0000000000000800,UL) /* Modified (dirty)     */
-#define _PAGE_FILE_4U	  _AC(0x0000000000000800,UL) /* Pagecache page       */
-#define _PAGE_ACCESSED_4U _AC(0x0000000000000400,UL) /* Accessed (ref'd)     */
-#define _PAGE_READ_4U	  _AC(0x0000000000000200,UL) /* Readable SW Bit      */
-#define _PAGE_WRITE_4U	  _AC(0x0000000000000100,UL) /* Writable SW Bit      */
-#define _PAGE_PRESENT_4U  _AC(0x0000000000000080,UL) /* Present              */
-#define _PAGE_L_4U	  _AC(0x0000000000000040,UL) /* Locked TTE           */
-#define _PAGE_CP_4U	  _AC(0x0000000000000020,UL) /* Cacheable in P-Cache */
-#define _PAGE_CV_4U	  _AC(0x0000000000000010,UL) /* Cacheable in V-Cache */
-#define _PAGE_E_4U	  _AC(0x0000000000000008,UL) /* side-Effect          */
-#define _PAGE_P_4U	  _AC(0x0000000000000004,UL) /* Privileged Page      */
-#define _PAGE_W_4U	  _AC(0x0000000000000002,UL) /* Writable             */
-
-/* SUN4V pte bits... */
-#define _PAGE_NFO_4V	  _AC(0x4000000000000000,UL) /* No Fault Only        */
-#define _PAGE_SOFT2_4V	  _AC(0x3F00000000000000,UL) /* Software bits, set 2 */
-#define _PAGE_MODIFIED_4V _AC(0x2000000000000000,UL) /* Modified (dirty)     */
-#define _PAGE_ACCESSED_4V _AC(0x1000000000000000,UL) /* Accessed (ref'd)     */
-#define _PAGE_READ_4V	  _AC(0x0800000000000000,UL) /* Readable SW Bit      */
-#define _PAGE_WRITE_4V	  _AC(0x0400000000000000,UL) /* Writable SW Bit      */
-#define _PAGE_PADDR_4V	  _AC(0x00FFFFFFFFFFE000,UL) /* paddr[55:13]         */
-#define _PAGE_IE_4V	  _AC(0x0000000000001000,UL) /* Invert Endianness    */
-#define _PAGE_E_4V	  _AC(0x0000000000000800,UL) /* side-Effect          */
-#define _PAGE_CP_4V	  _AC(0x0000000000000400,UL) /* Cacheable in P-Cache */
-#define _PAGE_CV_4V	  _AC(0x0000000000000200,UL) /* Cacheable in V-Cache */
-#define _PAGE_P_4V	  _AC(0x0000000000000100,UL) /* Privileged Page      */
-#define _PAGE_EXEC_4V	  _AC(0x0000000000000080,UL) /* Executable Page      */
-#define _PAGE_W_4V	  _AC(0x0000000000000040,UL) /* Writable             */
-#define _PAGE_SOFT_4V	  _AC(0x0000000000000030,UL) /* Software bits        */
-#define _PAGE_FILE_4V	  _AC(0x0000000000000020,UL) /* Pagecache page       */
-#define _PAGE_PRESENT_4V  _AC(0x0000000000000010,UL) /* Present              */
-#define _PAGE_RESV_4V	  _AC(0x0000000000000008,UL) /* Reserved             */
-#define _PAGE_SZ16GB_4V	  _AC(0x0000000000000007,UL) /* 16GB Page            */
-#define _PAGE_SZ2GB_4V	  _AC(0x0000000000000006,UL) /* 2GB Page             */
-#define _PAGE_SZ256MB_4V  _AC(0x0000000000000005,UL) /* 256MB Page           */
-#define _PAGE_SZ32MB_4V	  _AC(0x0000000000000004,UL) /* 32MB Page            */
-#define _PAGE_SZ4MB_4V	  _AC(0x0000000000000003,UL) /* 4MB Page             */
-#define _PAGE_SZ512K_4V	  _AC(0x0000000000000002,UL) /* 512K Page            */
-#define _PAGE_SZ64K_4V	  _AC(0x0000000000000001,UL) /* 64K Page             */
-#define _PAGE_SZ8K_4V	  _AC(0x0000000000000000,UL) /* 8K Page              */
-#define _PAGE_SZALL_4V	  _AC(0x0000000000000007,UL) /* All pgsz bits        */
-
-#if PAGE_SHIFT == 13
-#define _PAGE_SZBITS_4U	_PAGE_SZ8K_4U
-#define _PAGE_SZBITS_4V	_PAGE_SZ8K_4V
-#elif PAGE_SHIFT == 16
-#define _PAGE_SZBITS_4U	_PAGE_SZ64K_4U
-#define _PAGE_SZBITS_4V	_PAGE_SZ64K_4V
-#elif PAGE_SHIFT == 19
-#define _PAGE_SZBITS_4U	_PAGE_SZ512K_4U
-#define _PAGE_SZBITS_4V	_PAGE_SZ512K_4V
-#elif PAGE_SHIFT == 22
-#define _PAGE_SZBITS_4U	_PAGE_SZ4MB_4U
-#define _PAGE_SZBITS_4V	_PAGE_SZ4MB_4V
-#else
-#error Wrong PAGE_SHIFT specified
-#endif
-
-#if defined(CONFIG_HUGETLB_PAGE_SIZE_4MB)
-#define _PAGE_SZHUGE_4U	_PAGE_SZ4MB_4U
-#define _PAGE_SZHUGE_4V	_PAGE_SZ4MB_4V
-#elif defined(CONFIG_HUGETLB_PAGE_SIZE_512K)
-#define _PAGE_SZHUGE_4U	_PAGE_SZ512K_4U
-#define _PAGE_SZHUGE_4V	_PAGE_SZ512K_4V
-#elif defined(CONFIG_HUGETLB_PAGE_SIZE_64K)
-#define _PAGE_SZHUGE_4U	_PAGE_SZ64K_4U
-#define _PAGE_SZHUGE_4V	_PAGE_SZ64K_4V
-#endif
-
-/* These are actually filled in at boot time by sun4{u,v}_pgprot_init() */
-#define __P000	__pgprot(0)
-#define __P001	__pgprot(0)
-#define __P010	__pgprot(0)
-#define __P011	__pgprot(0)
-#define __P100	__pgprot(0)
-#define __P101	__pgprot(0)
-#define __P110	__pgprot(0)
-#define __P111	__pgprot(0)
-
-#define __S000	__pgprot(0)
-#define __S001	__pgprot(0)
-#define __S010	__pgprot(0)
-#define __S011	__pgprot(0)
-#define __S100	__pgprot(0)
-#define __S101	__pgprot(0)
-#define __S110	__pgprot(0)
-#define __S111	__pgprot(0)
-
-#ifndef __ASSEMBLY__
-
-extern pte_t mk_pte_io(unsigned long, pgprot_t, int, unsigned long);
-
-extern unsigned long pte_sz_bits(unsigned long size);
-
-extern pgprot_t PAGE_KERNEL;
-extern pgprot_t PAGE_KERNEL_LOCKED;
-extern pgprot_t PAGE_COPY;
-extern pgprot_t PAGE_SHARED;
-
-/* XXX This uglyness is for the atyfb driver's sparc mmap() support. XXX */
-extern unsigned long _PAGE_IE;
-extern unsigned long _PAGE_E;
-extern unsigned long _PAGE_CACHE;
-
-extern unsigned long pg_iobits;
-extern unsigned long _PAGE_ALL_SZ_BITS;
-extern unsigned long _PAGE_SZBITS;
-
-extern struct page *mem_map_zero;
-#define ZERO_PAGE(vaddr)	(mem_map_zero)
-
-/* PFNs are real physical page numbers.  However, mem_map only begins to record
- * per-page information starting at pfn_base.  This is to handle systems where
- * the first physical page in the machine is at some huge physical address,
- * such as 4GB.   This is common on a partitioned E10000, for example.
- */
-static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot)
-{
-	unsigned long paddr = pfn << PAGE_SHIFT;
-	unsigned long sz_bits;
-
-	sz_bits = 0UL;
-	if (_PAGE_SZBITS_4U != 0UL || _PAGE_SZBITS_4V != 0UL) {
-		__asm__ __volatile__(
-		"\n661:	sethi		%%uhi(%1), %0\n"
-		"	sllx		%0, 32, %0\n"
-		"	.section	.sun4v_2insn_patch, \"ax\"\n"
-		"	.word		661b\n"
-		"	mov		%2, %0\n"
-		"	nop\n"
-		"	.previous\n"
-		: "=r" (sz_bits)
-		: "i" (_PAGE_SZBITS_4U), "i" (_PAGE_SZBITS_4V));
-	}
-	return __pte(paddr | sz_bits | pgprot_val(prot));
-}
-#define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
-
-/* This one can be done with two shifts.  */
-static inline unsigned long pte_pfn(pte_t pte)
-{
-	unsigned long ret;
-
-	__asm__ __volatile__(
-	"\n661:	sllx		%1, %2, %0\n"
-	"	srlx		%0, %3, %0\n"
-	"	.section	.sun4v_2insn_patch, \"ax\"\n"
-	"	.word		661b\n"
-	"	sllx		%1, %4, %0\n"
-	"	srlx		%0, %5, %0\n"
-	"	.previous\n"
-	: "=r" (ret)
-	: "r" (pte_val(pte)),
-	  "i" (21), "i" (21 + PAGE_SHIFT),
-	  "i" (8), "i" (8 + PAGE_SHIFT));
-
-	return ret;
-}
-#define pte_page(x) pfn_to_page(pte_pfn(x))
-
-static inline pte_t pte_modify(pte_t pte, pgprot_t prot)
-{
-	unsigned long mask, tmp;
-
-	/* SUN4U: 0x600307ffffffecb8 (negated == 0x9ffcf80000001347)
-	 * SUN4V: 0x30ffffffffffee17 (negated == 0xcf000000000011e8)
-	 *
-	 * Even if we use negation tricks the result is still a 6
-	 * instruction sequence, so don't try to play fancy and just
-	 * do the most straightforward implementation.
-	 *
-	 * Note: We encode this into 3 sun4v 2-insn patch sequences.
-	 */
-
-	__asm__ __volatile__(
-	"\n661:	sethi		%%uhi(%2), %1\n"
-	"	sethi		%%hi(%2), %0\n"
-	"\n662:	or		%1, %%ulo(%2), %1\n"
-	"	or		%0, %%lo(%2), %0\n"
-	"\n663:	sllx		%1, 32, %1\n"
-	"	or		%0, %1, %0\n"
-	"	.section	.sun4v_2insn_patch, \"ax\"\n"
-	"	.word		661b\n"
-	"	sethi		%%uhi(%3), %1\n"
-	"	sethi		%%hi(%3), %0\n"
-	"	.word		662b\n"
-	"	or		%1, %%ulo(%3), %1\n"
-	"	or		%0, %%lo(%3), %0\n"
-	"	.word		663b\n"
-	"	sllx		%1, 32, %1\n"
-	"	or		%0, %1, %0\n"
-	"	.previous\n"
-	: "=r" (mask), "=r" (tmp)
-	: "i" (_PAGE_PADDR_4U | _PAGE_MODIFIED_4U | _PAGE_ACCESSED_4U |
-	       _PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U | _PAGE_PRESENT_4U |
-	       _PAGE_SZBITS_4U),
-	  "i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V |
-	       _PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V | _PAGE_PRESENT_4V |
-	       _PAGE_SZBITS_4V));
-
-	return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask));
-}
-
-static inline pte_t pgoff_to_pte(unsigned long off)
-{
-	off <<= PAGE_SHIFT;
-
-	__asm__ __volatile__(
-	"\n661:	or		%0, %2, %0\n"
-	"	.section	.sun4v_1insn_patch, \"ax\"\n"
-	"	.word		661b\n"
-	"	or		%0, %3, %0\n"
-	"	.previous\n"
-	: "=r" (off)
-	: "0" (off), "i" (_PAGE_FILE_4U), "i" (_PAGE_FILE_4V));
-
-	return __pte(off);
-}
-
-static inline pgprot_t pgprot_noncached(pgprot_t prot)
-{
-	unsigned long val = pgprot_val(prot);
-
-	__asm__ __volatile__(
-	"\n661:	andn		%0, %2, %0\n"
-	"	or		%0, %3, %0\n"
-	"	.section	.sun4v_2insn_patch, \"ax\"\n"
-	"	.word		661b\n"
-	"	andn		%0, %4, %0\n"
-	"	or		%0, %5, %0\n"
-	"	.previous\n"
-	: "=r" (val)
-	: "0" (val), "i" (_PAGE_CP_4U | _PAGE_CV_4U), "i" (_PAGE_E_4U),
-	             "i" (_PAGE_CP_4V | _PAGE_CV_4V), "i" (_PAGE_E_4V));
-
-	return __pgprot(val);
-}
-/* Various pieces of code check for platform support by ifdef testing
- * on "pgprot_noncached".  That's broken and should be fixed, but for
- * now...
- */
-#define pgprot_noncached pgprot_noncached
-
-#ifdef CONFIG_HUGETLB_PAGE
-static inline pte_t pte_mkhuge(pte_t pte)
-{
-	unsigned long mask;
-
-	__asm__ __volatile__(
-	"\n661:	sethi		%%uhi(%1), %0\n"
-	"	sllx		%0, 32, %0\n"
-	"	.section	.sun4v_2insn_patch, \"ax\"\n"
-	"	.word		661b\n"
-	"	mov		%2, %0\n"
-	"	nop\n"
-	"	.previous\n"
-	: "=r" (mask)
-	: "i" (_PAGE_SZHUGE_4U), "i" (_PAGE_SZHUGE_4V));
-
-	return __pte(pte_val(pte) | mask);
-}
-#endif
-
-static inline pte_t pte_mkdirty(pte_t pte)
-{
-	unsigned long val = pte_val(pte), tmp;
-
-	__asm__ __volatile__(
-	"\n661:	or		%0, %3, %0\n"
-	"	nop\n"
-	"\n662:	nop\n"
-	"	nop\n"
-	"	.section	.sun4v_2insn_patch, \"ax\"\n"
-	"	.word		661b\n"
-	"	sethi		%%uhi(%4), %1\n"
-	"	sllx		%1, 32, %1\n"
-	"	.word		662b\n"
-	"	or		%1, %%lo(%4), %1\n"
-	"	or		%0, %1, %0\n"
-	"	.previous\n"
-	: "=r" (val), "=r" (tmp)
-	: "0" (val), "i" (_PAGE_MODIFIED_4U | _PAGE_W_4U),
-	  "i" (_PAGE_MODIFIED_4V | _PAGE_W_4V));
-
-	return __pte(val);
-}
-
-static inline pte_t pte_mkclean(pte_t pte)
-{
-	unsigned long val = pte_val(pte), tmp;
-
-	__asm__ __volatile__(
-	"\n661:	andn		%0, %3, %0\n"
-	"	nop\n"
-	"\n662:	nop\n"
-	"	nop\n"
-	"	.section	.sun4v_2insn_patch, \"ax\"\n"
-	"	.word		661b\n"
-	"	sethi		%%uhi(%4), %1\n"
-	"	sllx		%1, 32, %1\n"
-	"	.word		662b\n"
-	"	or		%1, %%lo(%4), %1\n"
-	"	andn		%0, %1, %0\n"
-	"	.previous\n"
-	: "=r" (val), "=r" (tmp)
-	: "0" (val), "i" (_PAGE_MODIFIED_4U | _PAGE_W_4U),
-	  "i" (_PAGE_MODIFIED_4V | _PAGE_W_4V));
-
-	return __pte(val);
-}
-
-static inline pte_t pte_mkwrite(pte_t pte)
-{
-	unsigned long val = pte_val(pte), mask;
-
-	__asm__ __volatile__(
-	"\n661:	mov		%1, %0\n"
-	"	nop\n"
-	"	.section	.sun4v_2insn_patch, \"ax\"\n"
-	"	.word		661b\n"
-	"	sethi		%%uhi(%2), %0\n"
-	"	sllx		%0, 32, %0\n"
-	"	.previous\n"
-	: "=r" (mask)
-	: "i" (_PAGE_WRITE_4U), "i" (_PAGE_WRITE_4V));
-
-	return __pte(val | mask);
-}
-
-static inline pte_t pte_wrprotect(pte_t pte)
-{
-	unsigned long val = pte_val(pte), tmp;
-
-	__asm__ __volatile__(
-	"\n661:	andn		%0, %3, %0\n"
-	"	nop\n"
-	"\n662:	nop\n"
-	"	nop\n"
-	"	.section	.sun4v_2insn_patch, \"ax\"\n"
-	"	.word		661b\n"
-	"	sethi		%%uhi(%4), %1\n"
-	"	sllx		%1, 32, %1\n"
-	"	.word		662b\n"
-	"	or		%1, %%lo(%4), %1\n"
-	"	andn		%0, %1, %0\n"
-	"	.previous\n"
-	: "=r" (val), "=r" (tmp)
-	: "0" (val), "i" (_PAGE_WRITE_4U | _PAGE_W_4U),
-	  "i" (_PAGE_WRITE_4V | _PAGE_W_4V));
-
-	return __pte(val);
-}
-
-static inline pte_t pte_mkold(pte_t pte)
-{
-	unsigned long mask;
-
-	__asm__ __volatile__(
-	"\n661:	mov		%1, %0\n"
-	"	nop\n"
-	"	.section	.sun4v_2insn_patch, \"ax\"\n"
-	"	.word		661b\n"
-	"	sethi		%%uhi(%2), %0\n"
-	"	sllx		%0, 32, %0\n"
-	"	.previous\n"
-	: "=r" (mask)
-	: "i" (_PAGE_ACCESSED_4U), "i" (_PAGE_ACCESSED_4V));
-
-	mask |= _PAGE_R;
-
-	return __pte(pte_val(pte) & ~mask);
-}
-
-static inline pte_t pte_mkyoung(pte_t pte)
-{
-	unsigned long mask;
-
-	__asm__ __volatile__(
-	"\n661:	mov		%1, %0\n"
-	"	nop\n"
-	"	.section	.sun4v_2insn_patch, \"ax\"\n"
-	"	.word		661b\n"
-	"	sethi		%%uhi(%2), %0\n"
-	"	sllx		%0, 32, %0\n"
-	"	.previous\n"
-	: "=r" (mask)
-	: "i" (_PAGE_ACCESSED_4U), "i" (_PAGE_ACCESSED_4V));
-
-	mask |= _PAGE_R;
-
-	return __pte(pte_val(pte) | mask);
-}
-
-static inline pte_t pte_mkspecial(pte_t pte)
-{
-	return pte;
-}
-
-static inline unsigned long pte_young(pte_t pte)
-{
-	unsigned long mask;
-
-	__asm__ __volatile__(
-	"\n661:	mov		%1, %0\n"
-	"	nop\n"
-	"	.section	.sun4v_2insn_patch, \"ax\"\n"
-	"	.word		661b\n"
-	"	sethi		%%uhi(%2), %0\n"
-	"	sllx		%0, 32, %0\n"
-	"	.previous\n"
-	: "=r" (mask)
-	: "i" (_PAGE_ACCESSED_4U), "i" (_PAGE_ACCESSED_4V));
-
-	return (pte_val(pte) & mask);
-}
-
-static inline unsigned long pte_dirty(pte_t pte)
-{
-	unsigned long mask;
-
-	__asm__ __volatile__(
-	"\n661:	mov		%1, %0\n"
-	"	nop\n"
-	"	.section	.sun4v_2insn_patch, \"ax\"\n"
-	"	.word		661b\n"
-	"	sethi		%%uhi(%2), %0\n"
-	"	sllx		%0, 32, %0\n"
-	"	.previous\n"
-	: "=r" (mask)
-	: "i" (_PAGE_MODIFIED_4U), "i" (_PAGE_MODIFIED_4V));
-
-	return (pte_val(pte) & mask);
-}
-
-static inline unsigned long pte_write(pte_t pte)
-{
-	unsigned long mask;
-
-	__asm__ __volatile__(
-	"\n661:	mov		%1, %0\n"
-	"	nop\n"
-	"	.section	.sun4v_2insn_patch, \"ax\"\n"
-	"	.word		661b\n"
-	"	sethi		%%uhi(%2), %0\n"
-	"	sllx		%0, 32, %0\n"
-	"	.previous\n"
-	: "=r" (mask)
-	: "i" (_PAGE_WRITE_4U), "i" (_PAGE_WRITE_4V));
-
-	return (pte_val(pte) & mask);
-}
-
-static inline unsigned long pte_exec(pte_t pte)
-{
-	unsigned long mask;
-
-	__asm__ __volatile__(
-	"\n661:	sethi		%%hi(%1), %0\n"
-	"	.section	.sun4v_1insn_patch, \"ax\"\n"
-	"	.word		661b\n"
-	"	mov		%2, %0\n"
-	"	.previous\n"
-	: "=r" (mask)
-	: "i" (_PAGE_EXEC_4U), "i" (_PAGE_EXEC_4V));
-
-	return (pte_val(pte) & mask);
-}
-
-static inline unsigned long pte_file(pte_t pte)
-{
-	unsigned long val = pte_val(pte);
-
-	__asm__ __volatile__(
-	"\n661:	and		%0, %2, %0\n"
-	"	.section	.sun4v_1insn_patch, \"ax\"\n"
-	"	.word		661b\n"
-	"	and		%0, %3, %0\n"
-	"	.previous\n"
-	: "=r" (val)
-	: "0" (val), "i" (_PAGE_FILE_4U), "i" (_PAGE_FILE_4V));
-
-	return val;
-}
-
-static inline unsigned long pte_present(pte_t pte)
-{
-	unsigned long val = pte_val(pte);
-
-	__asm__ __volatile__(
-	"\n661:	and		%0, %2, %0\n"
-	"	.section	.sun4v_1insn_patch, \"ax\"\n"
-	"	.word		661b\n"
-	"	and		%0, %3, %0\n"
-	"	.previous\n"
-	: "=r" (val)
-	: "0" (val), "i" (_PAGE_PRESENT_4U), "i" (_PAGE_PRESENT_4V));
-
-	return val;
-}
-
-static inline int pte_special(pte_t pte)
-{
-	return 0;
-}
-
-#define pmd_set(pmdp, ptep)	\
-	(pmd_val(*(pmdp)) = (__pa((unsigned long) (ptep)) >> 11UL))
-#define pud_set(pudp, pmdp)	\
-	(pud_val(*(pudp)) = (__pa((unsigned long) (pmdp)) >> 11UL))
-#define __pmd_page(pmd)		\
-	((unsigned long) __va((((unsigned long)pmd_val(pmd))<<11UL)))
-#define pmd_page(pmd) 			virt_to_page((void *)__pmd_page(pmd))
-#define pud_page_vaddr(pud)		\
-	((unsigned long) __va((((unsigned long)pud_val(pud))<<11UL)))
-#define pud_page(pud) 			virt_to_page((void *)pud_page_vaddr(pud))
-#define pmd_none(pmd)			(!pmd_val(pmd))
-#define pmd_bad(pmd)			(0)
-#define pmd_present(pmd)		(pmd_val(pmd) != 0U)
-#define pmd_clear(pmdp)			(pmd_val(*(pmdp)) = 0U)
-#define pud_none(pud)			(!pud_val(pud))
-#define pud_bad(pud)			(0)
-#define pud_present(pud)		(pud_val(pud) != 0U)
-#define pud_clear(pudp)			(pud_val(*(pudp)) = 0U)
-
-/* Same in both SUN4V and SUN4U.  */
-#define pte_none(pte) 			(!pte_val(pte))
-
-/* to find an entry in a page-table-directory. */
-#define pgd_index(address)	(((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
-#define pgd_offset(mm, address)	((mm)->pgd + pgd_index(address))
-
-/* to find an entry in a kernel page-table-directory */
-#define pgd_offset_k(address) pgd_offset(&init_mm, address)
-
-/* Find an entry in the second-level page table.. */
-#define pmd_offset(pudp, address)	\
-	((pmd_t *) pud_page_vaddr(*(pudp)) + \
-	 (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)))
-
-/* Find an entry in the third-level page table.. */
-#define pte_index(dir, address)	\
-	((pte_t *) __pmd_page(*(dir)) + \
-	 ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
-#define pte_offset_kernel		pte_index
-#define pte_offset_map			pte_index
-#define pte_offset_map_nested		pte_index
-#define pte_unmap(pte)			do { } while (0)
-#define pte_unmap_nested(pte)		do { } while (0)
-
-/* Actual page table PTE updates.  */
-extern void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t orig);
-
-static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte)
-{
-	pte_t orig = *ptep;
-
-	*ptep = pte;
-
-	/* It is more efficient to let flush_tlb_kernel_range()
-	 * handle init_mm tlb flushes.
-	 *
-	 * SUN4V NOTE: _PAGE_VALID is the same value in both the SUN4U
-	 *             and SUN4V pte layout, so this inline test is fine.
-	 */
-	if (likely(mm != &init_mm) && (pte_val(orig) & _PAGE_VALID))
-		tlb_batch_add(mm, addr, ptep, orig);
-}
-
-#define pte_clear(mm,addr,ptep)		\
-	set_pte_at((mm), (addr), (ptep), __pte(0UL))
-
-#ifdef DCACHE_ALIASING_POSSIBLE
-#define __HAVE_ARCH_MOVE_PTE
-#define move_pte(pte, prot, old_addr, new_addr)				\
-({									\
- 	pte_t newpte = (pte);						\
-	if (tlb_type != hypervisor && pte_present(pte)) {		\
-		unsigned long this_pfn = pte_pfn(pte);			\
-									\
-		if (pfn_valid(this_pfn) &&				\
-		    (((old_addr) ^ (new_addr)) & (1 << 13)))		\
-			flush_dcache_page_all(current->mm,		\
-					      pfn_to_page(this_pfn));	\
-	}								\
-	newpte;								\
-})
-#endif
-
-extern pgd_t swapper_pg_dir[2048];
-extern pmd_t swapper_low_pmd_dir[2048];
-
-extern void paging_init(void);
-extern unsigned long find_ecache_flush_span(unsigned long size);
-
-/* These do nothing with the way I have things setup. */
-#define mmu_lockarea(vaddr, len)		(vaddr)
-#define mmu_unlockarea(vaddr, len)		do { } while(0)
-
-struct vm_area_struct;
-extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
-
-/* Encode and de-code a swap entry */
-#define __swp_type(entry)	(((entry).val >> PAGE_SHIFT) & 0xffUL)
-#define __swp_offset(entry)	((entry).val >> (PAGE_SHIFT + 8UL))
-#define __swp_entry(type, offset)	\
-	( (swp_entry_t) \
-	  { \
-		(((long)(type) << PAGE_SHIFT) | \
-                 ((long)(offset) << (PAGE_SHIFT + 8UL))) \
-	  } )
-#define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
-#define __swp_entry_to_pte(x)		((pte_t) { (x).val })
-
-/* File offset in PTE support. */
-extern unsigned long pte_file(pte_t);
-#define pte_to_pgoff(pte)	(pte_val(pte) >> PAGE_SHIFT)
-extern pte_t pgoff_to_pte(unsigned long);
-#define PTE_FILE_MAX_BITS	(64UL - PAGE_SHIFT - 1UL)
-
-extern unsigned long *sparc64_valid_addr_bitmap;
-
-/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
-#define kern_addr_valid(addr)	\
-	(test_bit(__pa((unsigned long)(addr))>>22, sparc64_valid_addr_bitmap))
-
-extern int page_in_phys_avail(unsigned long paddr);
-
-extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
-			       unsigned long pfn,
-			       unsigned long size, pgprot_t prot);
-
-/*
- * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
- * its high 4 bits.  These macros/functions put it there or get it from there.
- */
-#define MK_IOSPACE_PFN(space, pfn)	(pfn | (space << (BITS_PER_LONG - 4)))
-#define GET_IOSPACE(pfn)		(pfn >> (BITS_PER_LONG - 4))
-#define GET_PFN(pfn)			(pfn & 0x0fffffffffffffffUL)
-
-#include <asm-generic/pgtable.h>
-
-/* We provide our own get_unmapped_area to cope with VA holes and
- * SHM area cache aliasing for userland.
- */
-#define HAVE_ARCH_UNMAPPED_AREA
-#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
-
-/* We provide a special get_unmapped_area for framebuffer mmaps to try and use
- * the largest alignment possible such that larget PTEs can be used.
- */
-extern unsigned long get_fb_unmapped_area(struct file *filp, unsigned long,
-					  unsigned long, unsigned long,
-					  unsigned long);
-#define HAVE_ARCH_FB_UNMAPPED_AREA
-
-extern void pgtable_cache_init(void);
-extern void sun4v_register_fault_status(void);
-extern void sun4v_ktsb_register(void);
-extern void __init cheetah_ecache_flush_init(void);
-extern void sun4v_patch_tlb_handlers(void);
-
-extern unsigned long cmdline_memory_size;
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(_SPARC64_PGTABLE_H) */
+#include <asm-sparc/pgtable.h>
diff --git a/include/asm-sparc64/pil.h b/include/asm-sparc64/pil.h
index eaac842..d805f33 100644
--- a/include/asm-sparc64/pil.h
+++ b/include/asm-sparc64/pil.h
@@ -1,21 +1 @@
-#ifndef _SPARC64_PIL_H
-#define _SPARC64_PIL_H
-
-/* To avoid some locking problems, we hard allocate certain PILs
- * for SMP cross call messages that must do a etrap/rtrap.
- *
- * A local_irq_disable() does not block the cross call delivery, so
- * when SMP locking is an issue we reschedule the event into a PIL
- * interrupt which is blocked by local_irq_disable().
- *
- * In fact any XCALL which has to etrap/rtrap has a problem because
- * it is difficult to prevent rtrap from running BH's, and that would
- * need to be done if the XCALL arrived while %pil==15.
- */
-#define PIL_SMP_CALL_FUNC	1
-#define PIL_SMP_RECEIVE_SIGNAL	2
-#define PIL_SMP_CAPTURE		3
-#define PIL_SMP_CTX_NEW_VERSION	4
-#define PIL_DEVICE_IRQ		5
-
-#endif /* !(_SPARC64_PIL_H) */
+#include <asm-sparc/pil.h>
diff --git a/include/asm-sparc64/poll.h b/include/asm-sparc64/poll.h
index ebeeb38..8e2f31b 100644
--- a/include/asm-sparc64/poll.h
+++ b/include/asm-sparc64/poll.h
@@ -1,12 +1 @@
-#ifndef __SPARC64_POLL_H
-#define __SPARC64_POLL_H
-
-#define POLLWRNORM	POLLOUT
-#define POLLWRBAND	256
-#define POLLMSG		512
-#define POLLREMOVE	1024
-#define POLLRDHUP       2048
-
-#include <asm-generic/poll.h>
-
-#endif
+#include <asm-sparc/poll.h>
diff --git a/include/asm-sparc64/posix_types.h b/include/asm-sparc64/posix_types.h
index 4eaaa01..8cee992 100644
--- a/include/asm-sparc64/posix_types.h
+++ b/include/asm-sparc64/posix_types.h
@@ -1,122 +1 @@
-#ifndef __ARCH_SPARC64_POSIX_TYPES_H
-#define __ARCH_SPARC64_POSIX_TYPES_H
-
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc.  Also, we cannot
- * assume GCC is being used.
- */
-
-typedef unsigned long          __kernel_size_t;
-typedef long                   __kernel_ssize_t;
-typedef long                   __kernel_ptrdiff_t;
-typedef long                   __kernel_time_t;
-typedef long                   __kernel_clock_t;
-typedef int                    __kernel_pid_t;
-typedef int                    __kernel_ipc_pid_t;
-typedef unsigned int           __kernel_uid_t;
-typedef unsigned int           __kernel_gid_t;
-typedef unsigned long          __kernel_ino_t;
-typedef unsigned int           __kernel_mode_t;
-typedef unsigned short         __kernel_umode_t;
-typedef unsigned int           __kernel_nlink_t;
-typedef int                    __kernel_daddr_t;
-typedef long                   __kernel_off_t;
-typedef char *                 __kernel_caddr_t;
-typedef unsigned short	       __kernel_uid16_t;
-typedef unsigned short	       __kernel_gid16_t;
-typedef int                    __kernel_clockid_t;
-typedef int                    __kernel_timer_t;
-
-typedef unsigned short 	       __kernel_old_uid_t;
-typedef unsigned short         __kernel_old_gid_t;
-typedef __kernel_uid_t	       __kernel_uid32_t;
-typedef __kernel_gid_t	       __kernel_gid32_t;
-
-typedef unsigned int	       __kernel_old_dev_t;
-
-/* Note this piece of asymmetry from the v9 ABI.  */
-typedef int		       __kernel_suseconds_t;
-
-#ifdef __GNUC__
-typedef long long              __kernel_loff_t;
-#endif
-
-typedef struct {
-	int	val[2];
-} __kernel_fsid_t;
-
-#if defined(__KERNEL__)
-
-#undef __FD_SET
-static inline void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
-{
-	unsigned long _tmp = fd / __NFDBITS;
-	unsigned long _rem = fd % __NFDBITS;
-	fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
-}
-
-#undef __FD_CLR
-static inline void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
-{
-	unsigned long _tmp = fd / __NFDBITS;
-	unsigned long _rem = fd % __NFDBITS;
-	fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
-}
-
-#undef __FD_ISSET
-static inline int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
-{ 
-	unsigned long _tmp = fd / __NFDBITS;
-	unsigned long _rem = fd % __NFDBITS;
-	return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
-}
-
-/*
- * This will unroll the loop for the normal constant cases (8 or 32 longs,
- * for 256 and 1024-bit fd_sets respectively)
- */
-#undef __FD_ZERO
-static inline void __FD_ZERO(__kernel_fd_set *p)
-{
-	unsigned long *tmp = p->fds_bits;
-	int i;
-
-	if (__builtin_constant_p(__FDSET_LONGS)) {
-		switch (__FDSET_LONGS) {
-			case 32:
-			  tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
-			  tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
-			  tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
-			  tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
-			  tmp[16] = 0; tmp[17] = 0; tmp[18] = 0; tmp[19] = 0;
-			  tmp[20] = 0; tmp[21] = 0; tmp[22] = 0; tmp[23] = 0;
-			  tmp[24] = 0; tmp[25] = 0; tmp[26] = 0; tmp[27] = 0;
-			  tmp[28] = 0; tmp[29] = 0; tmp[30] = 0; tmp[31] = 0;
-			  return;
-			case 16:
-			  tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
-			  tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
-			  tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
-			  tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
-			  return;
-			case 8:
-			  tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
-			  tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
-			  return;
-			case 4:
-			  tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
-			  return;
-		}
-	}
-	i = __FDSET_LONGS;
-	while (i) {
-		i--;
-		*tmp = 0;
-		tmp++;
-	}
-}
-
-#endif /* defined(__KERNEL__) */
-
-#endif /* !(__ARCH_SPARC64_POSIX_TYPES_H) */
+#include <asm-sparc/posix_types.h>
diff --git a/include/asm-sparc64/processor.h b/include/asm-sparc64/processor.h
index 26b4e52..21de6cc 100644
--- a/include/asm-sparc64/processor.h
+++ b/include/asm-sparc64/processor.h
@@ -1,237 +1 @@
-/*
- * include/asm-sparc64/processor.h
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef __ASM_SPARC64_PROCESSOR_H
-#define __ASM_SPARC64_PROCESSOR_H
-
-/*
- * Sparc64 implementation of macro that returns current
- * instruction pointer ("program counter").
- */
-#define current_text_addr() ({ void *pc; __asm__("rd %%pc, %0" : "=r" (pc)); pc; })
-
-#include <asm/asi.h>
-#include <asm/pstate.h>
-#include <asm/ptrace.h>
-#include <asm/page.h>
-
-/* The sparc has no problems with write protection */
-#define wp_works_ok 1
-#define wp_works_ok__is_a_macro /* for versions in ksyms.c */
-
-/*
- * User lives in his very own context, and cannot reference us. Note
- * that TASK_SIZE is a misnomer, it really gives maximum user virtual 
- * address that the kernel will allocate out.
- *
- * XXX No longer using virtual page tables, kill this upper limit...
- */
-#define VA_BITS		44
-#ifndef __ASSEMBLY__
-#define VPTE_SIZE	(1UL << (VA_BITS - PAGE_SHIFT + 3))
-#else
-#define VPTE_SIZE	(1 << (VA_BITS - PAGE_SHIFT + 3))
-#endif
-
-#define TASK_SIZE	((unsigned long)-VPTE_SIZE)
-#define TASK_SIZE_OF(tsk) \
-	(test_tsk_thread_flag(tsk,TIF_32BIT) ? \
-	 (1UL << 32UL) : TASK_SIZE)
-#ifdef __KERNEL__
-
-#define STACK_TOP32	((1UL << 32UL) - PAGE_SIZE)
-#define STACK_TOP64	(0x0000080000000000UL - (1UL << 32UL))
-
-#define STACK_TOP	(test_thread_flag(TIF_32BIT) ? \
-			 STACK_TOP32 : STACK_TOP64)
-
-#define STACK_TOP_MAX	STACK_TOP64
-
-#endif
-
-#ifndef __ASSEMBLY__
-
-typedef struct {
-	unsigned char seg;
-} mm_segment_t;
-
-/* The Sparc processor specific thread struct. */
-/* XXX This should die, everything can go into thread_info now. */
-struct thread_struct {
-#ifdef CONFIG_DEBUG_SPINLOCK
-	/* How many spinlocks held by this thread.
-	 * Used with spin lock debugging to catch tasks
-	 * sleeping illegally with locks held.
-	 */
-	int smp_lock_count;
-	unsigned int smp_lock_pc;
-#else
-	int dummy; /* f'in gcc bug... */
-#endif
-};
-
-#endif /* !(__ASSEMBLY__) */
-
-#ifndef CONFIG_DEBUG_SPINLOCK
-#define INIT_THREAD  {			\
-	0,				\
-}
-#else /* CONFIG_DEBUG_SPINLOCK */
-#define INIT_THREAD  {					\
-/* smp_lock_count, smp_lock_pc, */			\
-   0,		   0,					\
-}
-#endif /* !(CONFIG_DEBUG_SPINLOCK) */
-
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-
-/* Return saved PC of a blocked thread. */
-struct task_struct;
-extern unsigned long thread_saved_pc(struct task_struct *);
-
-/* On Uniprocessor, even in RMO processes see TSO semantics */
-#ifdef CONFIG_SMP
-#define TSTATE_INITIAL_MM	TSTATE_TSO
-#else
-#define TSTATE_INITIAL_MM	TSTATE_RMO
-#endif
-
-/* Do necessary setup to start up a newly executed thread. */
-#define start_thread(regs, pc, sp) \
-do { \
-	unsigned long __asi = ASI_PNF; \
-	regs->tstate = (regs->tstate & (TSTATE_CWP)) | (TSTATE_INITIAL_MM|TSTATE_IE) | (__asi << 24UL); \
-	regs->tpc = ((pc & (~3)) - 4); \
-	regs->tnpc = regs->tpc + 4; \
-	regs->y = 0; \
-	set_thread_wstate(1 << 3); \
-	if (current_thread_info()->utraps) { \
-		if (*(current_thread_info()->utraps) < 2) \
-			kfree(current_thread_info()->utraps); \
-		else \
-			(*(current_thread_info()->utraps))--; \
-		current_thread_info()->utraps = NULL; \
-	} \
-	__asm__ __volatile__( \
-	"stx		%%g0, [%0 + %2 + 0x00]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x08]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x10]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x18]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x20]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x28]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x30]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x38]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x40]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x48]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x50]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x58]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x60]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x68]\n\t" \
-	"stx		%1,   [%0 + %2 + 0x70]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x78]\n\t" \
-	"wrpr		%%g0, (1 << 3), %%wstate\n\t" \
-	: \
-	: "r" (regs), "r" (sp - sizeof(struct reg_window) - STACK_BIAS), \
-	  "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \
-} while (0)
-
-#define start_thread32(regs, pc, sp) \
-do { \
-	unsigned long __asi = ASI_PNF; \
-	pc &= 0x00000000ffffffffUL; \
-	sp &= 0x00000000ffffffffUL; \
-	regs->tstate = (regs->tstate & (TSTATE_CWP))|(TSTATE_INITIAL_MM|TSTATE_IE|TSTATE_AM) | (__asi << 24UL); \
-	regs->tpc = ((pc & (~3)) - 4); \
-	regs->tnpc = regs->tpc + 4; \
-	regs->y = 0; \
-	set_thread_wstate(2 << 3); \
-	if (current_thread_info()->utraps) { \
-		if (*(current_thread_info()->utraps) < 2) \
-			kfree(current_thread_info()->utraps); \
-		else \
-			(*(current_thread_info()->utraps))--; \
-		current_thread_info()->utraps = NULL; \
-	} \
-	__asm__ __volatile__( \
-	"stx		%%g0, [%0 + %2 + 0x00]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x08]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x10]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x18]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x20]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x28]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x30]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x38]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x40]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x48]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x50]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x58]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x60]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x68]\n\t" \
-	"stx		%1,   [%0 + %2 + 0x70]\n\t" \
-	"stx		%%g0, [%0 + %2 + 0x78]\n\t" \
-	"wrpr		%%g0, (2 << 3), %%wstate\n\t" \
-	: \
-	: "r" (regs), "r" (sp - sizeof(struct reg_window32)), \
-	  "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \
-} while (0)
-
-/* Free all resources held by a thread. */
-#define release_thread(tsk)		do { } while (0)
-
-/* Prepare to copy thread state - unlazy all lazy status */
-#define prepare_to_copy(tsk)	do { } while (0)
-
-extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
-extern unsigned long get_wchan(struct task_struct *task);
-
-#define task_pt_regs(tsk) (task_thread_info(tsk)->kregs)
-#define KSTK_EIP(tsk)  (task_pt_regs(tsk)->tpc)
-#define KSTK_ESP(tsk)  (task_pt_regs(tsk)->u_regs[UREG_FP])
-
-#define cpu_relax()	barrier()
-
-/* Prefetch support.  This is tuned for UltraSPARC-III and later.
- * UltraSPARC-I will treat these as nops, and UltraSPARC-II has
- * a shallower prefetch queue than later chips.
- */
-#define ARCH_HAS_PREFETCH
-#define ARCH_HAS_PREFETCHW
-#define ARCH_HAS_SPINLOCK_PREFETCH
-
-static inline void prefetch(const void *x)
-{
-	/* We do not use the read prefetch mnemonic because that
-	 * prefetches into the prefetch-cache which only is accessible
-	 * by floating point operations in UltraSPARC-III and later.
-	 * By contrast, "#one_write" prefetches into the L2 cache
-	 * in shared state.
-	 */
-	__asm__ __volatile__("prefetch [%0], #one_write"
-			     : /* no outputs */
-			     : "r" (x));
-}
-
-static inline void prefetchw(const void *x)
-{
-	/* The most optimal prefetch to use for writes is
-	 * "#n_writes".  This brings the cacheline into the
-	 * L2 cache in "owned" state.
-	 */
-	__asm__ __volatile__("prefetch [%0], #n_writes"
-			     : /* no outputs */
-			     : "r" (x));
-}
-
-#define spin_lock_prefetch(x)	prefetchw(x)
-
-#define HAVE_ARCH_PICK_MMAP_LAYOUT
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(__ASM_SPARC64_PROCESSOR_H) */
+#include <asm-sparc/processor.h>
diff --git a/include/asm-sparc64/psrcompat.h b/include/asm-sparc64/psrcompat.h
index 44b6327..587846f 100644
--- a/include/asm-sparc64/psrcompat.h
+++ b/include/asm-sparc64/psrcompat.h
@@ -1,45 +1 @@
-#ifndef _SPARC64_PSRCOMPAT_H
-#define _SPARC64_PSRCOMPAT_H
-
-#include <asm/pstate.h>
-
-/* Old 32-bit PSR fields for the compatibility conversion code. */
-#define PSR_CWP     0x0000001f         /* current window pointer     */
-#define PSR_ET      0x00000020         /* enable traps field         */
-#define PSR_PS      0x00000040         /* previous privilege level   */
-#define PSR_S       0x00000080         /* current privilege level    */
-#define PSR_PIL     0x00000f00         /* processor interrupt level  */
-#define PSR_EF      0x00001000         /* enable floating point      */
-#define PSR_EC      0x00002000         /* enable co-processor        */
-#define PSR_SYSCALL 0x00004000         /* inside of a syscall        */
-#define PSR_LE      0x00008000         /* SuperSparcII little-endian */
-#define PSR_ICC     0x00f00000         /* integer condition codes    */
-#define PSR_C       0x00100000         /* carry bit                  */
-#define PSR_V       0x00200000         /* overflow bit               */
-#define PSR_Z       0x00400000         /* zero bit                   */
-#define PSR_N       0x00800000         /* negative bit               */
-#define PSR_VERS    0x0f000000         /* cpu-version field          */
-#define PSR_IMPL    0xf0000000         /* cpu-implementation field   */
-
-#define PSR_V8PLUS  0xff000000         /* fake impl/ver, meaning a 64bit CPU is present */
-#define PSR_XCC	    0x000f0000         /* if PSR_V8PLUS, this is %xcc */
-
-static inline unsigned int tstate_to_psr(unsigned long tstate)
-{
-	return ((tstate & TSTATE_CWP)			|
-		PSR_S					|
-		((tstate & TSTATE_ICC) >> 12)		|
-		((tstate & TSTATE_XCC) >> 20)		|
-		((tstate & TSTATE_SYSCALL) ? PSR_SYSCALL : 0) |
-		PSR_V8PLUS);
-}
-
-static inline unsigned long psr_to_tstate_icc(unsigned int psr)
-{
-	unsigned long tstate = ((unsigned long)(psr & PSR_ICC)) << 12;
-	if ((psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS)
-		tstate |= ((unsigned long)(psr & PSR_XCC)) << 20;
-	return tstate;
-}
-
-#endif /* !(_SPARC64_PSRCOMPAT_H) */
+#include <asm-sparc/psrcompat.h>
diff --git a/include/asm-sparc64/pstate.h b/include/asm-sparc64/pstate.h
index a26a537..3ccf0be 100644
--- a/include/asm-sparc64/pstate.h
+++ b/include/asm-sparc64/pstate.h
@@ -1,91 +1 @@
-#ifndef _SPARC64_PSTATE_H
-#define _SPARC64_PSTATE_H
-
-#include <linux/const.h>
-
-/* The V9 PSTATE Register (with SpitFire extensions).
- *
- * -----------------------------------------------------------------------
- * | Resv | IG | MG | CLE | TLE |  MM  | RED | PEF | AM | PRIV | IE | AG |
- * -----------------------------------------------------------------------
- *  63  12  11   10    9     8    7   6   5     4     3     2     1    0
- */
-#define PSTATE_IG   _AC(0x0000000000000800,UL) /* Interrupt Globals.	*/
-#define PSTATE_MG   _AC(0x0000000000000400,UL) /* MMU Globals.		*/
-#define PSTATE_CLE  _AC(0x0000000000000200,UL) /* Current Little Endian.*/
-#define PSTATE_TLE  _AC(0x0000000000000100,UL) /* Trap Little Endian.	*/
-#define PSTATE_MM   _AC(0x00000000000000c0,UL) /* Memory Model.		*/
-#define PSTATE_TSO  _AC(0x0000000000000000,UL) /* MM: TotalStoreOrder	*/
-#define PSTATE_PSO  _AC(0x0000000000000040,UL) /* MM: PartialStoreOrder	*/
-#define PSTATE_RMO  _AC(0x0000000000000080,UL) /* MM: RelaxedMemoryOrder*/
-#define PSTATE_RED  _AC(0x0000000000000020,UL) /* Reset Error Debug.	*/
-#define PSTATE_PEF  _AC(0x0000000000000010,UL) /* Floating Point Enable.*/
-#define PSTATE_AM   _AC(0x0000000000000008,UL) /* Address Mask.		*/
-#define PSTATE_PRIV _AC(0x0000000000000004,UL) /* Privilege.		*/
-#define PSTATE_IE   _AC(0x0000000000000002,UL) /* Interrupt Enable.	*/
-#define PSTATE_AG   _AC(0x0000000000000001,UL) /* Alternate Globals.	*/
-
-/* The V9 TSTATE Register (with SpitFire and Linux extensions).
- *
- * ---------------------------------------------------------------------
- * |  Resv |  GL  |  CCR  |  ASI  |  %pil  |  PSTATE  |  Resv  |  CWP  |
- * ---------------------------------------------------------------------
- *  63   43 42  40 39   32 31   24 23    20 19       8 7      5 4     0
- */
-#define TSTATE_GL	_AC(0x0000070000000000,UL) /* Global reg level  */
-#define TSTATE_CCR	_AC(0x000000ff00000000,UL) /* Condition Codes.	*/
-#define TSTATE_XCC	_AC(0x000000f000000000,UL) /* Condition Codes.	*/
-#define TSTATE_XNEG	_AC(0x0000008000000000,UL) /* %xcc Negative.	*/
-#define TSTATE_XZERO	_AC(0x0000004000000000,UL) /* %xcc Zero.	*/
-#define TSTATE_XOVFL	_AC(0x0000002000000000,UL) /* %xcc Overflow.	*/
-#define TSTATE_XCARRY	_AC(0x0000001000000000,UL) /* %xcc Carry.	*/
-#define TSTATE_ICC	_AC(0x0000000f00000000,UL) /* Condition Codes.	*/
-#define TSTATE_INEG	_AC(0x0000000800000000,UL) /* %icc Negative.	*/
-#define TSTATE_IZERO	_AC(0x0000000400000000,UL) /* %icc Zero.	*/
-#define TSTATE_IOVFL	_AC(0x0000000200000000,UL) /* %icc Overflow.	*/
-#define TSTATE_ICARRY	_AC(0x0000000100000000,UL) /* %icc Carry.	*/
-#define TSTATE_ASI	_AC(0x00000000ff000000,UL) /* AddrSpace ID.	*/
-#define TSTATE_PIL	_AC(0x0000000000f00000,UL) /* %pil (Linux traps)*/
-#define TSTATE_PSTATE	_AC(0x00000000000fff00,UL) /* PSTATE.		*/
-#define TSTATE_IG	_AC(0x0000000000080000,UL) /* Interrupt Globals.*/
-#define TSTATE_MG	_AC(0x0000000000040000,UL) /* MMU Globals.	*/
-#define TSTATE_CLE	_AC(0x0000000000020000,UL) /* CurrLittleEndian.	*/
-#define TSTATE_TLE	_AC(0x0000000000010000,UL) /* TrapLittleEndian.	*/
-#define TSTATE_MM	_AC(0x000000000000c000,UL) /* Memory Model.	*/
-#define TSTATE_TSO	_AC(0x0000000000000000,UL) /* MM: TSO		*/
-#define TSTATE_PSO	_AC(0x0000000000004000,UL) /* MM: PSO		*/
-#define TSTATE_RMO	_AC(0x0000000000008000,UL) /* MM: RMO		*/
-#define TSTATE_RED	_AC(0x0000000000002000,UL) /* Reset Error Debug.*/
-#define TSTATE_PEF	_AC(0x0000000000001000,UL) /* FPU Enable.	*/
-#define TSTATE_AM	_AC(0x0000000000000800,UL) /* Address Mask.	*/
-#define TSTATE_PRIV	_AC(0x0000000000000400,UL) /* Privilege.	*/
-#define TSTATE_IE	_AC(0x0000000000000200,UL) /* Interrupt Enable.	*/
-#define TSTATE_AG	_AC(0x0000000000000100,UL) /* Alternate Globals.*/
-#define TSTATE_SYSCALL	_AC(0x0000000000000020,UL) /* in syscall trap   */
-#define TSTATE_CWP	_AC(0x000000000000001f,UL) /* Curr Win-Pointer.	*/
-
-/* Floating-Point Registers State Register.
- *
- * --------------------------------
- * |  Resv  |  FEF  |  DU  |  DL  |
- * --------------------------------
- *  63     3    2       1      0
- */
-#define FPRS_FEF	_AC(0x0000000000000004,UL) /* FPU Enable.	*/
-#define FPRS_DU		_AC(0x0000000000000002,UL) /* Dirty Upper.	*/
-#define FPRS_DL		_AC(0x0000000000000001,UL) /* Dirty Lower.	*/
-
-/* Version Register.
- *
- * ------------------------------------------------------
- * | MANUF | IMPL | MASK | Resv | MAXTL | Resv | MAXWIN |
- * ------------------------------------------------------
- *  63   48 47  32 31  24 23  16 15    8 7    5 4      0
- */
-#define VERS_MANUF	_AC(0xffff000000000000,UL) /* Manufacturer.	*/
-#define VERS_IMPL	_AC(0x0000ffff00000000,UL) /* Implementation.	*/
-#define VERS_MASK	_AC(0x00000000ff000000,UL) /* Mask Set Revision.*/
-#define VERS_MAXTL	_AC(0x000000000000ff00,UL) /* Max Trap Level.	*/
-#define VERS_MAXWIN	_AC(0x000000000000001f,UL) /* Max RegWindow Idx.*/
-
-#endif /* !(_SPARC64_PSTATE_H) */
+#include <asm-sparc/pstate.h>
diff --git a/include/asm-sparc64/ptrace.h b/include/asm-sparc64/ptrace.h
index b163da7..1a55b9f 100644
--- a/include/asm-sparc64/ptrace.h
+++ b/include/asm-sparc64/ptrace.h
@@ -1,346 +1 @@
-#ifndef _SPARC64_PTRACE_H
-#define _SPARC64_PTRACE_H
-
-#include <asm/pstate.h>
-
-/* This struct defines the way the registers are stored on the 
- * stack during a system call and basically all traps.
- */
-
-/* This magic value must have the low 9 bits clear,
- * as that is where we encode the %tt value, see below.
- */
-#define PT_REGS_MAGIC 0x57ac6c00
-
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-
-struct pt_regs {
-	unsigned long u_regs[16]; /* globals and ins */
-	unsigned long tstate;
-	unsigned long tpc;
-	unsigned long tnpc;
-	unsigned int y;
-
-	/* We encode a magic number, PT_REGS_MAGIC, along
-	 * with the %tt (trap type) register value at trap
-	 * entry time.  The magic number allows us to identify
-	 * accurately a trap stack frame in the stack
-	 * unwinder, and the %tt value allows us to test
-	 * things like "in a system call" etc. for an arbitray
-	 * process.
-	 *
-	 * The PT_REGS_MAGIC is choosen such that it can be
-	 * loaded completely using just a sethi instruction.
-	 */
-	unsigned int magic;
-};
-
-static inline int pt_regs_trap_type(struct pt_regs *regs)
-{
-	return regs->magic & 0x1ff;
-}
-
-static inline bool pt_regs_is_syscall(struct pt_regs *regs)
-{
-	return (regs->tstate & TSTATE_SYSCALL);
-}
-
-static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
-{
-	return (regs->tstate &= ~TSTATE_SYSCALL);
-}
-
-struct pt_regs32 {
-	unsigned int psr;
-	unsigned int pc;
-	unsigned int npc;
-	unsigned int y;
-	unsigned int u_regs[16]; /* globals and ins */
-};
-
-#define UREG_G0        0
-#define UREG_G1        1
-#define UREG_G2        2
-#define UREG_G3        3
-#define UREG_G4        4
-#define UREG_G5        5
-#define UREG_G6        6
-#define UREG_G7        7
-#define UREG_I0        8
-#define UREG_I1        9
-#define UREG_I2        10
-#define UREG_I3        11
-#define UREG_I4        12
-#define UREG_I5        13
-#define UREG_I6        14
-#define UREG_I7        15
-#define UREG_FP        UREG_I6
-#define UREG_RETPC     UREG_I7
-
-/* A V9 register window */
-struct reg_window {
-	unsigned long locals[8];
-	unsigned long ins[8];
-};
-
-/* A 32-bit register window. */
-struct reg_window32 {
-	unsigned int locals[8];
-	unsigned int ins[8];
-};
-
-/* A V9 Sparc stack frame */
-struct sparc_stackf {
-	unsigned long locals[8];
-        unsigned long ins[6];
-	struct sparc_stackf *fp;
-	unsigned long callers_pc;
-	char *structptr;
-	unsigned long xargs[6];
-	unsigned long xxargs[1];
-};	
-
-/* A 32-bit Sparc stack frame */
-struct sparc_stackf32 {
-	unsigned int locals[8];
-        unsigned int ins[6];
-	unsigned int fp;
-	unsigned int callers_pc;
-	unsigned int structptr;
-	unsigned int xargs[6];
-	unsigned int xxargs[1];
-};	
-
-struct sparc_trapf {
-	unsigned long locals[8];
-	unsigned long ins[8];
-	unsigned long _unused;
-	struct pt_regs *regs;
-};
-
-#define TRACEREG_SZ	sizeof(struct pt_regs)
-#define STACKFRAME_SZ	sizeof(struct sparc_stackf)
-
-#define TRACEREG32_SZ	sizeof(struct pt_regs32)
-#define STACKFRAME32_SZ	sizeof(struct sparc_stackf32)
-
-#ifdef __KERNEL__
-
-struct global_reg_snapshot {
-	unsigned long		tstate;
-	unsigned long		tpc;
-	unsigned long		tnpc;
-	unsigned long		o7;
-	unsigned long		i7;
-	struct thread_info	*thread;
-	unsigned long		pad1;
-	unsigned long		pad2;
-};
-
-#define __ARCH_WANT_COMPAT_SYS_PTRACE
-
-#define force_successful_syscall_return()	    \
-do {	current_thread_info()->syscall_noerror = 1; \
-} while (0)
-#define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
-#define instruction_pointer(regs) ((regs)->tpc)
-#define regs_return_value(regs) ((regs)->u_regs[UREG_I0])
-#ifdef CONFIG_SMP
-extern unsigned long profile_pc(struct pt_regs *);
-#else
-#define profile_pc(regs) instruction_pointer(regs)
-#endif
-extern void show_regs(struct pt_regs *);
-extern void __show_regs(struct pt_regs *);
-#endif
-
-#else /* __ASSEMBLY__ */
-/* For assembly code. */
-#define TRACEREG_SZ		0xa0
-#define STACKFRAME_SZ		0xc0
-
-#define TRACEREG32_SZ		0x50
-#define STACKFRAME32_SZ		0x60
-#endif
-
-#ifdef __KERNEL__
-#define STACK_BIAS		2047
-#endif
-
-/* These are for pt_regs. */
-#define PT_V9_G0     0x00
-#define PT_V9_G1     0x08
-#define PT_V9_G2     0x10
-#define PT_V9_G3     0x18
-#define PT_V9_G4     0x20
-#define PT_V9_G5     0x28
-#define PT_V9_G6     0x30
-#define PT_V9_G7     0x38
-#define PT_V9_I0     0x40
-#define PT_V9_I1     0x48
-#define PT_V9_I2     0x50
-#define PT_V9_I3     0x58
-#define PT_V9_I4     0x60
-#define PT_V9_I5     0x68
-#define PT_V9_I6     0x70
-#define PT_V9_FP     PT_V9_I6
-#define PT_V9_I7     0x78
-#define PT_V9_TSTATE 0x80
-#define PT_V9_TPC    0x88
-#define PT_V9_TNPC   0x90
-#define PT_V9_Y      0x98
-#define PT_V9_MAGIC  0x9c
-#define PT_TSTATE	PT_V9_TSTATE
-#define PT_TPC		PT_V9_TPC
-#define PT_TNPC		PT_V9_TNPC
-
-/* These for pt_regs32. */
-#define PT_PSR    0x0
-#define PT_PC     0x4
-#define PT_NPC    0x8
-#define PT_Y      0xc
-#define PT_G0     0x10
-#define PT_WIM    PT_G0
-#define PT_G1     0x14
-#define PT_G2     0x18
-#define PT_G3     0x1c
-#define PT_G4     0x20
-#define PT_G5     0x24
-#define PT_G6     0x28
-#define PT_G7     0x2c
-#define PT_I0     0x30
-#define PT_I1     0x34
-#define PT_I2     0x38
-#define PT_I3     0x3c
-#define PT_I4     0x40
-#define PT_I5     0x44
-#define PT_I6     0x48
-#define PT_FP     PT_I6
-#define PT_I7     0x4c
-
-/* Reg_window offsets */
-#define RW_V9_L0     0x00
-#define RW_V9_L1     0x08
-#define RW_V9_L2     0x10
-#define RW_V9_L3     0x18
-#define RW_V9_L4     0x20
-#define RW_V9_L5     0x28
-#define RW_V9_L6     0x30
-#define RW_V9_L7     0x38
-#define RW_V9_I0     0x40
-#define RW_V9_I1     0x48
-#define RW_V9_I2     0x50
-#define RW_V9_I3     0x58
-#define RW_V9_I4     0x60
-#define RW_V9_I5     0x68
-#define RW_V9_I6     0x70
-#define RW_V9_I7     0x78
-
-#define RW_L0     0x00
-#define RW_L1     0x04
-#define RW_L2     0x08
-#define RW_L3     0x0c
-#define RW_L4     0x10
-#define RW_L5     0x14
-#define RW_L6     0x18
-#define RW_L7     0x1c
-#define RW_I0     0x20
-#define RW_I1     0x24
-#define RW_I2     0x28
-#define RW_I3     0x2c
-#define RW_I4     0x30
-#define RW_I5     0x34
-#define RW_I6     0x38
-#define RW_I7     0x3c
-
-/* Stack_frame offsets */
-#define SF_V9_L0     0x00
-#define SF_V9_L1     0x08
-#define SF_V9_L2     0x10
-#define SF_V9_L3     0x18
-#define SF_V9_L4     0x20
-#define SF_V9_L5     0x28
-#define SF_V9_L6     0x30
-#define SF_V9_L7     0x38
-#define SF_V9_I0     0x40
-#define SF_V9_I1     0x48
-#define SF_V9_I2     0x50
-#define SF_V9_I3     0x58
-#define SF_V9_I4     0x60
-#define SF_V9_I5     0x68
-#define SF_V9_FP     0x70
-#define SF_V9_PC     0x78
-#define SF_V9_RETP   0x80
-#define SF_V9_XARG0  0x88
-#define SF_V9_XARG1  0x90
-#define SF_V9_XARG2  0x98
-#define SF_V9_XARG3  0xa0
-#define SF_V9_XARG4  0xa8
-#define SF_V9_XARG5  0xb0
-#define SF_V9_XXARG  0xb8
-
-#define SF_L0     0x00
-#define SF_L1     0x04
-#define SF_L2     0x08
-#define SF_L3     0x0c
-#define SF_L4     0x10
-#define SF_L5     0x14
-#define SF_L6     0x18
-#define SF_L7     0x1c
-#define SF_I0     0x20
-#define SF_I1     0x24
-#define SF_I2     0x28
-#define SF_I3     0x2c
-#define SF_I4     0x30
-#define SF_I5     0x34
-#define SF_FP     0x38
-#define SF_PC     0x3c
-#define SF_RETP   0x40
-#define SF_XARG0  0x44
-#define SF_XARG1  0x48
-#define SF_XARG2  0x4c
-#define SF_XARG3  0x50
-#define SF_XARG4  0x54
-#define SF_XARG5  0x58
-#define SF_XXARG  0x5c
-
-#ifdef __KERNEL__
-
-/* global_reg_snapshot offsets */
-#define GR_SNAP_TSTATE	0x00
-#define GR_SNAP_TPC	0x08
-#define GR_SNAP_TNPC	0x10
-#define GR_SNAP_O7	0x18
-#define GR_SNAP_I7	0x20
-#define GR_SNAP_THREAD	0x28
-#define GR_SNAP_PAD1	0x30
-#define GR_SNAP_PAD2	0x38
-
-#endif  /*  __KERNEL__  */
-
-/* Stuff for the ptrace system call */
-#define PTRACE_SPARC_DETACH       11
-#define PTRACE_GETREGS            12
-#define PTRACE_SETREGS            13
-#define PTRACE_GETFPREGS          14
-#define PTRACE_SETFPREGS          15
-#define PTRACE_READDATA           16
-#define PTRACE_WRITEDATA          17
-#define PTRACE_READTEXT           18
-#define PTRACE_WRITETEXT          19
-#define PTRACE_GETFPAREGS         20
-#define PTRACE_SETFPAREGS         21
-
-/* There are for debugging 64-bit processes, either from a 32 or 64 bit
- * parent.  Thus their complements are for debugging 32-bit processes only.
- */
-
-#define PTRACE_GETREGS64	  22
-#define PTRACE_SETREGS64	  23
-/* PTRACE_SYSCALL is 24 */
-#define PTRACE_GETFPREGS64	  25
-#define PTRACE_SETFPREGS64	  26
-
-#endif /* !(_SPARC64_PTRACE_H) */
+#include <asm-sparc/ptrace.h>
diff --git a/include/asm-sparc64/reboot.h b/include/asm-sparc64/reboot.h
index 3f3f43f..0d72eb8 100644
--- a/include/asm-sparc64/reboot.h
+++ b/include/asm-sparc64/reboot.h
@@ -1,6 +1 @@
-#ifndef _SPARC64_REBOOT_H
-#define _SPARC64_REBOOT_H
-
-extern void machine_alt_power_off(void);
-
-#endif /* _SPARC64_REBOOT_H */
+#include <asm-sparc/reboot.h>
diff --git a/include/asm-sparc64/reg.h b/include/asm-sparc64/reg.h
index 77aa480..495bab2 100644
--- a/include/asm-sparc64/reg.h
+++ b/include/asm-sparc64/reg.h
@@ -1,56 +1 @@
-/*
- * linux/asm-sparc64/reg.h
- * Layout of the registers as expected by gdb on the Sparc
- * we should replace the user.h definitions with those in
- * this file, we don't even use the other 
- * -miguel
- *
- * The names of the structures, constants and aliases in this file
- * have the same names as the sunos ones, some programs rely on these
- * names (gdb for example).
- *
- */
-
-#ifndef __SPARC64_REG_H
-#define __SPARC64_REG_H
-
-struct regs {
-        unsigned long r_g1;
-        unsigned long r_g2;
-        unsigned long r_g3;
-        unsigned long r_g4;
-        unsigned long r_g5;
-        unsigned long r_g6;
-        unsigned long r_g7;
-        unsigned long r_o0;
-        unsigned long r_o1;
-        unsigned long r_o2;
-        unsigned long r_o3;
-        unsigned long r_o4;
-        unsigned long r_o5;
-        unsigned long r_o6;
-        unsigned long r_o7;
-        unsigned long __pad;
-        unsigned long r_tstate;
-        unsigned long r_tpc;
-        unsigned long r_tnpc;
-        unsigned int  r_y;
-        unsigned int  r_fprs;
-};
-
-#define FPU_REGS_TYPE unsigned int
-#define FPU_FSR_TYPE unsigned long
-
-struct fp_status {
-        unsigned long fpu_fr[32];
-        unsigned long Fpu_fsr;
-};
-
-struct fpu {
-	struct fp_status f_fpstatus;
-};
-
-#define fpu_regs  f_fpstatus.fpu_fr
-#define fpu_fsr   f_fpstatus.Fpu_fsr
-
-#endif /* __SPARC64_REG_H */
+#include <asm-sparc/reg.h>
diff --git a/include/asm-sparc64/resource.h b/include/asm-sparc64/resource.h
index 4f08fb5..46e3bc0 100644
--- a/include/asm-sparc64/resource.h
+++ b/include/asm-sparc64/resource.h
@@ -1,19 +1 @@
-/*
- * resource.h: Resource definitions.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef _SPARC64_RESOURCE_H
-#define _SPARC64_RESOURCE_H
-
-/*
- * These two resource limit IDs have a Sparc/Linux-specific ordering,
- * the rest comes from the generic header:
- */
-#define RLIMIT_NOFILE		6	/* max number of open files */
-#define RLIMIT_NPROC		7	/* max number of processes */
-
-#include <asm-generic/resource.h>
-
-#endif /* !(_SPARC64_RESOURCE_H) */
+#include <asm-sparc/resource.h>
diff --git a/include/asm-sparc64/rtc.h b/include/asm-sparc64/rtc.h
index f9ecb1f..e49a968 100644
--- a/include/asm-sparc64/rtc.h
+++ b/include/asm-sparc64/rtc.h
@@ -1,26 +1 @@
-/*
- * rtc.h: Definitions for access to the Mostek real time clock
- *
- * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu)
- */
-
-#ifndef _RTC_H
-#define _RTC_H
-
-#include <linux/ioctl.h>
-
-struct rtc_time
-{
-	int	sec;	/* Seconds (0-59) */
-	int	min;	/* Minutes (0-59) */
-	int	hour;	/* Hour (0-23) */
-	int	dow;	/* Day of the week (1-7) */
-	int	dom;	/* Day of the month (1-31) */
-	int	month;	/* Month of year (1-12) */
-	int	year;	/* Year (0-99) */
-};
-
-#define RTCGET _IOR('p', 20, struct rtc_time)
-#define RTCSET _IOW('p', 21, struct rtc_time)
-
-#endif
+#include <asm-sparc/rtc.h>
diff --git a/include/asm-sparc64/rwsem-const.h b/include/asm-sparc64/rwsem-const.h
index a303c9d..2a1de31 100644
--- a/include/asm-sparc64/rwsem-const.h
+++ b/include/asm-sparc64/rwsem-const.h
@@ -1,12 +1 @@
-/* rwsem-const.h: RW semaphore counter constants.  */
-#ifndef _SPARC64_RWSEM_CONST_H
-#define _SPARC64_RWSEM_CONST_H
-
-#define RWSEM_UNLOCKED_VALUE		0x00000000
-#define RWSEM_ACTIVE_BIAS		0x00000001
-#define RWSEM_ACTIVE_MASK		0x0000ffff
-#define RWSEM_WAITING_BIAS		0xffff0000
-#define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
-#define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
-
-#endif /* _SPARC64_RWSEM_CONST_H */
+#include <asm-sparc/rwsem-const.h>
diff --git a/include/asm-sparc64/rwsem.h b/include/asm-sparc64/rwsem.h
index 1dc129a..6943c56 100644
--- a/include/asm-sparc64/rwsem.h
+++ b/include/asm-sparc64/rwsem.h
@@ -1,84 +1 @@
-/*
- * rwsem.h: R/W semaphores implemented using CAS
- *
- * Written by David S. Miller (davem@redhat.com), 2001.
- * Derived from asm-i386/rwsem.h
- */
-#ifndef _SPARC64_RWSEM_H
-#define _SPARC64_RWSEM_H
-
-#ifndef _LINUX_RWSEM_H
-#error "please don't include asm/rwsem.h directly, use linux/rwsem.h instead"
-#endif
-
-#ifdef __KERNEL__
-
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <asm/rwsem-const.h>
-
-struct rwsem_waiter;
-
-struct rw_semaphore {
-	signed int count;
-	spinlock_t		wait_lock;
-	struct list_head	wait_list;
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-	struct lockdep_map	dep_map;
-#endif
-};
-
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
-#else
-# define __RWSEM_DEP_MAP_INIT(lockname)
-#endif
-
-#define __RWSEM_INITIALIZER(name) \
-{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, LIST_HEAD_INIT((name).wait_list) \
-  __RWSEM_DEP_MAP_INIT(name) }
-
-#define DECLARE_RWSEM(name) \
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
-
-extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
-			 struct lock_class_key *key);
-
-#define init_rwsem(sem)						\
-do {								\
-	static struct lock_class_key __key;			\
-								\
-	__init_rwsem((sem), #sem, &__key);			\
-} while (0)
-
-extern void __down_read(struct rw_semaphore *sem);
-extern int __down_read_trylock(struct rw_semaphore *sem);
-extern void __down_write(struct rw_semaphore *sem);
-extern int __down_write_trylock(struct rw_semaphore *sem);
-extern void __up_read(struct rw_semaphore *sem);
-extern void __up_write(struct rw_semaphore *sem);
-extern void __downgrade_write(struct rw_semaphore *sem);
-
-static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
-{
-	__down_write(sem);
-}
-
-static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
-{
-	return atomic_add_return(delta, (atomic_t *)(&sem->count));
-}
-
-static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
-{
-	atomic_add(delta, (atomic_t *)(&sem->count));
-}
-
-static inline int rwsem_is_locked(struct rw_semaphore *sem)
-{
-	return (sem->count != 0);
-}
-
-#endif /* __KERNEL__ */
-
-#endif /* _SPARC64_RWSEM_H */
+#include <asm-sparc/rwsem.h>
diff --git a/include/asm-sparc64/sbus.h b/include/asm-sparc64/sbus.h
index 24a04a5..0cab0e8 100644
--- a/include/asm-sparc64/sbus.h
+++ b/include/asm-sparc64/sbus.h
@@ -1,190 +1 @@
-/* sbus.h: Defines for the Sun SBus.
- *
- * Copyright (C) 1996, 1999, 2007 David S. Miller (davem@davemloft.net)
- */
-
-#ifndef _SPARC64_SBUS_H
-#define _SPARC64_SBUS_H
-
-#include <linux/dma-mapping.h>
-#include <linux/ioport.h>
-
-#include <asm/oplib.h>
-#include <asm/prom.h>
-#include <asm/of_device.h>
-#include <asm/iommu.h>
-#include <asm/scatterlist.h>
-
-/* We scan which devices are on the SBus using the PROM node device
- * tree.  SBus devices are described in two different ways.  You can
- * either get an absolute address at which to access the device, or
- * you can get a SBus 'slot' number and an offset within that slot.
- */
-
-/* The base address at which to calculate device OBIO addresses. */
-#define SUN_SBUS_BVADDR        0x00000000
-#define SBUS_OFF_MASK          0x0fffffff
-
-/* These routines are used to calculate device address from slot
- * numbers + offsets, and vice versa.
- */
-
-static inline unsigned long sbus_devaddr(int slotnum, unsigned long offset)
-{
-  return (unsigned long) (SUN_SBUS_BVADDR+((slotnum)<<28)+(offset));
-}
-
-static inline int sbus_dev_slot(unsigned long dev_addr)
-{
-  return (int) (((dev_addr)-SUN_SBUS_BVADDR)>>28);
-}
-
-struct sbus_bus;
-
-/* Linux SBUS device tables */
-struct sbus_dev {
-	struct of_device	ofdev;
-	struct sbus_bus		*bus;
-	struct sbus_dev		*next;
-	struct sbus_dev		*child;
-	struct sbus_dev		*parent;
-	int prom_node;	
-	char prom_name[64];
-	int slot;
-
-	struct resource resource[PROMREG_MAX];
-
-	struct linux_prom_registers reg_addrs[PROMREG_MAX];
-	int num_registers;
-
-	struct linux_prom_ranges device_ranges[PROMREG_MAX];
-	int num_device_ranges;
-
-	unsigned int irqs[4];
-	int num_irqs;
-};
-#define to_sbus_device(d) container_of(d, struct sbus_dev, ofdev.dev)
-
-/* This struct describes the SBus(s) found on this machine. */
-struct sbus_bus {
-	struct of_device	ofdev;
-	struct sbus_dev		*devices;	/* Tree of SBUS devices	*/
-	struct sbus_bus		*next;		/* Next SBUS in system	*/
-	int			prom_node;      /* OBP node of SBUS	*/
-	char			prom_name[64];	/* Usually "sbus" or "sbi" */
-	int			clock_freq;
-
-	struct linux_prom_ranges sbus_ranges[PROMREG_MAX];
-	int num_sbus_ranges;
-
-	int portid;
-};
-#define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev)
-
-extern struct sbus_bus *sbus_root;
-
-/* Device probing routines could find these handy */
-#define for_each_sbus(bus) \
-        for((bus) = sbus_root; (bus); (bus)=(bus)->next)
-
-#define for_each_sbusdev(device, bus) \
-        for((device) = (bus)->devices; (device); (device)=(device)->next)
-        
-#define for_all_sbusdev(device, bus) \
-	for ((bus) = sbus_root; (bus); (bus) = (bus)->next) \
-		for ((device) = (bus)->devices; (device); (device) = (device)->next)
-
-/* Driver DVMA interfaces. */
-#define sbus_can_dma_64bit(sdev)	(1)
-#define sbus_can_burst64(sdev)		(1)
-extern void sbus_set_sbus64(struct sbus_dev *, int);
-extern void sbus_fill_device_irq(struct sbus_dev *);
-
-static inline void *sbus_alloc_consistent(struct sbus_dev *sdev , size_t size,
-					  dma_addr_t *dma_handle)
-{
-	return dma_alloc_coherent(&sdev->ofdev.dev, size,
-				  dma_handle, GFP_ATOMIC);
-}
-
-static inline void sbus_free_consistent(struct sbus_dev *sdev, size_t size,
-					void *vaddr, dma_addr_t dma_handle)
-{
-	return dma_free_coherent(&sdev->ofdev.dev, size, vaddr, dma_handle);
-}
-
-#define SBUS_DMA_BIDIRECTIONAL	DMA_BIDIRECTIONAL
-#define SBUS_DMA_TODEVICE	DMA_TO_DEVICE
-#define SBUS_DMA_FROMDEVICE	DMA_FROM_DEVICE
-#define	SBUS_DMA_NONE		DMA_NONE
-
-/* All the rest use streaming mode mappings. */
-static inline dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr,
-					 size_t size, int direction)
-{
-	return dma_map_single(&sdev->ofdev.dev, ptr, size,
-			      (enum dma_data_direction) direction);
-}
-
-static inline void sbus_unmap_single(struct sbus_dev *sdev,
-				     dma_addr_t dma_addr, size_t size,
-				     int direction)
-{
-	dma_unmap_single(&sdev->ofdev.dev, dma_addr, size,
-			 (enum dma_data_direction) direction);
-}
-
-static inline int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg,
-			      int nents, int direction)
-{
-	return dma_map_sg(&sdev->ofdev.dev, sg, nents,
-			  (enum dma_data_direction) direction);
-}
-
-static inline void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg,
-				 int nents, int direction)
-{
-	dma_unmap_sg(&sdev->ofdev.dev, sg, nents,
-		     (enum dma_data_direction) direction);
-}
-
-/* Finally, allow explicit synchronization of streamable mappings. */
-static inline void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev,
-						dma_addr_t dma_handle,
-						size_t size, int direction)
-{
-	dma_sync_single_for_cpu(&sdev->ofdev.dev, dma_handle, size,
-				(enum dma_data_direction) direction);
-}
-#define sbus_dma_sync_single sbus_dma_sync_single_for_cpu
-
-static inline void sbus_dma_sync_single_for_device(struct sbus_dev *sdev,
-						   dma_addr_t dma_handle,
-						   size_t size, int direction)
-{
-	/* No flushing needed to sync cpu writes to the device.  */
-}
-
-static inline void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev,
-					    struct scatterlist *sg,
-					    int nents, int direction)
-{
-	dma_sync_sg_for_cpu(&sdev->ofdev.dev, sg, nents,
-			    (enum dma_data_direction) direction);
-}
-#define sbus_dma_sync_sg sbus_dma_sync_sg_for_cpu
-
-static inline void sbus_dma_sync_sg_for_device(struct sbus_dev *sdev,
-					       struct scatterlist *sg,
-					       int nents, int direction)
-{
-	/* No flushing needed to sync cpu writes to the device.  */
-}
-
-extern void sbus_arch_bus_ranges_init(struct device_node *, struct sbus_bus *);
-extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *);
-extern void sbus_setup_arch_props(struct sbus_bus *, struct device_node *);
-extern int sbus_arch_preinit(void);
-extern void sbus_arch_postinit(void);
-
-#endif /* !(_SPARC64_SBUS_H) */
+#include <asm-sparc/sbus.h>
diff --git a/include/asm-sparc64/scatterlist.h b/include/asm-sparc64/scatterlist.h
index 81bd058..b7fef95 100644
--- a/include/asm-sparc64/scatterlist.h
+++ b/include/asm-sparc64/scatterlist.h
@@ -1,27 +1 @@
-#ifndef _SPARC64_SCATTERLIST_H
-#define _SPARC64_SCATTERLIST_H
-
-#include <asm/page.h>
-#include <asm/types.h>
-
-struct scatterlist {
-#ifdef CONFIG_DEBUG_SG
-	unsigned long	sg_magic;
-#endif
-	unsigned long	page_link;
-	unsigned int	offset;
-
-	unsigned int	length;
-
-	dma_addr_t	dma_address;
-	__u32		dma_length;
-};
-
-#define sg_dma_address(sg)	((sg)->dma_address)
-#define sg_dma_len(sg)     	((sg)->dma_length)
-
-#define ISA_DMA_THRESHOLD	(~0UL)
-
-#define ARCH_HAS_SG_CHAIN
-
-#endif /* !(_SPARC64_SCATTERLIST_H) */
+#include <asm-sparc/scatterlist.h>
diff --git a/include/asm-sparc64/scratchpad.h b/include/asm-sparc64/scratchpad.h
index 5e8b01f..23675f6 100644
--- a/include/asm-sparc64/scratchpad.h
+++ b/include/asm-sparc64/scratchpad.h
@@ -1,14 +1 @@
-#ifndef _SPARC64_SCRATCHPAD_H
-#define _SPARC64_SCRATCHPAD_H
-
-/* Sun4v scratchpad registers, accessed via ASI_SCRATCHPAD.  */
-
-#define SCRATCHPAD_MMU_MISS	0x00 /* Shared with OBP - set by OBP	    */
-#define SCRATCHPAD_CPUID	0x08 /* Shared with OBP - set by hypervisor */
-#define SCRATCHPAD_UTSBREG1	0x10
-#define SCRATCHPAD_UTSBREG2	0x18
-	/* 0x20 and 0x28, hypervisor only... */
-#define SCRATCHPAD_UNUSED1	0x30
-#define SCRATCHPAD_UNUSED2	0x38 /* Reserved for OBP		    */
-
-#endif /* !(_SPARC64_SCRATCHPAD_H) */
+#include <asm-sparc/scratchpad.h>
diff --git a/include/asm-sparc64/seccomp.h b/include/asm-sparc64/seccomp.h
index 7fcd996..f22f02a 100644
--- a/include/asm-sparc64/seccomp.h
+++ b/include/asm-sparc64/seccomp.h
@@ -1,21 +1 @@
-#ifndef _ASM_SECCOMP_H
-
-#include <linux/thread_info.h> /* already defines TIF_32BIT */
-
-#ifndef TIF_32BIT
-#error "unexpected TIF_32BIT on sparc64"
-#endif
-
-#include <linux/unistd.h>
-
-#define __NR_seccomp_read __NR_read
-#define __NR_seccomp_write __NR_write
-#define __NR_seccomp_exit __NR_exit
-#define __NR_seccomp_sigreturn __NR_rt_sigreturn
-
-#define __NR_seccomp_read_32 __NR_read
-#define __NR_seccomp_write_32 __NR_write
-#define __NR_seccomp_exit_32 __NR_exit
-#define __NR_seccomp_sigreturn_32 __NR_sigreturn
-
-#endif /* _ASM_SECCOMP_H */
+#include <asm-sparc/seccomp.h>
diff --git a/include/asm-sparc64/sections.h b/include/asm-sparc64/sections.h
index 3f4b9fd..721496f 100644
--- a/include/asm-sparc64/sections.h
+++ b/include/asm-sparc64/sections.h
@@ -1,9 +1 @@
-#ifndef _SPARC64_SECTIONS_H
-#define _SPARC64_SECTIONS_H
-
-/* nothing to see, move along */
-#include <asm-generic/sections.h>
-
-extern char _start[];
-
-#endif
+#include <asm-sparc/sections.h>
diff --git a/include/asm-sparc64/semaphore.h b/include/asm-sparc64/semaphore.h
index d9b2034..39362afd 100644
--- a/include/asm-sparc64/semaphore.h
+++ b/include/asm-sparc64/semaphore.h
@@ -1 +1 @@
-#include <linux/semaphore.h>
+#include <asm-sparc/semaphore.h>
diff --git a/include/asm-sparc64/sembuf.h b/include/asm-sparc64/sembuf.h
index 99f04e4e..c55b952 100644
--- a/include/asm-sparc64/sembuf.h
+++ b/include/asm-sparc64/sembuf.h
@@ -1,22 +1 @@
-#ifndef _SPARC64_SEMBUF_H
-#define _SPARC64_SEMBUF_H
-
-/* 
- * The semid64_ds structure for sparc64 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 2 miscellaneous 64-bit values
- */
-
-struct semid64_ds {
-	struct ipc64_perm sem_perm;		/* permissions .. see ipc.h */
-	__kernel_time_t	sem_otime;		/* last semop time */
-	__kernel_time_t	sem_ctime;		/* last change time */
-	unsigned long	sem_nsems;		/* no. of semaphores in array */
-	unsigned long	__unused1;
-	unsigned long	__unused2;
-};
-
-#endif /* _SPARC64_SEMBUF_H */
+#include <asm-sparc/sembuf.h>
diff --git a/include/asm-sparc64/setup.h b/include/asm-sparc64/setup.h
index 5053df3..7143d06 100644
--- a/include/asm-sparc64/setup.h
+++ b/include/asm-sparc64/setup.h
@@ -1,10 +1 @@
-/*
- *	Just a place holder. 
- */
-
-#ifndef _SPARC64_SETUP_H
-#define _SPARC64_SETUP_H
-
-#define COMMAND_LINE_SIZE	2048
-
-#endif /* _SPARC64_SETUP_H */
+#include <asm-sparc/setup.h>
diff --git a/include/asm-sparc64/sfafsr.h b/include/asm-sparc64/sfafsr.h
index e96137b..8036fc3 100644
--- a/include/asm-sparc64/sfafsr.h
+++ b/include/asm-sparc64/sfafsr.h
@@ -1,82 +1 @@
-#ifndef _SPARC64_SFAFSR_H
-#define _SPARC64_SFAFSR_H
-
-#include <linux/const.h>
-
-/* Spitfire Asynchronous Fault Status register, ASI=0x4C VA<63:0>=0x0 */
-
-#define SFAFSR_ME		(_AC(1,UL) << SFAFSR_ME_SHIFT)
-#define SFAFSR_ME_SHIFT		32
-#define SFAFSR_PRIV		(_AC(1,UL) << SFAFSR_PRIV_SHIFT)
-#define SFAFSR_PRIV_SHIFT	31
-#define SFAFSR_ISAP		(_AC(1,UL) << SFAFSR_ISAP_SHIFT)
-#define SFAFSR_ISAP_SHIFT	30
-#define SFAFSR_ETP		(_AC(1,UL) << SFAFSR_ETP_SHIFT)
-#define SFAFSR_ETP_SHIFT	29
-#define SFAFSR_IVUE		(_AC(1,UL) << SFAFSR_IVUE_SHIFT)
-#define SFAFSR_IVUE_SHIFT	28
-#define SFAFSR_TO		(_AC(1,UL) << SFAFSR_TO_SHIFT)
-#define SFAFSR_TO_SHIFT		27
-#define SFAFSR_BERR		(_AC(1,UL) << SFAFSR_BERR_SHIFT)
-#define SFAFSR_BERR_SHIFT	26
-#define SFAFSR_LDP		(_AC(1,UL) << SFAFSR_LDP_SHIFT)
-#define SFAFSR_LDP_SHIFT	25
-#define SFAFSR_CP		(_AC(1,UL) << SFAFSR_CP_SHIFT)
-#define SFAFSR_CP_SHIFT		24
-#define SFAFSR_WP		(_AC(1,UL) << SFAFSR_WP_SHIFT)
-#define SFAFSR_WP_SHIFT		23
-#define SFAFSR_EDP		(_AC(1,UL) << SFAFSR_EDP_SHIFT)
-#define SFAFSR_EDP_SHIFT	22
-#define SFAFSR_UE		(_AC(1,UL) << SFAFSR_UE_SHIFT)
-#define SFAFSR_UE_SHIFT		21
-#define SFAFSR_CE		(_AC(1,UL) << SFAFSR_CE_SHIFT)
-#define SFAFSR_CE_SHIFT		20
-#define SFAFSR_ETS		(_AC(0xf,UL) << SFAFSR_ETS_SHIFT)
-#define SFAFSR_ETS_SHIFT	16
-#define SFAFSR_PSYND		(_AC(0xffff,UL) << SFAFSR_PSYND_SHIFT)
-#define SFAFSR_PSYND_SHIFT	0
-
-/* UDB Error Register, ASI=0x7f VA<63:0>=0x0(High),0x18(Low) for read
- *                     ASI=0x77 VA<63:0>=0x0(High),0x18(Low) for write
- */
-
-#define UDBE_UE			(_AC(1,UL) << 9)
-#define UDBE_CE			(_AC(1,UL) << 8)
-#define UDBE_E_SYNDR		(_AC(0xff,UL) << 0)
-
-/* The trap handlers for asynchronous errors encode the AFSR and
- * other pieces of information into a 64-bit argument for C code
- * encoded as follows:
- *
- * -----------------------------------------------
- * |  UDB_H  |  UDB_L  | TL>1  |  TT  |   AFSR   |
- * -----------------------------------------------
- *  63     54 53     44    42   41  33 32       0
- *
- * The AFAR is passed in unchanged.
- */
-#define SFSTAT_UDBH_MASK	(_AC(0x3ff,UL) << SFSTAT_UDBH_SHIFT)
-#define SFSTAT_UDBH_SHIFT	54
-#define SFSTAT_UDBL_MASK	(_AC(0x3ff,UL) << SFSTAT_UDBH_SHIFT)
-#define SFSTAT_UDBL_SHIFT	44
-#define SFSTAT_TL_GT_ONE	(_AC(1,UL) << SFSTAT_TL_GT_ONE_SHIFT)
-#define SFSTAT_TL_GT_ONE_SHIFT	42
-#define SFSTAT_TRAP_TYPE	(_AC(0x1FF,UL) << SFSTAT_TRAP_TYPE_SHIFT)
-#define SFSTAT_TRAP_TYPE_SHIFT	33
-#define SFSTAT_AFSR_MASK	(_AC(0x1ffffffff,UL) << SFSTAT_AFSR_SHIFT)
-#define SFSTAT_AFSR_SHIFT	0
-
-/* ESTATE Error Enable Register, ASI=0x4b VA<63:0>=0x0 */
-#define ESTATE_ERR_CE		0x1 /* Correctable errors                    */
-#define ESTATE_ERR_NCE		0x2 /* TO, BERR, LDP, ETP, EDP, WP, UE, IVUE */
-#define ESTATE_ERR_ISAP		0x4 /* System address parity error           */
-#define ESTATE_ERR_ALL		(ESTATE_ERR_CE | \
-				 ESTATE_ERR_NCE | \
-				 ESTATE_ERR_ISAP)
-
-/* The various trap types that report using the above state. */
-#define TRAP_TYPE_IAE		0x09 /* Instruction Access Error             */
-#define TRAP_TYPE_DAE		0x32 /* Data Access Error                    */
-#define TRAP_TYPE_CEE		0x63 /* Correctable ECC Error                */
-
-#endif /* _SPARC64_SFAFSR_H */
+#include <asm-sparc/sfafsr.h>
diff --git a/include/asm-sparc64/sfp-machine.h b/include/asm-sparc64/sfp-machine.h
index c9331b0..7bbc4fe 100644
--- a/include/asm-sparc64/sfp-machine.h
+++ b/include/asm-sparc64/sfp-machine.h
@@ -1,93 +1 @@
-/* Machine-dependent software floating-point definitions.
-   Sparc64 kernel version.
-   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Richard Henderson (rth@cygnus.com),
-		  Jakub Jelinek (jj@ultra.linux.cz) and
-		  David S. Miller (davem@redhat.com).
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Library General Public License for more details.
-
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If
-   not, write to the Free Software Foundation, Inc.,
-   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
-
-#ifndef _SFP_MACHINE_H
-#define _SFP_MACHINE_H
-   
-#define _FP_W_TYPE_SIZE		64
-#define _FP_W_TYPE		unsigned long
-#define _FP_WS_TYPE		signed long
-#define _FP_I_TYPE		long
-
-#define _FP_MUL_MEAT_S(R,X,Y)					\
-  _FP_MUL_MEAT_1_imm(_FP_WFRACBITS_S,R,X,Y)
-#define _FP_MUL_MEAT_D(R,X,Y)					\
-  _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
-#define _FP_MUL_MEAT_Q(R,X,Y)					\
-  _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
-
-#define _FP_DIV_MEAT_S(R,X,Y)	_FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm)
-#define _FP_DIV_MEAT_D(R,X,Y)	_FP_DIV_MEAT_1_udiv_norm(D,R,X,Y)
-#define _FP_DIV_MEAT_Q(R,X,Y)	_FP_DIV_MEAT_2_udiv(Q,R,X,Y)
-
-#define _FP_NANFRAC_S		((_FP_QNANBIT_S << 1) - 1)
-#define _FP_NANFRAC_D		((_FP_QNANBIT_D << 1) - 1)
-#define _FP_NANFRAC_Q		((_FP_QNANBIT_Q << 1) - 1), -1
-#define _FP_NANSIGN_S		0
-#define _FP_NANSIGN_D		0
-#define _FP_NANSIGN_Q		0
-
-#define _FP_KEEPNANFRACP 1
-
-/* If one NaN is signaling and the other is not,
- * we choose that one, otherwise we choose X.
- */
-/* For _Qp_* and _Q_*, this should prefer X, for
- * CPU instruction emulation this should prefer Y.
- * (see SPAMv9 B.2.2 section).
- */
-#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)			\
-  do {								\
-    if ((_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs)		\
-	&& !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))	\
-      {								\
-	R##_s = X##_s;						\
-	_FP_FRAC_COPY_##wc(R,X);				\
-      }								\
-    else							\
-      {								\
-	R##_s = Y##_s;						\
-	_FP_FRAC_COPY_##wc(R,Y);				\
-      }								\
-    R##_c = FP_CLS_NAN;						\
-  } while (0)
-
-/* Obtain the current rounding mode. */
-#ifndef FP_ROUNDMODE
-#define FP_ROUNDMODE	((current_thread_info()->xfsr[0] >> 30) & 0x3)
-#endif
-
-/* Exception flags. */
-#define FP_EX_INVALID		(1 << 4)
-#define FP_EX_OVERFLOW		(1 << 3)
-#define FP_EX_UNDERFLOW		(1 << 2)
-#define FP_EX_DIVZERO		(1 << 1)
-#define FP_EX_INEXACT		(1 << 0)
-
-#define FP_HANDLE_EXCEPTIONS return _fex
-
-#define FP_INHIBIT_RESULTS ((current_thread_info()->xfsr[0] >> 23) & _fex)
-
-#define FP_TRAPPING_EXCEPTIONS ((current_thread_info()->xfsr[0] >> 23) & 0x1f)
-
-#endif
+#include <asm-sparc/sfp-machine.h>
diff --git a/include/asm-sparc64/shmbuf.h b/include/asm-sparc64/shmbuf.h
index 61c2ef42..0c54a2d 100644
--- a/include/asm-sparc64/shmbuf.h
+++ b/include/asm-sparc64/shmbuf.h
@@ -1,38 +1 @@
-#ifndef _SPARC64_SHMBUF_H
-#define _SPARC64_SHMBUF_H
-
-/* 
- * The shmid64_ds structure for sparc64 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 2 miscellaneous 64-bit values
- */
-
-struct shmid64_ds {
-	struct ipc64_perm	shm_perm;	/* operation perms */
-	__kernel_time_t		shm_atime;	/* last attach time */
-	__kernel_time_t		shm_dtime;	/* last detach time */
-	__kernel_time_t		shm_ctime;	/* last change time */
-	size_t			shm_segsz;	/* size of segment (bytes) */
-	__kernel_pid_t		shm_cpid;	/* pid of creator */
-	__kernel_pid_t		shm_lpid;	/* pid of last operator */
-	unsigned long		shm_nattch;	/* no. of current attaches */
-	unsigned long		__unused1;
-	unsigned long		__unused2;
-};
-
-struct shminfo64 {
-	unsigned long	shmmax;
-	unsigned long	shmmin;
-	unsigned long	shmmni;
-	unsigned long	shmseg;
-	unsigned long	shmall;
-	unsigned long	__unused1;
-	unsigned long	__unused2;
-	unsigned long	__unused3;
-	unsigned long	__unused4;
-};
-
-#endif /* _SPARC64_SHMBUF_H */
+#include <asm-sparc/shmbuf.h>
diff --git a/include/asm-sparc64/shmparam.h b/include/asm-sparc64/shmparam.h
index 1ed0d67..5fa3a9b 100644
--- a/include/asm-sparc64/shmparam.h
+++ b/include/asm-sparc64/shmparam.h
@@ -1,10 +1 @@
-#ifndef _ASMSPARC64_SHMPARAM_H
-#define _ASMSPARC64_SHMPARAM_H
-
-#include <asm/spitfire.h>
-
-#define __ARCH_FORCE_SHMLBA	1
-/* attach addr a multiple of this */
-#define	SHMLBA	((PAGE_SIZE > L1DCACHE_SIZE) ? PAGE_SIZE : L1DCACHE_SIZE)
-
-#endif /* _ASMSPARC64_SHMPARAM_H */
+#include <asm-sparc/shmparam.h>
diff --git a/include/asm-sparc64/sigcontext.h b/include/asm-sparc64/sigcontext.h
index 1c868d6..5b16dcc 100644
--- a/include/asm-sparc64/sigcontext.h
+++ b/include/asm-sparc64/sigcontext.h
@@ -1,87 +1 @@
-#ifndef __SPARC64_SIGCONTEXT_H
-#define __SPARC64_SIGCONTEXT_H
-
-#ifdef __KERNEL__
-#include <asm/ptrace.h>
-#endif
-
-#ifndef __ASSEMBLY__
-
-#ifdef __KERNEL__
-
-#define __SUNOS_MAXWIN   31
-
-/* This is what SunOS does, so shall I unless we use new 32bit signals or rt signals. */
-struct sigcontext32 {
-	int sigc_onstack;      /* state to restore */
-	int sigc_mask;         /* sigmask to restore */
-	int sigc_sp;           /* stack pointer */
-	int sigc_pc;           /* program counter */
-	int sigc_npc;          /* next program counter */
-	int sigc_psr;          /* for condition codes etc */
-	int sigc_g1;           /* User uses these two registers */
-	int sigc_o0;           /* within the trampoline code. */
-
-	/* Now comes information regarding the users window set
-	 * at the time of the signal.
-	 */
-	int sigc_oswins;       /* outstanding windows */
-
-	/* stack ptrs for each regwin buf */
-	unsigned sigc_spbuf[__SUNOS_MAXWIN];
-
-	/* Windows to restore after signal */
-	struct reg_window32 sigc_wbuf[__SUNOS_MAXWIN];
-};
-
-#endif
-
-#ifdef __KERNEL__
-
-/* This is what we use for 32bit new non-rt signals. */
-
-typedef struct {
-	struct {
-		unsigned int psr;
-		unsigned int pc;
-		unsigned int npc;
-		unsigned int y;
-		unsigned int u_regs[16]; /* globals and ins */
-	}			si_regs;
-	int			si_mask;
-} __siginfo32_t;
-
-#endif
-
-typedef struct {
-	unsigned   int si_float_regs [64];
-	unsigned   long si_fsr;
-	unsigned   long si_gsr;
-	unsigned   long si_fprs;
-} __siginfo_fpu_t;
-
-/* This is what SunOS doesn't, so we have to write this alone
-   and do it properly. */
-struct sigcontext {
-	/* The size of this array has to match SI_MAX_SIZE from siginfo.h */
-	char			sigc_info[128];
-	struct {
-		unsigned long	u_regs[16]; /* globals and ins */
-		unsigned long	tstate;
-		unsigned long	tpc;
-		unsigned long	tnpc;
-		unsigned int	y;
-		unsigned int	fprs;
-	}			sigc_regs;
-	__siginfo_fpu_t *	sigc_fpu_save;
-	struct {
-		void	*	ss_sp;
-		int		ss_flags;
-		unsigned long	ss_size;
-	}			sigc_stack;
-	unsigned long		sigc_mask;
-};
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(__SPARC64_SIGCONTEXT_H) */
+#include <asm-sparc/sigcontext.h>
diff --git a/include/asm-sparc64/siginfo.h b/include/asm-sparc64/siginfo.h
index c96e6c3..8ffd6eb 100644
--- a/include/asm-sparc64/siginfo.h
+++ b/include/asm-sparc64/siginfo.h
@@ -1,32 +1 @@
-#ifndef _SPARC64_SIGINFO_H
-#define _SPARC64_SIGINFO_H
-
-#define SI_PAD_SIZE32	((SI_MAX_SIZE/sizeof(int)) - 3)
-
-#define __ARCH_SI_PREAMBLE_SIZE	(4 * sizeof(int))
-#define __ARCH_SI_TRAPNO
-#define __ARCH_SI_BAND_T int
-
-#include <asm-generic/siginfo.h>
-
-#ifdef __KERNEL__
-
-#include <linux/compat.h>
-
-#ifdef CONFIG_COMPAT
-
-struct compat_siginfo;
-
-#endif /* CONFIG_COMPAT */
-
-#endif /* __KERNEL__ */
-
-#define SI_NOINFO	32767		/* no information in siginfo_t */
-
-/*
- * SIGEMT si_codes
- */
-#define EMT_TAGOVF	(__SI_FAULT|1)	/* tag overflow */
-#define NSIGEMT		1
-
-#endif
+#include <asm-sparc/siginfo.h>
diff --git a/include/asm-sparc64/signal.h b/include/asm-sparc64/signal.h
index 2a7c793..79705e5 100644
--- a/include/asm-sparc64/signal.h
+++ b/include/asm-sparc64/signal.h
@@ -1,194 +1 @@
-#ifndef _ASMSPARC64_SIGNAL_H
-#define _ASMSPARC64_SIGNAL_H
-
-#include <asm/sigcontext.h>
-
-#ifdef __KERNEL__
-#ifndef __ASSEMBLY__
-#include <linux/personality.h>
-#include <linux/types.h>
-#endif
-#endif
-
-/* On the Sparc the signal handlers get passed a 'sub-signal' code
- * for certain signal types, which we document here.
- */
-#define SIGHUP		 1
-#define SIGINT		 2
-#define SIGQUIT		 3
-#define SIGILL		 4
-#define    SUBSIG_STACK       0
-#define    SUBSIG_ILLINST     2
-#define    SUBSIG_PRIVINST    3
-#define    SUBSIG_BADTRAP(t)  (0x80 + (t))
-
-#define SIGTRAP		 5
-#define SIGABRT		 6
-#define SIGIOT		 6
-
-#define SIGEMT           7
-#define    SUBSIG_TAG    10
-
-#define SIGFPE		 8
-#define    SUBSIG_FPDISABLED     0x400
-#define    SUBSIG_FPERROR        0x404
-#define    SUBSIG_FPINTOVFL      0x001
-#define    SUBSIG_FPSTSIG        0x002
-#define    SUBSIG_IDIVZERO       0x014
-#define    SUBSIG_FPINEXACT      0x0c4
-#define    SUBSIG_FPDIVZERO      0x0c8
-#define    SUBSIG_FPUNFLOW       0x0cc
-#define    SUBSIG_FPOPERROR      0x0d0
-#define    SUBSIG_FPOVFLOW       0x0d4
-
-#define SIGKILL		 9
-#define SIGBUS          10
-#define    SUBSIG_BUSTIMEOUT    1
-#define    SUBSIG_ALIGNMENT     2
-#define    SUBSIG_MISCERROR     5
-
-#define SIGSEGV		11
-#define    SUBSIG_NOMAPPING     3
-#define    SUBSIG_PROTECTION    4
-#define    SUBSIG_SEGERROR      5
-
-#define SIGSYS		12
-
-#define SIGPIPE		13
-#define SIGALRM		14
-#define SIGTERM		15
-#define SIGURG          16
-
-/* SunOS values which deviate from the Linux/i386 ones */
-#define SIGSTOP		17
-#define SIGTSTP		18
-#define SIGCONT		19
-#define SIGCHLD		20
-#define SIGTTIN		21
-#define SIGTTOU		22
-#define SIGIO		23
-#define SIGPOLL		SIGIO   /* SysV name for SIGIO */
-#define SIGXCPU		24
-#define SIGXFSZ		25
-#define SIGVTALRM	26
-#define SIGPROF		27
-#define SIGWINCH	28
-#define SIGLOST		29
-#define SIGPWR		SIGLOST
-#define SIGUSR1		30
-#define SIGUSR2		31
-
-/* Most things should be clean enough to redefine this at will, if care
-   is taken to make libc match.  */
-
-#define __OLD_NSIG	32
-#define __NEW_NSIG      64
-#define _NSIG_BPW     	64
-#define _NSIG_WORDS   	(__NEW_NSIG / _NSIG_BPW)
-
-#define SIGRTMIN       32
-#define SIGRTMAX       __NEW_NSIG
-
-#if defined(__KERNEL__) || defined(__WANT_POSIX1B_SIGNALS__)
-#define _NSIG			__NEW_NSIG
-#define __new_sigset_t		sigset_t
-#define __new_sigaction		sigaction
-#define __new_sigaction32	sigaction32
-#define __old_sigset_t		old_sigset_t
-#define __old_sigaction		old_sigaction
-#define __old_sigaction32	old_sigaction32
-#else
-#define _NSIG			__OLD_NSIG
-#define NSIG			_NSIG
-#define __old_sigset_t		sigset_t
-#define __old_sigaction		sigaction
-#define __old_sigaction32	sigaction32
-#endif
-
-#ifndef __ASSEMBLY__
-
-typedef unsigned long __old_sigset_t;            /* at least 32 bits */
-
-typedef struct {
-       unsigned long sig[_NSIG_WORDS];
-} __new_sigset_t;
-
-/* A SunOS sigstack */
-struct sigstack {
-	/* XXX 32-bit pointers pinhead XXX */
-	char *the_stack;
-	int   cur_status;
-};
-
-/* Sigvec flags */
-#define _SV_SSTACK    1u    /* This signal handler should use sig-stack */
-#define _SV_INTR      2u    /* Sig return should not restart system call */
-#define _SV_RESET     4u    /* Set handler to SIG_DFL upon taken signal */
-#define _SV_IGNCHILD  8u    /* Do not send SIGCHLD */
-
-/*
- * sa_flags values: SA_STACK is not currently supported, but will allow the
- * usage of signal stacks by using the (now obsolete) sa_restorer field in
- * the sigaction structure as a stack pointer. This is now possible due to
- * the changes in signal handling. LBT 010493.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- */
-#define SA_NOCLDSTOP	_SV_IGNCHILD
-#define SA_STACK	_SV_SSTACK
-#define SA_ONSTACK	_SV_SSTACK
-#define SA_RESTART	_SV_INTR
-#define SA_ONESHOT	_SV_RESET
-#define SA_NOMASK	0x20u
-#define SA_NOCLDWAIT    0x100u
-#define SA_SIGINFO      0x200u
-
-
-#define SIG_BLOCK          0x01	/* for blocking signals */
-#define SIG_UNBLOCK        0x02	/* for unblocking signals */
-#define SIG_SETMASK        0x04	/* for setting the signal mask */
-
-/* 
- * sigaltstack controls
- */
-#define SS_ONSTACK	1
-#define SS_DISABLE	2
-
-#define MINSIGSTKSZ	4096
-#define SIGSTKSZ	16384
-
-#include <asm-generic/signal.h>
-
-struct __new_sigaction {
-	__sighandler_t		sa_handler;
-	unsigned long		sa_flags;
-	__sigrestore_t 		sa_restorer;  /* not used by Linux/SPARC yet */
-	__new_sigset_t		sa_mask;
-};
-
-struct __old_sigaction {
-	__sighandler_t  	sa_handler;
-	__old_sigset_t  	sa_mask;
-	unsigned long   	sa_flags;
-	void 			(*sa_restorer)(void);     /* not used by Linux/SPARC yet */
-};
-
-typedef struct sigaltstack {
-	void			__user *ss_sp;
-	int			ss_flags;
-	size_t			ss_size;
-} stack_t;
-
-#ifdef __KERNEL__
-
-struct k_sigaction {
-	struct __new_sigaction 	sa;
-	void __user		*ka_restorer;
-};
-
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
-#endif /* !(__KERNEL__) */
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(_ASMSPARC64_SIGNAL_H) */
+#include <asm-sparc/signal.h>
diff --git a/include/asm-sparc64/smp.h b/include/asm-sparc64/smp.h
index cd0311b..5095a2c 100644
--- a/include/asm-sparc64/smp.h
+++ b/include/asm-sparc64/smp.h
@@ -1,64 +1 @@
-/* smp.h: Sparc64 specific SMP stuff.
- *
- * Copyright (C) 1996, 2008 David S. Miller (davem@davemloft.net)
- */
-
-#ifndef _SPARC64_SMP_H
-#define _SPARC64_SMP_H
-
-#include <linux/threads.h>
-#include <asm/asi.h>
-#include <asm/starfire.h>
-#include <asm/spitfire.h>
-
-#ifndef __ASSEMBLY__
-
-#include <linux/cpumask.h>
-#include <linux/cache.h>
-
-#endif /* !(__ASSEMBLY__) */
-
-#ifdef CONFIG_SMP
-
-#ifndef __ASSEMBLY__
-
-/*
- *	Private routines/data
- */
- 
-#include <linux/bitops.h>
-#include <asm/atomic.h>
-#include <asm/percpu.h>
-
-DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
-extern cpumask_t cpu_core_map[NR_CPUS];
-extern int sparc64_multi_core;
-
-/*
- *	General functions that each host system must provide.
- */
-
-extern int hard_smp_processor_id(void);
-#define raw_smp_processor_id() (current_thread_info()->cpu)
-
-extern void smp_fill_in_sib_core_maps(void);
-extern void cpu_play_dead(void);
-
-extern void smp_fetch_global_regs(void);
-
-#ifdef CONFIG_HOTPLUG_CPU
-extern int __cpu_disable(void);
-extern void __cpu_die(unsigned int cpu);
-#endif
-
-#endif /* !(__ASSEMBLY__) */
-
-#else
-
-#define hard_smp_processor_id()		0
-#define smp_fill_in_sib_core_maps() do { } while (0)
-#define smp_fetch_global_regs() do { } while (0)
-
-#endif /* !(CONFIG_SMP) */
-
-#endif /* !(_SPARC64_SMP_H) */
+#include <asm-sparc/smp.h>
diff --git a/include/asm-sparc64/socket.h b/include/asm-sparc64/socket.h
index 5af688f..13e0d5d 100644
--- a/include/asm-sparc64/socket.h
+++ b/include/asm-sparc64/socket.h
@@ -1,57 +1 @@
-#ifndef _ASM_SOCKET_H
-#define _ASM_SOCKET_H
-
-#include <asm/sockios.h>
-
-/* For setsockopt(2) */
-#define SOL_SOCKET	0xffff
-
-#define SO_DEBUG	0x0001
-#define SO_PASSCRED	0x0002
-#define SO_REUSEADDR	0x0004
-#define SO_KEEPALIVE	0x0008
-#define SO_DONTROUTE	0x0010
-#define SO_BROADCAST	0x0020
-#define SO_PEERCRED	0x0040
-#define SO_LINGER	0x0080
-#define SO_OOBINLINE	0x0100
-/* To add :#define SO_REUSEPORT 0x0200 */
-#define SO_BSDCOMPAT    0x0400
-#define SO_RCVLOWAT     0x0800
-#define SO_SNDLOWAT     0x1000
-#define SO_RCVTIMEO     0x2000
-#define SO_SNDTIMEO     0x4000
-#define SO_ACCEPTCONN	0x8000
-
-#define SO_SNDBUF	0x1001
-#define SO_RCVBUF	0x1002
-#define SO_SNDBUFFORCE	0x100a
-#define SO_RCVBUFFORCE	0x100b
-#define SO_ERROR	0x1007
-#define SO_TYPE		0x1008
-
-/* Linux specific, keep the same. */
-#define SO_NO_CHECK	0x000b
-#define SO_PRIORITY	0x000c
-
-#define SO_BINDTODEVICE 0x000d
-
-#define SO_ATTACH_FILTER	0x001a
-#define SO_DETACH_FILTER        0x001b
-
-#define SO_PEERNAME		0x001c
-#define SO_TIMESTAMP		0x001d
-#define SCM_TIMESTAMP		SO_TIMESTAMP
-
-#define SO_PEERSEC		0x001e
-#define SO_PASSSEC		0x001f
-#define SO_TIMESTAMPNS		0x0021
-#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
-
-/* Security levels - as per NRL IPv6 - don't actually do anything */
-#define SO_SECURITY_AUTHENTICATION		0x5001
-#define SO_SECURITY_ENCRYPTION_TRANSPORT	0x5002
-#define SO_SECURITY_ENCRYPTION_NETWORK		0x5004
-
-#define SO_MARK			0x0022
-#endif /* _ASM_SOCKET_H */
+#include <asm-sparc/socket.h>
diff --git a/include/asm-sparc64/sockios.h b/include/asm-sparc64/sockios.h
index c7d9900..2cb4b64 100644
--- a/include/asm-sparc64/sockios.h
+++ b/include/asm-sparc64/sockios.h
@@ -1,14 +1 @@
-#ifndef _ASM_SPARC64_SOCKIOS_H
-#define _ASM_SPARC64_SOCKIOS_H
-
-/* Socket-level I/O control calls. */
-#define FIOSETOWN 	0x8901
-#define SIOCSPGRP	0x8902
-#define FIOGETOWN	0x8903
-#define SIOCGPGRP	0x8904
-#define SIOCATMARK	0x8905
-#define SIOCGSTAMP	0x8906		/* Get stamp (timeval) */
-#define SIOCGSTAMPNS	0x8907		/* Get stamp (timespec) */
-
-#endif /* !(_ASM_SPARC64_SOCKIOS_H) */
-
+#include <asm-sparc/sockios.h>
diff --git a/include/asm-sparc64/sparsemem.h b/include/asm-sparc64/sparsemem.h
index b99d4e4..e681f22 100644
--- a/include/asm-sparc64/sparsemem.h
+++ b/include/asm-sparc64/sparsemem.h
@@ -1,12 +1 @@
-#ifndef _SPARC64_SPARSEMEM_H
-#define _SPARC64_SPARSEMEM_H
-
-#ifdef __KERNEL__
-
-#define SECTION_SIZE_BITS       30
-#define MAX_PHYSADDR_BITS       42
-#define MAX_PHYSMEM_BITS        42
-
-#endif /* !(__KERNEL__) */
-
-#endif /* !(_SPARC64_SPARSEMEM_H) */
+#include <asm-sparc/sparsemem.h>
diff --git a/include/asm-sparc64/spinlock.h b/include/asm-sparc64/spinlock.h
index 0006fe9..0115b81 100644
--- a/include/asm-sparc64/spinlock.h
+++ b/include/asm-sparc64/spinlock.h
@@ -1,250 +1 @@
-/* spinlock.h: 64-bit Sparc spinlock support.
- *
- * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef __SPARC64_SPINLOCK_H
-#define __SPARC64_SPINLOCK_H
-
-#include <linux/threads.h>	/* For NR_CPUS */
-
-#ifndef __ASSEMBLY__
-
-/* To get debugging spinlocks which detect and catch
- * deadlock situations, set CONFIG_DEBUG_SPINLOCK
- * and rebuild your kernel.
- */
-
-/* All of these locking primitives are expected to work properly
- * even in an RMO memory model, which currently is what the kernel
- * runs in.
- *
- * There is another issue.  Because we play games to save cycles
- * in the non-contention case, we need to be extra careful about
- * branch targets into the "spinning" code.  They live in their
- * own section, but the newer V9 branches have a shorter range
- * than the traditional 32-bit sparc branch variants.  The rule
- * is that the branches that go into and out of the spinner sections
- * must be pre-V9 branches.
- */
-
-#define __raw_spin_is_locked(lp)	((lp)->lock != 0)
-
-#define __raw_spin_unlock_wait(lp)	\
-	do {	rmb();			\
-	} while((lp)->lock)
-
-static inline void __raw_spin_lock(raw_spinlock_t *lock)
-{
-	unsigned long tmp;
-
-	__asm__ __volatile__(
-"1:	ldstub		[%1], %0\n"
-"	membar		#StoreLoad | #StoreStore\n"
-"	brnz,pn		%0, 2f\n"
-"	 nop\n"
-"	.subsection	2\n"
-"2:	ldub		[%1], %0\n"
-"	membar		#LoadLoad\n"
-"	brnz,pt		%0, 2b\n"
-"	 nop\n"
-"	ba,a,pt		%%xcc, 1b\n"
-"	.previous"
-	: "=&r" (tmp)
-	: "r" (lock)
-	: "memory");
-}
-
-static inline int __raw_spin_trylock(raw_spinlock_t *lock)
-{
-	unsigned long result;
-
-	__asm__ __volatile__(
-"	ldstub		[%1], %0\n"
-"	membar		#StoreLoad | #StoreStore"
-	: "=r" (result)
-	: "r" (lock)
-	: "memory");
-
-	return (result == 0UL);
-}
-
-static inline void __raw_spin_unlock(raw_spinlock_t *lock)
-{
-	__asm__ __volatile__(
-"	membar		#StoreStore | #LoadStore\n"
-"	stb		%%g0, [%0]"
-	: /* No outputs */
-	: "r" (lock)
-	: "memory");
-}
-
-static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags)
-{
-	unsigned long tmp1, tmp2;
-
-	__asm__ __volatile__(
-"1:	ldstub		[%2], %0\n"
-"	membar		#StoreLoad | #StoreStore\n"
-"	brnz,pn		%0, 2f\n"
-"	 nop\n"
-"	.subsection	2\n"
-"2:	rdpr		%%pil, %1\n"
-"	wrpr		%3, %%pil\n"
-"3:	ldub		[%2], %0\n"
-"	membar		#LoadLoad\n"
-"	brnz,pt		%0, 3b\n"
-"	 nop\n"
-"	ba,pt		%%xcc, 1b\n"
-"	 wrpr		%1, %%pil\n"
-"	.previous"
-	: "=&r" (tmp1), "=&r" (tmp2)
-	: "r"(lock), "r"(flags)
-	: "memory");
-}
-
-/* Multi-reader locks, these are much saner than the 32-bit Sparc ones... */
-
-static void inline __read_lock(raw_rwlock_t *lock)
-{
-	unsigned long tmp1, tmp2;
-
-	__asm__ __volatile__ (
-"1:	ldsw		[%2], %0\n"
-"	brlz,pn		%0, 2f\n"
-"4:	 add		%0, 1, %1\n"
-"	cas		[%2], %0, %1\n"
-"	cmp		%0, %1\n"
-"	membar		#StoreLoad | #StoreStore\n"
-"	bne,pn		%%icc, 1b\n"
-"	 nop\n"
-"	.subsection	2\n"
-"2:	ldsw		[%2], %0\n"
-"	membar		#LoadLoad\n"
-"	brlz,pt		%0, 2b\n"
-"	 nop\n"
-"	ba,a,pt		%%xcc, 4b\n"
-"	.previous"
-	: "=&r" (tmp1), "=&r" (tmp2)
-	: "r" (lock)
-	: "memory");
-}
-
-static int inline __read_trylock(raw_rwlock_t *lock)
-{
-	int tmp1, tmp2;
-
-	__asm__ __volatile__ (
-"1:	ldsw		[%2], %0\n"
-"	brlz,a,pn	%0, 2f\n"
-"	 mov		0, %0\n"
-"	add		%0, 1, %1\n"
-"	cas		[%2], %0, %1\n"
-"	cmp		%0, %1\n"
-"	membar		#StoreLoad | #StoreStore\n"
-"	bne,pn		%%icc, 1b\n"
-"	 mov		1, %0\n"
-"2:"
-	: "=&r" (tmp1), "=&r" (tmp2)
-	: "r" (lock)
-	: "memory");
-
-	return tmp1;
-}
-
-static void inline __read_unlock(raw_rwlock_t *lock)
-{
-	unsigned long tmp1, tmp2;
-
-	__asm__ __volatile__(
-"	membar	#StoreLoad | #LoadLoad\n"
-"1:	lduw	[%2], %0\n"
-"	sub	%0, 1, %1\n"
-"	cas	[%2], %0, %1\n"
-"	cmp	%0, %1\n"
-"	bne,pn	%%xcc, 1b\n"
-"	 nop"
-	: "=&r" (tmp1), "=&r" (tmp2)
-	: "r" (lock)
-	: "memory");
-}
-
-static void inline __write_lock(raw_rwlock_t *lock)
-{
-	unsigned long mask, tmp1, tmp2;
-
-	mask = 0x80000000UL;
-
-	__asm__ __volatile__(
-"1:	lduw		[%2], %0\n"
-"	brnz,pn		%0, 2f\n"
-"4:	 or		%0, %3, %1\n"
-"	cas		[%2], %0, %1\n"
-"	cmp		%0, %1\n"
-"	membar		#StoreLoad | #StoreStore\n"
-"	bne,pn		%%icc, 1b\n"
-"	 nop\n"
-"	.subsection	2\n"
-"2:	lduw		[%2], %0\n"
-"	membar		#LoadLoad\n"
-"	brnz,pt		%0, 2b\n"
-"	 nop\n"
-"	ba,a,pt		%%xcc, 4b\n"
-"	.previous"
-	: "=&r" (tmp1), "=&r" (tmp2)
-	: "r" (lock), "r" (mask)
-	: "memory");
-}
-
-static void inline __write_unlock(raw_rwlock_t *lock)
-{
-	__asm__ __volatile__(
-"	membar		#LoadStore | #StoreStore\n"
-"	stw		%%g0, [%0]"
-	: /* no outputs */
-	: "r" (lock)
-	: "memory");
-}
-
-static int inline __write_trylock(raw_rwlock_t *lock)
-{
-	unsigned long mask, tmp1, tmp2, result;
-
-	mask = 0x80000000UL;
-
-	__asm__ __volatile__(
-"	mov		0, %2\n"
-"1:	lduw		[%3], %0\n"
-"	brnz,pn		%0, 2f\n"
-"	 or		%0, %4, %1\n"
-"	cas		[%3], %0, %1\n"
-"	cmp		%0, %1\n"
-"	membar		#StoreLoad | #StoreStore\n"
-"	bne,pn		%%icc, 1b\n"
-"	 nop\n"
-"	mov		1, %2\n"
-"2:"
-	: "=&r" (tmp1), "=&r" (tmp2), "=&r" (result)
-	: "r" (lock), "r" (mask)
-	: "memory");
-
-	return result;
-}
-
-#define __raw_read_lock(p)	__read_lock(p)
-#define __raw_read_trylock(p)	__read_trylock(p)
-#define __raw_read_unlock(p)	__read_unlock(p)
-#define __raw_write_lock(p)	__write_lock(p)
-#define __raw_write_unlock(p)	__write_unlock(p)
-#define __raw_write_trylock(p)	__write_trylock(p)
-
-#define __raw_read_can_lock(rw)		(!((rw)->lock & 0x80000000UL))
-#define __raw_write_can_lock(rw)	(!(rw)->lock)
-
-#define _raw_spin_relax(lock)	cpu_relax()
-#define _raw_read_relax(lock)	cpu_relax()
-#define _raw_write_relax(lock)	cpu_relax()
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(__SPARC64_SPINLOCK_H) */
+#include <asm-sparc/spinlock.h>
diff --git a/include/asm-sparc64/spinlock_types.h b/include/asm-sparc64/spinlock_types.h
index e128112..48d81c8 100644
--- a/include/asm-sparc64/spinlock_types.h
+++ b/include/asm-sparc64/spinlock_types.h
@@ -1,20 +1 @@
-#ifndef __SPARC64_SPINLOCK_TYPES_H
-#define __SPARC64_SPINLOCK_TYPES_H
-
-#ifndef __LINUX_SPINLOCK_TYPES_H
-# error "please don't include this file directly"
-#endif
-
-typedef struct {
-	volatile unsigned char lock;
-} raw_spinlock_t;
-
-#define __RAW_SPIN_LOCK_UNLOCKED	{ 0 }
-
-typedef struct {
-	volatile unsigned int lock;
-} raw_rwlock_t;
-
-#define __RAW_RW_LOCK_UNLOCKED		{ 0 }
-
-#endif
+#include <asm-sparc/spinlock_types.h>
diff --git a/include/asm-sparc64/spitfire.h b/include/asm-sparc64/spitfire.h
index 985ea7e..4430d2f 100644
--- a/include/asm-sparc64/spitfire.h
+++ b/include/asm-sparc64/spitfire.h
@@ -1,342 +1 @@
-/* spitfire.h: SpitFire/BlackBird/Cheetah inline MMU operations.
- *
- * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
- */
-
-#ifndef _SPARC64_SPITFIRE_H
-#define _SPARC64_SPITFIRE_H
-
-#include <asm/asi.h>
-
-/* The following register addresses are accessible via ASI_DMMU
- * and ASI_IMMU, that is there is a distinct and unique copy of
- * each these registers for each TLB.
- */
-#define TSB_TAG_TARGET		0x0000000000000000 /* All chips				*/
-#define TLB_SFSR		0x0000000000000018 /* All chips				*/
-#define TSB_REG			0x0000000000000028 /* All chips				*/
-#define TLB_TAG_ACCESS		0x0000000000000030 /* All chips				*/
-#define VIRT_WATCHPOINT		0x0000000000000038 /* All chips				*/
-#define PHYS_WATCHPOINT		0x0000000000000040 /* All chips				*/
-#define TSB_EXTENSION_P		0x0000000000000048 /* Ultra-III and later		*/
-#define TSB_EXTENSION_S		0x0000000000000050 /* Ultra-III and later, D-TLB only	*/
-#define TSB_EXTENSION_N		0x0000000000000058 /* Ultra-III and later		*/
-#define TLB_TAG_ACCESS_EXT	0x0000000000000060 /* Ultra-III+ and later		*/
-
-/* These registers only exist as one entity, and are accessed
- * via ASI_DMMU only.
- */
-#define PRIMARY_CONTEXT		0x0000000000000008
-#define SECONDARY_CONTEXT	0x0000000000000010
-#define DMMU_SFAR		0x0000000000000020
-#define VIRT_WATCHPOINT		0x0000000000000038
-#define PHYS_WATCHPOINT		0x0000000000000040
-
-#define SPITFIRE_HIGHEST_LOCKED_TLBENT	(64 - 1)
-#define CHEETAH_HIGHEST_LOCKED_TLBENT	(16 - 1)
-
-#define L1DCACHE_SIZE		0x4000
-
-#define SUN4V_CHIP_INVALID	0x00
-#define SUN4V_CHIP_NIAGARA1	0x01
-#define SUN4V_CHIP_NIAGARA2	0x02
-#define SUN4V_CHIP_UNKNOWN	0xff
-
-#ifndef __ASSEMBLY__
-
-enum ultra_tlb_layout {
-	spitfire = 0,
-	cheetah = 1,
-	cheetah_plus = 2,
-	hypervisor = 3,
-};
-
-extern enum ultra_tlb_layout tlb_type;
-
-extern int sun4v_chip_type;
-
-extern int cheetah_pcache_forced_on;
-extern void cheetah_enable_pcache(void);
-
-#define sparc64_highest_locked_tlbent()	\
-	(tlb_type == spitfire ? \
-	 SPITFIRE_HIGHEST_LOCKED_TLBENT : \
-	 CHEETAH_HIGHEST_LOCKED_TLBENT)
-
-extern int num_kernel_image_mappings;
-
-/* The data cache is write through, so this just invalidates the
- * specified line.
- */
-static inline void spitfire_put_dcache_tag(unsigned long addr, unsigned long tag)
-{
-	__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
-			     "membar	#Sync"
-			     : /* No outputs */
-			     : "r" (tag), "r" (addr), "i" (ASI_DCACHE_TAG));
-}
-
-/* The instruction cache lines are flushed with this, but note that
- * this does not flush the pipeline.  It is possible for a line to
- * get flushed but stale instructions to still be in the pipeline,
- * a flush instruction (to any address) is sufficient to handle
- * this issue after the line is invalidated.
- */
-static inline void spitfire_put_icache_tag(unsigned long addr, unsigned long tag)
-{
-	__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
-			     "membar	#Sync"
-			     : /* No outputs */
-			     : "r" (tag), "r" (addr), "i" (ASI_IC_TAG));
-}
-
-static inline unsigned long spitfire_get_dtlb_data(int entry)
-{
-	unsigned long data;
-
-	__asm__ __volatile__("ldxa	[%1] %2, %0"
-			     : "=r" (data)
-			     : "r" (entry << 3), "i" (ASI_DTLB_DATA_ACCESS));
-
-	/* Clear TTE diag bits. */
-	data &= ~0x0003fe0000000000UL;
-
-	return data;
-}
-
-static inline unsigned long spitfire_get_dtlb_tag(int entry)
-{
-	unsigned long tag;
-
-	__asm__ __volatile__("ldxa	[%1] %2, %0"
-			     : "=r" (tag)
-			     : "r" (entry << 3), "i" (ASI_DTLB_TAG_READ));
-	return tag;
-}
-
-static inline void spitfire_put_dtlb_data(int entry, unsigned long data)
-{
-	__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
-			     "membar	#Sync"
-			     : /* No outputs */
-			     : "r" (data), "r" (entry << 3),
-			       "i" (ASI_DTLB_DATA_ACCESS));
-}
-
-static inline unsigned long spitfire_get_itlb_data(int entry)
-{
-	unsigned long data;
-
-	__asm__ __volatile__("ldxa	[%1] %2, %0"
-			     : "=r" (data)
-			     : "r" (entry << 3), "i" (ASI_ITLB_DATA_ACCESS));
-
-	/* Clear TTE diag bits. */
-	data &= ~0x0003fe0000000000UL;
-
-	return data;
-}
-
-static inline unsigned long spitfire_get_itlb_tag(int entry)
-{
-	unsigned long tag;
-
-	__asm__ __volatile__("ldxa	[%1] %2, %0"
-			     : "=r" (tag)
-			     : "r" (entry << 3), "i" (ASI_ITLB_TAG_READ));
-	return tag;
-}
-
-static inline void spitfire_put_itlb_data(int entry, unsigned long data)
-{
-	__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
-			     "membar	#Sync"
-			     : /* No outputs */
-			     : "r" (data), "r" (entry << 3),
-			       "i" (ASI_ITLB_DATA_ACCESS));
-}
-
-static inline void spitfire_flush_dtlb_nucleus_page(unsigned long page)
-{
-	__asm__ __volatile__("stxa	%%g0, [%0] %1\n\t"
-			     "membar	#Sync"
-			     : /* No outputs */
-			     : "r" (page | 0x20), "i" (ASI_DMMU_DEMAP));
-}
-
-static inline void spitfire_flush_itlb_nucleus_page(unsigned long page)
-{
-	__asm__ __volatile__("stxa	%%g0, [%0] %1\n\t"
-			     "membar	#Sync"
-			     : /* No outputs */
-			     : "r" (page | 0x20), "i" (ASI_IMMU_DEMAP));
-}
-
-/* Cheetah has "all non-locked" tlb flushes. */
-static inline void cheetah_flush_dtlb_all(void)
-{
-	__asm__ __volatile__("stxa	%%g0, [%0] %1\n\t"
-			     "membar	#Sync"
-			     : /* No outputs */
-			     : "r" (0x80), "i" (ASI_DMMU_DEMAP));
-}
-
-static inline void cheetah_flush_itlb_all(void)
-{
-	__asm__ __volatile__("stxa	%%g0, [%0] %1\n\t"
-			     "membar	#Sync"
-			     : /* No outputs */
-			     : "r" (0x80), "i" (ASI_IMMU_DEMAP));
-}
-
-/* Cheetah has a 4-tlb layout so direct access is a bit different.
- * The first two TLBs are fully assosciative, hold 16 entries, and are
- * used only for locked and >8K sized translations.  One exists for
- * data accesses and one for instruction accesses.
- *
- * The third TLB is for data accesses to 8K non-locked translations, is
- * 2 way assosciative, and holds 512 entries.  The fourth TLB is for
- * instruction accesses to 8K non-locked translations, is 2 way
- * assosciative, and holds 128 entries.
- *
- * Cheetah has some bug where bogus data can be returned from
- * ASI_{D,I}TLB_DATA_ACCESS loads, doing the load twice fixes
- * the problem for me. -DaveM
- */
-static inline unsigned long cheetah_get_ldtlb_data(int entry)
-{
-	unsigned long data;
-
-	__asm__ __volatile__("ldxa	[%1] %2, %%g0\n\t"
-			     "ldxa	[%1] %2, %0"
-			     : "=r" (data)
-			     : "r" ((0 << 16) | (entry << 3)),
-			     "i" (ASI_DTLB_DATA_ACCESS));
-
-	return data;
-}
-
-static inline unsigned long cheetah_get_litlb_data(int entry)
-{
-	unsigned long data;
-
-	__asm__ __volatile__("ldxa	[%1] %2, %%g0\n\t"
-			     "ldxa	[%1] %2, %0"
-			     : "=r" (data)
-			     : "r" ((0 << 16) | (entry << 3)),
-			     "i" (ASI_ITLB_DATA_ACCESS));
-
-	return data;
-}
-
-static inline unsigned long cheetah_get_ldtlb_tag(int entry)
-{
-	unsigned long tag;
-
-	__asm__ __volatile__("ldxa	[%1] %2, %0"
-			     : "=r" (tag)
-			     : "r" ((0 << 16) | (entry << 3)),
-			     "i" (ASI_DTLB_TAG_READ));
-
-	return tag;
-}
-
-static inline unsigned long cheetah_get_litlb_tag(int entry)
-{
-	unsigned long tag;
-
-	__asm__ __volatile__("ldxa	[%1] %2, %0"
-			     : "=r" (tag)
-			     : "r" ((0 << 16) | (entry << 3)),
-			     "i" (ASI_ITLB_TAG_READ));
-
-	return tag;
-}
-
-static inline void cheetah_put_ldtlb_data(int entry, unsigned long data)
-{
-	__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
-			     "membar	#Sync"
-			     : /* No outputs */
-			     : "r" (data),
-			       "r" ((0 << 16) | (entry << 3)),
-			       "i" (ASI_DTLB_DATA_ACCESS));
-}
-
-static inline void cheetah_put_litlb_data(int entry, unsigned long data)
-{
-	__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
-			     "membar	#Sync"
-			     : /* No outputs */
-			     : "r" (data),
-			       "r" ((0 << 16) | (entry << 3)),
-			       "i" (ASI_ITLB_DATA_ACCESS));
-}
-
-static inline unsigned long cheetah_get_dtlb_data(int entry, int tlb)
-{
-	unsigned long data;
-
-	__asm__ __volatile__("ldxa	[%1] %2, %%g0\n\t"
-			     "ldxa	[%1] %2, %0"
-			     : "=r" (data)
-			     : "r" ((tlb << 16) | (entry << 3)), "i" (ASI_DTLB_DATA_ACCESS));
-
-	return data;
-}
-
-static inline unsigned long cheetah_get_dtlb_tag(int entry, int tlb)
-{
-	unsigned long tag;
-
-	__asm__ __volatile__("ldxa	[%1] %2, %0"
-			     : "=r" (tag)
-			     : "r" ((tlb << 16) | (entry << 3)), "i" (ASI_DTLB_TAG_READ));
-	return tag;
-}
-
-static inline void cheetah_put_dtlb_data(int entry, unsigned long data, int tlb)
-{
-	__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
-			     "membar	#Sync"
-			     : /* No outputs */
-			     : "r" (data),
-			       "r" ((tlb << 16) | (entry << 3)),
-			       "i" (ASI_DTLB_DATA_ACCESS));
-}
-
-static inline unsigned long cheetah_get_itlb_data(int entry)
-{
-	unsigned long data;
-
-	__asm__ __volatile__("ldxa	[%1] %2, %%g0\n\t"
-			     "ldxa	[%1] %2, %0"
-			     : "=r" (data)
-			     : "r" ((2 << 16) | (entry << 3)),
-                               "i" (ASI_ITLB_DATA_ACCESS));
-
-	return data;
-}
-
-static inline unsigned long cheetah_get_itlb_tag(int entry)
-{
-	unsigned long tag;
-
-	__asm__ __volatile__("ldxa	[%1] %2, %0"
-			     : "=r" (tag)
-			     : "r" ((2 << 16) | (entry << 3)), "i" (ASI_ITLB_TAG_READ));
-	return tag;
-}
-
-static inline void cheetah_put_itlb_data(int entry, unsigned long data)
-{
-	__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
-			     "membar	#Sync"
-			     : /* No outputs */
-			     : "r" (data), "r" ((2 << 16) | (entry << 3)),
-			       "i" (ASI_ITLB_DATA_ACCESS));
-}
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(_SPARC64_SPITFIRE_H) */
+#include <asm-sparc/spitfire.h>
diff --git a/include/asm-sparc64/sstate.h b/include/asm-sparc64/sstate.h
index a7c35db..97720ce 100644
--- a/include/asm-sparc64/sstate.h
+++ b/include/asm-sparc64/sstate.h
@@ -1,13 +1 @@
-#ifndef _SPARC64_SSTATE_H
-#define _SPARC64_SSTATE_H
-
-extern void sstate_booting(void);
-extern void sstate_running(void);
-extern void sstate_halt(void);
-extern void sstate_poweroff(void);
-extern void sstate_panic(void);
-extern void sstate_reboot(void);
-
-extern void sun4v_sstate_init(void);
-
-#endif /* _SPARC64_SSTATE_H */
+#include <asm-sparc/sstate.h>
diff --git a/include/asm-sparc64/stacktrace.h b/include/asm-sparc64/stacktrace.h
index 6cee39a..adc9b92c 100644
--- a/include/asm-sparc64/stacktrace.h
+++ b/include/asm-sparc64/stacktrace.h
@@ -1,6 +1 @@
-#ifndef _SPARC64_STACKTRACE_H
-#define _SPARC64_STACKTRACE_H
-
-extern void stack_trace_flush(void);
-
-#endif /* _SPARC64_STACKTRACE_H */
+#include <asm-sparc/stacktrace.h>
diff --git a/include/asm-sparc64/starfire.h b/include/asm-sparc64/starfire.h
index 07bafd3..db97daa 100644
--- a/include/asm-sparc64/starfire.h
+++ b/include/asm-sparc64/starfire.h
@@ -1,21 +1 @@
-/*
- * starfire.h: Group all starfire specific code together.
- *
- * Copyright (C) 2000 Anton Blanchard (anton@samba.org)
- */
-
-#ifndef _SPARC64_STARFIRE_H
-#define _SPARC64_STARFIRE_H
-
-#ifndef __ASSEMBLY__
-
-extern int this_is_starfire;
-
-extern void check_if_starfire(void);
-extern void starfire_cpu_setup(void);
-extern int starfire_hard_smp_processor_id(void);
-extern void starfire_hookup(int);
-extern unsigned int starfire_translate(unsigned long imap, unsigned int upaid);
-
-#endif
-#endif
+#include <asm-sparc/starfire.h>
diff --git a/include/asm-sparc64/stat.h b/include/asm-sparc64/stat.h
index 9650fde..b108a86 100644
--- a/include/asm-sparc64/stat.h
+++ b/include/asm-sparc64/stat.h
@@ -1,47 +1 @@
-#ifndef _SPARC64_STAT_H
-#define _SPARC64_STAT_H
-
-#include <linux/types.h>
-
-struct stat {
-	unsigned   st_dev;
-	ino_t   st_ino;
-	mode_t  st_mode;
-	short   st_nlink;
-	uid_t   st_uid;
-	gid_t   st_gid;
-	unsigned   st_rdev;
-	off_t   st_size;
-	time_t  st_atime;
-	time_t  st_mtime;
-	time_t  st_ctime;
-	off_t   st_blksize;
-	off_t   st_blocks;
-	unsigned long  __unused4[2];
-};
-
-struct stat64 {
-	unsigned long	st_dev;
-	unsigned long	st_ino;
-	unsigned long	st_nlink;
-
-	unsigned int	st_mode;
-	unsigned int	st_uid;
-	unsigned int	st_gid;
-	unsigned int	__pad0;
-
-	unsigned long	st_rdev;
-	long		st_size;
-	long		st_blksize;
-	long		st_blocks;
-
-	unsigned long	st_atime;
-	unsigned long	st_atime_nsec;
-	unsigned long	st_mtime;
-	unsigned long	st_mtime_nsec;
-	unsigned long	st_ctime;
-	unsigned long	st_ctime_nsec;
-	long		__unused[3];
-};
-
-#endif
+#include <asm-sparc/stat.h>
diff --git a/include/asm-sparc64/statfs.h b/include/asm-sparc64/statfs.h
index 79b3c89..5503d6a 100644
--- a/include/asm-sparc64/statfs.h
+++ b/include/asm-sparc64/statfs.h
@@ -1,54 +1 @@
-#ifndef _SPARC64_STATFS_H
-#define _SPARC64_STATFS_H
-
-#ifndef __KERNEL_STRICT_NAMES
-
-#include <linux/types.h>
-
-typedef __kernel_fsid_t	fsid_t;
-
-#endif
-
-struct statfs {
-	long f_type;
-	long f_bsize;
-	long f_blocks;
-	long f_bfree;
-	long f_bavail;
-	long f_files;
-	long f_ffree;
-	__kernel_fsid_t f_fsid;
-	long f_namelen;
-	long f_frsize;
-	long f_spare[5];
-};
-
-struct statfs64 {
-	long f_type;
-	long f_bsize;
-	long f_blocks;
-	long f_bfree;
-	long f_bavail;
-	long f_files;
-	long f_ffree;
-	__kernel_fsid_t f_fsid;
-	long f_namelen;
-	long f_frsize;
-	long f_spare[5];
-};
-
-struct compat_statfs64 {
-	__u32 f_type;
-	__u32 f_bsize;
-	__u64 f_blocks;
-	__u64 f_bfree;
-	__u64 f_bavail;
-	__u64 f_files;
-	__u64 f_ffree;
-	__kernel_fsid_t f_fsid;
-	__u32 f_namelen;
-	__u32 f_frsize;
-	__u32 f_spare[5];
-};
-
-#endif
+#include <asm-sparc/statfs.h>
diff --git a/include/asm-sparc64/string.h b/include/asm-sparc64/string.h
index 43161f2..5018cd8 100644
--- a/include/asm-sparc64/string.h
+++ b/include/asm-sparc64/string.h
@@ -1,83 +1 @@
-/*
- * string.h: External definitions for optimized assembly string
- *           routines for the Linux Kernel.
- *
- * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1996,1997,1999 Jakub Jelinek (jakub@redhat.com)
- */
-
-#ifndef __SPARC64_STRING_H__
-#define __SPARC64_STRING_H__
-
-/* Really, userland/ksyms should not see any of this stuff. */
-
-#ifdef __KERNEL__
-
-#include <asm/asi.h>
-
-extern void *__memset(void *,int,__kernel_size_t);
-
-#ifndef EXPORT_SYMTAB_STROPS
-
-/* First the mem*() things. */
-#define __HAVE_ARCH_MEMMOVE
-extern void *memmove(void *, const void *, __kernel_size_t);
-
-#define __HAVE_ARCH_MEMCPY
-extern void *memcpy(void *, const void *, __kernel_size_t);
-
-#define __HAVE_ARCH_MEMSET
-extern void *__builtin_memset(void *,int,__kernel_size_t);
-
-static inline void *__constant_memset(void *s, int c, __kernel_size_t count)
-{
-	extern __kernel_size_t __bzero(void *, __kernel_size_t);
-
-	if (!c) {
-		__bzero(s, count);
-		return s;
-	} else
-		return __memset(s, c, count);
-}
-
-#undef memset
-#define memset(s, c, count) \
-((__builtin_constant_p(count) && (count) <= 32) ? \
- __builtin_memset((s), (c), (count)) : \
- (__builtin_constant_p(c) ? \
-  __constant_memset((s), (c), (count)) : \
-  __memset((s), (c), (count))))
-
-#define __HAVE_ARCH_MEMSCAN
-
-#undef memscan
-#define memscan(__arg0, __char, __arg2)					\
-({									\
-	extern void *__memscan_zero(void *, size_t);			\
-	extern void *__memscan_generic(void *, int, size_t);		\
-	void *__retval, *__addr = (__arg0);				\
-	size_t __size = (__arg2);					\
-									\
-	if(__builtin_constant_p(__char) && !(__char))			\
-		__retval = __memscan_zero(__addr, __size);		\
-	else								\
-		__retval = __memscan_generic(__addr, (__char), __size);	\
-									\
-	__retval;							\
-})
-
-#define __HAVE_ARCH_MEMCMP
-extern int memcmp(const void *,const void *,__kernel_size_t);
-
-/* Now the str*() stuff... */
-#define __HAVE_ARCH_STRLEN
-extern __kernel_size_t strlen(const char *);
-
-#define __HAVE_ARCH_STRNCMP
-extern int strncmp(const char *, const char *, __kernel_size_t);
-
-#endif /* !EXPORT_SYMTAB_STROPS */
-
-#endif /* __KERNEL__ */
-
-#endif /* !(__SPARC64_STRING_H__) */
+#include <asm-sparc/string.h>
diff --git a/include/asm-sparc64/sunbpp.h b/include/asm-sparc64/sunbpp.h
index 8e171b7..9632be2 100644
--- a/include/asm-sparc64/sunbpp.h
+++ b/include/asm-sparc64/sunbpp.h
@@ -1,80 +1 @@
-/*
- * include/asm-sparc64/sunbpp.h
- */
-
-#ifndef _ASM_SPARC64_SUNBPP_H
-#define _ASM_SPARC64_SUNBPP_H
-
-struct bpp_regs {
-  /* DMA registers */
-  __volatile__ __u32 p_csr;		/* DMA Control/Status Register */
-  __volatile__ __u32 p_addr;		/* Address Register */
-  __volatile__ __u32 p_bcnt;		/* Byte Count Register */
-  __volatile__ __u32 p_tst_csr;		/* Test Control/Status (DMA2 only) */
-  /* Parallel Port registers */
-  __volatile__ __u16 p_hcr;		/* Hardware Configuration Register */
-  __volatile__ __u16 p_ocr;		/* Operation Configuration Register */
-  __volatile__ __u8 p_dr;		/* Parallel Data Register */
-  __volatile__ __u8 p_tcr;		/* Transfer Control Register */
-  __volatile__ __u8 p_or;		/* Output Register */
-  __volatile__ __u8 p_ir;		/* Input Register */
-  __volatile__ __u16 p_icr;		/* Interrupt Control Register */
-};
-
-/* P_HCR. Time is in increments of SBus clock. */
-#define P_HCR_TEST      0x8000      /* Allows buried counters to be read */
-#define P_HCR_DSW       0x7f00      /* Data strobe width (in ticks) */
-#define P_HCR_DDS       0x007f      /* Data setup before strobe (in ticks) */
-
-/* P_OCR. */
-#define P_OCR_MEM_CLR   0x8000
-#define P_OCR_DATA_SRC  0x4000      /* )                  */
-#define P_OCR_DS_DSEL   0x2000      /* )  Bidirectional      */
-#define P_OCR_BUSY_DSEL 0x1000      /* )    selects            */
-#define P_OCR_ACK_DSEL  0x0800      /* )                  */
-#define P_OCR_EN_DIAG   0x0400
-#define P_OCR_BUSY_OP   0x0200      /* Busy operation */
-#define P_OCR_ACK_OP    0x0100      /* Ack operation */
-#define P_OCR_SRST      0x0080      /* Reset state machines. Not selfcleaning. */
-#define P_OCR_IDLE      0x0008      /* PP data transfer state machine is idle */
-#define P_OCR_V_ILCK    0x0002      /* Versatec faded. Zebra only. */
-#define P_OCR_EN_VER    0x0001      /* Enable Versatec (0 - enable). Zebra only. */
-
-/* P_TCR */
-#define P_TCR_DIR       0x08
-#define P_TCR_BUSY      0x04
-#define P_TCR_ACK       0x02
-#define P_TCR_DS        0x01        /* Strobe */
-
-/* P_OR */
-#define P_OR_V3         0x20        /* )                 */
-#define P_OR_V2         0x10        /* ) on Zebra only   */
-#define P_OR_V1         0x08        /* )                 */
-#define P_OR_INIT       0x04
-#define P_OR_AFXN       0x02        /* Auto Feed */
-#define P_OR_SLCT_IN    0x01
-
-/* P_IR */
-#define P_IR_PE         0x04
-#define P_IR_SLCT       0x02
-#define P_IR_ERR        0x01
-
-/* P_ICR */
-#define P_DS_IRQ        0x8000      /* RW1  */
-#define P_ACK_IRQ       0x4000      /* RW1  */
-#define P_BUSY_IRQ      0x2000      /* RW1  */
-#define P_PE_IRQ        0x1000      /* RW1  */
-#define P_SLCT_IRQ      0x0800      /* RW1  */
-#define P_ERR_IRQ       0x0400      /* RW1  */
-#define P_DS_IRQ_EN     0x0200      /* RW   Always on rising edge */
-#define P_ACK_IRQ_EN    0x0100      /* RW   Always on rising edge */
-#define P_BUSY_IRP      0x0080      /* RW   1= rising edge */
-#define P_BUSY_IRQ_EN   0x0040      /* RW   */
-#define P_PE_IRP        0x0020      /* RW   1= rising edge */
-#define P_PE_IRQ_EN     0x0010      /* RW   */
-#define P_SLCT_IRP      0x0008      /* RW   1= rising edge */
-#define P_SLCT_IRQ_EN   0x0004      /* RW   */
-#define P_ERR_IRP       0x0002      /* RW1  1= rising edge */
-#define P_ERR_IRQ_EN    0x0001      /* RW   */
-
-#endif /* !(_ASM_SPARC64_SUNBPP_H) */
+#include <asm-sparc/sunbpp.h>
diff --git a/include/asm-sparc64/syscalls.h b/include/asm-sparc64/syscalls.h
index 45a43f6..3477b16 100644
--- a/include/asm-sparc64/syscalls.h
+++ b/include/asm-sparc64/syscalls.h
@@ -1,13 +1 @@
-#ifndef _SPARC64_SYSCALLS_H
-#define _SPARC64_SYSCALLS_H
-
-struct pt_regs;
-
-extern asmlinkage long sparc_do_fork(unsigned long clone_flags,
-				     unsigned long stack_start,
-				     struct pt_regs *regs,
-				     unsigned long stack_size);
-
-extern asmlinkage int sparc_execve(struct pt_regs *regs);
-
-#endif /* _SPARC64_SYSCALLS_H */
+#include <asm-sparc/syscalls.h>
diff --git a/include/asm-sparc64/system.h b/include/asm-sparc64/system.h
index 6897ac3..be2603c 100644
--- a/include/asm-sparc64/system.h
+++ b/include/asm-sparc64/system.h
@@ -1,355 +1 @@
-#ifndef __SPARC64_SYSTEM_H
-#define __SPARC64_SYSTEM_H
-
-#include <asm/ptrace.h>
-#include <asm/processor.h>
-#include <asm/visasm.h>
-
-#ifndef __ASSEMBLY__
-
-#include <linux/irqflags.h>
-#include <asm-generic/cmpxchg-local.h>
-
-/*
- * Sparc (general) CPU types
- */
-enum sparc_cpu {
-  sun4        = 0x00,
-  sun4c       = 0x01,
-  sun4m       = 0x02,
-  sun4d       = 0x03,
-  sun4e       = 0x04,
-  sun4u       = 0x05, /* V8 ploos ploos */
-  sun_unknown = 0x06,
-  ap1000      = 0x07, /* almost a sun4m */
-};
-                  
-#define sparc_cpu_model sun4u
-
-/* This cannot ever be a sun4c nor sun4 :) That's just history. */
-#define ARCH_SUN4C_SUN4 0
-#define ARCH_SUN4 0
-
-extern char reboot_command[];
-
-/* These are here in an effort to more fully work around Spitfire Errata
- * #51.  Essentially, if a memory barrier occurs soon after a mispredicted
- * branch, the chip can stop executing instructions until a trap occurs.
- * Therefore, if interrupts are disabled, the chip can hang forever.
- *
- * It used to be believed that the memory barrier had to be right in the
- * delay slot, but a case has been traced recently wherein the memory barrier
- * was one instruction after the branch delay slot and the chip still hung.
- * The offending sequence was the following in sym_wakeup_done() of the
- * sym53c8xx_2 driver:
- *
- *	call	sym_ccb_from_dsa, 0
- *	 movge	%icc, 0, %l0
- *	brz,pn	%o0, .LL1303
- *	 mov	%o0, %l2
- *	membar	#LoadLoad
- *
- * The branch has to be mispredicted for the bug to occur.  Therefore, we put
- * the memory barrier explicitly into a "branch always, predicted taken"
- * delay slot to avoid the problem case.
- */
-#define membar_safe(type) \
-do {	__asm__ __volatile__("ba,pt	%%xcc, 1f\n\t" \
-			     " membar	" type "\n" \
-			     "1:\n" \
-			     : : : "memory"); \
-} while (0)
-
-#define mb()	\
-	membar_safe("#LoadLoad | #LoadStore | #StoreStore | #StoreLoad")
-#define rmb()	\
-	membar_safe("#LoadLoad")
-#define wmb()	\
-	membar_safe("#StoreStore")
-#define membar_storeload() \
-	membar_safe("#StoreLoad")
-#define membar_storeload_storestore() \
-	membar_safe("#StoreLoad | #StoreStore")
-#define membar_storeload_loadload() \
-	membar_safe("#StoreLoad | #LoadLoad")
-#define membar_storestore_loadstore() \
-	membar_safe("#StoreStore | #LoadStore")
-
-#endif
-
-#define nop() 		__asm__ __volatile__ ("nop")
-
-#define read_barrier_depends()		do { } while(0)
-#define set_mb(__var, __value) \
-	do { __var = __value; membar_storeload_storestore(); } while(0)
-
-#ifdef CONFIG_SMP
-#define smp_mb()	mb()
-#define smp_rmb()	rmb()
-#define smp_wmb()	wmb()
-#define smp_read_barrier_depends()	read_barrier_depends()
-#else
-#define smp_mb()	__asm__ __volatile__("":::"memory")
-#define smp_rmb()	__asm__ __volatile__("":::"memory")
-#define smp_wmb()	__asm__ __volatile__("":::"memory")
-#define smp_read_barrier_depends()	do { } while(0)
-#endif
-
-#define flushi(addr)	__asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory")
-
-#define flushw_all()	__asm__ __volatile__("flushw")
-
-/* Performance counter register access. */
-#define read_pcr(__p)  __asm__ __volatile__("rd	%%pcr, %0" : "=r" (__p))
-#define write_pcr(__p) __asm__ __volatile__("wr	%0, 0x0, %%pcr" : : "r" (__p))
-#define read_pic(__p)  __asm__ __volatile__("rd %%pic, %0" : "=r" (__p))
-
-/* Blackbird errata workaround.  See commentary in
- * arch/sparc64/kernel/smp.c:smp_percpu_timer_interrupt()
- * for more information.
- */
-#define reset_pic()    						\
-	__asm__ __volatile__("ba,pt	%xcc, 99f\n\t"		\
-			     ".align	64\n"			\
-			  "99:wr	%g0, 0x0, %pic\n\t"	\
-			     "rd	%pic, %g0")
-
-#ifndef __ASSEMBLY__
-
-extern void sun_do_break(void);
-extern int stop_a_enabled;
-
-extern void fault_in_user_windows(void);
-extern void synchronize_user_stack(void);
-
-extern void __flushw_user(void);
-#define flushw_user() __flushw_user()
-
-#define flush_user_windows flushw_user
-#define flush_register_windows flushw_all
-
-/* Don't hold the runqueue lock over context switch */
-#define __ARCH_WANT_UNLOCKED_CTXSW
-#define prepare_arch_switch(next)		\
-do {						\
-	flushw_all();				\
-} while (0)
-
-	/* See what happens when you design the chip correctly?
-	 *
-	 * We tell gcc we clobber all non-fixed-usage registers except
-	 * for l0/l1.  It will use one for 'next' and the other to hold
-	 * the output value of 'last'.  'next' is not referenced again
-	 * past the invocation of switch_to in the scheduler, so we need
-	 * not preserve it's value.  Hairy, but it lets us remove 2 loads
-	 * and 2 stores in this critical code path.  -DaveM
-	 */
-#define switch_to(prev, next, last)					\
-do {	if (test_thread_flag(TIF_PERFCTR)) {				\
-		unsigned long __tmp;					\
-		read_pcr(__tmp);					\
-		current_thread_info()->pcr_reg = __tmp;			\
-		read_pic(__tmp);					\
-		current_thread_info()->kernel_cntd0 += (unsigned int)(__tmp);\
-		current_thread_info()->kernel_cntd1 += ((__tmp) >> 32);	\
-	}								\
-	flush_tlb_pending();						\
-	save_and_clear_fpu();						\
-	/* If you are tempted to conditionalize the following */	\
-	/* so that ASI is only written if it changes, think again. */	\
-	__asm__ __volatile__("wr %%g0, %0, %%asi"			\
-	: : "r" (__thread_flag_byte_ptr(task_thread_info(next))[TI_FLAG_BYTE_CURRENT_DS]));\
-	trap_block[current_thread_info()->cpu].thread =			\
-		task_thread_info(next);					\
-	__asm__ __volatile__(						\
-	"mov	%%g4, %%g7\n\t"						\
-	"stx	%%i6, [%%sp + 2047 + 0x70]\n\t"				\
-	"stx	%%i7, [%%sp + 2047 + 0x78]\n\t"				\
-	"rdpr	%%wstate, %%o5\n\t"					\
-	"stx	%%o6, [%%g6 + %6]\n\t"					\
-	"stb	%%o5, [%%g6 + %5]\n\t"					\
-	"rdpr	%%cwp, %%o5\n\t"					\
-	"stb	%%o5, [%%g6 + %8]\n\t"					\
-	"mov	%4, %%g6\n\t"						\
-	"ldub	[%4 + %8], %%g1\n\t"					\
-	"wrpr	%%g1, %%cwp\n\t"					\
-	"ldx	[%%g6 + %6], %%o6\n\t"					\
-	"ldub	[%%g6 + %5], %%o5\n\t"					\
-	"ldub	[%%g6 + %7], %%o7\n\t"					\
-	"wrpr	%%o5, 0x0, %%wstate\n\t"				\
-	"ldx	[%%sp + 2047 + 0x70], %%i6\n\t"				\
-	"ldx	[%%sp + 2047 + 0x78], %%i7\n\t"				\
-	"ldx	[%%g6 + %9], %%g4\n\t"					\
-	"brz,pt %%o7, switch_to_pc\n\t"					\
-	" mov	%%g7, %0\n\t"						\
-	"sethi	%%hi(ret_from_syscall), %%g1\n\t"			\
-	"jmpl	%%g1 + %%lo(ret_from_syscall), %%g0\n\t"		\
-	" nop\n\t"							\
-	".globl switch_to_pc\n\t"					\
-	"switch_to_pc:\n\t"						\
-	: "=&r" (last), "=r" (current), "=r" (current_thread_info_reg),	\
-	  "=r" (__local_per_cpu_offset)					\
-	: "0" (task_thread_info(next)),					\
-	  "i" (TI_WSTATE), "i" (TI_KSP), "i" (TI_NEW_CHILD),            \
-	  "i" (TI_CWP), "i" (TI_TASK)					\
-	: "cc",								\
-	        "g1", "g2", "g3",                   "g7",		\
-	        "l1", "l2", "l3", "l4", "l5", "l6", "l7",		\
-	  "i0", "i1", "i2", "i3", "i4", "i5",				\
-	  "o0", "o1", "o2", "o3", "o4", "o5",       "o7");		\
-	/* If you fuck with this, update ret_from_syscall code too. */	\
-	if (test_thread_flag(TIF_PERFCTR)) {				\
-		write_pcr(current_thread_info()->pcr_reg);		\
-		reset_pic();						\
-	}								\
-} while(0)
-
-static inline unsigned long xchg32(__volatile__ unsigned int *m, unsigned int val)
-{
-	unsigned long tmp1, tmp2;
-
-	__asm__ __volatile__(
-"	membar		#StoreLoad | #LoadLoad\n"
-"	mov		%0, %1\n"
-"1:	lduw		[%4], %2\n"
-"	cas		[%4], %2, %0\n"
-"	cmp		%2, %0\n"
-"	bne,a,pn	%%icc, 1b\n"
-"	 mov		%1, %0\n"
-"	membar		#StoreLoad | #StoreStore\n"
-	: "=&r" (val), "=&r" (tmp1), "=&r" (tmp2)
-	: "0" (val), "r" (m)
-	: "cc", "memory");
-	return val;
-}
-
-static inline unsigned long xchg64(__volatile__ unsigned long *m, unsigned long val)
-{
-	unsigned long tmp1, tmp2;
-
-	__asm__ __volatile__(
-"	membar		#StoreLoad | #LoadLoad\n"
-"	mov		%0, %1\n"
-"1:	ldx		[%4], %2\n"
-"	casx		[%4], %2, %0\n"
-"	cmp		%2, %0\n"
-"	bne,a,pn	%%xcc, 1b\n"
-"	 mov		%1, %0\n"
-"	membar		#StoreLoad | #StoreStore\n"
-	: "=&r" (val), "=&r" (tmp1), "=&r" (tmp2)
-	: "0" (val), "r" (m)
-	: "cc", "memory");
-	return val;
-}
-
-#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-extern void __xchg_called_with_bad_pointer(void);
-
-static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr,
-				       int size)
-{
-	switch (size) {
-	case 4:
-		return xchg32(ptr, x);
-	case 8:
-		return xchg64(ptr, x);
-	};
-	__xchg_called_with_bad_pointer();
-	return x;
-}
-
-extern void die_if_kernel(char *str, struct pt_regs *regs) __attribute__ ((noreturn));
-
-/* 
- * Atomic compare and exchange.  Compare OLD with MEM, if identical,
- * store NEW in MEM.  Return the initial value in MEM.  Success is
- * indicated by comparing RETURN with OLD.
- */
-
-#define __HAVE_ARCH_CMPXCHG 1
-
-static inline unsigned long
-__cmpxchg_u32(volatile int *m, int old, int new)
-{
-	__asm__ __volatile__("membar #StoreLoad | #LoadLoad\n"
-			     "cas [%2], %3, %0\n\t"
-			     "membar #StoreLoad | #StoreStore"
-			     : "=&r" (new)
-			     : "0" (new), "r" (m), "r" (old)
-			     : "memory");
-
-	return new;
-}
-
-static inline unsigned long
-__cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new)
-{
-	__asm__ __volatile__("membar #StoreLoad | #LoadLoad\n"
-			     "casx [%2], %3, %0\n\t"
-			     "membar #StoreLoad | #StoreStore"
-			     : "=&r" (new)
-			     : "0" (new), "r" (m), "r" (old)
-			     : "memory");
-
-	return new;
-}
-
-/* This function doesn't exist, so you'll get a linker error
-   if something tries to do an invalid cmpxchg().  */
-extern void __cmpxchg_called_with_bad_pointer(void);
-
-static inline unsigned long
-__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
-{
-	switch (size) {
-		case 4:
-			return __cmpxchg_u32(ptr, old, new);
-		case 8:
-			return __cmpxchg_u64(ptr, old, new);
-	}
-	__cmpxchg_called_with_bad_pointer();
-	return old;
-}
-
-#define cmpxchg(ptr,o,n)						 \
-  ({									 \
-     __typeof__(*(ptr)) _o_ = (o);					 \
-     __typeof__(*(ptr)) _n_ = (n);					 \
-     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,		 \
-				    (unsigned long)_n_, sizeof(*(ptr))); \
-  })
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-
-static inline unsigned long __cmpxchg_local(volatile void *ptr,
-				      unsigned long old,
-				      unsigned long new, int size)
-{
-	switch (size) {
-	case 4:
-	case 8:	return __cmpxchg(ptr, old, new, size);
-	default:
-		return __cmpxchg_local_generic(ptr, old, new, size);
-	}
-
-	return old;
-}
-
-#define cmpxchg_local(ptr, o, n)				  	\
-	((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o),	\
-			(unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n)					\
-  ({									\
-	BUILD_BUG_ON(sizeof(*(ptr)) != 8);				\
-	cmpxchg_local((ptr), (o), (n));					\
-  })
-
-#endif /* !(__ASSEMBLY__) */
-
-#define arch_align_stack(x) (x)
-
-#endif /* !(__SPARC64_SYSTEM_H) */
+#include <asm-sparc/system.h>
diff --git a/include/asm-sparc64/termbits.h b/include/asm-sparc64/termbits.h
index ebe31c1..e03f975 100644
--- a/include/asm-sparc64/termbits.h
+++ b/include/asm-sparc64/termbits.h
@@ -1,260 +1 @@
-#ifndef _SPARC64_TERMBITS_H
-#define _SPARC64_TERMBITS_H
-
-#include <linux/posix_types.h>
-
-typedef unsigned char   cc_t;
-typedef unsigned int    speed_t;
-typedef unsigned int    tcflag_t;
-
-#define NCC 8
-struct termio {
-	unsigned short c_iflag;		/* input mode flags */
-	unsigned short c_oflag;		/* output mode flags */
-	unsigned short c_cflag;		/* control mode flags */
-	unsigned short c_lflag;		/* local mode flags */
-	unsigned char c_line;		/* line discipline */
-	unsigned char c_cc[NCC];	/* control characters */
-};
-
-#define NCCS 17
-struct termios {
-	tcflag_t c_iflag;		/* input mode flags */
-	tcflag_t c_oflag;		/* output mode flags */
-	tcflag_t c_cflag;		/* control mode flags */
-	tcflag_t c_lflag;		/* local mode flags */
-	cc_t c_line;			/* line discipline */
-	cc_t c_cc[NCCS];		/* control characters */
-#ifdef __KERNEL__
-#define SIZEOF_USER_TERMIOS sizeof (struct termios) - (2*sizeof (cc_t))
-	cc_t _x_cc[2];                  /* We need them to hold vmin/vtime */
-#endif
-};
-
-struct termios2 {
-	tcflag_t c_iflag;		/* input mode flags */
-	tcflag_t c_oflag;		/* output mode flags */
-	tcflag_t c_cflag;		/* control mode flags */
-	tcflag_t c_lflag;		/* local mode flags */
-	cc_t c_line;			/* line discipline */
-	cc_t c_cc[NCCS];		/* control characters */
-	cc_t _x_cc[2];                  /* padding to match ktermios */
-	speed_t c_ispeed;		/* input speed */
-	speed_t c_ospeed;		/* output speed */
-};
-
-struct ktermios {
-	tcflag_t c_iflag;		/* input mode flags */
-	tcflag_t c_oflag;		/* output mode flags */
-	tcflag_t c_cflag;		/* control mode flags */
-	tcflag_t c_lflag;		/* local mode flags */
-	cc_t c_line;			/* line discipline */
-	cc_t c_cc[NCCS];		/* control characters */
-	cc_t _x_cc[2];                  /* We need them to hold vmin/vtime */
-	speed_t c_ispeed;		/* input speed */
-	speed_t c_ospeed;		/* output speed */
-};
-
-/* c_cc characters */
-#define VINTR    0
-#define VQUIT    1
-#define VERASE   2
-#define VKILL    3
-#define VEOF     4
-#define VEOL     5
-#define VEOL2    6
-#define VSWTC    7
-#define VSTART   8
-#define VSTOP    9
-
-
-
-#define VSUSP    10
-#define VDSUSP   11  /* SunOS POSIX nicety I do believe... */
-#define VREPRINT 12
-#define VDISCARD 13
-#define VWERASE  14
-#define VLNEXT   15
-
-/* Kernel keeps vmin/vtime separated, user apps assume vmin/vtime is
- * shared with eof/eol
- */
-#ifdef __KERNEL__
-#define VMIN     16
-#define VTIME    17
-#else
-#define VMIN     VEOF
-#define VTIME    VEOL
-#endif
-
-/* c_iflag bits */
-#define IGNBRK	0x00000001
-#define BRKINT	0x00000002
-#define IGNPAR	0x00000004
-#define PARMRK	0x00000008
-#define INPCK	0x00000010
-#define ISTRIP	0x00000020
-#define INLCR	0x00000040
-#define IGNCR	0x00000080
-#define ICRNL	0x00000100
-#define IUCLC	0x00000200
-#define IXON	0x00000400
-#define IXANY	0x00000800
-#define IXOFF	0x00001000
-#define IMAXBEL	0x00002000
-#define IUTF8	0x00004000
-
-/* c_oflag bits */
-#define OPOST	0x00000001
-#define OLCUC	0x00000002
-#define ONLCR	0x00000004
-#define OCRNL	0x00000008
-#define ONOCR	0x00000010
-#define ONLRET	0x00000020
-#define OFILL	0x00000040
-#define OFDEL	0x00000080
-#define NLDLY	0x00000100
-#define   NL0	0x00000000
-#define   NL1	0x00000100
-#define CRDLY	0x00000600
-#define   CR0	0x00000000
-#define   CR1	0x00000200
-#define   CR2	0x00000400
-#define   CR3	0x00000600
-#define TABDLY	0x00001800
-#define   TAB0	0x00000000
-#define   TAB1	0x00000800
-#define   TAB2	0x00001000
-#define   TAB3	0x00001800
-#define   XTABS	0x00001800
-#define BSDLY	0x00002000
-#define   BS0	0x00000000
-#define   BS1	0x00002000
-#define VTDLY	0x00004000
-#define   VT0	0x00000000
-#define   VT1	0x00004000
-#define FFDLY	0x00008000
-#define   FF0	0x00000000
-#define   FF1	0x00008000
-#define PAGEOUT 0x00010000  /* SUNOS specific */
-#define WRAP    0x00020000  /* SUNOS specific */
-
-/* c_cflag bit meaning */
-#define CBAUD	  0x0000100f
-#define  B0	  0x00000000   /* hang up */
-#define  B50	  0x00000001
-#define  B75	  0x00000002
-#define  B110	  0x00000003
-#define  B134	  0x00000004
-#define  B150	  0x00000005
-#define  B200	  0x00000006
-#define  B300	  0x00000007
-#define  B600	  0x00000008
-#define  B1200	  0x00000009
-#define  B1800	  0x0000000a
-#define  B2400	  0x0000000b
-#define  B4800	  0x0000000c
-#define  B9600	  0x0000000d
-#define  B19200	  0x0000000e
-#define  B38400	  0x0000000f
-#define EXTA      B19200
-#define EXTB      B38400
-#define  CSIZE    0x00000030
-#define   CS5	  0x00000000
-#define   CS6	  0x00000010
-#define   CS7	  0x00000020
-#define   CS8	  0x00000030
-#define CSTOPB	  0x00000040
-#define CREAD	  0x00000080
-#define PARENB	  0x00000100
-#define PARODD	  0x00000200
-#define HUPCL	  0x00000400
-#define CLOCAL	  0x00000800
-#define CBAUDEX   0x00001000
-#define  BOTHER   0x00001000
-#define  B57600   0x00001001
-#define  B115200  0x00001002
-#define  B230400  0x00001003
-#define  B460800  0x00001004
-/* This is what we can do with the Zilogs. */
-#define  B76800   0x00001005
-/* This is what we can do with the SAB82532. */
-#define  B153600  0x00001006
-#define  B307200  0x00001007
-#define  B614400  0x00001008
-#define  B921600  0x00001009
-/* And these are the rest... */
-#define  B500000  0x0000100a
-#define  B576000  0x0000100b
-#define B1000000  0x0000100c
-#define B1152000  0x0000100d
-#define B1500000  0x0000100e
-#define B2000000  0x0000100f
-/* These have totally bogus values and nobody uses them
-   so far. Later on we'd have to use say 0x10000x and
-   adjust CBAUD constant and drivers accordingly.
-#define B2500000  0x00001010
-#define B3000000  0x00001011
-#define B3500000  0x00001012
-#define B4000000  0x00001013  */
-#define CIBAUD	  0x100f0000  /* input baud rate (not used) */
-#define CMSPAR    0x40000000  /* mark or space (stick) parity */
-#define CRTSCTS	  0x80000000  /* flow control */
-
-#define IBSHIFT	  16		/* Shift from CBAUD to CIBAUD */
-
-/* c_lflag bits */
-#define ISIG	0x00000001
-#define ICANON	0x00000002
-#define XCASE	0x00000004
-#define ECHO	0x00000008
-#define ECHOE	0x00000010
-#define ECHOK	0x00000020
-#define ECHONL	0x00000040
-#define NOFLSH	0x00000080
-#define TOSTOP	0x00000100
-#define ECHOCTL	0x00000200
-#define ECHOPRT	0x00000400
-#define ECHOKE	0x00000800
-#define DEFECHO 0x00001000  /* SUNOS thing, what is it? */
-#define FLUSHO	0x00002000
-#define PENDIN	0x00004000
-#define IEXTEN	0x00008000
-
-/* modem lines */
-#define TIOCM_LE	0x001
-#define TIOCM_DTR	0x002
-#define TIOCM_RTS	0x004
-#define TIOCM_ST	0x008
-#define TIOCM_SR	0x010
-#define TIOCM_CTS	0x020
-#define TIOCM_CAR	0x040
-#define TIOCM_RNG	0x080
-#define TIOCM_DSR	0x100
-#define TIOCM_CD	TIOCM_CAR
-#define TIOCM_RI	TIOCM_RNG
-#define TIOCM_OUT1	0x2000
-#define TIOCM_OUT2	0x4000
-#define TIOCM_LOOP	0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
-
-
-/* tcflow() and TCXONC use these */
-#define	TCOOFF		0
-#define	TCOON		1
-#define	TCIOFF		2
-#define	TCION		3
-
-/* tcflush() and TCFLSH use these */
-#define	TCIFLUSH	0
-#define	TCOFLUSH	1
-#define	TCIOFLUSH	2
-
-/* tcsetattr uses these */
-#define	TCSANOW		0
-#define	TCSADRAIN	1
-#define	TCSAFLUSH	2
-
-#endif /* !(_SPARC64_TERMBITS_H) */
+#include <asm-sparc/termbits.h>
diff --git a/include/asm-sparc64/termios.h b/include/asm-sparc64/termios.h
index 1f5dab2..940495e 100644
--- a/include/asm-sparc64/termios.h
+++ b/include/asm-sparc64/termios.h
@@ -1,186 +1 @@
-#ifndef _SPARC64_TERMIOS_H
-#define _SPARC64_TERMIOS_H
-
-#include <asm/ioctls.h>
-#include <asm/termbits.h>
-
-#if defined(__KERNEL__) || defined(__DEFINE_BSD_TERMIOS)
-struct sgttyb {
-	char	sg_ispeed;
-	char	sg_ospeed;
-	char	sg_erase;
-	char	sg_kill;
-	short	sg_flags;
-};
-
-struct tchars {
-	char	t_intrc;
-	char	t_quitc;
-	char	t_startc;
-	char	t_stopc;
-	char	t_eofc;
-	char	t_brkc;
-};
-
-struct ltchars {
-	char	t_suspc;
-	char	t_dsuspc;
-	char	t_rprntc;
-	char	t_flushc;
-	char	t_werasc;
-	char	t_lnextc;
-};
-#endif /* __KERNEL__ */
-
-struct winsize {
-	unsigned short ws_row;
-	unsigned short ws_col;
-	unsigned short ws_xpixel;
-	unsigned short ws_ypixel;
-};
-
-#ifdef __KERNEL__
-#include <linux/module.h>
-
-/*
- * c_cc characters in the termio structure.  Oh, how I love being
- * backwardly compatible.  Notice that character 4 and 5 are
- * interpreted differently depending on whether ICANON is set in
- * c_lflag.  If it's set, they are used as _VEOF and _VEOL, otherwise
- * as _VMIN and V_TIME.  This is for compatibility with OSF/1 (which
- * is compatible with sysV)...
- */
-#define _VMIN	4
-#define _VTIME	5
-
-/*	intr=^C		quit=^\		erase=del	kill=^U
-	eof=^D		eol=\0		eol2=\0		sxtc=\0
-	start=^Q	stop=^S		susp=^Z		dsusp=^Y
-	reprint=^R	discard=^U	werase=^W	lnext=^V
-	vmin=\1         vtime=\0
-*/
-#define INIT_C_CC "\003\034\177\025\004\000\000\000\021\023\032\031\022\025\027\026\001"
-
-/*
- * Translate a "termio" structure into a "termios". Ugh.
- */
-#define user_termio_to_kernel_termios(termios, termio) \
-({ \
-	unsigned short tmp; \
-	int err; \
-	err = get_user(tmp, &(termio)->c_iflag); \
-	(termios)->c_iflag = (0xffff0000 & ((termios)->c_iflag)) | tmp; \
-	err |= get_user(tmp, &(termio)->c_oflag); \
-	(termios)->c_oflag = (0xffff0000 & ((termios)->c_oflag)) | tmp; \
-	err |= get_user(tmp, &(termio)->c_cflag); \
-	(termios)->c_cflag = (0xffff0000 & ((termios)->c_cflag)) | tmp; \
-	err |= get_user(tmp, &(termio)->c_lflag); \
-	(termios)->c_lflag = (0xffff0000 & ((termios)->c_lflag)) | tmp; \
-	err |= copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
-	err; \
-})
-
-/*
- * Translate a "termios" structure into a "termio". Ugh.
- *
- * Note the "fun" _VMIN overloading.
- */
-#define kernel_termios_to_user_termio(termio, termios) \
-({ \
-	int err; \
-	err  = put_user((termios)->c_iflag, &(termio)->c_iflag); \
-	err |= put_user((termios)->c_oflag, &(termio)->c_oflag); \
-	err |= put_user((termios)->c_cflag, &(termio)->c_cflag); \
-	err |= put_user((termios)->c_lflag, &(termio)->c_lflag); \
-	err |= put_user((termios)->c_line,  &(termio)->c_line); \
-	err |= copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
-	if (!((termios)->c_lflag & ICANON)) { \
-		err |= put_user((termios)->c_cc[VMIN], &(termio)->c_cc[_VMIN]); \
-		err |= put_user((termios)->c_cc[VTIME], &(termio)->c_cc[_VTIME]); \
-	} \
-	err; \
-})
-
-#define user_termios_to_kernel_termios(k, u) \
-({ \
-	int err; \
-	err  = get_user((k)->c_iflag, &(u)->c_iflag); \
-	err |= get_user((k)->c_oflag, &(u)->c_oflag); \
-	err |= get_user((k)->c_cflag, &(u)->c_cflag); \
-	err |= get_user((k)->c_lflag, &(u)->c_lflag); \
-	err |= get_user((k)->c_line,  &(u)->c_line); \
-	err |= copy_from_user((k)->c_cc, (u)->c_cc, NCCS); \
-	if((k)->c_lflag & ICANON) { \
-		err |= get_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \
-		err |= get_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \
-	} else { \
-		err |= get_user((k)->c_cc[VMIN],  &(u)->c_cc[_VMIN]); \
-		err |= get_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \
-	} \
-	err |= get_user((k)->c_ispeed,  &(u)->c_ispeed); \
-	err |= get_user((k)->c_ospeed,  &(u)->c_ospeed); \
-	err; \
-})
-
-#define kernel_termios_to_user_termios(u, k) \
-({ \
-	int err; \
-	err  = put_user((k)->c_iflag, &(u)->c_iflag); \
-	err |= put_user((k)->c_oflag, &(u)->c_oflag); \
-	err |= put_user((k)->c_cflag, &(u)->c_cflag); \
-	err |= put_user((k)->c_lflag, &(u)->c_lflag); \
-	err |= put_user((k)->c_line, &(u)->c_line); \
-	err |= copy_to_user((u)->c_cc, (k)->c_cc, NCCS); \
-	if(!((k)->c_lflag & ICANON)) { \
-		err |= put_user((k)->c_cc[VMIN],  &(u)->c_cc[_VMIN]); \
-		err |= put_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \
-	} else { \
-		err |= put_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \
-		err |= put_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \
-	} \
-	err |= put_user((k)->c_ispeed, &(u)->c_ispeed); \
-	err |= put_user((k)->c_ospeed, &(u)->c_ospeed); \
-	err; \
-})
-
-#define user_termios_to_kernel_termios_1(k, u) \
-({ \
-	int err; \
-	err  = get_user((k)->c_iflag, &(u)->c_iflag); \
-	err |= get_user((k)->c_oflag, &(u)->c_oflag); \
-	err |= get_user((k)->c_cflag, &(u)->c_cflag); \
-	err |= get_user((k)->c_lflag, &(u)->c_lflag); \
-	err |= get_user((k)->c_line,  &(u)->c_line); \
-	err |= copy_from_user((k)->c_cc, (u)->c_cc, NCCS); \
-	if((k)->c_lflag & ICANON) { \
-		err |= get_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \
-		err |= get_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \
-	} else { \
-		err |= get_user((k)->c_cc[VMIN],  &(u)->c_cc[_VMIN]); \
-		err |= get_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \
-	} \
-	err; \
-})
-
-#define kernel_termios_to_user_termios_1(u, k) \
-({ \
-	int err; \
-	err  = put_user((k)->c_iflag, &(u)->c_iflag); \
-	err |= put_user((k)->c_oflag, &(u)->c_oflag); \
-	err |= put_user((k)->c_cflag, &(u)->c_cflag); \
-	err |= put_user((k)->c_lflag, &(u)->c_lflag); \
-	err |= put_user((k)->c_line, &(u)->c_line); \
-	err |= copy_to_user((u)->c_cc, (k)->c_cc, NCCS); \
-	if(!((k)->c_lflag & ICANON)) { \
-		err |= put_user((k)->c_cc[VMIN],  &(u)->c_cc[_VMIN]); \
-		err |= put_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \
-	} else { \
-		err |= put_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \
-		err |= put_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \
-	} \
-	err; \
-})
-
-#endif	/* __KERNEL__ */
-
-#endif /* _SPARC64_TERMIOS_H */
+#include <asm-sparc/termios.h>
diff --git a/include/asm-sparc64/thread_info.h b/include/asm-sparc64/thread_info.h
index e5873e3..92bed79 100644
--- a/include/asm-sparc64/thread_info.h
+++ b/include/asm-sparc64/thread_info.h
@@ -1,277 +1 @@
-/* thread_info.h: sparc64 low-level thread information
- *
- * Copyright (C) 2002  David S. Miller (davem@redhat.com)
- */
-
-#ifndef _ASM_THREAD_INFO_H
-#define _ASM_THREAD_INFO_H
-
-#ifdef __KERNEL__
-
-#define NSWINS		7
-
-#define TI_FLAG_BYTE_FAULT_CODE		0
-#define TI_FLAG_FAULT_CODE_SHIFT	56
-#define TI_FLAG_BYTE_WSTATE		1
-#define TI_FLAG_WSTATE_SHIFT		48
-#define TI_FLAG_BYTE_CWP		2
-#define TI_FLAG_CWP_SHIFT		40
-#define TI_FLAG_BYTE_CURRENT_DS		3
-#define TI_FLAG_CURRENT_DS_SHIFT	32
-#define TI_FLAG_BYTE_FPDEPTH		4
-#define TI_FLAG_FPDEPTH_SHIFT		24
-#define TI_FLAG_BYTE_WSAVED		5
-#define TI_FLAG_WSAVED_SHIFT		16
-
-#include <asm/page.h>
-
-#ifndef __ASSEMBLY__
-
-#include <asm/ptrace.h>
-#include <asm/types.h>
-
-struct task_struct;
-struct exec_domain;
-
-struct thread_info {
-	/* D$ line 1 */
-	struct task_struct	*task;
-	unsigned long		flags;
-	__u8			fpsaved[7];
-	__u8			status;
-	unsigned long		ksp;
-
-	/* D$ line 2 */
-	unsigned long		fault_address;
-	struct pt_regs		*kregs;
-	struct exec_domain	*exec_domain;
-	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
-	__u8			new_child;
-	__u8			syscall_noerror;
-	__u16			cpu;
-
-	unsigned long		*utraps;
-
-	struct reg_window 	reg_window[NSWINS];
-	unsigned long 		rwbuf_stkptrs[NSWINS];
-
-	unsigned long		gsr[7];
-	unsigned long		xfsr[7];
-
-	__u64			__user *user_cntd0;
-	__u64			__user *user_cntd1;
-	__u64			kernel_cntd0, kernel_cntd1;
-	__u64			pcr_reg;
-
-	struct restart_block	restart_block;
-
-	struct pt_regs		*kern_una_regs;
-	unsigned int		kern_una_insn;
-
-	unsigned long		fpregs[0] __attribute__ ((aligned(64)));
-};
-
-#endif /* !(__ASSEMBLY__) */
-
-/* offsets into the thread_info struct for assembly code access */
-#define TI_TASK		0x00000000
-#define TI_FLAGS	0x00000008
-#define TI_FAULT_CODE	(TI_FLAGS + TI_FLAG_BYTE_FAULT_CODE)
-#define TI_WSTATE	(TI_FLAGS + TI_FLAG_BYTE_WSTATE)
-#define TI_CWP		(TI_FLAGS + TI_FLAG_BYTE_CWP)
-#define TI_CURRENT_DS	(TI_FLAGS + TI_FLAG_BYTE_CURRENT_DS)
-#define TI_FPDEPTH	(TI_FLAGS + TI_FLAG_BYTE_FPDEPTH)
-#define TI_WSAVED	(TI_FLAGS + TI_FLAG_BYTE_WSAVED)
-#define TI_FPSAVED	0x00000010
-#define TI_KSP		0x00000018
-#define TI_FAULT_ADDR	0x00000020
-#define TI_KREGS	0x00000028
-#define TI_EXEC_DOMAIN	0x00000030
-#define TI_PRE_COUNT	0x00000038
-#define TI_NEW_CHILD	0x0000003c
-#define TI_SYS_NOERROR	0x0000003d
-#define TI_CPU		0x0000003e
-#define TI_UTRAPS	0x00000040
-#define TI_REG_WINDOW	0x00000048
-#define TI_RWIN_SPTRS	0x000003c8	
-#define TI_GSR		0x00000400
-#define TI_XFSR		0x00000438
-#define TI_USER_CNTD0	0x00000470
-#define TI_USER_CNTD1	0x00000478
-#define TI_KERN_CNTD0	0x00000480
-#define TI_KERN_CNTD1	0x00000488
-#define TI_PCR		0x00000490
-#define TI_RESTART_BLOCK 0x00000498
-#define TI_KUNA_REGS	0x000004c0
-#define TI_KUNA_INSN	0x000004c8
-#define TI_FPREGS	0x00000500
-
-/* We embed this in the uppermost byte of thread_info->flags */
-#define FAULT_CODE_WRITE	0x01	/* Write access, implies D-TLB	   */
-#define FAULT_CODE_DTLB		0x02	/* Miss happened in D-TLB	   */
-#define FAULT_CODE_ITLB		0x04	/* Miss happened in I-TLB	   */
-#define FAULT_CODE_WINFIXUP	0x08	/* Miss happened during spill/fill */
-#define FAULT_CODE_BLKCOMMIT	0x10	/* Use blk-commit ASI in copy_page */
-
-#if PAGE_SHIFT == 13
-#define THREAD_SIZE (2*PAGE_SIZE)
-#define THREAD_SHIFT (PAGE_SHIFT + 1)
-#else /* PAGE_SHIFT == 13 */
-#define THREAD_SIZE PAGE_SIZE
-#define THREAD_SHIFT PAGE_SHIFT
-#endif /* PAGE_SHIFT == 13 */
-
-#define PREEMPT_ACTIVE		0x4000000
-
-/*
- * macros/functions for gaining access to the thread information structure
- *
- * preempt_count needs to be 1 initially, until the scheduler is functional.
- */
-#ifndef __ASSEMBLY__
-
-#define INIT_THREAD_INFO(tsk)				\
-{							\
-	.task		=	&tsk,			\
-	.flags		= ((unsigned long)ASI_P) << TI_FLAG_CURRENT_DS_SHIFT,	\
-	.exec_domain	=	&default_exec_domain,	\
-	.preempt_count	=	1,			\
-	.restart_block	= {				\
-		.fn	=	do_no_restart_syscall,	\
-	},						\
-}
-
-#define init_thread_info	(init_thread_union.thread_info)
-#define init_stack		(init_thread_union.stack)
-
-/* how to get the thread information struct from C */
-register struct thread_info *current_thread_info_reg asm("g6");
-#define current_thread_info()	(current_thread_info_reg)
-
-/* thread information allocation */
-#if PAGE_SHIFT == 13
-#define __THREAD_INFO_ORDER	1
-#else /* PAGE_SHIFT == 13 */
-#define __THREAD_INFO_ORDER	0
-#endif /* PAGE_SHIFT == 13 */
-
-#ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info(tsk)					\
-({								\
-	struct thread_info *ret;				\
-								\
-	ret = (struct thread_info *)				\
-	  __get_free_pages(GFP_KERNEL, __THREAD_INFO_ORDER);	\
-	if (ret)						\
-		memset(ret, 0, PAGE_SIZE<<__THREAD_INFO_ORDER);	\
-	ret;							\
-})
-#else
-#define alloc_thread_info(tsk) \
-	((struct thread_info *)__get_free_pages(GFP_KERNEL, __THREAD_INFO_ORDER))
-#endif
-
-#define free_thread_info(ti) \
-	free_pages((unsigned long)(ti),__THREAD_INFO_ORDER)
-
-#define __thread_flag_byte_ptr(ti)	\
-	((unsigned char *)(&((ti)->flags)))
-#define __cur_thread_flag_byte_ptr	__thread_flag_byte_ptr(current_thread_info())
-
-#define get_thread_fault_code()		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FAULT_CODE])
-#define set_thread_fault_code(val)	(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FAULT_CODE] = (val))
-#define get_thread_wstate()		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSTATE])
-#define set_thread_wstate(val)		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSTATE] = (val))
-#define get_thread_cwp()		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP])
-#define set_thread_cwp(val)		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP] = (val))
-#define get_thread_current_ds()		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CURRENT_DS])
-#define set_thread_current_ds(val)	(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CURRENT_DS] = (val))
-#define get_thread_fpdepth()		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH])
-#define set_thread_fpdepth(val)		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH] = (val))
-#define get_thread_wsaved()		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED])
-#define set_thread_wsaved(val)		(__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED] = (val))
-
-#endif /* !(__ASSEMBLY__) */
-
-/*
- * Thread information flags, only 16 bits are available as we encode
- * other values into the upper 6 bytes.
- *
- * On trap return we need to test several values:
- *
- * user:	need_resched, notify_resume, sigpending, wsaved, perfctr
- * kernel:	fpdepth
- *
- * So to check for work in the kernel case we simply load the fpdepth
- * byte out of the flags and test it.  For the user case we encode the
- * lower 3 bytes of flags as follows:
- *	----------------------------------------
- *	| wsaved | flags byte 1 | flags byte 2 |
- *	----------------------------------------
- * This optimizes the user test into:
- *	ldx		[%g6 + TI_FLAGS], REG1
- *	sethi		%hi(_TIF_USER_WORK_MASK), REG2
- *	or		REG2, %lo(_TIF_USER_WORK_MASK), REG2
- *	andcc		REG1, REG2, %g0
- *	be,pt		no_work_to_do
- *	 nop
- */
-#define TIF_SYSCALL_TRACE	0	/* syscall trace active */
-/* flags bit 1 is available */
-#define TIF_SIGPENDING		2	/* signal pending */
-#define TIF_NEED_RESCHED	3	/* rescheduling necessary */
-#define TIF_PERFCTR		4	/* performance counters active */
-#define TIF_UNALIGNED		5	/* allowed to do unaligned accesses */
-/* flag bit 6 is available */
-#define TIF_32BIT		7	/* 32-bit binary */
-/* flag bit 8 is available */
-#define TIF_SECCOMP		9	/* secure computing */
-#define TIF_SYSCALL_AUDIT	10	/* syscall auditing active */
-/* flag bit 11 is available */
-/* NOTE: Thread flags >= 12 should be ones we have no interest
- *       in using in assembly, else we can't use the mask as
- *       an immediate value in instructions such as andcc.
- */
-#define TIF_ABI_PENDING		12
-#define TIF_MEMDIE		13
-#define TIF_POLLING_NRFLAG	14
-
-#define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
-#define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
-#define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
-#define _TIF_PERFCTR		(1<<TIF_PERFCTR)
-#define _TIF_UNALIGNED		(1<<TIF_UNALIGNED)
-#define _TIF_32BIT		(1<<TIF_32BIT)
-#define _TIF_SECCOMP		(1<<TIF_SECCOMP)
-#define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
-#define _TIF_ABI_PENDING	(1<<TIF_ABI_PENDING)
-#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
-
-#define _TIF_USER_WORK_MASK	((0xff << TI_FLAG_WSAVED_SHIFT) | \
-				 (_TIF_SIGPENDING | \
-				  _TIF_NEED_RESCHED | _TIF_PERFCTR))
-
-/*
- * Thread-synchronous status.
- *
- * This is different from the flags in that nobody else
- * ever touches our thread-synchronous status, so we don't
- * have to worry about atomic accesses.
- *
- * Note that there are only 8 bits available.
- */
-#define TS_RESTORE_SIGMASK	0x0001	/* restore signal mask in do_signal() */
-
-#ifndef __ASSEMBLY__
-#define HAVE_SET_RESTORE_SIGMASK	1
-static inline void set_restore_sigmask(void)
-{
-	struct thread_info *ti = current_thread_info();
-	ti->status |= TS_RESTORE_SIGMASK;
-	set_bit(TIF_SIGPENDING, &ti->flags);
-}
-#endif	/* !__ASSEMBLY__ */
-
-#endif /* __KERNEL__ */
-
-#endif /* _ASM_THREAD_INFO_H */
+#include <asm-sparc/thread_info.h>
diff --git a/include/asm-sparc64/timer.h b/include/asm-sparc64/timer.h
index 5b779fd..88026d8 100644
--- a/include/asm-sparc64/timer.h
+++ b/include/asm-sparc64/timer.h
@@ -1,30 +1 @@
-/* timer.h: System timer definitions for sun5.
- *
- * Copyright (C) 1997, 2008 David S. Miller (davem@davemloft.net)
- */
-
-#ifndef _SPARC64_TIMER_H
-#define _SPARC64_TIMER_H
-
-#include <linux/types.h>
-#include <linux/init.h>
-
-struct sparc64_tick_ops {
-	unsigned long (*get_tick)(void);
-	int (*add_compare)(unsigned long);
-	unsigned long softint_mask;
-	void (*disable_irq)(void);
-
-	void (*init_tick)(void);
-	unsigned long (*add_tick)(unsigned long);
-
-	char *name;
-};
-
-extern struct sparc64_tick_ops *tick_ops;
-
-extern unsigned long sparc64_get_clock_tick(unsigned int cpu);
-extern void __devinit setup_sparc64_timer(void);
-extern void __init time_init(void);
-
-#endif /* _SPARC64_TIMER_H */
+#include <asm-sparc/timer.h>
diff --git a/include/asm-sparc64/timex.h b/include/asm-sparc64/timex.h
index c622535..8dd59ee 100644
--- a/include/asm-sparc64/timex.h
+++ b/include/asm-sparc64/timex.h
@@ -1,19 +1 @@
-/*
- * linux/include/asm-sparc64/timex.h
- *
- * sparc64 architecture timex specifications
- */
-#ifndef _ASMsparc64_TIMEX_H
-#define _ASMsparc64_TIMEX_H
-
-#include <asm/timer.h>
-
-#define CLOCK_TICK_RATE	1193180 /* Underlying HZ */
-
-/* Getting on the cycle counter on sparc64. */
-typedef unsigned long cycles_t;
-#define get_cycles()	tick_ops->get_tick()
-
-#define ARCH_HAS_READ_CURRENT_TIMER
-
-#endif
+#include <asm-sparc/timex.h>
diff --git a/include/asm-sparc64/tlb.h b/include/asm-sparc64/tlb.h
index ec81cde..ae92fce 100644
--- a/include/asm-sparc64/tlb.h
+++ b/include/asm-sparc64/tlb.h
@@ -1,111 +1 @@
-#ifndef _SPARC64_TLB_H
-#define _SPARC64_TLB_H
-
-#include <linux/swap.h>
-#include <linux/pagemap.h>
-#include <asm/pgalloc.h>
-#include <asm/tlbflush.h>
-#include <asm/mmu_context.h>
-
-#define TLB_BATCH_NR	192
-
-/*
- * For UP we don't need to worry about TLB flush
- * and page free order so much..
- */
-#ifdef CONFIG_SMP
-  #define FREE_PTE_NR	506
-  #define tlb_fast_mode(bp) ((bp)->pages_nr == ~0U)
-#else
-  #define FREE_PTE_NR	1
-  #define tlb_fast_mode(bp) 1
-#endif
-
-struct mmu_gather {
-	struct mm_struct *mm;
-	unsigned int pages_nr;
-	unsigned int need_flush;
-	unsigned int fullmm;
-	unsigned int tlb_nr;
-	unsigned long vaddrs[TLB_BATCH_NR];
-	struct page *pages[FREE_PTE_NR];
-};
-
-DECLARE_PER_CPU(struct mmu_gather, mmu_gathers);
-
-#ifdef CONFIG_SMP
-extern void smp_flush_tlb_pending(struct mm_struct *,
-				  unsigned long, unsigned long *);
-#endif
-
-extern void __flush_tlb_pending(unsigned long, unsigned long, unsigned long *);
-extern void flush_tlb_pending(void);
-
-static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
-{
-	struct mmu_gather *mp = &get_cpu_var(mmu_gathers);
-
-	BUG_ON(mp->tlb_nr);
-
-	mp->mm = mm;
-	mp->pages_nr = num_online_cpus() > 1 ? 0U : ~0U;
-	mp->fullmm = full_mm_flush;
-
-	return mp;
-}
-
-
-static inline void tlb_flush_mmu(struct mmu_gather *mp)
-{
-	if (mp->need_flush) {
-		free_pages_and_swap_cache(mp->pages, mp->pages_nr);
-		mp->pages_nr = 0;
-		mp->need_flush = 0;
-	}
-
-}
-
-#ifdef CONFIG_SMP
-extern void smp_flush_tlb_mm(struct mm_struct *mm);
-#define do_flush_tlb_mm(mm) smp_flush_tlb_mm(mm)
-#else
-#define do_flush_tlb_mm(mm) __flush_tlb_mm(CTX_HWBITS(mm->context), SECONDARY_CONTEXT)
-#endif
-
-static inline void tlb_finish_mmu(struct mmu_gather *mp, unsigned long start, unsigned long end)
-{
-	tlb_flush_mmu(mp);
-
-	if (mp->fullmm)
-		mp->fullmm = 0;
-	else
-		flush_tlb_pending();
-
-	/* keep the page table cache within bounds */
-	check_pgt_cache();
-
-	put_cpu_var(mmu_gathers);
-}
-
-static inline void tlb_remove_page(struct mmu_gather *mp, struct page *page)
-{
-	if (tlb_fast_mode(mp)) {
-		free_page_and_swap_cache(page);
-		return;
-	}
-	mp->need_flush = 1;
-	mp->pages[mp->pages_nr++] = page;
-	if (mp->pages_nr >= FREE_PTE_NR)
-		tlb_flush_mmu(mp);
-}
-
-#define tlb_remove_tlb_entry(mp,ptep,addr) do { } while (0)
-#define pte_free_tlb(mp, ptepage) pte_free((mp)->mm, ptepage)
-#define pmd_free_tlb(mp, pmdp) pmd_free((mp)->mm, pmdp)
-#define pud_free_tlb(tlb,pudp) __pud_free_tlb(tlb,pudp)
-
-#define tlb_migrate_finish(mm)	do { } while (0)
-#define tlb_start_vma(tlb, vma) do { } while (0)
-#define tlb_end_vma(tlb, vma)	do { } while (0)
-
-#endif /* _SPARC64_TLB_H */
+#include <asm-sparc/tlb.h>
diff --git a/include/asm-sparc64/tlbflush.h b/include/asm-sparc64/tlbflush.h
index fbb675d..a43979a 100644
--- a/include/asm-sparc64/tlbflush.h
+++ b/include/asm-sparc64/tlbflush.h
@@ -1,44 +1 @@
-#ifndef _SPARC64_TLBFLUSH_H
-#define _SPARC64_TLBFLUSH_H
-
-#include <linux/mm.h>
-#include <asm/mmu_context.h>
-
-/* TSB flush operations. */
-struct mmu_gather;
-extern void flush_tsb_kernel_range(unsigned long start, unsigned long end);
-extern void flush_tsb_user(struct mmu_gather *mp);
-
-/* TLB flush operations. */
-
-extern void flush_tlb_pending(void);
-
-#define flush_tlb_range(vma,start,end)	\
-	do { (void)(start); flush_tlb_pending(); } while (0)
-#define flush_tlb_page(vma,addr)	flush_tlb_pending()
-#define flush_tlb_mm(mm)		flush_tlb_pending()
-
-/* Local cpu only.  */
-extern void __flush_tlb_all(void);
-
-extern void __flush_tlb_kernel_range(unsigned long start, unsigned long end);
-
-#ifndef CONFIG_SMP
-
-#define flush_tlb_kernel_range(start,end) \
-do {	flush_tsb_kernel_range(start,end); \
-	__flush_tlb_kernel_range(start,end); \
-} while (0)
-
-#else /* CONFIG_SMP */
-
-extern void smp_flush_tlb_kernel_range(unsigned long start, unsigned long end);
-
-#define flush_tlb_kernel_range(start, end) \
-do {	flush_tsb_kernel_range(start,end); \
-	smp_flush_tlb_kernel_range(start, end); \
-} while (0)
-
-#endif /* ! CONFIG_SMP */
-
-#endif /* _SPARC64_TLBFLUSH_H */
+#include <asm-sparc/tlbflush.h>
diff --git a/include/asm-sparc64/topology.h b/include/asm-sparc64/topology.h
index 001c040..46999b60 100644
--- a/include/asm-sparc64/topology.h
+++ b/include/asm-sparc64/topology.h
@@ -1,86 +1 @@
-#ifndef _ASM_SPARC64_TOPOLOGY_H
-#define _ASM_SPARC64_TOPOLOGY_H
-
-#ifdef CONFIG_NUMA
-
-#include <asm/mmzone.h>
-
-static inline int cpu_to_node(int cpu)
-{
-	return numa_cpu_lookup_table[cpu];
-}
-
-#define parent_node(node)	(node)
-
-static inline cpumask_t node_to_cpumask(int node)
-{
-	return numa_cpumask_lookup_table[node];
-}
-
-/* Returns a pointer to the cpumask of CPUs on Node 'node'. */
-#define node_to_cpumask_ptr(v, node)		\
-		cpumask_t *v = &(numa_cpumask_lookup_table[node])
-
-#define node_to_cpumask_ptr_next(v, node)	\
-			   v = &(numa_cpumask_lookup_table[node])
-
-static inline int node_to_first_cpu(int node)
-{
-	cpumask_t tmp;
-	tmp = node_to_cpumask(node);
-	return first_cpu(tmp);
-}
-
-struct pci_bus;
-#ifdef CONFIG_PCI
-extern int pcibus_to_node(struct pci_bus *pbus);
-#else
-static inline int pcibus_to_node(struct pci_bus *pbus)
-{
-	return -1;
-}
-#endif
-
-#define pcibus_to_cpumask(bus)	\
-	(pcibus_to_node(bus) == -1 ? \
-	 CPU_MASK_ALL : \
-	 node_to_cpumask(pcibus_to_node(bus)))
-
-#define SD_NODE_INIT (struct sched_domain) {		\
-	.min_interval		= 8,			\
-	.max_interval		= 32,			\
-	.busy_factor		= 32,			\
-	.imbalance_pct		= 125,			\
-	.cache_nice_tries	= 2,			\
-	.busy_idx		= 3,			\
-	.idle_idx		= 2,			\
-	.newidle_idx		= 0, 			\
-	.wake_idx		= 1,			\
-	.forkexec_idx		= 1,			\
-	.flags			= SD_LOAD_BALANCE	\
-				| SD_BALANCE_FORK	\
-				| SD_BALANCE_EXEC	\
-				| SD_SERIALIZE		\
-				| SD_WAKE_BALANCE,	\
-	.last_balance		= jiffies,		\
-	.balance_interval	= 1,			\
-}
-
-#else /* CONFIG_NUMA */
-
-#include <asm-generic/topology.h>
-
-#endif /* !(CONFIG_NUMA) */
-
-#ifdef CONFIG_SMP
-#define topology_physical_package_id(cpu)	(cpu_data(cpu).proc_id)
-#define topology_core_id(cpu)			(cpu_data(cpu).core_id)
-#define topology_core_siblings(cpu)		(cpu_core_map[cpu])
-#define topology_thread_siblings(cpu)		(per_cpu(cpu_sibling_map, cpu))
-#define mc_capable()				(sparc64_multi_core)
-#define smt_capable()				(sparc64_multi_core)
-#endif /* CONFIG_SMP */
-
-#define cpu_coregroup_map(cpu)			(cpu_core_map[cpu])
-
-#endif /* _ASM_SPARC64_TOPOLOGY_H */
+#include <asm-sparc/topology.h>
diff --git a/include/asm-sparc64/tsb.h b/include/asm-sparc64/tsb.h
index 76e4299..3677a30 100644
--- a/include/asm-sparc64/tsb.h
+++ b/include/asm-sparc64/tsb.h
@@ -1,283 +1 @@
-#ifndef _SPARC64_TSB_H
-#define _SPARC64_TSB_H
-
-/* The sparc64 TSB is similar to the powerpc hashtables.  It's a
- * power-of-2 sized table of TAG/PTE pairs.  The cpu precomputes
- * pointers into this table for 8K and 64K page sizes, and also a
- * comparison TAG based upon the virtual address and context which
- * faults.
- *
- * TLB miss trap handler software does the actual lookup via something
- * of the form:
- *
- * 	ldxa		[%g0] ASI_{D,I}MMU_TSB_8KB_PTR, %g1
- * 	ldxa		[%g0] ASI_{D,I}MMU, %g6
- *	sllx		%g6, 22, %g6
- *	srlx		%g6, 22, %g6
- * 	ldda		[%g1] ASI_NUCLEUS_QUAD_LDD, %g4
- * 	cmp		%g4, %g6
- * 	bne,pn	%xcc, tsb_miss_{d,i}tlb
- * 	 mov		FAULT_CODE_{D,I}TLB, %g3
- * 	stxa		%g5, [%g0] ASI_{D,I}TLB_DATA_IN
- * 	retry
- *
- *
- * Each 16-byte slot of the TSB is the 8-byte tag and then the 8-byte
- * PTE.  The TAG is of the same layout as the TLB TAG TARGET mmu
- * register which is:
- *
- * -------------------------------------------------
- * |  -  |  CONTEXT |  -  |    VADDR bits 63:22    |
- * -------------------------------------------------
- *  63 61 60      48 47 42 41                     0
- *
- * But actually, since we use per-mm TSB's, we zero out the CONTEXT
- * field.
- *
- * Like the powerpc hashtables we need to use locking in order to
- * synchronize while we update the entries.  PTE updates need locking
- * as well.
- *
- * We need to carefully choose a lock bits for the TSB entry.  We
- * choose to use bit 47 in the tag.  Also, since we never map anything
- * at page zero in context zero, we use zero as an invalid tag entry.
- * When the lock bit is set, this forces a tag comparison failure.
- */
-
-#define TSB_TAG_LOCK_BIT	47
-#define TSB_TAG_LOCK_HIGH	(1 << (TSB_TAG_LOCK_BIT - 32))
-
-#define TSB_TAG_INVALID_BIT	46
-#define TSB_TAG_INVALID_HIGH	(1 << (TSB_TAG_INVALID_BIT - 32))
-
-#define TSB_MEMBAR	membar	#StoreStore
-
-/* Some cpus support physical address quad loads.  We want to use
- * those if possible so we don't need to hard-lock the TSB mapping
- * into the TLB.  We encode some instruction patching in order to
- * support this.
- *
- * The kernel TSB is locked into the TLB by virtue of being in the
- * kernel image, so we don't play these games for swapper_tsb access.
- */
-#ifndef __ASSEMBLY__
-struct tsb_ldquad_phys_patch_entry {
-	unsigned int	addr;
-	unsigned int	sun4u_insn;
-	unsigned int	sun4v_insn;
-};
-extern struct tsb_ldquad_phys_patch_entry __tsb_ldquad_phys_patch,
-	__tsb_ldquad_phys_patch_end;
-
-struct tsb_phys_patch_entry {
-	unsigned int	addr;
-	unsigned int	insn;
-};
-extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
-#endif
-#define TSB_LOAD_QUAD(TSB, REG)	\
-661:	ldda		[TSB] ASI_NUCLEUS_QUAD_LDD, REG; \
-	.section	.tsb_ldquad_phys_patch, "ax"; \
-	.word		661b; \
-	ldda		[TSB] ASI_QUAD_LDD_PHYS, REG; \
-	ldda		[TSB] ASI_QUAD_LDD_PHYS_4V, REG; \
-	.previous
-
-#define TSB_LOAD_TAG_HIGH(TSB, REG) \
-661:	lduwa		[TSB] ASI_N, REG; \
-	.section	.tsb_phys_patch, "ax"; \
-	.word		661b; \
-	lduwa		[TSB] ASI_PHYS_USE_EC, REG; \
-	.previous
-
-#define TSB_LOAD_TAG(TSB, REG) \
-661:	ldxa		[TSB] ASI_N, REG; \
-	.section	.tsb_phys_patch, "ax"; \
-	.word		661b; \
-	ldxa		[TSB] ASI_PHYS_USE_EC, REG; \
-	.previous
-
-#define TSB_CAS_TAG_HIGH(TSB, REG1, REG2) \
-661:	casa		[TSB] ASI_N, REG1, REG2; \
-	.section	.tsb_phys_patch, "ax"; \
-	.word		661b; \
-	casa		[TSB] ASI_PHYS_USE_EC, REG1, REG2; \
-	.previous
-
-#define TSB_CAS_TAG(TSB, REG1, REG2) \
-661:	casxa		[TSB] ASI_N, REG1, REG2; \
-	.section	.tsb_phys_patch, "ax"; \
-	.word		661b; \
-	casxa		[TSB] ASI_PHYS_USE_EC, REG1, REG2; \
-	.previous
-
-#define TSB_STORE(ADDR, VAL) \
-661:	stxa		VAL, [ADDR] ASI_N; \
-	.section	.tsb_phys_patch, "ax"; \
-	.word		661b; \
-	stxa		VAL, [ADDR] ASI_PHYS_USE_EC; \
-	.previous
-
-#define TSB_LOCK_TAG(TSB, REG1, REG2)	\
-99:	TSB_LOAD_TAG_HIGH(TSB, REG1);	\
-	sethi	%hi(TSB_TAG_LOCK_HIGH), REG2;\
-	andcc	REG1, REG2, %g0;	\
-	bne,pn	%icc, 99b;		\
-	 nop;				\
-	TSB_CAS_TAG_HIGH(TSB, REG1, REG2);	\
-	cmp	REG1, REG2;		\
-	bne,pn	%icc, 99b;		\
-	 nop;				\
-	TSB_MEMBAR
-
-#define TSB_WRITE(TSB, TTE, TAG) \
-	add	TSB, 0x8, TSB;   \
-	TSB_STORE(TSB, TTE);     \
-	sub	TSB, 0x8, TSB;   \
-	TSB_MEMBAR;              \
-	TSB_STORE(TSB, TAG);
-
-#define KTSB_LOAD_QUAD(TSB, REG) \
-	ldda		[TSB] ASI_NUCLEUS_QUAD_LDD, REG;
-
-#define KTSB_STORE(ADDR, VAL) \
-	stxa		VAL, [ADDR] ASI_N;
-
-#define KTSB_LOCK_TAG(TSB, REG1, REG2)	\
-99:	lduwa	[TSB] ASI_N, REG1;	\
-	sethi	%hi(TSB_TAG_LOCK_HIGH), REG2;\
-	andcc	REG1, REG2, %g0;	\
-	bne,pn	%icc, 99b;		\
-	 nop;				\
-	casa	[TSB] ASI_N, REG1, REG2;\
-	cmp	REG1, REG2;		\
-	bne,pn	%icc, 99b;		\
-	 nop;				\
-	TSB_MEMBAR
-
-#define KTSB_WRITE(TSB, TTE, TAG) \
-	add	TSB, 0x8, TSB;   \
-	stxa	TTE, [TSB] ASI_N;     \
-	sub	TSB, 0x8, TSB;   \
-	TSB_MEMBAR;              \
-	stxa	TAG, [TSB] ASI_N;
-
-	/* Do a kernel page table walk.  Leaves physical PTE pointer in
-	 * REG1.  Jumps to FAIL_LABEL on early page table walk termination.
-	 * VADDR will not be clobbered, but REG2 will.
-	 */
-#define KERN_PGTABLE_WALK(VADDR, REG1, REG2, FAIL_LABEL)	\
-	sethi		%hi(swapper_pg_dir), REG1; \
-	or		REG1, %lo(swapper_pg_dir), REG1; \
-	sllx		VADDR, 64 - (PGDIR_SHIFT + PGDIR_BITS), REG2; \
-	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
-	andn		REG2, 0x3, REG2; \
-	lduw		[REG1 + REG2], REG1; \
-	brz,pn		REG1, FAIL_LABEL; \
-	 sllx		VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \
-	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
-	sllx		REG1, 11, REG1; \
-	andn		REG2, 0x3, REG2; \
-	lduwa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
-	brz,pn		REG1, FAIL_LABEL; \
-	 sllx		VADDR, 64 - PMD_SHIFT, REG2; \
-	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
-	sllx		REG1, 11, REG1; \
-	andn		REG2, 0x7, REG2; \
-	add		REG1, REG2, REG1;
-
-	/* Do a user page table walk in MMU globals.  Leaves physical PTE
-	 * pointer in REG1.  Jumps to FAIL_LABEL on early page table walk
-	 * termination.  Physical base of page tables is in PHYS_PGD which
-	 * will not be modified.
-	 *
-	 * VADDR will not be clobbered, but REG1 and REG2 will.
-	 */
-#define USER_PGTABLE_WALK_TL1(VADDR, PHYS_PGD, REG1, REG2, FAIL_LABEL)	\
-	sllx		VADDR, 64 - (PGDIR_SHIFT + PGDIR_BITS), REG2; \
-	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
-	andn		REG2, 0x3, REG2; \
-	lduwa		[PHYS_PGD + REG2] ASI_PHYS_USE_EC, REG1; \
-	brz,pn		REG1, FAIL_LABEL; \
-	 sllx		VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \
-	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
-	sllx		REG1, 11, REG1; \
-	andn		REG2, 0x3, REG2; \
-	lduwa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
-	brz,pn		REG1, FAIL_LABEL; \
-	 sllx		VADDR, 64 - PMD_SHIFT, REG2; \
-	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
-	sllx		REG1, 11, REG1; \
-	andn		REG2, 0x7, REG2; \
-	add		REG1, REG2, REG1;
-
-/* Lookup a OBP mapping on VADDR in the prom_trans[] table at TL>0.
- * If no entry is found, FAIL_LABEL will be branched to.  On success
- * the resulting PTE value will be left in REG1.  VADDR is preserved
- * by this routine.
- */
-#define OBP_TRANS_LOOKUP(VADDR, REG1, REG2, REG3, FAIL_LABEL) \
-	sethi		%hi(prom_trans), REG1; \
-	or		REG1, %lo(prom_trans), REG1; \
-97:	ldx		[REG1 + 0x00], REG2; \
-	brz,pn		REG2, FAIL_LABEL; \
-	 nop; \
-	ldx		[REG1 + 0x08], REG3; \
-	add		REG2, REG3, REG3; \
-	cmp		REG2, VADDR; \
-	bgu,pt		%xcc, 98f; \
-	 cmp		VADDR, REG3; \
-	bgeu,pt		%xcc, 98f; \
-	 ldx		[REG1 + 0x10], REG3; \
-	sub		VADDR, REG2, REG2; \
-	ba,pt		%xcc, 99f; \
-	 add		REG3, REG2, REG1; \
-98:	ba,pt		%xcc, 97b; \
-	 add		REG1, (3 * 8), REG1; \
-99:
-
-	/* We use a 32K TSB for the whole kernel, this allows to
-	 * handle about 16MB of modules and vmalloc mappings without
-	 * incurring many hash conflicts.
-	 */
-#define KERNEL_TSB_SIZE_BYTES	(32 * 1024)
-#define KERNEL_TSB_NENTRIES	\
-	(KERNEL_TSB_SIZE_BYTES / 16)
-#define KERNEL_TSB4M_NENTRIES	4096
-
-	/* Do a kernel TSB lookup at tl>0 on VADDR+TAG, branch to OK_LABEL
-	 * on TSB hit.  REG1, REG2, REG3, and REG4 are used as temporaries
-	 * and the found TTE will be left in REG1.  REG3 and REG4 must
-	 * be an even/odd pair of registers.
-	 *
-	 * VADDR and TAG will be preserved and not clobbered by this macro.
-	 */
-#define KERN_TSB_LOOKUP_TL1(VADDR, TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
-	sethi		%hi(swapper_tsb), REG1; \
-	or		REG1, %lo(swapper_tsb), REG1; \
-	srlx		VADDR, PAGE_SHIFT, REG2; \
-	and		REG2, (KERNEL_TSB_NENTRIES - 1), REG2; \
-	sllx		REG2, 4, REG2; \
-	add		REG1, REG2, REG2; \
-	KTSB_LOAD_QUAD(REG2, REG3); \
-	cmp		REG3, TAG; \
-	be,a,pt		%xcc, OK_LABEL; \
-	 mov		REG4, REG1;
-
-#ifndef CONFIG_DEBUG_PAGEALLOC
-	/* This version uses a trick, the TAG is already (VADDR >> 22) so
-	 * we can make use of that for the index computation.
-	 */
-#define KERN_TSB4M_LOOKUP_TL1(TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
-	sethi		%hi(swapper_4m_tsb), REG1; \
-	or		REG1, %lo(swapper_4m_tsb), REG1; \
-	and		TAG, (KERNEL_TSB4M_NENTRIES - 1), REG2; \
-	sllx		REG2, 4, REG2; \
-	add		REG1, REG2, REG2; \
-	KTSB_LOAD_QUAD(REG2, REG3); \
-	cmp		REG3, TAG; \
-	be,a,pt		%xcc, OK_LABEL; \
-	 mov		REG4, REG1;
-#endif
-
-#endif /* !(_SPARC64_TSB_H) */
+#include <asm-sparc/tsb.h>
diff --git a/include/asm-sparc64/ttable.h b/include/asm-sparc64/ttable.h
index 0ba1995..a550f1b 100644
--- a/include/asm-sparc64/ttable.h
+++ b/include/asm-sparc64/ttable.h
@@ -1,658 +1 @@
-#ifndef _SPARC64_TTABLE_H
-#define _SPARC64_TTABLE_H
-
-#include <asm/utrap.h>
-
-#ifdef __ASSEMBLY__
-#include <asm/thread_info.h>
-#endif
-
-#define BOOT_KERNEL b sparc64_boot; nop; nop; nop; nop; nop; nop; nop;
-
-/* We need a "cleaned" instruction... */
-#define CLEAN_WINDOW							\
-	rdpr	%cleanwin, %l0;		add	%l0, 1, %l0;		\
-	wrpr	%l0, 0x0, %cleanwin;					\
-	clr	%o0;	clr	%o1;	clr	%o2;	clr	%o3;	\
-	clr	%o4;	clr	%o5;	clr	%o6;	clr	%o7;	\
-	clr	%l0;	clr	%l1;	clr	%l2;	clr	%l3;	\
-	clr	%l4;	clr	%l5;	clr	%l6;	clr	%l7;	\
-	retry;								\
-	nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;
-
-#define TRAP(routine)					\
-	sethi	%hi(109f), %g7;				\
-	ba,pt	%xcc, etrap;				\
-109:	 or	%g7, %lo(109b), %g7;			\
-	call	routine;				\
-	 add	%sp, PTREGS_OFF, %o0;			\
-	ba,pt	%xcc, rtrap;				\
-	 nop;						\
-	nop;
-
-#define TRAP_7INSNS(routine)				\
-	sethi	%hi(109f), %g7;				\
-	ba,pt	%xcc, etrap;				\
-109:	 or	%g7, %lo(109b), %g7;			\
-	call	routine;				\
-	 add	%sp, PTREGS_OFF, %o0;			\
-	ba,pt	%xcc, rtrap;				\
-	 nop;
-
-#define TRAP_SAVEFPU(routine)				\
-	sethi	%hi(109f), %g7;				\
-	ba,pt	%xcc, do_fptrap;			\
-109:	 or	%g7, %lo(109b), %g7;			\
-	call	routine;				\
-	 add	%sp, PTREGS_OFF, %o0;			\
-	ba,pt	%xcc, rtrap;				\
-	 nop;						\
-	nop;
-
-#define TRAP_NOSAVE(routine)				\
-	ba,pt	%xcc, routine;				\
-	 nop;						\
-	nop; nop; nop; nop; nop; nop;
-	
-#define TRAP_NOSAVE_7INSNS(routine)			\
-	ba,pt	%xcc, routine;				\
-	 nop;						\
-	nop; nop; nop; nop; nop;
-	
-#define TRAPTL1(routine)				\
-	sethi	%hi(109f), %g7;				\
-	ba,pt	%xcc, etraptl1;				\
-109:	 or	%g7, %lo(109b), %g7;			\
-	call	routine;				\
-	 add	%sp, PTREGS_OFF, %o0;			\
-	ba,pt	%xcc, rtrap;				\
-	 nop;						\
-	nop;
-	
-#define TRAP_ARG(routine, arg)				\
-	sethi	%hi(109f), %g7;				\
-	ba,pt	%xcc, etrap;				\
-109:	 or	%g7, %lo(109b), %g7;			\
-	add	%sp, PTREGS_OFF, %o0;			\
-	call	routine;				\
-	 mov	arg, %o1;				\
-	ba,pt	%xcc, rtrap;				\
-	 nop;
-	
-#define TRAPTL1_ARG(routine, arg)			\
-	sethi	%hi(109f), %g7;				\
-	ba,pt	%xcc, etraptl1;				\
-109:	 or	%g7, %lo(109b), %g7;			\
-	add	%sp, PTREGS_OFF, %o0;			\
-	call	routine;				\
-	 mov	arg, %o1;				\
-	ba,pt	%xcc, rtrap;				\
-	 nop;
-	
-#define SYSCALL_TRAP(routine, systbl)			\
-	rdpr	%pil, %g2;				\
-	mov	TSTATE_SYSCALL, %g3;			\
-	sethi	%hi(109f), %g7;				\
-	ba,pt	%xcc, etrap_syscall;			\
-109:	 or	%g7, %lo(109b), %g7;			\
-	sethi	%hi(systbl), %l7;			\
-	ba,pt	%xcc, routine;				\
-	 or	%l7, %lo(systbl), %l7;
-	
-#define TRAP_UTRAP(handler,lvl)				\
-	mov	handler, %g3;				\
-	ba,pt	%xcc, utrap_trap;			\
-	 mov	lvl, %g4;				\
-	nop;						\
-	nop;						\
-	nop;						\
-	nop;						\
-	nop;
-
-#ifdef CONFIG_COMPAT
-#define	LINUX_32BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall32, sys_call_table32)
-#else
-#define	LINUX_32BIT_SYSCALL_TRAP BTRAP(0x110)
-#endif
-#define LINUX_64BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall, sys_call_table64)
-#define GETCC_TRAP TRAP(getcc)
-#define SETCC_TRAP TRAP(setcc)
-#define BREAKPOINT_TRAP TRAP(breakpoint_trap)
-
-#ifdef CONFIG_TRACE_IRQFLAGS
-
-#define TRAP_IRQ(routine, level)			\
-	rdpr	%pil, %g2;				\
-	wrpr	%g0, 15, %pil;				\
-	sethi	%hi(1f-4), %g7;				\
-	ba,pt	%xcc, etrap_irq;			\
-	 or	%g7, %lo(1f-4), %g7;			\
-	nop;						\
-	nop;						\
-	nop;						\
-	.subsection	2;				\
-1:	call	trace_hardirqs_off;			\
-	 nop;						\
-	mov	level, %o0;				\
-	call	routine;				\
-	 add	%sp, PTREGS_OFF, %o1;			\
-	ba,a,pt	%xcc, rtrap_irq;			\
-	.previous;
-
-#else
-
-#define TRAP_IRQ(routine, level)			\
-	rdpr	%pil, %g2;				\
-	wrpr	%g0, 15, %pil;				\
-	ba,pt	%xcc, etrap_irq;			\
-	 rd	%pc, %g7;				\
-	mov	level, %o0;				\
-	call	routine;				\
-	 add	%sp, PTREGS_OFF, %o1;			\
-	ba,a,pt	%xcc, rtrap_irq;
-	
-#endif
-
-#define TRAP_IVEC TRAP_NOSAVE(do_ivec)
-
-#define BTRAP(lvl) TRAP_ARG(bad_trap, lvl)
-
-#define BTRAPTL1(lvl) TRAPTL1_ARG(bad_trap_tl1, lvl)
-
-#define FLUSH_WINDOW_TRAP						\
-	ba,pt	%xcc, etrap;						\
-	 rd	%pc, %g7;						\
-	flushw;								\
-	ldx	[%sp + PTREGS_OFF + PT_V9_TNPC], %l1;			\
-	add	%l1, 4, %l2;						\
-	stx	%l1, [%sp + PTREGS_OFF + PT_V9_TPC];			\
-	ba,pt	%xcc, rtrap;						\
-	 stx	%l2, [%sp + PTREGS_OFF + PT_V9_TNPC];
-	        
-#ifdef CONFIG_KPROBES
-#define KPROBES_TRAP(lvl) TRAP_IRQ(kprobe_trap, lvl)
-#else
-#define KPROBES_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
-#endif
-
-#ifdef CONFIG_KGDB
-#define KGDB_TRAP(lvl) TRAP_IRQ(kgdb_trap, lvl)
-#else
-#define KGDB_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
-#endif
-
-#define SUN4V_ITSB_MISS					\
-	ldxa	[%g0] ASI_SCRATCHPAD, %g2;		\
-	ldx	[%g2 + HV_FAULT_I_ADDR_OFFSET], %g4;	\
-	ldx	[%g2 + HV_FAULT_I_CTX_OFFSET], %g5;	\
-	srlx	%g4, 22, %g6;				\
-	ba,pt	%xcc, sun4v_itsb_miss;			\
-	 nop;						\
-	nop;						\
-	nop;
-
-#define SUN4V_DTSB_MISS					\
-	ldxa	[%g0] ASI_SCRATCHPAD, %g2;		\
-	ldx	[%g2 + HV_FAULT_D_ADDR_OFFSET], %g4;	\
-	ldx	[%g2 + HV_FAULT_D_CTX_OFFSET], %g5;	\
-	srlx	%g4, 22, %g6;				\
-	ba,pt	%xcc, sun4v_dtsb_miss;			\
-	 nop;						\
-	nop;						\
-	nop;
-
-/* Before touching these macros, you owe it to yourself to go and
- * see how arch/sparc64/kernel/winfixup.S works... -DaveM
- *
- * For the user cases we used to use the %asi register, but
- * it turns out that the "wr xxx, %asi" costs ~5 cycles, so
- * now we use immediate ASI loads and stores instead.  Kudos
- * to Greg Onufer for pointing out this performance anomaly.
- *
- * Further note that we cannot use the g2, g4, g5, and g7 alternate
- * globals in the spill routines, check out the save instruction in
- * arch/sparc64/kernel/etrap.S to see what I mean about g2, and
- * g4/g5 are the globals which are preserved by etrap processing
- * for the caller of it.  The g7 register is the return pc for
- * etrap.  Finally, g6 is the current thread register so we cannot
- * us it in the spill handlers either.  Most of these rules do not
- * apply to fill processing, only g6 is not usable.
- */
-
-/* Normal kernel spill */
-#define SPILL_0_NORMAL					\
-	stx	%l0, [%sp + STACK_BIAS + 0x00];		\
-	stx	%l1, [%sp + STACK_BIAS + 0x08];		\
-	stx	%l2, [%sp + STACK_BIAS + 0x10];		\
-	stx	%l3, [%sp + STACK_BIAS + 0x18];		\
-	stx	%l4, [%sp + STACK_BIAS + 0x20];		\
-	stx	%l5, [%sp + STACK_BIAS + 0x28];		\
-	stx	%l6, [%sp + STACK_BIAS + 0x30];		\
-	stx	%l7, [%sp + STACK_BIAS + 0x38];		\
-	stx	%i0, [%sp + STACK_BIAS + 0x40];		\
-	stx	%i1, [%sp + STACK_BIAS + 0x48];		\
-	stx	%i2, [%sp + STACK_BIAS + 0x50];		\
-	stx	%i3, [%sp + STACK_BIAS + 0x58];		\
-	stx	%i4, [%sp + STACK_BIAS + 0x60];		\
-	stx	%i5, [%sp + STACK_BIAS + 0x68];		\
-	stx	%i6, [%sp + STACK_BIAS + 0x70];		\
-	stx	%i7, [%sp + STACK_BIAS + 0x78];		\
-	saved; retry; nop; nop; nop; nop; nop; nop;	\
-	nop; nop; nop; nop; nop; nop; nop; nop;
-
-#define SPILL_0_NORMAL_ETRAP				\
-etrap_kernel_spill:					\
-	stx	%l0, [%sp + STACK_BIAS + 0x00];		\
-	stx	%l1, [%sp + STACK_BIAS + 0x08];		\
-	stx	%l2, [%sp + STACK_BIAS + 0x10];		\
-	stx	%l3, [%sp + STACK_BIAS + 0x18];		\
-	stx	%l4, [%sp + STACK_BIAS + 0x20];		\
-	stx	%l5, [%sp + STACK_BIAS + 0x28];		\
-	stx	%l6, [%sp + STACK_BIAS + 0x30];		\
-	stx	%l7, [%sp + STACK_BIAS + 0x38];		\
-	stx	%i0, [%sp + STACK_BIAS + 0x40];		\
-	stx	%i1, [%sp + STACK_BIAS + 0x48];		\
-	stx	%i2, [%sp + STACK_BIAS + 0x50];		\
-	stx	%i3, [%sp + STACK_BIAS + 0x58];		\
-	stx	%i4, [%sp + STACK_BIAS + 0x60];		\
-	stx	%i5, [%sp + STACK_BIAS + 0x68];		\
-	stx	%i6, [%sp + STACK_BIAS + 0x70];		\
-	stx	%i7, [%sp + STACK_BIAS + 0x78];		\
-	saved;						\
-	sub	%g1, 2, %g1;				\
-	ba,pt	%xcc, etrap_save;			\
-	wrpr	%g1, %cwp;				\
-	nop; nop; nop; nop; nop; nop; nop; nop;		\
-	nop; nop; nop; nop;
-
-/* Normal 64bit spill */
-#define SPILL_1_GENERIC(ASI)				\
-	add	%sp, STACK_BIAS + 0x00, %g1;		\
-	stxa	%l0, [%g1 + %g0] ASI;			\
-	mov	0x08, %g3;				\
-	stxa	%l1, [%g1 + %g3] ASI;			\
-	add	%g1, 0x10, %g1;				\
-	stxa	%l2, [%g1 + %g0] ASI;			\
-	stxa	%l3, [%g1 + %g3] ASI;			\
-	add	%g1, 0x10, %g1;				\
-	stxa	%l4, [%g1 + %g0] ASI;			\
-	stxa	%l5, [%g1 + %g3] ASI;			\
-	add	%g1, 0x10, %g1;				\
-	stxa	%l6, [%g1 + %g0] ASI;			\
-	stxa	%l7, [%g1 + %g3] ASI;			\
-	add	%g1, 0x10, %g1;				\
-	stxa	%i0, [%g1 + %g0] ASI;			\
-	stxa	%i1, [%g1 + %g3] ASI;			\
-	add	%g1, 0x10, %g1;				\
-	stxa	%i2, [%g1 + %g0] ASI;			\
-	stxa	%i3, [%g1 + %g3] ASI;			\
-	add	%g1, 0x10, %g1;				\
-	stxa	%i4, [%g1 + %g0] ASI;			\
-	stxa	%i5, [%g1 + %g3] ASI;			\
-	add	%g1, 0x10, %g1;				\
-	stxa	%i6, [%g1 + %g0] ASI;			\
-	stxa	%i7, [%g1 + %g3] ASI;			\
-	saved;						\
-	retry; nop; nop;				\
-	b,a,pt	%xcc, spill_fixup_dax;			\
-	b,a,pt	%xcc, spill_fixup_mna;			\
-	b,a,pt	%xcc, spill_fixup;
-
-#define SPILL_1_GENERIC_ETRAP				\
-etrap_user_spill_64bit:					\
-	stxa	%l0, [%sp + STACK_BIAS + 0x00] %asi;	\
-	stxa	%l1, [%sp + STACK_BIAS + 0x08] %asi;	\
-	stxa	%l2, [%sp + STACK_BIAS + 0x10] %asi;	\
-	stxa	%l3, [%sp + STACK_BIAS + 0x18] %asi;	\
-	stxa	%l4, [%sp + STACK_BIAS + 0x20] %asi;	\
-	stxa	%l5, [%sp + STACK_BIAS + 0x28] %asi;	\
-	stxa	%l6, [%sp + STACK_BIAS + 0x30] %asi;	\
-	stxa	%l7, [%sp + STACK_BIAS + 0x38] %asi;	\
-	stxa	%i0, [%sp + STACK_BIAS + 0x40] %asi;	\
-	stxa	%i1, [%sp + STACK_BIAS + 0x48] %asi;	\
-	stxa	%i2, [%sp + STACK_BIAS + 0x50] %asi;	\
-	stxa	%i3, [%sp + STACK_BIAS + 0x58] %asi;	\
-	stxa	%i4, [%sp + STACK_BIAS + 0x60] %asi;	\
-	stxa	%i5, [%sp + STACK_BIAS + 0x68] %asi;	\
-	stxa	%i6, [%sp + STACK_BIAS + 0x70] %asi;	\
-	stxa	%i7, [%sp + STACK_BIAS + 0x78] %asi;	\
-	saved;						\
-	sub	%g1, 2, %g1;				\
-	ba,pt	%xcc, etrap_save;			\
-	 wrpr	%g1, %cwp;				\
-	nop; nop; nop; nop; nop;			\
-	nop; nop; nop; nop;				\
-	ba,a,pt	%xcc, etrap_spill_fixup_64bit;		\
-	ba,a,pt	%xcc, etrap_spill_fixup_64bit;		\
-	ba,a,pt	%xcc, etrap_spill_fixup_64bit;
-
-#define SPILL_1_GENERIC_ETRAP_FIXUP			\
-etrap_spill_fixup_64bit:				\
-	ldub	[%g6 + TI_WSAVED], %g1;			\
-	sll	%g1, 3, %g3;				\
-	add	%g6, %g3, %g3;				\
-	stx	%sp, [%g3 + TI_RWIN_SPTRS];		\
-	sll	%g1, 7, %g3;				\
-	add	%g6, %g3, %g3;				\
-	stx	%l0, [%g3 + TI_REG_WINDOW + 0x00];	\
-	stx	%l1, [%g3 + TI_REG_WINDOW + 0x08];	\
-	stx	%l2, [%g3 + TI_REG_WINDOW + 0x10];	\
-	stx	%l3, [%g3 + TI_REG_WINDOW + 0x18];	\
-	stx	%l4, [%g3 + TI_REG_WINDOW + 0x20];	\
-	stx	%l5, [%g3 + TI_REG_WINDOW + 0x28];	\
-	stx	%l6, [%g3 + TI_REG_WINDOW + 0x30];	\
-	stx	%l7, [%g3 + TI_REG_WINDOW + 0x38];	\
-	stx	%i0, [%g3 + TI_REG_WINDOW + 0x40];	\
-	stx	%i1, [%g3 + TI_REG_WINDOW + 0x48];	\
-	stx	%i2, [%g3 + TI_REG_WINDOW + 0x50];	\
-	stx	%i3, [%g3 + TI_REG_WINDOW + 0x58];	\
-	stx	%i4, [%g3 + TI_REG_WINDOW + 0x60];	\
-	stx	%i5, [%g3 + TI_REG_WINDOW + 0x68];	\
-	stx	%i6, [%g3 + TI_REG_WINDOW + 0x70];	\
-	stx	%i7, [%g3 + TI_REG_WINDOW + 0x78];	\
-	add	%g1, 1, %g1;				\
-	stb	%g1, [%g6 + TI_WSAVED];			\
-	saved;						\
-	rdpr	%cwp, %g1;				\
-	sub	%g1, 2, %g1;				\
-	ba,pt	%xcc, etrap_save;			\
-	 wrpr	%g1, %cwp;				\
-	nop; nop; nop
-
-/* Normal 32bit spill */
-#define SPILL_2_GENERIC(ASI)				\
-	srl	%sp, 0, %sp;				\
-	stwa	%l0, [%sp + %g0] ASI;			\
-	mov	0x04, %g3;				\
-	stwa	%l1, [%sp + %g3] ASI;			\
-	add	%sp, 0x08, %g1;				\
-	stwa	%l2, [%g1 + %g0] ASI;			\
-	stwa	%l3, [%g1 + %g3] ASI;			\
-	add	%g1, 0x08, %g1;				\
-	stwa	%l4, [%g1 + %g0] ASI;			\
-	stwa	%l5, [%g1 + %g3] ASI;			\
-	add	%g1, 0x08, %g1;				\
-	stwa	%l6, [%g1 + %g0] ASI;			\
-	stwa	%l7, [%g1 + %g3] ASI;			\
-	add	%g1, 0x08, %g1;				\
-	stwa	%i0, [%g1 + %g0] ASI;			\
-	stwa	%i1, [%g1 + %g3] ASI;			\
-	add	%g1, 0x08, %g1;				\
-	stwa	%i2, [%g1 + %g0] ASI;			\
-	stwa	%i3, [%g1 + %g3] ASI;			\
-	add	%g1, 0x08, %g1;				\
-	stwa	%i4, [%g1 + %g0] ASI;			\
-	stwa	%i5, [%g1 + %g3] ASI;			\
-	add	%g1, 0x08, %g1;				\
-	stwa	%i6, [%g1 + %g0] ASI;			\
-	stwa	%i7, [%g1 + %g3] ASI;			\
-	saved;						\
-        retry; nop; nop;				\
-	b,a,pt	%xcc, spill_fixup_dax;			\
-	b,a,pt	%xcc, spill_fixup_mna;			\
-	b,a,pt	%xcc, spill_fixup;
-
-#define SPILL_2_GENERIC_ETRAP		\
-etrap_user_spill_32bit:			\
-	srl	%sp, 0, %sp;		\
-	stwa	%l0, [%sp + 0x00] %asi;	\
-	stwa	%l1, [%sp + 0x04] %asi;	\
-	stwa	%l2, [%sp + 0x08] %asi;	\
-	stwa	%l3, [%sp + 0x0c] %asi;	\
-	stwa	%l4, [%sp + 0x10] %asi;	\
-	stwa	%l5, [%sp + 0x14] %asi;	\
-	stwa	%l6, [%sp + 0x18] %asi;	\
-	stwa	%l7, [%sp + 0x1c] %asi;	\
-	stwa	%i0, [%sp + 0x20] %asi;	\
-	stwa	%i1, [%sp + 0x24] %asi;	\
-	stwa	%i2, [%sp + 0x28] %asi;	\
-	stwa	%i3, [%sp + 0x2c] %asi;	\
-	stwa	%i4, [%sp + 0x30] %asi;	\
-	stwa	%i5, [%sp + 0x34] %asi;	\
-	stwa	%i6, [%sp + 0x38] %asi;	\
-	stwa	%i7, [%sp + 0x3c] %asi;	\
-	saved;				\
-	sub	%g1, 2, %g1;		\
-	ba,pt	%xcc, etrap_save;	\
-	 wrpr	%g1, %cwp;		\
-	nop; nop; nop; nop;		\
-	nop; nop; nop; nop;		\
-	ba,a,pt	%xcc, etrap_spill_fixup_32bit; \
-	ba,a,pt	%xcc, etrap_spill_fixup_32bit; \
-	ba,a,pt	%xcc, etrap_spill_fixup_32bit;
-
-#define SPILL_2_GENERIC_ETRAP_FIXUP			\
-etrap_spill_fixup_32bit:				\
-	ldub	[%g6 + TI_WSAVED], %g1;			\
-	sll	%g1, 3, %g3;				\
-	add	%g6, %g3, %g3;				\
-	stx	%sp, [%g3 + TI_RWIN_SPTRS];		\
-	sll	%g1, 7, %g3;				\
-	add	%g6, %g3, %g3;				\
-	stw	%l0, [%g3 + TI_REG_WINDOW + 0x00];	\
-	stw	%l1, [%g3 + TI_REG_WINDOW + 0x04];	\
-	stw	%l2, [%g3 + TI_REG_WINDOW + 0x08];	\
-	stw	%l3, [%g3 + TI_REG_WINDOW + 0x0c];	\
-	stw	%l4, [%g3 + TI_REG_WINDOW + 0x10];	\
-	stw	%l5, [%g3 + TI_REG_WINDOW + 0x14];	\
-	stw	%l6, [%g3 + TI_REG_WINDOW + 0x18];	\
-	stw	%l7, [%g3 + TI_REG_WINDOW + 0x1c];	\
-	stw	%i0, [%g3 + TI_REG_WINDOW + 0x20];	\
-	stw	%i1, [%g3 + TI_REG_WINDOW + 0x24];	\
-	stw	%i2, [%g3 + TI_REG_WINDOW + 0x28];	\
-	stw	%i3, [%g3 + TI_REG_WINDOW + 0x2c];	\
-	stw	%i4, [%g3 + TI_REG_WINDOW + 0x30];	\
-	stw	%i5, [%g3 + TI_REG_WINDOW + 0x34];	\
-	stw	%i6, [%g3 + TI_REG_WINDOW + 0x38];	\
-	stw	%i7, [%g3 + TI_REG_WINDOW + 0x3c];	\
-	add	%g1, 1, %g1;				\
-	stb	%g1, [%g6 + TI_WSAVED];			\
-	saved;						\
-	rdpr	%cwp, %g1;				\
-	sub	%g1, 2, %g1;				\
-	ba,pt	%xcc, etrap_save;			\
-	 wrpr	%g1, %cwp;				\
-	nop; nop; nop
-
-#define SPILL_1_NORMAL SPILL_1_GENERIC(ASI_AIUP)
-#define SPILL_2_NORMAL SPILL_2_GENERIC(ASI_AIUP)
-#define SPILL_3_NORMAL SPILL_0_NORMAL
-#define SPILL_4_NORMAL SPILL_0_NORMAL
-#define SPILL_5_NORMAL SPILL_0_NORMAL
-#define SPILL_6_NORMAL SPILL_0_NORMAL
-#define SPILL_7_NORMAL SPILL_0_NORMAL
-
-#define SPILL_0_OTHER SPILL_0_NORMAL
-#define SPILL_1_OTHER SPILL_1_GENERIC(ASI_AIUS)
-#define SPILL_2_OTHER SPILL_2_GENERIC(ASI_AIUS)
-#define SPILL_3_OTHER SPILL_3_NORMAL
-#define SPILL_4_OTHER SPILL_4_NORMAL
-#define SPILL_5_OTHER SPILL_5_NORMAL
-#define SPILL_6_OTHER SPILL_6_NORMAL
-#define SPILL_7_OTHER SPILL_7_NORMAL
-
-/* Normal kernel fill */
-#define FILL_0_NORMAL					\
-	ldx	[%sp + STACK_BIAS + 0x00], %l0;		\
-	ldx	[%sp + STACK_BIAS + 0x08], %l1;		\
-	ldx	[%sp + STACK_BIAS + 0x10], %l2;		\
-	ldx	[%sp + STACK_BIAS + 0x18], %l3;		\
-	ldx	[%sp + STACK_BIAS + 0x20], %l4;		\
-	ldx	[%sp + STACK_BIAS + 0x28], %l5;		\
-	ldx	[%sp + STACK_BIAS + 0x30], %l6;		\
-	ldx	[%sp + STACK_BIAS + 0x38], %l7;		\
-	ldx	[%sp + STACK_BIAS + 0x40], %i0;		\
-	ldx	[%sp + STACK_BIAS + 0x48], %i1;		\
-	ldx	[%sp + STACK_BIAS + 0x50], %i2;		\
-	ldx	[%sp + STACK_BIAS + 0x58], %i3;		\
-	ldx	[%sp + STACK_BIAS + 0x60], %i4;		\
-	ldx	[%sp + STACK_BIAS + 0x68], %i5;		\
-	ldx	[%sp + STACK_BIAS + 0x70], %i6;		\
-	ldx	[%sp + STACK_BIAS + 0x78], %i7;		\
-	restored; retry; nop; nop; nop; nop; nop; nop;	\
-	nop; nop; nop; nop; nop; nop; nop; nop;
-
-#define FILL_0_NORMAL_RTRAP				\
-kern_rtt_fill:						\
-	rdpr	%cwp, %g1;				\
-	sub	%g1, 1, %g1;				\
-	wrpr	%g1, %cwp;				\
-	ldx	[%sp + STACK_BIAS + 0x00], %l0;		\
-	ldx	[%sp + STACK_BIAS + 0x08], %l1;		\
-	ldx	[%sp + STACK_BIAS + 0x10], %l2;		\
-	ldx	[%sp + STACK_BIAS + 0x18], %l3;		\
-	ldx	[%sp + STACK_BIAS + 0x20], %l4;		\
-	ldx	[%sp + STACK_BIAS + 0x28], %l5;		\
-	ldx	[%sp + STACK_BIAS + 0x30], %l6;		\
-	ldx	[%sp + STACK_BIAS + 0x38], %l7;		\
-	ldx	[%sp + STACK_BIAS + 0x40], %i0;		\
-	ldx	[%sp + STACK_BIAS + 0x48], %i1;		\
-	ldx	[%sp + STACK_BIAS + 0x50], %i2;		\
-	ldx	[%sp + STACK_BIAS + 0x58], %i3;		\
-	ldx	[%sp + STACK_BIAS + 0x60], %i4;		\
-	ldx	[%sp + STACK_BIAS + 0x68], %i5;		\
-	ldx	[%sp + STACK_BIAS + 0x70], %i6;		\
-	ldx	[%sp + STACK_BIAS + 0x78], %i7;		\
-	restored;					\
-	add	%g1, 1, %g1;				\
-	ba,pt	%xcc, kern_rtt_restore;			\
-	 wrpr	%g1, %cwp;				\
-	nop; nop; nop; nop; nop;			\
-	nop; nop; nop; nop;
-
-
-/* Normal 64bit fill */
-#define FILL_1_GENERIC(ASI)				\
-	add	%sp, STACK_BIAS + 0x00, %g1;		\
-	ldxa	[%g1 + %g0] ASI, %l0;			\
-	mov	0x08, %g2;				\
-	mov	0x10, %g3;				\
-	ldxa	[%g1 + %g2] ASI, %l1;			\
-	mov	0x18, %g5;				\
-	ldxa	[%g1 + %g3] ASI, %l2;			\
-	ldxa	[%g1 + %g5] ASI, %l3;			\
-	add	%g1, 0x20, %g1;				\
-	ldxa	[%g1 + %g0] ASI, %l4;			\
-	ldxa	[%g1 + %g2] ASI, %l5;			\
-	ldxa	[%g1 + %g3] ASI, %l6;			\
-	ldxa	[%g1 + %g5] ASI, %l7;			\
-	add	%g1, 0x20, %g1;				\
-	ldxa	[%g1 + %g0] ASI, %i0;			\
-	ldxa	[%g1 + %g2] ASI, %i1;			\
-	ldxa	[%g1 + %g3] ASI, %i2;			\
-	ldxa	[%g1 + %g5] ASI, %i3;			\
-	add	%g1, 0x20, %g1;				\
-	ldxa	[%g1 + %g0] ASI, %i4;			\
-	ldxa	[%g1 + %g2] ASI, %i5;			\
-	ldxa	[%g1 + %g3] ASI, %i6;			\
-	ldxa	[%g1 + %g5] ASI, %i7;			\
-	restored;					\
-	retry; nop; nop; nop; nop;			\
-	b,a,pt	%xcc, fill_fixup_dax;			\
-	b,a,pt	%xcc, fill_fixup_mna;			\
-	b,a,pt	%xcc, fill_fixup;
-
-#define FILL_1_GENERIC_RTRAP				\
-user_rtt_fill_64bit:					\
-	ldxa	[%sp + STACK_BIAS + 0x00] %asi, %l0;	\
-	ldxa	[%sp + STACK_BIAS + 0x08] %asi, %l1;	\
-	ldxa	[%sp + STACK_BIAS + 0x10] %asi, %l2;	\
-	ldxa	[%sp + STACK_BIAS + 0x18] %asi, %l3;	\
-	ldxa	[%sp + STACK_BIAS + 0x20] %asi, %l4;	\
-	ldxa	[%sp + STACK_BIAS + 0x28] %asi, %l5;	\
-	ldxa	[%sp + STACK_BIAS + 0x30] %asi, %l6;	\
-	ldxa	[%sp + STACK_BIAS + 0x38] %asi, %l7;	\
-	ldxa	[%sp + STACK_BIAS + 0x40] %asi, %i0;	\
-	ldxa	[%sp + STACK_BIAS + 0x48] %asi, %i1;	\
-	ldxa	[%sp + STACK_BIAS + 0x50] %asi, %i2;	\
-	ldxa	[%sp + STACK_BIAS + 0x58] %asi, %i3;	\
-	ldxa	[%sp + STACK_BIAS + 0x60] %asi, %i4;	\
-	ldxa	[%sp + STACK_BIAS + 0x68] %asi, %i5;	\
-	ldxa	[%sp + STACK_BIAS + 0x70] %asi, %i6;	\
-	ldxa	[%sp + STACK_BIAS + 0x78] %asi, %i7;	\
-	ba,pt	%xcc, user_rtt_pre_restore;		\
-	 restored;					\
-	nop; nop; nop; nop; nop; nop;			\
-	nop; nop; nop; nop; nop;			\
-	ba,a,pt	%xcc, user_rtt_fill_fixup;		\
-	ba,a,pt	%xcc, user_rtt_fill_fixup;		\
-	ba,a,pt	%xcc, user_rtt_fill_fixup;
-
-
-/* Normal 32bit fill */
-#define FILL_2_GENERIC(ASI)				\
-	srl	%sp, 0, %sp;				\
-	lduwa	[%sp + %g0] ASI, %l0;			\
-	mov	0x04, %g2;				\
-	mov	0x08, %g3;				\
-	lduwa	[%sp + %g2] ASI, %l1;			\
-	mov	0x0c, %g5;				\
-	lduwa	[%sp + %g3] ASI, %l2;			\
-	lduwa	[%sp + %g5] ASI, %l3;			\
-	add	%sp, 0x10, %g1;				\
-	lduwa	[%g1 + %g0] ASI, %l4;			\
-	lduwa	[%g1 + %g2] ASI, %l5;			\
-	lduwa	[%g1 + %g3] ASI, %l6;			\
-	lduwa	[%g1 + %g5] ASI, %l7;			\
-	add	%g1, 0x10, %g1;				\
-	lduwa	[%g1 + %g0] ASI, %i0;			\
-	lduwa	[%g1 + %g2] ASI, %i1;			\
-	lduwa	[%g1 + %g3] ASI, %i2;			\
-	lduwa	[%g1 + %g5] ASI, %i3;			\
-	add	%g1, 0x10, %g1;				\
-	lduwa	[%g1 + %g0] ASI, %i4;			\
-	lduwa	[%g1 + %g2] ASI, %i5;			\
-	lduwa	[%g1 + %g3] ASI, %i6;			\
-	lduwa	[%g1 + %g5] ASI, %i7;			\
-	restored;					\
-	retry; nop; nop; nop; nop;			\
-	b,a,pt	%xcc, fill_fixup_dax;			\
-	b,a,pt	%xcc, fill_fixup_mna;			\
-	b,a,pt	%xcc, fill_fixup;
-
-#define FILL_2_GENERIC_RTRAP				\
-user_rtt_fill_32bit:					\
-	srl	%sp, 0, %sp;				\
-	lduwa	[%sp + 0x00] %asi, %l0;			\
-	lduwa	[%sp + 0x04] %asi, %l1;			\
-	lduwa	[%sp + 0x08] %asi, %l2;			\
-	lduwa	[%sp + 0x0c] %asi, %l3;			\
-	lduwa	[%sp + 0x10] %asi, %l4;			\
-	lduwa	[%sp + 0x14] %asi, %l5;			\
-	lduwa	[%sp + 0x18] %asi, %l6;			\
-	lduwa	[%sp + 0x1c] %asi, %l7;			\
-	lduwa	[%sp + 0x20] %asi, %i0;			\
-	lduwa	[%sp + 0x24] %asi, %i1;			\
-	lduwa	[%sp + 0x28] %asi, %i2;			\
-	lduwa	[%sp + 0x2c] %asi, %i3;			\
-	lduwa	[%sp + 0x30] %asi, %i4;			\
-	lduwa	[%sp + 0x34] %asi, %i5;			\
-	lduwa	[%sp + 0x38] %asi, %i6;			\
-	lduwa	[%sp + 0x3c] %asi, %i7;			\
-	ba,pt	%xcc, user_rtt_pre_restore;		\
-	 restored;					\
-	nop; nop; nop; nop; nop;			\
-	nop; nop; nop; nop; nop;			\
-	ba,a,pt	%xcc, user_rtt_fill_fixup;		\
-	ba,a,pt	%xcc, user_rtt_fill_fixup;		\
-	ba,a,pt	%xcc, user_rtt_fill_fixup;
-		
-
-#define FILL_1_NORMAL FILL_1_GENERIC(ASI_AIUP)
-#define FILL_2_NORMAL FILL_2_GENERIC(ASI_AIUP)
-#define FILL_3_NORMAL FILL_0_NORMAL
-#define FILL_4_NORMAL FILL_0_NORMAL
-#define FILL_5_NORMAL FILL_0_NORMAL
-#define FILL_6_NORMAL FILL_0_NORMAL
-#define FILL_7_NORMAL FILL_0_NORMAL
-
-#define FILL_0_OTHER FILL_0_NORMAL
-#define FILL_1_OTHER FILL_1_GENERIC(ASI_AIUS)
-#define FILL_2_OTHER FILL_2_GENERIC(ASI_AIUS)
-#define FILL_3_OTHER FILL_3_NORMAL
-#define FILL_4_OTHER FILL_4_NORMAL
-#define FILL_5_OTHER FILL_5_NORMAL
-#define FILL_6_OTHER FILL_6_NORMAL
-#define FILL_7_OTHER FILL_7_NORMAL
-
-#endif /* !(_SPARC64_TTABLE_H) */
+#include <asm-sparc/ttable.h>
diff --git a/include/asm-sparc64/types.h b/include/asm-sparc64/types.h
index b27ccc8..cfbfad5 100644
--- a/include/asm-sparc64/types.h
+++ b/include/asm-sparc64/types.h
@@ -1,34 +1 @@
-#ifndef _SPARC64_TYPES_H
-#define _SPARC64_TYPES_H
-
-/*
- * This file is never included by application software unless
- * explicitly requested (e.g., via linux/types.h) in which case the
- * application is Linux specific so (user-) name space pollution is
- * not a major issue.  However, for interoperability, libraries still
- * need to be careful to avoid a name clashes.
- */
-#include <asm-generic/int-l64.h>
-
-#ifndef __ASSEMBLY__
-
-typedef unsigned short umode_t;
-
-#endif /* __ASSEMBLY__ */
-
-#ifdef __KERNEL__
-
-#define BITS_PER_LONG 64
-
-#ifndef __ASSEMBLY__
-
-/* Dma addresses come in generic and 64-bit flavours.  */
-
-typedef u32 dma_addr_t;
-typedef u64 dma64_addr_t;
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* __KERNEL__ */
-
-#endif /* defined(_SPARC64_TYPES_H) */
+#include <asm-sparc/types.h>
diff --git a/include/asm-sparc64/uaccess.h b/include/asm-sparc64/uaccess.h
index 5fcbaf6..2872d22 100644
--- a/include/asm-sparc64/uaccess.h
+++ b/include/asm-sparc64/uaccess.h
@@ -1,273 +1 @@
-#ifndef _ASM_UACCESS_H
-#define _ASM_UACCESS_H
-
-/*
- * User space memory access functions
- */
-
-#ifdef __KERNEL__
-#include <linux/compiler.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <asm/asi.h>
-#include <asm/system.h>
-#include <asm/spitfire.h>
-#include <asm-generic/uaccess.h>
-#endif
-
-#ifndef __ASSEMBLY__
-
-/*
- * Sparc64 is segmented, though more like the M68K than the I386. 
- * We use the secondary ASI to address user memory, which references a
- * completely different VM map, thus there is zero chance of the user
- * doing something queer and tricking us into poking kernel memory.
- *
- * What is left here is basically what is needed for the other parts of
- * the kernel that expect to be able to manipulate, erum, "segments".
- * Or perhaps more properly, permissions.
- *
- * "For historical reasons, these macros are grossly misnamed." -Linus
- */
-
-#define KERNEL_DS   ((mm_segment_t) { ASI_P })
-#define USER_DS     ((mm_segment_t) { ASI_AIUS })	/* har har har */
-
-#define VERIFY_READ	0
-#define VERIFY_WRITE	1
-
-#define get_fs() ((mm_segment_t) { get_thread_current_ds() })
-#define get_ds() (KERNEL_DS)
-
-#define segment_eq(a,b)  ((a).seg == (b).seg)
-
-#define set_fs(val)								\
-do {										\
-	set_thread_current_ds((val).seg);					\
-	__asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "r" ((val).seg));	\
-} while(0)
-
-static inline int __access_ok(const void __user * addr, unsigned long size)
-{
-	return 1;
-}
-
-static inline int access_ok(int type, const void __user * addr, unsigned long size)
-{
-	return 1;
-}
-
-/*
- * The exception table consists of pairs of addresses: the first is the
- * address of an instruction that is allowed to fault, and the second is
- * the address at which the program should continue.  No registers are
- * modified, so it is entirely up to the continuation code to figure out
- * what to do.
- *
- * All the routines below use bits of fixup code that are out of line
- * with the main instruction path.  This means when everything is well,
- * we don't even have to jump over them.  Further, they do not intrude
- * on our cache or tlb entries.
- */
-
-struct exception_table_entry {
-        unsigned int insn, fixup;
-};
-
-extern void __ret_efault(void);
-extern void __retl_efault(void);
-
-/* Uh, these should become the main single-value transfer routines..
- * They automatically use the right size if we just have the right
- * pointer type..
- *
- * This gets kind of ugly. We want to return _two_ values in "get_user()"
- * and yet we don't want to do any pointers, because that is too much
- * of a performance impact. Thus we have a few rather ugly macros here,
- * and hide all the ugliness from the user.
- */
-#define put_user(x,ptr) ({ \
-unsigned long __pu_addr = (unsigned long)(ptr); \
-__chk_user_ptr(ptr); \
-__put_user_nocheck((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr))); })
-
-#define get_user(x,ptr) ({ \
-unsigned long __gu_addr = (unsigned long)(ptr); \
-__chk_user_ptr(ptr); \
-__get_user_nocheck((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr))); })
-
-#define __put_user(x,ptr) put_user(x,ptr)
-#define __get_user(x,ptr) get_user(x,ptr)
-
-struct __large_struct { unsigned long buf[100]; };
-#define __m(x) ((struct __large_struct *)(x))
-
-#define __put_user_nocheck(data,addr,size) ({ \
-register int __pu_ret; \
-switch (size) { \
-case 1: __put_user_asm(data,b,addr,__pu_ret); break; \
-case 2: __put_user_asm(data,h,addr,__pu_ret); break; \
-case 4: __put_user_asm(data,w,addr,__pu_ret); break; \
-case 8: __put_user_asm(data,x,addr,__pu_ret); break; \
-default: __pu_ret = __put_user_bad(); break; \
-} __pu_ret; })
-
-#define __put_user_asm(x,size,addr,ret)					\
-__asm__ __volatile__(							\
-	"/* Put user asm, inline. */\n"					\
-"1:\t"	"st"#size "a %1, [%2] %%asi\n\t"				\
-	"clr	%0\n"							\
-"2:\n\n\t"								\
-	".section .fixup,#alloc,#execinstr\n\t"				\
-	".align	4\n"							\
-"3:\n\t"								\
-	"sethi	%%hi(2b), %0\n\t"					\
-	"jmpl	%0 + %%lo(2b), %%g0\n\t"				\
-	" mov	%3, %0\n\n\t"						\
-	".previous\n\t"							\
-	".section __ex_table,\"a\"\n\t"					\
-	".align	4\n\t"							\
-	".word	1b, 3b\n\t"						\
-	".previous\n\n\t"						\
-       : "=r" (ret) : "r" (x), "r" (__m(addr)),				\
-	 "i" (-EFAULT))
-
-extern int __put_user_bad(void);
-
-#define __get_user_nocheck(data,addr,size,type) ({ \
-register int __gu_ret; \
-register unsigned long __gu_val; \
-switch (size) { \
-case 1: __get_user_asm(__gu_val,ub,addr,__gu_ret); break; \
-case 2: __get_user_asm(__gu_val,uh,addr,__gu_ret); break; \
-case 4: __get_user_asm(__gu_val,uw,addr,__gu_ret); break; \
-case 8: __get_user_asm(__gu_val,x,addr,__gu_ret); break; \
-default: __gu_val = 0; __gu_ret = __get_user_bad(); break; \
-} data = (type) __gu_val; __gu_ret; })
-
-#define __get_user_nocheck_ret(data,addr,size,type,retval) ({ \
-register unsigned long __gu_val __asm__ ("l1"); \
-switch (size) { \
-case 1: __get_user_asm_ret(__gu_val,ub,addr,retval); break; \
-case 2: __get_user_asm_ret(__gu_val,uh,addr,retval); break; \
-case 4: __get_user_asm_ret(__gu_val,uw,addr,retval); break; \
-case 8: __get_user_asm_ret(__gu_val,x,addr,retval); break; \
-default: if (__get_user_bad()) return retval; \
-} data = (type) __gu_val; })
-
-#define __get_user_asm(x,size,addr,ret)					\
-__asm__ __volatile__(							\
-	"/* Get user asm, inline. */\n"					\
-"1:\t"	"ld"#size "a [%2] %%asi, %1\n\t"				\
-	"clr	%0\n"							\
-"2:\n\n\t"								\
-	".section .fixup,#alloc,#execinstr\n\t"				\
-	".align	4\n"							\
-"3:\n\t"								\
-	"sethi	%%hi(2b), %0\n\t"					\
-	"clr	%1\n\t"							\
-	"jmpl	%0 + %%lo(2b), %%g0\n\t"				\
-	" mov	%3, %0\n\n\t"						\
-	".previous\n\t"							\
-	".section __ex_table,\"a\"\n\t"					\
-	".align	4\n\t"							\
-	".word	1b, 3b\n\n\t"						\
-	".previous\n\t"							\
-       : "=r" (ret), "=r" (x) : "r" (__m(addr)),			\
-	 "i" (-EFAULT))
-
-#define __get_user_asm_ret(x,size,addr,retval)				\
-if (__builtin_constant_p(retval) && retval == -EFAULT)			\
-__asm__ __volatile__(							\
-	"/* Get user asm ret, inline. */\n"				\
-"1:\t"	"ld"#size "a [%1] %%asi, %0\n\n\t"				\
-	".section __ex_table,\"a\"\n\t"					\
-	".align	4\n\t"							\
-	".word	1b,__ret_efault\n\n\t"					\
-	".previous\n\t"							\
-       : "=r" (x) : "r" (__m(addr)));					\
-else									\
-__asm__ __volatile__(							\
-	"/* Get user asm ret, inline. */\n"				\
-"1:\t"	"ld"#size "a [%1] %%asi, %0\n\n\t"				\
-	".section .fixup,#alloc,#execinstr\n\t"				\
-	".align	4\n"							\
-"3:\n\t"								\
-	"ret\n\t"							\
-	" restore %%g0, %2, %%o0\n\n\t"					\
-	".previous\n\t"							\
-	".section __ex_table,\"a\"\n\t"					\
-	".align	4\n\t"							\
-	".word	1b, 3b\n\n\t"						\
-	".previous\n\t"							\
-       : "=r" (x) : "r" (__m(addr)), "i" (retval))
-
-extern int __get_user_bad(void);
-
-extern unsigned long __must_check ___copy_from_user(void *to,
-						    const void __user *from,
-						    unsigned long size);
-extern unsigned long copy_from_user_fixup(void *to, const void __user *from,
-					  unsigned long size);
-static inline unsigned long __must_check
-copy_from_user(void *to, const void __user *from, unsigned long size)
-{
-	unsigned long ret = ___copy_from_user(to, from, size);
-
-	if (unlikely(ret))
-		ret = copy_from_user_fixup(to, from, size);
-	return ret;
-}
-#define __copy_from_user copy_from_user
-
-extern unsigned long __must_check ___copy_to_user(void __user *to,
-						  const void *from,
-						  unsigned long size);
-extern unsigned long copy_to_user_fixup(void __user *to, const void *from,
-					unsigned long size);
-static inline unsigned long __must_check
-copy_to_user(void __user *to, const void *from, unsigned long size)
-{
-	unsigned long ret = ___copy_to_user(to, from, size);
-
-	if (unlikely(ret))
-		ret = copy_to_user_fixup(to, from, size);
-	return ret;
-}
-#define __copy_to_user copy_to_user
-
-extern unsigned long __must_check ___copy_in_user(void __user *to,
-						  const void __user *from,
-						  unsigned long size);
-extern unsigned long copy_in_user_fixup(void __user *to, void __user *from,
-					unsigned long size);
-static inline unsigned long __must_check
-copy_in_user(void __user *to, void __user *from, unsigned long size)
-{
-	unsigned long ret = ___copy_in_user(to, from, size);
-
-	if (unlikely(ret))
-		ret = copy_in_user_fixup(to, from, size);
-	return ret;
-}
-#define __copy_in_user copy_in_user
-
-extern unsigned long __must_check __clear_user(void __user *, unsigned long);
-
-#define clear_user __clear_user
-
-extern long __must_check __strncpy_from_user(char *dest, const char __user *src, long count);
-
-#define strncpy_from_user __strncpy_from_user
-
-extern long __strlen_user(const char __user *);
-extern long __strnlen_user(const char __user *, long len);
-
-#define strlen_user __strlen_user
-#define strnlen_user __strnlen_user
-#define __copy_to_user_inatomic __copy_to_user
-#define __copy_from_user_inatomic __copy_from_user
-
-#endif  /* __ASSEMBLY__ */
-
-#endif /* _ASM_UACCESS_H */
+#include <asm-sparc/uaccess.h>
diff --git a/include/asm-sparc64/uctx.h b/include/asm-sparc64/uctx.h
index dc937c7..9e1b579 100644
--- a/include/asm-sparc64/uctx.h
+++ b/include/asm-sparc64/uctx.h
@@ -1,71 +1 @@
-/*
- * uctx.h: Sparc64 {set,get}context() register state layouts.
- *
- * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef __SPARC64_UCTX_H
-#define __SPARC64_UCTX_H
-
-#define MC_TSTATE	0
-#define MC_PC		1
-#define MC_NPC		2
-#define MC_Y		3
-#define MC_G1		4
-#define MC_G2		5
-#define MC_G3		6
-#define MC_G4		7
-#define MC_G5		8
-#define MC_G6		9
-#define MC_G7		10
-#define MC_O0		11
-#define MC_O1		12
-#define MC_O2		13
-#define MC_O3		14
-#define MC_O4		15
-#define MC_O5		16
-#define MC_O6		17
-#define MC_O7		18
-#define MC_NGREG	19
-
-typedef unsigned long mc_greg_t;
-typedef mc_greg_t mc_gregset_t[MC_NGREG];
-
-#define MC_MAXFPQ	16
-struct mc_fq {
-	unsigned long	*mcfq_addr;
-	unsigned int	mcfq_insn;
-};
-
-struct mc_fpu {
-	union {
-		unsigned int	sregs[32];
-		unsigned long	dregs[32];
-		long double	qregs[16];
-	} mcfpu_fregs;
-	unsigned long	mcfpu_fsr;
-	unsigned long	mcfpu_fprs;
-	unsigned long	mcfpu_gsr;
-	struct mc_fq	*mcfpu_fq;
-	unsigned char	mcfpu_qcnt;
-	unsigned char	mcfpu_qentsz;
-	unsigned char	mcfpu_enab;
-};
-typedef struct mc_fpu mc_fpu_t;
-
-typedef struct {
-	mc_gregset_t	mc_gregs;
-	mc_greg_t	mc_fp;
-	mc_greg_t	mc_i7;
-	mc_fpu_t	mc_fpregs;
-} mcontext_t;
-
-struct ucontext {
-	struct ucontext		*uc_link;
-	unsigned long		uc_flags;
-	sigset_t		uc_sigmask;
-	mcontext_t		uc_mcontext;
-};
-typedef struct ucontext ucontext_t;
-
-#endif /* __SPARC64_UCTX_H */
+#include <asm-sparc/uctx.h>
diff --git a/include/asm-sparc64/unaligned.h b/include/asm-sparc64/unaligned.h
index edcebb0..19fbf95 100644
--- a/include/asm-sparc64/unaligned.h
+++ b/include/asm-sparc64/unaligned.h
@@ -1,10 +1 @@
-#ifndef _ASM_SPARC64_UNALIGNED_H
-#define _ASM_SPARC64_UNALIGNED_H
-
-#include <linux/unaligned/be_struct.h>
-#include <linux/unaligned/le_byteshift.h>
-#include <linux/unaligned/generic.h>
-#define get_unaligned	__get_unaligned_be
-#define put_unaligned	__put_unaligned_be
-
-#endif /* _ASM_SPARC64_UNALIGNED_H */
+#include <asm-sparc/unaligned.h>
diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
index 13be445..ad86e0b 100644
--- a/include/asm-sparc64/unistd.h
+++ b/include/asm-sparc64/unistd.h
@@ -1,373 +1 @@
-#ifndef _SPARC64_UNISTD_H
-#define _SPARC64_UNISTD_H
-
-/*
- * System calls under the Sparc.
- *
- * Don't be scared by the ugly clobbers, it is the only way I can
- * think of right now to force the arguments into fixed registers
- * before the trap into the system call with gcc 'asm' statements.
- *
- * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
- *
- * SunOS compatibility based upon preliminary work which is:
- *
- * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
- */
-
-#define __NR_restart_syscall      0 /* Linux Specific				   */
-#define __NR_exit                 1 /* Common                                      */
-#define __NR_fork                 2 /* Common                                      */
-#define __NR_read                 3 /* Common                                      */
-#define __NR_write                4 /* Common                                      */
-#define __NR_open                 5 /* Common                                      */
-#define __NR_close                6 /* Common                                      */
-#define __NR_wait4                7 /* Common                                      */
-#define __NR_creat                8 /* Common                                      */
-#define __NR_link                 9 /* Common                                      */
-#define __NR_unlink              10 /* Common                                      */
-#define __NR_execv               11 /* SunOS Specific                              */
-#define __NR_chdir               12 /* Common                                      */
-#define __NR_chown		 13 /* Common					   */
-#define __NR_mknod               14 /* Common                                      */
-#define __NR_chmod               15 /* Common                                      */
-#define __NR_lchown              16 /* Common                                      */
-#define __NR_brk                 17 /* Common                                      */
-#define __NR_perfctr             18 /* Performance counter operations              */
-#define __NR_lseek               19 /* Common                                      */
-#define __NR_getpid              20 /* Common                                      */
-#define __NR_capget		 21 /* Linux Specific				   */
-#define __NR_capset		 22 /* Linux Specific				   */
-#define __NR_setuid              23 /* Implemented via setreuid in SunOS           */
-#define __NR_getuid              24 /* Common                                      */
-#define __NR_vmsplice	         25 /* ENOSYS under SunOS			   */
-#define __NR_ptrace              26 /* Common                                      */
-#define __NR_alarm               27 /* Implemented via setitimer in SunOS          */
-#define __NR_sigaltstack	 28 /* Common					   */
-#define __NR_pause               29 /* Is sigblock(0)->sigpause() in SunOS         */
-#define __NR_utime               30 /* Implemented via utimes() under SunOS        */
-/* #define __NR_lchown32         31    Linux sparc32 specific                      */
-/* #define __NR_fchown32         32    Linux sparc32 specific                      */
-#define __NR_access              33 /* Common                                      */
-#define __NR_nice                34 /* Implemented via get/setpriority() in SunOS  */
-/* #define __NR_chown32          35    Linux sparc32 specific                      */
-#define __NR_sync                36 /* Common                                      */
-#define __NR_kill                37 /* Common                                      */
-#define __NR_stat                38 /* Common                                      */
-#define __NR_sendfile		 39 /* Linux Specific				   */
-#define __NR_lstat               40 /* Common                                      */
-#define __NR_dup                 41 /* Common                                      */
-#define __NR_pipe                42 /* Common                                      */
-#define __NR_times               43 /* Implemented via getrusage() in SunOS        */
-/* #define __NR_getuid32         44    Linux sparc32 specific                      */
-#define __NR_umount2             45 /* Linux Specific                              */
-#define __NR_setgid              46 /* Implemented via setregid() in SunOS         */
-#define __NR_getgid              47 /* Common                                      */
-#define __NR_signal              48 /* Implemented via sigvec() in SunOS           */
-#define __NR_geteuid             49 /* SunOS calls getuid()                        */
-#define __NR_getegid             50 /* SunOS calls getgid()                        */
-#define __NR_acct                51 /* Common                                      */
-#define __NR_memory_ordering	 52 /* Linux Specific				   */
-/* #define __NR_getgid32         53    Linux sparc32 specific                      */
-#define __NR_ioctl               54 /* Common                                      */
-#define __NR_reboot              55 /* Common                                      */
-/* #define __NR_mmap2		 56    Linux sparc32 Specific                      */
-#define __NR_symlink             57 /* Common                                      */
-#define __NR_readlink            58 /* Common                                      */
-#define __NR_execve              59 /* Common                                      */
-#define __NR_umask               60 /* Common                                      */
-#define __NR_chroot              61 /* Common                                      */
-#define __NR_fstat               62 /* Common                                      */
-#define __NR_fstat64             63 /* Linux Specific                              */
-#define __NR_getpagesize         64 /* Common                                      */
-#define __NR_msync               65 /* Common in newer 1.3.x revs...               */
-#define __NR_vfork               66 /* Common                                      */
-#define __NR_pread64             67 /* Linux Specific                              */
-#define __NR_pwrite64            68 /* Linux Specific                              */
-/* #define __NR_geteuid32        69    Linux sparc32, sbrk under SunOS             */
-/* #define __NR_getegid32        70    Linux sparc32, sstk under SunOS             */
-#define __NR_mmap                71 /* Common                                      */
-/* #define __NR_setreuid32       72    Linux sparc32, vadvise under SunOS          */
-#define __NR_munmap              73 /* Common                                      */
-#define __NR_mprotect            74 /* Common                                      */
-#define __NR_madvise             75 /* Common                                      */
-#define __NR_vhangup             76 /* Common                                      */
-/* #define __NR_truncate64       77    Linux sparc32 Specific			   */
-#define __NR_mincore             78 /* Common                                      */
-#define __NR_getgroups           79 /* Common                                      */
-#define __NR_setgroups           80 /* Common                                      */
-#define __NR_getpgrp             81 /* Common                                      */
-/* #define __NR_setgroups32      82    Linux sparc32, setpgrp under SunOS          */
-#define __NR_setitimer           83 /* Common                                      */
-/* #define __NR_ftruncate64      84    Linux sparc32 Specific			   */
-#define __NR_swapon              85 /* Common                                      */
-#define __NR_getitimer           86 /* Common                                      */
-/* #define __NR_setuid32         87    Linux sparc32, gethostname under SunOS      */
-#define __NR_sethostname         88 /* Common                                      */
-/* #define __NR_setgid32         89    Linux sparc32, getdtablesize under SunOS    */
-#define __NR_dup2                90 /* Common                                      */
-/* #define __NR_setfsuid32       91    Linux sparc32, getdopt under SunOS          */
-#define __NR_fcntl               92 /* Common                                      */
-#define __NR_select              93 /* Common                                      */
-/* #define __NR_setfsgid32       94    Linux sparc32, setdopt under SunOS          */
-#define __NR_fsync               95 /* Common                                      */
-#define __NR_setpriority         96 /* Common                                      */
-#define __NR_socket              97 /* Common                                      */
-#define __NR_connect             98 /* Common                                      */
-#define __NR_accept              99 /* Common                                      */
-#define __NR_getpriority        100 /* Common                                      */
-#define __NR_rt_sigreturn       101 /* Linux Specific                              */
-#define __NR_rt_sigaction       102 /* Linux Specific                              */
-#define __NR_rt_sigprocmask     103 /* Linux Specific                              */
-#define __NR_rt_sigpending      104 /* Linux Specific                              */
-#define __NR_rt_sigtimedwait    105 /* Linux Specific                              */
-#define __NR_rt_sigqueueinfo    106 /* Linux Specific                              */
-#define __NR_rt_sigsuspend      107 /* Linux Specific                              */
-#define __NR_setresuid          108 /* Linux Specific, sigvec under SunOS	   */
-#define __NR_getresuid          109 /* Linux Specific, sigblock under SunOS	   */
-#define __NR_setresgid          110 /* Linux Specific, sigsetmask under SunOS	   */
-#define __NR_getresgid          111 /* Linux Specific, sigpause under SunOS	   */
-/* #define __NR_setregid32       75    Linux sparc32, sigstack under SunOS         */
-#define __NR_recvmsg            113 /* Common                                      */
-#define __NR_sendmsg            114 /* Common                                      */
-/* #define __NR_getgroups32     115    Linux sparc32, vtrace under SunOS           */
-#define __NR_gettimeofday       116 /* Common                                      */
-#define __NR_getrusage          117 /* Common                                      */
-#define __NR_getsockopt         118 /* Common                                      */
-#define __NR_getcwd		119 /* Linux Specific				   */
-#define __NR_readv              120 /* Common                                      */
-#define __NR_writev             121 /* Common                                      */
-#define __NR_settimeofday       122 /* Common                                      */
-#define __NR_fchown             123 /* Common                                      */
-#define __NR_fchmod             124 /* Common                                      */
-#define __NR_recvfrom           125 /* Common                                      */
-#define __NR_setreuid           126 /* Common                                      */
-#define __NR_setregid           127 /* Common                                      */
-#define __NR_rename             128 /* Common                                      */
-#define __NR_truncate           129 /* Common                                      */
-#define __NR_ftruncate          130 /* Common                                      */
-#define __NR_flock              131 /* Common                                      */
-#define __NR_lstat64		132 /* Linux Specific                              */
-#define __NR_sendto             133 /* Common                                      */
-#define __NR_shutdown           134 /* Common                                      */
-#define __NR_socketpair         135 /* Common                                      */
-#define __NR_mkdir              136 /* Common                                      */
-#define __NR_rmdir              137 /* Common                                      */
-#define __NR_utimes             138 /* SunOS Specific                              */
-#define __NR_stat64		139 /* Linux Specific			           */
-#define __NR_sendfile64         140 /* adjtime under SunOS                         */
-#define __NR_getpeername        141 /* Common                                      */
-#define __NR_futex              142 /* gethostid under SunOS                       */
-#define __NR_gettid             143 /* ENOSYS under SunOS                          */
-#define __NR_getrlimit		144 /* Common                                      */
-#define __NR_setrlimit          145 /* Common                                      */
-#define __NR_pivot_root		146 /* Linux Specific, killpg under SunOS          */
-#define __NR_prctl		147 /* ENOSYS under SunOS                          */
-#define __NR_pciconfig_read	148 /* ENOSYS under SunOS                          */
-#define __NR_pciconfig_write	149 /* ENOSYS under SunOS                          */
-#define __NR_getsockname        150 /* Common                                      */
-#define __NR_inotify_init       151 /* Linux specific                              */
-#define __NR_inotify_add_watch  152 /* Linux specific                              */
-#define __NR_poll               153 /* Common                                      */
-#define __NR_getdents64		154 /* Linux specific				   */
-/* #define __NR_fcntl64         155    Linux sparc32 Specific                      */
-#define __NR_inotify_rm_watch   156 /* Linux specific				   */
-#define __NR_statfs             157 /* Common                                      */
-#define __NR_fstatfs            158 /* Common                                      */
-#define __NR_umount             159 /* Common                                      */
-#define __NR_sched_set_affinity 160 /* Linux specific, async_daemon under SunOS    */
-#define __NR_sched_get_affinity 161 /* Linux specific, getfh under SunOS           */
-#define __NR_getdomainname      162 /* SunOS Specific                              */
-#define __NR_setdomainname      163 /* Common                                      */
-#define __NR_utrap_install	164 /* SYSV ABI/v9 required			   */
-#define __NR_quotactl           165 /* Common                                      */
-#define __NR_set_tid_address    166 /* Linux specific, exportfs under SunOS        */
-#define __NR_mount              167 /* Common                                      */
-#define __NR_ustat              168 /* Common                                      */
-#define __NR_setxattr           169 /* SunOS: semsys                               */
-#define __NR_lsetxattr          170 /* SunOS: msgsys                               */
-#define __NR_fsetxattr          171 /* SunOS: shmsys                               */
-#define __NR_getxattr           172 /* SunOS: auditsys                             */
-#define __NR_lgetxattr          173 /* SunOS: rfssys                               */
-#define __NR_getdents           174 /* Common                                      */
-#define __NR_setsid             175 /* Common                                      */
-#define __NR_fchdir             176 /* Common                                      */
-#define __NR_fgetxattr          177 /* SunOS: fchroot                              */
-#define __NR_listxattr          178 /* SunOS: vpixsys                              */
-#define __NR_llistxattr         179 /* SunOS: aioread                              */
-#define __NR_flistxattr         180 /* SunOS: aiowrite                             */
-#define __NR_removexattr        181 /* SunOS: aiowait                              */
-#define __NR_lremovexattr       182 /* SunOS: aiocancel                            */
-#define __NR_sigpending         183 /* Common                                      */
-#define __NR_query_module	184 /* Linux Specific				   */
-#define __NR_setpgid            185 /* Common                                      */
-#define __NR_fremovexattr       186 /* SunOS: pathconf                             */
-#define __NR_tkill              187 /* SunOS: fpathconf                            */
-#define __NR_exit_group		188 /* Linux specific, sysconf undef SunOS         */
-#define __NR_uname              189 /* Linux Specific                              */
-#define __NR_init_module        190 /* Linux Specific                              */
-#define __NR_personality        191 /* Linux Specific                              */
-#define __NR_remap_file_pages   192 /* Linux Specific                              */
-#define __NR_epoll_create       193 /* Linux Specific                              */
-#define __NR_epoll_ctl          194 /* Linux Specific                              */
-#define __NR_epoll_wait         195 /* Linux Specific                              */
-#define __NR_ioprio_set         196 /* Linux Specific                              */
-#define __NR_getppid            197 /* Linux Specific                              */
-#define __NR_sigaction          198 /* Linux Specific                              */
-#define __NR_sgetmask           199 /* Linux Specific                              */
-#define __NR_ssetmask           200 /* Linux Specific                              */
-#define __NR_sigsuspend         201 /* Linux Specific                              */
-#define __NR_oldlstat           202 /* Linux Specific                              */
-#define __NR_uselib             203 /* Linux Specific                              */
-#define __NR_readdir            204 /* Linux Specific                              */
-#define __NR_readahead          205 /* Linux Specific                              */
-#define __NR_socketcall         206 /* Linux Specific                              */
-#define __NR_syslog             207 /* Linux Specific                              */
-#define __NR_lookup_dcookie     208 /* Linux Specific                              */
-#define __NR_fadvise64          209 /* Linux Specific                              */
-#define __NR_fadvise64_64       210 /* Linux Specific                              */
-#define __NR_tgkill             211 /* Linux Specific                              */
-#define __NR_waitpid            212 /* Linux Specific                              */
-#define __NR_swapoff            213 /* Linux Specific                              */
-#define __NR_sysinfo            214 /* Linux Specific                              */
-#define __NR_ipc                215 /* Linux Specific                              */
-#define __NR_sigreturn          216 /* Linux Specific                              */
-#define __NR_clone              217 /* Linux Specific                              */
-#define __NR_ioprio_get         218 /* Linux Specific                              */
-#define __NR_adjtimex           219 /* Linux Specific                              */
-#define __NR_sigprocmask        220 /* Linux Specific                              */
-#define __NR_create_module      221 /* Linux Specific                              */
-#define __NR_delete_module      222 /* Linux Specific                              */
-#define __NR_get_kernel_syms    223 /* Linux Specific                              */
-#define __NR_getpgid            224 /* Linux Specific                              */
-#define __NR_bdflush            225 /* Linux Specific                              */
-#define __NR_sysfs              226 /* Linux Specific                              */
-#define __NR_afs_syscall        227 /* Linux Specific                              */
-#define __NR_setfsuid           228 /* Linux Specific                              */
-#define __NR_setfsgid           229 /* Linux Specific                              */
-#define __NR__newselect         230 /* Linux Specific                              */
-#ifdef __KERNEL__
-#define __NR_time		231 /* Linux sparc32                               */
-#endif
-#define __NR_splice             232 /* Linux Specific                              */
-#define __NR_stime              233 /* Linux Specific                              */
-#define __NR_statfs64           234 /* Linux Specific                              */
-#define __NR_fstatfs64          235 /* Linux Specific                              */
-#define __NR__llseek            236 /* Linux Specific                              */
-#define __NR_mlock              237
-#define __NR_munlock            238
-#define __NR_mlockall           239
-#define __NR_munlockall         240
-#define __NR_sched_setparam     241
-#define __NR_sched_getparam     242
-#define __NR_sched_setscheduler 243
-#define __NR_sched_getscheduler 244
-#define __NR_sched_yield        245
-#define __NR_sched_get_priority_max 246
-#define __NR_sched_get_priority_min 247
-#define __NR_sched_rr_get_interval  248
-#define __NR_nanosleep          249
-#define __NR_mremap             250
-#define __NR__sysctl            251
-#define __NR_getsid             252
-#define __NR_fdatasync          253
-#define __NR_nfsservctl         254
-#define __NR_sync_file_range	255
-#define __NR_clock_settime	256
-#define __NR_clock_gettime	257
-#define __NR_clock_getres	258
-#define __NR_clock_nanosleep	259
-#define __NR_sched_getaffinity	260
-#define __NR_sched_setaffinity	261
-#define __NR_timer_settime	262
-#define __NR_timer_gettime	263
-#define __NR_timer_getoverrun	264
-#define __NR_timer_delete	265
-#define __NR_timer_create	266
-/* #define __NR_vserver		267 Reserved for VSERVER */
-#define __NR_io_setup		268
-#define __NR_io_destroy		269
-#define __NR_io_submit		270
-#define __NR_io_cancel		271
-#define __NR_io_getevents	272
-#define __NR_mq_open		273
-#define __NR_mq_unlink		274
-#define __NR_mq_timedsend	275
-#define __NR_mq_timedreceive	276
-#define __NR_mq_notify		277
-#define __NR_mq_getsetattr	278
-#define __NR_waitid		279
-#define __NR_tee		280
-#define __NR_add_key		281
-#define __NR_request_key	282
-#define __NR_keyctl		283
-#define __NR_openat		284
-#define __NR_mkdirat		285
-#define __NR_mknodat		286
-#define __NR_fchownat		287
-#define __NR_futimesat		288
-#define __NR_fstatat64		289
-#define __NR_unlinkat		290
-#define __NR_renameat		291
-#define __NR_linkat		292
-#define __NR_symlinkat		293
-#define __NR_readlinkat		294
-#define __NR_fchmodat		295
-#define __NR_faccessat		296
-#define __NR_pselect6		297
-#define __NR_ppoll		298
-#define __NR_unshare		299
-#define __NR_set_robust_list	300
-#define __NR_get_robust_list	301
-#define __NR_migrate_pages	302
-#define __NR_mbind		303
-#define __NR_get_mempolicy	304
-#define __NR_set_mempolicy	305
-#define __NR_kexec_load		306
-#define __NR_move_pages		307
-#define __NR_getcpu		308
-#define __NR_epoll_pwait	309
-#define __NR_utimensat		310
-#define __NR_signalfd		311
-#define __NR_timerfd_create	312
-#define __NR_eventfd		313
-#define __NR_fallocate		314
-#define __NR_timerfd_settime	315
-#define __NR_timerfd_gettime	316
-
-#define NR_SYSCALLS		317
-
-#ifdef __KERNEL__
-#define __ARCH_WANT_IPC_PARSE_VERSION
-#define __ARCH_WANT_OLD_READDIR
-#define __ARCH_WANT_STAT64
-#define __ARCH_WANT_SYS_ALARM
-#define __ARCH_WANT_SYS_GETHOSTNAME
-#define __ARCH_WANT_SYS_PAUSE
-#define __ARCH_WANT_SYS_SGETMASK
-#define __ARCH_WANT_SYS_SIGNAL
-#define __ARCH_WANT_SYS_TIME
-#define __ARCH_WANT_COMPAT_SYS_TIME
-#define __ARCH_WANT_SYS_UTIME
-#define __ARCH_WANT_SYS_WAITPID
-#define __ARCH_WANT_SYS_SOCKETCALL
-#define __ARCH_WANT_SYS_FADVISE64
-#define __ARCH_WANT_SYS_GETPGRP
-#define __ARCH_WANT_SYS_LLSEEK
-#define __ARCH_WANT_SYS_NICE
-#define __ARCH_WANT_SYS_OLDUMOUNT
-#define __ARCH_WANT_SYS_SIGPENDING
-#define __ARCH_WANT_SYS_SIGPROCMASK
-#define __ARCH_WANT_SYS_RT_SIGSUSPEND
-#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
-
-/*
- * "Conditional" syscalls
- *
- * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
- * but it doesn't work on all toolchains, so we just do it by hand
- */
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
-
-#endif /* __KERNEL__ */
-#endif /* _SPARC64_UNISTD_H */
+#include <asm-sparc/unistd.h>
diff --git a/include/asm-sparc64/upa.h b/include/asm-sparc64/upa.h
index 5b16332..aab7293 100644
--- a/include/asm-sparc64/upa.h
+++ b/include/asm-sparc64/upa.h
@@ -1,109 +1 @@
-#ifndef _SPARC64_UPA_H
-#define _SPARC64_UPA_H
-
-#include <asm/asi.h>
-
-/* UPA level registers and defines. */
-
-/* UPA Config Register */
-#define UPA_CONFIG_RESV		0xffffffffc0000000 /* Reserved.                    */
-#define UPA_CONFIG_PCON		0x000000003fc00000 /* Depth of various sys queues. */
-#define UPA_CONFIG_MID		0x00000000003e0000 /* Module ID.                   */
-#define UPA_CONFIG_PCAP		0x000000000001ffff /* Port Capabilities.           */
-
-/* UPA Port ID Register */
-#define UPA_PORTID_FNP		0xff00000000000000 /* Hardcoded to 0xfc on ultra.  */
-#define UPA_PORTID_RESV		0x00fffff800000000 /* Reserved.                    */
-#define UPA_PORTID_ECCVALID     0x0000000400000000 /* Zero if mod can generate ECC */
-#define UPA_PORTID_ONEREAD      0x0000000200000000 /* Set if mod generates P_RASB  */
-#define UPA_PORTID_PINTRDQ      0x0000000180000000 /* # outstanding P_INT_REQ's    */
-#define UPA_PORTID_PREQDQ       0x000000007e000000 /* slave-wr's to mod supported  */
-#define UPA_PORTID_PREQRD       0x0000000001e00000 /* # incoming P_REQ's supported */
-#define UPA_PORTID_UPACAP       0x00000000001f0000 /* UPA capabilities of mod      */
-#define UPA_PORTID_ID           0x000000000000ffff /* Module Identification bits  */
-
-/* UPA I/O space accessors */
-#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
-static inline unsigned char _upa_readb(unsigned long addr)
-{
-	unsigned char ret;
-
-	__asm__ __volatile__("lduba\t[%1] %2, %0\t/* upa_readb */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-
-	return ret;
-}
-
-static inline unsigned short _upa_readw(unsigned long addr)
-{
-	unsigned short ret;
-
-	__asm__ __volatile__("lduha\t[%1] %2, %0\t/* upa_readw */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-
-	return ret;
-}
-
-static inline unsigned int _upa_readl(unsigned long addr)
-{
-	unsigned int ret;
-
-	__asm__ __volatile__("lduwa\t[%1] %2, %0\t/* upa_readl */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-
-	return ret;
-}
-
-static inline unsigned long _upa_readq(unsigned long addr)
-{
-	unsigned long ret;
-
-	__asm__ __volatile__("ldxa\t[%1] %2, %0\t/* upa_readq */"
-			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-
-	return ret;
-}
-
-static inline void _upa_writeb(unsigned char b, unsigned long addr)
-{
-	__asm__ __volatile__("stba\t%0, [%1] %2\t/* upa_writeb */"
-			     : /* no outputs */
-			     : "r" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-}
-
-static inline void _upa_writew(unsigned short w, unsigned long addr)
-{
-	__asm__ __volatile__("stha\t%0, [%1] %2\t/* upa_writew */"
-			     : /* no outputs */
-			     : "r" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-}
-
-static inline void _upa_writel(unsigned int l, unsigned long addr)
-{
-	__asm__ __volatile__("stwa\t%0, [%1] %2\t/* upa_writel */"
-			     : /* no outputs */
-			     : "r" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-}
-
-static inline void _upa_writeq(unsigned long q, unsigned long addr)
-{
-	__asm__ __volatile__("stxa\t%0, [%1] %2\t/* upa_writeq */"
-			     : /* no outputs */
-			     : "r" (q), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
-}
-
-#define upa_readb(__addr)		(_upa_readb((unsigned long)(__addr)))
-#define upa_readw(__addr)		(_upa_readw((unsigned long)(__addr)))
-#define upa_readl(__addr)		(_upa_readl((unsigned long)(__addr)))
-#define upa_readq(__addr)		(_upa_readq((unsigned long)(__addr)))
-#define upa_writeb(__b, __addr)		(_upa_writeb((__b), (unsigned long)(__addr)))
-#define upa_writew(__w, __addr)		(_upa_writew((__w), (unsigned long)(__addr)))
-#define upa_writel(__l, __addr)		(_upa_writel((__l), (unsigned long)(__addr)))
-#define upa_writeq(__q, __addr)		(_upa_writeq((__q), (unsigned long)(__addr)))
-#endif /* __KERNEL__ && !__ASSEMBLY__ */
-
-#endif /* !(_SPARC64_UPA_H) */
+#include <asm-sparc/upa.h>
diff --git a/include/asm-sparc64/utrap.h b/include/asm-sparc64/utrap.h
index e49e5c4..b030a41 100644
--- a/include/asm-sparc64/utrap.h
+++ b/include/asm-sparc64/utrap.h
@@ -1,51 +1 @@
-/*
- * include/asm-sparc64/utrap.h
- *
- * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- */
-
-#ifndef __ASM_SPARC64_UTRAP_H
-#define __ASM_SPARC64_UTRAP_H
-
-#define UT_INSTRUCTION_EXCEPTION		1
-#define UT_INSTRUCTION_ERROR			2
-#define UT_INSTRUCTION_PROTECTION		3
-#define UT_ILLTRAP_INSTRUCTION			4
-#define UT_ILLEGAL_INSTRUCTION			5
-#define UT_PRIVILEGED_OPCODE			6
-#define UT_FP_DISABLED				7
-#define UT_FP_EXCEPTION_IEEE_754		8
-#define UT_FP_EXCEPTION_OTHER			9
-#define UT_TAG_OVERVIEW				10
-#define UT_DIVISION_BY_ZERO			11
-#define UT_DATA_EXCEPTION			12
-#define UT_DATA_ERROR				13
-#define UT_DATA_PROTECTION			14
-#define UT_MEM_ADDRESS_NOT_ALIGNED		15
-#define UT_PRIVILEGED_ACTION			16
-#define UT_ASYNC_DATA_ERROR			17
-#define UT_TRAP_INSTRUCTION_16			18
-#define UT_TRAP_INSTRUCTION_17			19
-#define UT_TRAP_INSTRUCTION_18			20
-#define UT_TRAP_INSTRUCTION_19			21
-#define UT_TRAP_INSTRUCTION_20			22
-#define UT_TRAP_INSTRUCTION_21			23
-#define UT_TRAP_INSTRUCTION_22			24
-#define UT_TRAP_INSTRUCTION_23			25
-#define UT_TRAP_INSTRUCTION_24			26
-#define UT_TRAP_INSTRUCTION_25			27
-#define UT_TRAP_INSTRUCTION_26			28
-#define UT_TRAP_INSTRUCTION_27			29
-#define UT_TRAP_INSTRUCTION_28			30
-#define UT_TRAP_INSTRUCTION_29			31
-#define UT_TRAP_INSTRUCTION_30			32
-#define UT_TRAP_INSTRUCTION_31			33
-
-#define	UTH_NOCHANGE				(-1)
-
-#ifndef __ASSEMBLY__ 
-typedef int utrap_entry_t;
-typedef void *utrap_handler_t;
-#endif /* __ASSEMBLY__ */
-
-#endif /* !(__ASM_SPARC64_PROCESSOR_H) */
+#include <asm-sparc/utrap.h>
diff --git a/include/asm-sparc64/vga.h b/include/asm-sparc64/vga.h
index c69d5b2..fbf4d58 100644
--- a/include/asm-sparc64/vga.h
+++ b/include/asm-sparc64/vga.h
@@ -1,33 +1 @@
-/*
- *	Access to VGA videoram
- *
- *	(c) 1998 Martin Mares <mj@ucw.cz>
- */
-
-#ifndef _LINUX_ASM_VGA_H_
-#define _LINUX_ASM_VGA_H_
-
-#include <asm/types.h>
-
-#define VT_BUF_HAVE_RW
-
-#undef scr_writew
-#undef scr_readw
-
-static inline void scr_writew(u16 val, u16 *addr)
-{
-	BUG_ON((long) addr >= 0);
-
-	*addr = val;
-}
-
-static inline u16 scr_readw(const u16 *addr)
-{
-	BUG_ON((long) addr >= 0);
-
-	return *addr;
-}
-
-#define VGA_MAP_MEM(x,s) (x)
-
-#endif
+#include <asm-sparc/vga.h>
diff --git a/include/asm-sparc64/vio.h b/include/asm-sparc64/vio.h
index d4de32f..299b26a 100644
--- a/include/asm-sparc64/vio.h
+++ b/include/asm-sparc64/vio.h
@@ -1,406 +1 @@
-#ifndef _SPARC64_VIO_H
-#define _SPARC64_VIO_H
-
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/mod_devicetable.h>
-#include <linux/timer.h>
-#include <linux/spinlock.h>
-#include <linux/completion.h>
-#include <linux/list.h>
-#include <linux/log2.h>
-
-#include <asm/ldc.h>
-#include <asm/mdesc.h>
-
-struct vio_msg_tag {
-	u8			type;
-#define VIO_TYPE_CTRL		0x01
-#define VIO_TYPE_DATA		0x02
-#define VIO_TYPE_ERR		0x04
-
-	u8			stype;
-#define VIO_SUBTYPE_INFO	0x01
-#define VIO_SUBTYPE_ACK		0x02
-#define VIO_SUBTYPE_NACK	0x04
-
-	u16			stype_env;
-#define VIO_VER_INFO		0x0001
-#define VIO_ATTR_INFO		0x0002
-#define VIO_DRING_REG		0x0003
-#define VIO_DRING_UNREG		0x0004
-#define VIO_RDX			0x0005
-#define VIO_PKT_DATA		0x0040
-#define VIO_DESC_DATA		0x0041
-#define VIO_DRING_DATA		0x0042
-#define VNET_MCAST_INFO		0x0101
-
-	u32		sid;
-};
-
-struct vio_rdx {
-	struct vio_msg_tag	tag;
-	u64			resv[6];
-};
-
-struct vio_ver_info {
-	struct vio_msg_tag	tag;
-	u16			major;
-	u16			minor;
-	u8			dev_class;
-#define VDEV_NETWORK		0x01
-#define VDEV_NETWORK_SWITCH	0x02
-#define VDEV_DISK		0x03
-#define VDEV_DISK_SERVER	0x04
-
-	u8			resv1[3];
-	u64			resv2[5];
-};
-
-struct vio_dring_register {
-	struct vio_msg_tag	tag;
-	u64			dring_ident;
-	u32			num_descr;
-	u32			descr_size;
-	u16			options;
-#define VIO_TX_DRING		0x0001
-#define VIO_RX_DRING		0x0002
-	u16			resv;
-	u32			num_cookies;
-	struct ldc_trans_cookie	cookies[0];
-};
-
-struct vio_dring_unregister {
-	struct vio_msg_tag	tag;
-	u64			dring_ident;
-	u64			resv[5];
-};
-
-/* Data transfer modes */
-#define VIO_PKT_MODE		0x01 /* Packet based transfer	*/
-#define VIO_DESC_MODE		0x02 /* In-band descriptors	*/
-#define VIO_DRING_MODE		0x03 /* Descriptor rings	*/
-
-struct vio_dring_data {
-	struct vio_msg_tag	tag;
-	u64			seq;
-	u64			dring_ident;
-	u32			start_idx;
-	u32			end_idx;
-	u8			state;
-#define VIO_DRING_ACTIVE	0x01
-#define VIO_DRING_STOPPED	0x02
-
-	u8			__pad1;
-	u16			__pad2;
-	u32			__pad3;
-	u64			__par4[2];
-};
-
-struct vio_dring_hdr {
-	u8			state;
-#define VIO_DESC_FREE		0x01
-#define VIO_DESC_READY		0x02
-#define VIO_DESC_ACCEPTED	0x03
-#define VIO_DESC_DONE		0x04
-	u8			ack;
-#define VIO_ACK_ENABLE		0x01
-#define VIO_ACK_DISABLE		0x00
-
-	u16			__pad1;
-	u32			__pad2;
-};
-
-/* VIO disk specific structures and defines */
-struct vio_disk_attr_info {
-	struct vio_msg_tag	tag;
-	u8			xfer_mode;
-	u8			vdisk_type;
-#define VD_DISK_TYPE_SLICE	0x01 /* Slice in block device	*/
-#define VD_DISK_TYPE_DISK	0x02 /* Entire block device	*/
-	u16			resv1;
-	u32			vdisk_block_size;
-	u64			operations;
-	u64			vdisk_size;
-	u64			max_xfer_size;
-	u64			resv2[2];
-};
-
-struct vio_disk_desc {
-	struct vio_dring_hdr	hdr;
-	u64			req_id;
-	u8			operation;
-#define VD_OP_BREAD		0x01 /* Block read			*/
-#define VD_OP_BWRITE		0x02 /* Block write			*/
-#define VD_OP_FLUSH		0x03 /* Flush disk contents		*/
-#define VD_OP_GET_WCE		0x04 /* Get write-cache status		*/
-#define VD_OP_SET_WCE		0x05 /* Enable/disable write-cache	*/
-#define VD_OP_GET_VTOC		0x06 /* Get VTOC			*/
-#define VD_OP_SET_VTOC		0x07 /* Set VTOC			*/
-#define VD_OP_GET_DISKGEOM	0x08 /* Get disk geometry		*/
-#define VD_OP_SET_DISKGEOM	0x09 /* Set disk geometry		*/
-#define VD_OP_SCSICMD		0x0a /* SCSI control command		*/
-#define VD_OP_GET_DEVID		0x0b /* Get device ID			*/
-#define VD_OP_GET_EFI		0x0c /* Get EFI				*/
-#define VD_OP_SET_EFI		0x0d /* Set EFI				*/
-	u8			slice;
-	u16			resv1;
-	u32			status;
-	u64			offset;
-	u64			size;
-	u32			ncookies;
-	u32			resv2;
-	struct ldc_trans_cookie	cookies[0];
-};
-
-#define VIO_DISK_VNAME_LEN	8
-#define VIO_DISK_ALABEL_LEN	128
-#define VIO_DISK_NUM_PART	8
-
-struct vio_disk_vtoc {
-	u8			volume_name[VIO_DISK_VNAME_LEN];
-	u16			sector_size;
-	u16			num_partitions;
-	u8			ascii_label[VIO_DISK_ALABEL_LEN];
-	struct {
-		u16		id;
-		u16		perm_flags;
-		u32		resv;
-		u64		start_block;
-		u64		num_blocks;
-	} partitions[VIO_DISK_NUM_PART];
-};
-
-struct vio_disk_geom {
-	u16			num_cyl; /* Num data cylinders		*/
-	u16			alt_cyl; /* Num alternate cylinders	*/
-	u16			beg_cyl; /* Cyl off of fixed head area	*/
-	u16			num_hd;  /* Num heads			*/
-	u16			num_sec; /* Num sectors			*/
-	u16			ifact;   /* Interleave factor		*/
-	u16			apc;     /* Alts per cylinder (SCSI)	*/
-	u16			rpm;	 /* Revolutions per minute	*/
-	u16			phy_cyl; /* Num physical cylinders	*/
-	u16			wr_skip; /* Num sects to skip, writes	*/
-	u16			rd_skip; /* Num sects to skip, writes	*/
-};
-
-struct vio_disk_devid {
-	u16			resv;
-	u16			type;
-	u32			len;
-	char			id[0];
-};
-
-struct vio_disk_efi {
-	u64			lba;
-	u64			len;
-	char			data[0];
-};
-
-/* VIO net specific structures and defines */
-struct vio_net_attr_info {
-	struct vio_msg_tag	tag;
-	u8			xfer_mode;
-	u8			addr_type;
-#define VNET_ADDR_ETHERMAC	0x01
-	u16			ack_freq;
-	u32			resv1;
-	u64			addr;
-	u64			mtu;
-	u64			resv2[3];
-};
-
-#define VNET_NUM_MCAST		7
-
-struct vio_net_mcast_info {
-	struct vio_msg_tag	tag;
-	u8			set;
-	u8			count;
-	u8			mcast_addr[VNET_NUM_MCAST * 6];
-	u32			resv;
-};
-
-struct vio_net_desc {
-	struct vio_dring_hdr	hdr;
-	u32			size;
-	u32			ncookies;
-	struct ldc_trans_cookie	cookies[0];
-};
-
-#define VIO_MAX_RING_COOKIES	24
-
-struct vio_dring_state {
-	u64			ident;
-	void			*base;
-	u64			snd_nxt;
-	u64			rcv_nxt;
-	u32			entry_size;
-	u32			num_entries;
-	u32			prod;
-	u32			cons;
-	u32			pending;
-	int			ncookies;
-	struct ldc_trans_cookie	cookies[VIO_MAX_RING_COOKIES];
-};
-
-static inline void *vio_dring_cur(struct vio_dring_state *dr)
-{
-	return dr->base + (dr->entry_size * dr->prod);
-}
-
-static inline void *vio_dring_entry(struct vio_dring_state *dr,
-				    unsigned int index)
-{
-	return dr->base + (dr->entry_size * index);
-}
-
-static inline u32 vio_dring_avail(struct vio_dring_state *dr,
-				  unsigned int ring_size)
-{
-	BUILD_BUG_ON(!is_power_of_2(ring_size));
-
-	return (dr->pending -
-		((dr->prod - dr->cons) & (ring_size - 1)));
-}
-
-#define VIO_MAX_TYPE_LEN	32
-#define VIO_MAX_COMPAT_LEN	64
-
-struct vio_dev {
-	u64			mp;
-	struct device_node	*dp;
-
-	char			type[VIO_MAX_TYPE_LEN];
-	char			compat[VIO_MAX_COMPAT_LEN];
-	int			compat_len;
-
-	u64			dev_no;
-
-	unsigned long		channel_id;
-
-	unsigned int		tx_irq;
-	unsigned int		rx_irq;
-
-	struct device		dev;
-};
-
-struct vio_driver {
-	struct list_head		node;
-	const struct vio_device_id	*id_table;
-	int (*probe)(struct vio_dev *dev, const struct vio_device_id *id);
-	int (*remove)(struct vio_dev *dev);
-	void (*shutdown)(struct vio_dev *dev);
-	unsigned long			driver_data;
-	struct device_driver		driver;
-};
-
-struct vio_version {
-	u16		major;
-	u16		minor;
-};
-
-struct vio_driver_state;
-struct vio_driver_ops {
-	int	(*send_attr)(struct vio_driver_state *vio);
-	int	(*handle_attr)(struct vio_driver_state *vio, void *pkt);
-	void	(*handshake_complete)(struct vio_driver_state *vio);
-};
-
-struct vio_completion {
-	struct completion	com;
-	int			err;
-	int			waiting_for;
-};
-
-struct vio_driver_state {
-	/* Protects VIO handshake and, optionally, driver private state.  */
-	spinlock_t		lock;
-
-	struct ldc_channel	*lp;
-
-	u32			_peer_sid;
-	u32			_local_sid;
-	struct vio_dring_state	drings[2];
-#define VIO_DRIVER_TX_RING	0
-#define VIO_DRIVER_RX_RING	1
-
-	u8			hs_state;
-#define VIO_HS_INVALID		0x00
-#define VIO_HS_GOTVERS		0x01
-#define VIO_HS_GOT_ATTR		0x04
-#define VIO_HS_SENT_DREG	0x08
-#define VIO_HS_SENT_RDX		0x10
-#define VIO_HS_GOT_RDX_ACK	0x20
-#define VIO_HS_GOT_RDX		0x40
-#define VIO_HS_SENT_RDX_ACK	0x80
-#define VIO_HS_COMPLETE		(VIO_HS_GOT_RDX_ACK | VIO_HS_SENT_RDX_ACK)
-
-	u8			dev_class;
-
-	u8			dr_state;
-#define VIO_DR_STATE_TXREG	0x01
-#define VIO_DR_STATE_RXREG	0x02
-#define VIO_DR_STATE_TXREQ	0x10
-#define VIO_DR_STATE_RXREQ	0x20
-
-	u8			debug;
-#define VIO_DEBUG_HS		0x01
-#define VIO_DEBUG_DATA		0x02
-
-	void			*desc_buf;
-	unsigned int		desc_buf_len;
-
-	struct vio_completion	*cmp;
-
-	struct vio_dev		*vdev;
-
-	struct timer_list	timer;
-
-	struct vio_version	ver;
-
-	struct vio_version	*ver_table;
-	int			ver_table_entries;
-
-	char			*name;
-
-	struct vio_driver_ops	*ops;
-};
-
-#define viodbg(TYPE, f, a...) \
-do {	if (vio->debug & VIO_DEBUG_##TYPE) \
-		printk(KERN_INFO "vio: ID[%lu] " f, \
-		       vio->vdev->channel_id, ## a); \
-} while (0)
-
-extern int vio_register_driver(struct vio_driver *drv);
-extern void vio_unregister_driver(struct vio_driver *drv);
-
-static inline struct vio_driver *to_vio_driver(struct device_driver *drv)
-{
-	return container_of(drv, struct vio_driver, driver);
-}
-
-static inline struct vio_dev *to_vio_dev(struct device *dev)
-{
-	return container_of(dev, struct vio_dev, dev);
-}
-
-extern int vio_ldc_send(struct vio_driver_state *vio, void *data, int len);
-extern void vio_link_state_change(struct vio_driver_state *vio, int event);
-extern void vio_conn_reset(struct vio_driver_state *vio);
-extern int vio_control_pkt_engine(struct vio_driver_state *vio, void *pkt);
-extern int vio_validate_sid(struct vio_driver_state *vio,
-			    struct vio_msg_tag *tp);
-extern u32 vio_send_sid(struct vio_driver_state *vio);
-extern int vio_ldc_alloc(struct vio_driver_state *vio,
-			 struct ldc_channel_config *base_cfg, void *event_arg);
-extern void vio_ldc_free(struct vio_driver_state *vio);
-extern int vio_driver_init(struct vio_driver_state *vio, struct vio_dev *vdev,
-			   u8 dev_class, struct vio_version *ver_table,
-			   int ver_table_size, struct vio_driver_ops *ops,
-			   char *name);
-
-extern void vio_port_up(struct vio_driver_state *vio);
-
-#endif /* _SPARC64_VIO_H */
+#include <asm-sparc/vio.h>
diff --git a/include/asm-sparc64/visasm.h b/include/asm-sparc64/visasm.h
index 34f2ec64..837a122 100644
--- a/include/asm-sparc64/visasm.h
+++ b/include/asm-sparc64/visasm.h
@@ -1,62 +1 @@
-#ifndef _SPARC64_VISASM_H
-#define _SPARC64_VISASM_H
-
-/* visasm.h:  FPU saving macros for VIS routines
- *
- * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
- */
- 
-#include <asm/pstate.h>
-#include <asm/ptrace.h>
-
-/* Clobbers %o5, %g1, %g2, %g3, %g7, %icc, %xcc */
-
-#define VISEntry					\
-	rd		%fprs, %o5;			\
-	andcc		%o5, (FPRS_FEF|FPRS_DU), %g0;	\
-	be,pt		%icc, 297f;			\
-	 sethi		%hi(297f), %g7;			\
-	sethi		%hi(VISenter), %g1;		\
-	jmpl		%g1 + %lo(VISenter), %g0;	\
-	 or		%g7, %lo(297f), %g7;		\
-297:	wr		%g0, FPRS_FEF, %fprs;		\
-
-#define VISExit						\
-	wr		%g0, 0, %fprs;
-
-/* Clobbers %o5, %g1, %g2, %g3, %g7, %icc, %xcc.
- * Must preserve %o5 between VISEntryHalf and VISExitHalf */
-
-#define VISEntryHalf					\
-	rd		%fprs, %o5;			\
-	andcc		%o5, FPRS_FEF, %g0;		\
-	be,pt		%icc, 297f;			\
-	 sethi		%hi(298f), %g7;			\
-	sethi		%hi(VISenterhalf), %g1;		\
-	jmpl		%g1 + %lo(VISenterhalf), %g0;	\
-	 or		%g7, %lo(298f), %g7;		\
-	clr		%o5;				\
-297:	wr		%o5, FPRS_FEF, %fprs;		\
-298:
-
-#define VISExitHalf					\
-	wr		%o5, 0, %fprs;
-
-#ifndef __ASSEMBLY__	
-static inline void save_and_clear_fpu(void) {
-	__asm__ __volatile__ (
-"		rd %%fprs, %%o5\n"
-"		andcc %%o5, %0, %%g0\n"
-"		be,pt %%icc, 299f\n"
-"		 sethi %%hi(298f), %%g7\n"
-"		sethi %%hi(VISenter), %%g1\n"
-"		jmpl %%g1 + %%lo(VISenter), %%g0\n"
-"		 or %%g7, %%lo(298f), %%g7\n"
-"	298:	wr %%g0, 0, %%fprs\n"
-"	299:\n"
-"		" : : "i" (FPRS_FEF|FPRS_DU) :
-		"o5", "g1", "g2", "g3", "g7", "cc");
-}
-#endif
-
-#endif /* _SPARC64_ASI_H */
+#include <asm-sparc/visasm.h>
diff --git a/include/asm-sparc64/watchdog.h b/include/asm-sparc64/watchdog.h
index 5baf2d3..b0f2857 100644
--- a/include/asm-sparc64/watchdog.h
+++ b/include/asm-sparc64/watchdog.h
@@ -1,31 +1 @@
-/*
- *
- * watchdog - Driver interface for the hardware watchdog timers
- * present on Sun Microsystems boardsets
- *
- * Copyright (c) 2000 Eric Brower <ebrower@usa.net>
- *
- */
-
-#ifndef _SPARC64_WATCHDOG_H
-#define _SPARC64_WATCHDOG_H
-
-#include <linux/watchdog.h>
-
-/* Solaris compatibility ioctls--
- * Ref. <linux/watchdog.h> for standard linux watchdog ioctls
- */
-#define WIOCSTART _IO (WATCHDOG_IOCTL_BASE, 10)		/* Start Timer		*/
-#define WIOCSTOP  _IO (WATCHDOG_IOCTL_BASE, 11)		/* Stop Timer		*/
-#define WIOCGSTAT _IOR(WATCHDOG_IOCTL_BASE, 12, int)/* Get Timer Status	*/
-
-/* Status flags from WIOCGSTAT ioctl
- */
-#define WD_FREERUN	0x01	/* timer is running, interrupts disabled	*/
-#define WD_EXPIRED	0x02	/* timer has expired						*/
-#define WD_RUNNING	0x04	/* timer is running, interrupts enabled		*/
-#define WD_STOPPED	0x08	/* timer has not been started				*/
-#define WD_SERVICED 0x10	/* timer interrupt was serviced				*/
-
-#endif /* ifndef _SPARC64_WATCHDOG_H */
-
+#include <asm-sparc/watchdog.h>
diff --git a/include/asm-sparc64/xor.h b/include/asm-sparc64/xor.h
index a023388..ef187cc 100644
--- a/include/asm-sparc64/xor.h
+++ b/include/asm-sparc64/xor.h
@@ -1,70 +1 @@
-/*
- * include/asm-sparc64/xor.h
- *
- * High speed xor_block operation for RAID4/5 utilizing the
- * UltraSparc Visual Instruction Set and Niagara block-init
- * twin-load instructions.
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 2006 David S. Miller <davem@davemloft.net>
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * (for example /usr/src/linux/COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <asm/spitfire.h>
-
-extern void xor_vis_2(unsigned long, unsigned long *, unsigned long *);
-extern void xor_vis_3(unsigned long, unsigned long *, unsigned long *,
-		      unsigned long *);
-extern void xor_vis_4(unsigned long, unsigned long *, unsigned long *,
-		      unsigned long *, unsigned long *);
-extern void xor_vis_5(unsigned long, unsigned long *, unsigned long *,
-		      unsigned long *, unsigned long *, unsigned long *);
-
-/* XXX Ugh, write cheetah versions... -DaveM */
-
-static struct xor_block_template xor_block_VIS = {
-        .name	= "VIS",
-        .do_2	= xor_vis_2,
-        .do_3	= xor_vis_3,
-        .do_4	= xor_vis_4,
-        .do_5	= xor_vis_5,
-};
-
-extern void xor_niagara_2(unsigned long, unsigned long *, unsigned long *);
-extern void xor_niagara_3(unsigned long, unsigned long *, unsigned long *,
-			  unsigned long *);
-extern void xor_niagara_4(unsigned long, unsigned long *, unsigned long *,
-			  unsigned long *, unsigned long *);
-extern void xor_niagara_5(unsigned long, unsigned long *, unsigned long *,
-			  unsigned long *, unsigned long *, unsigned long *);
-
-static struct xor_block_template xor_block_niagara = {
-        .name	= "Niagara",
-        .do_2	= xor_niagara_2,
-        .do_3	= xor_niagara_3,
-        .do_4	= xor_niagara_4,
-        .do_5	= xor_niagara_5,
-};
-
-#undef XOR_TRY_TEMPLATES
-#define XOR_TRY_TEMPLATES				\
-	do {						\
-		xor_speed(&xor_block_VIS);		\
-		xor_speed(&xor_block_niagara);		\
-	} while (0)
-
-/* For VIS for everything except Niagara.  */
-#define XOR_SELECT_TEMPLATE(FASTEST) \
-	((tlb_type == hypervisor && \
-	  (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 || \
-	   sun4v_chip_type == SUN4V_CHIP_NIAGARA2)) ? \
-	 &xor_block_niagara : \
-	 &xor_block_VIS)
+#include <asm-sparc/xor.h>
diff --git a/include/asm-x86/amd_iommu_types.h b/include/asm-x86/amd_iommu_types.h
index 7bfcb47..22aa58c 100644
--- a/include/asm-x86/amd_iommu_types.h
+++ b/include/asm-x86/amd_iommu_types.h
@@ -27,13 +27,12 @@
 /*
  * some size calculation constants
  */
-#define DEV_TABLE_ENTRY_SIZE		256
+#define DEV_TABLE_ENTRY_SIZE		32
 #define ALIAS_TABLE_ENTRY_SIZE		2
 #define RLOOKUP_TABLE_ENTRY_SIZE	(sizeof(void *))
 
 /* helper macros */
 #define LOW_U32(x) ((x) & ((1ULL << 32)-1))
-#define HIGH_U32(x) (LOW_U32((x) >> 32))
 
 /* Length of the MMIO region for the AMD IOMMU */
 #define MMIO_REGION_LENGTH       0x4000
@@ -158,78 +157,170 @@
 
 #define MAX_DOMAIN_ID 65536
 
+/*
+ * This structure contains generic data for  IOMMU protection domains
+ * independent of their use.
+ */
 struct protection_domain {
-	spinlock_t lock;
-	u16 id;
-	int mode;
-	u64 *pt_root;
-	void *priv;
+	spinlock_t lock; /* mostly used to lock the page table*/
+	u16 id;		 /* the domain id written to the device table */
+	int mode;	 /* paging mode (0-6 levels) */
+	u64 *pt_root;	 /* page table root pointer */
+	void *priv;	 /* private data */
 };
 
+/*
+ * Data container for a dma_ops specific protection domain
+ */
 struct dma_ops_domain {
 	struct list_head list;
+
+	/* generic protection domain information */
 	struct protection_domain domain;
+
+	/* size of the aperture for the mappings */
 	unsigned long aperture_size;
+
+	/* address we start to search for free addresses */
 	unsigned long next_bit;
+
+	/* address allocation bitmap */
 	unsigned long *bitmap;
+
+	/*
+	 * Array of PTE pages for the aperture. In this array we save all the
+	 * leaf pages of the domain page table used for the aperture. This way
+	 * we don't need to walk the page table to find a specific PTE. We can
+	 * just calculate its address in constant time.
+	 */
 	u64 **pte_pages;
 };
 
+/*
+ * Structure where we save information about one hardware AMD IOMMU in the
+ * system.
+ */
 struct amd_iommu {
 	struct list_head list;
+
+	/* locks the accesses to the hardware */
 	spinlock_t lock;
 
+	/* device id of this IOMMU */
 	u16 devid;
+	/*
+	 * Capability pointer. There could be more than one IOMMU per PCI
+	 * device function if there are more than one AMD IOMMU capability
+	 * pointers.
+	 */
 	u16 cap_ptr;
 
+	/* physical address of MMIO space */
 	u64 mmio_phys;
+	/* virtual address of MMIO space */
 	u8 *mmio_base;
+
+	/* capabilities of that IOMMU read from ACPI */
 	u32 cap;
+
+	/* first device this IOMMU handles. read from PCI */
 	u16 first_device;
+	/* last device this IOMMU handles. read from PCI */
 	u16 last_device;
+
+	/* start of exclusion range of that IOMMU */
 	u64 exclusion_start;
+	/* length of exclusion range of that IOMMU */
 	u64 exclusion_length;
 
+	/* command buffer virtual address */
 	u8 *cmd_buf;
+	/* size of command buffer */
 	u32 cmd_buf_size;
 
+	/* if one, we need to send a completion wait command */
 	int need_sync;
 
+	/* default dma_ops domain for that IOMMU */
 	struct dma_ops_domain *default_dom;
 };
 
+/*
+ * List with all IOMMUs in the system. This list is not locked because it is
+ * only written and read at driver initialization or suspend time
+ */
 extern struct list_head amd_iommu_list;
 
+/*
+ * Structure defining one entry in the device table
+ */
 struct dev_table_entry {
 	u32 data[8];
 };
 
+/*
+ * One entry for unity mappings parsed out of the ACPI table.
+ */
 struct unity_map_entry {
 	struct list_head list;
+
+	/* starting device id this entry is used for (including) */
 	u16 devid_start;
+	/* end device id this entry is used for (including) */
 	u16 devid_end;
+
+	/* start address to unity map (including) */
 	u64 address_start;
+	/* end address to unity map (including) */
 	u64 address_end;
+
+	/* required protection */
 	int prot;
 };
 
+/*
+ * List of all unity mappings. It is not locked because as runtime it is only
+ * read. It is created at ACPI table parsing time.
+ */
 extern struct list_head amd_iommu_unity_map;
 
-/* data structures for device handling */
+/*
+ * Data structures for device handling
+ */
+
+/*
+ * Device table used by hardware. Read and write accesses by software are
+ * locked with the amd_iommu_pd_table lock.
+ */
 extern struct dev_table_entry *amd_iommu_dev_table;
+
+/*
+ * Alias table to find requestor ids to device ids. Not locked because only
+ * read on runtime.
+ */
 extern u16 *amd_iommu_alias_table;
+
+/*
+ * Reverse lookup table to find the IOMMU which translates a specific device.
+ */
 extern struct amd_iommu **amd_iommu_rlookup_table;
 
+/* size of the dma_ops aperture as power of 2 */
 extern unsigned amd_iommu_aperture_order;
 
+/* largest PCI device id we expect translation requests for */
 extern u16 amd_iommu_last_bdf;
 
 /* data structures for protection domain handling */
 extern struct protection_domain **amd_iommu_pd_table;
+
+/* allocation bitmap for domain ids */
 extern unsigned long *amd_iommu_pd_alloc_bitmap;
 
+/* will be 1 if device isolation is enabled */
 extern int amd_iommu_isolate;
 
+/* takes a PCI device id and prints it out in a readable form */
 static inline void print_devid(u16 devid, int nl)
 {
 	int bus = devid >> 8;
@@ -241,4 +332,11 @@
 		printk("\n");
 }
 
+/* takes bus and device/function and returns the device id
+ * FIXME: should that be in generic PCI code? */
+static inline u16 calc_devid(u8 bus, u8 devfn)
+{
+	return (((u16)bus) << 8) | devfn;
+}
+
 #endif
diff --git a/include/asm-x86/apic.h b/include/asm-x86/apic.h
index 4e2c1e5..133c998 100644
--- a/include/asm-x86/apic.h
+++ b/include/asm-x86/apic.h
@@ -3,6 +3,8 @@
 
 #include <linux/pm.h>
 #include <linux/delay.h>
+
+#include <asm/alternative.h>
 #include <asm/fixmap.h>
 #include <asm/apicdef.h>
 #include <asm/processor.h>
@@ -10,8 +12,6 @@
 
 #define ARCH_APICTIMER_STOPS_ON_C3	1
 
-#define Dprintk(x...)
-
 /*
  * Debugging macros
  */
@@ -35,7 +35,7 @@
 
 #ifdef CONFIG_X86_LOCAL_APIC
 
-extern int apic_verbosity;
+extern unsigned int apic_verbosity;
 extern int local_apic_timer_c2_ok;
 
 extern int ioapic_force;
@@ -48,7 +48,6 @@
 #include <asm/paravirt.h>
 #else
 #define apic_write native_apic_write
-#define apic_write_atomic native_apic_write_atomic
 #define apic_read native_apic_read
 #define setup_boot_clock setup_boot_APIC_clock
 #define setup_secondary_clock setup_secondary_APIC_clock
@@ -58,12 +57,11 @@
 
 static inline void native_apic_write(unsigned long reg, u32 v)
 {
-	*((volatile u32 *)(APIC_BASE + reg)) = v;
-}
+	volatile u32 *addr = (volatile u32 *)(APIC_BASE + reg);
 
-static inline void native_apic_write_atomic(unsigned long reg, u32 v)
-{
-	(void)xchg((u32 *)(APIC_BASE + reg), v);
+	alternative_io("movl %0, %1", "xchgl %0, %1", X86_FEATURE_11AP,
+		       ASM_OUTPUT2("=r" (v), "=m" (*addr)),
+		       ASM_OUTPUT2("0" (v), "m" (*addr)));
 }
 
 static inline u32 native_apic_read(unsigned long reg)
@@ -75,16 +73,6 @@
 extern u32 safe_apic_wait_icr_idle(void);
 extern int get_physical_broadcast(void);
 
-#ifdef CONFIG_X86_GOOD_APIC
-# define FORCE_READ_AROUND_WRITE 0
-# define apic_read_around(x)
-# define apic_write_around(x, y) apic_write((x), (y))
-#else
-# define FORCE_READ_AROUND_WRITE 1
-# define apic_read_around(x) apic_read(x)
-# define apic_write_around(x, y) apic_write_atomic((x), (y))
-#endif
-
 static inline void ack_APIC_irq(void)
 {
 	/*
@@ -95,7 +83,7 @@
 	 */
 
 	/* Docs say use 0 for future compatibility */
-	apic_write_around(APIC_EOI, 0);
+	apic_write(APIC_EOI, 0);
 }
 
 extern int lapic_get_maxlvt(void);
diff --git a/include/asm-x86/arch_hooks.h b/include/asm-x86/arch_hooks.h
index 768aee8..8411750 100644
--- a/include/asm-x86/arch_hooks.h
+++ b/include/asm-x86/arch_hooks.h
@@ -21,6 +21,7 @@
 extern void pre_intr_init_hook(void);
 extern void pre_setup_arch_hook(void);
 extern void trap_init_hook(void);
+extern void pre_time_init_hook(void);
 extern void time_init_hook(void);
 extern void mca_nmi_hook(void);
 
diff --git a/include/asm-x86/bitops.h b/include/asm-x86/bitops.h
index 96b1829..cfb2b64 100644
--- a/include/asm-x86/bitops.h
+++ b/include/asm-x86/bitops.h
@@ -356,7 +356,7 @@
  * __fls: find last set bit in word
  * @word: The word to search
  *
- * Undefined if no zero exists, so code should check against ~0UL first.
+ * Undefined if no set bit exists, so code should check against 0 first.
  */
 static inline unsigned long __fls(unsigned long word)
 {
diff --git a/include/asm-x86/calling.h b/include/asm-x86/calling.h
index f13e62e..2bc162e 100644
--- a/include/asm-x86/calling.h
+++ b/include/asm-x86/calling.h
@@ -104,7 +104,7 @@
 	.endif
 	.endm
 
-	.macro LOAD_ARGS offset
+	.macro LOAD_ARGS offset, skiprax=0
 	movq \offset(%rsp),    %r11
 	movq \offset+8(%rsp),  %r10
 	movq \offset+16(%rsp), %r9
@@ -113,7 +113,10 @@
 	movq \offset+48(%rsp), %rdx
 	movq \offset+56(%rsp), %rsi
 	movq \offset+64(%rsp), %rdi
+	.if \skiprax
+	.else
 	movq \offset+72(%rsp), %rax
+	.endif
 	.endm
 
 #define REST_SKIP	6*8
@@ -165,4 +168,3 @@
 	.macro icebp
 	.byte 0xf1
 	.endm
-
diff --git a/include/asm-x86/cpufeature.h b/include/asm-x86/cpufeature.h
index 75ef959..2f5a792 100644
--- a/include/asm-x86/cpufeature.h
+++ b/include/asm-x86/cpufeature.h
@@ -79,6 +79,7 @@
 #define X86_FEATURE_REP_GOOD	(3*32+16) /* rep microcode works well on this CPU */
 #define X86_FEATURE_MFENCE_RDTSC (3*32+17) /* Mfence synchronizes RDTSC */
 #define X86_FEATURE_LFENCE_RDTSC (3*32+18) /* Lfence synchronizes RDTSC */
+#define X86_FEATURE_11AP	(3*32+19)  /* Bad local APIC aka 11AP */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
 #define X86_FEATURE_XMM3	(4*32+ 0) /* Streaming SIMD Extensions-3 */
diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h
index a1a4dc7..c2ddd3d 100644
--- a/include/asm-x86/dma-mapping.h
+++ b/include/asm-x86/dma-mapping.h
@@ -14,7 +14,6 @@
 extern int iommu_merge;
 extern struct device fallback_dev;
 extern int panic_on_overflow;
-extern int forbid_dac;
 extern int force_iommu;
 
 struct dma_mapping_ops {
diff --git a/include/asm-x86/e820.h b/include/asm-x86/e820.h
index 06633b0..16a31e2 100644
--- a/include/asm-x86/e820.h
+++ b/include/asm-x86/e820.h
@@ -90,6 +90,14 @@
 }
 #endif
 
+#ifdef CONFIG_MEMTEST
+extern void early_memtest(unsigned long start, unsigned long end);
+#else
+static inline void early_memtest(unsigned long start, unsigned long end)
+{
+}
+#endif
+
 extern unsigned long end_user_pfn;
 
 extern u64 find_e820_area(u64 start, u64 end, u64 size, u64 align);
diff --git a/include/asm-x86/fixmap_32.h b/include/asm-x86/fixmap_32.h
index aae2f05..f1ac2b2 100644
--- a/include/asm-x86/fixmap_32.h
+++ b/include/asm-x86/fixmap_32.h
@@ -90,13 +90,13 @@
 	 * 256 temporary boot-time mappings, used by early_ioremap(),
 	 * before ioremap() is functional.
 	 *
-	 * We round it up to the next 512 pages boundary so that we
+	 * We round it up to the next 256 pages boundary so that we
 	 * can have a single pgd entry and a single pte table:
 	 */
 #define NR_FIX_BTMAPS		64
 #define FIX_BTMAPS_NESTING	4
-	FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 512 -
-			(__end_of_permanent_fixed_addresses & 511),
+	FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 -
+			(__end_of_permanent_fixed_addresses & 255),
 	FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_NESTING - 1,
 	FIX_WP_TEST,
 #ifdef CONFIG_ACPI
diff --git a/include/asm-x86/ftrace.h b/include/asm-x86/ftrace.h
index c184441..5c68b32 100644
--- a/include/asm-x86/ftrace.h
+++ b/include/asm-x86/ftrace.h
@@ -1,5 +1,5 @@
 #ifndef _ASM_X86_FTRACE
-#define _ASM_SPARC64_FTRACE
+#define _ASM_X86_FTRACE
 
 #ifdef CONFIG_FTRACE
 #define MCOUNT_ADDR		((long)(mcount))
diff --git a/include/asm-x86/gart.h b/include/asm-x86/gart.h
index 33b9aee..3f62a83 100644
--- a/include/asm-x86/gart.h
+++ b/include/asm-x86/gart.h
@@ -2,7 +2,6 @@
 #define _ASM_X8664_GART_H 1
 
 #include <asm/e820.h>
-#include <asm/iommu.h>
 
 extern void set_up_gart_resume(u32, u32);
 
diff --git a/include/asm-x86/iommu.h b/include/asm-x86/iommu.h
index 068c9a4..d63166f 100644
--- a/include/asm-x86/iommu.h
+++ b/include/asm-x86/iommu.h
@@ -25,10 +25,18 @@
 static inline void early_gart_iommu_check(void)
 {
 }
-
+static inline void gart_iommu_init(void)
+{
+}
 static inline void gart_iommu_shutdown(void)
 {
 }
+static inline void gart_parse_options(char *options)
+{
+}
+static inline void gart_iommu_hole_init(void)
+{
+}
 #endif
 
 #endif
diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h
index f995783..fdde0be 100644
--- a/include/asm-x86/kvm_host.h
+++ b/include/asm-x86/kvm_host.h
@@ -703,9 +703,11 @@
 						vcpu, 0, 0, 0, 0, 0, 0)
 
 #ifdef CONFIG_64BIT
-#define KVM_EX_ENTRY ".quad"
+# define KVM_EX_ENTRY ".quad"
+# define KVM_EX_PUSH "pushq"
 #else
-#define KVM_EX_ENTRY ".long"
+# define KVM_EX_ENTRY ".long"
+# define KVM_EX_PUSH "pushl"
 #endif
 
 /*
@@ -719,7 +721,7 @@
 	"666: " insn "\n\t" \
 	".pushsection .text.fixup, \"ax\" \n" \
 	"667: \n\t" \
-	"push $666b \n\t" \
+	KVM_EX_PUSH " $666b \n\t" \
 	"jmp kvm_handle_fault_on_reboot \n\t" \
 	".popsection \n\t" \
 	".pushsection __ex_table, \"a\" \n\t" \
diff --git a/include/asm-x86/mach-bigsmp/mach_apic.h b/include/asm-x86/mach-bigsmp/mach_apic.h
index 017c8c1..c3b9dc6 100644
--- a/include/asm-x86/mach-bigsmp/mach_apic.h
+++ b/include/asm-x86/mach-bigsmp/mach_apic.h
@@ -63,9 +63,9 @@
 	unsigned long val;
 	int cpu = smp_processor_id();
 
-	apic_write_around(APIC_DFR, APIC_DFR_VALUE);
+	apic_write(APIC_DFR, APIC_DFR_VALUE);
 	val = calculate_ldr(cpu);
-	apic_write_around(APIC_LDR, val);
+	apic_write(APIC_LDR, val);
 }
 
 static inline void setup_apic_routing(void)
diff --git a/include/asm-x86/mach-default/mach_apic.h b/include/asm-x86/mach-default/mach_apic.h
index 0b2cde5..f3226b9 100644
--- a/include/asm-x86/mach-default/mach_apic.h
+++ b/include/asm-x86/mach-default/mach_apic.h
@@ -46,10 +46,10 @@
 {
 	unsigned long val;
 
-	apic_write_around(APIC_DFR, APIC_DFR_VALUE);
+	apic_write(APIC_DFR, APIC_DFR_VALUE);
 	val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
 	val |= SET_APIC_LOGICAL_ID(1UL << smp_processor_id());
-	apic_write_around(APIC_LDR, val);
+	apic_write(APIC_LDR, val);
 }
 
 static inline int apic_id_registered(void)
diff --git a/include/asm-x86/mach-default/smpboot_hooks.h b/include/asm-x86/mach-default/smpboot_hooks.h
index 56d001b..dbab36d 100644
--- a/include/asm-x86/mach-default/smpboot_hooks.h
+++ b/include/asm-x86/mach-default/smpboot_hooks.h
@@ -12,11 +12,11 @@
 {
 	CMOS_WRITE(0xa, 0xf);
 	local_flush_tlb();
-	Dprintk("1.\n");
+	pr_debug("1.\n");
 	*((volatile unsigned short *) TRAMPOLINE_HIGH) = start_eip >> 4;
-	Dprintk("2.\n");
+	pr_debug("2.\n");
 	*((volatile unsigned short *) TRAMPOLINE_LOW) = start_eip & 0xf;
-	Dprintk("3.\n");
+	pr_debug("3.\n");
 }
 
 static inline void smpboot_restore_warm_reset_vector(void)
diff --git a/include/asm-x86/mach-es7000/mach_apic.h b/include/asm-x86/mach-es7000/mach_apic.h
index fbc8ad2..0a3fdf9 100644
--- a/include/asm-x86/mach-es7000/mach_apic.h
+++ b/include/asm-x86/mach-es7000/mach_apic.h
@@ -66,9 +66,9 @@
 	unsigned long val;
 	int cpu = smp_processor_id();
 
-	apic_write_around(APIC_DFR, APIC_DFR_VALUE);
+	apic_write(APIC_DFR, APIC_DFR_VALUE);
 	val = calculate_ldr(cpu);
-	apic_write_around(APIC_LDR, val);
+	apic_write(APIC_LDR, val);
 }
 
 #ifndef CONFIG_X86_GENERICARCH
diff --git a/include/asm-x86/mach-generic/mach_mpspec.h b/include/asm-x86/mach-generic/mach_mpspec.h
index 9ef0b94..c83c120 100644
--- a/include/asm-x86/mach-generic/mach_mpspec.h
+++ b/include/asm-x86/mach-generic/mach_mpspec.h
@@ -7,4 +7,6 @@
 /* Maximum 256 PCI busses, plus 1 ISA bus in each of 4 cabinets. */
 #define MAX_MP_BUSSES 260
 
+extern void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem,
+				char *productid);
 #endif /* __ASM_MACH_MPSPEC_H */
diff --git a/include/asm-x86/mach-summit/mach_apic.h b/include/asm-x86/mach-summit/mach_apic.h
index 1f76c2e7..75d2c950 100644
--- a/include/asm-x86/mach-summit/mach_apic.h
+++ b/include/asm-x86/mach-summit/mach_apic.h
@@ -63,10 +63,10 @@
 	 * BIOS puts 5 CPUs in one APIC cluster, we're hosed. */
 	BUG_ON(count >= XAPIC_DEST_CPUS_SHIFT);
 	id = my_cluster | (1UL << count);
-	apic_write_around(APIC_DFR, APIC_DFR_VALUE);
+	apic_write(APIC_DFR, APIC_DFR_VALUE);
 	val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
 	val |= SET_APIC_LOGICAL_ID(id);
-	apic_write_around(APIC_LDR, val);
+	apic_write(APIC_LDR, val);
 }
 
 static inline int multi_timer_check(int apic, int irq)
diff --git a/include/asm-x86/mach-visws/entry_arch.h b/include/asm-x86/mach-visws/entry_arch.h
deleted file mode 100644
index 86be554..0000000
--- a/include/asm-x86/mach-visws/entry_arch.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
- * VISWS uses the standard Linux entry points:
- */
-
-#include "../mach-default/entry_arch.h"
diff --git a/include/asm-x86/mach-visws/mach_apic.h b/include/asm-x86/mach-visws/mach_apic.h
deleted file mode 100644
index 6943e7a..0000000
--- a/include/asm-x86/mach-visws/mach_apic.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "../mach-default/mach_apic.h"
diff --git a/include/asm-x86/mach-visws/mach_apicdef.h b/include/asm-x86/mach-visws/mach_apicdef.h
deleted file mode 100644
index 42711d1..0000000
--- a/include/asm-x86/mach-visws/mach_apicdef.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "../mach-default/mach_apicdef.h"
diff --git a/include/asm-x86/mach-visws/setup_arch.h b/include/asm-x86/mach-visws/setup_arch.h
deleted file mode 100644
index fa4766c..0000000
--- a/include/asm-x86/mach-visws/setup_arch.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "../mach-default/setup_arch.h"
diff --git a/include/asm-x86/mach-visws/smpboot_hooks.h b/include/asm-x86/mach-visws/smpboot_hooks.h
deleted file mode 100644
index e4433ca..0000000
--- a/include/asm-x86/mach-visws/smpboot_hooks.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "../mach-default/smpboot_hooks.h"
diff --git a/include/asm-x86/page.h b/include/asm-x86/page.h
index 28d7b45..6c84622 100644
--- a/include/asm-x86/page.h
+++ b/include/asm-x86/page.h
@@ -18,8 +18,11 @@
    (ie, 32-bit PAE). */
 #define PHYSICAL_PAGE_MASK	(((signed long)PAGE_MASK) & __PHYSICAL_MASK)
 
-/* PTE_MASK extracts the PFN from a (pte|pmd|pud|pgd)val_t */
-#define PTE_MASK		((pteval_t)PHYSICAL_PAGE_MASK)
+/* PTE_PFN_MASK extracts the PFN from a (pte|pmd|pud|pgd)val_t */
+#define PTE_PFN_MASK		((pteval_t)PHYSICAL_PAGE_MASK)
+
+/* PTE_FLAGS_MASK extracts the flags from a (pte|pmd|pud|pgd)val_t */
+#define PTE_FLAGS_MASK		(~PTE_PFN_MASK)
 
 #define PMD_PAGE_SIZE		(_AC(1, UL) << PMD_SHIFT)
 #define PMD_PAGE_MASK		(~(PMD_PAGE_SIZE-1))
@@ -144,6 +147,11 @@
 	return pte.pte;
 }
 
+static inline pteval_t native_pte_flags(pte_t pte)
+{
+	return native_pte_val(pte) & PTE_FLAGS_MASK;
+}
+
 #define pgprot_val(x)	((x).pgprot)
 #define __pgprot(x)	((pgprot_t) { (x) } )
 
@@ -165,7 +173,7 @@
 #endif
 
 #define pte_val(x)	native_pte_val(x)
-#define pte_flags(x)	native_pte_val(x)
+#define pte_flags(x)	native_pte_flags(x)
 #define __pte(x)	native_make_pte(x)
 
 #endif	/* CONFIG_PARAVIRT */
diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h
index ef5e8ec..fbbde93 100644
--- a/include/asm-x86/paravirt.h
+++ b/include/asm-x86/paravirt.h
@@ -205,7 +205,6 @@
 	 * these shouldn't be in this interface.
 	 */
 	void (*apic_write)(unsigned long reg, u32 v);
-	void (*apic_write_atomic)(unsigned long reg, u32 v);
 	u32 (*apic_read)(unsigned long reg);
 	void (*setup_boot_clock)(void);
 	void (*setup_secondary_clock)(void);
@@ -326,6 +325,15 @@
 			   unsigned long phys, pgprot_t flags);
 };
 
+struct raw_spinlock;
+struct pv_lock_ops {
+	int (*spin_is_locked)(struct raw_spinlock *lock);
+	int (*spin_is_contended)(struct raw_spinlock *lock);
+	void (*spin_lock)(struct raw_spinlock *lock);
+	int (*spin_trylock)(struct raw_spinlock *lock);
+	void (*spin_unlock)(struct raw_spinlock *lock);
+};
+
 /* This contains all the paravirt structures: we get a convenient
  * number for each function using the offset which we use to indicate
  * what to patch. */
@@ -336,6 +344,7 @@
 	struct pv_irq_ops pv_irq_ops;
 	struct pv_apic_ops pv_apic_ops;
 	struct pv_mmu_ops pv_mmu_ops;
+	struct pv_lock_ops pv_lock_ops;
 };
 
 extern struct pv_info pv_info;
@@ -345,6 +354,7 @@
 extern struct pv_irq_ops pv_irq_ops;
 extern struct pv_apic_ops pv_apic_ops;
 extern struct pv_mmu_ops pv_mmu_ops;
+extern struct pv_lock_ops pv_lock_ops;
 
 #define PARAVIRT_PATCH(x)					\
 	(offsetof(struct paravirt_patch_template, x) / sizeof(void *))
@@ -896,11 +906,6 @@
 	PVOP_VCALL2(pv_apic_ops.apic_write, reg, v);
 }
 
-static inline void apic_write_atomic(unsigned long reg, u32 v)
-{
-	PVOP_VCALL2(pv_apic_ops.apic_write_atomic, reg, v);
-}
-
 static inline u32 apic_read(unsigned long reg)
 {
 	return PVOP_CALL1(unsigned long, pv_apic_ops.apic_read, reg);
@@ -1083,6 +1088,9 @@
 		ret = PVOP_CALL1(pteval_t, pv_mmu_ops.pte_flags,
 				 pte.pte);
 
+#ifdef CONFIG_PARAVIRT_DEBUG
+	BUG_ON(ret & PTE_PFN_MASK);
+#endif
 	return ret;
 }
 
@@ -1374,6 +1382,37 @@
 void _paravirt_nop(void);
 #define paravirt_nop	((void *)_paravirt_nop)
 
+void paravirt_use_bytelocks(void);
+
+#ifdef CONFIG_SMP
+
+static inline int __raw_spin_is_locked(struct raw_spinlock *lock)
+{
+	return PVOP_CALL1(int, pv_lock_ops.spin_is_locked, lock);
+}
+
+static inline int __raw_spin_is_contended(struct raw_spinlock *lock)
+{
+	return PVOP_CALL1(int, pv_lock_ops.spin_is_contended, lock);
+}
+
+static __always_inline void __raw_spin_lock(struct raw_spinlock *lock)
+{
+	PVOP_VCALL1(pv_lock_ops.spin_lock, lock);
+}
+
+static __always_inline int __raw_spin_trylock(struct raw_spinlock *lock)
+{
+	return PVOP_CALL1(int, pv_lock_ops.spin_trylock, lock);
+}
+
+static __always_inline void __raw_spin_unlock(struct raw_spinlock *lock)
+{
+	PVOP_VCALL1(pv_lock_ops.spin_unlock, lock);
+}
+
+#endif
+
 /* These all sit in the .parainstructions section to tell us what to patch. */
 struct paravirt_patch_site {
 	u8 *instr; 		/* original instructions */
@@ -1396,8 +1435,8 @@
  * caller saved registers but the argument parameter */
 #define PV_SAVE_REGS "pushq %%rdi;"
 #define PV_RESTORE_REGS "popq %%rdi;"
-#define PV_EXTRA_CLOBBERS EXTRA_CLOBBERS, "rcx" , "rdx"
-#define PV_VEXTRA_CLOBBERS EXTRA_CLOBBERS, "rdi", "rcx" , "rdx"
+#define PV_EXTRA_CLOBBERS EXTRA_CLOBBERS, "rcx" , "rdx", "rsi"
+#define PV_VEXTRA_CLOBBERS EXTRA_CLOBBERS, "rdi", "rcx" , "rdx", "rsi"
 #define PV_FLAGS_ARG "D"
 #endif
 
@@ -1458,6 +1497,7 @@
 	return f;
 }
 
+
 /* Make sure as little as possible of this mess escapes. */
 #undef PARAVIRT_CALL
 #undef __PVOP_CALL
@@ -1489,8 +1529,26 @@
 
 
 #ifdef CONFIG_X86_64
-#define PV_SAVE_REGS   pushq %rax; pushq %rdi; pushq %rcx; pushq %rdx
-#define PV_RESTORE_REGS popq %rdx; popq %rcx; popq %rdi; popq %rax
+#define PV_SAVE_REGS				\
+	push %rax;				\
+	push %rcx;				\
+	push %rdx;				\
+	push %rsi;				\
+	push %rdi;				\
+	push %r8;				\
+	push %r9;				\
+	push %r10;				\
+	push %r11
+#define PV_RESTORE_REGS				\
+	pop %r11;				\
+	pop %r10;				\
+	pop %r9;				\
+	pop %r8;				\
+	pop %rdi;				\
+	pop %rsi;				\
+	pop %rdx;				\
+	pop %rcx;				\
+	pop %rax
 #define PARA_PATCH(struct, off)        ((PARAVIRT_PATCH_##struct + (off)) / 8)
 #define PARA_SITE(ptype, clobbers, ops) _PVSITE(ptype, clobbers, ops, .quad, 8)
 #define PARA_INDIRECT(addr)	*addr(%rip)
diff --git a/include/asm-x86/percpu.h b/include/asm-x86/percpu.h
index 912a3a1..4e91ee1 100644
--- a/include/asm-x86/percpu.h
+++ b/include/asm-x86/percpu.h
@@ -22,6 +22,32 @@
 
 DECLARE_PER_CPU(struct x8664_pda, pda);
 
+/*
+ * These are supposed to be implemented as a single instruction which
+ * operates on the per-cpu data base segment.  x86-64 doesn't have
+ * that yet, so this is a fairly inefficient workaround for the
+ * meantime.  The single instruction is atomic with respect to
+ * preemption and interrupts, so we need to explicitly disable
+ * interrupts here to achieve the same effect.  However, because it
+ * can be used from within interrupt-disable/enable, we can't actually
+ * disable interrupts; disabling preemption is enough.
+ */
+#define x86_read_percpu(var)						\
+	({								\
+		typeof(per_cpu_var(var)) __tmp;				\
+		preempt_disable();					\
+		__tmp = __get_cpu_var(var);				\
+		preempt_enable();					\
+		__tmp;							\
+	})
+
+#define x86_write_percpu(var, val)					\
+	do {								\
+		preempt_disable();					\
+		__get_cpu_var(var) = (val);				\
+		preempt_enable();					\
+	} while(0)
+
 #else /* CONFIG_X86_64 */
 
 #ifdef __ASSEMBLY__
diff --git a/include/asm-x86/pgtable-3level.h b/include/asm-x86/pgtable-3level.h
index c93dbb6..105057f 100644
--- a/include/asm-x86/pgtable-3level.h
+++ b/include/asm-x86/pgtable-3level.h
@@ -25,7 +25,7 @@
 
 static inline int pud_bad(pud_t pud)
 {
-	return (pud_val(pud) & ~(PTE_MASK | _KERNPG_TABLE | _PAGE_USER)) != 0;
+	return (pud_val(pud) & ~(PTE_PFN_MASK | _KERNPG_TABLE | _PAGE_USER)) != 0;
 }
 
 static inline int pud_present(pud_t pud)
@@ -120,9 +120,9 @@
 		write_cr3(pgd);
 }
 
-#define pud_page(pud) ((struct page *) __va(pud_val(pud) & PTE_MASK))
+#define pud_page(pud) ((struct page *) __va(pud_val(pud) & PTE_PFN_MASK))
 
-#define pud_page_vaddr(pud) ((unsigned long) __va(pud_val(pud) & PTE_MASK))
+#define pud_page_vaddr(pud) ((unsigned long) __va(pud_val(pud) & PTE_PFN_MASK))
 
 
 /* Find an entry in the second-level page table.. */
@@ -160,7 +160,7 @@
 
 static inline unsigned long pte_pfn(pte_t pte)
 {
-	return (pte_val(pte) & PTE_MASK) >> PAGE_SHIFT;
+	return (pte_val(pte) & PTE_PFN_MASK) >> PAGE_SHIFT;
 }
 
 /*
diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h
index 49cbd76..3e5dbc4 100644
--- a/include/asm-x86/pgtable.h
+++ b/include/asm-x86/pgtable.h
@@ -53,7 +53,7 @@
 			 _PAGE_DIRTY)
 
 /* Set of bits not changed in pte_modify */
-#define _PAGE_CHG_MASK	(PTE_MASK | _PAGE_PCD | _PAGE_PWT |		\
+#define _PAGE_CHG_MASK	(PTE_PFN_MASK | _PAGE_PCD | _PAGE_PWT |		\
 			 _PAGE_ACCESSED | _PAGE_DIRTY)
 
 #define _PAGE_CACHE_MASK	(_PAGE_PCD | _PAGE_PWT)
@@ -286,7 +286,7 @@
 	return __pgprot(preservebits | addbits);
 }
 
-#define pte_pgprot(x) __pgprot(pte_flags(x) & ~PTE_MASK)
+#define pte_pgprot(x) __pgprot(pte_flags(x) & PTE_FLAGS_MASK)
 
 #define canon_pgprot(p) __pgprot(pgprot_val(p) & __supported_pte_mask)
 
@@ -302,6 +302,14 @@
 /* Install a pte for a particular vaddr in kernel space. */
 void set_pte_vaddr(unsigned long vaddr, pte_t pte);
 
+#ifdef CONFIG_X86_32
+extern void native_pagetable_setup_start(pgd_t *base);
+extern void native_pagetable_setup_done(pgd_t *base);
+#else
+static inline void native_pagetable_setup_start(pgd_t *base) {}
+static inline void native_pagetable_setup_done(pgd_t *base) {}
+#endif
+
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt.h>
 #else  /* !CONFIG_PARAVIRT */
@@ -333,6 +341,16 @@
 
 #define pte_update(mm, addr, ptep)              do { } while (0)
 #define pte_update_defer(mm, addr, ptep)        do { } while (0)
+
+static inline void __init paravirt_pagetable_setup_start(pgd_t *base)
+{
+	native_pagetable_setup_start(base);
+}
+
+static inline void __init paravirt_pagetable_setup_done(pgd_t *base)
+{
+	native_pagetable_setup_done(base);
+}
 #endif	/* CONFIG_PARAVIRT */
 
 #endif	/* __ASSEMBLY__ */
diff --git a/include/asm-x86/pgtable_32.h b/include/asm-x86/pgtable_32.h
index ec871c4..5c3b265 100644
--- a/include/asm-x86/pgtable_32.h
+++ b/include/asm-x86/pgtable_32.h
@@ -88,7 +88,7 @@
 /* To avoid harmful races, pmd_none(x) should check only the lower when PAE */
 #define pmd_none(x)	(!(unsigned long)pmd_val((x)))
 #define pmd_present(x)	(pmd_val((x)) & _PAGE_PRESENT)
-#define pmd_bad(x) ((pmd_val(x) & (~PTE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
+#define pmd_bad(x) ((pmd_val(x) & (PTE_FLAGS_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
 
 #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
 
@@ -139,7 +139,7 @@
 #define pmd_page(pmd) (pfn_to_page(pmd_val((pmd)) >> PAGE_SHIFT))
 
 #define pmd_page_vaddr(pmd)					\
-	((unsigned long)__va(pmd_val((pmd)) & PTE_MASK))
+	((unsigned long)__va(pmd_val((pmd)) & PTE_PFN_MASK))
 
 #if defined(CONFIG_HIGHPTE)
 #define pte_offset_map(dir, address)					\
@@ -171,21 +171,6 @@
  */
 #define update_mmu_cache(vma, address, pte) do { } while (0)
 
-extern void native_pagetable_setup_start(pgd_t *base);
-extern void native_pagetable_setup_done(pgd_t *base);
-
-#ifndef CONFIG_PARAVIRT
-static inline void __init paravirt_pagetable_setup_start(pgd_t *base)
-{
-	native_pagetable_setup_start(base);
-}
-
-static inline void __init paravirt_pagetable_setup_done(pgd_t *base)
-{
-	native_pagetable_setup_done(base);
-}
-#endif	/* !CONFIG_PARAVIRT */
-
 #endif /* !__ASSEMBLY__ */
 
 /*
diff --git a/include/asm-x86/pgtable_64.h b/include/asm-x86/pgtable_64.h
index fa7208b..ac5fff4 100644
--- a/include/asm-x86/pgtable_64.h
+++ b/include/asm-x86/pgtable_64.h
@@ -16,6 +16,8 @@
 extern pud_t level3_kernel_pgt[512];
 extern pud_t level3_ident_pgt[512];
 extern pmd_t level2_kernel_pgt[512];
+extern pmd_t level2_fixmap_pgt[512];
+extern pmd_t level2_ident_pgt[512];
 extern pgd_t init_level4_pgt[];
 
 #define swapper_pg_dir init_level4_pgt
@@ -156,17 +158,17 @@
 
 static inline int pgd_bad(pgd_t pgd)
 {
-	return (pgd_val(pgd) & ~(PTE_MASK | _PAGE_USER)) != _KERNPG_TABLE;
+	return (pgd_val(pgd) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE;
 }
 
 static inline int pud_bad(pud_t pud)
 {
-	return (pud_val(pud) & ~(PTE_MASK | _PAGE_USER)) != _KERNPG_TABLE;
+	return (pud_val(pud) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE;
 }
 
 static inline int pmd_bad(pmd_t pmd)
 {
-	return (pmd_val(pmd) & ~(PTE_MASK | _PAGE_USER)) != _KERNPG_TABLE;
+	return (pmd_val(pmd) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE;
 }
 
 #define pte_none(x)	(!pte_val((x)))
@@ -191,7 +193,7 @@
  * Level 4 access.
  */
 #define pgd_page_vaddr(pgd)						\
-	((unsigned long)__va((unsigned long)pgd_val((pgd)) & PTE_MASK))
+	((unsigned long)__va((unsigned long)pgd_val((pgd)) & PTE_PFN_MASK))
 #define pgd_page(pgd)		(pfn_to_page(pgd_val((pgd)) >> PAGE_SHIFT))
 #define pgd_present(pgd) (pgd_val(pgd) & _PAGE_PRESENT)
 static inline int pgd_large(pgd_t pgd) { return 0; }
@@ -214,7 +216,7 @@
 }
 
 /* PMD  - Level 2 access */
-#define pmd_page_vaddr(pmd) ((unsigned long) __va(pmd_val((pmd)) & PTE_MASK))
+#define pmd_page_vaddr(pmd) ((unsigned long) __va(pmd_val((pmd)) & PTE_PFN_MASK))
 #define pmd_page(pmd)		(pfn_to_page(pmd_val((pmd)) >> PAGE_SHIFT))
 
 #define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h
index f92315e..5f58da4 100644
--- a/include/asm-x86/processor.h
+++ b/include/asm-x86/processor.h
@@ -722,8 +722,6 @@
 
 extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
 
-extern int			force_mwait;
-
 extern void select_idle_routine(const struct cpuinfo_x86 *c);
 
 extern unsigned long		boot_option_idle_override;
diff --git a/include/asm-x86/ptrace-abi.h b/include/asm-x86/ptrace-abi.h
index f224eb3..72e7b9d 100644
--- a/include/asm-x86/ptrace-abi.h
+++ b/include/asm-x86/ptrace-abi.h
@@ -73,11 +73,11 @@
 
 #ifdef __x86_64__
 # define PTRACE_ARCH_PRCTL	  30
-#else
-# define PTRACE_SYSEMU		  31
-# define PTRACE_SYSEMU_SINGLESTEP 32
 #endif
 
+#define PTRACE_SYSEMU		  31
+#define PTRACE_SYSEMU_SINGLESTEP  32
+
 #define PTRACE_SINGLEBLOCK	33	/* resume execution until next branch */
 
 #ifndef __ASSEMBLY__
diff --git a/include/asm-x86/segment.h b/include/asm-x86/segment.h
index dfc8601..646452e 100644
--- a/include/asm-x86/segment.h
+++ b/include/asm-x86/segment.h
@@ -1,6 +1,15 @@
 #ifndef _ASM_X86_SEGMENT_H_
 #define _ASM_X86_SEGMENT_H_
 
+/* Constructor for a conventional segment GDT (or LDT) entry */
+/* This is a macro so it can be used in initializers */
+#define GDT_ENTRY(flags, base, limit)			\
+	((((base)  & 0xff000000ULL) << (56-24)) |	\
+	 (((flags) & 0x0000f0ffULL) << 40) |		\
+	 (((limit) & 0x000f0000ULL) << (48-16)) |	\
+	 (((base)  & 0x00ffffffULL) << 16) |		\
+	 (((limit) & 0x0000ffffULL)))
+
 /* Simple and small GDT entries for booting only */
 
 #define GDT_ENTRY_BOOT_CS	2
diff --git a/include/asm-x86/setup.h b/include/asm-x86/setup.h
index 90ab222..a07c6f1 100644
--- a/include/asm-x86/setup.h
+++ b/include/asm-x86/setup.h
@@ -19,13 +19,28 @@
 /*
  * Any setup quirks to be performed?
  */
-extern int (*arch_time_init_quirk)(void);
-extern int (*arch_pre_intr_init_quirk)(void);
-extern int (*arch_intr_init_quirk)(void);
-extern int (*arch_trap_init_quirk)(void);
-extern char * (*arch_memory_setup_quirk)(void);
-extern int (*mach_get_smp_config_quirk)(unsigned int early);
-extern int (*mach_find_smp_config_quirk)(unsigned int reserve);
+struct mpc_config_processor;
+struct mpc_config_bus;
+struct mp_config_oemtable;
+struct x86_quirks {
+	int (*arch_pre_time_init)(void);
+	int (*arch_time_init)(void);
+	int (*arch_pre_intr_init)(void);
+	int (*arch_intr_init)(void);
+	int (*arch_trap_init)(void);
+	char * (*arch_memory_setup)(void);
+	int (*mach_get_smp_config)(unsigned int early);
+	int (*mach_find_smp_config)(unsigned int reserve);
+
+	int *mpc_record;
+	int (*mpc_apic_id)(struct mpc_config_processor *m);
+	void (*mpc_oem_bus_info)(struct mpc_config_bus *m, char *name);
+	void (*mpc_oem_pci_bus)(struct mpc_config_bus *m);
+	void (*smp_read_mpc_oem)(struct mp_config_oemtable *oemtable,
+                                    unsigned short oemsize);
+};
+
+extern struct x86_quirks *x86_quirks;
 
 #ifndef CONFIG_PARAVIRT
 #define paravirt_post_allocator_init()	do {} while (0)
@@ -76,6 +91,7 @@
 extern unsigned long init_pg_tables_end;
 
 #else
+void __init x86_64_init_pda(void);
 void __init x86_64_start_kernel(char *real_mode);
 void __init x86_64_start_reservations(char *real_mode_data);
 
diff --git a/include/asm-x86/signal.h b/include/asm-x86/signal.h
index f15186d..6dac493 100644
--- a/include/asm-x86/signal.h
+++ b/include/asm-x86/signal.h
@@ -181,12 +181,12 @@
 #ifdef __KERNEL__
 #include <asm/sigcontext.h>
 
-#ifdef __386__
+#ifdef __i386__
 
 #define __HAVE_ARCH_SIG_BITOPS
 
 #define sigaddset(set,sig)		    \
-	(__builtin_constantp(sig)	    \
+	(__builtin_constant_p(sig)	    \
 	 ? __const_sigaddset((set), (sig))  \
 	 : __gen_sigaddset((set), (sig)))
 
diff --git a/include/asm-x86/smp.h b/include/asm-x86/smp.h
index c2784b3..3c877f7 100644
--- a/include/asm-x86/smp.h
+++ b/include/asm-x86/smp.h
@@ -25,6 +25,8 @@
 extern void (*mtrr_hook)(void);
 extern void zap_low_mappings(void);
 
+extern int __cpuinit get_local_pda(int cpu);
+
 extern int smp_num_siblings;
 extern unsigned int num_processors;
 extern cpumask_t cpu_initialized;
diff --git a/include/asm-x86/spinlock.h b/include/asm-x86/spinlock.h
index 21e89bf..4f9a986 100644
--- a/include/asm-x86/spinlock.h
+++ b/include/asm-x86/spinlock.h
@@ -6,7 +6,7 @@
 #include <asm/page.h>
 #include <asm/processor.h>
 #include <linux/compiler.h>
-
+#include <asm/paravirt.h>
 /*
  * Your basic SMP spinlocks, allowing only a single CPU anywhere
  *
@@ -54,21 +54,21 @@
  * much between them in performance though, especially as locks are out of line.
  */
 #if (NR_CPUS < 256)
-static inline int __raw_spin_is_locked(raw_spinlock_t *lock)
+static inline int __ticket_spin_is_locked(raw_spinlock_t *lock)
 {
 	int tmp = ACCESS_ONCE(lock->slock);
 
 	return (((tmp >> 8) & 0xff) != (tmp & 0xff));
 }
 
-static inline int __raw_spin_is_contended(raw_spinlock_t *lock)
+static inline int __ticket_spin_is_contended(raw_spinlock_t *lock)
 {
 	int tmp = ACCESS_ONCE(lock->slock);
 
 	return (((tmp >> 8) & 0xff) - (tmp & 0xff)) > 1;
 }
 
-static __always_inline void __raw_spin_lock(raw_spinlock_t *lock)
+static __always_inline void __ticket_spin_lock(raw_spinlock_t *lock)
 {
 	short inc = 0x0100;
 
@@ -87,9 +87,7 @@
 		: "memory", "cc");
 }
 
-#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
-
-static __always_inline int __raw_spin_trylock(raw_spinlock_t *lock)
+static __always_inline int __ticket_spin_trylock(raw_spinlock_t *lock)
 {
 	int tmp;
 	short new;
@@ -110,7 +108,7 @@
 	return tmp;
 }
 
-static __always_inline void __raw_spin_unlock(raw_spinlock_t *lock)
+static __always_inline void __ticket_spin_unlock(raw_spinlock_t *lock)
 {
 	asm volatile(UNLOCK_LOCK_PREFIX "incb %0"
 		     : "+m" (lock->slock)
@@ -118,21 +116,21 @@
 		     : "memory", "cc");
 }
 #else
-static inline int __raw_spin_is_locked(raw_spinlock_t *lock)
+static inline int __ticket_spin_is_locked(raw_spinlock_t *lock)
 {
 	int tmp = ACCESS_ONCE(lock->slock);
 
 	return (((tmp >> 16) & 0xffff) != (tmp & 0xffff));
 }
 
-static inline int __raw_spin_is_contended(raw_spinlock_t *lock)
+static inline int __ticket_spin_is_contended(raw_spinlock_t *lock)
 {
 	int tmp = ACCESS_ONCE(lock->slock);
 
 	return (((tmp >> 16) & 0xffff) - (tmp & 0xffff)) > 1;
 }
 
-static __always_inline void __raw_spin_lock(raw_spinlock_t *lock)
+static __always_inline void __ticket_spin_lock(raw_spinlock_t *lock)
 {
 	int inc = 0x00010000;
 	int tmp;
@@ -153,9 +151,7 @@
 		     : "memory", "cc");
 }
 
-#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
-
-static __always_inline int __raw_spin_trylock(raw_spinlock_t *lock)
+static __always_inline int __ticket_spin_trylock(raw_spinlock_t *lock)
 {
 	int tmp;
 	int new;
@@ -177,7 +173,7 @@
 	return tmp;
 }
 
-static __always_inline void __raw_spin_unlock(raw_spinlock_t *lock)
+static __always_inline void __ticket_spin_unlock(raw_spinlock_t *lock)
 {
 	asm volatile(UNLOCK_LOCK_PREFIX "incw %0"
 		     : "+m" (lock->slock)
@@ -186,6 +182,98 @@
 }
 #endif
 
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+
+#ifdef CONFIG_PARAVIRT
+/*
+ * Define virtualization-friendly old-style lock byte lock, for use in
+ * pv_lock_ops if desired.
+ *
+ * This differs from the pre-2.6.24 spinlock by always using xchgb
+ * rather than decb to take the lock; this allows it to use a
+ * zero-initialized lock structure.  It also maintains a 1-byte
+ * contention counter, so that we can implement
+ * __byte_spin_is_contended.
+ */
+struct __byte_spinlock {
+	s8 lock;
+	s8 spinners;
+};
+
+static inline int __byte_spin_is_locked(raw_spinlock_t *lock)
+{
+	struct __byte_spinlock *bl = (struct __byte_spinlock *)lock;
+	return bl->lock != 0;
+}
+
+static inline int __byte_spin_is_contended(raw_spinlock_t *lock)
+{
+	struct __byte_spinlock *bl = (struct __byte_spinlock *)lock;
+	return bl->spinners != 0;
+}
+
+static inline void __byte_spin_lock(raw_spinlock_t *lock)
+{
+	struct __byte_spinlock *bl = (struct __byte_spinlock *)lock;
+	s8 val = 1;
+
+	asm("1: xchgb %1, %0\n"
+	    "   test %1,%1\n"
+	    "   jz 3f\n"
+	    "   " LOCK_PREFIX "incb %2\n"
+	    "2: rep;nop\n"
+	    "   cmpb $1, %0\n"
+	    "   je 2b\n"
+	    "   " LOCK_PREFIX "decb %2\n"
+	    "   jmp 1b\n"
+	    "3:"
+	    : "+m" (bl->lock), "+q" (val), "+m" (bl->spinners): : "memory");
+}
+
+static inline int __byte_spin_trylock(raw_spinlock_t *lock)
+{
+	struct __byte_spinlock *bl = (struct __byte_spinlock *)lock;
+	u8 old = 1;
+
+	asm("xchgb %1,%0"
+	    : "+m" (bl->lock), "+q" (old) : : "memory");
+
+	return old == 0;
+}
+
+static inline void __byte_spin_unlock(raw_spinlock_t *lock)
+{
+	struct __byte_spinlock *bl = (struct __byte_spinlock *)lock;
+	smp_wmb();
+	bl->lock = 0;
+}
+#else  /* !CONFIG_PARAVIRT */
+static inline int __raw_spin_is_locked(raw_spinlock_t *lock)
+{
+	return __ticket_spin_is_locked(lock);
+}
+
+static inline int __raw_spin_is_contended(raw_spinlock_t *lock)
+{
+	return __ticket_spin_is_contended(lock);
+}
+
+static __always_inline void __raw_spin_lock(raw_spinlock_t *lock)
+{
+	__ticket_spin_lock(lock);
+}
+
+static __always_inline int __raw_spin_trylock(raw_spinlock_t *lock)
+{
+	return __ticket_spin_trylock(lock);
+}
+
+static __always_inline void __raw_spin_unlock(raw_spinlock_t *lock)
+{
+	__ticket_spin_unlock(lock);
+}
+#endif	/* CONFIG_PARAVIRT */
+
 static inline void __raw_spin_unlock_wait(raw_spinlock_t *lock)
 {
 	while (__raw_spin_is_locked(lock))
diff --git a/include/asm-x86/spinlock_types.h b/include/asm-x86/spinlock_types.h
index 9029cf7..06c071c 100644
--- a/include/asm-x86/spinlock_types.h
+++ b/include/asm-x86/spinlock_types.h
@@ -5,7 +5,7 @@
 # error "please don't include this file directly"
 #endif
 
-typedef struct {
+typedef struct raw_spinlock {
 	unsigned int slock;
 } raw_spinlock_t;
 
diff --git a/include/asm-x86/swiotlb.h b/include/asm-x86/swiotlb.h
index f5d9e74..c706a74 100644
--- a/include/asm-x86/swiotlb.h
+++ b/include/asm-x86/swiotlb.h
@@ -45,12 +45,14 @@
 
 #ifdef CONFIG_SWIOTLB
 extern int swiotlb;
+extern void pci_swiotlb_init(void);
 #else
 #define swiotlb 0
+static inline void pci_swiotlb_init(void)
+{
+}
 #endif
 
-extern void pci_swiotlb_init(void);
-
 static inline void dma_mark_clean(void *addr, size_t size) {}
 
 #endif /* _ASM_SWIOTLB_H */
diff --git a/include/asm-x86/thread_info.h b/include/asm-x86/thread_info.h
index 895339d..0a8f27d 100644
--- a/include/asm-x86/thread_info.h
+++ b/include/asm-x86/thread_info.h
@@ -75,9 +75,7 @@
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_SINGLESTEP		4	/* reenable singlestep on user return*/
 #define TIF_IRET		5	/* force IRET */
-#ifdef CONFIG_X86_32
 #define TIF_SYSCALL_EMU		6	/* syscall emulation active */
-#endif
 #define TIF_SYSCALL_AUDIT	7	/* syscall auditing active */
 #define TIF_SECCOMP		8	/* secure computing */
 #define TIF_MCE_NOTIFY		10	/* notify userspace of an MCE */
@@ -100,11 +98,7 @@
 #define _TIF_SINGLESTEP		(1 << TIF_SINGLESTEP)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_IRET		(1 << TIF_IRET)
-#ifdef CONFIG_X86_32
 #define _TIF_SYSCALL_EMU	(1 << TIF_SYSCALL_EMU)
-#else
-#define _TIF_SYSCALL_EMU	0
-#endif
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
 #define _TIF_MCE_NOTIFY		(1 << TIF_MCE_NOTIFY)
@@ -121,18 +115,27 @@
 #define _TIF_DS_AREA_MSR	(1 << TIF_DS_AREA_MSR)
 #define _TIF_BTS_TRACE_TS	(1 << TIF_BTS_TRACE_TS)
 
+/* work to do in syscall_trace_enter() */
+#define _TIF_WORK_SYSCALL_ENTRY	\
+	(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_EMU | \
+	 _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | _TIF_SINGLESTEP)
+
+/* work to do in syscall_trace_leave() */
+#define _TIF_WORK_SYSCALL_EXIT	\
+	(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SINGLESTEP)
+
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK							\
 	(0x0000FFFF &							\
-	 ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP|	\
-	 _TIF_SECCOMP|_TIF_SYSCALL_EMU))
+	 ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|			\
+	   _TIF_SINGLESTEP|_TIF_SECCOMP|_TIF_SYSCALL_EMU))
 
 /* work to do on any return to user space */
 #define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP)
 
 /* Only used for 64 bit */
 #define _TIF_DO_NOTIFY_MASK						\
-	(_TIF_SIGPENDING|_TIF_SINGLESTEP|_TIF_MCE_NOTIFY|_TIF_HRTICK_RESCHED)
+	(_TIF_SIGPENDING|_TIF_MCE_NOTIFY|_TIF_HRTICK_RESCHED)
 
 /* flags to check in __switch_to() */
 #define _TIF_WORK_CTXSW							\
diff --git a/include/asm-x86/traps.h b/include/asm-x86/traps.h
new file mode 100644
index 0000000..a4b65a7
--- /dev/null
+++ b/include/asm-x86/traps.h
@@ -0,0 +1,66 @@
+#ifndef _ASM_X86_TRAPS_H
+#define _ASM_X86_TRAPS_H
+
+/* Common in X86_32 and X86_64 */
+asmlinkage void divide_error(void);
+asmlinkage void debug(void);
+asmlinkage void nmi(void);
+asmlinkage void int3(void);
+asmlinkage void overflow(void);
+asmlinkage void bounds(void);
+asmlinkage void invalid_op(void);
+asmlinkage void device_not_available(void);
+asmlinkage void coprocessor_segment_overrun(void);
+asmlinkage void invalid_TSS(void);
+asmlinkage void segment_not_present(void);
+asmlinkage void stack_segment(void);
+asmlinkage void general_protection(void);
+asmlinkage void page_fault(void);
+asmlinkage void coprocessor_error(void);
+asmlinkage void simd_coprocessor_error(void);
+asmlinkage void alignment_check(void);
+asmlinkage void spurious_interrupt_bug(void);
+#ifdef CONFIG_X86_MCE
+asmlinkage void machine_check(void);
+#endif /* CONFIG_X86_MCE */
+
+void do_divide_error(struct pt_regs *, long);
+void do_overflow(struct pt_regs *, long);
+void do_bounds(struct pt_regs *, long);
+void do_coprocessor_segment_overrun(struct pt_regs *, long);
+void do_invalid_TSS(struct pt_regs *, long);
+void do_segment_not_present(struct pt_regs *, long);
+void do_stack_segment(struct pt_regs *, long);
+void do_alignment_check(struct pt_regs *, long);
+void do_invalid_op(struct pt_regs *, long);
+void do_general_protection(struct pt_regs *, long);
+void do_nmi(struct pt_regs *, long);
+
+extern int panic_on_unrecovered_nmi;
+extern int kstack_depth_to_print;
+
+#ifdef CONFIG_X86_32
+
+void do_iret_error(struct pt_regs *, long);
+void do_int3(struct pt_regs *, long);
+void do_debug(struct pt_regs *, long);
+void math_error(void __user *);
+void do_coprocessor_error(struct pt_regs *, long);
+void do_simd_coprocessor_error(struct pt_regs *, long);
+void do_spurious_interrupt_bug(struct pt_regs *, long);
+unsigned long patch_espfix_desc(unsigned long, unsigned long);
+asmlinkage void math_emulate(long);
+
+#else /* CONFIG_X86_32 */
+
+asmlinkage void double_fault(void);
+
+asmlinkage void do_int3(struct pt_regs *, long);
+asmlinkage void do_stack_segment(struct pt_regs *, long);
+asmlinkage void do_debug(struct pt_regs *, unsigned long);
+asmlinkage void do_coprocessor_error(struct pt_regs *);
+asmlinkage void do_simd_coprocessor_error(struct pt_regs *);
+asmlinkage void do_spurious_interrupt_bug(struct pt_regs *);
+
+#endif /* CONFIG_X86_32 */
+#endif /* _ASM_X86_TRAPS_H */
diff --git a/include/asm-x86/uv/bios.h b/include/asm-x86/uv/bios.h
new file mode 100644
index 0000000..aa73362
--- /dev/null
+++ b/include/asm-x86/uv/bios.h
@@ -0,0 +1,68 @@
+#ifndef _ASM_X86_BIOS_H
+#define _ASM_X86_BIOS_H
+
+/*
+ * BIOS layer definitions.
+ *
+ *  Copyright (c) 2008 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  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/rtc.h>
+
+#define BIOS_FREQ_BASE			0x01000001
+
+enum {
+	BIOS_FREQ_BASE_PLATFORM = 0,
+	BIOS_FREQ_BASE_INTERVAL_TIMER = 1,
+	BIOS_FREQ_BASE_REALTIME_CLOCK = 2
+};
+
+# define BIOS_CALL(result, a0, a1, a2, a3, a4, a5, a6, a7)		\
+	do {								\
+		/* XXX - the real call goes here */			\
+		result.status = BIOS_STATUS_UNIMPLEMENTED;		\
+		isrv.v0 = 0;						\
+		isrv.v1 = 0;						\
+	} while (0)
+
+enum {
+	BIOS_STATUS_SUCCESS		=  0,
+	BIOS_STATUS_UNIMPLEMENTED	= -1,
+	BIOS_STATUS_EINVAL		= -2,
+	BIOS_STATUS_ERROR		= -3
+};
+
+struct uv_bios_retval {
+	/*
+	 * A zero status value indicates call completed without error.
+	 * A negative status value indicates reason of call failure.
+	 * A positive status value indicates success but an
+	 * informational value should be printed (e.g., "reboot for
+	 * change to take effect").
+	 */
+	s64 status;
+	u64 v0;
+	u64 v1;
+	u64 v2;
+};
+
+extern long
+x86_bios_freq_base(unsigned long which, unsigned long *ticks_per_second,
+		   unsigned long *drift_info);
+extern const char *x86_bios_strerror(long status);
+
+#endif /* _ASM_X86_BIOS_H */
diff --git a/include/asm-x86/vdso.h b/include/asm-x86/vdso.h
index 86e085e..8e18fb8 100644
--- a/include/asm-x86/vdso.h
+++ b/include/asm-x86/vdso.h
@@ -36,4 +36,12 @@
 extern void __user __kernel_sigreturn;
 extern void __user __kernel_rt_sigreturn;
 
+/*
+ * These symbols are defined by vdso32.S to mark the bounds
+ * of the ELF DSO images included therein.
+ */
+extern const char vdso32_int80_start, vdso32_int80_end;
+extern const char vdso32_syscall_start, vdso32_syscall_end;
+extern const char vdso32_sysenter_start, vdso32_sysenter_end;
+
 #endif	/* asm-x86/vdso.h */
diff --git a/include/asm-x86/xen/events.h b/include/asm-x86/xen/events.h
index f8d57ea..8ded747 100644
--- a/include/asm-x86/xen/events.h
+++ b/include/asm-x86/xen/events.h
@@ -5,6 +5,7 @@
 	XEN_RESCHEDULE_VECTOR,
 	XEN_CALL_FUNCTION_VECTOR,
 	XEN_CALL_FUNCTION_SINGLE_VECTOR,
+	XEN_SPIN_UNLOCK_VECTOR,
 
 	XEN_NR_IPIS,
 };
diff --git a/include/asm-x86/xen/hypercall.h b/include/asm-x86/xen/hypercall.h
index 2a4f9b4..91cb7fd 100644
--- a/include/asm-x86/xen/hypercall.h
+++ b/include/asm-x86/xen/hypercall.h
@@ -40,83 +40,157 @@
 #include <xen/interface/sched.h>
 #include <xen/interface/physdev.h>
 
+/*
+ * The hypercall asms have to meet several constraints:
+ * - Work on 32- and 64-bit.
+ *    The two architectures put their arguments in different sets of
+ *    registers.
+ *
+ * - Work around asm syntax quirks
+ *    It isn't possible to specify one of the rNN registers in a
+ *    constraint, so we use explicit register variables to get the
+ *    args into the right place.
+ *
+ * - Mark all registers as potentially clobbered
+ *    Even unused parameters can be clobbered by the hypervisor, so we
+ *    need to make sure gcc knows it.
+ *
+ * - Avoid compiler bugs.
+ *    This is the tricky part.  Because x86_32 has such a constrained
+ *    register set, gcc versions below 4.3 have trouble generating
+ *    code when all the arg registers and memory are trashed by the
+ *    asm.  There are syntactically simpler ways of achieving the
+ *    semantics below, but they cause the compiler to crash.
+ *
+ *    The only combination I found which works is:
+ *     - assign the __argX variables first
+ *     - list all actually used parameters as "+r" (__argX)
+ *     - clobber the rest
+ *
+ * The result certainly isn't pretty, and it really shows up cpp's
+ * weakness as as macro language.  Sorry.  (But let's just give thanks
+ * there aren't more than 5 arguments...)
+ */
+
 extern struct { char _entry[32]; } hypercall_page[];
 
+#define __HYPERCALL		"call hypercall_page+%c[offset]"
+#define __HYPERCALL_ENTRY(x)						\
+	[offset] "i" (__HYPERVISOR_##x * sizeof(hypercall_page[0]))
+
+#ifdef CONFIG_X86_32
+#define __HYPERCALL_RETREG	"eax"
+#define __HYPERCALL_ARG1REG	"ebx"
+#define __HYPERCALL_ARG2REG	"ecx"
+#define __HYPERCALL_ARG3REG	"edx"
+#define __HYPERCALL_ARG4REG	"esi"
+#define __HYPERCALL_ARG5REG	"edi"
+#else
+#define __HYPERCALL_RETREG	"rax"
+#define __HYPERCALL_ARG1REG	"rdi"
+#define __HYPERCALL_ARG2REG	"rsi"
+#define __HYPERCALL_ARG3REG	"rdx"
+#define __HYPERCALL_ARG4REG	"r10"
+#define __HYPERCALL_ARG5REG	"r8"
+#endif
+
+#define __HYPERCALL_DECLS						\
+	register unsigned long __res  asm(__HYPERCALL_RETREG);		\
+	register unsigned long __arg1 asm(__HYPERCALL_ARG1REG) = __arg1; \
+	register unsigned long __arg2 asm(__HYPERCALL_ARG2REG) = __arg2; \
+	register unsigned long __arg3 asm(__HYPERCALL_ARG3REG) = __arg3; \
+	register unsigned long __arg4 asm(__HYPERCALL_ARG4REG) = __arg4; \
+	register unsigned long __arg5 asm(__HYPERCALL_ARG5REG) = __arg5;
+
+#define __HYPERCALL_0PARAM	"=r" (__res)
+#define __HYPERCALL_1PARAM	__HYPERCALL_0PARAM, "+r" (__arg1)
+#define __HYPERCALL_2PARAM	__HYPERCALL_1PARAM, "+r" (__arg2)
+#define __HYPERCALL_3PARAM	__HYPERCALL_2PARAM, "+r" (__arg3)
+#define __HYPERCALL_4PARAM	__HYPERCALL_3PARAM, "+r" (__arg4)
+#define __HYPERCALL_5PARAM	__HYPERCALL_4PARAM, "+r" (__arg5)
+
+#define __HYPERCALL_0ARG()
+#define __HYPERCALL_1ARG(a1)						\
+	__HYPERCALL_0ARG()		__arg1 = (unsigned long)(a1);
+#define __HYPERCALL_2ARG(a1,a2)						\
+	__HYPERCALL_1ARG(a1)		__arg2 = (unsigned long)(a2);
+#define __HYPERCALL_3ARG(a1,a2,a3)					\
+	__HYPERCALL_2ARG(a1,a2)		__arg3 = (unsigned long)(a3);
+#define __HYPERCALL_4ARG(a1,a2,a3,a4)					\
+	__HYPERCALL_3ARG(a1,a2,a3)	__arg4 = (unsigned long)(a4);
+#define __HYPERCALL_5ARG(a1,a2,a3,a4,a5)				\
+	__HYPERCALL_4ARG(a1,a2,a3,a4)	__arg5 = (unsigned long)(a5);
+
+#define __HYPERCALL_CLOBBER5	"memory"
+#define __HYPERCALL_CLOBBER4	__HYPERCALL_CLOBBER5, __HYPERCALL_ARG5REG
+#define __HYPERCALL_CLOBBER3	__HYPERCALL_CLOBBER4, __HYPERCALL_ARG4REG
+#define __HYPERCALL_CLOBBER2	__HYPERCALL_CLOBBER3, __HYPERCALL_ARG3REG
+#define __HYPERCALL_CLOBBER1	__HYPERCALL_CLOBBER2, __HYPERCALL_ARG2REG
+#define __HYPERCALL_CLOBBER0	__HYPERCALL_CLOBBER1, __HYPERCALL_ARG1REG
+
 #define _hypercall0(type, name)						\
 ({									\
-	long __res;							\
-	asm volatile (							\
-		"call %[call]"						\
-		: "=a" (__res)						\
-		: [call] "m" (hypercall_page[__HYPERVISOR_##name])	\
-		: "memory" );						\
+	__HYPERCALL_DECLS;						\
+	__HYPERCALL_0ARG();						\
+	asm volatile (__HYPERCALL					\
+		      : __HYPERCALL_0PARAM				\
+		      : __HYPERCALL_ENTRY(name)				\
+		      : __HYPERCALL_CLOBBER0);				\
 	(type)__res;							\
 })
 
 #define _hypercall1(type, name, a1)					\
 ({									\
-	long __res, __ign1;						\
-	asm volatile (							\
-		"call %[call]"						\
-		: "=a" (__res), "=b" (__ign1)				\
-		: "1" ((long)(a1)),					\
-		  [call] "m" (hypercall_page[__HYPERVISOR_##name])	\
-		: "memory" );						\
+	__HYPERCALL_DECLS;						\
+	__HYPERCALL_1ARG(a1);						\
+	asm volatile (__HYPERCALL					\
+		      : __HYPERCALL_1PARAM				\
+		      : __HYPERCALL_ENTRY(name)				\
+		      : __HYPERCALL_CLOBBER1);				\
 	(type)__res;							\
 })
 
 #define _hypercall2(type, name, a1, a2)					\
 ({									\
-	long __res, __ign1, __ign2;					\
-	asm volatile (							\
-		"call %[call]"						\
-		: "=a" (__res), "=b" (__ign1), "=c" (__ign2)		\
-		: "1" ((long)(a1)), "2" ((long)(a2)),			\
-		  [call] "m" (hypercall_page[__HYPERVISOR_##name])	\
-		: "memory" );						\
+	__HYPERCALL_DECLS;						\
+	__HYPERCALL_2ARG(a1, a2);					\
+	asm volatile (__HYPERCALL					\
+		      : __HYPERCALL_2PARAM				\
+		      : __HYPERCALL_ENTRY(name)				\
+		      : __HYPERCALL_CLOBBER2);				\
 	(type)__res;							\
 })
 
 #define _hypercall3(type, name, a1, a2, a3)				\
 ({									\
-	long __res, __ign1, __ign2, __ign3;				\
-	asm volatile (							\
-		"call %[call]"						\
-		: "=a" (__res), "=b" (__ign1), "=c" (__ign2),		\
-		"=d" (__ign3)						\
-		: "1" ((long)(a1)), "2" ((long)(a2)),			\
-		  "3" ((long)(a3)),					\
-		  [call] "m" (hypercall_page[__HYPERVISOR_##name])	\
-		: "memory" );						\
+	__HYPERCALL_DECLS;						\
+	__HYPERCALL_3ARG(a1, a2, a3);					\
+	asm volatile (__HYPERCALL					\
+		      : __HYPERCALL_3PARAM				\
+		      : __HYPERCALL_ENTRY(name)				\
+		      : __HYPERCALL_CLOBBER3);				\
 	(type)__res;							\
 })
 
 #define _hypercall4(type, name, a1, a2, a3, a4)				\
 ({									\
-	long __res, __ign1, __ign2, __ign3, __ign4;			\
-	asm volatile (							\
-		"call %[call]"						\
-		: "=a" (__res), "=b" (__ign1), "=c" (__ign2),		\
-		"=d" (__ign3), "=S" (__ign4)				\
-		: "1" ((long)(a1)), "2" ((long)(a2)),			\
-		  "3" ((long)(a3)), "4" ((long)(a4)),			\
-		  [call] "m" (hypercall_page[__HYPERVISOR_##name])	\
-		: "memory" );						\
+	__HYPERCALL_DECLS;						\
+	__HYPERCALL_4ARG(a1, a2, a3, a4);				\
+	asm volatile (__HYPERCALL					\
+		      : __HYPERCALL_4PARAM				\
+		      : __HYPERCALL_ENTRY(name)				\
+		      : __HYPERCALL_CLOBBER4);				\
 	(type)__res;							\
 })
 
 #define _hypercall5(type, name, a1, a2, a3, a4, a5)			\
 ({									\
-	long __res, __ign1, __ign2, __ign3, __ign4, __ign5;		\
-	asm volatile (							\
-		"call %[call]"						\
-		: "=a" (__res), "=b" (__ign1), "=c" (__ign2),		\
-		"=d" (__ign3), "=S" (__ign4), "=D" (__ign5)		\
-		: "1" ((long)(a1)), "2" ((long)(a2)),			\
-		  "3" ((long)(a3)), "4" ((long)(a4)),			\
-		  "5" ((long)(a5)),					\
-		  [call] "m" (hypercall_page[__HYPERVISOR_##name])	\
-		: "memory" );						\
+	__HYPERCALL_DECLS;						\
+	__HYPERCALL_5ARG(a1, a2, a3, a4, a5);				\
+	asm volatile (__HYPERCALL					\
+		      : __HYPERCALL_5PARAM				\
+		      : __HYPERCALL_ENTRY(name)				\
+		      : __HYPERCALL_CLOBBER5);				\
 	(type)__res;							\
 })
 
@@ -152,6 +226,7 @@
 	return _hypercall2(int, stack_switch, ss, esp);
 }
 
+#ifdef CONFIG_X86_32
 static inline int
 HYPERVISOR_set_callbacks(unsigned long event_selector,
 			 unsigned long event_address,
@@ -162,6 +237,17 @@
 			   event_selector, event_address,
 			   failsafe_selector, failsafe_address);
 }
+#else  /* CONFIG_X86_64 */
+static inline int
+HYPERVISOR_set_callbacks(unsigned long event_address,
+			unsigned long failsafe_address,
+			unsigned long syscall_address)
+{
+	return _hypercall3(int, set_callbacks,
+			   event_address, failsafe_address,
+			   syscall_address);
+}
+#endif  /* CONFIG_X86_{32,64} */
 
 static inline int
 HYPERVISOR_callback_op(int cmd, void *arg)
@@ -223,12 +309,12 @@
 HYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val,
 			     unsigned long flags)
 {
-	unsigned long pte_hi = 0;
-#ifdef CONFIG_X86_PAE
-	pte_hi = new_val.pte_high;
-#endif
-	return _hypercall4(int, update_va_mapping, va,
-			   new_val.pte_low, pte_hi, flags);
+	if (sizeof(new_val) == sizeof(long))
+		return _hypercall3(int, update_va_mapping, va,
+				   new_val.pte, flags);
+	else
+		return _hypercall4(int, update_va_mapping, va,
+				   new_val.pte, new_val.pte >> 32, flags);
 }
 
 static inline int
@@ -281,12 +367,13 @@
 HYPERVISOR_update_va_mapping_otherdomain(unsigned long va, pte_t new_val,
 					 unsigned long flags, domid_t domid)
 {
-	unsigned long pte_hi = 0;
-#ifdef CONFIG_X86_PAE
-	pte_hi = new_val.pte_high;
-#endif
-	return _hypercall5(int, update_va_mapping_otherdomain, va,
-			   new_val.pte_low, pte_hi, flags, domid);
+	if (sizeof(new_val) == sizeof(long))
+		return _hypercall4(int, update_va_mapping_otherdomain, va,
+				   new_val.pte, flags, domid);
+	else
+		return _hypercall5(int, update_va_mapping_otherdomain, va,
+				   new_val.pte, new_val.pte >> 32,
+				   flags, domid);
 }
 
 static inline int
@@ -301,6 +388,14 @@
 	return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
 }
 
+#ifdef CONFIG_X86_64
+static inline int
+HYPERVISOR_set_segment_base(int reg, unsigned long value)
+{
+	return _hypercall2(int, set_segment_base, reg, value);
+}
+#endif
+
 static inline int
 HYPERVISOR_suspend(unsigned long srec)
 {
@@ -327,14 +422,14 @@
 {
 	mcl->op = __HYPERVISOR_update_va_mapping;
 	mcl->args[0] = va;
-#ifdef CONFIG_X86_PAE
-	mcl->args[1] = new_val.pte_low;
-	mcl->args[2] = new_val.pte_high;
-#else
-	mcl->args[1] = new_val.pte_low;
-	mcl->args[2] = 0;
-#endif
-	mcl->args[3] = flags;
+	if (sizeof(new_val) == sizeof(long)) {
+		mcl->args[1] = new_val.pte;
+		mcl->args[2] = flags;
+	} else {
+		mcl->args[1] = new_val.pte;
+		mcl->args[2] = new_val.pte >> 32;
+		mcl->args[3] = flags;
+	}
 }
 
 static inline void
@@ -354,15 +449,16 @@
 {
 	mcl->op = __HYPERVISOR_update_va_mapping_otherdomain;
 	mcl->args[0] = va;
-#ifdef CONFIG_X86_PAE
-	mcl->args[1] = new_val.pte_low;
-	mcl->args[2] = new_val.pte_high;
-#else
-	mcl->args[1] = new_val.pte_low;
-	mcl->args[2] = 0;
-#endif
-	mcl->args[3] = flags;
-	mcl->args[4] = domid;
+	if (sizeof(new_val) == sizeof(long)) {
+		mcl->args[1] = new_val.pte;
+		mcl->args[2] = flags;
+		mcl->args[3] = domid;
+	} else {
+		mcl->args[1] = new_val.pte;
+		mcl->args[2] = new_val.pte >> 32;
+		mcl->args[3] = flags;
+		mcl->args[4] = domid;
+	}
 }
 
 static inline void
@@ -370,10 +466,15 @@
 			struct desc_struct desc)
 {
 	mcl->op = __HYPERVISOR_update_descriptor;
-	mcl->args[0] = maddr;
-	mcl->args[1] = maddr >> 32;
-	mcl->args[2] = desc.a;
-	mcl->args[3] = desc.b;
+	if (sizeof(maddr) == sizeof(long)) {
+		mcl->args[0] = maddr;
+		mcl->args[1] = *(unsigned long *)&desc;
+	} else {
+		mcl->args[0] = maddr;
+		mcl->args[1] = maddr >> 32;
+		mcl->args[2] = desc.a;
+		mcl->args[3] = desc.b;
+	}
 }
 
 static inline void
diff --git a/include/asm-x86/xen/interface.h b/include/asm-x86/xen/interface.h
index 6227000..9d810f2 100644
--- a/include/asm-x86/xen/interface.h
+++ b/include/asm-x86/xen/interface.h
@@ -1,13 +1,13 @@
 /******************************************************************************
  * arch-x86_32.h
  *
- * Guest OS interface to x86 32-bit Xen.
+ * Guest OS interface to x86 Xen.
  *
  * Copyright (c) 2004, K A Fraser
  */
 
-#ifndef __XEN_PUBLIC_ARCH_X86_32_H__
-#define __XEN_PUBLIC_ARCH_X86_32_H__
+#ifndef __ASM_X86_XEN_INTERFACE_H
+#define __ASM_X86_XEN_INTERFACE_H
 
 #ifdef __XEN__
 #define __DEFINE_GUEST_HANDLE(name, type) \
@@ -57,6 +57,17 @@
 DEFINE_GUEST_HANDLE(void);
 #endif
 
+#ifndef HYPERVISOR_VIRT_START
+#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START)
+#endif
+
+#ifndef machine_to_phys_mapping
+#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
+#endif
+
+/* Maximum number of virtual CPUs in multi-processor guests. */
+#define MAX_VIRT_CPUS 32
+
 /*
  * SEGMENT DESCRIPTOR TABLES
  */
@@ -71,58 +82,21 @@
 #define FIRST_RESERVED_GDT_ENTRY (FIRST_RESERVED_GDT_BYTE / 8)
 
 /*
- * These flat segments are in the Xen-private section of every GDT. Since these
- * are also present in the initial GDT, many OSes will be able to avoid
- * installing their own GDT.
- */
-#define FLAT_RING1_CS 0xe019    /* GDT index 259 */
-#define FLAT_RING1_DS 0xe021    /* GDT index 260 */
-#define FLAT_RING1_SS 0xe021    /* GDT index 260 */
-#define FLAT_RING3_CS 0xe02b    /* GDT index 261 */
-#define FLAT_RING3_DS 0xe033    /* GDT index 262 */
-#define FLAT_RING3_SS 0xe033    /* GDT index 262 */
-
-#define FLAT_KERNEL_CS FLAT_RING1_CS
-#define FLAT_KERNEL_DS FLAT_RING1_DS
-#define FLAT_KERNEL_SS FLAT_RING1_SS
-#define FLAT_USER_CS    FLAT_RING3_CS
-#define FLAT_USER_DS    FLAT_RING3_DS
-#define FLAT_USER_SS    FLAT_RING3_SS
-
-/* And the trap vector is... */
-#define TRAP_INSTR "int $0x82"
-
-/*
- * Virtual addresses beyond this are not modifiable by guest OSes. The
- * machine->physical mapping table starts at this address, read-only.
- */
-#ifdef CONFIG_X86_PAE
-#define __HYPERVISOR_VIRT_START 0xF5800000
-#else
-#define __HYPERVISOR_VIRT_START 0xFC000000
-#endif
-
-#ifndef HYPERVISOR_VIRT_START
-#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START)
-#endif
-
-#ifndef machine_to_phys_mapping
-#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
-#endif
-
-/* Maximum number of virtual CPUs in multi-processor guests. */
-#define MAX_VIRT_CPUS 32
-
-#ifndef __ASSEMBLY__
-
-/*
  * Send an array of these to HYPERVISOR_set_trap_table()
+ * The privilege level specifies which modes may enter a trap via a software
+ * interrupt. On x86/64, since rings 1 and 2 are unavailable, we allocate
+ * privilege levels as follows:
+ *  Level == 0: Noone may enter
+ *  Level == 1: Kernel may enter
+ *  Level == 2: Kernel may enter
+ *  Level == 3: Everyone may enter
  */
 #define TI_GET_DPL(_ti)		((_ti)->flags & 3)
 #define TI_GET_IF(_ti)		((_ti)->flags & 4)
 #define TI_SET_DPL(_ti, _dpl)	((_ti)->flags |= (_dpl))
 #define TI_SET_IF(_ti, _if)	((_ti)->flags |= ((!!(_if))<<2))
 
+#ifndef __ASSEMBLY__
 struct trap_info {
     uint8_t       vector;  /* exception vector                              */
     uint8_t       flags;   /* 0-3: privilege level; 4: clear event enable?  */
@@ -131,32 +105,21 @@
 };
 DEFINE_GUEST_HANDLE_STRUCT(trap_info);
 
-struct cpu_user_regs {
-    uint32_t ebx;
-    uint32_t ecx;
-    uint32_t edx;
-    uint32_t esi;
-    uint32_t edi;
-    uint32_t ebp;
-    uint32_t eax;
-    uint16_t error_code;    /* private */
-    uint16_t entry_vector;  /* private */
-    uint32_t eip;
-    uint16_t cs;
-    uint8_t  saved_upcall_mask;
-    uint8_t  _pad0;
-    uint32_t eflags;        /* eflags.IF == !saved_upcall_mask */
-    uint32_t esp;
-    uint16_t ss, _pad1;
-    uint16_t es, _pad2;
-    uint16_t ds, _pad3;
-    uint16_t fs, _pad4;
-    uint16_t gs, _pad5;
+struct arch_shared_info {
+    unsigned long max_pfn;                  /* max pfn that appears in table */
+    /* Frame containing list of mfns containing list of mfns containing p2m. */
+    unsigned long pfn_to_mfn_frame_list_list;
+    unsigned long nmi_reason;
 };
-DEFINE_GUEST_HANDLE_STRUCT(cpu_user_regs);
+#endif	/* !__ASSEMBLY__ */
 
-typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */
+#ifdef CONFIG_X86_32
+#include "interface_32.h"
+#else
+#include "interface_64.h"
+#endif
 
+#ifndef __ASSEMBLY__
 /*
  * The following is all CPU context. Note that the fpu_ctxt block is filled
  * in by FXSAVE if the CPU has feature FXSR; otherwise FSAVE is used.
@@ -173,33 +136,29 @@
     unsigned long ldt_base, ldt_ents;       /* LDT (linear address, # ents) */
     unsigned long gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents) */
     unsigned long kernel_ss, kernel_sp;     /* Virtual TSS (only SS1/SP1)   */
+    /* NB. User pagetable on x86/64 is placed in ctrlreg[1]. */
     unsigned long ctrlreg[8];               /* CR0-CR7 (control registers)  */
     unsigned long debugreg[8];              /* DB0-DB7 (debug registers)    */
+#ifdef __i386__
     unsigned long event_callback_cs;        /* CS:EIP of event callback     */
     unsigned long event_callback_eip;
     unsigned long failsafe_callback_cs;     /* CS:EIP of failsafe callback  */
     unsigned long failsafe_callback_eip;
+#else
+    unsigned long event_callback_eip;
+    unsigned long failsafe_callback_eip;
+    unsigned long syscall_callback_eip;
+#endif
     unsigned long vm_assist;                /* VMASST_TYPE_* bitmap */
+#ifdef __x86_64__
+    /* Segment base addresses. */
+    uint64_t      fs_base;
+    uint64_t      gs_base_kernel;
+    uint64_t      gs_base_user;
+#endif
 };
 DEFINE_GUEST_HANDLE_STRUCT(vcpu_guest_context);
-
-struct arch_shared_info {
-    unsigned long max_pfn;                  /* max pfn that appears in table */
-    /* Frame containing list of mfns containing list of mfns containing p2m. */
-    unsigned long pfn_to_mfn_frame_list_list;
-    unsigned long nmi_reason;
-};
-
-struct arch_vcpu_info {
-    unsigned long cr2;
-    unsigned long pad[5]; /* sizeof(struct vcpu_info) == 64 */
-};
-
-struct xen_callback {
-	unsigned long cs;
-	unsigned long eip;
-};
-#endif /* !__ASSEMBLY__ */
+#endif	/* !__ASSEMBLY__ */
 
 /*
  * Prefix forces emulation of some non-trapping instructions.
@@ -213,4 +172,4 @@
 #define XEN_CPUID          XEN_EMULATE_PREFIX "cpuid"
 #endif
 
-#endif
+#endif	/* __ASM_X86_XEN_INTERFACE_H */
diff --git a/include/asm-x86/xen/interface_32.h b/include/asm-x86/xen/interface_32.h
new file mode 100644
index 0000000..d8ac41d
--- /dev/null
+++ b/include/asm-x86/xen/interface_32.h
@@ -0,0 +1,97 @@
+/******************************************************************************
+ * arch-x86_32.h
+ *
+ * Guest OS interface to x86 32-bit Xen.
+ *
+ * Copyright (c) 2004, K A Fraser
+ */
+
+#ifndef __ASM_X86_XEN_INTERFACE_32_H
+#define __ASM_X86_XEN_INTERFACE_32_H
+
+
+/*
+ * These flat segments are in the Xen-private section of every GDT. Since these
+ * are also present in the initial GDT, many OSes will be able to avoid
+ * installing their own GDT.
+ */
+#define FLAT_RING1_CS 0xe019    /* GDT index 259 */
+#define FLAT_RING1_DS 0xe021    /* GDT index 260 */
+#define FLAT_RING1_SS 0xe021    /* GDT index 260 */
+#define FLAT_RING3_CS 0xe02b    /* GDT index 261 */
+#define FLAT_RING3_DS 0xe033    /* GDT index 262 */
+#define FLAT_RING3_SS 0xe033    /* GDT index 262 */
+
+#define FLAT_KERNEL_CS FLAT_RING1_CS
+#define FLAT_KERNEL_DS FLAT_RING1_DS
+#define FLAT_KERNEL_SS FLAT_RING1_SS
+#define FLAT_USER_CS    FLAT_RING3_CS
+#define FLAT_USER_DS    FLAT_RING3_DS
+#define FLAT_USER_SS    FLAT_RING3_SS
+
+/* And the trap vector is... */
+#define TRAP_INSTR "int $0x82"
+
+/*
+ * Virtual addresses beyond this are not modifiable by guest OSes. The
+ * machine->physical mapping table starts at this address, read-only.
+ */
+#define __HYPERVISOR_VIRT_START 0xF5800000
+
+#ifndef __ASSEMBLY__
+
+struct cpu_user_regs {
+    uint32_t ebx;
+    uint32_t ecx;
+    uint32_t edx;
+    uint32_t esi;
+    uint32_t edi;
+    uint32_t ebp;
+    uint32_t eax;
+    uint16_t error_code;    /* private */
+    uint16_t entry_vector;  /* private */
+    uint32_t eip;
+    uint16_t cs;
+    uint8_t  saved_upcall_mask;
+    uint8_t  _pad0;
+    uint32_t eflags;        /* eflags.IF == !saved_upcall_mask */
+    uint32_t esp;
+    uint16_t ss, _pad1;
+    uint16_t es, _pad2;
+    uint16_t ds, _pad3;
+    uint16_t fs, _pad4;
+    uint16_t gs, _pad5;
+};
+DEFINE_GUEST_HANDLE_STRUCT(cpu_user_regs);
+
+typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */
+
+struct arch_vcpu_info {
+    unsigned long cr2;
+    unsigned long pad[5]; /* sizeof(struct vcpu_info) == 64 */
+};
+
+struct xen_callback {
+	unsigned long cs;
+	unsigned long eip;
+};
+typedef struct xen_callback xen_callback_t;
+
+#define XEN_CALLBACK(__cs, __eip)				\
+	((struct xen_callback){ .cs = (__cs), .eip = (unsigned long)(__eip) })
+#endif /* !__ASSEMBLY__ */
+
+
+/*
+ * Page-directory addresses above 4GB do not fit into architectural %cr3.
+ * When accessing %cr3, or equivalent field in vcpu_guest_context, guests
+ * must use the following accessor macros to pack/unpack valid MFNs.
+ *
+ * Note that Xen is using the fact that the pagetable base is always
+ * page-aligned, and putting the 12 MSB of the address into the 12 LSB
+ * of cr3.
+ */
+#define xen_pfn_to_cr3(pfn) (((unsigned)(pfn) << 12) | ((unsigned)(pfn) >> 20))
+#define xen_cr3_to_pfn(cr3) (((unsigned)(cr3) >> 12) | ((unsigned)(cr3) << 20))
+
+#endif	/* __ASM_X86_XEN_INTERFACE_32_H */
diff --git a/include/asm-x86/xen/interface_64.h b/include/asm-x86/xen/interface_64.h
new file mode 100644
index 0000000..842266c
--- /dev/null
+++ b/include/asm-x86/xen/interface_64.h
@@ -0,0 +1,159 @@
+#ifndef __ASM_X86_XEN_INTERFACE_64_H
+#define __ASM_X86_XEN_INTERFACE_64_H
+
+/*
+ * 64-bit segment selectors
+ * These flat segments are in the Xen-private section of every GDT. Since these
+ * are also present in the initial GDT, many OSes will be able to avoid
+ * installing their own GDT.
+ */
+
+#define FLAT_RING3_CS32 0xe023  /* GDT index 260 */
+#define FLAT_RING3_CS64 0xe033  /* GDT index 261 */
+#define FLAT_RING3_DS32 0xe02b  /* GDT index 262 */
+#define FLAT_RING3_DS64 0x0000  /* NULL selector */
+#define FLAT_RING3_SS32 0xe02b  /* GDT index 262 */
+#define FLAT_RING3_SS64 0xe02b  /* GDT index 262 */
+
+#define FLAT_KERNEL_DS64 FLAT_RING3_DS64
+#define FLAT_KERNEL_DS32 FLAT_RING3_DS32
+#define FLAT_KERNEL_DS   FLAT_KERNEL_DS64
+#define FLAT_KERNEL_CS64 FLAT_RING3_CS64
+#define FLAT_KERNEL_CS32 FLAT_RING3_CS32
+#define FLAT_KERNEL_CS   FLAT_KERNEL_CS64
+#define FLAT_KERNEL_SS64 FLAT_RING3_SS64
+#define FLAT_KERNEL_SS32 FLAT_RING3_SS32
+#define FLAT_KERNEL_SS   FLAT_KERNEL_SS64
+
+#define FLAT_USER_DS64 FLAT_RING3_DS64
+#define FLAT_USER_DS32 FLAT_RING3_DS32
+#define FLAT_USER_DS   FLAT_USER_DS64
+#define FLAT_USER_CS64 FLAT_RING3_CS64
+#define FLAT_USER_CS32 FLAT_RING3_CS32
+#define FLAT_USER_CS   FLAT_USER_CS64
+#define FLAT_USER_SS64 FLAT_RING3_SS64
+#define FLAT_USER_SS32 FLAT_RING3_SS32
+#define FLAT_USER_SS   FLAT_USER_SS64
+
+#define __HYPERVISOR_VIRT_START 0xFFFF800000000000
+#define __HYPERVISOR_VIRT_END   0xFFFF880000000000
+#define __MACH2PHYS_VIRT_START  0xFFFF800000000000
+#define __MACH2PHYS_VIRT_END    0xFFFF804000000000
+
+#ifndef HYPERVISOR_VIRT_START
+#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START)
+#define HYPERVISOR_VIRT_END   mk_unsigned_long(__HYPERVISOR_VIRT_END)
+#endif
+
+#define MACH2PHYS_VIRT_START  mk_unsigned_long(__MACH2PHYS_VIRT_START)
+#define MACH2PHYS_VIRT_END    mk_unsigned_long(__MACH2PHYS_VIRT_END)
+#define MACH2PHYS_NR_ENTRIES  ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>3)
+#ifndef machine_to_phys_mapping
+#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
+#endif
+
+/*
+ * int HYPERVISOR_set_segment_base(unsigned int which, unsigned long base)
+ *  @which == SEGBASE_*  ;  @base == 64-bit base address
+ * Returns 0 on success.
+ */
+#define SEGBASE_FS          0
+#define SEGBASE_GS_USER     1
+#define SEGBASE_GS_KERNEL   2
+#define SEGBASE_GS_USER_SEL 3 /* Set user %gs specified in base[15:0] */
+
+/*
+ * int HYPERVISOR_iret(void)
+ * All arguments are on the kernel stack, in the following format.
+ * Never returns if successful. Current kernel context is lost.
+ * The saved CS is mapped as follows:
+ *   RING0 -> RING3 kernel mode.
+ *   RING1 -> RING3 kernel mode.
+ *   RING2 -> RING3 kernel mode.
+ *   RING3 -> RING3 user mode.
+ * However RING0 indicates that the guest kernel should return to iteself
+ * directly with
+ *      orb   $3,1*8(%rsp)
+ *      iretq
+ * If flags contains VGCF_in_syscall:
+ *   Restore RAX, RIP, RFLAGS, RSP.
+ *   Discard R11, RCX, CS, SS.
+ * Otherwise:
+ *   Restore RAX, R11, RCX, CS:RIP, RFLAGS, SS:RSP.
+ * All other registers are saved on hypercall entry and restored to user.
+ */
+/* Guest exited in SYSCALL context? Return to guest with SYSRET? */
+#define _VGCF_in_syscall 8
+#define VGCF_in_syscall  (1<<_VGCF_in_syscall)
+#define VGCF_IN_SYSCALL  VGCF_in_syscall
+
+#ifndef __ASSEMBLY__
+
+struct iret_context {
+    /* Top of stack (%rsp at point of hypercall). */
+    uint64_t rax, r11, rcx, flags, rip, cs, rflags, rsp, ss;
+    /* Bottom of iret stack frame. */
+};
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+/* Anonymous union includes both 32- and 64-bit names (e.g., eax/rax). */
+#define __DECL_REG(name) union { \
+    uint64_t r ## name, e ## name; \
+    uint32_t _e ## name; \
+}
+#else
+/* Non-gcc sources must always use the proper 64-bit name (e.g., rax). */
+#define __DECL_REG(name) uint64_t r ## name
+#endif
+
+struct cpu_user_regs {
+    uint64_t r15;
+    uint64_t r14;
+    uint64_t r13;
+    uint64_t r12;
+    __DECL_REG(bp);
+    __DECL_REG(bx);
+    uint64_t r11;
+    uint64_t r10;
+    uint64_t r9;
+    uint64_t r8;
+    __DECL_REG(ax);
+    __DECL_REG(cx);
+    __DECL_REG(dx);
+    __DECL_REG(si);
+    __DECL_REG(di);
+    uint32_t error_code;    /* private */
+    uint32_t entry_vector;  /* private */
+    __DECL_REG(ip);
+    uint16_t cs, _pad0[1];
+    uint8_t  saved_upcall_mask;
+    uint8_t  _pad1[3];
+    __DECL_REG(flags);      /* rflags.IF == !saved_upcall_mask */
+    __DECL_REG(sp);
+    uint16_t ss, _pad2[3];
+    uint16_t es, _pad3[3];
+    uint16_t ds, _pad4[3];
+    uint16_t fs, _pad5[3]; /* Non-zero => takes precedence over fs_base.     */
+    uint16_t gs, _pad6[3]; /* Non-zero => takes precedence over gs_base_usr. */
+};
+DEFINE_GUEST_HANDLE_STRUCT(cpu_user_regs);
+
+#undef __DECL_REG
+
+#define xen_pfn_to_cr3(pfn) ((unsigned long)(pfn) << 12)
+#define xen_cr3_to_pfn(cr3) ((unsigned long)(cr3) >> 12)
+
+struct arch_vcpu_info {
+    unsigned long cr2;
+    unsigned long pad; /* sizeof(vcpu_info_t) == 64 */
+};
+
+typedef unsigned long xen_callback_t;
+
+#define XEN_CALLBACK(__cs, __rip)				\
+	((unsigned long)(__rip))
+
+#endif /* !__ASSEMBLY__ */
+
+
+#endif	/* __ASM_X86_XEN_INTERFACE_64_H */
diff --git a/include/asm-x86/xen/page.h b/include/asm-x86/xen/page.h
index 377c045..7b3835d 100644
--- a/include/asm-x86/xen/page.h
+++ b/include/asm-x86/xen/page.h
@@ -124,7 +124,7 @@
 
 static inline unsigned long pte_mfn(pte_t pte)
 {
-	return (pte.pte & PTE_MASK) >> PAGE_SHIFT;
+	return (pte.pte & PTE_PFN_MASK) >> PAGE_SHIFT;
 }
 
 static inline pte_t mfn_pte(unsigned long page_nr, pgprot_t pgprot)
@@ -148,13 +148,17 @@
 }
 
 #define pmd_val_ma(v) ((v).pmd)
+#ifdef __PAGETABLE_PUD_FOLDED
 #define pud_val_ma(v) ((v).pgd.pgd)
+#else
+#define pud_val_ma(v) ((v).pud)
+#endif
 #define __pmd_ma(x)	((pmd_t) { (x) } )
 
 #define pgd_val_ma(x)	((x).pgd)
 
 
-xmaddr_t arbitrary_virt_to_machine(unsigned long address);
+xmaddr_t arbitrary_virt_to_machine(void *address);
 void make_lowmem_page_readonly(void *vaddr);
 void make_lowmem_page_readwrite(void *vaddr);
 
diff --git a/include/linux/async_tx.h b/include/linux/async_tx.h
index eb640f0..0f50d4c 100644
--- a/include/linux/async_tx.h
+++ b/include/linux/async_tx.h
@@ -101,21 +101,14 @@
 
 /**
  * async_tx_sync_epilog - actions to take if an operation is run synchronously
- * @flags: async_tx flags
- * @depend_tx: transaction depends on depend_tx
  * @cb_fn: function to call when the transaction completes
  * @cb_fn_param: parameter to pass to the callback routine
  */
 static inline void
-async_tx_sync_epilog(unsigned long flags,
-	struct dma_async_tx_descriptor *depend_tx,
-	dma_async_tx_callback cb_fn, void *cb_fn_param)
+async_tx_sync_epilog(dma_async_tx_callback cb_fn, void *cb_fn_param)
 {
 	if (cb_fn)
 		cb_fn(cb_fn_param);
-
-	if (depend_tx && (flags & ASYNC_TX_DEP_ACK))
-		async_tx_ack(depend_tx);
 }
 
 void
@@ -152,4 +145,6 @@
 async_trigger_callback(enum async_tx_flags flags,
 	struct dma_async_tx_descriptor *depend_tx,
 	dma_async_tx_callback cb_fn, void *cb_fn_param);
+
+void async_tx_quiesce(struct dma_async_tx_descriptor **tx);
 #endif /* _ASYNC_TX_H_ */
diff --git a/include/linux/auxvec.h b/include/linux/auxvec.h
index ad895455..0da17d1 100644
--- a/include/linux/auxvec.h
+++ b/include/linux/auxvec.h
@@ -26,8 +26,10 @@
 
 #define AT_SECURE 23   /* secure mode boolean */
 
+#define AT_EXECFN  31	/* filename of program */
 #ifdef __KERNEL__
-#define AT_VECTOR_SIZE_BASE (14 + 2) /* NEW_AUX_ENT entries in auxiliary table */
+#define AT_VECTOR_SIZE_BASE 17 /* NEW_AUX_ENT entries in auxiliary table */
+  /* number of "#define AT_.*" above, minus {AT_NULL, AT_IGNORE, AT_NOTELF} */
 #endif
 
 #endif /* _LINUX_AUXVEC_H */
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index e7e91db..2270ca5 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -4,9 +4,6 @@
  *  Copyright (C) 2001 Russell King
  *            (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
  *            
- *
- * $Id: cpufreq.h,v 1.36 2003/01/20 17:31:48 db Exp $
- *
  * 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.
diff --git a/include/linux/dca.h b/include/linux/dca.h
index af61cd1..b00a753 100644
--- a/include/linux/dca.h
+++ b/include/linux/dca.h
@@ -10,6 +10,7 @@
 #define DCA_PROVIDER_REMOVE  0x0002
 
 struct dca_provider {
+	struct list_head	node;
 	struct dca_ops		*ops;
 	struct device 		*cd;
 	int			 id;
@@ -18,7 +19,9 @@
 struct dca_ops {
 	int	(*add_requester)    (struct dca_provider *, struct device *);
 	int	(*remove_requester) (struct dca_provider *, struct device *);
-	u8	(*get_tag)	    (struct dca_provider *, int cpu);
+	u8	(*get_tag)	    (struct dca_provider *, struct device *,
+				     int cpu);
+	int	(*dev_managed)      (struct dca_provider *, struct device *);
 };
 
 struct dca_provider *alloc_dca_provider(struct dca_ops *ops, int priv_size);
@@ -32,9 +35,11 @@
 }
 
 /* Requester API */
+#define DCA_GET_TAG_TWO_ARGS
 int dca_add_requester(struct device *dev);
 int dca_remove_requester(struct device *dev);
 u8 dca_get_tag(int cpu);
+u8 dca3_get_tag(struct device *dev, int cpu);
 
 /* internal stuff */
 int __init dca_sysfs_init(void);
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index 7266124..e1a6c04 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -26,6 +26,8 @@
 	unsigned long size;
 };
 
+extern struct dentry *arch_debugfs_dir;
+
 #if defined(CONFIG_DEBUG_FS)
 
 /* declared over in file.c */
@@ -42,6 +44,7 @@
 				      const char *dest);
 
 void debugfs_remove(struct dentry *dentry);
+void debugfs_remove_recursive(struct dentry *dentry);
 
 struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
                 struct dentry *new_dir, const char *new_name);
@@ -99,6 +102,9 @@
 static inline void debugfs_remove(struct dentry *dentry)
 { }
 
+static inline void debugfs_remove_recursive(struct dentry *dentry)
+{ }
+
 static inline struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
                 struct dentry *new_dir, char *new_name)
 {
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index 0d8d419..a90222e 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -9,11 +9,13 @@
 #define _LINUX_DEVICE_MAPPER_H
 
 #include <linux/bio.h>
+#include <linux/blkdev.h>
 
 struct dm_target;
 struct dm_table;
 struct dm_dev;
 struct mapped_device;
+struct bio_vec;
 
 typedef enum { STATUSTYPE_INFO, STATUSTYPE_TABLE } status_type_t;
 
@@ -72,6 +74,9 @@
 			    struct file *filp, unsigned int cmd,
 			    unsigned long arg);
 
+typedef int (*dm_merge_fn) (struct dm_target *ti, struct bvec_merge_data *bvm,
+			    struct bio_vec *biovec, int max_size);
+
 void dm_error(const char *message);
 
 /*
@@ -107,6 +112,7 @@
 	dm_status_fn status;
 	dm_message_fn message;
 	dm_ioctl_fn ioctl;
+	dm_merge_fn merge;
 };
 
 struct io_restrictions {
diff --git a/include/linux/device.h b/include/linux/device.h
index f71a78d..d24a47f 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -16,6 +16,7 @@
 #include <linux/kobject.h>
 #include <linux/klist.h>
 #include <linux/list.h>
+#include <linux/lockdep.h>
 #include <linux/compiler.h>
 #include <linux/types.h>
 #include <linux/module.h>
@@ -24,17 +25,13 @@
 #include <asm/atomic.h>
 #include <asm/device.h>
 
-#define DEVICE_NAME_SIZE	50
-/* DEVICE_NAME_HALF is really less than half to accommodate slop */
-#define DEVICE_NAME_HALF	__stringify(20)
-#define DEVICE_ID_SIZE		32
-#define BUS_ID_SIZE		KOBJ_NAME_LEN
-
+#define BUS_ID_SIZE		20
 
 struct device;
 struct device_driver;
 struct driver_private;
 struct class;
+struct class_private;
 struct bus_type;
 struct bus_type_private;
 
@@ -186,13 +183,9 @@
 	const char		*name;
 	struct module		*owner;
 
-	struct kset		subsys;
-	struct list_head	devices;
-	struct list_head	interfaces;
-	struct kset		class_dirs;
-	struct semaphore	sem; /* locks children, devices, interfaces */
 	struct class_attribute		*class_attrs;
 	struct device_attribute		*dev_attrs;
+	struct kobject			*dev_kobj;
 
 	int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
 
@@ -203,13 +196,28 @@
 	int (*resume)(struct device *dev);
 
 	struct pm_ops *pm;
+	struct class_private *p;
 };
 
-extern int __must_check class_register(struct class *class);
+extern struct kobject *sysfs_dev_block_kobj;
+extern struct kobject *sysfs_dev_char_kobj;
+extern int __must_check __class_register(struct class *class,
+					 struct lock_class_key *key);
 extern void class_unregister(struct class *class);
-extern int class_for_each_device(struct class *class, void *data,
+
+/* This is a #define to keep the compiler from merging different
+ * instances of the __key variable */
+#define class_register(class)			\
+({						\
+	static struct lock_class_key __key;	\
+	__class_register(class, &__key);	\
+})
+
+extern int class_for_each_device(struct class *class, struct device *start,
+				 void *data,
 				 int (*fn)(struct device *dev, void *data));
-extern struct device *class_find_device(struct class *class, void *data,
+extern struct device *class_find_device(struct class *class,
+					struct device *start, void *data,
 					int (*match)(struct device *, void *));
 
 struct class_attribute {
@@ -237,9 +245,19 @@
 extern int __must_check class_interface_register(struct class_interface *);
 extern void class_interface_unregister(struct class_interface *);
 
-extern struct class *class_create(struct module *owner, const char *name);
+extern struct class * __must_check __class_create(struct module *owner,
+						  const char *name,
+						  struct lock_class_key *key);
 extern void class_destroy(struct class *cls);
 
+/* This is a #define to keep the compiler from merging different
+ * instances of the __key variable */
+#define class_create(owner, name)		\
+({						\
+	static struct lock_class_key __key;	\
+	__class_create(owner, name, &__key);	\
+})
+
 /*
  * The type of device, "struct device" is embedded in. A class
  * or bus can contain devices of different types
@@ -468,14 +486,10 @@
 					  const char *fmt,
 					  va_list vargs);
 extern struct device *device_create(struct class *cls, struct device *parent,
-				    dev_t devt, const char *fmt, ...)
-				    __attribute__((format(printf, 4, 5)));
-extern struct device *device_create_drvdata(struct class *cls,
-					    struct device *parent,
-					    dev_t devt,
-					    void *drvdata,
-					    const char *fmt, ...)
+				    dev_t devt, void *drvdata,
+				    const char *fmt, ...)
 				    __attribute__((format(printf, 5, 6)));
+#define device_create_drvdata	device_create
 extern void device_destroy(struct class *cls, dev_t devt);
 
 /*
diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h
index b03c41b..28c2940 100644
--- a/include/linux/dm-ioctl.h
+++ b/include/linux/dm-ioctl.h
@@ -256,9 +256,9 @@
 #define DM_DEV_SET_GEOMETRY	_IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
 
 #define DM_VERSION_MAJOR	4
-#define DM_VERSION_MINOR	13
+#define DM_VERSION_MINOR	14
 #define DM_VERSION_PATCHLEVEL	0
-#define DM_VERSION_EXTRA	"-ioctl (2007-10-18)"
+#define DM_VERSION_EXTRA	"-ioctl (2008-04-23)"
 
 /* Status bits */
 #define DM_READONLY_FLAG	(1 << 0) /* In/Out */
diff --git a/include/linux/dma-attrs.h b/include/linux/dma-attrs.h
index 1677e2b..71ad34e 100644
--- a/include/linux/dma-attrs.h
+++ b/include/linux/dma-attrs.h
@@ -12,6 +12,7 @@
  */
 enum dma_attr {
 	DMA_ATTR_WRITE_BARRIER,
+	DMA_ATTR_WEAK_ORDERING,
 	DMA_ATTR_MAX,
 };
 
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index d08a5c5..adb0b08 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -89,10 +89,23 @@
 	DMA_MEMSET,
 	DMA_MEMCPY_CRC32C,
 	DMA_INTERRUPT,
+	DMA_SLAVE,
 };
 
 /* last transaction type for creation of the capabilities mask */
-#define DMA_TX_TYPE_END (DMA_INTERRUPT + 1)
+#define DMA_TX_TYPE_END (DMA_SLAVE + 1)
+
+/**
+ * enum dma_slave_width - DMA slave register access width.
+ * @DMA_SLAVE_WIDTH_8BIT: Do 8-bit slave register accesses
+ * @DMA_SLAVE_WIDTH_16BIT: Do 16-bit slave register accesses
+ * @DMA_SLAVE_WIDTH_32BIT: Do 32-bit slave register accesses
+ */
+enum dma_slave_width {
+	DMA_SLAVE_WIDTH_8BIT,
+	DMA_SLAVE_WIDTH_16BIT,
+	DMA_SLAVE_WIDTH_32BIT,
+};
 
 /**
  * enum dma_ctrl_flags - DMA flags to augment operation preparation,
@@ -102,10 +115,14 @@
  * @DMA_CTRL_ACK - the descriptor cannot be reused until the client
  * 	acknowledges receipt, i.e. has has a chance to establish any
  * 	dependency chains
+ * @DMA_COMPL_SKIP_SRC_UNMAP - set to disable dma-unmapping the source buffer(s)
+ * @DMA_COMPL_SKIP_DEST_UNMAP - set to disable dma-unmapping the destination(s)
  */
 enum dma_ctrl_flags {
 	DMA_PREP_INTERRUPT = (1 << 0),
 	DMA_CTRL_ACK = (1 << 1),
+	DMA_COMPL_SKIP_SRC_UNMAP = (1 << 2),
+	DMA_COMPL_SKIP_DEST_UNMAP = (1 << 3),
 };
 
 /**
@@ -115,6 +132,32 @@
 typedef struct { DECLARE_BITMAP(bits, DMA_TX_TYPE_END); } dma_cap_mask_t;
 
 /**
+ * struct dma_slave - Information about a DMA slave
+ * @dev: device acting as DMA slave
+ * @dma_dev: required DMA master device. If non-NULL, the client can not be
+ *	bound to other masters than this.
+ * @tx_reg: physical address of data register used for
+ *	memory-to-peripheral transfers
+ * @rx_reg: physical address of data register used for
+ *	peripheral-to-memory transfers
+ * @reg_width: peripheral register width
+ *
+ * If dma_dev is non-NULL, the client can not be bound to other DMA
+ * masters than the one corresponding to this device. The DMA master
+ * driver may use this to determine if there is controller-specific
+ * data wrapped around this struct. Drivers of platform code that sets
+ * the dma_dev field must therefore make sure to use an appropriate
+ * controller-specific dma slave structure wrapping this struct.
+ */
+struct dma_slave {
+	struct device		*dev;
+	struct device		*dma_dev;
+	dma_addr_t		tx_reg;
+	dma_addr_t		rx_reg;
+	enum dma_slave_width	reg_width;
+};
+
+/**
  * struct dma_chan_percpu - the per-CPU part of struct dma_chan
  * @refcount: local_t used for open-coded "bigref" counting
  * @memcpy_count: transaction counter
@@ -139,6 +182,7 @@
  * @rcu: the DMA channel's RCU head
  * @device_node: used to add this to the device chan list
  * @local: per-cpu pointer to a struct dma_chan_percpu
+ * @client-count: how many clients are using this channel
  */
 struct dma_chan {
 	struct dma_device *device;
@@ -154,6 +198,7 @@
 
 	struct list_head device_node;
 	struct dma_chan_percpu *local;
+	int client_count;
 };
 
 #define to_dma_chan(p) container_of(p, struct dma_chan, dev)
@@ -202,11 +247,14 @@
  * @event_callback: func ptr to call when something happens
  * @cap_mask: only return channels that satisfy the requested capabilities
  *  a value of zero corresponds to any capability
+ * @slave: data for preparing slave transfer. Must be non-NULL iff the
+ *  DMA_SLAVE capability is requested.
  * @global_node: list_head for global dma_client_list
  */
 struct dma_client {
 	dma_event_callback	event_callback;
 	dma_cap_mask_t		cap_mask;
+	struct dma_slave	*slave;
 	struct list_head	global_node;
 };
 
@@ -263,6 +311,8 @@
  * @device_prep_dma_zero_sum: prepares a zero_sum operation
  * @device_prep_dma_memset: prepares a memset operation
  * @device_prep_dma_interrupt: prepares an end of chain interrupt operation
+ * @device_prep_slave_sg: prepares a slave dma operation
+ * @device_terminate_all: terminate all pending operations
  * @device_issue_pending: push pending transactions to hardware
  */
 struct dma_device {
@@ -279,7 +329,8 @@
 	int dev_id;
 	struct device *dev;
 
-	int (*device_alloc_chan_resources)(struct dma_chan *chan);
+	int (*device_alloc_chan_resources)(struct dma_chan *chan,
+			struct dma_client *client);
 	void (*device_free_chan_resources)(struct dma_chan *chan);
 
 	struct dma_async_tx_descriptor *(*device_prep_dma_memcpy)(
@@ -297,6 +348,12 @@
 	struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)(
 		struct dma_chan *chan, unsigned long flags);
 
+	struct dma_async_tx_descriptor *(*device_prep_slave_sg)(
+		struct dma_chan *chan, struct scatterlist *sgl,
+		unsigned int sg_len, enum dma_data_direction direction,
+		unsigned long flags);
+	void (*device_terminate_all)(struct dma_chan *chan);
+
 	enum dma_status (*device_is_tx_complete)(struct dma_chan *chan,
 			dma_cookie_t cookie, dma_cookie_t *last,
 			dma_cookie_t *used);
@@ -318,16 +375,14 @@
 void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx,
 	struct dma_chan *chan);
 
-static inline void
-async_tx_ack(struct dma_async_tx_descriptor *tx)
+static inline void async_tx_ack(struct dma_async_tx_descriptor *tx)
 {
 	tx->flags |= DMA_CTRL_ACK;
 }
 
-static inline int
-async_tx_test_ack(struct dma_async_tx_descriptor *tx)
+static inline bool async_tx_test_ack(struct dma_async_tx_descriptor *tx)
 {
-	return tx->flags & DMA_CTRL_ACK;
+	return (tx->flags & DMA_CTRL_ACK) == DMA_CTRL_ACK;
 }
 
 #define first_dma_cap(mask) __first_dma_cap(&(mask))
diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h
new file mode 100644
index 0000000..04d217b
--- /dev/null
+++ b/include/linux/dw_dmac.h
@@ -0,0 +1,62 @@
+/*
+ * Driver for the Synopsys DesignWare DMA Controller (aka DMACA on
+ * AVR32 systems.)
+ *
+ * Copyright (C) 2007 Atmel 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.
+ */
+#ifndef DW_DMAC_H
+#define DW_DMAC_H
+
+#include <linux/dmaengine.h>
+
+/**
+ * struct dw_dma_platform_data - Controller configuration parameters
+ * @nr_channels: Number of channels supported by hardware (max 8)
+ */
+struct dw_dma_platform_data {
+	unsigned int	nr_channels;
+};
+
+/**
+ * struct dw_dma_slave - Controller-specific information about a slave
+ * @slave: Generic information about the slave
+ * @ctl_lo: Platform-specific initializer for the CTL_LO register
+ * @cfg_hi: Platform-specific initializer for the CFG_HI register
+ * @cfg_lo: Platform-specific initializer for the CFG_LO register
+ */
+struct dw_dma_slave {
+	struct dma_slave	slave;
+	u32			cfg_hi;
+	u32			cfg_lo;
+};
+
+/* Platform-configurable bits in CFG_HI */
+#define DWC_CFGH_FCMODE		(1 << 0)
+#define DWC_CFGH_FIFO_MODE	(1 << 1)
+#define DWC_CFGH_PROTCTL(x)	((x) << 2)
+#define DWC_CFGH_SRC_PER(x)	((x) << 7)
+#define DWC_CFGH_DST_PER(x)	((x) << 11)
+
+/* Platform-configurable bits in CFG_LO */
+#define DWC_CFGL_PRIO(x)	((x) << 5)	/* priority */
+#define DWC_CFGL_LOCK_CH_XFER	(0 << 12)	/* scope of LOCK_CH */
+#define DWC_CFGL_LOCK_CH_BLOCK	(1 << 12)
+#define DWC_CFGL_LOCK_CH_XACT	(2 << 12)
+#define DWC_CFGL_LOCK_BUS_XFER	(0 << 14)	/* scope of LOCK_BUS */
+#define DWC_CFGL_LOCK_BUS_BLOCK	(1 << 14)
+#define DWC_CFGL_LOCK_BUS_XACT	(2 << 14)
+#define DWC_CFGL_LOCK_CH	(1 << 15)	/* channel lockout */
+#define DWC_CFGL_LOCK_BUS	(1 << 16)	/* busmaster lockout */
+#define DWC_CFGL_HS_DST_POL	(1 << 18)	/* dst handshake active low */
+#define DWC_CFGL_HS_SRC_POL	(1 << 19)	/* src handshake active low */
+
+static inline struct dw_dma_slave *to_dw_dma_slave(struct dma_slave *slave)
+{
+	return container_of(slave, struct dw_dma_slave, slave);
+}
+
+#endif /* DW_DMAC_H */
diff --git a/include/linux/eisa.h b/include/linux/eisa.h
index fe806b6..e61c0be 100644
--- a/include/linux/eisa.h
+++ b/include/linux/eisa.h
@@ -40,7 +40,7 @@
 	u64                   dma_mask;
 	struct device         dev; /* generic device */
 #ifdef CONFIG_EISA_NAMES
-	char		      pretty_name[DEVICE_NAME_SIZE];
+	char		      pretty_name[50];
 #endif
 };
 
diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h
index 9bc045b..8300cab 100644
--- a/include/linux/fs_enet_pd.h
+++ b/include/linux/fs_enet_pd.h
@@ -103,10 +103,6 @@
 	struct fs_mii_bit 	mdio_dir;
 	struct fs_mii_bit 	mdio_dat;
 	struct fs_mii_bit	mdc_dat;
-	int mdio_port;	/* port & bit for MDIO */
-	int mdio_bit;
-	int mdc_port;	/* port & bit for MDC  */
-	int mdc_bit;
 	int delay;	/* delay in us         */
 	int irq[32]; 	/* irqs per phy's */
 };
@@ -135,11 +131,7 @@
 	u32 device_flags;
 
 	int phy_addr;		/* the phy address (-1 no phy) */
-#ifdef CONFIG_PPC_CPM_NEW_BINDING
 	char bus_id[16];
-#else
-	const char*	bus_id;
-#endif
 	int phy_irq;		/* the phy irq (if it exists)  */
 
 	const struct fs_mii_bus_info *bus_info;
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index c415a49..4e625e0 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -69,6 +69,7 @@
 #define FSL_GIANFAR_DEV_HAS_VLAN		0x00000020
 #define FSL_GIANFAR_DEV_HAS_EXTENDED_HASH	0x00000040
 #define FSL_GIANFAR_DEV_HAS_PADDING		0x00000080
+#define FSL_GIANFAR_DEV_HAS_MAGIC_PACKET	0x00000100
 
 /* Flags in gianfar_platform_data */
 #define FSL_GIANFAR_BRD_HAS_PHY_INTR	0x00000001 /* set or use a timer */
@@ -125,4 +126,10 @@
 	int(*voltage_set)(int slot, int vcc, int vpp);
 };
 
+/* Returns non-zero if the current suspend operation would
+ * lead to a deep sleep (i.e. power removed from the core,
+ * instead of just the clock).
+ */
+int fsl_deep_sleep(void);
+
 #endif /* _FSL_DEVICE_H_ */
diff --git a/include/linux/gameport.h b/include/linux/gameport.h
index afad952..f64e29c 100644
--- a/include/linux/gameport.h
+++ b/include/linux/gameport.h
@@ -68,7 +68,6 @@
 
 int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode);
 void gameport_close(struct gameport *gameport);
-void gameport_rescan(struct gameport *gameport);
 
 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
 
diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h
index c6d3a9d..ec6ecd7 100644
--- a/include/linux/gpio_keys.h
+++ b/include/linux/gpio_keys.h
@@ -9,6 +9,7 @@
 	char *desc;
 	int type;		/* input event type (EV_KEY, EV_SW) */
 	int wakeup;		/* configure the button as a wake-up source */
+	int debounce_interval;	/* debounce ticks interval in msecs */
 };
 
 struct gpio_keys_platform_data {
diff --git a/include/linux/hid.h b/include/linux/hid.h
index fe56b86..ac4e678 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -512,7 +512,7 @@
 
 /* Applications from HID Usage Tables 4/8/99 Version 1.1 */
 /* We ignore a few input applications that are not widely used */
-#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001))
+#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001) || (a == 0x000d0002))
 
 /* HID core API */
 
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 4726126..d67ccca 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -178,6 +178,7 @@
 	ide_ack_intr_t	*ack_intr;		/* acknowledge interrupt */
 	hwif_chipset_t  chipset;
 	struct device	*dev, *parent;
+	unsigned long	config;
 } hw_regs_t;
 
 void ide_init_port_data(struct hwif_s *, unsigned int);
@@ -307,7 +308,65 @@
 struct ide_acpi_hwif_link;
 #endif
 
-typedef struct ide_drive_s {
+/* ATAPI device flags */
+enum {
+	IDE_AFLAG_DRQ_INTERRUPT		= (1 << 0),
+	IDE_AFLAG_MEDIA_CHANGED		= (1 << 1),
+
+	/* ide-cd */
+	/* Drive cannot lock the door. */
+	IDE_AFLAG_NO_DOORLOCK		= (1 << 2),
+	/* Drive cannot eject the disc. */
+	IDE_AFLAG_NO_EJECT		= (1 << 3),
+	/* Drive is a pre ATAPI 1.2 drive. */
+	IDE_AFLAG_PRE_ATAPI12		= (1 << 4),
+	/* TOC addresses are in BCD. */
+	IDE_AFLAG_TOCADDR_AS_BCD	= (1 << 5),
+	/* TOC track numbers are in BCD. */
+	IDE_AFLAG_TOCTRACKS_AS_BCD	= (1 << 6),
+	/*
+	 * Drive does not provide data in multiples of SECTOR_SIZE
+	 * when more than one interrupt is needed.
+	 */
+	IDE_AFLAG_LIMIT_NFRAMES		= (1 << 7),
+	/* Seeking in progress. */
+	IDE_AFLAG_SEEKING		= (1 << 8),
+	/* Saved TOC information is current. */
+	IDE_AFLAG_TOC_VALID		= (1 << 9),
+	/* We think that the drive door is locked. */
+	IDE_AFLAG_DOOR_LOCKED		= (1 << 10),
+	/* SET_CD_SPEED command is unsupported. */
+	IDE_AFLAG_NO_SPEED_SELECT	= (1 << 11),
+	IDE_AFLAG_VERTOS_300_SSD	= (1 << 12),
+	IDE_AFLAG_VERTOS_600_ESD	= (1 << 13),
+	IDE_AFLAG_SANYO_3CD		= (1 << 14),
+	IDE_AFLAG_FULL_CAPS_PAGE	= (1 << 15),
+	IDE_AFLAG_PLAY_AUDIO_OK		= (1 << 16),
+	IDE_AFLAG_LE_SPEED_FIELDS	= (1 << 17),
+
+	/* ide-floppy */
+	/* Format in progress */
+	IDE_AFLAG_FORMAT_IN_PROGRESS	= (1 << 18),
+	/* Avoid commands not supported in Clik drive */
+	IDE_AFLAG_CLIK_DRIVE		= (1 << 19),
+	/* Requires BH algorithm for packets */
+	IDE_AFLAG_ZIP_DRIVE		= (1 << 20),
+
+	/* ide-tape */
+	IDE_AFLAG_IGNORE_DSC		= (1 << 21),
+	/* 0 When the tape position is unknown */
+	IDE_AFLAG_ADDRESS_VALID		= (1 <<	22),
+	/* Device already opened */
+	IDE_AFLAG_BUSY			= (1 << 23),
+	/* Attempt to auto-detect the current user block size */
+	IDE_AFLAG_DETECT_BS		= (1 << 24),
+	/* Currently on a filemark */
+	IDE_AFLAG_FILEMARK		= (1 << 25),
+	/* 0 = no tape is loaded, so we don't rewind after ejecting */
+	IDE_AFLAG_MEDIUM_PRESENT	= (1 << 26)
+};
+
+struct ide_drive_s {
 	char		name[4];	/* drive name, such as "hda" */
         char            driver_req[10];	/* requests specific driver */
 
@@ -355,7 +414,6 @@
 	unsigned nodma		: 1;	/* disallow DMA */
 	unsigned remap_0_to_1	: 1;	/* 0=noremap, 1=remap 0->1 (for EZDrive) */
 	unsigned blocked        : 1;	/* 1=powermanagment told us not to do anything, so sleep nicely */
-	unsigned vdma		: 1;	/* 1=doing PIO over DMA 0=doing normal DMA */
 	unsigned scsi		: 1;	/* 0=default, 1=ide-scsi emulation */
 	unsigned sleeping	: 1;	/* 1=sleeping & sleep field valid */
 	unsigned post_reset	: 1;
@@ -400,7 +458,14 @@
 	struct list_head list;
 	struct device	gendev;
 	struct completion gendev_rel_comp;	/* to deal with device release() */
-} ide_drive_t;
+
+	/* callback for packet commands */
+	void (*pc_callback)(struct ide_drive_s *);
+
+	unsigned long atapi_flags;
+};
+
+typedef struct ide_drive_s ide_drive_t;
 
 #define to_ide_device(dev)container_of(dev, ide_drive_t, gendev)
 
@@ -408,8 +473,28 @@
     ((1<<ide_pci)|(1<<ide_cmd646)|(1<<ide_ali14xx))
 #define IDE_CHIPSET_IS_PCI(c)	((IDE_CHIPSET_PCI_MASK >> (c)) & 1)
 
+struct ide_task_s;
 struct ide_port_info;
 
+struct ide_tp_ops {
+	void	(*exec_command)(struct hwif_s *, u8);
+	u8	(*read_status)(struct hwif_s *);
+	u8	(*read_altstatus)(struct hwif_s *);
+	u8	(*read_sff_dma_status)(struct hwif_s *);
+
+	void	(*set_irq)(struct hwif_s *, int);
+
+	void	(*tf_load)(ide_drive_t *, struct ide_task_s *);
+	void	(*tf_read)(ide_drive_t *, struct ide_task_s *);
+
+	void	(*input_data)(ide_drive_t *, struct request *, void *,
+			      unsigned int);
+	void	(*output_data)(ide_drive_t *, struct request *, void *,
+			       unsigned int);
+};
+
+extern const struct ide_tp_ops default_tp_ops;
+
 struct ide_port_ops {
 	/* host specific initialization of a device */
 	void	(*init_dev)(ide_drive_t *);
@@ -447,8 +532,6 @@
 	void	(*dma_timeout)(struct ide_drive_s *);
 };
 
-struct ide_task_s;
-
 typedef struct hwif_s {
 	struct hwif_s *next;		/* for linked-list in ide_hwgroup_t */
 	struct hwif_s *mate;		/* other hwif from same PCI chip */
@@ -486,22 +569,12 @@
 
 	void (*rw_disk)(ide_drive_t *, struct request *);
 
+	const struct ide_tp_ops		*tp_ops;
 	const struct ide_port_ops	*port_ops;
 	const struct ide_dma_ops	*dma_ops;
 
-	void (*tf_load)(ide_drive_t *, struct ide_task_s *);
-	void (*tf_read)(ide_drive_t *, struct ide_task_s *);
-
-	void (*input_data)(ide_drive_t *, struct request *, void *, unsigned);
-	void (*output_data)(ide_drive_t *, struct request *, void *, unsigned);
-
 	void (*ide_dma_clear_irq)(ide_drive_t *drive);
 
-	void (*OUTB)(u8 addr, unsigned long port);
-	void (*OUTBSYNC)(struct hwif_s *hwif, u8 addr, unsigned long port);
-
-	u8  (*INB)(unsigned long port);
-
 	/* dma physical region descriptor table (cpu view) */
 	unsigned int	*dmatable_cpu;
 	/* dma physical region descriptor table (dma view) */
@@ -524,8 +597,6 @@
 	int		irq;		/* our irq number */
 
 	unsigned long	dma_base;	/* base addr for dma ports */
-	unsigned long	dma_command;	/* dma command register */
-	unsigned long	dma_status;	/* dma status register */
 
 	unsigned long	config_data;	/* for use by chipset-specific code */
 	unsigned long	select_data;	/* for use by chipset-specific code */
@@ -552,6 +623,11 @@
 #endif
 } ____cacheline_internodealigned_in_smp ide_hwif_t;
 
+struct ide_host {
+	ide_hwif_t	*ports[MAX_HWIFS];
+	unsigned int	n_ports;
+};
+
 /*
  *  internal ide interrupt handler type
  */
@@ -611,8 +687,6 @@
 	PC_FLAG_WRITING			= (1 << 6),
 	/* command timed out */
 	PC_FLAG_TIMEDOUT		= (1 << 7),
-	PC_FLAG_ZIP_DRIVE		= (1 << 8),
-	PC_FLAG_DRQ_INTERRUPT		= (1 << 9),
 };
 
 struct ide_atapi_pc {
@@ -646,8 +720,6 @@
 	 */
 	u8 pc_buf[256];
 
-	void (*callback)(ide_drive_t *);
-
 	/* idetape only */
 	struct idetape_bh *bh;
 	char *b_data;
@@ -807,13 +879,6 @@
 extern int ide_vlb_clk;
 extern int ide_pci_clk;
 
-ide_hwif_t *ide_find_port_slot(const struct ide_port_info *);
-
-static inline ide_hwif_t *ide_find_port(void)
-{
-	return ide_find_port_slot(NULL);
-}
-
 extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs);
 int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq,
 			     int uptodate, int nr_sectors);
@@ -884,6 +949,7 @@
 	IDE_TFLAG_IN_HOB		= IDE_TFLAG_IN_HOB_FEATURE |
 					  IDE_TFLAG_IN_HOB_NSECT |
 					  IDE_TFLAG_IN_HOB_LBA,
+	IDE_TFLAG_IN_FEATURE		= (1 << 1),
 	IDE_TFLAG_IN_NSECT		= (1 << 25),
 	IDE_TFLAG_IN_LBAL		= (1 << 26),
 	IDE_TFLAG_IN_LBAM		= (1 << 27),
@@ -948,9 +1014,25 @@
 
 void ide_tf_dump(const char *, struct ide_taskfile *);
 
+void ide_exec_command(ide_hwif_t *, u8);
+u8 ide_read_status(ide_hwif_t *);
+u8 ide_read_altstatus(ide_hwif_t *);
+u8 ide_read_sff_dma_status(ide_hwif_t *);
+
+void ide_set_irq(ide_hwif_t *, int);
+
+void ide_tf_load(ide_drive_t *, ide_task_t *);
+void ide_tf_read(ide_drive_t *, ide_task_t *);
+
+void ide_input_data(ide_drive_t *, struct request *, void *, unsigned int);
+void ide_output_data(ide_drive_t *, struct request *, void *, unsigned int);
+
 extern void SELECT_DRIVE(ide_drive_t *);
 void SELECT_MASK(ide_drive_t *, int);
 
+u8 ide_read_error(ide_drive_t *);
+void ide_read_bcount_and_ireason(ide_drive_t *, u16 *, u8 *);
+
 extern int drive_is_ready(ide_drive_t *);
 
 void ide_pktcmd_tf_load(ide_drive_t *, u32, u16, u8);
@@ -1000,12 +1082,15 @@
 #define ide_pci_register_driver(d) pci_register_driver(d)
 #endif
 
-void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *, int, u8 *);
+void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *, int,
+			 hw_regs_t *, hw_regs_t **);
 void ide_setup_pci_noise(struct pci_dev *, const struct ide_port_info *);
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
 int ide_pci_set_master(struct pci_dev *, const char *);
 unsigned long ide_pci_dma_base(ide_hwif_t *, const struct ide_port_info *);
+extern const struct ide_dma_ops sff_dma_ops;
+int ide_pci_check_simplex(ide_hwif_t *, const struct ide_port_info *);
 int ide_hwif_setup_dma(ide_hwif_t *, const struct ide_port_info *);
 #else
 static inline int ide_hwif_setup_dma(ide_hwif_t *hwif,
@@ -1015,10 +1100,6 @@
 }
 #endif
 
-extern void default_hwif_iops(ide_hwif_t *);
-extern void default_hwif_mmiops(ide_hwif_t *);
-extern void default_hwif_transport(ide_hwif_t *);
-
 typedef struct ide_pci_enablebit_s {
 	u8	reg;	/* byte pci reg holding the enable-bit */
 	u8	mask;	/* mask to isolate the enable-bit */
@@ -1081,7 +1162,6 @@
 	IDE_HFLAG_IO_32BIT		= (1 << 24),
 	/* unmask IRQs */
 	IDE_HFLAG_UNMASK_IRQS		= (1 << 25),
-	IDE_HFLAG_ABUSE_SET_DMA_MODE	= (1 << 26),
 	/* serialize ports if DMA is possible (for sl82c105) */
 	IDE_HFLAG_SERIALIZE_DMA		= (1 << 27),
 	/* force host out of "simplex" mode */
@@ -1092,8 +1172,6 @@
 	IDE_HFLAG_NO_IO_32BIT		= (1 << 30),
 	/* never unmask IRQs */
 	IDE_HFLAG_NO_UNMASK_IRQS	= (1 << 31),
-	/* host uses VDMA (disabled for now) */
-	IDE_HFLAG_VDMA			= 0,
 };
 
 #ifdef CONFIG_BLK_DEV_OFFBOARD
@@ -1110,6 +1188,7 @@
 	int			(*init_dma)(ide_hwif_t *,
 					    const struct ide_port_info *);
 
+	const struct ide_tp_ops		*tp_ops;
 	const struct ide_port_ops	*port_ops;
 	const struct ide_dma_ops	*dma_ops;
 
@@ -1163,7 +1242,6 @@
 extern int ide_build_dmatable(ide_drive_t *, struct request *);
 int ide_allocate_dma_engine(ide_hwif_t *);
 void ide_release_dma_engine(ide_hwif_t *);
-void ide_setup_dma(ide_hwif_t *, unsigned long);
 
 void ide_dma_host_set(ide_drive_t *, int);
 extern int ide_dma_setup(ide_drive_t *);
@@ -1217,8 +1295,14 @@
 
 void ide_port_apply_params(ide_hwif_t *);
 
-int ide_device_add_all(u8 *idx, const struct ide_port_info *);
-int ide_device_add(u8 idx[4], const struct ide_port_info *);
+struct ide_host *ide_host_alloc_all(const struct ide_port_info *, hw_regs_t **);
+struct ide_host *ide_host_alloc(const struct ide_port_info *, hw_regs_t **);
+void ide_host_free(struct ide_host *);
+int ide_host_register(struct ide_host *, const struct ide_port_info *,
+		      hw_regs_t **);
+int ide_host_add(const struct ide_port_info *, hw_regs_t **,
+		 struct ide_host **);
+void ide_host_remove(struct ide_host *);
 int ide_legacy_device_add(const struct ide_port_info *, unsigned long);
 void ide_port_unregister_devices(ide_hwif_t *);
 void ide_port_scan(ide_hwif_t *);
@@ -1350,33 +1434,4 @@
 
 	return &hwif->drives[(drive->dn ^ 1) & 1];
 }
-
-static inline void ide_set_irq(ide_drive_t *drive, int on)
-{
-	ide_hwif_t *hwif = drive->hwif;
-
-	hwif->OUTBSYNC(hwif, ATA_DEVCTL_OBS | (on ? 0 : 2),
-		       hwif->io_ports.ctl_addr);
-}
-
-static inline u8 ide_read_status(ide_drive_t *drive)
-{
-	ide_hwif_t *hwif = drive->hwif;
-
-	return hwif->INB(hwif->io_ports.status_addr);
-}
-
-static inline u8 ide_read_altstatus(ide_drive_t *drive)
-{
-	ide_hwif_t *hwif = drive->hwif;
-
-	return hwif->INB(hwif->io_ports.ctl_addr);
-}
-
-static inline u8 ide_read_error(ide_drive_t *drive)
-{
-	ide_hwif_t *hwif = drive->hwif;
-
-	return hwif->INB(hwif->io_ports.error_addr);
-}
 #endif /* _IDE_H */
diff --git a/include/linux/input.h b/include/linux/input.h
index d150c57..a5802c9 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -373,6 +373,8 @@
 
 #define KEY_WIMAX		246
 
+/* Range 248 - 255 is reserved for special needs of AT keyboard driver */
+
 #define BTN_MISC		0x100
 #define BTN_0			0x100
 #define BTN_1			0x101
@@ -640,6 +642,8 @@
 #define SW_RFKILL_ALL		0x03  /* rfkill master switch, type "any"
 					 set = radio enabled */
 #define SW_RADIO		SW_RFKILL_ALL	/* deprecated */
+#define SW_MICROPHONE_INSERT	0x04  /* set = inserted */
+#define SW_DOCK			0x05  /* set = plugged into dock */
 #define SW_MAX			0x0f
 #define SW_CNT			(SW_MAX+1)
 
@@ -1215,11 +1219,6 @@
 	struct list_head	h_node;
 };
 
-#define to_dev(n) container_of(n, struct input_dev, node)
-#define to_handler(n) container_of(n, struct input_handler, node)
-#define to_handle(n) container_of(n, struct input_handle, d_node)
-#define to_handle_h(n) container_of(n, struct input_handle, h_node)
-
 struct input_dev *input_allocate_device(void);
 void input_free_device(struct input_dev *dev);
 
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 391ad08..641e026 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -123,6 +123,7 @@
 	struct	in6_addr	daddr;
 };
 
+#ifdef __KERNEL__
 /*
  * This structure contains configuration options per IPv6 link.
  */
@@ -167,6 +168,7 @@
 	__s32		accept_dad;
 	void		*sysctl;
 };
+#endif
 
 /* index values for the variables in ipv6_devconf */
 enum {
diff --git a/include/linux/joystick.h b/include/linux/joystick.h
index e2d3a18..b5e0512 100644
--- a/include/linux/joystick.h
+++ b/include/linux/joystick.h
@@ -2,8 +2,6 @@
 #define _LINUX_JOYSTICK_H
 
 /*
- * $Id: joystick.h,v 1.3 2000/11/30 11:07:05 vojtech Exp $
- *
  *  Copyright (C) 1996-2000 Vojtech Pavlik
  *
  *  Sponsored by SuSE
diff --git a/include/linux/kmod.h b/include/linux/kmod.h
index 5dc1384..0509c4c 100644
--- a/include/linux/kmod.h
+++ b/include/linux/kmod.h
@@ -25,15 +25,16 @@
 
 #define KMOD_PATH_LEN 256
 
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
 /* modprobe exit status on success, -ve on error.  Return value
  * usually useless though. */
 extern int request_module(const char * name, ...) __attribute__ ((format (printf, 1, 2)));
+#define try_then_request_module(x, mod...) ((x) ?: (request_module(mod), (x)))
 #else
 static inline int request_module(const char * name, ...) { return -ENOSYS; }
+#define try_then_request_module(x, mod...) (x)
 #endif
 
-#define try_then_request_module(x, mod...) ((x) ?: (request_module(mod), (x)))
 
 struct key;
 struct file;
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 39e709f..60f0d41 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -26,7 +26,6 @@
 #include <linux/wait.h>
 #include <asm/atomic.h>
 
-#define KOBJ_NAME_LEN			20
 #define UEVENT_HELPER_PATH_LEN		256
 #define UEVENT_NUM_ENVP			32	/* number of env pointers */
 #define UEVENT_BUFFER_SIZE		2048	/* buffer for the variables */
@@ -59,12 +58,12 @@
 
 struct kobject {
 	const char		*name;
-	struct kref		kref;
 	struct list_head	entry;
 	struct kobject		*parent;
 	struct kset		*kset;
 	struct kobj_type	*ktype;
 	struct sysfs_dirent	*sd;
+	struct kref		kref;
 	unsigned int state_initialized:1;
 	unsigned int state_in_sysfs:1;
 	unsigned int state_add_uevent_sent:1;
diff --git a/include/linux/libps2.h b/include/linux/libps2.h
index f6f301e..afc4133 100644
--- a/include/linux/libps2.h
+++ b/include/linux/libps2.h
@@ -43,7 +43,6 @@
 int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout);
 void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout);
 int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command);
-int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int command);
 int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data);
 int ps2_handle_response(struct ps2dev *ps2dev, unsigned char data);
 void ps2_cmd_aborted(struct ps2dev *ps2dev);
diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
new file mode 100644
index 0000000..bb3dd054
--- /dev/null
+++ b/include/linux/mfd/core.h
@@ -0,0 +1,55 @@
+#ifndef MFD_CORE_H
+#define MFD_CORE_H
+/*
+ * drivers/mfd/mfd-core.h
+ *
+ * core MFD support
+ * Copyright (c) 2006 Ian Molton
+ * Copyright (c) 2007 Dmitry Baryshkov
+ *
+ * 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/platform_device.h>
+
+/*
+ * This struct describes the MFD part ("cell").
+ * After registration the copy of this structure will become the platform data
+ * of the resulting platform_device
+ */
+struct mfd_cell {
+	const char		*name;
+
+	int			(*enable)(struct platform_device *dev);
+	int			(*disable)(struct platform_device *dev);
+	int			(*suspend)(struct platform_device *dev);
+	int			(*resume)(struct platform_device *dev);
+
+	void			*driver_data; /* driver-specific data */
+
+	/*
+	 * This resources can be specified relatievly to the parent device.
+	 * For accessing device you should use resources from device
+	 */
+	int			num_resources;
+	const struct resource	*resources;
+};
+
+static inline struct mfd_cell *
+mfd_get_cell(struct platform_device *pdev)
+{
+	return (struct mfd_cell *)pdev->dev.platform_data;
+}
+
+extern int mfd_add_devices(
+		struct platform_device *parent,
+		const struct mfd_cell *cells, int n_devs,
+		struct resource *mem_base,
+		int irq_base);
+
+extern void mfd_remove_devices(struct platform_device *parent);
+
+#endif
diff --git a/include/linux/mfd/tc6393xb.h b/include/linux/mfd/tc6393xb.h
new file mode 100644
index 0000000..7cc824a
--- /dev/null
+++ b/include/linux/mfd/tc6393xb.h
@@ -0,0 +1,49 @@
+/*
+ * Toshiba TC6393XB SoC support
+ *
+ * Copyright(c) 2005-2006 Chris Humbert
+ * Copyright(c) 2005 Dirk Opfer
+ * Copyright(c) 2005 Ian Molton <spyro@f2s.com>
+ * Copyright(c) 2007 Dmitry Baryshkov
+ *
+ * Based on code written by Sharp/Lineo for 2.4 kernels
+ * Based on locomo.c
+ *
+ * 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 TC6393XB_H
+#define TC6393XB_H
+
+/* Also one should provide the CK3P6MI clock */
+struct tc6393xb_platform_data {
+	u16	scr_pll2cr;	/* PLL2 Control */
+	u16	scr_gper;	/* GP Enable */
+	u32	scr_gpo_doecr;	/* GPO Data OE Control */
+	u32	scr_gpo_dsr;	/* GPO Data Set */
+
+	int	(*enable)(struct platform_device *dev);
+	int	(*disable)(struct platform_device *dev);
+	int	(*suspend)(struct platform_device *dev);
+	int	(*resume)(struct platform_device *dev);
+
+	int	irq_base;	/* a base for cascaded irq */
+	int	gpio_base;
+
+	struct tmio_nand_data	*nand_data;
+};
+
+/*
+ * Relative to irq_base
+ */
+#define	IRQ_TC6393_NAND		0
+#define	IRQ_TC6393_MMC		1
+#define	IRQ_TC6393_OHCI		2
+#define	IRQ_TC6393_SERIAL	3
+#define	IRQ_TC6393_FB		4
+
+#define	TC6393XB_NR_IRQS	8
+
+#endif
diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h
new file mode 100644
index 0000000..9438d8c
--- /dev/null
+++ b/include/linux/mfd/tmio.h
@@ -0,0 +1,17 @@
+#ifndef MFD_TMIO_H
+#define MFD_TMIO_H
+
+/*
+ * data for the NAND controller
+ */
+struct tmio_nand_data {
+	struct nand_bbt_descr	*badblock_pattern;
+	struct mtd_partition	*partition;
+	unsigned int		num_partitions;
+};
+
+#define TMIO_NAND_CONFIG	"tmio-nand-config"
+#define TMIO_NAND_CONTROL	"tmio-nand-control"
+#define TMIO_NAND_IRQ		"tmio-nand"
+
+#endif
diff --git a/include/linux/module.h b/include/linux/module.h
index 3e03b1a..fce15eb 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -249,27 +249,30 @@
 
 	/* Exported symbols */
 	const struct kernel_symbol *syms;
-	unsigned int num_syms;
 	const unsigned long *crcs;
+	unsigned int num_syms;
 
 	/* GPL-only exported symbols. */
-	const struct kernel_symbol *gpl_syms;
 	unsigned int num_gpl_syms;
+	const struct kernel_symbol *gpl_syms;
 	const unsigned long *gpl_crcs;
 
+#ifdef CONFIG_UNUSED_SYMBOLS
 	/* unused exported symbols. */
 	const struct kernel_symbol *unused_syms;
-	unsigned int num_unused_syms;
 	const unsigned long *unused_crcs;
+	unsigned int num_unused_syms;
+
 	/* GPL-only, unused exported symbols. */
-	const struct kernel_symbol *unused_gpl_syms;
 	unsigned int num_unused_gpl_syms;
+	const struct kernel_symbol *unused_gpl_syms;
 	const unsigned long *unused_gpl_crcs;
+#endif
 
 	/* symbols that will be GPL-only in the near future. */
 	const struct kernel_symbol *gpl_future_syms;
-	unsigned int num_gpl_future_syms;
 	const unsigned long *gpl_future_crcs;
+	unsigned int num_gpl_future_syms;
 
 	/* Exception table */
 	unsigned int num_exentries;
@@ -285,10 +288,10 @@
 	void *module_core;
 
 	/* Here are the sizes of the init and core sections */
-	unsigned long init_size, core_size;
+	unsigned int init_size, core_size;
 
 	/* The size of the executable code in each section.  */
-	unsigned long init_text_size, core_text_size;
+	unsigned int init_text_size, core_text_size;
 
 	/* The handle returned from unwind_add_table. */
 	void *unwind_info;
@@ -300,29 +303,15 @@
 
 #ifdef CONFIG_GENERIC_BUG
 	/* Support for BUG */
+	unsigned num_bugs;
 	struct list_head bug_list;
 	struct bug_entry *bug_table;
-	unsigned num_bugs;
-#endif
-
-#ifdef CONFIG_MODULE_UNLOAD
-	/* Reference counts */
-	struct module_ref ref[NR_CPUS];
-
-	/* What modules depend on me? */
-	struct list_head modules_which_use_me;
-
-	/* Who is waiting for us to be unloaded */
-	struct task_struct *waiter;
-
-	/* Destruction function. */
-	void (*exit)(void);
 #endif
 
 #ifdef CONFIG_KALLSYMS
 	/* We keep the symbol and string tables for kallsyms. */
 	Elf_Sym *symtab;
-	unsigned long num_symtab;
+	unsigned int num_symtab;
 	char *strtab;
 
 	/* Section attributes */
@@ -342,6 +331,21 @@
 	struct marker *markers;
 	unsigned int num_markers;
 #endif
+
+#ifdef CONFIG_MODULE_UNLOAD
+	/* What modules depend on me? */
+	struct list_head modules_which_use_me;
+
+	/* Who is waiting for us to be unloaded */
+	struct task_struct *waiter;
+
+	/* Destruction function. */
+	void (*exit)(void);
+
+	/* Reference counts */
+	struct module_ref ref[NR_CPUS];
+#endif
+
 };
 #ifndef MODULE_ARCH_INIT
 #define MODULE_ARCH_INIT {}
diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h
index a9fae03..9c1d954 100644
--- a/include/linux/mtd/map.h
+++ b/include/linux/mtd/map.h
@@ -189,7 +189,7 @@
 */
 
 struct map_info {
-	char *name;
+	const char *name;
 	unsigned long size;
 	resource_size_t phys;
 #define NO_XIP (-1UL)
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 245f909..8b5d491 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -121,7 +121,7 @@
 	u_int32_t oobavail;  // Available OOB bytes per block
 
 	// Kernel-only stuff starts here.
-	char *name;
+	const char *name;
 	int index;
 
 	/* ecc layout structure pointer - read only ! */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 812bcd8..b4d056c 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -996,17 +996,17 @@
 		netif_schedule_queue(netdev_get_tx_queue(dev, i));
 }
 
+static inline void netif_tx_start_queue(struct netdev_queue *dev_queue)
+{
+	clear_bit(__QUEUE_STATE_XOFF, &dev_queue->state);
+}
+
 /**
  *	netif_start_queue - allow transmit
  *	@dev: network device
  *
  *	Allow upper layers to call the device hard_start_xmit routine.
  */
-static inline void netif_tx_start_queue(struct netdev_queue *dev_queue)
-{
-	clear_bit(__QUEUE_STATE_XOFF, &dev_queue->state);
-}
-
 static inline void netif_start_queue(struct net_device *dev)
 {
 	netif_tx_start_queue(netdev_get_tx_queue(dev, 0));
@@ -1022,13 +1022,6 @@
 	}
 }
 
-/**
- *	netif_wake_queue - restart transmit
- *	@dev: network device
- *
- *	Allow upper layers to call the device hard_start_xmit routine.
- *	Used for flow control when transmit resources are available.
- */
 static inline void netif_tx_wake_queue(struct netdev_queue *dev_queue)
 {
 #ifdef CONFIG_NETPOLL_TRAP
@@ -1041,6 +1034,13 @@
 		__netif_schedule(dev_queue->qdisc);
 }
 
+/**
+ *	netif_wake_queue - restart transmit
+ *	@dev: network device
+ *
+ *	Allow upper layers to call the device hard_start_xmit routine.
+ *	Used for flow control when transmit resources are available.
+ */
 static inline void netif_wake_queue(struct net_device *dev)
 {
 	netif_tx_wake_queue(netdev_get_tx_queue(dev, 0));
@@ -1056,6 +1056,11 @@
 	}
 }
 
+static inline void netif_tx_stop_queue(struct netdev_queue *dev_queue)
+{
+	set_bit(__QUEUE_STATE_XOFF, &dev_queue->state);
+}
+
 /**
  *	netif_stop_queue - stop transmitted packets
  *	@dev: network device
@@ -1063,11 +1068,6 @@
  *	Stop upper layers calling the device hard_start_xmit routine.
  *	Used for flow control when transmit resources are unavailable.
  */
-static inline void netif_tx_stop_queue(struct netdev_queue *dev_queue)
-{
-	set_bit(__QUEUE_STATE_XOFF, &dev_queue->state);
-}
-
 static inline void netif_stop_queue(struct net_device *dev)
 {
 	netif_tx_stop_queue(netdev_get_tx_queue(dev, 0));
@@ -1083,17 +1083,17 @@
 	}
 }
 
+static inline int netif_tx_queue_stopped(const struct netdev_queue *dev_queue)
+{
+	return test_bit(__QUEUE_STATE_XOFF, &dev_queue->state);
+}
+
 /**
  *	netif_queue_stopped - test if transmit queue is flowblocked
  *	@dev: network device
  *
  *	Test if transmit queue on device is currently unable to send.
  */
-static inline int netif_tx_queue_stopped(const struct netdev_queue *dev_queue)
-{
-	return test_bit(__QUEUE_STATE_XOFF, &dev_queue->state);
-}
-
 static inline int netif_queue_stopped(const struct net_device *dev)
 {
 	return netif_tx_queue_stopped(netdev_get_tx_queue(dev, 0));
@@ -1463,13 +1463,6 @@
 	local_irq_restore(flags);
 }
 
-/**
- *	netif_tx_lock - grab network device transmit lock
- *	@dev: network device
- *	@cpu: cpu number of lock owner
- *
- * Get network device transmit lock
- */
 static inline void __netif_tx_lock(struct netdev_queue *txq, int cpu)
 {
 	spin_lock(&txq->_xmit_lock);
@@ -1482,6 +1475,13 @@
 	txq->xmit_lock_owner = smp_processor_id();
 }
 
+/**
+ *	netif_tx_lock - grab network device transmit lock
+ *	@dev: network device
+ *	@cpu: cpu number of lock owner
+ *
+ * Get network device transmit lock
+ */
 static inline void netif_tx_lock(struct net_device *dev)
 {
 	int cpu = smp_processor_id();
@@ -1645,6 +1645,8 @@
 extern int netdev_class_create_file(struct class_attribute *class_attr);
 extern void netdev_class_remove_file(struct class_attribute *class_attr);
 
+extern char *netdev_drivername(struct net_device *dev, char *buffer, int len);
+
 extern void linkwatch_run_queue(void);
 
 extern int netdev_compute_features(unsigned long all, unsigned long one);
diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h
index bad1eb7..885cbe2 100644
--- a/include/linux/netfilter/nf_conntrack_common.h
+++ b/include/linux/netfilter/nf_conntrack_common.h
@@ -122,7 +122,7 @@
 	IPCT_NATINFO_BIT = 10,
 	IPCT_NATINFO = (1 << IPCT_NATINFO_BIT),
 
-	/* Counter highest bit has been set */
+	/* Counter highest bit has been set, unused */
 	IPCT_COUNTER_FILLING_BIT = 11,
 	IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT),
 
@@ -145,12 +145,6 @@
 };
 
 #ifdef __KERNEL__
-struct ip_conntrack_counter
-{
-	u_int32_t packets;
-	u_int32_t bytes;
-};
-
 struct ip_conntrack_stat
 {
 	unsigned int searched;
diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h
index 759bc04..c19595c 100644
--- a/include/linux/netfilter/nfnetlink_conntrack.h
+++ b/include/linux/netfilter/nfnetlink_conntrack.h
@@ -115,10 +115,10 @@
 
 enum ctattr_counters {
 	CTA_COUNTERS_UNSPEC,
-	CTA_COUNTERS_PACKETS,		/* old 64bit counters */
-	CTA_COUNTERS_BYTES,		/* old 64bit counters */
-	CTA_COUNTERS32_PACKETS,
-	CTA_COUNTERS32_BYTES,
+	CTA_COUNTERS_PACKETS,		/* 64bit counters */
+	CTA_COUNTERS_BYTES,		/* 64bit counters */
+	CTA_COUNTERS32_PACKETS,		/* old 32bit counters, unused */
+	CTA_COUNTERS32_BYTES,		/* old 32bit counters, unused */
 	__CTA_COUNTERS_MAX
 };
 #define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1)
diff --git a/include/linux/netfilter/nfnetlink_log.h b/include/linux/netfilter/nfnetlink_log.h
index a857213..f661731 100644
--- a/include/linux/netfilter/nfnetlink_log.h
+++ b/include/linux/netfilter/nfnetlink_log.h
@@ -48,6 +48,9 @@
 	NFULA_SEQ,			/* instance-local sequence number */
 	NFULA_SEQ_GLOBAL,		/* global sequence number */
 	NFULA_GID,			/* group id of socket */
+	NFULA_HWTYPE,			/* hardware type */
+	NFULA_HWHEADER,			/* hardware header */
+	NFULA_HWLEN,			/* hardware header length */
 
 	__NFULA_MAX
 };
diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h
index 2ee97e9..67db101 100644
--- a/include/linux/of_gpio.h
+++ b/include/linux/of_gpio.h
@@ -15,7 +15,7 @@
 #define __LINUX_OF_GPIO_H
 
 #include <linux/errno.h>
-#include <asm/gpio.h>
+#include <linux/gpio.h>
 
 #ifdef CONFIG_OF_GPIO
 
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index d8507eb..119ae7b 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2371,6 +2371,14 @@
 #define PCI_DEVICE_ID_INTEL_ICH9_7	0x2916
 #define PCI_DEVICE_ID_INTEL_ICH9_8	0x2918
 #define PCI_DEVICE_ID_INTEL_82855PM_HB	0x3340
+#define PCI_DEVICE_ID_INTEL_IOAT_TBG4	0x3429
+#define PCI_DEVICE_ID_INTEL_IOAT_TBG5	0x342a
+#define PCI_DEVICE_ID_INTEL_IOAT_TBG6	0x342b
+#define PCI_DEVICE_ID_INTEL_IOAT_TBG7	0x342c
+#define PCI_DEVICE_ID_INTEL_IOAT_TBG0	0x3430
+#define PCI_DEVICE_ID_INTEL_IOAT_TBG1	0x3431
+#define PCI_DEVICE_ID_INTEL_IOAT_TBG2	0x3432
+#define PCI_DEVICE_ID_INTEL_IOAT_TBG3	0x3433
 #define PCI_DEVICE_ID_INTEL_82830_HB	0x3575
 #define PCI_DEVICE_ID_INTEL_82830_CGC	0x3577
 #define PCI_DEVICE_ID_INTEL_82855GM_HB	0x3580
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index fff1d27..15a9eaf 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -305,8 +305,6 @@
 	return pde->parent->data;
 }
 
-struct net *get_proc_net(const struct inode *inode);
-
 struct proc_maps_private {
 	struct pid *pid;
 	struct task_struct *task;
diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h
index 78bfdea..e989006 100644
--- a/include/linux/raid/bitmap.h
+++ b/include/linux/raid/bitmap.h
@@ -221,6 +221,7 @@
 	unsigned long syncchunk;
 
 	__u64	events_cleared;
+	int need_sync;
 
 	/* bitmap spinlock */
 	spinlock_t lock;
diff --git a/include/linux/raid/linear.h b/include/linux/raid/linear.h
index ba15469..7e37511 100644
--- a/include/linux/raid/linear.h
+++ b/include/linux/raid/linear.h
@@ -16,7 +16,7 @@
 	struct linear_private_data *prev;	/* earlier version */
 	dev_info_t		**hash_table;
 	sector_t		hash_spacing;
-	sector_t		array_size;
+	sector_t		array_sectors;
 	int			preshift; /* shift before dividing by hash_spacing */
 	dev_info_t		disks[0];
 };
diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h
index b7386ae..dc0e3fc 100644
--- a/include/linux/raid/md.h
+++ b/include/linux/raid/md.h
@@ -95,7 +95,7 @@
 			struct page *page, int rw);
 extern void md_do_sync(mddev_t *mddev);
 extern void md_new_event(mddev_t *mddev);
-extern void md_allow_write(mddev_t *mddev);
+extern int md_allow_write(mddev_t *mddev);
 extern void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
 
 #endif /* CONFIG_MD */
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
index 3dea9f5..9f2549a 100644
--- a/include/linux/raid/md_k.h
+++ b/include/linux/raid/md_k.h
@@ -59,7 +59,7 @@
 	int		sb_loaded;
 	__u64		sb_events;
 	sector_t	data_offset;	/* start of data in array */
-	sector_t	sb_offset;
+	sector_t 	sb_start;	/* offset of the super block (in 512byte sectors) */
 	int		sb_size;	/* bytes in the superblock */
 	int		preferred_minor;	/* autorun support */
 
@@ -87,6 +87,9 @@
 #define Blocked		8		/* An error occured on an externally
 					 * managed array, don't allow writes
 					 * until it is cleared */
+#define StateChanged	9		/* Faulty or Blocked has changed during
+					 * interrupt, so it needs to be
+					 * notified by the thread */
 	wait_queue_head_t blocked_wait;
 
 	int desc_nr;			/* descriptor index in the superblock */
@@ -147,7 +150,7 @@
 	int				raid_disks;
 	int				max_disks;
 	sector_t			size; /* used size of component devices */
-	sector_t			array_size; /* exported array size */
+	sector_t			array_sectors; /* exported array size */
 	__u64				events;
 
 	char				uuid[16];
@@ -188,6 +191,7 @@
 	 * NEEDED:   we might need to start a resync/recover
 	 * RUNNING:  a thread is running, or about to be started
 	 * SYNC:     actually doing a resync, not a recovery
+	 * RECOVER:  doing recovery, or need to try it.
 	 * INTR:     resync needs to be aborted for some reason
 	 * DONE:     thread is done and is waiting to be reaped
 	 * REQUEST:  user-space has requested a sync (used with SYNC)
@@ -198,6 +202,7 @@
 	 */
 #define	MD_RECOVERY_RUNNING	0
 #define	MD_RECOVERY_SYNC	1
+#define	MD_RECOVERY_RECOVER	2
 #define	MD_RECOVERY_INTR	3
 #define	MD_RECOVERY_DONE	4
 #define	MD_RECOVERY_NEEDED	5
@@ -210,7 +215,8 @@
 
 	int				in_sync;	/* know to not need resync */
 	struct mutex			reconfig_mutex;
-	atomic_t			active;
+	atomic_t			active;		/* general refcount */
+	atomic_t			openers;	/* number of active opens */
 
 	int				changed;	/* true if we might need to reread partition info */
 	int				degraded;	/* whether md should consider
@@ -227,6 +233,8 @@
 	atomic_t			recovery_active; /* blocks scheduled, but not written */
 	wait_queue_head_t		recovery_wait;
 	sector_t			recovery_cp;
+	sector_t			resync_min;	/* user requested sync
+							 * starts here */
 	sector_t			resync_max;	/* resync should pause
 							 * when it gets here */
 
@@ -331,6 +339,9 @@
 #define rdev_for_each(rdev, tmp, mddev)				\
 	rdev_for_each_list(rdev, tmp, (mddev)->disks)
 
+#define rdev_for_each_rcu(rdev, mddev)				\
+	list_for_each_entry_rcu(rdev, &((mddev)->disks), same_set)
+
 typedef struct mdk_thread_s {
 	void			(*run) (mddev_t *mddev);
 	mddev_t			*mddev;
diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h
index 3f2cd98..8b4de4a 100644
--- a/include/linux/raid/md_p.h
+++ b/include/linux/raid/md_p.h
@@ -43,14 +43,11 @@
  */
 #define MD_RESERVED_BYTES		(64 * 1024)
 #define MD_RESERVED_SECTORS		(MD_RESERVED_BYTES / 512)
-#define MD_RESERVED_BLOCKS		(MD_RESERVED_BYTES / BLOCK_SIZE)
 
 #define MD_NEW_SIZE_SECTORS(x)		((x & ~(MD_RESERVED_SECTORS - 1)) - MD_RESERVED_SECTORS)
-#define MD_NEW_SIZE_BLOCKS(x)		((x & ~(MD_RESERVED_BLOCKS - 1)) - MD_RESERVED_BLOCKS)
 
 #define MD_SB_BYTES			4096
 #define MD_SB_WORDS			(MD_SB_BYTES / 4)
-#define MD_SB_BLOCKS			(MD_SB_BYTES / BLOCK_SIZE)
 #define MD_SB_SECTORS			(MD_SB_BYTES / 512)
 
 /*
diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h
index f0827d3..3b26727 100644
--- a/include/linux/raid/raid5.h
+++ b/include/linux/raid/raid5.h
@@ -158,6 +158,43 @@
  *    the compute block completes.
  */
 
+/*
+ * Operations state - intermediate states that are visible outside of sh->lock
+ * In general _idle indicates nothing is running, _run indicates a data
+ * processing operation is active, and _result means the data processing result
+ * is stable and can be acted upon.  For simple operations like biofill and
+ * compute that only have an _idle and _run state they are indicated with
+ * sh->state flags (STRIPE_BIOFILL_RUN and STRIPE_COMPUTE_RUN)
+ */
+/**
+ * enum check_states - handles syncing / repairing a stripe
+ * @check_state_idle - check operations are quiesced
+ * @check_state_run - check operation is running
+ * @check_state_result - set outside lock when check result is valid
+ * @check_state_compute_run - check failed and we are repairing
+ * @check_state_compute_result - set outside lock when compute result is valid
+ */
+enum check_states {
+	check_state_idle = 0,
+	check_state_run, /* parity check */
+	check_state_check_result,
+	check_state_compute_run, /* parity repair */
+	check_state_compute_result,
+};
+
+/**
+ * enum reconstruct_states - handles writing or expanding a stripe
+ */
+enum reconstruct_states {
+	reconstruct_state_idle = 0,
+	reconstruct_state_prexor_drain_run,	/* prexor-write */
+	reconstruct_state_drain_run,		/* write */
+	reconstruct_state_run,			/* expand */
+	reconstruct_state_prexor_drain_result,
+	reconstruct_state_drain_result,
+	reconstruct_state_result,
+};
+
 struct stripe_head {
 	struct hlist_node	hash;
 	struct list_head	lru;			/* inactive_list or handle_list */
@@ -169,19 +206,13 @@
 	spinlock_t		lock;
 	int			bm_seq;	/* sequence number for bitmap flushes */
 	int			disks;			/* disks in stripe */
+	enum check_states	check_state;
+	enum reconstruct_states reconstruct_state;
 	/* stripe_operations
-	 * @pending - pending ops flags (set for request->issue->complete)
-	 * @ack - submitted ops flags (set for issue->complete)
-	 * @complete - completed ops flags (set for complete)
 	 * @target - STRIPE_OP_COMPUTE_BLK target
-	 * @count - raid5_runs_ops is set to run when this is non-zero
 	 */
 	struct stripe_operations {
-		unsigned long	   pending;
-		unsigned long	   ack;
-		unsigned long	   complete;
 		int		   target;
-		int		   count;
 		u32		   zero_sum_result;
 	} ops;
 	struct r5dev {
@@ -202,6 +233,7 @@
 	int locked, uptodate, to_read, to_write, failed, written;
 	int to_fill, compute, req_compute, non_overwrite;
 	int failed_num;
+	unsigned long ops_request;
 };
 
 /* r6_state - extra state data only relevant to r6 */
@@ -228,9 +260,7 @@
 #define	R5_Wantfill	12 /* dev->toread contains a bio that needs
 				    * filling
 				    */
-#define	R5_Wantprexor	13 /* distinguish blocks ready for rmw from
-				    * other "towrites"
-				    */
+#define R5_Wantdrain	13 /* dev->towrite needs to be drained */
 /*
  * Write method
  */
@@ -254,8 +284,10 @@
 #define	STRIPE_EXPAND_READY	11
 #define	STRIPE_IO_STARTED	12 /* do not count towards 'bypass_count' */
 #define	STRIPE_FULL_WRITE	13 /* all blocks are set to be overwritten */
+#define	STRIPE_BIOFILL_RUN	14
+#define	STRIPE_COMPUTE_RUN	15
 /*
- * Operations flags (in issue order)
+ * Operation request flags
  */
 #define STRIPE_OP_BIOFILL	0
 #define STRIPE_OP_COMPUTE_BLK	1
@@ -263,14 +295,6 @@
 #define STRIPE_OP_BIODRAIN	3
 #define STRIPE_OP_POSTXOR	4
 #define STRIPE_OP_CHECK	5
-#define STRIPE_OP_IO		6
-
-/* modifiers to the base operations
- * STRIPE_OP_MOD_REPAIR_PD - compute the parity block and write it back
- * STRIPE_OP_MOD_DMA_CHECK - parity is not corrupted by the check
- */
-#define STRIPE_OP_MOD_REPAIR_PD 7
-#define STRIPE_OP_MOD_DMA_CHECK 8
 
 /*
  * Plugging:
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index 71fc813..e599698 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -224,4 +224,42 @@
  */
 #define SG_MAX_SINGLE_ALLOC		(PAGE_SIZE / sizeof(struct scatterlist))
 
+
+/*
+ * Mapping sg iterator
+ *
+ * Iterates over sg entries mapping page-by-page.  On each successful
+ * iteration, @miter->page points to the mapped page and
+ * @miter->length bytes of data can be accessed at @miter->addr.  As
+ * long as an interation is enclosed between start and stop, the user
+ * is free to choose control structure and when to stop.
+ *
+ * @miter->consumed is set to @miter->length on each iteration.  It
+ * can be adjusted if the user can't consume all the bytes in one go.
+ * Also, a stopped iteration can be resumed by calling next on it.
+ * This is useful when iteration needs to release all resources and
+ * continue later (e.g. at the next interrupt).
+ */
+
+#define SG_MITER_ATOMIC		(1 << 0)	 /* use kmap_atomic */
+
+struct sg_mapping_iter {
+	/* the following three fields can be accessed directly */
+	struct page		*page;		/* currently mapped page */
+	void			*addr;		/* pointer to the mapped area */
+	size_t			length;		/* length of the mapped area */
+	size_t			consumed;	/* number of consumed bytes */
+
+	/* these are internal states, keep away */
+	struct scatterlist	*__sg;		/* current entry */
+	unsigned int		__nents;	/* nr of remaining entries */
+	unsigned int		__offset;	/* offset within sg */
+	unsigned int		__flags;
+};
+
+void sg_miter_start(struct sg_mapping_iter *miter, struct scatterlist *sgl,
+		    unsigned int nents, unsigned int flags);
+bool sg_miter_next(struct sg_mapping_iter *miter);
+void sg_miter_stop(struct sg_mapping_iter *miter);
+
 #endif /* _LINUX_SCATTERLIST_H */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 1941d8b..af443a0 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -295,10 +295,11 @@
 extern void spawn_softlockup_task(void);
 extern void touch_softlockup_watchdog(void);
 extern void touch_all_softlockup_watchdogs(void);
-extern unsigned long  softlockup_thresh;
+extern unsigned int  softlockup_panic;
 extern unsigned long sysctl_hung_task_check_count;
 extern unsigned long sysctl_hung_task_timeout_secs;
 extern unsigned long sysctl_hung_task_warnings;
+extern int softlockup_thresh;
 #else
 static inline void softlockup_tick(void)
 {
diff --git a/include/linux/serio.h b/include/linux/serio.h
index 95674d9..e72716c 100644
--- a/include/linux/serio.h
+++ b/include/linux/serio.h
@@ -175,7 +175,7 @@
 #define SERIO_8042_XL	0x06
 
 /*
- * Serio types
+ * Serio protocols
  */
 #define SERIO_UNKNOWN	0x00
 #define SERIO_MSC	0x01
@@ -212,5 +212,7 @@
 #define SERIO_TAOSEVM	0x34
 #define SERIO_FUJITSU	0x35
 #define SERIO_ZHENHUA	0x36
+#define SERIO_INEXIO	0x37
+#define SERIO_TOUCHIT213	0x37
 
 #endif
diff --git a/include/linux/smc91x.h b/include/linux/smc91x.h
index 8e0556b..3827b92 100644
--- a/include/linux/smc91x.h
+++ b/include/linux/smc91x.h
@@ -5,9 +5,19 @@
 #define SMC91X_USE_16BIT (1 << 1)
 #define SMC91X_USE_32BIT (1 << 2)
 
+#define SMC91X_NOWAIT		(1 << 3)
+
+/* two bits for IO_SHIFT, let's hope later designs will keep this sane */
+#define SMC91X_IO_SHIFT_0	(0 << 4)
+#define SMC91X_IO_SHIFT_1	(1 << 4)
+#define SMC91X_IO_SHIFT_2	(2 << 4)
+#define SMC91X_IO_SHIFT_3	(3 << 4)
+#define SMC91X_IO_SHIFT(x)	(((x) >> 4) & 0x3)
+
+#define SMC91X_USE_DMA		(1 << 6)
+
 struct smc91x_platdata {
 	unsigned long flags;
-	unsigned long irq_flags; /* IRQF_... */
 };
 
 #endif /* __SMC91X_H__ */
diff --git a/include/linux/spi/max7301.h b/include/linux/spi/max7301.h
new file mode 100644
index 0000000..6dfd83f
--- /dev/null
+++ b/include/linux/spi/max7301.h
@@ -0,0 +1,9 @@
+#ifndef LINUX_SPI_MAX7301_H
+#define LINUX_SPI_MAX7301_H
+
+struct max7301_platform_data {
+	/* number assigned to the first GPIO */
+	unsigned	base;
+};
+
+#endif
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 387e428..b9a76c9 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -733,7 +733,7 @@
 	 * controller_data goes to spi_device.controller_data,
 	 * irq is copied too
 	 */
-	char		modalias[KOBJ_NAME_LEN];
+	char		modalias[32];
 	const void	*platform_data;
 	void		*controller_data;
 	int		irq;
diff --git a/include/linux/synclink.h b/include/linux/synclink.h
index 45f6bc8..c844a22 100644
--- a/include/linux/synclink.h
+++ b/include/linux/synclink.h
@@ -136,6 +136,7 @@
 #define MGSL_INTERFACE_RTS_EN   0x10
 #define MGSL_INTERFACE_LL       0x20
 #define MGSL_INTERFACE_RL       0x40
+#define MGSL_INTERFACE_MSB_FIRST 0x80
 
 typedef struct _MGSL_PARAMS
 {
diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h
index f2767bc..f395bb3 100644
--- a/include/linux/sysdev.h
+++ b/include/linux/sysdev.h
@@ -99,8 +99,9 @@
 
 struct sysdev_attribute { 
 	struct attribute	attr;
-	ssize_t (*show)(struct sys_device *, char *);
-	ssize_t (*store)(struct sys_device *, const char *, size_t);
+	ssize_t (*show)(struct sys_device *, struct sysdev_attribute *, char *);
+	ssize_t (*store)(struct sys_device *, struct sysdev_attribute *,
+			 const char *, size_t);
 };
 
 
@@ -118,4 +119,38 @@
 extern int sysdev_create_file(struct sys_device *, struct sysdev_attribute *);
 extern void sysdev_remove_file(struct sys_device *, struct sysdev_attribute *);
 
+struct sysdev_ext_attribute {
+	struct sysdev_attribute attr;
+	void *var;
+};
+
+/*
+ * Support for simple variable sysdev attributes.
+ * The pointer to the variable is stored in a sysdev_ext_attribute
+ */
+
+/* Add more types as needed */
+
+extern ssize_t sysdev_show_ulong(struct sys_device *, struct sysdev_attribute *,
+				char *);
+extern ssize_t sysdev_store_ulong(struct sys_device *,
+			struct sysdev_attribute *, const char *, size_t);
+extern ssize_t sysdev_show_int(struct sys_device *, struct sysdev_attribute *,
+				char *);
+extern ssize_t sysdev_store_int(struct sys_device *,
+			struct sysdev_attribute *, const char *, size_t);
+
+#define _SYSDEV_ULONG_ATTR(_name, _mode, _var)				\
+	{ _SYSDEV_ATTR(_name, _mode, sysdev_show_ulong, sysdev_store_ulong), \
+	  &(_var) }
+#define SYSDEV_ULONG_ATTR(_name, _mode, _var)			\
+	struct sysdev_ext_attribute attr_##_name = 		\
+		_SYSDEV_ULONG_ATTR(_name, _mode, _var);
+#define _SYSDEV_INT_ATTR(_name, _mode, _var)				\
+	{ _SYSDEV_ATTR(_name, _mode, sysdev_show_int, sysdev_store_int), \
+	  &(_var) }
+#define SYSDEV_INT_ATTR(_name, _mode, _var)			\
+	struct sysdev_ext_attribute attr_##_name = 		\
+		_SYSDEV_INT_ATTR(_name, _mode, _var);
+
 #endif /* _SYSDEV_H_ */
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 7858eac..37fa241 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -101,6 +101,9 @@
 
 int __must_check sysfs_create_link(struct kobject *kobj, struct kobject *target,
 				   const char *name);
+int __must_check sysfs_create_link_nowarn(struct kobject *kobj,
+					  struct kobject *target,
+					  const char *name);
 void sysfs_remove_link(struct kobject *kobj, const char *name);
 
 int __must_check sysfs_create_group(struct kobject *kobj,
@@ -180,6 +183,13 @@
 	return 0;
 }
 
+static inline int sysfs_create_link_nowarn(struct kobject *kobj,
+					   struct kobject *target,
+					   const char *name)
+{
+	return 0;
+}
+
 static inline void sysfs_remove_link(struct kobject *kobj, const char *name)
 {
 }
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 4e58330..e3579cb 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -317,8 +317,6 @@
 extern int tty_check_change(struct tty_struct *tty);
 extern void stop_tty(struct tty_struct *tty);
 extern void start_tty(struct tty_struct *tty);
-extern int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc);
-extern int tty_unregister_ldisc(int disc);
 extern int tty_register_driver(struct tty_driver *driver);
 extern int tty_unregister_driver(struct tty_driver *driver);
 extern struct device *tty_register_device(struct tty_driver *driver,
@@ -383,6 +381,15 @@
 extern int tty_port_alloc_xmit_buf(struct tty_port *port);
 extern void tty_port_free_xmit_buf(struct tty_port *port);
 
+extern int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc);
+extern int tty_unregister_ldisc(int disc);
+extern int tty_set_ldisc(struct tty_struct *tty, int ldisc);
+extern int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty);
+extern void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty);
+extern void tty_ldisc_init(struct tty_struct *tty);
+extern void tty_ldisc_begin(void);
+/* This last one is just for the tty layer internals and shouldn't be used elsewhere */
+extern void tty_ldisc_enable(struct tty_struct *tty);
 
 
 /* n_tty.c */
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index d2a0035..e1065ac 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -135,7 +135,7 @@
  *
  *	Optional:
  *
- * void (*break_ctl)(struct tty_stuct *tty, int state);
+ * int (*break_ctl)(struct tty_stuct *tty, int state);
  *
  * 	This optional routine requests the tty driver to turn on or
  * 	off BREAK status on the RS-232 port.  If state is -1,
@@ -146,6 +146,10 @@
  * 	handle the following ioctls: TCSBRK, TCSBRKP, TIOCSBRK,
  * 	TIOCCBRK.
  *
+ *	If the driver sets TTY_DRIVER_HARDWARE_BREAK then the interface
+ *	will also be called with actual times and the hardware is expected
+ *	to do the delay work itself. 0 and -1 are still used for on/off.
+ *
  *	Optional: Required for TCSBRK/BRKP/etc handling.
  *
  * void (*wait_until_sent)(struct tty_struct *tty, int timeout);
@@ -192,7 +196,7 @@
 	void (*stop)(struct tty_struct *tty);
 	void (*start)(struct tty_struct *tty);
 	void (*hangup)(struct tty_struct *tty);
-	void (*break_ctl)(struct tty_struct *tty, int state);
+	int (*break_ctl)(struct tty_struct *tty, int state);
 	void (*flush_buffer)(struct tty_struct *tty);
 	void (*set_ldisc)(struct tty_struct *tty);
 	void (*wait_until_sent)(struct tty_struct *tty, int timeout);
@@ -285,12 +289,18 @@
  * TTY_DRIVER_DEVPTS_MEM -- don't use the standard arrays, instead
  *	use dynamic memory keyed through the devpts filesystem.  This
  *	is only applicable to the pty driver.
+ *
+ * TTY_DRIVER_HARDWARE_BREAK -- hardware handles break signals. Pass
+ *	the requested timeout to the caller instead of using a simple
+ *	on/off interface.
+ *
  */
 #define TTY_DRIVER_INSTALLED		0x0001
 #define TTY_DRIVER_RESET_TERMIOS	0x0002
 #define TTY_DRIVER_REAL_RAW		0x0004
 #define TTY_DRIVER_DYNAMIC_DEV		0x0008
 #define TTY_DRIVER_DEVPTS_MEM		0x0010
+#define TTY_DRIVER_HARDWARE_BREAK	0x0020
 
 /* tty driver types */
 #define TTY_DRIVER_TYPE_SYSTEM		0x0001
diff --git a/include/linux/uio_driver.h b/include/linux/uio_driver.h
index 973386d..cdf338d 100644
--- a/include/linux/uio_driver.h
+++ b/include/linux/uio_driver.h
@@ -36,7 +36,7 @@
 	struct uio_map		*map;
 };
 
-#define MAX_UIO_MAPS 	5
+#define MAX_UIO_MAPS	5
 
 struct uio_device;
 
@@ -53,6 +53,7 @@
  * @mmap:		mmap operation for this uio device
  * @open:		open operation for this uio device
  * @release:		release operation for this uio device
+ * @irqcontrol:		disable/enable irqs when 0/1 is written to /dev/uioX
  */
 struct uio_info {
 	struct uio_device	*uio_dev;
@@ -66,6 +67,7 @@
 	int (*mmap)(struct uio_info *info, struct vm_area_struct *vma);
 	int (*open)(struct uio_info *info, struct inode *inode);
 	int (*release)(struct uio_info *info, struct inode *inode);
+	int (*irqcontrol)(struct uio_info *info, s32 irq_on);
 };
 
 extern int __must_check
@@ -80,11 +82,11 @@
 extern void uio_unregister_device(struct uio_info *info);
 extern void uio_event_notify(struct uio_info *info);
 
-/* defines for uio_device->irq */
+/* defines for uio_info->irq */
 #define UIO_IRQ_CUSTOM	-1
 #define UIO_IRQ_NONE	-2
 
-/* defines for uio_device->memtype */
+/* defines for uio_mem->memtype */
 #define UIO_MEM_NONE	0
 #define UIO_MEM_PHYS	1
 #define UIO_MEM_LOGICAL	2
diff --git a/include/linux/usb.h b/include/linux/usb.h
index c08689e..5811c5d 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -160,6 +160,7 @@
 	unsigned is_active:1;		/* the interface is not suspended */
 	unsigned sysfs_files_created:1;	/* the sysfs attributes exist */
 	unsigned needs_remote_wakeup:1;	/* driver requires remote wakeup */
+	unsigned needs_binding:1;	/* needs delayed unbind/rebind */
 
 	struct device dev;		/* interface specific device info */
 	struct device *usb_dev;
@@ -293,7 +294,7 @@
 struct usb_bus {
 	struct device *controller;	/* host/master side hardware */
 	int busnum;			/* Bus number (in order of reg) */
-	char *bus_name;			/* stable id (PCI slot_name etc) */
+	const 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 */
@@ -497,8 +498,6 @@
 
 /* USB port reset for device reinitialization */
 extern int usb_reset_device(struct usb_device *dev);
-extern int usb_reset_composite_device(struct usb_device *dev,
-		struct usb_interface *iface);
 
 extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id);
 
@@ -958,9 +957,9 @@
  * @resume: Called when the device is being resumed by the system.
  * @reset_resume: Called when the suspended device has been reset instead
  *	of being resumed.
- * @pre_reset: Called by usb_reset_composite_device() when the device
+ * @pre_reset: Called by usb_reset_device() when the device
  *	is about to be reset.
- * @post_reset: Called by usb_reset_composite_device() after the device
+ * @post_reset: Called by usb_reset_device() after the device
  *	has been reset
  * @id_table: USB drivers use ID table to support hotplugging.
  *	Export this with MODULE_DEVICE_TABLE(usb,...).  This must be set
@@ -972,6 +971,8 @@
  *	added to this driver by preventing the sysfs file from being created.
  * @supports_autosuspend: if set to 0, the USB core will not allow autosuspend
  *	for interfaces bound to this driver.
+ * @soft_unbind: if set to 1, the USB core will not kill URBs and disable
+ *	endpoints before calling the driver's disconnect method.
  *
  * USB interface drivers must provide a name, probe() and disconnect()
  * methods, and an id_table.  Other driver fields are optional.
@@ -1012,6 +1013,7 @@
 	struct usbdrv_wrap drvwrap;
 	unsigned int no_dynamic_id:1;
 	unsigned int supports_autosuspend:1;
+	unsigned int soft_unbind:1;
 };
 #define	to_usb_driver(d) container_of(d, struct usb_driver, drvwrap.driver)
 
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
new file mode 100644
index 0000000..747c3a4
--- /dev/null
+++ b/include/linux/usb/composite.h
@@ -0,0 +1,338 @@
+/*
+ * composite.h -- framework for usb gadgets which are composite devices
+ *
+ * Copyright (C) 2006-2008 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 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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef	__LINUX_USB_COMPOSITE_H
+#define	__LINUX_USB_COMPOSITE_H
+
+/*
+ * This framework is an optional layer on top of the USB Gadget interface,
+ * making it easier to build (a) Composite devices, supporting multiple
+ * functions within any single configuration, and (b) Multi-configuration
+ * devices, also supporting multiple functions but without necessarily
+ * having more than one function per configuration.
+ *
+ * Example:  a device with a single configuration supporting both network
+ * link and mass storage functions is a composite device.  Those functions
+ * might alternatively be packaged in individual configurations, but in
+ * the composite model the host can use both functions at the same time.
+ */
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+
+struct usb_configuration;
+
+/**
+ * struct usb_function - describes one function of a configuration
+ * @name: For diagnostics, identifies the function.
+ * @strings: tables of strings, keyed by identifiers assigned during bind()
+ *	and by language IDs provided in control requests
+ * @descriptors: Table of full (or low) speed descriptors, using interface and
+ *	string identifiers assigned during @bind().  If this pointer is null,
+ *	the function will not be available at full speed (or at low speed).
+ * @hs_descriptors: Table of high speed descriptors, using interface and
+ *	string identifiers assigned during @bind().  If this pointer is null,
+ *	the function will not be available at high speed.
+ * @config: assigned when @usb_add_function() is called; this is the
+ *	configuration with which this function is associated.
+ * @bind: Before the gadget can register, all of its functions bind() to the
+ *	available resources including string and interface identifiers used
+ *	in interface or class descriptors; endpoints; I/O buffers; and so on.
+ * @unbind: Reverses @bind; called as a side effect of unregistering the
+ *	driver which added this function.
+ * @set_alt: (REQUIRED) Reconfigures altsettings; function drivers may
+ *	initialize usb_ep.driver data at this time (when it is used).
+ *	Note that setting an interface to its current altsetting resets
+ *	interface state, and that all interfaces have a disabled state.
+ * @get_alt: Returns the active altsetting.  If this is not provided,
+ *	then only altsetting zero is supported.
+ * @disable: (REQUIRED) Indicates the function should be disabled.  Reasons
+ *	include host resetting or reconfiguring the gadget, and disconnection.
+ * @setup: Used for interface-specific control requests.
+ * @suspend: Notifies functions when the host stops sending USB traffic.
+ * @resume: Notifies functions when the host restarts USB traffic.
+ *
+ * A single USB function uses one or more interfaces, and should in most
+ * cases support operation at both full and high speeds.  Each function is
+ * associated by @usb_add_function() with a one configuration; that function
+ * causes @bind() to be called so resources can be allocated as part of
+ * setting up a gadget driver.  Those resources include endpoints, which
+ * should be allocated using @usb_ep_autoconfig().
+ *
+ * To support dual speed operation, a function driver provides descriptors
+ * for both high and full speed operation.  Except in rare cases that don't
+ * involve bulk endpoints, each speed needs different endpoint descriptors.
+ *
+ * Function drivers choose their own strategies for managing instance data.
+ * The simplest strategy just declares it "static', which means the function
+ * can only be activated once.  If the function needs to be exposed in more
+ * than one configuration at a given speed, it needs to support multiple
+ * usb_function structures (one for each configuration).
+ *
+ * A more complex strategy might encapsulate a @usb_function structure inside
+ * a driver-specific instance structure to allows multiple activations.  An
+ * example of multiple activations might be a CDC ACM function that supports
+ * two or more distinct instances within the same configuration, providing
+ * several independent logical data links to a USB host.
+ */
+struct usb_function {
+	const char			*name;
+	struct usb_gadget_strings	**strings;
+	struct usb_descriptor_header	**descriptors;
+	struct usb_descriptor_header	**hs_descriptors;
+
+	struct usb_configuration	*config;
+
+	/* REVISIT:  bind() functions can be marked __init, which
+	 * makes trouble for section mismatch analysis.  See if
+	 * we can't restructure things to avoid mismatching.
+	 * Related:  unbind() may kfree() but bind() won't...
+	 */
+
+	/* configuration management:  bind/unbind */
+	int			(*bind)(struct usb_configuration *,
+					struct usb_function *);
+	void			(*unbind)(struct usb_configuration *,
+					struct usb_function *);
+
+	/* runtime state management */
+	int			(*set_alt)(struct usb_function *,
+					unsigned interface, unsigned alt);
+	int			(*get_alt)(struct usb_function *,
+					unsigned interface);
+	void			(*disable)(struct usb_function *);
+	int			(*setup)(struct usb_function *,
+					const struct usb_ctrlrequest *);
+	void			(*suspend)(struct usb_function *);
+	void			(*resume)(struct usb_function *);
+
+	/* internals */
+	struct list_head		list;
+};
+
+int usb_add_function(struct usb_configuration *, struct usb_function *);
+
+int usb_interface_id(struct usb_configuration *, struct usb_function *);
+
+/**
+ * ep_choose - select descriptor endpoint at current device speed
+ * @g: gadget, connected and running at some speed
+ * @hs: descriptor to use for high speed operation
+ * @fs: descriptor to use for full or low speed operation
+ */
+static inline struct usb_endpoint_descriptor *
+ep_choose(struct usb_gadget *g, struct usb_endpoint_descriptor *hs,
+		struct usb_endpoint_descriptor *fs)
+{
+	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
+		return hs;
+	return fs;
+}
+
+#define	MAX_CONFIG_INTERFACES		16	/* arbitrary; max 255 */
+
+/**
+ * struct usb_configuration - represents one gadget configuration
+ * @label: For diagnostics, describes the configuration.
+ * @strings: Tables of strings, keyed by identifiers assigned during @bind()
+ *	and by language IDs provided in control requests.
+ * @descriptors: Table of descriptors preceding all function descriptors.
+ *	Examples include OTG and vendor-specific descriptors.
+ * @bind: Called from @usb_add_config() to allocate resources unique to this
+ *	configuration and to call @usb_add_function() for each function used.
+ * @unbind: Reverses @bind; called as a side effect of unregistering the
+ *	driver which added this configuration.
+ * @setup: Used to delegate control requests that aren't handled by standard
+ *	device infrastructure or directed at a specific interface.
+ * @bConfigurationValue: Copied into configuration descriptor.
+ * @iConfiguration: Copied into configuration descriptor.
+ * @bmAttributes: Copied into configuration descriptor.
+ * @bMaxPower: Copied into configuration descriptor.
+ * @cdev: assigned by @usb_add_config() before calling @bind(); this is
+ *	the device associated with this configuration.
+ *
+ * Configurations are building blocks for gadget drivers structured around
+ * function drivers.  Simple USB gadgets require only one function and one
+ * configuration, and handle dual-speed hardware by always providing the same
+ * functionality.  Slightly more complex gadgets may have more than one
+ * single-function configuration at a given speed; or have configurations
+ * that only work at one speed.
+ *
+ * Composite devices are, by definition, ones with configurations which
+ * include more than one function.
+ *
+ * The lifecycle of a usb_configuration includes allocation, initialization
+ * of the fields described above, and calling @usb_add_config() to set up
+ * internal data and bind it to a specific device.  The configuration's
+ * @bind() method is then used to initialize all the functions and then
+ * call @usb_add_function() for them.
+ *
+ * Those functions would normally be independant of each other, but that's
+ * not mandatory.  CDC WMC devices are an example where functions often
+ * depend on other functions, with some functions subsidiary to others.
+ * Such interdependency may be managed in any way, so long as all of the
+ * descriptors complete by the time the composite driver returns from
+ * its bind() routine.
+ */
+struct usb_configuration {
+	const char			*label;
+	struct usb_gadget_strings	**strings;
+	const struct usb_descriptor_header **descriptors;
+
+	/* REVISIT:  bind() functions can be marked __init, which
+	 * makes trouble for section mismatch analysis.  See if
+	 * we can't restructure things to avoid mismatching...
+	 */
+
+	/* configuration management:  bind/unbind */
+	int			(*bind)(struct usb_configuration *);
+	void			(*unbind)(struct usb_configuration *);
+	int			(*setup)(struct usb_configuration *,
+					const struct usb_ctrlrequest *);
+
+	/* fields in the config descriptor */
+	u8			bConfigurationValue;
+	u8			iConfiguration;
+	u8			bmAttributes;
+	u8			bMaxPower;
+
+	struct usb_composite_dev	*cdev;
+
+	/* internals */
+	struct list_head	list;
+	struct list_head	functions;
+	u8			next_interface_id;
+	unsigned		highspeed:1;
+	unsigned		fullspeed:1;
+	struct usb_function	*interface[MAX_CONFIG_INTERFACES];
+};
+
+int usb_add_config(struct usb_composite_dev *,
+		struct usb_configuration *);
+
+/**
+ * struct usb_composite_driver - groups configurations into a gadget
+ * @name: For diagnostics, identifies the driver.
+ * @dev: Template descriptor for the device, including default device
+ *	identifiers.
+ * @strings: tables of strings, keyed by identifiers assigned during bind()
+ *	and language IDs provided in control requests
+ * @bind: (REQUIRED) Used to allocate resources that are shared across the
+ *	whole device, such as string IDs, and add its configurations using
+ *	@usb_add_config().  This may fail by returning a negative errno
+ *	value; it should return zero on successful initialization.
+ * @unbind: Reverses @bind(); called as a side effect of unregistering
+ *	this driver.
+ *
+ * Devices default to reporting self powered operation.  Devices which rely
+ * on bus powered operation should report this in their @bind() method.
+ *
+ * Before returning from @bind, various fields in the template descriptor
+ * may be overridden.  These include the idVendor/idProduct/bcdDevice values
+ * normally to bind the appropriate host side driver, and the three strings
+ * (iManufacturer, iProduct, iSerialNumber) normally used to provide user
+ * meaningful device identifiers.  (The strings will not be defined unless
+ * they are defined in @dev and @strings.)  The correct ep0 maxpacket size
+ * is also reported, as defined by the underlying controller driver.
+ */
+struct usb_composite_driver {
+	const char				*name;
+	const struct usb_device_descriptor	*dev;
+	struct usb_gadget_strings		**strings;
+
+	/* REVISIT:  bind() functions can be marked __init, which
+	 * makes trouble for section mismatch analysis.  See if
+	 * we can't restructure things to avoid mismatching...
+	 */
+
+	int			(*bind)(struct usb_composite_dev *);
+	int			(*unbind)(struct usb_composite_dev *);
+};
+
+extern int usb_composite_register(struct usb_composite_driver *);
+extern void usb_composite_unregister(struct usb_composite_driver *);
+
+
+/**
+ * struct usb_composite_device - represents one composite usb gadget
+ * @gadget: read-only, abstracts the gadget's usb peripheral controller
+ * @req: used for control responses; buffer is pre-allocated
+ * @bufsiz: size of buffer pre-allocated in @req
+ * @config: the currently active configuration
+ *
+ * One of these devices is allocated and initialized before the
+ * associated device driver's bind() is called.
+ *
+ * OPEN ISSUE:  it appears that some WUSB devices will need to be
+ * built by combining a normal (wired) gadget with a wireless one.
+ * This revision of the gadget framework should probably try to make
+ * sure doing that won't hurt too much.
+ *
+ * One notion for how to handle Wireless USB devices involves:
+ * (a) a second gadget here, discovery mechanism TBD, but likely
+ *     needing separate "register/unregister WUSB gadget" calls;
+ * (b) updates to usb_gadget to include flags "is it wireless",
+ *     "is it wired", plus (presumably in a wrapper structure)
+ *     bandgroup and PHY info;
+ * (c) presumably a wireless_ep wrapping a usb_ep, and reporting
+ *     wireless-specific parameters like maxburst and maxsequence;
+ * (d) configurations that are specific to wireless links;
+ * (e) function drivers that understand wireless configs and will
+ *     support wireless for (additional) function instances;
+ * (f) a function to support association setup (like CBAF), not
+ *     necessarily requiring a wireless adapter;
+ * (g) composite device setup that can create one or more wireless
+ *     configs, including appropriate association setup support;
+ * (h) more, TBD.
+ */
+struct usb_composite_dev {
+	struct usb_gadget		*gadget;
+	struct usb_request		*req;
+	unsigned			bufsiz;
+
+	struct usb_configuration	*config;
+
+	/* internals */
+	struct usb_device_descriptor	desc;
+	struct list_head		configs;
+	struct usb_composite_driver	*driver;
+	u8				next_string_id;
+
+	spinlock_t			lock;
+
+	/* REVISIT use and existence of lock ... */
+};
+
+extern int usb_string_id(struct usb_composite_dev *c);
+
+/* messaging utils */
+#define DBG(d, fmt, args...) \
+	dev_dbg(&(d)->gadget->dev , fmt , ## args)
+#define VDBG(d, fmt, args...) \
+	dev_vdbg(&(d)->gadget->dev , fmt , ## args)
+#define ERROR(d, fmt, args...) \
+	dev_err(&(d)->gadget->dev , fmt , ## args)
+#define WARN(d, fmt, args...) \
+	dev_warn(&(d)->gadget->dev , fmt , ## args)
+#define INFO(d, fmt, args...) \
+	dev_info(&(d)->gadget->dev , fmt , ## args)
+
+#endif	/* __LINUX_USB_COMPOSITE_H */
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index cf468fb..0460a74 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -33,7 +33,8 @@
  * @short_not_ok: When reading data, makes short packets be
  *     treated as errors (queue stops advancing till cleanup).
  * @complete: Function called when request completes, so this request and
- *	its buffer may be re-used.
+ *	its buffer may be re-used.  The function will always be called with
+ *	interrupts disabled, and it must not sleep.
  *	Reads terminate with a short packet, or when the buffer fills,
  *	whichever comes first.  When writes terminate, some data bytes
  *	will usually still be in flight (often in a hardware fifo).
@@ -271,7 +272,10 @@
  * (Note that some USB device controllers disallow protocol stall responses
  * in some cases.)  When control responses are deferred (the response is
  * written after the setup callback returns), then usb_ep_set_halt() may be
- * used on ep0 to trigger protocol stalls.
+ * used on ep0 to trigger protocol stalls.  Depending on the controller,
+ * it may not be possible to trigger a status-stage protocol stall when the
+ * data stage is over, that is, from within the response's completion
+ * routine.
  *
  * For periodic endpoints, like interrupt or isochronous ones, the usb host
  * arranges to poll once per interval, and the gadget driver usually will
@@ -858,6 +862,25 @@
 int usb_gadget_config_buf(const struct usb_config_descriptor *config,
 	void *buf, unsigned buflen, const struct usb_descriptor_header **desc);
 
+/* copy a NULL-terminated vector of descriptors */
+struct usb_descriptor_header **usb_copy_descriptors(
+		struct usb_descriptor_header **);
+
+/* return copy of endpoint descriptor given original descriptor set */
+struct usb_endpoint_descriptor *usb_find_endpoint(
+	struct usb_descriptor_header **src,
+	struct usb_descriptor_header **copy,
+	struct usb_endpoint_descriptor *match);
+
+/**
+ * usb_free_descriptors - free descriptors returned by usb_copy_descriptors()
+ * @v: vector of descriptors
+ */
+static inline void usb_free_descriptors(struct usb_descriptor_header **v)
+{
+	kfree(v);
+}
+
 /*-------------------------------------------------------------------------*/
 
 /* utility wrapping a simple endpoint selection policy */
diff --git a/include/linux/usb/irda.h b/include/linux/usb/irda.h
new file mode 100644
index 0000000..e345cea
--- /dev/null
+++ b/include/linux/usb/irda.h
@@ -0,0 +1,151 @@
+/*
+ * USB IrDA Bridge Device Definition
+ */
+
+#ifndef __LINUX_USB_IRDA_H
+#define __LINUX_USB_IRDA_H
+
+/* This device should use Application-specific class */
+
+#define USB_SUBCLASS_IRDA			0x02
+
+/*-------------------------------------------------------------------------*/
+
+/* Class-Specific requests (bRequest field) */
+
+#define USB_REQ_CS_IRDA_RECEIVING		1
+#define USB_REQ_CS_IRDA_CHECK_MEDIA_BUSY	3
+#define USB_REQ_CS_IRDA_RATE_SNIFF		4
+#define USB_REQ_CS_IRDA_UNICAST_LIST		5
+#define USB_REQ_CS_IRDA_GET_CLASS_DESC		6
+
+/*-------------------------------------------------------------------------*/
+
+/* Class-Specific descriptor */
+
+#define USB_DT_CS_IRDA				0x21
+
+/*-------------------------------------------------------------------------*/
+
+/* Data sizes */
+
+#define USB_IRDA_DS_2048			(1 << 5)
+#define USB_IRDA_DS_1024			(1 << 4)
+#define USB_IRDA_DS_512				(1 << 3)
+#define USB_IRDA_DS_256				(1 << 2)
+#define USB_IRDA_DS_128				(1 << 1)
+#define USB_IRDA_DS_64				(1 << 0)
+
+/* Window sizes */
+
+#define USB_IRDA_WS_7				(1 << 6)
+#define USB_IRDA_WS_6				(1 << 5)
+#define USB_IRDA_WS_5				(1 << 4)
+#define USB_IRDA_WS_4				(1 << 3)
+#define USB_IRDA_WS_3				(1 << 2)
+#define USB_IRDA_WS_2				(1 << 1)
+#define USB_IRDA_WS_1				(1 << 0)
+
+/* Min turnaround times in usecs */
+
+#define USB_IRDA_MTT_0				(1 << 7)
+#define USB_IRDA_MTT_10				(1 << 6)
+#define USB_IRDA_MTT_50				(1 << 5)
+#define USB_IRDA_MTT_100			(1 << 4)
+#define USB_IRDA_MTT_500			(1 << 3)
+#define USB_IRDA_MTT_1000			(1 << 2)
+#define USB_IRDA_MTT_5000			(1 << 1)
+#define USB_IRDA_MTT_10000			(1 << 0)
+
+/* Baud rates */
+
+#define USB_IRDA_BR_4000000			(1 << 8)
+#define USB_IRDA_BR_1152000			(1 << 7)
+#define USB_IRDA_BR_576000			(1 << 6)
+#define USB_IRDA_BR_115200			(1 << 5)
+#define USB_IRDA_BR_57600			(1 << 4)
+#define USB_IRDA_BR_38400			(1 << 3)
+#define USB_IRDA_BR_19200			(1 << 2)
+#define USB_IRDA_BR_9600			(1 << 1)
+#define USB_IRDA_BR_2400			(1 << 0)
+
+/* Additional BOFs */
+
+#define USB_IRDA_AB_0				(1 << 7)
+#define USB_IRDA_AB_1				(1 << 6)
+#define USB_IRDA_AB_2				(1 << 5)
+#define USB_IRDA_AB_3				(1 << 4)
+#define USB_IRDA_AB_6				(1 << 3)
+#define USB_IRDA_AB_12				(1 << 2)
+#define USB_IRDA_AB_24				(1 << 1)
+#define USB_IRDA_AB_48				(1 << 0)
+
+/* IRDA Rate Sniff */
+
+#define USB_IRDA_RATE_SNIFF			1
+
+/*-------------------------------------------------------------------------*/
+
+struct usb_irda_cs_descriptor {
+	__u8	bLength;
+	__u8	bDescriptorType;
+
+	__le16	bcdSpecRevision;
+	__u8	bmDataSize;
+	__u8	bmWindowSize;
+	__u8	bmMinTurnaroundTime;
+	__le16	wBaudRate;
+	__u8	bmAdditionalBOFs;
+	__u8	bIrdaRateSniff;
+	__u8	bMaxUnicastList;
+} __attribute__ ((packed));
+
+/*-------------------------------------------------------------------------*/
+
+/* Data Format */
+
+#define USB_IRDA_STATUS_MEDIA_BUSY	(1 << 7)
+
+/* The following is a 4-bit value used for both
+ * inbound and outbound headers:
+ *
+ * 0 - speed ignored
+ * 1 - 2400 bps
+ * 2 - 9600 bps
+ * 3 - 19200 bps
+ * 4 - 38400 bps
+ * 5 - 57600 bps
+ * 6 - 115200 bps
+ * 7 - 576000 bps
+ * 8 - 1.152 Mbps
+ * 9 - 5 mbps
+ * 10..15 - Reserved
+ */
+#define USB_IRDA_STATUS_LINK_SPEED	0x0f
+
+/* The following is a 4-bit value used only for
+ * outbound header:
+ *
+ * 0 - No change (BOF ignored)
+ * 1 - 48 BOFs
+ * 2 - 24 BOFs
+ * 3 - 12 BOFs
+ * 4 - 6 BOFs
+ * 5 - 3 BOFs
+ * 6 - 2 BOFs
+ * 7 - 1 BOFs
+ * 8 - 0 BOFs
+ * 9..15 - Reserved
+ */
+#define USB_IRDA_EXTRA_BOFS		0xf0
+
+struct usb_irda_inbound_header {
+	__u8		bmStatus;
+};
+
+struct usb_irda_outbound_header {
+	__u8		bmChange;
+};
+
+#endif /* __LINUX_USB_IRDA_H */
+
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index 8f891cb..09a3e6a 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -62,7 +62,7 @@
  */
 struct usb_serial_port {
 	struct usb_serial	*serial;
-	struct tty_struct	*tty;
+	struct tty_port		port;
 	spinlock_t		lock;
 	struct mutex            mutex;
 	unsigned char		number;
@@ -89,7 +89,6 @@
 
 	wait_queue_head_t	write_wait;
 	struct work_struct	work;
-	int			open_count;
 	char			throttled;
 	char			throttle_req;
 	char			console;
@@ -217,22 +216,27 @@
 	int (*resume)(struct usb_serial *serial);
 
 	/* serial function calls */
-	int  (*open)(struct usb_serial_port *port, struct file *filp);
-	void (*close)(struct usb_serial_port *port, struct file *filp);
-	int  (*write)(struct usb_serial_port *port, const unsigned char *buf,
-		      int count);
-	int  (*write_room)(struct usb_serial_port *port);
-	int  (*ioctl)(struct usb_serial_port *port, struct file *file,
+	/* Called by console with tty = NULL and by tty */
+	int  (*open)(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
+	void (*close)(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
+	int  (*write)(struct tty_struct *tty, struct usb_serial_port *port,
+			const unsigned char *buf, int count);
+	/* Called only by the tty layer */
+	int  (*write_room)(struct tty_struct *tty);
+	int  (*ioctl)(struct tty_struct *tty, struct file *file,
 		      unsigned int cmd, unsigned long arg);
-	void (*set_termios)(struct usb_serial_port *port, struct ktermios *old);
-	void (*break_ctl)(struct usb_serial_port *port, int break_state);
-	int  (*chars_in_buffer)(struct usb_serial_port *port);
-	void (*throttle)(struct usb_serial_port *port);
-	void (*unthrottle)(struct usb_serial_port *port);
-	int  (*tiocmget)(struct usb_serial_port *port, struct file *file);
-	int  (*tiocmset)(struct usb_serial_port *port, struct file *file,
+	void (*set_termios)(struct tty_struct *tty,
+			struct usb_serial_port *port, struct ktermios *old);
+	void (*break_ctl)(struct tty_struct *tty, int break_state);
+	int  (*chars_in_buffer)(struct tty_struct *tty);
+	void (*throttle)(struct tty_struct *tty);
+	void (*unthrottle)(struct tty_struct *tty);
+	int  (*tiocmget)(struct tty_struct *tty, struct file *file);
+	int  (*tiocmset)(struct tty_struct *tty, struct file *file,
 			 unsigned int set, unsigned int clear);
-
+	/* USB events */
 	void (*read_int_callback)(struct urb *urb);
 	void (*write_int_callback)(struct urb *urb);
 	void (*read_bulk_callback)(struct urb *urb);
@@ -270,19 +274,19 @@
 /* Functions needed by other parts of the usbserial core */
 extern struct usb_serial *usb_serial_get_by_index(unsigned int minor);
 extern void usb_serial_put(struct usb_serial *serial);
-extern int usb_serial_generic_open(struct usb_serial_port *port,
-				   struct file *filp);
-extern int usb_serial_generic_write(struct usb_serial_port *port,
-				    const unsigned char *buf, int count);
-extern void usb_serial_generic_close(struct usb_serial_port *port,
-				     struct file *filp);
+extern int usb_serial_generic_open(struct tty_struct *tty,
+		struct usb_serial_port *port, struct file *filp);
+extern int usb_serial_generic_write(struct tty_struct *tty,
+	struct usb_serial_port *port, const unsigned char *buf, int count);
+extern void usb_serial_generic_close(struct tty_struct *tty,
+			struct usb_serial_port *port, struct file *filp);
 extern int usb_serial_generic_resume(struct usb_serial *serial);
-extern int usb_serial_generic_write_room(struct usb_serial_port *port);
-extern int usb_serial_generic_chars_in_buffer(struct usb_serial_port *port);
+extern int usb_serial_generic_write_room(struct tty_struct *tty);
+extern int usb_serial_generic_chars_in_buffer(struct tty_struct *tty);
 extern void usb_serial_generic_read_bulk_callback(struct urb *urb);
 extern void usb_serial_generic_write_bulk_callback(struct urb *urb);
-extern void usb_serial_generic_throttle(struct usb_serial_port *port);
-extern void usb_serial_generic_unthrottle(struct usb_serial_port *port);
+extern void usb_serial_generic_throttle(struct tty_struct *tty);
+extern void usb_serial_generic_unthrottle(struct tty_struct *tty);
 extern void usb_serial_generic_shutdown(struct usb_serial *serial);
 extern int usb_serial_generic_register(int debug);
 extern void usb_serial_generic_deregister(void);
diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
index 3118ede..0044d9b 100644
--- a/include/linux/usbdevice_fs.h
+++ b/include/linux/usbdevice_fs.h
@@ -22,8 +22,6 @@
  *
  *  History:
  *   0.1  04.01.2000  Created
- *
- *  $Id: usbdevice_fs.h,v 1.1 2000/01/06 18:40:41 tom Exp $
  */
 
 /*****************************************************************************/
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index db66c79..c8effa4 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -193,8 +193,6 @@
 	struct rcu_head		rcu;
 };
 
-extern struct ipv6_devconf ipv6_devconf;
-
 static inline void ipv6_eth_mc_map(struct in6_addr *addr, char *buf)
 {
 	/*
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 9313491..2f8b3c06 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -68,7 +68,7 @@
 extern struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
 					 struct neighbour *neigh,
 					 const struct in6_addr *addr);
-extern int icmp6_dst_gc(int *more);
+extern int icmp6_dst_gc(void);
 
 extern void fib6_force_start_gc(struct net *net);
 
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 8f5b757..0741ad592 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -88,7 +88,6 @@
 	u8 expecting[NF_CT_MAX_EXPECT_CLASSES];
 };
 
-
 #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
 #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
 
@@ -111,11 +110,6 @@
 	/* Timer function; drops refcnt when it goes off. */
 	struct timer_list timeout;
 
-#ifdef CONFIG_NF_CT_ACCT
-	/* Accounting Information (same cache line as other written members) */
-	struct ip_conntrack_counter counters[IP_CT_DIR_MAX];
-#endif
-
 #if defined(CONFIG_NF_CONNTRACK_MARK)
 	u_int32_t mark;
 #endif
diff --git a/include/net/netfilter/nf_conntrack_acct.h b/include/net/netfilter/nf_conntrack_acct.h
new file mode 100644
index 0000000..5d5ae55
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_acct.h
@@ -0,0 +1,51 @@
+/*
+ * (C) 2008 Krzysztof Piotr Oledzki <ole@ans.pl>
+ *
+ * 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 _NF_CONNTRACK_ACCT_H
+#define _NF_CONNTRACK_ACCT_H
+#include <linux/netfilter/nf_conntrack_common.h>
+#include <linux/netfilter/nf_conntrack_tuple_common.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_extend.h>
+
+struct nf_conn_counter {
+	u_int64_t packets;
+	u_int64_t bytes;
+};
+
+extern int nf_ct_acct;
+
+static inline
+struct nf_conn_counter *nf_conn_acct_find(const struct nf_conn *ct)
+{
+	return nf_ct_ext_find(ct, NF_CT_EXT_ACCT);
+}
+
+static inline
+struct nf_conn_counter *nf_ct_acct_ext_add(struct nf_conn *ct, gfp_t gfp)
+{
+	struct nf_conn_counter *acct;
+
+	if (!nf_ct_acct)
+		return NULL;
+
+	acct = nf_ct_ext_add(ct, NF_CT_EXT_ACCT, gfp);
+	if (!acct)
+		pr_debug("failed to add accounting extension area");
+
+
+	return acct;
+};
+
+extern unsigned int
+seq_print_acct(struct seq_file *s, const struct nf_conn *ct, int dir);
+
+extern int nf_conntrack_acct_init(void);
+extern void nf_conntrack_acct_fini(void);
+
+#endif /* _NF_CONNTRACK_ACCT_H */
diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h
index f80c0ed..da8ee52 100644
--- a/include/net/netfilter/nf_conntrack_extend.h
+++ b/include/net/netfilter/nf_conntrack_extend.h
@@ -7,11 +7,13 @@
 {
 	NF_CT_EXT_HELPER,
 	NF_CT_EXT_NAT,
+	NF_CT_EXT_ACCT,
 	NF_CT_EXT_NUM,
 };
 
 #define NF_CT_EXT_HELPER_TYPE struct nf_conn_help
 #define NF_CT_EXT_NAT_TYPE struct nf_conn_nat
+#define NF_CT_EXT_ACCT_TYPE struct nf_conn_counter
 
 /* Extensions: optional stuff which isn't permanently in struct. */
 struct nf_ct_ext {
diff --git a/include/net/netlink.h b/include/net/netlink.h
index dfc3701..18024b8 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -896,6 +896,9 @@
 #define NLA_PUT_U64(skb, attrtype, value) \
 	NLA_PUT_TYPE(skb, u64, attrtype, value)
 
+#define NLA_PUT_BE64(skb, attrtype, value) \
+	NLA_PUT_TYPE(skb, __be64, attrtype, value)
+
 #define NLA_PUT_STRING(skb, attrtype, value) \
 	NLA_PUT(skb, attrtype, strlen(value) + 1, value)
 
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index 5bacd83..2932721 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -39,7 +39,7 @@
 #endif
 	struct rt6_info         *ip6_null_entry;
 	struct rt6_statistics   *rt6_stats;
-	struct timer_list       *ip6_fib_timer;
+	struct timer_list       ip6_fib_timer;
 	struct hlist_head       *fib_table_hash;
 	struct fib6_table       *fib6_main_tbl;
 	struct dst_ops		*ip6_dst_ops;
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 70eb64a..535a18f 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1161,7 +1161,6 @@
 void sctp_outq_teardown(struct sctp_outq *);
 void sctp_outq_free(struct sctp_outq*);
 int sctp_outq_tail(struct sctp_outq *, struct sctp_chunk *chunk);
-int sctp_outq_flush(struct sctp_outq *, int);
 int sctp_outq_sack(struct sctp_outq *, struct sctp_sackhdr *);
 int sctp_outq_is_empty(const struct sctp_outq *);
 void sctp_outq_restart(struct sctp_outq *);
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 1834fdf..a594bac 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -623,7 +623,7 @@
 	/*
 	 * Optional work queue to be utilized by the transport
 	 */
-	char work_q_name[KOBJ_NAME_LEN];
+	char work_q_name[20];
 	struct workqueue_struct *work_q;
 
 	/*
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 06f72ba..878373c 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -489,9 +489,9 @@
 	u16 npiv_vports_inuse;
 
 	/* work queues for rport state manipulation */
-	char work_q_name[KOBJ_NAME_LEN];
+	char work_q_name[20];
 	struct workqueue_struct *work_q;
-	char devloss_work_q_name[KOBJ_NAME_LEN];
+	char devloss_work_q_name[20];
 	struct workqueue_struct *devloss_work_q;
 };
 
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index f5444e0..8b6c91d 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -198,7 +198,7 @@
 	atomic_t nr_scans;
 	struct mutex mutex;
 	struct workqueue_struct *scan_workq;
-	char scan_workq_name[KOBJ_NAME_LEN];
+	char scan_workq_name[20];
 };
 
 extern void iscsi_host_for_each_session(struct Scsi_Host *shost,
diff --git a/include/xen/events.h b/include/xen/events.h
index 67c4436..4680ff3 100644
--- a/include/xen/events.h
+++ b/include/xen/events.h
@@ -44,4 +44,11 @@
 
 extern void xen_irq_resume(void);
 
+/* Clear an irq's pending state, in preparation for polling on it */
+void xen_clear_irq_pending(int irq);
+
+/* Poll waiting for an irq to become pending.  In the usual case, the
+   irq will be disabled so it won't deliver an interrupt. */
+void xen_poll_irq(int irq);
+
 #endif	/* _XEN_EVENTS_H */
diff --git a/include/xen/hvc-console.h b/include/xen/hvc-console.h
index 98b79bc..c3adde3 100644
--- a/include/xen/hvc-console.h
+++ b/include/xen/hvc-console.h
@@ -5,11 +5,12 @@
 
 #ifdef CONFIG_HVC_XEN
 void xen_console_resume(void);
-#else
-static inline void xen_console_resume(void) { }
-#endif
-
 void xen_raw_console_write(const char *str);
 void xen_raw_printk(const char *fmt, ...);
+#else
+static inline void xen_console_resume(void) { }
+static inline void xen_raw_console_write(const char *str) { }
+static inline void xen_raw_printk(const char *fmt, ...) { }
+#endif
 
 #endif	/* XEN_HVC_CONSOLE_H */
diff --git a/include/xen/interface/callback.h b/include/xen/interface/callback.h
index 4aadcba..2ae3cd2 100644
--- a/include/xen/interface/callback.h
+++ b/include/xen/interface/callback.h
@@ -82,9 +82,9 @@
  */
 #define CALLBACKOP_register                0
 struct callback_register {
-    uint16_t type;
-    uint16_t flags;
-    struct xen_callback address;
+	uint16_t type;
+	uint16_t flags;
+	xen_callback_t address;
 };
 
 /*
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
index a706d6a..883a21b 100644
--- a/include/xen/xen-ops.h
+++ b/include/xen/xen-ops.h
@@ -11,4 +11,7 @@
 void xen_mm_pin_all(void);
 void xen_mm_unpin_all(void);
 
+void xen_timer_resume(void);
+void xen_arch_resume(void);
+
 #endif /* INCLUDE_XEN_OPS_H */
diff --git a/init/Kconfig b/init/Kconfig
index 6199d11..a50bdfed 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -856,8 +856,8 @@
 	help
 	  Without this option you will not be able to unload any
 	  modules (note that some modules may not be unloadable
-	  anyway), which makes your kernel slightly smaller and
-	  simpler.  If unsure, say Y.
+	  anyway), which makes your kernel smaller, faster
+	  and simpler.  If unsure, say Y.
 
 config MODULE_FORCE_UNLOAD
 	bool "Forced module unloading"
@@ -893,16 +893,11 @@
 	  will be created for all modules.  If unsure, say N.
 
 config KMOD
-	bool "Automatic kernel module loading"
+	def_bool y
 	depends on MODULES
 	help
-	  Normally when you have selected some parts of the kernel to
-	  be created as kernel modules, you must load them (using the
-	  "modprobe" command) before you can use them. If you say Y
-	  here, some parts of the kernel will be able to load modules
-	  automatically: when a part of the kernel needs a module, it
-	  runs modprobe with the appropriate arguments, thereby
-	  loading the module if it is available.  If unsure, say Y.
+	  This is being removed soon.  These days, CONFIG_MODULES
+	  implies CONFIG_KMOD, so use that instead.
 
 config STOP_MACHINE
 	bool
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 459d601..d2cc67d 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -679,7 +679,9 @@
 				if (apn == b->pn) {
 					cpus_or(*dp, *dp, b->cpus_allowed);
 					b->pn = -1;
-					update_domain_attr(dattr, b);
+					if (dattr)
+						update_domain_attr(dattr
+								   + nslot, b);
 				}
 			}
 			nslot++;
diff --git a/kernel/exec_domain.c b/kernel/exec_domain.c
index a9e6bad..c1ef192 100644
--- a/kernel/exec_domain.c
+++ b/kernel/exec_domain.c
@@ -65,7 +65,7 @@
 				goto out;
 	}
 
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
 	read_unlock(&exec_domains_lock);
 	request_module("personality-%ld", pers);
 	read_lock(&exec_domains_lock);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 77a51be..3cfc0fe 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -217,6 +217,17 @@
 }
 EXPORT_SYMBOL(enable_irq);
 
+int set_irq_wake_real(unsigned int irq, unsigned int on)
+{
+	struct irq_desc *desc = irq_desc + irq;
+	int ret = -ENXIO;
+
+	if (desc->chip->set_wake)
+		ret = desc->chip->set_wake(irq, on);
+
+	return ret;
+}
+
 /**
  *	set_irq_wake - control irq power management wakeup
  *	@irq:	interrupt to control
@@ -233,30 +244,34 @@
 {
 	struct irq_desc *desc = irq_desc + irq;
 	unsigned long flags;
-	int ret = -ENXIO;
-	int (*set_wake)(unsigned, unsigned) = desc->chip->set_wake;
+	int ret = 0;
 
 	/* wakeup-capable irqs can be shared between drivers that
 	 * don't need to have the same sleep mode behaviors.
 	 */
 	spin_lock_irqsave(&desc->lock, flags);
 	if (on) {
-		if (desc->wake_depth++ == 0)
-			desc->status |= IRQ_WAKEUP;
-		else
-			set_wake = NULL;
+		if (desc->wake_depth++ == 0) {
+			ret = set_irq_wake_real(irq, on);
+			if (ret)
+				desc->wake_depth = 0;
+			else
+				desc->status |= IRQ_WAKEUP;
+		}
 	} else {
 		if (desc->wake_depth == 0) {
 			printk(KERN_WARNING "Unbalanced IRQ %d "
 					"wake disable\n", irq);
 			WARN_ON(1);
-		} else if (--desc->wake_depth == 0)
-			desc->status &= ~IRQ_WAKEUP;
-		else
-			set_wake = NULL;
+		} else if (--desc->wake_depth == 0) {
+			ret = set_irq_wake_real(irq, on);
+			if (ret)
+				desc->wake_depth = 1;
+			else
+				desc->status &= ~IRQ_WAKEUP;
+		}
 	}
-	if (set_wake)
-		ret = desc->chip->set_wake(irq, on);
+
 	spin_unlock_irqrestore(&desc->lock, flags);
 	return ret;
 }
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 8df97d3..90d7af1 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -42,7 +42,7 @@
 
 static struct workqueue_struct *khelper_wq;
 
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
 
 /*
 	modprobe_path is set via /proc/sys.
diff --git a/kernel/module.c b/kernel/module.c
index 5f80478..d8b5605 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -70,6 +70,9 @@
 
 static BLOCKING_NOTIFIER_HEAD(module_notify_list);
 
+/* Bounds of module allocation, for speeding __module_text_address */
+static unsigned long module_addr_min = -1UL, module_addr_max = 0;
+
 int register_module_notifier(struct notifier_block * nb)
 {
 	return blocking_notifier_chain_register(&module_notify_list, nb);
@@ -134,17 +137,19 @@
 extern const struct kernel_symbol __stop___ksymtab_gpl[];
 extern const struct kernel_symbol __start___ksymtab_gpl_future[];
 extern const struct kernel_symbol __stop___ksymtab_gpl_future[];
-extern const struct kernel_symbol __start___ksymtab_unused[];
-extern const struct kernel_symbol __stop___ksymtab_unused[];
-extern const struct kernel_symbol __start___ksymtab_unused_gpl[];
-extern const struct kernel_symbol __stop___ksymtab_unused_gpl[];
 extern const struct kernel_symbol __start___ksymtab_gpl_future[];
 extern const struct kernel_symbol __stop___ksymtab_gpl_future[];
 extern const unsigned long __start___kcrctab[];
 extern const unsigned long __start___kcrctab_gpl[];
 extern const unsigned long __start___kcrctab_gpl_future[];
+#ifdef CONFIG_UNUSED_SYMBOLS
+extern const struct kernel_symbol __start___ksymtab_unused[];
+extern const struct kernel_symbol __stop___ksymtab_unused[];
+extern const struct kernel_symbol __start___ksymtab_unused_gpl[];
+extern const struct kernel_symbol __stop___ksymtab_unused_gpl[];
 extern const unsigned long __start___kcrctab_unused[];
 extern const unsigned long __start___kcrctab_unused_gpl[];
+#endif
 
 #ifndef CONFIG_MODVERSIONS
 #define symversion(base, idx) NULL
@@ -152,6 +157,174 @@
 #define symversion(base, idx) ((base != NULL) ? ((base) + (idx)) : NULL)
 #endif
 
+struct symsearch {
+	const struct kernel_symbol *start, *stop;
+	const unsigned long *crcs;
+	enum {
+		NOT_GPL_ONLY,
+		GPL_ONLY,
+		WILL_BE_GPL_ONLY,
+	} licence;
+	bool unused;
+};
+
+static bool each_symbol_in_section(const struct symsearch *arr,
+				   unsigned int arrsize,
+				   struct module *owner,
+				   bool (*fn)(const struct symsearch *syms,
+					      struct module *owner,
+					      unsigned int symnum, void *data),
+				   void *data)
+{
+	unsigned int i, j;
+
+	for (j = 0; j < arrsize; j++) {
+		for (i = 0; i < arr[j].stop - arr[j].start; i++)
+			if (fn(&arr[j], owner, i, data))
+				return true;
+	}
+
+	return false;
+}
+
+/* Returns true as soon as fn returns true, otherwise false. */
+static bool each_symbol(bool (*fn)(const struct symsearch *arr,
+				   struct module *owner,
+				   unsigned int symnum, void *data),
+			void *data)
+{
+	struct module *mod;
+	const struct symsearch arr[] = {
+		{ __start___ksymtab, __stop___ksymtab, __start___kcrctab,
+		  NOT_GPL_ONLY, false },
+		{ __start___ksymtab_gpl, __stop___ksymtab_gpl,
+		  __start___kcrctab_gpl,
+		  GPL_ONLY, false },
+		{ __start___ksymtab_gpl_future, __stop___ksymtab_gpl_future,
+		  __start___kcrctab_gpl_future,
+		  WILL_BE_GPL_ONLY, false },
+#ifdef CONFIG_UNUSED_SYMBOLS
+		{ __start___ksymtab_unused, __stop___ksymtab_unused,
+		  __start___kcrctab_unused,
+		  NOT_GPL_ONLY, true },
+		{ __start___ksymtab_unused_gpl, __stop___ksymtab_unused_gpl,
+		  __start___kcrctab_unused_gpl,
+		  GPL_ONLY, true },
+#endif
+	};
+
+	if (each_symbol_in_section(arr, ARRAY_SIZE(arr), NULL, fn, data))
+		return true;
+
+	list_for_each_entry(mod, &modules, list) {
+		struct symsearch arr[] = {
+			{ mod->syms, mod->syms + mod->num_syms, mod->crcs,
+			  NOT_GPL_ONLY, false },
+			{ mod->gpl_syms, mod->gpl_syms + mod->num_gpl_syms,
+			  mod->gpl_crcs,
+			  GPL_ONLY, false },
+			{ mod->gpl_future_syms,
+			  mod->gpl_future_syms + mod->num_gpl_future_syms,
+			  mod->gpl_future_crcs,
+			  WILL_BE_GPL_ONLY, false },
+#ifdef CONFIG_UNUSED_SYMBOLS
+			{ mod->unused_syms,
+			  mod->unused_syms + mod->num_unused_syms,
+			  mod->unused_crcs,
+			  NOT_GPL_ONLY, true },
+			{ mod->unused_gpl_syms,
+			  mod->unused_gpl_syms + mod->num_unused_gpl_syms,
+			  mod->unused_gpl_crcs,
+			  GPL_ONLY, true },
+#endif
+		};
+
+		if (each_symbol_in_section(arr, ARRAY_SIZE(arr), mod, fn, data))
+			return true;
+	}
+	return false;
+}
+
+struct find_symbol_arg {
+	/* Input */
+	const char *name;
+	bool gplok;
+	bool warn;
+
+	/* Output */
+	struct module *owner;
+	const unsigned long *crc;
+	unsigned long value;
+};
+
+static bool find_symbol_in_section(const struct symsearch *syms,
+				   struct module *owner,
+				   unsigned int symnum, void *data)
+{
+	struct find_symbol_arg *fsa = data;
+
+	if (strcmp(syms->start[symnum].name, fsa->name) != 0)
+		return false;
+
+	if (!fsa->gplok) {
+		if (syms->licence == GPL_ONLY)
+			return false;
+		if (syms->licence == WILL_BE_GPL_ONLY && fsa->warn) {
+			printk(KERN_WARNING "Symbol %s is being used "
+			       "by a non-GPL module, which will not "
+			       "be allowed in the future\n", fsa->name);
+			printk(KERN_WARNING "Please see the file "
+			       "Documentation/feature-removal-schedule.txt "
+			       "in the kernel source tree for more details.\n");
+		}
+	}
+
+#ifdef CONFIG_UNUSED_SYMBOLS
+	if (syms->unused && fsa->warn) {
+		printk(KERN_WARNING "Symbol %s is marked as UNUSED, "
+		       "however this module is using it.\n", fsa->name);
+		printk(KERN_WARNING
+		       "This symbol will go away in the future.\n");
+		printk(KERN_WARNING
+		       "Please evalute if this is the right api to use and if "
+		       "it really is, submit a report the linux kernel "
+		       "mailinglist together with submitting your code for "
+		       "inclusion.\n");
+	}
+#endif
+
+	fsa->owner = owner;
+	fsa->crc = symversion(syms->crcs, symnum);
+	fsa->value = syms->start[symnum].value;
+	return true;
+}
+
+/* Find a symbol, return value, (optional) crc and (optional) module
+ * which owns it */
+static unsigned long find_symbol(const char *name,
+				 struct module **owner,
+				 const unsigned long **crc,
+				 bool gplok,
+				 bool warn)
+{
+	struct find_symbol_arg fsa;
+
+	fsa.name = name;
+	fsa.gplok = gplok;
+	fsa.warn = warn;
+
+	if (each_symbol(find_symbol_in_section, &fsa)) {
+		if (owner)
+			*owner = fsa.owner;
+		if (crc)
+			*crc = fsa.crc;
+		return fsa.value;
+	}
+
+	DEBUGP("Failed to find symbol %s\n", name);
+	return -ENOENT;
+}
+
 /* lookup symbol in given range of kernel_symbols */
 static const struct kernel_symbol *lookup_symbol(const char *name,
 	const struct kernel_symbol *start,
@@ -164,144 +337,6 @@
 	return NULL;
 }
 
-static bool always_ok(bool gplok, bool warn, const char *name)
-{
-	return true;
-}
-
-static bool printk_unused_warning(bool gplok, bool warn, const char *name)
-{
-	if (warn) {
-		printk(KERN_WARNING "Symbol %s is marked as UNUSED, "
-		       "however this module is using it.\n", name);
-		printk(KERN_WARNING
-		       "This symbol will go away in the future.\n");
-		printk(KERN_WARNING
-		       "Please evalute if this is the right api to use and if "
-		       "it really is, submit a report the linux kernel "
-		       "mailinglist together with submitting your code for "
-		       "inclusion.\n");
-	}
-	return true;
-}
-
-static bool gpl_only_unused_warning(bool gplok, bool warn, const char *name)
-{
-	if (!gplok)
-		return false;
-	return printk_unused_warning(gplok, warn, name);
-}
-
-static bool gpl_only(bool gplok, bool warn, const char *name)
-{
-	return gplok;
-}
-
-static bool warn_if_not_gpl(bool gplok, bool warn, const char *name)
-{
-	if (!gplok && warn) {
-		printk(KERN_WARNING "Symbol %s is being used "
-		       "by a non-GPL module, which will not "
-		       "be allowed in the future\n", name);
-		printk(KERN_WARNING "Please see the file "
-		       "Documentation/feature-removal-schedule.txt "
-		       "in the kernel source tree for more details.\n");
-	}
-	return true;
-}
-
-struct symsearch {
-	const struct kernel_symbol *start, *stop;
-	const unsigned long *crcs;
-	bool (*check)(bool gplok, bool warn, const char *name);
-};
-
-/* Look through this array of symbol tables for a symbol match which
- * passes the check function. */
-static const struct kernel_symbol *search_symarrays(const struct symsearch *arr,
-						    unsigned int num,
-						    const char *name,
-						    bool gplok,
-						    bool warn,
-						    const unsigned long **crc)
-{
-	unsigned int i;
-	const struct kernel_symbol *ks;
-
-	for (i = 0; i < num; i++) {
-		ks = lookup_symbol(name, arr[i].start, arr[i].stop);
-		if (!ks || !arr[i].check(gplok, warn, name))
-			continue;
-
-		if (crc)
-			*crc = symversion(arr[i].crcs, ks - arr[i].start);
-		return ks;
-	}
-	return NULL;
-}
-
-/* Find a symbol, return value, (optional) crc and (optional) module
- * which owns it */
-static unsigned long find_symbol(const char *name,
-				 struct module **owner,
-				 const unsigned long **crc,
-				 bool gplok,
-				 bool warn)
-{
-	struct module *mod;
-	const struct kernel_symbol *ks;
-	const struct symsearch arr[] = {
-		{ __start___ksymtab, __stop___ksymtab, __start___kcrctab,
-		  always_ok },
-		{ __start___ksymtab_gpl, __stop___ksymtab_gpl,
-		  __start___kcrctab_gpl, gpl_only },
-		{ __start___ksymtab_gpl_future, __stop___ksymtab_gpl_future,
-		  __start___kcrctab_gpl_future, warn_if_not_gpl },
-		{ __start___ksymtab_unused, __stop___ksymtab_unused,
-		  __start___kcrctab_unused, printk_unused_warning },
-		{ __start___ksymtab_unused_gpl, __stop___ksymtab_unused_gpl,
-		  __start___kcrctab_unused_gpl, gpl_only_unused_warning },
-	};
-
-	/* Core kernel first. */
-	ks = search_symarrays(arr, ARRAY_SIZE(arr), name, gplok, warn, crc);
-	if (ks) {
-		if (owner)
-			*owner = NULL;
-		return ks->value;
-	}
-
-	/* Now try modules. */
-	list_for_each_entry(mod, &modules, list) {
-		struct symsearch arr[] = {
-			{ mod->syms, mod->syms + mod->num_syms, mod->crcs,
-			  always_ok },
-			{ mod->gpl_syms, mod->gpl_syms + mod->num_gpl_syms,
-			  mod->gpl_crcs, gpl_only },
-			{ mod->gpl_future_syms,
-			  mod->gpl_future_syms + mod->num_gpl_future_syms,
-			  mod->gpl_future_crcs, warn_if_not_gpl },
-			{ mod->unused_syms,
-			  mod->unused_syms + mod->num_unused_syms,
-			  mod->unused_crcs, printk_unused_warning },
-			{ mod->unused_gpl_syms,
-			  mod->unused_gpl_syms + mod->num_unused_gpl_syms,
-			  mod->unused_gpl_crcs, gpl_only_unused_warning },
-		};
-
-		ks = search_symarrays(arr, ARRAY_SIZE(arr),
-				      name, gplok, warn, crc);
-		if (ks) {
-			if (owner)
-				*owner = mod;
-			return ks->value;
-		}
-	}
-
-	DEBUGP("Failed to find symbol %s\n", name);
-	return -ENOENT;
-}
-
 /* Search for module by name: must hold module_mutex. */
 static struct module *find_module(const char *name)
 {
@@ -639,8 +674,8 @@
 {
 	struct stopref *sref = _sref;
 
-	/* If it's not unused, quit unless we are told to block. */
-	if ((sref->flags & O_NONBLOCK) && module_refcount(sref->mod) != 0) {
+	/* If it's not unused, quit unless we're forcing. */
+	if (module_refcount(sref->mod) != 0) {
 		if (!(*sref->forced = try_force_unload(sref->flags)))
 			return -EWOULDBLOCK;
 	}
@@ -652,9 +687,16 @@
 
 static int try_stop_module(struct module *mod, int flags, int *forced)
 {
-	struct stopref sref = { mod, flags, forced };
+	if (flags & O_NONBLOCK) {
+		struct stopref sref = { mod, flags, forced };
 
-	return stop_machine_run(__try_stop_module, &sref, NR_CPUS);
+		return stop_machine_run(__try_stop_module, &sref, NR_CPUS);
+	} else {
+		/* We don't need to stop the machine for this. */
+		mod->state = MODULE_STATE_GOING;
+		synchronize_sched();
+		return 0;
+	}
 }
 
 unsigned int module_refcount(struct module *mod)
@@ -1445,8 +1487,10 @@
 		{ mod->syms, mod->num_syms },
 		{ mod->gpl_syms, mod->num_gpl_syms },
 		{ mod->gpl_future_syms, mod->num_gpl_future_syms },
+#ifdef CONFIG_UNUSED_SYMBOLS
 		{ mod->unused_syms, mod->num_unused_syms },
 		{ mod->unused_gpl_syms, mod->num_unused_gpl_syms },
+#endif
 	};
 
 	for (i = 0; i < ARRAY_SIZE(arr); i++) {
@@ -1526,7 +1570,7 @@
 }
 
 /* Update size with this section: return offset. */
-static long get_offset(unsigned long *size, Elf_Shdr *sechdr)
+static long get_offset(unsigned int *size, Elf_Shdr *sechdr)
 {
 	long ret;
 
@@ -1738,6 +1782,20 @@
 }
 #endif /* CONFIG_KALLSYMS */
 
+static void *module_alloc_update_bounds(unsigned long size)
+{
+	void *ret = module_alloc(size);
+
+	if (ret) {
+		/* Update module bounds. */
+		if ((unsigned long)ret < module_addr_min)
+			module_addr_min = (unsigned long)ret;
+		if ((unsigned long)ret + size > module_addr_max)
+			module_addr_max = (unsigned long)ret + size;
+	}
+	return ret;
+}
+
 /* Allocate and load the module: note that size of section 0 is always
    zero, and we rely on this for optional sections. */
 static struct module *load_module(void __user *umod,
@@ -1764,10 +1822,12 @@
 	unsigned int gplfutureindex;
 	unsigned int gplfuturecrcindex;
 	unsigned int unwindex = 0;
+#ifdef CONFIG_UNUSED_SYMBOLS
 	unsigned int unusedindex;
 	unsigned int unusedcrcindex;
 	unsigned int unusedgplindex;
 	unsigned int unusedgplcrcindex;
+#endif
 	unsigned int markersindex;
 	unsigned int markersstringsindex;
 	struct module *mod;
@@ -1850,13 +1910,15 @@
 	exportindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab");
 	gplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl");
 	gplfutureindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl_future");
-	unusedindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused");
-	unusedgplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused_gpl");
 	crcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab");
 	gplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl");
 	gplfuturecrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl_future");
+#ifdef CONFIG_UNUSED_SYMBOLS
+	unusedindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused");
+	unusedgplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused_gpl");
 	unusedcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused");
 	unusedgplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused_gpl");
+#endif
 	setupindex = find_sec(hdr, sechdrs, secstrings, "__param");
 	exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table");
 	obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm");
@@ -1935,7 +1997,7 @@
 	layout_sections(mod, hdr, sechdrs, secstrings);
 
 	/* Do the allocs. */
-	ptr = module_alloc(mod->core_size);
+	ptr = module_alloc_update_bounds(mod->core_size);
 	if (!ptr) {
 		err = -ENOMEM;
 		goto free_percpu;
@@ -1943,7 +2005,7 @@
 	memset(ptr, 0, mod->core_size);
 	mod->module_core = ptr;
 
-	ptr = module_alloc(mod->init_size);
+	ptr = module_alloc_update_bounds(mod->init_size);
 	if (!ptr && mod->init_size) {
 		err = -ENOMEM;
 		goto free_core;
@@ -2018,14 +2080,15 @@
 		mod->gpl_crcs = (void *)sechdrs[gplcrcindex].sh_addr;
 	mod->num_gpl_future_syms = sechdrs[gplfutureindex].sh_size /
 					sizeof(*mod->gpl_future_syms);
-	mod->num_unused_syms = sechdrs[unusedindex].sh_size /
-					sizeof(*mod->unused_syms);
-	mod->num_unused_gpl_syms = sechdrs[unusedgplindex].sh_size /
-					sizeof(*mod->unused_gpl_syms);
 	mod->gpl_future_syms = (void *)sechdrs[gplfutureindex].sh_addr;
 	if (gplfuturecrcindex)
 		mod->gpl_future_crcs = (void *)sechdrs[gplfuturecrcindex].sh_addr;
 
+#ifdef CONFIG_UNUSED_SYMBOLS
+	mod->num_unused_syms = sechdrs[unusedindex].sh_size /
+					sizeof(*mod->unused_syms);
+	mod->num_unused_gpl_syms = sechdrs[unusedgplindex].sh_size /
+					sizeof(*mod->unused_gpl_syms);
 	mod->unused_syms = (void *)sechdrs[unusedindex].sh_addr;
 	if (unusedcrcindex)
 		mod->unused_crcs = (void *)sechdrs[unusedcrcindex].sh_addr;
@@ -2033,13 +2096,17 @@
 	if (unusedgplcrcindex)
 		mod->unused_gpl_crcs
 			= (void *)sechdrs[unusedgplcrcindex].sh_addr;
+#endif
 
 #ifdef CONFIG_MODVERSIONS
-	if ((mod->num_syms && !crcindex) ||
-	    (mod->num_gpl_syms && !gplcrcindex) ||
-	    (mod->num_gpl_future_syms && !gplfuturecrcindex) ||
-	    (mod->num_unused_syms && !unusedcrcindex) ||
-	    (mod->num_unused_gpl_syms && !unusedgplcrcindex)) {
+	if ((mod->num_syms && !crcindex)
+	    || (mod->num_gpl_syms && !gplcrcindex)
+	    || (mod->num_gpl_future_syms && !gplfuturecrcindex)
+#ifdef CONFIG_UNUSED_SYMBOLS
+	    || (mod->num_unused_syms && !unusedcrcindex)
+	    || (mod->num_unused_gpl_syms && !unusedgplcrcindex)
+#endif
+		) {
 		printk(KERN_WARNING "%s: No versions for exported symbols.\n", mod->name);
 		err = try_to_force_load(mod, "nocrc");
 		if (err)
@@ -2512,7 +2579,7 @@
 	struct module *mod = list_entry(p, struct module, list);
 	char buf[8];
 
-	seq_printf(m, "%s %lu",
+	seq_printf(m, "%s %u",
 		   mod->name, mod->init_size + mod->core_size);
 	print_unload_info(m, mod);
 
@@ -2595,6 +2662,9 @@
 {
 	struct module *mod;
 
+	if (addr < module_addr_min || addr > module_addr_max)
+		return NULL;
+
 	list_for_each_entry(mod, &modules, list)
 		if (within(addr, mod->module_init, mod->init_text_size)
 		    || within(addr, mod->module_core, mod->core_text_size))
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index b45da40..59dfdf1 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -82,7 +82,7 @@
 
 config PM_SLEEP
 	bool
-	depends on SUSPEND || HIBERNATION
+	depends on SUSPEND || HIBERNATION || XEN_SAVE_RESTORE
 	default y
 
 config SUSPEND
diff --git a/kernel/rtmutex-tester.c b/kernel/rtmutex-tester.c
index 092e4c6..a56f629 100644
--- a/kernel/rtmutex-tester.c
+++ b/kernel/rtmutex-tester.c
@@ -297,8 +297,8 @@
  *
  * opcode:data
  */
-static ssize_t sysfs_test_command(struct sys_device *dev, const char *buf,
-				  size_t count)
+static ssize_t sysfs_test_command(struct sys_device *dev, struct sysdev_attribute *attr,
+				  const char *buf, size_t count)
 {
 	struct sched_param schedpar;
 	struct test_thread_data *td;
@@ -360,7 +360,8 @@
  * @dev:	thread to query
  * @buf:	char buffer to be filled with thread status info
  */
-static ssize_t sysfs_test_status(struct sys_device *dev, char *buf)
+static ssize_t sysfs_test_status(struct sys_device *dev, struct sysdev_attribute *attr,
+				 char *buf)
 {
 	struct test_thread_data *td;
 	struct task_struct *tsk;
diff --git a/kernel/sched.c b/kernel/sched.c
index a6d0a7f..df80bae 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -7737,11 +7737,13 @@
 }
 
 #ifdef CONFIG_SCHED_MC
-static ssize_t sched_mc_power_savings_show(struct sys_device *dev, char *page)
+static ssize_t sched_mc_power_savings_show(struct sys_device *dev,
+				struct sysdev_attribute *attr, char *page)
 {
 	return sprintf(page, "%u\n", sched_mc_power_savings);
 }
 static ssize_t sched_mc_power_savings_store(struct sys_device *dev,
+					    struct sysdev_attribute *attr,
 					    const char *buf, size_t count)
 {
 	return sched_power_savings_store(buf, count, 0);
@@ -7751,11 +7753,13 @@
 #endif
 
 #ifdef CONFIG_SCHED_SMT
-static ssize_t sched_smt_power_savings_show(struct sys_device *dev, char *page)
+static ssize_t sched_smt_power_savings_show(struct sys_device *dev,
+				struct sysdev_attribute *attr, char *page)
 {
 	return sprintf(page, "%u\n", sched_smt_power_savings);
 }
 static ssize_t sched_smt_power_savings_store(struct sys_device *dev,
+					     struct sysdev_attribute *attr,
 					     const char *buf, size_t count)
 {
 	return sched_power_savings_store(buf, count, 1);
diff --git a/kernel/softlockup.c b/kernel/softlockup.c
index a272d78..7bd8d1a 100644
--- a/kernel/softlockup.c
+++ b/kernel/softlockup.c
@@ -13,6 +13,7 @@
 #include <linux/delay.h>
 #include <linux/freezer.h>
 #include <linux/kthread.h>
+#include <linux/lockdep.h>
 #include <linux/notifier.h>
 #include <linux/module.h>
 
@@ -25,7 +26,22 @@
 static DEFINE_PER_CPU(struct task_struct *, watchdog_task);
 
 static int __read_mostly did_panic;
-unsigned long __read_mostly softlockup_thresh = 60;
+int __read_mostly softlockup_thresh = 60;
+
+/*
+ * Should we panic (and reboot, if panic_timeout= is set) when a
+ * soft-lockup occurs:
+ */
+unsigned int __read_mostly softlockup_panic =
+				CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE;
+
+static int __init softlockup_panic_setup(char *str)
+{
+	softlockup_panic = simple_strtoul(str, NULL, 0);
+
+	return 1;
+}
+__setup("softlockup_panic=", softlockup_panic_setup);
 
 static int
 softlock_panic(struct notifier_block *this, unsigned long event, void *ptr)
@@ -84,6 +100,14 @@
 	struct pt_regs *regs = get_irq_regs();
 	unsigned long now;
 
+	/* Is detection switched off? */
+	if (!per_cpu(watchdog_task, this_cpu) || softlockup_thresh <= 0) {
+		/* Be sure we don't false trigger if switched back on */
+		if (touch_timestamp)
+			per_cpu(touch_timestamp, this_cpu) = 0;
+		return;
+	}
+
 	if (touch_timestamp == 0) {
 		__touch_softlockup_watchdog();
 		return;
@@ -92,11 +116,8 @@
 	print_timestamp = per_cpu(print_timestamp, this_cpu);
 
 	/* report at most once a second */
-	if ((print_timestamp >= touch_timestamp &&
-			print_timestamp < (touch_timestamp + 1)) ||
-			did_panic || !per_cpu(watchdog_task, this_cpu)) {
+	if (print_timestamp == touch_timestamp || did_panic)
 		return;
-	}
 
 	/* do not print during early bootup: */
 	if (unlikely(system_state != SYSTEM_RUNNING)) {
@@ -106,8 +127,11 @@
 
 	now = get_timestamp(this_cpu);
 
-	/* Wake up the high-prio watchdog task every second: */
-	if (now > (touch_timestamp + 1))
+	/*
+	 * Wake up the high-prio watchdog task twice per
+	 * threshold timespan.
+	 */
+	if (now > touch_timestamp + softlockup_thresh/2)
 		wake_up_process(per_cpu(watchdog_task, this_cpu));
 
 	/* Warn about unreasonable delays: */
@@ -121,11 +145,15 @@
 			this_cpu, now - touch_timestamp,
 			current->comm, task_pid_nr(current));
 	print_modules();
+	print_irqtrace_events(current);
 	if (regs)
 		show_regs(regs);
 	else
 		dump_stack();
 	spin_unlock(&print_lock);
+
+	if (softlockup_panic)
+		panic("softlockup: hung tasks");
 }
 
 /*
@@ -178,6 +206,9 @@
 
 	t->last_switch_timestamp = now;
 	touch_nmi_watchdog();
+
+	if (softlockup_panic)
+		panic("softlockup: blocked tasks");
 }
 
 /*
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 5b9b467..0fea0ee 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -59,6 +59,7 @@
 cond_syscall(sys_epoll_ctl);
 cond_syscall(sys_epoll_wait);
 cond_syscall(sys_epoll_pwait);
+cond_syscall(compat_sys_epoll_pwait);
 cond_syscall(sys_semget);
 cond_syscall(sys_semop);
 cond_syscall(sys_semtimedop);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 6b16e16..2a7b9d8 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -88,12 +88,13 @@
 #endif /* #ifdef CONFIG_RCU_TORTURE_TEST */
 
 /* Constants used for minimum and  maximum */
-#if defined(CONFIG_DETECT_SOFTLOCKUP) || defined(CONFIG_HIGHMEM)
+#if defined(CONFIG_HIGHMEM) || defined(CONFIG_DETECT_SOFTLOCKUP)
 static int one = 1;
 #endif
 
 #ifdef CONFIG_DETECT_SOFTLOCKUP
 static int sixty = 60;
+static int neg_one = -1;
 #endif
 
 #ifdef CONFIG_MMU
@@ -110,7 +111,7 @@
 
 static int ngroups_max = NGROUPS_MAX;
 
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
 extern char modprobe_path[];
 #endif
 #ifdef CONFIG_CHR_DEV_SG
@@ -475,7 +476,7 @@
 		.proc_handler	= &ftrace_enable_sysctl,
 	},
 #endif
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
 	{
 		.ctl_name	= KERN_MODPROBE,
 		.procname	= "modprobe",
@@ -739,13 +740,24 @@
 #ifdef CONFIG_DETECT_SOFTLOCKUP
 	{
 		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "softlockup_panic",
+		.data		= &softlockup_panic,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &zero,
+		.extra2		= &one,
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
 		.procname	= "softlockup_thresh",
 		.data		= &softlockup_thresh,
-		.maxlen		= sizeof(unsigned long),
+		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= &proc_doulongvec_minmax,
+		.proc_handler	= &proc_dointvec_minmax,
 		.strategy	= &sysctl_intvec,
-		.extra1		= &one,
+		.extra1		= &neg_one,
 		.extra2		= &sixty,
 	},
 	{
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index 60ceabd..093d4ac 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -376,7 +376,8 @@
  * Provides sysfs interface for listing current clocksource.
  */
 static ssize_t
-sysfs_show_current_clocksources(struct sys_device *dev, char *buf)
+sysfs_show_current_clocksources(struct sys_device *dev,
+				struct sysdev_attribute *attr, char *buf)
 {
 	ssize_t count = 0;
 
@@ -397,6 +398,7 @@
  * clocksource selction.
  */
 static ssize_t sysfs_override_clocksource(struct sys_device *dev,
+					  struct sysdev_attribute *attr,
 					  const char *buf, size_t count)
 {
 	struct clocksource *ovr = NULL;
@@ -449,7 +451,9 @@
  * Provides sysfs interface for listing registered clocksources
  */
 static ssize_t
-sysfs_show_available_clocksources(struct sys_device *dev, char *buf)
+sysfs_show_available_clocksources(struct sys_device *dev,
+				  struct sysdev_attribute *attr,
+				  char *buf)
 {
 	struct clocksource *src;
 	ssize_t count = 0;
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index beef7cc..942fc7c 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -140,8 +140,6 @@
 	if (!ts->tick_stopped)
 		return;
 
-	touch_softlockup_watchdog();
-
 	cpu_clear(cpu, nohz_cpu_mask);
 	now = ktime_get();
 	ts->idle_waketime = now;
@@ -149,6 +147,8 @@
 	local_irq_save(flags);
 	tick_do_update_jiffies64(now);
 	local_irq_restore(flags);
+
+	touch_softlockup_watchdog();
 }
 
 void tick_nohz_stop_idle(int cpu)
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index df27132..882c510 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -74,6 +74,9 @@
 	  debugging files into.  Enable this option to be able to read and
 	  write to these files.
 
+	  For detailed documentation on the debugfs API, see
+	  Documentation/DocBook/filesystems.
+
 	  If unsure, say N.
 
 config HEADERS_CHECK
@@ -147,7 +150,7 @@
 	help
 	  Say Y here to enable the kernel to detect "soft lockups",
 	  which are bugs that cause the kernel to loop in kernel
-	  mode for more than 10 seconds, without giving other tasks a
+	  mode for more than 60 seconds, without giving other tasks a
 	  chance to run.
 
 	  When a soft-lockup is detected, the kernel will print the
@@ -159,6 +162,30 @@
 	   can be detected via the NMI-watchdog, on platforms that
 	   support it.)
 
+config BOOTPARAM_SOFTLOCKUP_PANIC
+	bool "Panic (Reboot) On Soft Lockups"
+	depends on DETECT_SOFTLOCKUP
+	help
+	  Say Y here to enable the kernel to panic on "soft lockups",
+	  which are bugs that cause the kernel to loop in kernel
+	  mode for more than 60 seconds, without giving other tasks a
+	  chance to run.
+
+	  The panic can be used in combination with panic_timeout,
+	  to cause the system to reboot automatically after a
+	  lockup has been detected. This feature is useful for
+	  high-availability systems that have uptime guarantees and
+	  where a lockup must be resolved ASAP.
+
+	  Say N if unsure.
+
+config BOOTPARAM_SOFTLOCKUP_PANIC_VALUE
+	int
+	depends on DETECT_SOFTLOCKUP
+	range 0 1
+	default 0 if !BOOTPARAM_SOFTLOCKUP_PANIC
+	default 1 if BOOTPARAM_SOFTLOCKUP_PANIC
+
 config SCHED_DEBUG
 	bool "Collect scheduler debugging info"
 	depends on DEBUG_KERNEL && PROC_FS
diff --git a/lib/Kconfig.kgdb b/lib/Kconfig.kgdb
index a5d4b1d..2cfd272 100644
--- a/lib/Kconfig.kgdb
+++ b/lib/Kconfig.kgdb
@@ -1,7 +1,4 @@
 
-config HAVE_ARCH_KGDB_SHADOW_INFO
-	bool
-
 config HAVE_ARCH_KGDB
 	bool
 
diff --git a/lib/kobject.c b/lib/kobject.c
index dcade05..7444015 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -216,13 +216,19 @@
 static int kobject_set_name_vargs(struct kobject *kobj, const char *fmt,
 				  va_list vargs)
 {
-	/* Free the old name, if necessary. */
-	kfree(kobj->name);
+	const char *old_name = kobj->name;
+	char *s;
 
 	kobj->name = kvasprintf(GFP_KERNEL, fmt, vargs);
 	if (!kobj->name)
 		return -ENOMEM;
 
+	/* ewww... some of these buggers have '/' in the name ... */
+	s = strchr(kobj->name, '/');
+	if (s)
+		s[0] = '!';
+
+	kfree(old_name);
 	return 0;
 }
 
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 2fa545a..9f8d599 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -245,7 +245,8 @@
 		if (retval)
 			goto exit;
 
-		call_usermodehelper(argv[0], argv, env->envp, UMH_WAIT_EXEC);
+		retval = call_usermodehelper(argv[0], argv,
+					     env->envp, UMH_WAIT_EXEC);
 	}
 
 exit:
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index b80c211..876ba6d 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -295,6 +295,117 @@
 EXPORT_SYMBOL(sg_alloc_table);
 
 /**
+ * sg_miter_start - start mapping iteration over a sg list
+ * @miter: sg mapping iter to be started
+ * @sgl: sg list to iterate over
+ * @nents: number of sg entries
+ *
+ * Description:
+ *   Starts mapping iterator @miter.
+ *
+ * Context:
+ *   Don't care.
+ */
+void sg_miter_start(struct sg_mapping_iter *miter, struct scatterlist *sgl,
+		    unsigned int nents, unsigned int flags)
+{
+	memset(miter, 0, sizeof(struct sg_mapping_iter));
+
+	miter->__sg = sgl;
+	miter->__nents = nents;
+	miter->__offset = 0;
+	miter->__flags = flags;
+}
+EXPORT_SYMBOL(sg_miter_start);
+
+/**
+ * sg_miter_next - proceed mapping iterator to the next mapping
+ * @miter: sg mapping iter to proceed
+ *
+ * Description:
+ *   Proceeds @miter@ to the next mapping.  @miter@ should have been
+ *   started using sg_miter_start().  On successful return,
+ *   @miter@->page, @miter@->addr and @miter@->length point to the
+ *   current mapping.
+ *
+ * Context:
+ *   IRQ disabled if SG_MITER_ATOMIC.  IRQ must stay disabled till
+ *   @miter@ is stopped.  May sleep if !SG_MITER_ATOMIC.
+ *
+ * Returns:
+ *   true if @miter contains the next mapping.  false if end of sg
+ *   list is reached.
+ */
+bool sg_miter_next(struct sg_mapping_iter *miter)
+{
+	unsigned int off, len;
+
+	/* check for end and drop resources from the last iteration */
+	if (!miter->__nents)
+		return false;
+
+	sg_miter_stop(miter);
+
+	/* get to the next sg if necessary.  __offset is adjusted by stop */
+	if (miter->__offset == miter->__sg->length && --miter->__nents) {
+		miter->__sg = sg_next(miter->__sg);
+		miter->__offset = 0;
+	}
+
+	/* map the next page */
+	off = miter->__sg->offset + miter->__offset;
+	len = miter->__sg->length - miter->__offset;
+
+	miter->page = nth_page(sg_page(miter->__sg), off >> PAGE_SHIFT);
+	off &= ~PAGE_MASK;
+	miter->length = min_t(unsigned int, len, PAGE_SIZE - off);
+	miter->consumed = miter->length;
+
+	if (miter->__flags & SG_MITER_ATOMIC)
+		miter->addr = kmap_atomic(miter->page, KM_BIO_SRC_IRQ) + off;
+	else
+		miter->addr = kmap(miter->page) + off;
+
+	return true;
+}
+EXPORT_SYMBOL(sg_miter_next);
+
+/**
+ * sg_miter_stop - stop mapping iteration
+ * @miter: sg mapping iter to be stopped
+ *
+ * Description:
+ *   Stops mapping iterator @miter.  @miter should have been started
+ *   started using sg_miter_start().  A stopped iteration can be
+ *   resumed by calling sg_miter_next() on it.  This is useful when
+ *   resources (kmap) need to be released during iteration.
+ *
+ * Context:
+ *   IRQ disabled if the SG_MITER_ATOMIC is set.  Don't care otherwise.
+ */
+void sg_miter_stop(struct sg_mapping_iter *miter)
+{
+	WARN_ON(miter->consumed > miter->length);
+
+	/* drop resources from the last iteration */
+	if (miter->addr) {
+		miter->__offset += miter->consumed;
+
+		if (miter->__flags & SG_MITER_ATOMIC) {
+			WARN_ON(!irqs_disabled());
+			kunmap_atomic(miter->addr, KM_BIO_SRC_IRQ);
+		} else
+			kunmap(miter->addr);
+
+		miter->page = NULL;
+		miter->addr = NULL;
+		miter->length = 0;
+		miter->consumed = 0;
+	}
+}
+EXPORT_SYMBOL(sg_miter_stop);
+
+/**
  * sg_copy_buffer - Copy data between a linear buffer and an SG list
  * @sgl:		 The SG list
  * @nents:		 Number of SG entries
@@ -309,56 +420,29 @@
 static size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents,
 			     void *buf, size_t buflen, int to_buffer)
 {
-	struct scatterlist *sg;
-	size_t buf_off = 0;
-	int i;
+	unsigned int offset = 0;
+	struct sg_mapping_iter miter;
 
-	WARN_ON(!irqs_disabled());
+	sg_miter_start(&miter, sgl, nents, SG_MITER_ATOMIC);
 
-	for_each_sg(sgl, sg, nents, i) {
-		struct page *page;
-		int n = 0;
-		unsigned int sg_off = sg->offset;
-		unsigned int sg_copy = sg->length;
+	while (sg_miter_next(&miter) && offset < buflen) {
+		unsigned int len;
 
-		if (sg_copy > buflen)
-			sg_copy = buflen;
-		buflen -= sg_copy;
+		len = min(miter.length, buflen - offset);
 
-		while (sg_copy > 0) {
-			unsigned int page_copy;
-			void *p;
-
-			page_copy = PAGE_SIZE - sg_off;
-			if (page_copy > sg_copy)
-				page_copy = sg_copy;
-
-			page = nth_page(sg_page(sg), n);
-			p = kmap_atomic(page, KM_BIO_SRC_IRQ);
-
-			if (to_buffer)
-				memcpy(buf + buf_off, p + sg_off, page_copy);
-			else {
-				memcpy(p + sg_off, buf + buf_off, page_copy);
-				flush_kernel_dcache_page(page);
-			}
-
-			kunmap_atomic(p, KM_BIO_SRC_IRQ);
-
-			buf_off += page_copy;
-			sg_off += page_copy;
-			if (sg_off == PAGE_SIZE) {
-				sg_off = 0;
-				n++;
-			}
-			sg_copy -= page_copy;
+		if (to_buffer)
+			memcpy(buf + offset, miter.addr, len);
+		else {
+			memcpy(miter.addr, buf + offset, len);
+			flush_kernel_dcache_page(miter.page);
 		}
 
-		if (!buflen)
-			break;
+		offset += len;
 	}
 
-	return buf_off;
+	sg_miter_stop(&miter);
+
+	return offset;
 }
 
 /**
diff --git a/lib/textsearch.c b/lib/textsearch.c
index 4b7c607..9fbcb44 100644
--- a/lib/textsearch.c
+++ b/lib/textsearch.c
@@ -267,7 +267,7 @@
 		return ERR_PTR(-EINVAL);
 
 	ops = lookup_ts_algo(algo);
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
 	/*
 	 * Why not always autoload you may ask. Some users are
 	 * in a situation where requesting a module may deadlock,
diff --git a/mm/slub.c b/mm/slub.c
index 35ab38a..6d4a49c 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -492,7 +492,7 @@
 	if (p > addr + 16)
 		print_section("Bytes b4", p - 16, 16);
 
-	print_section("Object", p, min(s->objsize, 128));
+	print_section("Object", p, min_t(unsigned long, s->objsize, PAGE_SIZE));
 
 	if (s->flags & SLAB_RED_ZONE)
 		print_section("Redzone", p + s->objsize,
@@ -1495,15 +1495,7 @@
 
 static void flush_all(struct kmem_cache *s)
 {
-#ifdef CONFIG_SMP
 	on_each_cpu(flush_cpu_slab, s, 1);
-#else
-	unsigned long flags;
-
-	local_irq_save(flags);
-	flush_cpu_slab(s);
-	local_irq_restore(flags);
-#endif
 }
 
 /*
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index f42bc2b..4bf014e 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -569,6 +569,7 @@
  * separate class since they always nest.
  */
 static struct lock_class_key vlan_netdev_xmit_lock_key;
+static struct lock_class_key vlan_netdev_addr_lock_key;
 
 static void vlan_dev_set_lockdep_one(struct net_device *dev,
 				     struct netdev_queue *txq,
@@ -581,6 +582,9 @@
 
 static void vlan_dev_set_lockdep_class(struct net_device *dev, int subclass)
 {
+	lockdep_set_class_and_subclass(&dev->addr_list_lock,
+				       &vlan_netdev_addr_lock_key,
+				       subclass);
 	netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, &subclass);
 }
 
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 844ca5f..c85bf8f 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -398,10 +398,6 @@
 		if (device_create_file(dev, bt_attrs[i]) < 0)
 			BT_ERR("Failed to create device attribute");
 
-	if (sysfs_create_link(&bt_class->subsys.kobj,
-				&dev->kobj, kobject_name(&dev->kobj)) < 0)
-		BT_ERR("Failed to create class symlink");
-
 	return 0;
 }
 
@@ -409,9 +405,6 @@
 {
 	BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
 
-	sysfs_remove_link(&bt_class->subsys.kobj,
-					kobject_name(&hdev->dev.kobj));
-
 	device_del(&hdev->dev);
 }
 
diff --git a/net/core/dev.c b/net/core/dev.c
index 106d5e6..7463a21 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -124,6 +124,8 @@
 #include <linux/ip.h>
 #include <linux/ipv6.h>
 #include <linux/in.h>
+#include <linux/jhash.h>
+#include <linux/random.h>
 
 #include "net-sysfs.h"
 
@@ -259,7 +261,7 @@
 
 DEFINE_PER_CPU(struct softnet_data, softnet_data);
 
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
+#ifdef CONFIG_LOCKDEP
 /*
  * register_netdevice() inits txq->_xmit_lock and sets lockdep class
  * according to dev->type
@@ -299,6 +301,7 @@
 	 "_xmit_NONE"};
 
 static struct lock_class_key netdev_xmit_lock_key[ARRAY_SIZE(netdev_lock_type)];
+static struct lock_class_key netdev_addr_lock_key[ARRAY_SIZE(netdev_lock_type)];
 
 static inline unsigned short netdev_lock_pos(unsigned short dev_type)
 {
@@ -311,8 +314,8 @@
 	return ARRAY_SIZE(netdev_lock_type) - 1;
 }
 
-static inline void netdev_set_lockdep_class(spinlock_t *lock,
-					    unsigned short dev_type)
+static inline void netdev_set_xmit_lockdep_class(spinlock_t *lock,
+						 unsigned short dev_type)
 {
 	int i;
 
@@ -320,9 +323,22 @@
 	lockdep_set_class_and_name(lock, &netdev_xmit_lock_key[i],
 				   netdev_lock_name[i]);
 }
+
+static inline void netdev_set_addr_lockdep_class(struct net_device *dev)
+{
+	int i;
+
+	i = netdev_lock_pos(dev->type);
+	lockdep_set_class_and_name(&dev->addr_list_lock,
+				   &netdev_addr_lock_key[i],
+				   netdev_lock_name[i]);
+}
 #else
-static inline void netdev_set_lockdep_class(spinlock_t *lock,
-					    unsigned short dev_type)
+static inline void netdev_set_xmit_lockdep_class(spinlock_t *lock,
+						 unsigned short dev_type)
+{
+}
+static inline void netdev_set_addr_lockdep_class(struct net_device *dev)
 {
 }
 #endif
@@ -1325,7 +1341,8 @@
 
 void __netif_schedule(struct Qdisc *q)
 {
-	BUG_ON(q == &noop_qdisc);
+	if (WARN_ON_ONCE(q == &noop_qdisc))
+		return;
 
 	if (!test_and_set_bit(__QDISC_STATE_SCHED, &q->state)) {
 		struct softnet_data *sd;
@@ -1642,6 +1659,73 @@
 	return 0;
 }
 
+static u32 simple_tx_hashrnd;
+static int simple_tx_hashrnd_initialized = 0;
+
+static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb)
+{
+	u32 addr1, addr2, ports;
+	u32 hash, ihl;
+	u8 ip_proto;
+
+	if (unlikely(!simple_tx_hashrnd_initialized)) {
+		get_random_bytes(&simple_tx_hashrnd, 4);
+		simple_tx_hashrnd_initialized = 1;
+	}
+
+	switch (skb->protocol) {
+	case __constant_htons(ETH_P_IP):
+		ip_proto = ip_hdr(skb)->protocol;
+		addr1 = ip_hdr(skb)->saddr;
+		addr2 = ip_hdr(skb)->daddr;
+		ihl = ip_hdr(skb)->ihl;
+		break;
+	case __constant_htons(ETH_P_IPV6):
+		ip_proto = ipv6_hdr(skb)->nexthdr;
+		addr1 = ipv6_hdr(skb)->saddr.s6_addr32[3];
+		addr2 = ipv6_hdr(skb)->daddr.s6_addr32[3];
+		ihl = (40 >> 2);
+		break;
+	default:
+		return 0;
+	}
+
+
+	switch (ip_proto) {
+	case IPPROTO_TCP:
+	case IPPROTO_UDP:
+	case IPPROTO_DCCP:
+	case IPPROTO_ESP:
+	case IPPROTO_AH:
+	case IPPROTO_SCTP:
+	case IPPROTO_UDPLITE:
+		ports = *((u32 *) (skb_network_header(skb) + (ihl * 4)));
+		break;
+
+	default:
+		ports = 0;
+		break;
+	}
+
+	hash = jhash_3words(addr1, addr2, ports, simple_tx_hashrnd);
+
+	return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32);
+}
+
+static struct netdev_queue *dev_pick_tx(struct net_device *dev,
+					struct sk_buff *skb)
+{
+	u16 queue_index = 0;
+
+	if (dev->select_queue)
+		queue_index = dev->select_queue(dev, skb);
+	else if (dev->real_num_tx_queues > 1)
+		queue_index = simple_tx_hash(dev, skb);
+
+	skb_set_queue_mapping(skb, queue_index);
+	return netdev_get_tx_queue(dev, queue_index);
+}
+
 /**
  *	dev_queue_xmit - transmit a buffer
  *	@skb: buffer to transmit
@@ -1667,68 +1751,6 @@
  *      the BH enable code must have IRQs enabled so that it will not deadlock.
  *          --BLG
  */
-
-static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb)
-{
-	u32 *addr, *ports, hash, ihl;
-	u8 ip_proto;
-	int alen;
-
-	switch (skb->protocol) {
-	case __constant_htons(ETH_P_IP):
-		ip_proto = ip_hdr(skb)->protocol;
-		addr = &ip_hdr(skb)->saddr;
-		ihl = ip_hdr(skb)->ihl;
-		alen = 2;
-		break;
-	case __constant_htons(ETH_P_IPV6):
-		ip_proto = ipv6_hdr(skb)->nexthdr;
-		addr = &ipv6_hdr(skb)->saddr.s6_addr32[0];
-		ihl = (40 >> 2);
-		alen = 8;
-		break;
-	default:
-		return 0;
-	}
-
-	ports = (u32 *) (skb_network_header(skb) + (ihl * 4));
-
-	hash = 0;
-	while (alen--)
-		hash ^= *addr++;
-
-	switch (ip_proto) {
-	case IPPROTO_TCP:
-	case IPPROTO_UDP:
-	case IPPROTO_DCCP:
-	case IPPROTO_ESP:
-	case IPPROTO_AH:
-	case IPPROTO_SCTP:
-	case IPPROTO_UDPLITE:
-		hash ^= *ports;
-		break;
-
-	default:
-		break;
-	}
-
-	return hash % dev->real_num_tx_queues;
-}
-
-static struct netdev_queue *dev_pick_tx(struct net_device *dev,
-					struct sk_buff *skb)
-{
-	u16 queue_index = 0;
-
-	if (dev->select_queue)
-		queue_index = dev->select_queue(dev, skb);
-	else if (dev->real_num_tx_queues > 1)
-		queue_index = simple_tx_hash(dev, skb);
-
-	skb_set_queue_mapping(skb, queue_index);
-	return netdev_get_tx_queue(dev, queue_index);
-}
-
 int dev_queue_xmit(struct sk_buff *skb)
 {
 	struct net_device *dev = skb->dev;
@@ -3843,7 +3865,7 @@
 					  void *_unused)
 {
 	spin_lock_init(&dev_queue->_xmit_lock);
-	netdev_set_lockdep_class(&dev_queue->_xmit_lock, dev->type);
+	netdev_set_xmit_lockdep_class(&dev_queue->_xmit_lock, dev->type);
 	dev_queue->xmit_lock_owner = -1;
 }
 
@@ -3888,6 +3910,7 @@
 	net = dev_net(dev);
 
 	spin_lock_init(&dev->addr_list_lock);
+	netdev_set_addr_lockdep_class(dev);
 	netdev_init_queue_locks(dev);
 
 	dev->iflink = -1;
@@ -4198,7 +4221,7 @@
 {
 	struct netdev_queue *tx;
 	struct net_device *dev;
-	int alloc_size;
+	size_t alloc_size;
 	void *p;
 
 	BUG_ON(strlen(name) >= sizeof(dev->name));
@@ -4218,7 +4241,7 @@
 		return NULL;
 	}
 
-	tx = kzalloc(sizeof(struct netdev_queue) * queue_count, GFP_KERNEL);
+	tx = kcalloc(queue_count, sizeof(struct netdev_queue), GFP_KERNEL);
 	if (!tx) {
 		printk(KERN_ERR "alloc_netdev: Unable to allocate "
 		       "tx qdiscs.\n");
@@ -4677,6 +4700,26 @@
 	return -ENOMEM;
 }
 
+char *netdev_drivername(struct net_device *dev, char *buffer, int len)
+{
+	struct device_driver *driver;
+	struct device *parent;
+
+	if (len <= 0 || !buffer)
+		return buffer;
+	buffer[0] = 0;
+
+	parent = dev->dev.parent;
+
+	if (!parent)
+		return buffer;
+
+	driver = parent->driver;
+	if (driver && driver->name)
+		strlcpy(buffer, driver->name, len);
+	return buffer;
+}
+
 static void __net_exit netdev_exit(struct net *net)
 {
 	kfree(net->dev_name_head);
diff --git a/net/core/user_dma.c b/net/core/user_dma.c
index c77aff9..8c6b706 100644
--- a/net/core/user_dma.c
+++ b/net/core/user_dma.c
@@ -34,6 +34,7 @@
 #define NET_DMA_DEFAULT_COPYBREAK 4096
 
 int sysctl_tcp_dma_copybreak = NET_DMA_DEFAULT_COPYBREAK;
+EXPORT_SYMBOL(sysctl_tcp_dma_copybreak);
 
 /**
  *	dma_skb_copy_datagram_iovec - Copy a datagram to an iovec.
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
index 40a46d4..3a02072 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
@@ -18,19 +18,7 @@
 #include <net/netfilter/nf_conntrack_l3proto.h>
 #include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_expect.h>
-
-#ifdef CONFIG_NF_CT_ACCT
-static unsigned int
-seq_print_counters(struct seq_file *s,
-		   const struct ip_conntrack_counter *counter)
-{
-	return seq_printf(s, "packets=%llu bytes=%llu ",
-			  (unsigned long long)counter->packets,
-			  (unsigned long long)counter->bytes);
-}
-#else
-#define seq_print_counters(x, y)	0
-#endif
+#include <net/netfilter/nf_conntrack_acct.h>
 
 struct ct_iter_state {
 	unsigned int bucket;
@@ -127,7 +115,7 @@
 			l3proto, l4proto))
 		return -ENOSPC;
 
-	if (seq_print_counters(s, &ct->counters[IP_CT_DIR_ORIGINAL]))
+	if (seq_print_acct(s, ct, IP_CT_DIR_ORIGINAL))
 		return -ENOSPC;
 
 	if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status)))
@@ -138,7 +126,7 @@
 			l3proto, l4proto))
 		return -ENOSPC;
 
-	if (seq_print_counters(s, &ct->counters[IP_CT_DIR_REPLY]))
+	if (seq_print_acct(s, ct, IP_CT_DIR_REPLY))
 		return -ENOSPC;
 
 	if (test_bit(IPS_ASSURED_BIT, &ct->status))
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
index d2a887f..6c6a3cb 100644
--- a/net/ipv4/netfilter/nf_nat_core.c
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -240,12 +240,12 @@
 	   This is only required for source (ie. NAT/masq) mappings.
 	   So far, we don't do local source mappings, so multiple
 	   manips not an issue.  */
-	if (maniptype == IP_NAT_MANIP_SRC) {
+	if (maniptype == IP_NAT_MANIP_SRC &&
+	    !(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) {
 		if (find_appropriate_src(orig_tuple, tuple, range)) {
 			pr_debug("get_unique_tuple: Found current src map\n");
-			if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM))
-				if (!nf_nat_used_tuple(tuple, ct))
-					return;
+			if (!nf_nat_used_tuple(tuple, ct))
+				return;
 		}
 	}
 
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
index 4334d5c..1454432 100644
--- a/net/ipv4/netfilter/nf_nat_sip.c
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -318,11 +318,11 @@
 			     buffer, buflen);
 }
 
-static unsigned mangle_sdp_packet(struct sk_buff *skb, const char **dptr,
-				  unsigned int dataoff, unsigned int *datalen,
-				  enum sdp_header_types type,
-				  enum sdp_header_types term,
-				  char *buffer, int buflen)
+static int mangle_sdp_packet(struct sk_buff *skb, const char **dptr,
+			     unsigned int dataoff, unsigned int *datalen,
+			     enum sdp_header_types type,
+			     enum sdp_header_types term,
+			     char *buffer, int buflen)
 {
 	enum ip_conntrack_info ctinfo;
 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
@@ -330,9 +330,9 @@
 
 	if (ct_sip_get_sdp_header(ct, *dptr, dataoff, *datalen, type, term,
 				  &matchoff, &matchlen) <= 0)
-		return 0;
+		return -ENOENT;
 	return mangle_packet(skb, dptr, datalen, matchoff, matchlen,
-			     buffer, buflen);
+			     buffer, buflen) ? 0 : -EINVAL;
 }
 
 static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, const char **dptr,
@@ -346,8 +346,8 @@
 	unsigned int buflen;
 
 	buflen = sprintf(buffer, NIPQUAD_FMT, NIPQUAD(addr->ip));
-	if (!mangle_sdp_packet(skb, dptr, dataoff, datalen, type, term,
-			       buffer, buflen))
+	if (mangle_sdp_packet(skb, dptr, dataoff, datalen, type, term,
+			      buffer, buflen))
 		return 0;
 
 	return mangle_content_len(skb, dptr, datalen);
@@ -381,15 +381,27 @@
 
 	/* Mangle session description owner and contact addresses */
 	buflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(addr->ip));
-	if (!mangle_sdp_packet(skb, dptr, dataoff, datalen,
+	if (mangle_sdp_packet(skb, dptr, dataoff, datalen,
 			       SDP_HDR_OWNER_IP4, SDP_HDR_MEDIA,
 			       buffer, buflen))
 		return 0;
 
-	if (!mangle_sdp_packet(skb, dptr, dataoff, datalen,
-			       SDP_HDR_CONNECTION_IP4, SDP_HDR_MEDIA,
-			       buffer, buflen))
+	switch (mangle_sdp_packet(skb, dptr, dataoff, datalen,
+				  SDP_HDR_CONNECTION_IP4, SDP_HDR_MEDIA,
+				  buffer, buflen)) {
+	case 0:
+	/*
+	 * RFC 2327:
+	 *
+	 * Session description
+	 *
+	 * c=* (connection information - not required if included in all media)
+	 */
+	case -ENOENT:
+		break;
+	default:
 		return 0;
+	}
 
 	return mangle_content_len(skb, dptr, datalen);
 }
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 1fa683c0..a00532d 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -472,7 +472,7 @@
 	}
 	if (likely(sysctl_tcp_sack)) {
 		opts->options |= OPTION_SACK_ADVERTISE;
-		if (unlikely(!OPTION_TS & opts->options))
+		if (unlikely(!(OPTION_TS & opts->options)))
 			size += TCPOLEN_SACKPERM_ALIGNED;
 	}
 
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index a751770..383d173 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1325,6 +1325,8 @@
 			return -ENOPROTOOPT;
 		if (val != 0 && val < 8) /* Illegal coverage: use default (8) */
 			val = 8;
+		else if (val > USHORT_MAX)
+			val = USHORT_MAX;
 		up->pcslen = val;
 		up->pcflag |= UDPLITE_SEND_CC;
 		break;
@@ -1337,6 +1339,8 @@
 			return -ENOPROTOOPT;
 		if (val != 0 && val < 8) /* Avoid silly minimal values.       */
 			val = 8;
+		else if (val > USHORT_MAX)
+			val = USHORT_MAX;
 		up->pcrlen = val;
 		up->pcflag |= UDPLITE_RECV_CC;
 		break;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 9f4fcce..74d543d 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -153,7 +153,7 @@
 
 static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
 
-struct ipv6_devconf ipv6_devconf __read_mostly = {
+static struct ipv6_devconf ipv6_devconf __read_mostly = {
 	.forwarding		= 0,
 	.hop_limit		= IPV6_DEFAULT_HOPLIMIT,
 	.mtu6			= IPV6_MIN_MTU,
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 4de2b9e..08ea2de 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -661,17 +661,17 @@
 
 static __inline__ void fib6_start_gc(struct net *net, struct rt6_info *rt)
 {
-	if (net->ipv6.ip6_fib_timer->expires == 0 &&
+	if (!timer_pending(&net->ipv6.ip6_fib_timer) &&
 	    (rt->rt6i_flags & (RTF_EXPIRES|RTF_CACHE)))
-		mod_timer(net->ipv6.ip6_fib_timer, jiffies +
-			  net->ipv6.sysctl.ip6_rt_gc_interval);
+		mod_timer(&net->ipv6.ip6_fib_timer,
+			  jiffies + net->ipv6.sysctl.ip6_rt_gc_interval);
 }
 
 void fib6_force_start_gc(struct net *net)
 {
-	if (net->ipv6.ip6_fib_timer->expires == 0)
-		mod_timer(net->ipv6.ip6_fib_timer, jiffies +
-			  net->ipv6.sysctl.ip6_rt_gc_interval);
+	if (!timer_pending(&net->ipv6.ip6_fib_timer))
+		mod_timer(&net->ipv6.ip6_fib_timer,
+			  jiffies + net->ipv6.sysctl.ip6_rt_gc_interval);
 }
 
 /*
@@ -1447,27 +1447,23 @@
 		gc_args.timeout = expires ? (int)expires :
 			net->ipv6.sysctl.ip6_rt_gc_interval;
 	} else {
-		local_bh_disable();
-		if (!spin_trylock(&fib6_gc_lock)) {
-			mod_timer(net->ipv6.ip6_fib_timer, jiffies + HZ);
-			local_bh_enable();
+		if (!spin_trylock_bh(&fib6_gc_lock)) {
+			mod_timer(&net->ipv6.ip6_fib_timer, jiffies + HZ);
 			return;
 		}
 		gc_args.timeout = net->ipv6.sysctl.ip6_rt_gc_interval;
 	}
-	gc_args.more = 0;
 
-	icmp6_dst_gc(&gc_args.more);
+	gc_args.more = icmp6_dst_gc();
 
 	fib6_clean_all(net, fib6_age, 0, NULL);
 
 	if (gc_args.more)
-		mod_timer(net->ipv6.ip6_fib_timer, jiffies +
-			  net->ipv6.sysctl.ip6_rt_gc_interval);
-	else {
-		del_timer(net->ipv6.ip6_fib_timer);
-		net->ipv6.ip6_fib_timer->expires = 0;
-	}
+		mod_timer(&net->ipv6.ip6_fib_timer,
+			  round_jiffies(jiffies
+					+ net->ipv6.sysctl.ip6_rt_gc_interval));
+	else
+		del_timer(&net->ipv6.ip6_fib_timer);
 	spin_unlock_bh(&fib6_gc_lock);
 }
 
@@ -1478,24 +1474,15 @@
 
 static int fib6_net_init(struct net *net)
 {
-	int ret;
-	struct timer_list *timer;
-
-	ret = -ENOMEM;
-	timer = kzalloc(sizeof(*timer), GFP_KERNEL);
-	if (!timer)
-		goto out;
-
-	setup_timer(timer, fib6_gc_timer_cb, (unsigned long)net);
-	net->ipv6.ip6_fib_timer = timer;
+	setup_timer(&net->ipv6.ip6_fib_timer, fib6_gc_timer_cb, (unsigned long)net);
 
 	net->ipv6.rt6_stats = kzalloc(sizeof(*net->ipv6.rt6_stats), GFP_KERNEL);
 	if (!net->ipv6.rt6_stats)
 		goto out_timer;
 
-	net->ipv6.fib_table_hash =
-		kzalloc(sizeof(*net->ipv6.fib_table_hash)*FIB_TABLE_HASHSZ,
-			GFP_KERNEL);
+	net->ipv6.fib_table_hash = kcalloc(FIB_TABLE_HASHSZ,
+					   sizeof(*net->ipv6.fib_table_hash),
+					   GFP_KERNEL);
 	if (!net->ipv6.fib_table_hash)
 		goto out_rt6_stats;
 
@@ -1521,9 +1508,7 @@
 #endif
 	fib6_tables_init(net);
 
-	ret = 0;
-out:
-	return ret;
+	return 0;
 
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
 out_fib6_main_tbl:
@@ -1534,15 +1519,14 @@
 out_rt6_stats:
 	kfree(net->ipv6.rt6_stats);
 out_timer:
-	kfree(timer);
-	goto out;
+	return -ENOMEM;
  }
 
 static void fib6_net_exit(struct net *net)
 {
 	rt6_ifdown(net, NULL);
-	del_timer_sync(net->ipv6.ip6_fib_timer);
-	kfree(net->ipv6.ip6_fib_timer);
+	del_timer_sync(&net->ipv6.ip6_fib_timer);
+
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
 	kfree(net->ipv6.fib6_local_tbl);
 #endif
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 615b328..86540b2 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -978,13 +978,12 @@
 	return &rt->u.dst;
 }
 
-int icmp6_dst_gc(int *more)
+int icmp6_dst_gc(void)
 {
 	struct dst_entry *dst, *next, **pprev;
-	int freed;
+	int more = 0;
 
 	next = NULL;
-	freed = 0;
 
 	spin_lock_bh(&icmp6_dst_lock);
 	pprev = &icmp6_dst_gc_list;
@@ -993,16 +992,15 @@
 		if (!atomic_read(&dst->__refcnt)) {
 			*pprev = dst->next;
 			dst_free(dst);
-			freed++;
 		} else {
 			pprev = &dst->next;
-			(*more)++;
+			++more;
 		}
 	}
 
 	spin_unlock_bh(&icmp6_dst_lock);
 
-	return freed;
+	return more;
 }
 
 static int ip6_dst_gc(struct dst_ops *ops)
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 316c7af..ee898e7 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -49,6 +49,15 @@
 	  Those counters can be used for flow-based accounting or the
 	  `connbytes' match.
 
+	  Please note that currently this option only sets a default state.
+	  You may change it at boot time with nf_conntrack.acct=0/1 kernel
+	  paramater or by loading the nf_conntrack module with acct=0/1.
+
+	  You may also disable/enable it on a running system with:
+	   sysctl net.netfilter.nf_conntrack_acct=0/1
+
+	  This option will be removed in 2.6.29.
+
 	  If unsure, say `N'.
 
 config NF_CONNTRACK_MARK
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 5c4b183..3bd2cc5 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -1,6 +1,6 @@
 netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o
 
-nf_conntrack-y	:= nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o nf_conntrack_extend.o
+nf_conntrack-y	:= nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o nf_conntrack_extend.o nf_conntrack_acct.o
 nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
 
 obj-$(CONFIG_NETFILTER) = netfilter.o
diff --git a/net/netfilter/nf_conntrack_acct.c b/net/netfilter/nf_conntrack_acct.c
new file mode 100644
index 0000000..59bd8b9
--- /dev/null
+++ b/net/netfilter/nf_conntrack_acct.c
@@ -0,0 +1,104 @@
+/* Accouting handling for netfilter. */
+
+/*
+ * (C) 2008 Krzysztof Piotr Oledzki <ole@ans.pl>
+ *
+ * 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/netfilter.h>
+#include <linux/kernel.h>
+#include <linux/moduleparam.h>
+
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_extend.h>
+#include <net/netfilter/nf_conntrack_acct.h>
+
+#ifdef CONFIG_NF_CT_ACCT
+#define NF_CT_ACCT_DEFAULT 1
+#else
+#define NF_CT_ACCT_DEFAULT 0
+#endif
+
+int nf_ct_acct __read_mostly = NF_CT_ACCT_DEFAULT;
+EXPORT_SYMBOL_GPL(nf_ct_acct);
+
+module_param_named(acct, nf_ct_acct, bool, 0644);
+MODULE_PARM_DESC(acct, "Enable connection tracking flow accounting.");
+
+#ifdef CONFIG_SYSCTL
+static struct ctl_table_header *acct_sysctl_header;
+static struct ctl_table acct_sysctl_table[] = {
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "nf_conntrack_acct",
+		.data		= &nf_ct_acct,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{}
+};
+#endif /* CONFIG_SYSCTL */
+
+unsigned int
+seq_print_acct(struct seq_file *s, const struct nf_conn *ct, int dir)
+{
+	struct nf_conn_counter *acct;
+
+	acct = nf_conn_acct_find(ct);
+	if (!acct)
+		return 0;
+
+	return seq_printf(s, "packets=%llu bytes=%llu ",
+			  (unsigned long long)acct[dir].packets,
+			  (unsigned long long)acct[dir].bytes);
+};
+EXPORT_SYMBOL_GPL(seq_print_acct);
+
+static struct nf_ct_ext_type acct_extend __read_mostly = {
+	.len	= sizeof(struct nf_conn_counter[IP_CT_DIR_MAX]),
+	.align	= __alignof__(struct nf_conn_counter[IP_CT_DIR_MAX]),
+	.id	= NF_CT_EXT_ACCT,
+};
+
+int nf_conntrack_acct_init(void)
+{
+	int ret;
+
+#ifdef CONFIG_NF_CT_ACCT
+	printk(KERN_WARNING "CONFIG_NF_CT_ACCT is deprecated and will be removed soon. Plase use\n");
+	printk(KERN_WARNING "nf_conntrack.acct=1 kernel paramater, acct=1 nf_conntrack module option or\n");
+	printk(KERN_WARNING "sysctl net.netfilter.nf_conntrack_acct=1 to enable it.\n");
+#endif
+
+	ret = nf_ct_extend_register(&acct_extend);
+	if (ret < 0) {
+		printk(KERN_ERR "nf_conntrack_acct: Unable to register extension\n");
+		return ret;
+	}
+
+#ifdef CONFIG_SYSCTL
+	acct_sysctl_header = register_sysctl_paths(nf_net_netfilter_sysctl_path,
+				acct_sysctl_table);
+
+	if (!acct_sysctl_header) {
+		nf_ct_extend_unregister(&acct_extend);
+
+		printk(KERN_ERR "nf_conntrack_acct: can't register to sysctl.\n");
+		return -ENOMEM;
+	}
+#endif
+
+	return 0;
+}
+
+void nf_conntrack_acct_fini(void)
+{
+#ifdef CONFIG_SYSCTL
+	unregister_sysctl_table(acct_sysctl_header);
+#endif
+	nf_ct_extend_unregister(&acct_extend);
+}
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 28d03e6..c519d09 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -37,6 +37,7 @@
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/nf_conntrack_extend.h>
+#include <net/netfilter/nf_conntrack_acct.h>
 
 #define NF_CONNTRACK_VERSION	"0.5.0"
 
@@ -555,6 +556,8 @@
 		return NULL;
 	}
 
+	nf_ct_acct_ext_add(ct, GFP_ATOMIC);
+
 	spin_lock_bh(&nf_conntrack_lock);
 	exp = nf_ct_find_expectation(tuple);
 	if (exp) {
@@ -828,17 +831,16 @@
 	}
 
 acct:
-#ifdef CONFIG_NF_CT_ACCT
 	if (do_acct) {
-		ct->counters[CTINFO2DIR(ctinfo)].packets++;
-		ct->counters[CTINFO2DIR(ctinfo)].bytes +=
-			skb->len - skb_network_offset(skb);
+		struct nf_conn_counter *acct;
 
-		if ((ct->counters[CTINFO2DIR(ctinfo)].packets & 0x80000000)
-		    || (ct->counters[CTINFO2DIR(ctinfo)].bytes & 0x80000000))
-			event |= IPCT_COUNTER_FILLING;
+		acct = nf_conn_acct_find(ct);
+		if (acct) {
+			acct[CTINFO2DIR(ctinfo)].packets++;
+			acct[CTINFO2DIR(ctinfo)].bytes +=
+				skb->len - skb_network_offset(skb);
+		}
 	}
-#endif
 
 	spin_unlock_bh(&nf_conntrack_lock);
 
@@ -853,15 +855,19 @@
 		       const struct sk_buff *skb,
 		       int do_acct)
 {
-#ifdef CONFIG_NF_CT_ACCT
 	if (do_acct) {
+		struct nf_conn_counter *acct;
+
 		spin_lock_bh(&nf_conntrack_lock);
-		ct->counters[CTINFO2DIR(ctinfo)].packets++;
-		ct->counters[CTINFO2DIR(ctinfo)].bytes +=
-			skb->len - skb_network_offset(skb);
+		acct = nf_conn_acct_find(ct);
+		if (acct) {
+			acct[CTINFO2DIR(ctinfo)].packets++;
+			acct[CTINFO2DIR(ctinfo)].bytes +=
+				skb->len - skb_network_offset(skb);
+		}
 		spin_unlock_bh(&nf_conntrack_lock);
 	}
-#endif
+
 	if (del_timer(&ct->timeout)) {
 		ct->timeout.function((unsigned long)ct);
 		return true;
@@ -1029,6 +1035,7 @@
 	nf_conntrack_proto_fini();
 	nf_conntrack_helper_fini();
 	nf_conntrack_expect_fini();
+	nf_conntrack_acct_fini();
 }
 
 struct hlist_head *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced)
@@ -1168,6 +1175,10 @@
 	if (ret < 0)
 		goto out_fini_expect;
 
+	ret = nf_conntrack_acct_init();
+	if (ret < 0)
+		goto out_fini_helper;
+
 	/* For use by REJECT target */
 	rcu_assign_pointer(ip_ct_attach, nf_conntrack_attach);
 	rcu_assign_pointer(nf_ct_destroy, destroy_conntrack);
@@ -1180,6 +1191,8 @@
 
 	return ret;
 
+out_fini_helper:
+	nf_conntrack_helper_fini();
 out_fini_expect:
 	nf_conntrack_expect_fini();
 out_fini_proto:
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 95a7967..105a616 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -37,6 +37,7 @@
 #include <net/netfilter/nf_conntrack_l3proto.h>
 #include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_tuple.h>
+#include <net/netfilter/nf_conntrack_acct.h>
 #ifdef CONFIG_NF_NAT_NEEDED
 #include <net/netfilter/nf_nat_core.h>
 #include <net/netfilter/nf_nat_protocol.h>
@@ -206,22 +207,26 @@
 	return -1;
 }
 
-#ifdef CONFIG_NF_CT_ACCT
 static int
 ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct,
 			enum ip_conntrack_dir dir)
 {
 	enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG;
 	struct nlattr *nest_count;
+	const struct nf_conn_counter *acct;
+
+	acct = nf_conn_acct_find(ct);
+	if (!acct)
+		return 0;
 
 	nest_count = nla_nest_start(skb, type | NLA_F_NESTED);
 	if (!nest_count)
 		goto nla_put_failure;
 
-	NLA_PUT_BE32(skb, CTA_COUNTERS32_PACKETS,
-		     htonl(ct->counters[dir].packets));
-	NLA_PUT_BE32(skb, CTA_COUNTERS32_BYTES,
-		     htonl(ct->counters[dir].bytes));
+	NLA_PUT_BE64(skb, CTA_COUNTERS_PACKETS,
+		     cpu_to_be64(acct[dir].packets));
+	NLA_PUT_BE64(skb, CTA_COUNTERS_BYTES,
+		     cpu_to_be64(acct[dir].bytes));
 
 	nla_nest_end(skb, nest_count);
 
@@ -230,9 +235,6 @@
 nla_put_failure:
 	return -1;
 }
-#else
-#define ctnetlink_dump_counters(a, b, c) (0)
-#endif
 
 #ifdef CONFIG_NF_CONNTRACK_MARK
 static inline int
@@ -501,11 +503,6 @@
 			goto nla_put_failure;
 #endif
 
-		if (events & IPCT_COUNTER_FILLING &&
-		    (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
-		     ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0))
-			goto nla_put_failure;
-
 		if (events & IPCT_RELATED &&
 		    ctnetlink_dump_master(skb, ct) < 0)
 			goto nla_put_failure;
@@ -576,11 +573,15 @@
 				cb->args[1] = (unsigned long)ct;
 				goto out;
 			}
-#ifdef CONFIG_NF_CT_ACCT
+
 			if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) ==
-						IPCTNL_MSG_CT_GET_CTRZERO)
-				memset(&ct->counters, 0, sizeof(ct->counters));
-#endif
+						IPCTNL_MSG_CT_GET_CTRZERO) {
+				struct nf_conn_counter *acct;
+
+				acct = nf_conn_acct_find(ct);
+				if (acct)
+					memset(acct, 0, sizeof(struct nf_conn_counter[IP_CT_DIR_MAX]));
+			}
 		}
 		if (cb->args[1]) {
 			cb->args[1] = 0;
@@ -832,14 +833,9 @@
 	u_int8_t u3 = nfmsg->nfgen_family;
 	int err = 0;
 
-	if (nlh->nlmsg_flags & NLM_F_DUMP) {
-#ifndef CONFIG_NF_CT_ACCT
-		if (NFNL_MSG_TYPE(nlh->nlmsg_type) == IPCTNL_MSG_CT_GET_CTRZERO)
-			return -ENOTSUPP;
-#endif
+	if (nlh->nlmsg_flags & NLM_F_DUMP)
 		return netlink_dump_start(ctnl, skb, nlh, ctnetlink_dump_table,
 					  ctnetlink_done);
-	}
 
 	if (cda[CTA_TUPLE_ORIG])
 		err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3);
@@ -1152,6 +1148,8 @@
 			goto err;
 	}
 
+	nf_ct_acct_ext_add(ct, GFP_KERNEL);
+
 #if defined(CONFIG_NF_CONNTRACK_MARK)
 	if (cda[CTA_MARK])
 		ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index 41183a4..30aa5b9 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -482,11 +482,11 @@
 
 	NLA_PUT_BE32(skb,
 		     CTA_PROTOINFO_SCTP_VTAG_ORIGINAL,
-		     htonl(ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL]));
+		     ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL]);
 
 	NLA_PUT_BE32(skb,
 		     CTA_PROTOINFO_SCTP_VTAG_REPLY,
-		     htonl(ct->proto.sctp.vtag[IP_CT_DIR_REPLY]));
+		     ct->proto.sctp.vtag[IP_CT_DIR_REPLY]);
 
 	read_unlock_bh(&sctp_lock);
 
@@ -530,9 +530,9 @@
 	write_lock_bh(&sctp_lock);
 	ct->proto.sctp.state = nla_get_u8(tb[CTA_PROTOINFO_SCTP_STATE]);
 	ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] =
-		ntohl(nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL]));
+		nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL]);
 	ct->proto.sctp.vtag[IP_CT_DIR_REPLY] =
-		ntohl(nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_REPLY]));
+		nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_REPLY]);
 	write_unlock_bh(&sctp_lock);
 
 	return 0;
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 46ea542..869ef93 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -25,6 +25,7 @@
 #include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_expect.h>
 #include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_acct.h>
 
 MODULE_LICENSE("GPL");
 
@@ -38,19 +39,6 @@
 }
 EXPORT_SYMBOL_GPL(print_tuple);
 
-#ifdef CONFIG_NF_CT_ACCT
-static unsigned int
-seq_print_counters(struct seq_file *s,
-		   const struct ip_conntrack_counter *counter)
-{
-	return seq_printf(s, "packets=%llu bytes=%llu ",
-			  (unsigned long long)counter->packets,
-			  (unsigned long long)counter->bytes);
-}
-#else
-#define seq_print_counters(x, y)	0
-#endif
-
 struct ct_iter_state {
 	unsigned int bucket;
 };
@@ -146,7 +134,7 @@
 			l3proto, l4proto))
 		return -ENOSPC;
 
-	if (seq_print_counters(s, &ct->counters[IP_CT_DIR_ORIGINAL]))
+	if (seq_print_acct(s, ct, IP_CT_DIR_ORIGINAL))
 		return -ENOSPC;
 
 	if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status)))
@@ -157,7 +145,7 @@
 			l3proto, l4proto))
 		return -ENOSPC;
 
-	if (seq_print_counters(s, &ct->counters[IP_CT_DIR_REPLY]))
+	if (seq_print_acct(s, ct, IP_CT_DIR_REPLY))
 		return -ENOSPC;
 
 	if (test_bit(IPS_ASSURED_BIT, &ct->status))
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index b8173af..9a35b57 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -453,6 +453,14 @@
 		}
 	}
 
+	if (indev && skb_mac_header_was_set(skb)) {
+		NLA_PUT_BE16(inst->skb, NFULA_HWTYPE, htons(skb->dev->type));
+		NLA_PUT_BE16(inst->skb, NFULA_HWLEN,
+			     htons(skb->dev->hard_header_len));
+		NLA_PUT(inst->skb, NFULA_HWHEADER, skb->dev->hard_header_len,
+			skb_mac_header(skb));
+	}
+
 	if (skb->tstamp.tv64) {
 		struct nfulnl_msg_packet_timestamp ts;
 		struct timeval tv = ktime_to_timeval(skb->tstamp);
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index 217e2b6..beb5094 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -147,17 +147,21 @@
 	return TCPOLEN_MSS;
 }
 
-static u_int32_t tcpmss_reverse_mtu4(const struct iphdr *iph)
+static u_int32_t tcpmss_reverse_mtu(const struct sk_buff *skb,
+				    unsigned int family)
 {
-	struct flowi fl = {
-		.fl4_dst = iph->saddr,
-	};
+	struct flowi fl = {};
 	const struct nf_afinfo *ai;
 	struct rtable *rt = NULL;
 	u_int32_t mtu     = ~0U;
 
+	if (family == PF_INET)
+		fl.fl4_dst = ip_hdr(skb)->saddr;
+	else
+		fl.fl6_dst = ipv6_hdr(skb)->saddr;
+
 	rcu_read_lock();
-	ai = nf_get_afinfo(AF_INET);
+	ai = nf_get_afinfo(family);
 	if (ai != NULL)
 		ai->route((struct dst_entry **)&rt, &fl);
 	rcu_read_unlock();
@@ -178,7 +182,8 @@
 	__be16 newlen;
 	int ret;
 
-	ret = tcpmss_mangle_packet(skb, targinfo, tcpmss_reverse_mtu4(iph),
+	ret = tcpmss_mangle_packet(skb, targinfo,
+				   tcpmss_reverse_mtu(skb, PF_INET),
 				   iph->ihl * 4,
 				   sizeof(*iph) + sizeof(struct tcphdr));
 	if (ret < 0)
@@ -193,28 +198,6 @@
 }
 
 #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
-static u_int32_t tcpmss_reverse_mtu6(const struct ipv6hdr *iph)
-{
-	struct flowi fl = {
-		.fl6_dst = iph->saddr,
-	};
-	const struct nf_afinfo *ai;
-	struct rtable *rt = NULL;
-	u_int32_t mtu     = ~0U;
-
-	rcu_read_lock();
-	ai = nf_get_afinfo(AF_INET6);
-	if (ai != NULL)
-		ai->route((struct dst_entry **)&rt, &fl);
-	rcu_read_unlock();
-
-	if (rt != NULL) {
-		mtu = dst_mtu(&rt->u.dst);
-		dst_release(&rt->u.dst);
-	}
-	return mtu;
-}
-
 static unsigned int
 tcpmss_tg6(struct sk_buff *skb, const struct net_device *in,
            const struct net_device *out, unsigned int hooknum,
@@ -229,7 +212,8 @@
 	tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr);
 	if (tcphoff < 0)
 		return NF_DROP;
-	ret = tcpmss_mangle_packet(skb, targinfo, tcpmss_reverse_mtu6(ipv6h),
+	ret = tcpmss_mangle_packet(skb, targinfo,
+				   tcpmss_reverse_mtu(skb, PF_INET6),
 				   tcphoff,
 				   sizeof(*ipv6h) + sizeof(struct tcphdr));
 	if (ret < 0)
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index d7e8983..3e39c4f 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -8,6 +8,7 @@
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter/xt_connbytes.h>
 #include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_acct.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
@@ -27,12 +28,15 @@
 	u_int64_t what = 0;	/* initialize to make gcc happy */
 	u_int64_t bytes = 0;
 	u_int64_t pkts = 0;
-	const struct ip_conntrack_counter *counters;
+	const struct nf_conn_counter *counters;
 
 	ct = nf_ct_get(skb, &ctinfo);
 	if (!ct)
 		return false;
-	counters = ct->counters;
+
+	counters = nf_conn_acct_find(ct);
+	if (!counters)
+		return false;
 
 	switch (sinfo->what) {
 	case XT_CONNBYTES_PKTS:
diff --git a/net/netfilter/xt_time.c b/net/netfilter/xt_time.c
index ed76baab..9f32859 100644
--- a/net/netfilter/xt_time.c
+++ b/net/netfilter/xt_time.c
@@ -173,7 +173,7 @@
 		__net_timestamp((struct sk_buff *)skb);
 
 	stamp = ktime_to_ns(skb->tstamp);
-	do_div(stamp, NSEC_PER_SEC);
+	stamp = div_s64(stamp, NSEC_PER_SEC);
 
 	if (info->flags & XT_TIME_LOCAL_TZ)
 		/* Adjust for local timezone */
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index fccc250..532e4fa 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -73,6 +73,7 @@
  * separate class since they always nest.
  */
 static struct lock_class_key nr_netdev_xmit_lock_key;
+static struct lock_class_key nr_netdev_addr_lock_key;
 
 static void nr_set_lockdep_one(struct net_device *dev,
 			       struct netdev_queue *txq,
@@ -83,6 +84,7 @@
 
 static void nr_set_lockdep_key(struct net_device *dev)
 {
+	lockdep_set_class(&dev->addr_list_lock, &nr_netdev_addr_lock_key);
 	netdev_for_each_tx_queue(dev, nr_set_lockdep_one, NULL);
 }
 
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index dbc963b..a7f1ce1 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -74,6 +74,7 @@
  * separate class since they always nest.
  */
 static struct lock_class_key rose_netdev_xmit_lock_key;
+static struct lock_class_key rose_netdev_addr_lock_key;
 
 static void rose_set_lockdep_one(struct net_device *dev,
 				 struct netdev_queue *txq,
@@ -84,6 +85,7 @@
 
 static void rose_set_lockdep_key(struct net_device *dev)
 {
+	lockdep_set_class(&dev->addr_list_lock, &rose_netdev_addr_lock_key);
 	netdev_for_each_tx_queue(dev, rose_set_lockdep_one, NULL);
 }
 
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 5219d5f..b060164 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -447,7 +447,7 @@
 }
 EXPORT_SYMBOL(qdisc_watchdog_cancel);
 
-struct hlist_head *qdisc_class_hash_alloc(unsigned int n)
+static struct hlist_head *qdisc_class_hash_alloc(unsigned int n)
 {
 	unsigned int size = n * sizeof(struct hlist_head), i;
 	struct hlist_head *h;
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 0ddf692..4ac7e3a 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -212,9 +212,9 @@
 			if (some_queue_stopped &&
 			    time_after(jiffies, (dev->trans_start +
 						 dev->watchdog_timeo))) {
-				printk(KERN_INFO "NETDEV WATCHDOG: %s: "
-				       "transmit timed out\n",
-				       dev->name);
+				char drivername[64];
+				printk(KERN_INFO "NETDEV WATCHDOG: %s (%s): transmit timed out\n",
+				       dev->name, netdev_drivername(dev, drivername, 64));
 				dev->tx_timeout(dev);
 				WARN_ON_ONCE(1);
 			}
@@ -356,44 +356,99 @@
 };
 
 
-static int fifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc)
-{
-	struct sk_buff_head *list = &qdisc->q;
+static const u8 prio2band[TC_PRIO_MAX+1] =
+	{ 1, 2, 2, 2, 1, 2, 0, 0 , 1, 1, 1, 1, 1, 1, 1, 1 };
 
-	if (skb_queue_len(list) < qdisc_dev(qdisc)->tx_queue_len)
+/* 3-band FIFO queue: old style, but should be a bit faster than
+   generic prio+fifo combination.
+ */
+
+#define PFIFO_FAST_BANDS 3
+
+static inline struct sk_buff_head *prio2list(struct sk_buff *skb,
+					     struct Qdisc *qdisc)
+{
+	struct sk_buff_head *list = qdisc_priv(qdisc);
+	return list + prio2band[skb->priority & TC_PRIO_MAX];
+}
+
+static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc)
+{
+	struct sk_buff_head *list = prio2list(skb, qdisc);
+
+	if (skb_queue_len(list) < qdisc_dev(qdisc)->tx_queue_len) {
+		qdisc->q.qlen++;
 		return __qdisc_enqueue_tail(skb, qdisc, list);
+	}
 
 	return qdisc_drop(skb, qdisc);
 }
 
-static struct sk_buff *fifo_fast_dequeue(struct Qdisc* qdisc)
+static struct sk_buff *pfifo_fast_dequeue(struct Qdisc* qdisc)
 {
-	struct sk_buff_head *list = &qdisc->q;
+	int prio;
+	struct sk_buff_head *list = qdisc_priv(qdisc);
 
-	if (!skb_queue_empty(list))
-		return __qdisc_dequeue_head(qdisc, list);
+	for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) {
+		if (!skb_queue_empty(list + prio)) {
+			qdisc->q.qlen--;
+			return __qdisc_dequeue_head(qdisc, list + prio);
+		}
+	}
 
 	return NULL;
 }
 
-static int fifo_fast_requeue(struct sk_buff *skb, struct Qdisc* qdisc)
+static int pfifo_fast_requeue(struct sk_buff *skb, struct Qdisc* qdisc)
 {
-	return __qdisc_requeue(skb, qdisc, &qdisc->q);
+	qdisc->q.qlen++;
+	return __qdisc_requeue(skb, qdisc, prio2list(skb, qdisc));
 }
 
-static void fifo_fast_reset(struct Qdisc* qdisc)
+static void pfifo_fast_reset(struct Qdisc* qdisc)
 {
-	__qdisc_reset_queue(qdisc, &qdisc->q);
+	int prio;
+	struct sk_buff_head *list = qdisc_priv(qdisc);
+
+	for (prio = 0; prio < PFIFO_FAST_BANDS; prio++)
+		__qdisc_reset_queue(qdisc, list + prio);
+
 	qdisc->qstats.backlog = 0;
+	qdisc->q.qlen = 0;
 }
 
-static struct Qdisc_ops fifo_fast_ops __read_mostly = {
-	.id		=	"fifo_fast",
-	.priv_size	=	0,
-	.enqueue	=	fifo_fast_enqueue,
-	.dequeue	=	fifo_fast_dequeue,
-	.requeue	=	fifo_fast_requeue,
-	.reset		=	fifo_fast_reset,
+static int pfifo_fast_dump(struct Qdisc *qdisc, struct sk_buff *skb)
+{
+	struct tc_prio_qopt opt = { .bands = PFIFO_FAST_BANDS };
+
+	memcpy(&opt.priomap, prio2band, TC_PRIO_MAX+1);
+	NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
+	return skb->len;
+
+nla_put_failure:
+	return -1;
+}
+
+static int pfifo_fast_init(struct Qdisc *qdisc, struct nlattr *opt)
+{
+	int prio;
+	struct sk_buff_head *list = qdisc_priv(qdisc);
+
+	for (prio = 0; prio < PFIFO_FAST_BANDS; prio++)
+		skb_queue_head_init(list + prio);
+
+	return 0;
+}
+
+static struct Qdisc_ops pfifo_fast_ops __read_mostly = {
+	.id		=	"pfifo_fast",
+	.priv_size	=	PFIFO_FAST_BANDS * sizeof(struct sk_buff_head),
+	.enqueue	=	pfifo_fast_enqueue,
+	.dequeue	=	pfifo_fast_dequeue,
+	.requeue	=	pfifo_fast_requeue,
+	.init		=	pfifo_fast_init,
+	.reset		=	pfifo_fast_reset,
+	.dump		=	pfifo_fast_dump,
 	.owner		=	THIS_MODULE,
 };
 
@@ -522,7 +577,7 @@
 
 	if (dev->tx_queue_len) {
 		qdisc = qdisc_create_dflt(dev, dev_queue,
-					  &fifo_fast_ops, TC_H_ROOT);
+					  &pfifo_fast_ops, TC_H_ROOT);
 		if (!qdisc) {
 			printk(KERN_INFO "%s: activation failed\n", dev->name);
 			return;
@@ -550,9 +605,9 @@
 	int need_watchdog;
 
 	/* No queueing discipline is attached to device;
-	 * create default one i.e. fifo_fast for devices,
-	 * which need queueing and noqueue_qdisc for
-	 * virtual interfaces.
+	   create default one i.e. pfifo_fast for devices,
+	   which need queueing and noqueue_qdisc for
+	   virtual interfaces
 	 */
 
 	if (dev_all_qdisc_sleeping_noop(dev))
@@ -576,7 +631,6 @@
 				 void *_qdisc_default)
 {
 	struct Qdisc *qdisc_default = _qdisc_default;
-	struct sk_buff *skb = NULL;
 	struct Qdisc *qdisc;
 
 	qdisc = dev_queue->qdisc;
@@ -588,8 +642,6 @@
 
 		spin_unlock_bh(qdisc_lock(qdisc));
 	}
-
-	kfree_skb(skb);
 }
 
 static bool some_qdisc_is_running(struct net_device *dev, int lock)
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 70ead8d..4328ad5 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -71,6 +71,8 @@
 
 static void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 sack_ctsn);
 
+static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout);
+
 /* Add data to the front of the queue. */
 static inline void sctp_outq_head_data(struct sctp_outq *q,
 					struct sctp_chunk *ch)
@@ -712,7 +714,7 @@
  * locking concerns must be made.  Today we use the sock lock to protect
  * this function.
  */
-int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
+static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
 {
 	struct sctp_packet *packet;
 	struct sctp_packet singleton;
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 5dd8983..f268910 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -519,8 +519,3 @@
 
 	return 0;
 }
-
-void sctp_assoc_proc_exit(void)
-{
-	remove_proc_entry("remaddr", proc_net_sctp);
-}
diff --git a/samples/firmware_class/firmware_sample_firmware_class.c b/samples/firmware_class/firmware_sample_firmware_class.c
index 9392116..e6cf7a4 100644
--- a/samples/firmware_class/firmware_sample_firmware_class.c
+++ b/samples/firmware_class/firmware_sample_firmware_class.c
@@ -124,7 +124,7 @@
 	class_dev->class_id[BUS_ID_SIZE-1] = '\0';
 	class_dev->dev = device;
 
-	class_dev->class = &firmware_class,
+	class_dev->class = &firmware_class;
 	class_set_devdata(class_dev, fw_priv);
 	retval = class_device_register(class_dev);
 	if (retval) {
diff --git a/samples/kobject/kset-example.c b/samples/kobject/kset-example.c
index b0a1b4f..7395c0b 100644
--- a/samples/kobject/kset-example.c
+++ b/samples/kobject/kset-example.c
@@ -211,7 +211,7 @@
 	 */
 	retval = kobject_init_and_add(&foo->kobj, &foo_ktype, NULL, "%s", name);
 	if (retval) {
-		kfree(foo);
+		kobject_put(&foo->kobj);
 		return NULL;
 	}
 
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 17092d6..9ee9783 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -101,6 +101,7 @@
       cmd_kernel-mod = $(modpost) $@
 
 vmlinux.o: FORCE
+	@rm -fr $(kernelmarkersfile)
 	$(call cmd,kernel-mod)
 
 # Declare generated files as targets for modpost
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 37d5c36..1fcaf32 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -340,11 +340,18 @@
 }
 
 /* looks like: "pnp:dD" */
-static int do_pnp_entry(const char *filename,
-			struct pnp_device_id *id, char *alias)
+static void do_pnp_device_entry(void *symval, unsigned long size,
+				struct module *mod)
 {
-	sprintf(alias, "pnp:d%s*", id->id);
-	return 1;
+	const unsigned long id_size = sizeof(struct pnp_device_id);
+	const struct pnp_device_id *id = symval;
+
+	device_id_check(mod->name, "pnp", size, id_size, symval);
+
+	buf_printf(&mod->dev_table_buf,
+		   "MODULE_ALIAS(\"pnp:d%s*\");\n", id->id);
+	buf_printf(&mod->dev_table_buf,
+		   "MODULE_ALIAS(\"acpi*:%s:*\");\n", id->id);
 }
 
 /* looks like: "pnp:dD" for every device of the card */
@@ -388,9 +395,12 @@
 			}
 
 			/* add an individual alias for every device entry */
-			if (!dup)
+			if (!dup) {
 				buf_printf(&mod->dev_table_buf,
 					   "MODULE_ALIAS(\"pnp:d%s*\");\n", id);
+				buf_printf(&mod->dev_table_buf,
+					   "MODULE_ALIAS(\"acpi*:%s:*\");\n", id);
+			}
 		}
 	}
 }
@@ -701,9 +711,7 @@
 			 sizeof(struct acpi_device_id), "acpi",
 			 do_acpi_entry, mod);
 	else if (sym_is(symname, "__mod_pnp_device_table"))
-		do_table(symval, sym->st_size,
-			 sizeof(struct pnp_device_id), "pnp",
-			 do_pnp_entry, mod);
+		do_pnp_device_entry(symval, sym->st_size, mod);
 	else if (sym_is(symname, "__mod_pnp_card_device_table"))
 		do_pnp_card_entries(symval, sym->st_size, mod);
 	else if (sym_is(symname, "__mod_pcmcia_device_table"))
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index a07f91a..8f038e6 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -1992,7 +1992,8 @@
 			mod->skip = 1;
 		}
 
-		add_marker(mod, marker, fmt);
+		if (!mod->skip)
+			add_marker(mod, marker, fmt);
 	}
 	return;
 fail:
diff --git a/sound/core/init.c b/sound/core/init.c
index 5c254d4..df46bbc 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -548,8 +548,9 @@
 	snd_assert(card != NULL, return -EINVAL);
 #ifndef CONFIG_SYSFS_DEPRECATED
 	if (!card->card_dev) {
-		card->card_dev = device_create(sound_class, card->dev, 0,
-					       "card%i", card->number);
+		card->card_dev = device_create_drvdata(sound_class, card->dev,
+						       MKDEV(0, 0), NULL,
+						       "card%i", card->number);
 		if (IS_ERR(card->card_dev))
 			card->card_dev = NULL;
 	}
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c
index a9c23b2..7d89c08 100644
--- a/sound/oss/soundcard.c
+++ b/sound/oss/soundcard.c
@@ -560,17 +560,19 @@
 	sound_dmap_flag = (dmabuf > 0 ? 1 : 0);
 
 	for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
-		device_create(sound_class, NULL,
-			      MKDEV(SOUND_MAJOR, dev_list[i].minor),
-			      "%s", dev_list[i].name);
+		device_create_drvdata(sound_class, NULL,
+				      MKDEV(SOUND_MAJOR, dev_list[i].minor),
+				      NULL, "%s", dev_list[i].name);
 
 		if (!dev_list[i].num)
 			continue;
 
 		for (j = 1; j < *dev_list[i].num; j++)
-			device_create(sound_class, NULL,
-				      MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)),
-				      "%s%d", dev_list[i].name, j);
+			device_create_drvdata(sound_class, NULL,
+					      MKDEV(SOUND_MAJOR,
+						    dev_list[i].minor + (j*0x10)),
+					      NULL,
+					      "%s%d", dev_list[i].name, j);
 	}
 
 	if (sound_nblocks >= 1024)
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index 12f6ac9..9212c37 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -48,6 +48,7 @@
 config SND_PXA2XX_SOC_TOSA
 	tristate "SoC AC97 Audio support for Tosa"
 	depends on SND_PXA2XX_SOC && MACH_TOSA
+	depends on MFD_TC6393XB
 	select SND_PXA2XX_SOC_AC97
 	select SND_SOC_WM9712
 	help
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
index b6edb61..fe6cca9 100644
--- a/sound/soc/pxa/tosa.c
+++ b/sound/soc/pxa/tosa.c
@@ -21,6 +21,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/device.h>
+#include <linux/gpio.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -28,7 +29,7 @@
 #include <sound/soc-dapm.h>
 
 #include <asm/mach-types.h>
-#include <asm/hardware/tmio.h>
+#include <asm/arch/tosa.h>
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/audio.h>
@@ -137,10 +138,7 @@
 static int tosa_hp_event(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *k, int event)
 {
-	if (SND_SOC_DAPM_EVENT_ON(event))
-		set_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_L_MUTE);
-	else
-		reset_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_L_MUTE);
+	gpio_set_value(TOSA_GPIO_L_MUTE, SND_SOC_DAPM_EVENT_ON(event) ? 1 :0);
 	return 0;
 }
 
@@ -254,16 +252,28 @@
 	if (!machine_is_tosa())
 		return -ENODEV;
 
+	ret = gpio_request(TOSA_GPIO_L_MUTE, "Headphone Jack");
+	if (ret)
+		return ret;
+	gpio_direction_output(TOSA_GPIO_L_MUTE, 0);
+
 	tosa_snd_device = platform_device_alloc("soc-audio", -1);
-	if (!tosa_snd_device)
-		return -ENOMEM;
+	if (!tosa_snd_device) {
+		ret = -ENOMEM;
+		goto err_alloc;
+	}
 
 	platform_set_drvdata(tosa_snd_device, &tosa_snd_devdata);
 	tosa_snd_devdata.dev = &tosa_snd_device->dev;
 	ret = platform_device_add(tosa_snd_device);
 
-	if (ret)
-		platform_device_put(tosa_snd_device);
+	if (!ret)
+		return 0;
+
+	platform_device_put(tosa_snd_device);
+
+err_alloc:
+	gpio_free(TOSA_GPIO_L_MUTE);
 
 	return ret;
 }
@@ -271,6 +281,7 @@
 static void __exit tosa_exit(void)
 {
 	platform_device_unregister(tosa_snd_device);
+	gpio_free(TOSA_GPIO_L_MUTE);
 }
 
 module_init(tosa_init);
diff --git a/sound/sound_core.c b/sound/sound_core.c
index dcfc1d5..1b04259 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -171,8 +171,9 @@
 	else
 		sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP);
 
-	device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor),
-		      s->name+6);
+	device_create_drvdata(sound_class, dev,
+			      MKDEV(SOUND_MAJOR, s->unit_minor),
+			      NULL, s->name+6);
 	return r;
 
  fail: